【问题标题】:How to cache a large machine learning model in Flask?如何在 Flask 中缓存大型机器学习模型?
【发布时间】:2021-03-31 21:05:42
【问题描述】:

这是我面临的情况:

我刚刚编写了一个 Flask 应用程序,人们可以输入他们想要的文本评论,我的应用程序会从我们的数据集中返回最相似的评论。所以基本上它是一个 NLP 项目,机器学习模型已经训练过了。现在的问题是模型大约 2.5GB,每次用户输入内容时,它都会加载该模型进行一些计算。

我对机器学习的东西很满意,但在 Web 开发领域完全是新手。经过一番谷歌搜索,我发现 Flask 中的缓存可能是解决方案,我尝试按照本教程进行操作 http://brunorocha.org/python/flask/using-flask-cache.html

但是,我未能实现它。谁能给我一些关于什么是正确的方法的建议。如果 Flask 缓存是“最佳”解决方案,我会继续研究这些东西并希望我能做到。

【问题讨论】:

    标签: python caching flask machine-learning


    【解决方案1】:

    我建议在您运行应用程序时加载一次模型。只需在主函数中加载模型即可完成。第一次加载应用需要一些时间,但每次调用 predict 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)
    

    【讨论】:

      【解决方案2】:

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

      更好的解决方案是:

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

      【讨论】:

      • 如果有人找到分步教程,请告诉我
      【解决方案3】:

      这就是我的做法:

      1. 为我的模型创建一个类文件,并在def __init__(self,...): 中加载所有内容
      2. 我在全局范围内实例化主烧瓶服务器文件中的类,它可用于我的所有功能(我将其作为模块从其自己的子目录加载)

      不确定这是构建它的最佳方式,但在我的情况下它很简单并且效果很好,我通常只需要为数据驱动模型公开少量路线,而不是根据可靠的原则设计复杂的软件!

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 感谢您的回复。我确实想过这种方式,但我不确定我是否打算在 AWS 上部署应用程序。
        【解决方案5】:

        这是我的解决方案。

        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 变量不是一个好主意。

        【讨论】:

        • 如果您为您的代码提供解释以及为什么global 不是一个好主意,您的回答会更有帮助。
        猜你喜欢
        • 2015-11-18
        • 1970-01-01
        • 2017-06-08
        • 2020-09-29
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        • 2019-11-15
        • 1970-01-01
        相关资源
        最近更新 更多