• 深度学习模型部署


      主要介绍下完成了模型训练、评估之后的部署环节。

      前言:之前舆情情感分析那一篇文章已经讲了如何使用ernie以及paddlehub来进行模型的训练和优化以及评估环节,所以接下来会讲下如何进行部署,进行实际的运用环节。在这里,用的是上次讲的舆情情感分析的模型。

      将Fine-tune好的模型转化成paddleHub Module:

      第1步,创建必要的目录与文件

      创建一个finetuned_model_to_module的目录,并在finetuned_model_to_module目录下分别创建__init__.py、module.py,其中

     

    文件名用途
    __init__.py 空文件
    module.py 主模块,提供Module的实现代码
    ckpt文件 利用PaddleHub Fine-tune得到的ckpt文件夹,其中必须包含best_model文件

      第2步,编写Module处理代码

      module.py文件为Module的入口代码所在,我们需要在其中实现预测逻辑。

      step 2_1. 引入必要的头文件

     1 from __future__ import absolute_import
     2 from __future__ import division
     3 from __future__ import print_function
     4 
     5 import os
     6 
     7 import numpy as np
     8 from paddlehub.common.logger import logger
     9 from paddlehub.module.module import moduleinfo, serving
    10 import paddlehub as hub

      step 2_2. 定义ERNIE_Finetuned类

          module.py中需要有一个继承了hub.Module的类存在,该类负责实现预测逻辑,并使用moduleinfo填写基本信息。当使用hub.Module(name=”ernie_finetuned”)加载Module时,PaddleHub会自动创建ERNIE_Finetuned的对象并返回。

    1 @moduleinfo(
    2     name="ernie_finetuned",
    3     version="1.0.0",
    4     summary="ERNIE which was fine-tuned on the yuqing dataset.",
    5     author="enhaofrank",
    6     author_email="",
    7     type="nlp/semantic_model")
    8 class ERNIETinyFinetuned(hub.Module):

      step 2_3. 执行必要的初始化

     1   def _initialize(self,
     2                     ckpt_dir="ckpt_yuqing",
     3                     num_class=3,#3分类
     4                     max_seq_len=128,
     5                     use_gpu=False,
     6                     batch_size=1):
     7         self.ckpt_dir = os.path.join(self.directory, ckpt_dir)
     8         self.num_class = num_class
     9         self.MAX_SEQ_LEN = max_seq_len
    10 
    11         # Load Paddlehub ERNIE Tiny pretrained model
    12         self.module = hub.Module(name="ernie")
    13         inputs, outputs, program = self.module.context(
    14             trainable=True, max_seq_len=max_seq_len)
    15 
    16         self.vocab_path = self.module.get_vocab_path()
    17 
    18         # Download dataset and use accuracy as metrics
    19         # Choose dataset: GLUE/XNLI/ChinesesGLUE/NLPCC-DBQA/LCQMC
    20         # metric should be acc, f1 or matthews
    21         metrics_choices = ["acc"]
    22 
    23         # For ernie_tiny, it use sub-word to tokenize chinese sentence
    24         # If not ernie tiny, sp_model_path and word_dict_path should be set None
    25         reader = hub.reader.ClassifyReader(
    26             vocab_path=self.module.get_vocab_path(),
    27             max_seq_len=max_seq_len,
    28             sp_model_path=self.module.get_spm_path(),
    29             word_dict_path=self.module.get_word_dict_path())
    30 
    31         # Construct transfer learning network
    32         # Use "pooled_output" for classification tasks on an entire sentence.
    33         # Use "sequence_output" for token-level output.
    34         pooled_output = outputs["pooled_output"]
    35 
    36         # Setup feed list for data feeder
    37         # Must feed all the tensor of module need
    38         feed_list = [
    39             inputs["input_ids"].name,
    40             inputs["position_ids"].name,
    41             inputs["segment_ids"].name,
    42             inputs["input_mask"].name,
    43         ]
    44 
    45         # Setup runing config for PaddleHub Finetune API
    46         config = hub.RunConfig(
    47             use_data_parallel=False,
    48             use_cuda=use_gpu,
    49             batch_size=batch_size,
    50             checkpoint_dir=self.ckpt_dir,
    51             strategy=hub.AdamWeightDecayStrategy())
    52 
    53         # Define a classfication finetune task by PaddleHub's API
    54         self.cls_task = hub.TextClassifierTask(
    55             data_reader=reader,
    56             feature=pooled_output,
    57             feed_list=feed_list,
    58             num_classes=self.num_class,
    59             config=config,
    60             metrics_choices=metrics_choices)

    初始化过程即为Fine-tune时创建Task的过程。

    NOTE:

    1. 执行类的初始化不能使用默认的__init__接口,而是应该重载实现_initialize接口。对象默认内置了directory属性,可以直接获取到Module所在路径。

    2. 使用Fine-tune保存的模型预测时,无需加载数据集Dataset,即Reader中的dataset参数可为None。

      step 2_4. 完善预测逻辑

     1 def predict(self, data, return_result=False, accelerate_mode=True):
     2     """
     3     Get prediction results
     4     """
     5     run_states = self.cls_task.predict(
     6         data=data,
     7         return_result=return_result,
     8         accelerate_mode=accelerate_mode)
     9     results = [run_state.run_results for run_state in run_states]
    10     prediction = []
    11     for batch_result in results:
    12         # get predict index
    13         batch_result = np.argmax(batch_result, axis=2)[0]
    14         batch_result = batch_result.tolist()
    15         prediction += batch_result
    16     return prediction

      step 2_5. 支持serving调用

    如果希望Module可以支持PaddleHub Serving部署预测服务,则需要将预测接口predcit加上serving修饰(@serving),接口负责解析传入数据并进行预测,将结果返回。

    如果不需要提供PaddleHub Serving部署预测服务,则可以不需要加上serving修饰。

     1    @serving
     2     def predict(self, data, return_result=False, accelerate_mode=True):
     3         """
     4         Get prediction results
     5         """
     6         run_states = self.cls_task.predict(
     7             data=data,
     8             return_result=return_result,
     9             accelerate_mode=accelerate_mode)
    10         results = [run_state.run_results for run_state in run_states]
    11         prediction = []
    12         for batch_result in results:
    13             # get predict index
    14             batch_result = np.argmax(batch_result, axis=2)[0]
    15             batch_result = batch_result.tolist()
    16             prediction += batch_result
    17         return prediction

      这样子,就得到了module

      完成Module编写后,我们可以通过以下方式测试该Module:

      调用方法

      直接通过Hub.Module(directory=…)加载

    1 import paddlehub as hub
    2 import numpy as np
    3 import datetime
    4 ernie_finetuned = hub.Module(directory="finetuned_model_to_module")
    1 data = [["美邦服饰经营范围新增日用口罩、食品经营等。原标题:美邦服饰经营范围新增日用口罩、食品经营等,天眼查数据显示,近日,上海美特斯邦威服饰股份有限公司发生工商变更,经营范围新增日用口罩(非医疗),食品经营(销售预包装食品);此外,公司新增许可项目,为第二类增值电信业务(依法须经批准的项目,经相关部门批准后方可开展经营活动,具体经营项目以相关部门批准文件或许可证件为准)。(文章来源:e公司)(责任编辑:DF358)"]]
    2 inv_label_map = {0: '中性', 1: '利空', 2: '利好'}
    3 predictions = ernie_finetuned.predict(data=data)
    4 for index, text in enumerate(data):
    5     print("%s	predict=%s" % (data[index][0], inv_label_map[predictions[index]]))

       这样就可以对新闻内容进行预测了!例如输入上面的一段内容,预测结果为中性。

      接下来进行serving的调用方法:

      第一步:启动预测服务

    1 hub serving start -m ernie_finetuned

      

      第二步:发送请求,获取预测结果

      通过如下脚本既可以发送请求:

     1 # coding: utf8
     2 import requests
     3 import json
     4 
     5 
     6 # 待预测文本
     7 texts = [["美邦服饰经营范围新增日用口罩、食品经营等。原标题:美邦服饰经营范围新增日用口罩、食品经营等,天眼查数据显示,近日,上海美特斯邦威服饰股份有限公司发生工商变更,经营范围新增日用口罩(非医疗),食品经营(销售预包装食品);此外,公司新增许可项目,为第二类增值电信业务(依法须经批准的项目,经相关部门批准后方可开展经营活动,具体经营项目以相关部门批准文件或许可证件为准)。(文章来源:e公司)(责任编辑:DF358)"],
     8             ["近半数食品饮料股获机构推荐 杠杆资金提前入场7月份加仓超80亿元。最近30日内,有47家食品饮料行业公司获得评级机构192次推荐类评级,占业内公司总数的47%。数据显示,食品饮料行业中的51只两融标的的融资融券余额,从6月30日的346.07亿元,升至7月30日的426.49亿元,剧增80.43亿元,环比增长23.24%。其中,贵州茅台、五粮液两融余额增长最多,均超过20亿元。此外,包括伊利股份、山西汾酒、汤臣倍健等在内的9只食品饮料股两融余额增长均在亿元以上。(证券日报) 来源: 同花顺金融研究中心"]]
     9 
    10 # key为'data', 对应着预测接口predict的参数data
    11 data = {'data': texts}
    12 
    13 # 指定模型为ernie_finetuned并发送post请求,且请求的headers为application/json方式
    14 url = "http://127.0.0.1:8866/predict/ernie_tiny_finetuned"
    15 headers = {"Content-Type": "application/json"}
    16 r = requests.post(url=url, headers=headers,    data=json.dumps(data))
    17 
    18 # 打印预测结果
    19 print(json.dumps(r.json(), indent=4, ensure_ascii=False)

      

      PaddleHub Serving 一键部署

      命令行命令启动

      开放接口

    1 hub serving start --modules [Module1==Version1, Module2==Version2, ...] 
    2                     --port XXXX 
    3                     --use_gpu 
    4                     --use_multiprocess 
    5                     --workers 

      这样就可以用接口形式来访问,只要输入文本,就可以通过接口服务得到预测结果!  

      关闭接口

    hub serving stop --port xxxx

      总结:利用paddlehub将训练好的模型参数保存成module,之后在服务器端就可以直接使用这个模型的预测功能了,同时也可以通过接口的形式对外进行服务。

     参考资料:

    1、https://paddlehub.readthedocs.io/zh_CN/develop/tutorial/finetuned_model_to_module.html

    ---------------------------本博客所有内容以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,并且是非商业用途,谢谢!---------------------

    作者:enhaofrank

    出处:https://www.cnblogs.com/enhaofrank/

    中科院硕士毕业

    现为深漂打工人

  • 相关阅读:
    二叉树的镜像
    判断树B是不是树A的子结构
    LeetCode-21. Merge Two Sorted Lists
    LeetCode-Reverse Linked List I & II
    LeetCode-Permutations & Permutations II
    Linux常用命令
    Mac OS 快捷键
    Git 常用命令
    SVM参数寻优:grid search
    转载:Normal Equation证明及应用
  • 原文地址:https://www.cnblogs.com/enhaofrank/p/14006819.html
Copyright © 2020-2023  润新知