Dash应用加载Pickle模型报错:无法获取'tokenize'属性
解决Pickle加载Dash应用中模型时找不到tokenize函数的问题
问题根源是训练模型时,tokenize函数被标记为__main__.tokenize(直接运行train_classifier.py作为脚本导致),pickle保存了该命名空间的函数引用,而Dash运行时app.py作为__main__模块,无法匹配到正确的函数。以下是两种解决方案:
方案一:重新训练模型(推荐,规范做法)
步骤1:调整训练代码结构
在models/train_classifier.py中封装训练逻辑,确保tokenize函数可被外部导入:
# models/train_classifier.py import nltk from nltk.tokenize import word_tokenize from nltk.stem import WordNetLemmatizer import pickle import os from sklearn.pipeline import Pipeline from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer from sklearn.ensemble import RandomForestClassifier def tokenize(text): # 你的tokenize实现示例 tokens = word_tokenize(text) lemmatizer = WordNetLemmatizer() clean_tokens = [] for tok in tokens: clean_tok = lemmatizer.lemmatize(tok).lower().strip() clean_tokens.append(clean_tok) return clean_tokens def train_model(): # 替换为你的数据加载、模型训练逻辑 pipeline = Pipeline([ ('vect', CountVectorizer(tokenizer=tokenize)), ('tfidf', TfidfTransformer()), ('clf', RandomForestClassifier(random_state=42)) ]) # pipeline.fit(X_train, y_train) # 执行训练 # 保存模型到正确路径 model_path = os.path.join(os.path.dirname(__file__), 'model.pkl') with open(model_path, 'wb') as file: pickle.dump(pipeline, file) if __name__ == '__main__': import sys from pathlib import Path sys.path.append(str(Path(__file__).parent.parent)) train_model()
步骤2:通过模块导入方式运行训练
在项目根目录Dashboard下创建run_train.py:
# Dashboard/run_train.py from models.train_classifier import train_model if __name__ == '__main__': train_model()
运行python run_train.py训练模型,此时tokenize的命名空间为models.train_classifier.tokenize,pickle会保存正确的引用。
步骤3:修改add_new.py加载逻辑
# pages/add_new.py import sys import os import pickle # 添加项目根目录到sys.path,确保能导入models模块 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from models.train_classifier import tokenize # 加载模型 model_filepath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'models', 'model.pkl')) with open(model_filepath, 'rb') as f: model = pickle.load(f) # 后续的Dash布局和回调代码...
方案二:无需重新训练,修改加载代码
如果不想重新训练,可在加载时手动映射__main__模块的tokenize到正确函数:
# pages/add_new.py import sys import os import pickle # 添加项目根目录到sys.path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from models.train_classifier import tokenize # 将__main__模块的tokenize指向导入的正确函数 sys.modules['__main__'].tokenize = tokenize # 加载模型 model_filepath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'models', 'model.pkl')) with open(model_filepath, 'rb') as f: model = pickle.load(f) # 后续代码...
关键注意点
- 必须将项目根目录添加到
sys.path,否则会出现模块导入失败; - 避免直接运行
train_classifier.py作为脚本训练,防止函数被标记为__main__.tokenize; - 确保Dash应用环境安装了
tokenize依赖的所有库(如nltk)。
内容的提问来源于stack exchange,提问作者jrichter
相关产品推荐
相关产品推荐

