Paddle训练之后的镜像-动态图转静态图,并使用inferen

2022-05-16  本文已影响0人  onmeiei
class SampleInfer(Processor):
    preprocess: []
    pool: paddle.inference.PredictorPool
    ids: {}

    def __init__(self):
        logging.info("Loading model file")
        # 加载动态图,并转换为静态图
        model = RedNet26(pretrained='/share/PaddleClas/output/RedNet26/latest')
        # 静态图需要制定输入的形状,`None`代表可变,例如:本例子中,每次可以同时预测多张图像。
        static_mode = paddle.jit.to_static(model, input_spec=[InputSpec(shape=[None, 3, 224, 224], name='x')])
        # 保存jit(静态模型)
        paddle.jit.save(static_mode, '/share/PaddleClas/output/RedNet26/static/latest')

        # 开始模型加载,需要指定两个参数,一个是网络结构,一个是训练参数。此时不再需要RedNet26网络结构了,直接加载就可以了。
        config = paddle.inference.Config('/share/PaddleClas/output/RedNet26/static/latest.pdmodel', '/share/PaddleClas/output/RedNet26/static/latest.pdiparams')
        # 使用0号显卡的100M显存
        config.enable_use_gpu(100, 0)
        # predictor不是线程安全的,所以需要创建一个PredictorPool来保证线程的并发安全性。
        self.pool = paddle.inference.PredictorPool(config, 4)
        
        # 数据预处理,与训练时一致即可。
        self.preprocess = []
        self.preprocess.append(DecodeImage(to_rgb=True, channel_first=False))
        self.preprocess.append(ResizeImage(resize_short=256))
        self.preprocess.append(CropImage(size=224))
        self.preprocess.append(NormalizeImage(scale=1.0, mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], order=''))
        self.preprocess.append(ToCHWImage())
        
        self.ids = {}
        self.idx = 0
        
    def process(self, msg: str):
        # 线程号绑定predictor,这里未处理锁,正式代码自行处理一下。
        tid = threading.current_thread().ident
        if not tid in self.ids:
            self.idx += 1
            self.ids[tid] = int(self.idx)
        idx = self.ids[tid]
        logging.info("tid({}) use idx({})".format(tid, idx))
        
        # 第一步:获取图像内容
        img = base64.decodebytes(bytes(msg, encoding="utf-8"))
        req = img
        # 第二步:加载图像内容,并进行预处理(匹配网络输入的数据结构)
        for process in self.preprocess:
            req = process(req)
        # 第三步:升维,因为只有一张图,所以需要升维成4D,以匹配InputSpec
        req = np.expand_dims(req, axis=0)

        # 第四步:获取本线程绑定的predictor对象 
        predictor = self.pool.retrive(idx)

        # 第五步:开始预测,并获得预测结果
        try:
            input_names = predictor.get_input_names() # 获得输入参数名称,即'x',在静态图构建过程中使用InputSpec指定的
            input_tensor = predictor.get_input_handle(input_names[0])
            input_tensor.copy_from_cpu(req) # 将数据从内存中拷贝到GPU(因为本例子使用了gpu做预测)中
            predictor.run()
            output_names = predictor.get_output_names()
            output_tensor = predictor.get_output_handle(output_names[0])
            resp = output_tensor.copy_to_cpu() # 将数据从GPU读取到内存中进行处理。
            return str(resp.argmax())
        finally:
            predictor.clear_intermediate_tensor() # 释放中间计算产生的Tensor
            predictor.try_shrink_memory() # 释放显存
上一篇下一篇

猜你喜欢

热点阅读