1. 程式人生 > 實用技巧 >深度學習模型部署

深度學習模型部署

  摘要:主要介紹下完成了模型訓練、評估之後的部署環節。

  前言:之前輿情情感分析那一篇文章已經講了如何使用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[0], axis=1)
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\tpredict=%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/

中科院碩士畢業

現為深漂打工人