Jos*_*row 4 python machine-learning pickle flask
我开始着手研究使用Flask将预测模型部署到Web应用程序,但不幸地陷入了起步阶段。
我做了什么:
我在model.py程序中腌制了模型:
import numpy as np
from sklearn.externals import joblib
class NeuralNetwork():
"""
Two (hidden) layer neural network model.
First and second layer contain the same number of hidden units
"""
def __init__(self, input_dim, units, std=0.0001):
self.params = {}
self.input_dim = input_dim
self.params['W1'] = np.random.rand(self.input_dim, units)
self.params['W1'] *= std
self.params['b1'] = np.zeros((units))
self.params['W2'] = np.random.rand(units, units)
self.params['W2'] *= std * 10 # Compensate for vanishing gradients
self.params['b2'] = np.zeros((units))
self.params['W3'] = np.random.rand(units, 1)
self.params['b3'] = np.zeros((1,))
model = NeuralNetwork(input_dim=12, units=64)
#####THIS RIGHT HERE ##############
joblib.dump(model, 'demo_model.pkl')
Run Code Online (Sandbox Code Playgroud)
然后,我创建了一个api.py在同一目录作为我的文件demo_model.pkl,每本教程(https://blog.hyperiondev.com/index.php/2018/02/01/deploy-machine-learning-models- flask-api /):
import flask
from flask import Flask, render_template, request
from sklearn.externals import joblib
app = Flask(__name__)
@app.route("/")
@app.route("/index")
def index():
return flask.render_template('index.html')
# create endpoint for the predictions (HTTP POST requests)
@app.route('/predict', methods=['POST'])
def make_prediction():
if request.method == 'POST':
return render_template('index.html', label='3')
if __name__ == '__main__':
# LOAD MODEL WHEN APP RUNS ####
model = joblib.load('demo_model.pkl')
app.run(host='0.0.0.0', port=8000, debug=True)
Run Code Online (Sandbox Code Playgroud)
我还使用以下信息在同一目录中创建了一个templates / index.html文件:
<html>
<head>
<title>NN Model as Flask API</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Boston Housing Price Predictor</h1>
<form action="/predict" method="post" enctype="multipart/form-data">
<input type="file" name="image" value="Upload">
<input type="submit" value="Predict"> {% if label %} {{ label }} {% endif %}
</form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
运行:
>> python api.py
Run Code Online (Sandbox Code Playgroud)
给我一个错误的选择器:
Traceback (most recent call last):
File "api.py", line 22, in <module>
model = joblib.load('model.pkl')
File "C:\Users\joshu\Anaconda3\lib\site-packages\sklearn\externals\joblib\numpy_pickle.py", line 578, in load
obj = _unpickle(fobj, filename, mmap_mode)
File "C:\Users\joshu\Anaconda3\lib\site-packages\sklearn\externals\joblib\numpy_pickle.py", line 508, in _unpickle
obj = unpickler.load()
File "C:\Users\joshu\Anaconda3\lib\pickle.py", line 1043, in load
dispatch[key[0]](self)
File "C:\Users\joshu\Anaconda3\lib\pickle.py", line 1342, in load_global
klass = self.find_class(module, name)
File "C:\Users\joshu\Anaconda3\lib\pickle.py", line 1396, in find_class
return getattr(sys.modules[module], name)
AttributeError: module '__main__' has no attribute 'NeuralNetwork'
Run Code Online (Sandbox Code Playgroud)
为什么程序的主要模块与我的NeuralNetwork模型有关?我现在很困惑...任何建议将不胜感激。
更新:
在class NeuralNetwork(object): pass我的api.py程序中添加类定义可修复该错误。
import flask
from flask import Flask, render_template, request
from sklearn.externals import joblib
class NeuralNetwork(object):
pass
app = Flask(__name__)
Run Code Online (Sandbox Code Playgroud)
如果有人愿意向我解释发生的事情,将不胜感激!
您要获得的特定异常是指中的属性__main__,但这主要是红色鲱鱼。我很确定问题实际上与您转储实例的方式有关。
Pickle不会转储实际的代码类和函数,仅转储其名称。它包括每个模块定义所在的模块的名称,因此可以再次找到它们。如果转储正在作为脚本运行的模块中定义的类,则它将转储该名称__main__作为模块名称,因为这就是Python用作主模块的名称(如if __name__ == "__main__"样板代码所示)。
当您model.py以脚本形式运行并腌制其中定义的类的实例时,该类将另存为__main__.NeuralNetwork而不是model.NeuralNetwork。当您运行其他模块并尝试加载pickle文件时,Python会在__main__模块中查找该类,因为那是pickle数据告诉它查找的地方。这就是为什么您遇到有关的属性的异常的原因__main__。
为了解决这个问题,您可能想要更改转储数据的方式。除了model.py可能作为脚本运行之外,您可能还应该运行其他一些模块并使其执行操作import model,因此您可以使用其正常名称获取该模块。(我想您可以model.py将自己导入到一个if __name__ == "__main__"块中,但这非常丑陋和尴尬)。您可能还需要避免在model导入时无条件地重新创建和转储实例,因为这在加载pickle文件时会发生(我认为pickle的全部目的是避免从头开始重新创建实例)。
因此,从的底部删除转储逻辑model.py,并添加一个新文件,如下所示:
# new script, dump_model.py, does the creation and dumping of the NeuralNetwork
from sklearn.externals import joblib
from model import NeuralNetwork
if __name__ == "__main__":
model = NeuralNetwork(input_dim=12, units=64)
joblib.dump(model, 'demo_model.pkl')
Run Code Online (Sandbox Code Playgroud)
当您转储NeuralNetwork使用此脚本的脚本时,它将正确地model将类定义为该模块,因此加载代码将能够导入该模块并正确地创建该类的实例。
您当前针对该问题的“修复”(NeuralNetwork在__main__加载对象时在模块中定义一个空类)可能是一个不好的解决方案。从加载pickle文件中获得的实例将是新类的实例,而不是原始类。它将加载旧实例的属性,但不会设置任何方法或其他类变量(这与您显示的类无关,但可能适用于任何实例更复杂的对象)。
| 归档时间: |
|
| 查看次数: |
1938 次 |
| 最近记录: |