Flask部署预测模型遇joblib.load __main__属性错误求助
嘿,这个问题我之前也踩过坑!本质原因是pickle(joblib底层依赖pickle机制)序列化自定义类时,会记录类的模块路径,加载时如果当前环境找不到这个路径对应的类定义,就会抛出AttributeError。咱们一步步来搞定它:
问题根源
你在model.py里定义了NeuralNetwork类,如果是直接运行model.py来序列化模型(比如在if __name__ == "__main__"块里执行joblib.dump),这时候序列化的类会被标记为__main__.NeuralNetwork。但当你在Flask应用里加载模型时,Flask的主模块是__main__,可这个模块里并没有NeuralNetwork类的定义,自然就报错了。
解决方案
方案1:加载模型前导入正确的类定义
在你的Flask应用脚本(比如app.py)里,先从model.py导入NeuralNetwork类,再加载模型:
# app.py 中的代码 from model import NeuralNetwork import joblib from flask import Flask app = Flask(__name__) # 加载模型(确保模型文件路径正确) model = joblib.load('your_model_file.pkl') # 后续的Flask路由逻辑...
这样加载时,Python就能找到model.NeuralNetwork类,匹配序列化时的类路径(如果序列化时是通过导入模块执行的)。
方案2:规范模型序列化的方式
不要直接在model.py的主模块里序列化模型,而是单独写一个训练+保存的脚本(比如train_model.py),通过导入model模块来使用NeuralNetwork类:
# train_model.py 中的代码 from model import NeuralNetwork import joblib import numpy as np # 初始化并训练模型 nn = NeuralNetwork(input_dim=10, units=20) # 这里添加你的训练逻辑,比如nn.train(X_train, y_train) # 保存模型 joblib.dump(nn, 'trained_model.pkl')
运行这个脚本序列化模型时,类的路径会被记录为model.NeuralNetwork,之后在Flask里加载时,只要导入model.NeuralNetwork就能正常加载。
方案3:手动映射类路径(备选)
如果因为某些原因不能修改序列化的方式,可以在加载模型时,把__main__模块里的NeuralNetwork指向正确的类:
# Flask脚本中的代码 import joblib import sys from model import NeuralNetwork # 将__main__模块的NeuralNetwork指向model中的类 sys.modules['__main__'].NeuralNetwork = NeuralNetwork # 现在可以正常加载模型了 model = joblib.load('trained_model.pkl')
总结
最稳妥的方式是用方案2,把训练、序列化和Web应用的代码分开,保持类的定义在固定模块,这样能从根源上避免模块路径不匹配的问题。
内容的提问来源于stack exchange,提问作者Joshua Zastrow

