零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。

汀丶發表於2023-04-21

零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。

1.通用文字分類技術UTC介紹

本專案提供基於通用文字分類 UTC(Universal Text Classification) 模型微調的文字分類端到端應用方案,打通資料標註-模型訓練-模型調優-預測部署全流程,可快速實現文字分類產品落地。

文字分類是一種重要的自然語言處理任務,它可以幫助我們將大量的文字資料進行有效的分類和歸納。實際上,在日常生活中,我們也經常會用到文字分類技術。例如,我們可以使用文字分類來對新聞報導進行分類,對電子郵件進行分類,對社交媒體上的評論進行情感分析等等。但是,文字分類也面臨著許多挑戰。其中最重要的挑戰之一是資料稀缺。由於文字資料往往非常龐大,因此獲取足夠的訓練資料可能非常困難。此外,不同的文字分類任務也可能面臨著領域多變和任務多樣等挑戰。為了應對這些挑戰,PaddleNLP推出了一項零樣本文字分類應用UTC。該應用透過統一語義匹配方式USM(Unified Semantic Matching)來將標籤和文字的語義匹配能力進行統一建模。這種方法可以幫助我們更好地理解文字資料,並從中提取出有用的特徵資訊。

UTC具有低資源遷移能力,可以支援通用分類、評論情感分析、語義相似度計算、蘊含推理、多項式閱讀理解等多種“泛分類”任務。這使得開發者可以更加輕鬆高效地實現多工文字分類資料標註、訓練、調優和上線,從而降低文字分類技術門檻。

總之,文字分類是一項重要的自然語言處理任務,它可以幫助我們更好地理解和歸納文字資料。儘管它面臨著許多挑戰,但是透過使用PaddleNLP的零樣本文字分類應用UTC,開發者們可以簡單高效實現多工文字分類資料標註、訓練、調優、上線,降低文字分類落地技術門檻。

UTC模型結構圖

1.1 分類落地面臨難度

分類任務看似簡單,然而在產業級文字分類落地實踐中,面臨著諸多挑戰:

  • 任務多樣:單標籤、多標籤、層次標籤、大規模標籤等不同的文字分類任務,需要開發不同的分類模型,模型架構往往特化於具體任務,難以使用統一形式建模;

  • 資料稀缺:部分領域資料稀缺,難以獲取,且領域專業性使得資料標註門檻高;

  • 標籤遷移:不同領域的標籤多樣,並且遷移難度大,尤其不同領域間的標籤知識很難遷移。

1.2 UTC亮點

1.2.1 多工統一建模

在傳統技術方案中,針對不同的分類任務需要構建多個分類模型,模型需單獨訓練且資料和知識不共享。而在UTC方案下,單個模型能解決所有分類需求,包括但不限於單標籤分類、多標籤分類、層次標籤分類、大規模事件標籤檢測、蘊含推理、語義相似度計算等,降低了開發成本和機器成本。

UTC模型結構圖

1.2.2 零樣本分類和小樣本遷移能力強

UTC透過大規模多工預訓練後,可以適配不同的行業領域,不同的分類標籤,僅標註了幾條樣本,分類效果就取得大幅提升,大大降低標註門檻和成本。

UTC模型結構圖

在醫療、金融、法律等領域中,無需訓練資料的零樣本情況下UTC效果平均可達到70%+(如下表所示),標註少樣本也可帶來顯著的效果提升:每個標籤僅僅標註1條樣本後,平均提升了10個點!也就是說,即使在某些場景下表現欠佳,人工標幾個樣本,丟給模型後就會有大幅的效果提升。

1.3 UTC技術思路

UTC基於百度最新提出的統一語義匹配框架USM(Unified Semantic Matching)[1],將分類任務統一建模為標籤與文字之間的匹配任務,對不同標籤的分類任務進行統一建模。具體地說:

  1. 為了實現任務架構統一,UTC設計了標籤與文字之間的詞對連線操作(Label–>CLS-Token Linking),這使得模型能夠適應不同領域和任務的標籤資訊,並按需求進行分類,從而實現了開放域場景下的通用文字分類。
    例如,對於事件檢測任務,可將一系列事件標籤拼接為[L]上映[L]奪冠[L]下架 ,然後與原文字一起作為整體輸入到UTC中,UTC將不同標籤識別符號[L]與[CLS]進行匹配,可對不同標籤型別的分類任務統一建模,直接上圖:
UTC模型結構圖
  1. 為了實現通用能力共享,讓不同領域間的標籤知識跨域遷移,UTC構建了統一的異質監督學習方法進行多工預訓練,使不同領域任務具備良好的零/少樣本遷移效能。統一的異質監督學習方法主要包括三種不同的監督訊號:
    • 直接監督:分類任務直接相關的資料集,如情感分類、新聞分類、意圖識別等。
    • 間接監督:分類任務間接相關的資料集,如選項式閱讀理解、問題-文章匹配等。
    • 遠端監督:標籤知識庫或層級標題與文字對齊後弱標註資料。

