如何在Flask中缓存大型机器学习模型



我面临的情况是这样的:

我刚刚写了一个Flask应用程序,人们可以输入他们想要的文本评论,我的应用程序会从我们的数据集中返回最相似的评论。所以基本上这是一个自然语言处理项目,机器学习模型已经训练好了。现在的问题是模型大约2.5GB,每次用户输入一些东西时,它都会加载该模型来做一些计算。

我对机器学习的东西还行,但在web开发领域完全是个新手。经过一些谷歌搜索,我发现Flask中的缓存可能是解决方案,我尝试遵循本教程http://brunorocha.org/python/flask/using-flask-cache.html

然而,我未能实现它。谁能给我一些建议,告诉我正确的做法是什么?如果Flask缓存是"解决方案",我将继续关注这个东西,并希望我能做到。

我建议在运行应用程序时加载一次模型。它可以简单地在main函数中加载模型。当你第一次加载你的应用程序时,它会花一些时间,但每次当你调用预测API时,它会更快。

@app.route('/predict', methods=['POST', 'OPTIONS']) 
def predict(tokenized):
     global model
     "do something"
     return jsonify(result)
 if __name__ == '__main__':
    model = load_model('/model/files/model.h5')
    app.run(host='0.0.0.0', port=5000)

显然,模型加载操作是时间密集且阻塞的,并且随着更新模型的大小而增加。默认情况下,Flask是阻塞的,除非你在它上面使用像uwsgi负载平衡器这样的东西,并部署n个线程或进程来确保一定程度的水平可伸缩性。假设你只有一个Flask Application的实例在运行,那么在初始化应用程序时(特别是在app.run()之前)加载更新后的模型是有意义的。您需要将其维护为全局变量,以便其上下文在整个应用程序实例中可用。您还可以添加/reload-model端点,该端点接受模型名称并更新内存中的引用,以指向已更新的模型。当然,您不会经常调用此端点,但会不时调用。

一个更好的解决方案是:

  • 编写一些与主Flask应用一起运行的调度器(看看ApScheduler的BackgroundScheduler)。
  • 这个调度器有一个作业,它定期轮询包含您训练过的模型的目录,并检查模型最近是否更改(使用类似https://pythonhosted.org/watchdog/的东西),如果文件已更改,调度器只是重新加载并更新全局引用变量中的模型实例引用。

我是这样做的:

  1. 为我的模型创建一个类文件,并加载def __init__(self,...):
  2. 中的所有内容
  3. 我在全局作用域的主flask服务器文件中实例化类,在那里它可以用于我的所有函数(我从它自己的子目录中将它作为模块加载)

不确定这是不是最好的架构方式,但它很简单,在我的情况下工作得很好,我通常只需要为数据驱动模型公开几个路由,而不是根据坚实的原则设计复杂的软件!

您可以在脚本中初始化模型,而不是每次都在函数中加载模型,这样它就保留在内存中,而不必重新加载它。您可以先尝试上述方法,而不是使用flask-cache。

这是我的解决方案。

from flask import current_app
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
    current_app.model.predict_something()
if __name__ == '__main__':
    with app.app_context():
        current_app.model = load_your_model()
    app.run()

使用global变量不是一个好主意。

最新更新