深度學習模型部署
摘要:主要介紹下完成了模型訓練、評估之後的部署環節。
前言:之前輿情情感分析那一篇文章已經講了如何使用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_function4 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:
-
執行類的初始化不能使用預設的__init__介面,而是應該過載實現_initialize介面。物件預設內建了directory屬性,可以直接獲取到Module所在路徑。
-
使用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/
中科院碩士畢業
現為深漂打工人