Django调用pickle保存的自定义神经网络报AttributeError问题
问题原因
两个核心问题导致报错:
- 模型序列化对象错误:代码中
pickle.dump(model, file)存入的是自定义的前向传播函数model,并非训练完成得到的权重W和偏置b,生成的pkl文件完全不包含训练好的模型参数,根本无法用于预测。 - pickle序列化机制限制:pickle不会存储自定义函数/类的实际代码,仅记录对象所属的模块路径。你训练脚本里的
artificial_neuron、predict等函数都定义在训练脚本的__main__作用域下,Django项目的运行入口是manage.py,其__main__模块中不存在这些自定义函数定义,加载pkl时自然找不到对应属性抛出异常。
修复方案
按以下步骤调整即可:
- 补全训练脚本缺失的依赖:训练代码开头加上
import numpy as np,否则调用numpy相关方法时会直接报错。 - 修正模型保存逻辑:训练完成后仅持久化实际需要的模型参数,不要保存函数对象,替换原有保存代码为:
import pickle # 把预测需要的所有参数打包存储,后续如果加了特征归一化、类别映射等逻辑,也把对应参数放进这个字典 model_package = { "W": W, "b": b } # 用上下文管理器自动处理文件关闭,避免文件损坏 with open("model.pkl", "wb") as f: pickle.dump(model_package, f)
- 抽离公共工具函数:在Django对应的app目录下新建
ml_utils.py文件,把预测依赖的自定义函数全部移到这个文件中,保证Django项目运行时可以正常导入这些函数,示例内容:
import numpy as np def _sigmoid(Z): return 1 / (1 + np.exp(-Z)) def forward(X, W, b): Z = X.dot(W) + b return _sigmoid(Z) def predict(X, W, b): prob = forward(X, W, b) return prob >= 0.5
- 调整Django视图加载逻辑:在视图中从公共模块导入预测函数,再加载pkl中的模型参数,不要依赖
__main__作用域的对象,参考代码:
import pickle import numpy as np from django.http import JsonResponse from .ml_utils import predict # 项目启动时一次性加载模型,避免每次请求重复读文件 with open("model.pkl", "rb") as f: model_params = pickle.load(f) W = model_params["W"] b = model_params["b"] def predict_view(request): if request.method == "POST": # 此处补充从请求中提取特征、转换为和训练时维度/格式一致的numpy数组的逻辑 # 注意必须和训练时做完全一致的特征预处理,否则预测结果无效 input_x = np.array([]).reshape(1, -1) # 替换为实际输入特征 pred_result = predict(input_x, W, b) return JsonResponse({"predict_result": int(pred_result[0][0])})
注意:如果训练阶段做了特征归一化、类别编码等预处理操作,必须把预处理用到的所有参数(比如特征均值、标准差、类别映射字典)一起存入pkl包中,预测阶段对用户输入做完全相同的预处理后再传入模型。
内容的提问来源于stack exchange,提问作者بلقاسم المامون
相关产品推荐
相关产品推荐

