Python中如何在Flask等Web服务下实现facenet的load_model常驻或全局化

最新在学习人脸识别模型,

我想尝试将其应用在 web 服务上,

其中用到了 facenet 在 facenet 中有一个load_model()方法。 Link

经过确认,这里面的saver.restore等是最耗时的,

每次加载都会消耗大约 14 秒,这明显是不能接受的,我不能每次请求都要等这么久。

所以我想将让其只在开启时加载一次,不知这个想法可行?

我搜集了资料 比较贴近的有这么几个

link0 link1 link2

我按照上面的文章多次测试,要么 RuntimError,要么 graph is None,或者其他更可怕的错误

主要的运行原代码

# compare.py
origin_data_path = ''
img_path = ''
args = parse_arguments(['./face/src/20180408-102900', img_path])
images = load_and_align_data(args.image_files, args.image_size, args.margin, args.gpu_memory_fraction)
with tf.Graph().as_default():
    with tf.Session() as sess:
        # 加载模型 这里耗时是最多的
        facenet.load_model(args.model)
        images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
        embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
        phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
        # 获取特征向量
        feed_dict = {images_placeholder: images, phase_train_placeholder: False}
        emb = sess.run(embeddings, feed_dict=feed_dict)
        # 保存到本地
        np.savetxt('', emb[0])

我需要将其改写,小白初次接触,提前谢谢各位了!~


Python中如何在Flask等Web服务下实现facenet的load_model常驻或全局化

7 回复

糙快猛的话你就把 facenet 改成全局变量呗…好好搞的话 compare.py 做成 service


在Flask这类Web服务里用facenet的load_model,关键就是别在每次请求里都加载,那太慢了。得把模型实例做成全局的,或者用应用上下文来管理。

简单直接的办法就是搞个全局变量。在应用启动的时候把模型加载好,后面所有请求都共用这个实例。比如这样:

from flask import Flask, request, jsonify
import tensorflow as tf
import numpy as np
from facenet import load_model  # 假设这是你的facenet加载函数

app = Flask(__name__)

# 全局变量存模型
facenet_model = None

@app.before_first_request
def load_facenet_model():
    global facenet_model
    # 这里加载你的facenet模型
    # 假设load_model返回一个可以直接做推理的模型对象
    facenet_model = load_model('path/to/your/facenet_model.pb')
    print("Facenet model loaded globally")

@app.route('/encode', methods=['POST'])
def encode_face():
    # 从请求里拿到图片数据
    image_data = request.files['image'].read()
    # 这里应该有预处理,把图片转成模型要的格式
    processed_image = preprocess_image(image_data)
    
    # 直接用全局的模型实例
    embedding = facenet_model.predict(processed_image)
    
    return jsonify({'embedding': embedding.tolist()})

def preprocess_image(image_data):
    # 这里写你的图片预处理逻辑
    # 比如resize、归一化这些
    pass

if __name__ == '__main__':
    app.run()

@app.before_first_request装饰器确保模型只在第一个请求前加载一次。所有后续的/encode请求都直接用facenet_model这个全局变量,避免了重复加载的开销。

如果你担心全局变量不够优雅,也可以用Flask的g对象或者搞个单例类来包装模型。但原理都一样,就是让模型实例在应用生命周期里只存在一份。

注意一下,像TensorFlow模型可能有多线程的问题。如果遇到并发请求时模型预测出错,可能需要在预测时加个锁,或者用TensorFlow Serving这类专门的服务来部署模型会更稳。

总结:把模型加载一次存成全局变量,所有请求共用。

可以的,我是写成了类的成员。可供参考: https://github.com/cvmodel/Face_Utility/blob/master/face_utility/solver.py ,如果写成类似的格式,直接通过 cvpm 就可以调用- - 当然写成 flask 的也可以

通过不断地测试,总算找到比较合适的方法了,最后时间基本在 1 秒内,还是感谢二位了

不知道为啥,我不能 @了,说是注册时间不满 360 天,其实这是我小号。。。

什么方法?

#5 就是把 saver 和 session 预先加载,后面用的时候注意用 as_default 等参数就行了,避免 with 上下文管理器释放资源

回到顶部