更多內容參考論文見文末連結 or fork一下專案論文已上傳

2.文字分類任務Label Studio教程

2.1 Label Studio安裝

以下標註示例用到的環境配置:

  • Python 3.8+
  • label-studio == 1.7.2

在終端(terminal)使用pip安裝label-studio:

pip install label-studio==1.7.2

安裝完成後,執行以下命令列:

label-studio start

在瀏覽器開啟http://localhost:8080/,輸入使用者名稱和密碼登入,開始使用label-studio進行標註。

2.2 文字分類任務標註

2.2.1 專案建立

點選建立(Create)開始建立一個新的專案,填寫專案名稱、描述,然後在Labeling Setup中選擇Text Classification

  • 填寫專案名稱、描述
零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。
  • 資料上傳,從本地上傳txt格式檔案,選擇List of tasks,然後選擇匯入本專案
零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。
  • 設定任務,新增標籤
零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。
零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。
  • 資料上傳

專案建立後,可在Project/文字分類任務中點選Import繼續匯入資料,同樣從本地上傳txt格式檔案,選擇List of tasks

2.2.2 標籤構建

專案建立後,可在Setting/Labeling Interface中繼續配置標籤,

預設模式為單標籤多分類資料標註。對於多標籤多分類資料標註,需要將choice的值由single改為multiple

零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。

2.2.3 任務標註

零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。

2.2.4 資料匯出

勾選已標註文字ID,選擇匯出的檔案型別為JSON,匯出資料:

零樣本文字分類應用:基於UTC的醫療意圖多分類,打通資料標註-模型訓練-模型調優-預測部署全流程。

參考連結:

3.資料轉換

將匯出的檔案重新命名為label_studio.json後,放入./data目錄下。透過label_studio.py指令碼可轉為UTC的資料格式。

在資料轉換階段,還需要提供標籤候選資訊,放在./data/label.txt檔案中,每個標籤佔一行。例如在醫療意圖分類中,標籤候選為["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"],也可透過options引數直接進行配置。

這裡提供預先標註好的醫療意圖分類資料集的檔案,可以執行下面的命令列下載資料集,我們將展示如何使用資料轉化指令碼生成訓練/驗證/測試集檔案,並使用UTC模型進行微調。

#下載醫療意圖分類資料集:
!wget https://bj.bcebos.com/paddlenlp/datasets/utc-medical.tar.gz
!tar -xvf utc-medical.tar.gz
!mv utc-medical data
!rm utc-medical.tar.gz

資料集部分展示

[{"id":26092,"annotations":[{"id":59,"completed_by":1,"result":[{"value":{"choices":["注意事項"]},"id":"7iya31L9oc","from_name":"sentiment","to_name":"text","type":"choices","origin":"manual"}],"was_cancelled":false,"ground_truth":false,"created_at":"2023-01-09T07:13:18.982993Z","updated_at":"2023-01-09T07:13:18.983032Z","lead_time":4.022,"prediction":{},"result_count":0,"task":26092,"parent_prediction":null,"parent_annotation":null}],"file_upload":"838fb89a-10-shot.txt","drafts":[],"predictions":[],"data":{"text":"燒氧割要注意那些問題"},"meta":{},"created_at":"2023-01-09T06:48:10.725717Z","updated_at":"2023-01-09T07:13:19.022666Z","inner_id":35,"total_annotations":1,"cancelled_annotations":0,"total_predictions":0,"comment_count":0,"unresolved_comment_count":0,"last_comment_updated_at":null,"project":5,"updated_by":1,"comment_authors":[]},
{"id":26091,"annotations":[{"id":4,"completed_by":1,"result":[{"value":{"choices":["病因分析"]}]
# 生成訓練/驗證集檔案:
!python label_studio.py \
    --label_studio_file ./data/utc-medical/label_studio.json \
    --save_dir ./data \
    --splits 0.8 0.1 0.1 \
    --options ./data/utc-medical/label.txt
[32m[2023-04-14 11:28:46,056] [    INFO][0m - Save 45 examples to ./data/train.txt.[0m
[32m[2023-04-14 11:28:46,057] [    INFO][0m - Save 6 examples to ./data/dev.txt.[0m
[32m[2023-04-14 11:28:46,057] [    INFO][0m - Save 6 examples to ./data/test.txt.[0m
[32m[2023-04-14 11:28:46,057] [    INFO][0m - Finished! It takes 0.00 seconds[0m
[0m
{"text_a": "老年痴呆的症狀有哪些", "text_b": "", "question": "", "choices": ["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"], "labels": [5]}

  • label_studio_file: 從label studio匯出的資料標註檔案。
  • save_dir: 訓練資料的儲存目錄,預設儲存在data目錄下。
  • splits: 劃分資料集時訓練集、驗證集所佔的比例。預設為[0.8, 0.1, 0.1]表示按照8:1:1的比例將資料劃分為訓練集、驗證集和測試集。
  • options: 指定分類任務的類別標籤。若輸入型別為檔案,則檔案中每行一個標籤。
  • is_shuffle: 是否對資料集進行隨機打散,預設為True。
  • seed: 隨機種子,預設為1000.

備註:

  • 預設情況下 label_studio.py 指令碼會按照比例將資料劃分為 train/dev/test 資料集
  • 每次執行 label_studio.py 指令碼,將會覆蓋已有的同名資料檔案
  • 對於從label_studio匯出的檔案,預設檔案中的每條資料都是經過人工正確標註的。

使用Label Studio 資料標註工具進行標註,如果已有標註好的本地資料集,我們需要將資料集整理為文件要求的格式,

4.模型訓練預測

多工訓練場景可分別進行資料轉換再進行混合:通用分類、評論情感分析、語義相似度計算、蘊含推理、多項式閱讀理解等眾多“泛分類”任務

##程式碼結構
├── deploy/simple_serving/ # 模型部署指令碼
├── utils.py               # 資料處理工具
├── run_train.py           # 模型微調指令碼
├── run_eval.py            # 模型評估指令碼
├── label_studio.py        # 資料格式轉換指令碼
├── label_studio_text.md   # 資料標註說明文件
└── README.md

4.1 模型微調

推薦使用 PromptTrainer API 對模型進行微調,該 API 封裝了提示定義功能,且繼承自 Trainer API 。只需輸入模型、資料集等就可以使用 Trainer API 高效快速地進行預訓練、微調等任務,可以一鍵啟動多卡訓練、混合精度訓練、梯度累積、斷點重啟、日誌顯示等功能,Trainer API 還針對訓練過程的通用訓練配置做了封裝,比如:最佳化器、學習率排程等。

使用下面的命令,使用 utc-base 作為預訓練模型進行模型微調,將微調後的模型儲存至output_dir

4.1.1 單卡訓練

#安裝最新版本paddlenlp
!pip install --upgrade paddlenlp
# 單卡啟動:
!python run_train.py  \
    --device gpu \
    --logging_steps 10 \
    --save_steps 10 \
    --eval_steps 10 \
    --seed 1000 \
    --model_name_or_path utc-base \
    --output_dir ./checkpoint/model_best \
    --dataset_path ./data/ \
    --max_seq_length 512  \
    --per_device_train_batch_size 2 \
    --per_device_eval_batch_size 2 \
    --gradient_accumulation_steps 8 \
    --num_train_epochs 20 \
    --learning_rate 1e-5 \
    --do_train \
    --do_eval \
    --do_export \
    --export_model_dir ./checkpoint/model_best \
    --overwrite_output_dir \
    --disable_tqdm True \
    --metric_for_best_model macro_f1 \
    --load_best_model_at_end  True \
    --save_total_limit 1 \
    --save_plm
eval_loss: 0.3148668706417084, eval_micro_f1: 0.9848484848484849, eval_macro_f1: 0.9504132231404958, eval_runtime: 0.0757, eval_samples_per_second: 79.286, eval_steps_per_second: 39.643, epoch: 19.6957

[2023-04-13 17:02:45,941] [    INFO] -   epoch                    =    19.6957
[2023-04-13 17:02:45,941] [    INFO] -   train_loss               =     0.9758
[2023-04-13 17:02:45,942] [    INFO] -   train_runtime            = 0:00:45.91
[2023-04-13 17:02:45,942] [    INFO] -   train_samples_per_second =     19.602
[2023-04-13 17:02:45,942] [    INFO] -   train_steps_per_second   =      0.871

二分類時需要注意的問題

  • ModuleNotFoundError: No module named 'fast_tokenizer'
安裝一下fast tokenizer
pip install --upgrade fast_tokenizer
  • 開啟single_label時需要將執行指令碼中的 metric_for_best_model 引數改為accuracy
metric_value = metrics[metric_to_check]
KeyError: 'eval_macro_f1'

4.1.2 多卡訓練

如果在GPU環境中使用,可以指定gpus引數進行多卡訓練:

# !python -u -m paddle.distributed.launch --gpus "0,1,2,3" run_train.py \
#     --device gpu \
#     --logging_steps 10 \
#     --save_steps 10 \
#     --eval_steps 10 \
#     --seed 1000 \
#     --model_name_or_path utc-base \
#     --output_dir ./checkpoint/model_best \
#     --dataset_path ./data/ \
#     --max_seq_length 512  \
#     --per_device_train_batch_size 2 \
#     --per_device_eval_batch_size 2 \
#     --gradient_accumulation_steps 8 \
#     --num_train_epochs 20 \
#     --learning_rate 1e-5 \
#     --do_train \
#     --do_eval \
#     --do_export \
#     --export_model_dir ./checkpoint/model_best \
#     --overwrite_output_dir \
#     --disable_tqdm True \
#     --metric_for_best_model macro_f1 \
#     --load_best_model_at_end  True \
#     --save_total_limit 1 \
#     --save_plm

該示例程式碼中由於設定了引數 --do_eval,因此在訓練完會自動進行評估。

可配置引數說明:

  • single_label: 每條樣本是否只預測一個標籤。預設為False,表示多標籤分類。
  • device: 訓練裝置,可選擇 'cpu'、'gpu' 其中的一種;預設為 GPU 訓練。
  • logging_steps: 訓練過程中日誌列印的間隔 steps 數,預設10。
  • save_steps: 訓練過程中儲存模型 checkpoint 的間隔 steps 數,預設100。
  • eval_steps: 訓練過程中儲存模型 checkpoint 的間隔 steps 數,預設100。
  • seed:全域性隨機種子,預設為 42。
  • model_name_or_path:進行 few shot 訓練使用的預訓練模型。預設為 "utc-base", 可選"utc-xbase", "utc-base", "utc-medium", "utc-mini", "utc-micro", "utc-nano", "utc-pico"。
  • output_dir:必須,模型訓練或壓縮後儲存的模型目錄;預設為 None
  • dataset_path:資料集檔案所在目錄;預設為 ./data/
  • train_file:訓練集字尾;預設為 train.txt
  • dev_file:開發集字尾;預設為 dev.txt
  • max_seq_len:文字最大切分長度,包括標籤的輸入超過最大長度時會對輸入文字進行自動切分,標籤部分不可切分,預設為512。
  • per_device_train_batch_size:用於訓練的每個 GPU 核心/CPU 的batch大小,預設為8。
  • per_device_eval_batch_size:用於評估的每個 GPU 核心/CPU 的batch大小,預設為8。
  • num_train_epochs: 訓練輪次,使用早停法時可以選擇 100;預設為10。
  • learning_rate:訓練最大學習率,UTC 推薦設定為 1e-5;預設值為3e-5。
  • do_train:是否進行微調訓練,設定該參數列示進行微調訓練,預設不設定。
  • do_eval:是否進行評估,設定該參數列示進行評估,預設不設定。
  • do_export:是否進行匯出,設定該參數列示進行靜態圖匯出,預設不設定。
  • export_model_dir:靜態圖匯出地址,預設為None。
  • overwrite_output_dir: 如果 True,覆蓋輸出目錄的內容。如果 output_dir 指向檢查點目錄,則使用它繼續訓練。
  • disable_tqdm: 是否使用tqdm進度條。
  • metric_for_best_model:最優模型指標, UTC 推薦設定為 macro_f1,預設為None。
  • load_best_model_at_end:訓練結束後是否載入最優模型,通常與metric_for_best_model配合使用,預設為False。
  • save_total_limit:如果設定次引數,將限制checkpoint的總數。刪除舊的checkpoints 輸出目錄,預設為None。
  • --save_plm:儲存模型進行推理部署

4.2 模型評估

透過執行以下命令進行模型評估預測:

!python run_eval.py \
    --model_path ./checkpoint/model_best \
    --test_path ./data/test.txt \
    --per_device_eval_batch_size 16 \
    --max_seq_len 512 \
    --output_dir ./checkpoint_test

測試結果

[2023-04-13 17:06:59,413] [    INFO] -   test_loss               =     1.6392
[2023-04-13 17:06:59,413] [    INFO] -   test_macro_f1           =     0.8167
[2023-04-13 17:06:59,413] [    INFO] -   test_micro_f1           =     0.9394
[2023-04-13 17:06:59,413] [    INFO] -   test_runtime            = 0:00:00.87
[2023-04-13 17:06:59,413] [    INFO] -   test_samples_per_second =      6.835
[2023-04-13 17:06:59,413] [    INFO] -   test_steps_per_second   =      1.139

可配置引數說明:

  • model_path: 進行評估的模型資料夾路徑,路徑下需包含模型權重檔案model_state.pdparams及配置檔案model_config.json
  • test_path: 進行評估的測試集檔案。
  • per_device_eval_batch_size: 批處理大小,請結合機器情況進行調整,預設為16。
  • max_seq_len: 文字最大切分長度,輸入超過最大長度時會對輸入文字進行自動切分,預設為512。
  • single_label: 每條樣本是否只預測一個標籤。預設為False,表示多標籤分類。

4.3模型預測

paddlenlp.Taskflow裝載定製模型,透過task_path指定模型權重檔案的路徑,路徑下需要包含訓練好的模型權重檔案model_state.pdparams

!pip install onnxruntime-gpu onnx onnxconverter-common
!pip install paddle2onnx
#如果出現這個報錯 local variable 'paddle2onnx' referenced before assignment ,請安裝上述庫onnx 的包需要安裝
#中途出現一些警告可以忽視

from pprint import pprint
from paddlenlp import Taskflow
schema = ["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"]
# my_cls = Taskflow("zero_shot_text_classification", model="utc-base", schema=schema, task_path='/home/aistudio/checkpoint/model_best/plm', precision="fp16")
my_cls = Taskflow("zero_shot_text_classification", model="utc-base", schema=schema, task_path='/home/aistudio/checkpoint/model_best/plm')
#支援FP16半精度推理加速,需要安裝onnx
pprint(my_cls(["老年斑為什麼都長在面部和手背上","老成都市哪家內痔醫院比較好怎麼樣最好?","中性粒細胞比率偏低"]))
[2023-04-14 11:45:11,057] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load 'utc-base'.
[2023-04-14 11:45:11,059] [    INFO] - Already cached /home/aistudio/.paddlenlp/models/utc-base/utc_base_vocab.txt
[2023-04-14 11:45:11,083] [    INFO] - tokenizer config file saved in /home/aistudio/.paddlenlp/models/utc-base/tokenizer_config.json
[2023-04-14 11:45:11,085] [    INFO] - Special tokens file saved in /home/aistudio/.paddlenlp/models/utc-base/special_tokens_map.json
[2023-04-14 11:45:11,088] [    INFO] - Assigning ['[O-MASK]'] to the additional_special_tokens key of the tokenizer


[{'predictions': [{'label': '病因分析', 'score': 0.7360146263899581}],
  'text_a': '老年斑為什麼都長在面部和手背上'},
 {'predictions': [{'label': '就醫建議', 'score': 0.9940570944549809}],
  'text_a': '老成都市哪家內痔醫院比較好怎麼樣最好?'},
 {'predictions': [{'label': '指標解讀', 'score': 0.6683004187689248}],
  'text_a': '中性粒細胞比率偏低'}]
from pprint import pprint
from paddlenlp import Taskflow
schema = ["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"]
my_cls = Taskflow("zero_shot_text_classification", model="utc-base", schema=schema)
pprint(my_cls(["老年斑為什麼都長在面部和手背上","老成都市哪家內痔醫院比較好怎麼樣最好?","中性粒細胞比率偏低"]))
[2023-04-14 11:45:20,869] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load 'utc-base'.
[2023-04-14 11:45:20,872] [    INFO] - Already cached /home/aistudio/.paddlenlp/models/utc-base/utc_base_vocab.txt
[2023-04-14 11:45:20,897] [    INFO] - tokenizer config file saved in /home/aistudio/.paddlenlp/models/utc-base/tokenizer_config.json
[2023-04-14 11:45:20,900] [    INFO] - Special tokens file saved in /home/aistudio/.paddlenlp/models/utc-base/special_tokens_map.json
[2023-04-14 11:45:20,903] [    INFO] - Assigning ['[O-MASK]'] to the additional_special_tokens key of the tokenizer


[{'predictions': [], 'text_a': '老年斑為什麼都長在面部和手背上'},
 {'predictions': [{'label': '就醫建議', 'score': 0.9283481315032535},
                  {'label': '其他', 'score': 0.5083715719139965}],
  'text_a': '老成都市哪家內痔醫院比較好怎麼樣最好?'},
 {'predictions': [{'label': '其他', 'score': 0.9437889944553786}],
  'text_a': '中性粒細胞比率偏低'}]

4.3.1 預測結果對比

模型 文字 預測結果 評估得分
utc-base 老年斑為什麼都長在面部和手背上 ---
utc-base 老成都市哪家內痔醫院比較好怎麼樣最好? 就醫建議/其他 0.92/0.51
utc-base 中性粒細胞比率偏低 其他 0.94
utc-base+微調 老年斑為什麼都長在面部和手背上 病因分析 0.73
utc-base+微調 老成都市哪家內痔醫院比較好怎麼樣最好? 就醫建議 0.99
utc-base+微調 中性粒細胞比率偏低 指標解讀 0.66

明顯可以看到在透過樣本訓練後,在test測試的結果小樣本本微調的結果顯著提升

4.3.2 各個模型見對比

Micro F1更關注整個資料集的效能,而Macro F1更關注每個類別的效能。

醫療意圖分類資料集 KUAKE-QIC 驗證集 zero-shot 實驗指標和小樣本下訓練對比:

Macro F1 Micro F1 微調後 Macro F1 微調後 Micro F1
utc-xbase 66.30 89.67
utc-base 64.13 89.06 81.67(+17.54) 93.94 (+4.88)
utc-medium 69.62 89.15
utc-micro 60.31 79.14
utc-mini 65.82 89.82
utc-nano 62.03 80.92
utc-pico 53.63 83.57

其餘模型就不一一驗證了,感興趣同學自行驗證。

5.模型部署

目前 UTC 模型提供基於多種部署方式,包括基於 FastDeploy 的本地 Python 部署以及 PaddleNLP SimpleServing 的服務化部署。

5.1 FastDeploy UTC 模型 Python 部署示例

以下示例展示如何基於 FastDeploy 庫完成 UTC 模型完成通用文字分類任務的 Python 預測部署,可透過命令列引數--device以及--backend指定執行在不同的硬體以及推理引擎後端,並使用--model_dir引數指定執行的模型。模型目錄為 application/zero_shot_text_classification/checkpoint/model_best(使用者可按實際情況設定)。

在部署前,參考 FastDeploy SDK 安裝文件安裝 FastDeploy Python SDK。

本目錄下提供 infer.py 快速完成在 CPU/GPU 的通用文字分類任務的 Python 部署示例。

  • 依賴安裝

直接執行以下命令安裝部署示例的依賴。

# 安裝 fast_tokenizer 以及 GPU 版本 fastdeploy
pip install fast-tokenizer-python fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html

以下示例展示如何基於 FastDeploy 庫完成 UTC 模型進行文字分類任務的 Python 預測部署,可透過命令列引數--device以及--backend指定執行在不同的硬體以及推理引擎後端,並使用--model_dir引數指定執行的模型,具體引數設定可檢視下面[引數說明])。示例中的模型是按照 [UTC 訓練文件]匯出得到的部署模型,其模型目錄為 application/zero_shot_text_classification/checkpoint/model_best(使用者可按實際情況設定)。

# CPU 推理
python /home/aistudio/deploy/python/infer.py--model_dir /home/aistudio/checkpoint/model_best --device cpu
# GPU 推理
python /home/aistudio/deploy/python/infer.py --model_dir /home/aistudio/checkpoint/model_best --device gpu

執行完成後返回的結果如下:

  • 引數說明
引數 引數說明
--model_dir 指定部署模型的目錄,
--batch_size 輸入的batch size,預設為 1
--max_length 最大序列長度,預設為 128
--num_omask_tokens 最大標籤數量,預設為64
--device 執行的裝置,可選範圍: ['cpu', 'gpu'],預設為'cpu'
--device_id 執行裝置的id。預設為0。
--cpu_threads 當使用cpu推理時,指定推理的cpu執行緒數,預設為1。
--backend 支援的推理後端,可選範圍: ['onnx_runtime', 'paddle', 'tensorrt', 'paddle_tensorrt'],預設為'paddle'
--use_fp16 是否使用FP16模式進行推理。使用tensorrt和paddle_tensorrt後端時可開啟,預設為False
  • FastDeploy 高階用法

FastDeploy 在 Python 端上,提供 fastdeploy.RuntimeOption.use_xxx() 以及 fastdeploy.RuntimeOption.use_xxx_backend() 介面支援開發者選擇不同的硬體、不同的推理引擎進行部署。在不同的硬體上部署 UTC 模型,需要選擇硬體所支援的推理引擎進行部署,下表展示如何在不同的硬體上選擇可用的推理引擎部署 UTC 模型。

符號說明: (1) ✅: 已經支援; (2) ❔: 正在進行中; (3) N/A: 暫不支援;

硬體 硬體對應的介面 可用的推理引擎 推理引擎對應的介面 是否支援 Paddle 新格式量化模型 是否支援 FP16 模式
CPU use_cpu() Paddle Inference use_paddle_infer_backend() N/A
ONNX Runtime use_ort_backend() N/A
GPU use_gpu() Paddle Inference use_paddle_infer_backend() N/A
ONNX Runtime use_ort_backend()
Paddle TensorRT use_paddle_infer_backend() + paddle_infer_option.enable_trt = True
TensorRT use_trt_backend()
崑崙芯 XPU use_kunlunxin() Paddle Lite use_paddle_lite_backend() N/A
華為 昇騰 use_ascend() Paddle Lite use_paddle_lite_backend()
Graphcore IPU use_ipu() Paddle Inference use_paddle_infer_backend() N/A
# !pip install --user fast-tokenizer-python fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html
#比較大1.4G 去終端安裝

在notebook執行出現問題,可能需要本地對fastdeploy應用除錯,或者有小夥伴解決了可以再評論區發表一下,一起解決。

  1. 在studio 目前顯示是安裝成功了,但是初始化是失敗的
  File "/home/aistudio/.data/webide/pip/lib/python3.7/site-packages/fastdeploy/c_lib_wrap.py", line 166, in <module>
    raise RuntimeError("FastDeploy initalized failed!")
RuntimeError: FastDeploy initalized failed!
  1. 在本地測試模型使用了utc-pico,cpu情況下除錯。

效果如下:

記得修改infer檔案對應的預測內容

    predictor = Predictor(args, schema=["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"])
    results = predictor.predict(["月經期間刮痧拔罐會引起身體什麼","老年斑為什麼都長在面部和手背上","成都市哪家內痔醫院比較好怎麼樣最好?","中性粒細胞比率偏低"])

推理:模型目錄需要包含:model.pdmodel等檔案

5.2 SimpleServing 的服務化部署

在 UTC 的服務化能力中我們提供基於PaddleNLP SimpleServing 來搭建服務化能力,透過幾行程式碼即可搭建服務化部署能力。

  • 環境準備

使用有SimpleServing功能的PaddleNLP版本(或者最新的develop版本)

pip install paddlenlp >= 2.5.0
  • Server服務啟動

進入檔案當前所在路徑

paddlenlp server server:app --workers 1 --host 0.0.0.0 --port 8190
  • Client請求啟動
python client.py
  • 服務化自定義引數

    • Server 自定義引數

    • schema替換

# Default schema
schema = ["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"]
* 設定模型路徑
# Default task_path
utc = Taskflow("zero_shot_text_classification", model="utc-base", task_path="../../checkpoint/model_best/plm", schema=schema)
* 多卡服務化預測

PaddleNLP SimpleServing 支援多卡負載均衡預測,主要在服務化註冊的時候,註冊兩個Taskflow的task即可,下面是示例程式碼

utc1 = Taskflow("zero_shot_text_classification", model="utc-base", task_path="../../checkpoint/model_best", schema=schema)
utc2 = Taskflow("zero_shot_text_classification", model="utc-base", task_path="../../checkpoint/model_best", schema=schema)
service.register_taskflow("taskflow/utc", [utc1, utc2])
  • 更多配置
from paddlenlp import Taskflow
schema = ["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"]
utc = Taskflow("zero_shot_text_classification",
                   schema=schema,
                   model="utc-base",
                   max_seq_len=512,
                   batch_size=1,
                   pred_threshold=0.5,
                   precision="fp32")
  • schema:定義任務標籤候選集合。

  • model:選擇任務使用的模型,預設為utc-base, 可選有utc-xbase, utc-base, utc-medium, utc-micro, utc-mini, utc-nano, utc-pico

  • max_seq_len:最長輸入長度,包括所有標籤的長度,預設為512。

  • batch_size:批處理大小,請結合機器情況進行調整,預設為1。

  • pred_threshold:模型對標籤預測的機率在0~1之間,返回結果去掉小於這個閾值的結果,預設為0.5。

  • precision:選擇模型精度,預設為fp32,可選有fp16fp32fp16推理速度更快。如果選擇fp16,請先確保機器正確安裝NVIDIA相關驅動和基礎軟體,確保CUDA>=11.2,cuDNN>=8.1.1,初次使用需按照提示安裝相關依賴。其次,需要確保GPU裝置的CUDA計算能力(CUDA Compute Capability)大於7.0,典型的裝置包括V100、T4、A10、A100、GTX 20系列和30系列顯示卡等。更多關於CUDA Compute Capability和精度支援情況請參考NVIDIA文件:GPU硬體與支援精度對照表

    • Client 自定義引數
# Changed to input texts you wanted
texts = ["中性粒細胞比率偏低"]
%cd /home/aistudio/deploy/simple_serving
!paddlenlp server server:app --workers 1 --host 0.0.0.0 --port 8190
#Error loading ASGI app. Could not import module "server".
#去終端執行即可
/home/aistudio/deploy/simple_serving
[2023-04-13 18:26:51,839] [    INFO] - starting to PaddleNLP SimpleServer...
[2023-04-13 18:26:51,840] [    INFO] - The PaddleNLP SimpleServer is starting, backend component uvicorn arguments as follows:
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [host]=0.0.0.0
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [port]=8190
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [log_level]=None
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [workers]=1
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [limit_concurrency]=None
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [limit_max_requests]=None
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [timeout_keep_alive]=15
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [app_dir]=/home/aistudio/deploy/simple_serving
[2023-04-13 18:26:51,840] [    INFO] -    the starting argument [reload]=False
[2023-04-13 18:26:52,037] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load 'utc-base'.
[2023-04-13 18:26:52,038] [    INFO] - Already cached /home/aistudio/.paddlenlp/models/utc-base/utc_base_vocab.txt
[2023-04-13 18:26:52,067] [    INFO] - tokenizer config file saved in /home/aistudio/.paddlenlp/models/utc-base/tokenizer_config.json
[2023-04-13 18:26:52,067] [    INFO] - Special tokens file saved in /home/aistudio/.paddlenlp/models/utc-base/special_tokens_map.json
[2023-04-13 18:26:52,069] [    INFO] - Assigning ['[O-MASK]'] to the additional_special_tokens key of the tokenizer
[2023-04-13 18:26:55,628] [    INFO] -    Taskflow  request [path]=/taskflow/utc is genereated.
INFO:     Started server process [1718]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)
^C
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [1718]

在notebook如果不行,可以直接進入終端進行除錯,需要注意的是要在同一個路徑下不然會報錯

# Save at server.py
from paddlenlp import SimpleServer, Taskflow

schema = ["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議"]
utc = Taskflow("zero_shot_text_classification",
               model="utc-base",
               schema=schema,
               task_path="/home/aistudio/checkpoint/model_best/plm",
               precision="fp32")
app = SimpleServer()
app.register_taskflow("taskflow/utc", utc)
# %cd /home/aistudio/deploy/simple_serving
!python client.py

6.總結

原專案連結:

https://blog.csdn.net/sinat_39620217/article/details/130237035

原文文末含碼源以及地址

Macro F1和Micro F1都是評估分類模型效能的指標,但是它們計算方式不同。

  • Macro F1是每個類別的F1值的平均值,不考慮類別的樣本數。它適用於資料集中各個類別的樣本數量相近的情況下,可以更好地反映每個類別的效能。

  • Micro F1是所有類別的F1值的加權平均,其中權重為每個類別的樣本數。它將所有類別的預測結果彙總為一個混淆矩陣,並計算出整個資料集的精確率、召回率和F1值。Micro F1適用於多分類問題,尤其是在資料集不平衡的情況下,可以更好地反映整體的效能。

總之,Micro F1更關注整個資料集的效能,而Macro F1更關注每個類別的效能。

醫療意圖分類資料集 KUAKE-QIC 驗證集 zero-shot 實驗指標和小樣本下訓練對比:

Macro F1 Micro F1 微調後 Macro F1 微調後 Micro F1
utc-xbase 66.30 89.67
utc-base 64.13 89.06 81.67(+17.54) 93.94 (+4.88)
utc-medium 69.62 89.15
utc-micro 60.31 79.14
utc-mini 65.82 89.82
utc-nano 62.03 80.92
utc-pico 53.63 83.57

6.1 更多工適配

PaddleNLP結合文心ERNIE,基於UTC技術開源了首個面向通用文字分類的產業級技術方案。對於簡單任務,透過呼叫 paddlenlp.Taskflow API ,僅用三行程式碼即可實現零樣本(Zero-shot)通用文字分類,可支援情感分析、意圖識別、語義匹配、蘊含推理等各種可轉換為分類問題的NLU任務。僅使用一個模型即可同時支援多個任務,便捷高效!

from pprint import pprint
from paddlenlp import Taskflow
# 情感分析
cls = Taskflow("zero_shot_text_classification", schema=["這是一條好評", "這是一條差評"])
cls("房間乾淨明亮,非常不錯")
>>>
[{'predictions': [{'label': '這是一條好評', 'score': 0.9695149765679986}], 
'text_a': '房間乾淨明亮,非常不錯'}]

# 意圖識別
schema = ["病情診斷", "治療方案", "病因分析", "指標解讀", "就醫建議", "疾病表述", "後果表述", "注意事項", "功效作用", "醫療費用", "其他"]
pprint(cls("先天性厚甲症去哪裡治"))
>>>
[{'predictions': [{'label': '就醫建議', 'score': 0.9628814210597645}], 
'text_a': '先天性厚甲症去哪裡治'}]

# 語義相似度
cls = Taskflow("zero_shot_text_classification", schema=["不同", "相同"])
pprint(cls([["怎麼檢視合同", "從哪裡可以看到合同"], ["為什麼一直沒有電話來確認借款資訊", "為何我還款了,今天卻接到客服電話通知"]]))
>>>
[{'predictions': [{'label': '相同', 'score': 0.9775065319076257}],
'text_a': '怎麼檢視合同',
'text_b': '從哪裡可以看到合同'},
{'predictions': [{'label': '不同', 'score': 0.9918983379165037}],
'text_a': '為什麼一直沒有電話來確認借款資訊',
'text_b': '為何我還款了,今天卻接到客服電話通知'}]

# 蘊含推理
cls = Taskflow("zero_shot_text_classification", schema=["中立", "蘊含", "矛盾"])
pprint(cls([["一個騎腳踏車的人正沿著一條城市街道朝一座有時鐘的塔走去。", "騎腳踏車的人正朝鐘樓走去。"],
          ["一個留著長髮和鬍鬚的怪人,在地鐵裡穿著一件顏色鮮豔的襯衫。", "這件襯衫是新的。"],
          ["一個穿著綠色襯衫的媽媽和一個穿全黑衣服的男人在跳舞。", "兩人都穿著白色褲子。"]]))
>>>
[{'predictions': [{'label': '蘊含', 'score': 0.9944843058584897}], 
'text_a': '一個騎腳踏車的人正沿著一條城市街道朝一座有時鐘的塔走去。',
'text_b': '騎腳踏車的人正朝鐘樓走去。'},
{'predictions': [{'label': '中立', 'score': 0.6659998351201399}], 
'text_a': '一個留著長髮和鬍鬚的怪人,在地鐵裡穿著一件顏色鮮豔的襯衫。',
'text_b': '這件襯衫是新的。'},
{'predictions': [{'label': '矛盾', 'score': 0.9270557883904931}], 
'text_a': '一個穿著綠色襯衫的媽媽和一個穿全黑衣服的男人在跳舞。',
'text_b': '兩人都穿著白色褲子。'}]

相關文章