基於Labelstudio的UIE半監督智慧標註方案(本地版)

✨汀、發表於2023-04-03

基於Labelstudio的UIE半監督智慧標註方案(本地版)

更多技術細節參考上一篇專案,本篇主要側重本地端鏈路走通教學,提速提效:

基於Labelstudio的UIE半監督深度學習的智慧標註方案(雲端版),提效

更多內容參考文末碼源

自然語言處理資訊抽取智慧標註方案包括以下幾種:

  1. 基於規則的標註方案:透過編寫一系列規則來識別文字中的實體、關係等資訊,並將其標註。

    • 基於規則的標註方案是一種傳統的方法,它需要人工編寫規則來識別文字中的實體、關係等資訊,並將其標註。
    • 這種方法的優點是易於理解和實現,但缺點是需要大量的人工工作,並且規則難以覆蓋所有情況。
  2. 基於機器學習的標註方案:透過訓練模型來自動識別文字中的實體、關係等資訊,並將其標註。

    • 基於機器學習的標註方案是一種自動化的方法,它使用已經標註好的資料集訓練模型,並使用模型來自動標註文字中的實體、關係等資訊。
    • 這種方法的優點是可以處理大量的資料,並且可以自適應地調整模型,但缺點是需要大量的標註資料和計算資源,並且模型的效能受到標註資料的質量和數量的限制。
  3. 基於深度學習的標註方案:透過使用深度學習模型來自動識別文字中的實體、關係等資訊,並將其標註。

    • 基於深度學習的標註方案是一種最新的方法,它使用深度學習模型來自動從文字中提取實體、關係等資訊,並將其標註。
    • 這種方法的優點是可以處理大量的資料,並且具有較高的準確性,但缺點是需要大量的標註資料和計算資源,並且模型的訓練和除錯需要專業的知識和技能。
  4. 基於半監督學習的標註方案:透過使用少量的手工標註資料和大量的未標註資料來訓練模型,從而實現自動標註。

    • 基於半監督學習的標註方案是一種利用少量的手工標註資料和大量的未標註資料來訓練模型的方法。
    • 這種方法的優點是可以利用未標註資料來提高模型的效能,但缺點是需要大量的未標註資料和計算資源,並且模型的效能受到標註資料的質量
  5. 基於遠端監督的標註方案:利用已知的知識庫來自動標註文字中的實體、關係等資訊,從而減少手工標註的工作量。

本次專案主要講解的是基於半監督深度學習的標註方案。

1.智慧標註本地版 Machine Learning 整合教學

1.1 本地啟動 Label Studio

安裝label-studio:

#建立名為label_studio的虛擬環境(示例的Python版本為3.8)
conda create -n labelstudio python=3.8

#啟用虛擬環境
conda activate labelstudio


#pip安裝label-studio (version=1.7.2)
pip install label-studio==1.7.2

1.2 啟動 Machine Learning Backend

在終端中依次執行下列命令:


#安裝label-studio機器學習後端,dirname為放程式碼的資料夾路徑
cd dirname
git clone https://github.com/heartexlabs/label-studio-ml-backend

#安裝label-studio及其依賴
cd label-studio-ml-backend
pip install -U -e .

#(可選) 安裝label-studio中examples執行所需的requirements
pip install -r label_studio_ml/examples/requirements.txt

建立與啟動模型:定義模型
在使用label-studio後端之前,要先定義好自己的訓練模型,模型的定義需要繼承自label-studio指定的類,具體可參考第四節。
建立後端模型:按照要求建立好的模型檔案的路徑假設為/Users/kyrol/Desktop/my_ml_backend.py,終端中執行以下命令:


# 初始化自定義機器學習後端
label-studio-ml init my_ml_backend --script /Users/kyrol/Desktop/my_ml_backend.py

#命令執行完畢會在當前資料夾下建立名為 my_ml_backend 的資料夾, 裡面放有 my_ml_backend.py, _wsgi.py 等內容。
#其中,_wsgi.py是要執行的python 主檔案,可以檢視裡面內容。注意:同時需要把依賴檔案放入my_ml_backend.py資料夾。

# 開啟機器學習後端服務
label-studio-ml start my_ml_backend

成功啟動後,在終端中可以看到 ML 後端的 URL。

1.3 模型配置與訓練

開啟視覺化視窗,再開啟一個終端視窗,首先,啟用conda對應的環境;然後,cd 到label-studio程式碼所在路徑;然後,執行以下終端命令,啟動視覺化的視窗:

在啟動自定義機器學習後端之後,就可以將其新增到 Label Studio 專案中。

具體步驟如下:

  • 配置訓練資料檔案

    • 根據不同的任務配置不同的標籤,在settings中點選Labeling Interface, 配置專案標籤,具體可參考官網。
  • 訓練模型

    • 建立一個project
    • 點選 setting
    • 點選 Machine Learning
    • 配置模型訓練埠,匯入模型
  • 訓練後的模型會儲存在 my_ml_backend 資料夾中以數字命名的資料夾內。

具體步驟如下所示:

  1. 點選 Settings - Machine Learning - Add Model

  1. 填入標題、ML 後端的 URL、描述(可選)等內容

  1. 選擇 Use for interactive preannotations 開啟互動式預註釋功能(可選)

  2. 點選 Validate and Save

1.3 獲取互動式預註釋

若要使用互動式預註釋功能,需在新增 ML Backend 時開啟 Use for interactive preannotations 選項。如未開啟,可點選 Edit 進行編輯。然後隨便點選一個資料,label studio 就會悄悄執行剛才的 ml backend 生成新的標註了。

檢視預標註好的資料,如有必要,對標註進行修改。

  • 本例中,預標註的結果中『NBA』沒有被識別出來,手動新增實體將其標註為『組織』。

  • 本例中,預標註的結果中將『人名』實體『三月』錯標註為『時間』實體,手動進行修改。

修改完成後,或預標註的結果已經符合預期,點選 Submit 提交標註結果。

1.4 智慧標註(自動再訓練模型)

在標註了至少一項任務之後,就可以開始訓練模型了。

點選 Settings - Machine Learning - Start Training 開始訓練。

動態圖為引用方便展示這個流程。

**然後返回啟動 label-studio-ml-backend 的視窗可以看到訓練的流程啟動了。 **

2.UIE-base預訓練模型進行命名實體識別

from pprint import pprint
from paddlenlp import Taskflow

schema = ['地名', '人名', '組織', '時間', '產品', '價格', '天氣']
ie = Taskflow('information_extraction', schema=schema)

pprint(ie("2K 與 Gearbox Software 宣佈,《小緹娜的奇幻之地》將於 6 月 24 日凌晨 1 點登入 Steam,此前 PC 平臺為 Epic 限時獨佔。在限定期間內,Steam 玩家可以在 Steam 入手《小緹娜的奇幻之地》,並在 2022 年 7 月 8 日前享有獲得黃金英雄鎧甲包。"))
[{'產品': [{'end': 35,
          'probability': 0.8595664902550801,
          'start': 25,
          'text': '《小緹娜的奇幻之地》'}],
  '地名': [{'end': 34,
          'probability': 0.30077351606695757,
          'start': 26,
          'text': '小緹娜的奇幻之地'},
         {'end': 117,
          'probability': 0.5250433327469182,
          'start': 109,
          'text': '小緹娜的奇幻之地'}],
  '時間': [{'end': 52,
          'probability': 0.8796518890642702,
          'start': 38,
          'text': '6 月 24 日凌晨 1 點'}],
  '組織': [{'end': 2,
          'probability': 0.6914450625760651,
          'start': 0,
          'text': '2K'},
         {'end': 93,
          'probability': 0.5971815528872604,
          'start': 88,
          'text': 'Steam'},
         {'end': 75,
          'probability': 0.5844303540013343,
          'start': 71,
          'text': 'Epic'},
         {'end': 105,
          'probability': 0.45620707081511114,
          'start': 100,
          'text': 'Steam'},
         {'end': 60,
          'probability': 0.5683007420326334,
          'start': 55,
          'text': 'Steam'},
         {'end': 21,
          'probability': 0.6797917390407271,
          'start': 5,
          'text': 'Gearbox Software'}]}]
pprint(ie("近日,量子計算專家、ACM計算獎得主Scott Aaronson透過部落格宣佈,將於本週離開得克薩斯大學奧斯汀分校(UT Austin)一年,並加盟人工智慧研究公司OpenAI。"))
[{'人名': [{'end': 23,
          'probability': 0.664236391748247,
          'start': 18,
          'text': 'Scott'},
         {'end': 32,
          'probability': 0.479811241610971,
          'start': 24,
          'text': 'Aaronson'}],
  '時間': [{'end': 43,
          'probability': 0.8424644728072508,
          'start': 41,
          'text': '本週'}],
  '組織': [{'end': 87,
          'probability': 0.5550909248934985,
          'start': 81,
          'text': 'OpenAI'}]}]

使用預設模型 uie-base 進行命名實體識別,效果還不錯,大多數的命名實體被識別出來了,但依然存在部分實體未被識別出,部分文字被誤識別等問題。比如 "Scott Aaronson" 被識別為了兩個人名,比如 "得克薩斯大學奧斯汀分校" 沒有被識別出來。為提升識別效果,將透過標註少量資料對模型進行微調。

3.模型微調

在終端中執行以下指令碼,將 label studio 匯出的資料檔案格式轉換成 doccano 匯出的資料檔案格式。

python labelstudio2doccano.py --labelstudio_file dataset/label-studio.json

引數說明:

  • labelstudio_file: label studio 的匯出檔案路徑(僅支援 JSON 格式)。
  • doccano_file: doccano 格式的資料檔案儲存路徑,預設為 "doccano_ext.jsonl"。
  • task_type: 任務型別,可選有抽取("ext")和分類("cls")兩種型別的任務,預設為 "ext"。
!python doccano.py \
    --doccano_file dataset/doccano_ext.jsonl \
    --task_type "ext" \
    --save_dir ./data \
    --splits 0.8 0.2 0

引數說明:

  • doccano_file: doccano 格式的資料標註檔案路徑。
  • task_type: 選擇任務型別,可選有抽取("ext")和分類("cls")兩種型別的任務。
  • save_dir: 訓練資料的儲存目錄,預設儲存在 data 目錄下。
  • negative_ratio: 最大負例比例,該引數只對抽取型別任務有效,適當構造負例可提升模型效果。負例數量和實際的標籤數量有關,最大負例數量 = negative_ratio * 正例數量。該引數只對訓練集有效,預設為 5。為了保證評估指標的準確性,驗證集和測試集預設構造全負例。
  • splits: 劃分資料集時訓練集、驗證集、測試集所佔的比例。預設為 [0.8, 0.1, 0.1] 。
  • options: 指定分類任務的類別標籤,該引數只對分類型別任務有效。預設為 ["正向", "負向"]。
  • prompt_prefix: 宣告分類任務的 prompt 字首資訊,該引數只對分類型別任務有效。預設為 "情感傾向"。
  • is_shuffle: 是否對資料集進行隨機打散,預設為 True。
  • seed: 隨機種子,預設為 1000。
  • separator: 實體類別/評價維度與分類標籤的分隔符,該引數只對實體/評價維度級分類任務有效。預設為 "##"。

注:

  • 每次執行 doccano.py 指令碼,將會覆蓋已有的同名資料檔案。

3.1 Finetune

在終端中執行以下指令碼進行模型微調。

# 然後在終端中執行以下指令碼,對 doccano 格式的資料檔案進行處理,執行後會在 /home/data 目錄下生成訓練/驗證/測試集檔案。
!python finetune.py \
    --train_path "./data/train.txt" \
    --dev_path "./data/dev.txt" \
    --save_dir "./checkpoint" \
    --learning_rate 1e-5 \
    --batch_size 32 \
    --max_seq_len 512 \
    --num_epochs 100 \
    --model "uie-base" \
    --seed 1000 \
    --logging_steps 100 \
    --valid_steps 100 \
    --device "gpu"
[2023-03-31 16:14:53,465] [    INFO] - global step 600, epoch: 67, loss: 0.00012, speed: 3.76 step/s
[2023-03-31 16:14:53,908] [    INFO] - Evaluation precision: 0.93478, recall: 0.79630, F1: 0.86000
[2023-03-31 16:15:20,328] [    INFO] - global step 700, epoch: 78, loss: 0.00010, speed: 3.79 step/s
[2023-03-31 16:15:20,777] [    INFO] - Evaluation precision: 0.93750, recall: 0.83333, F1: 0.88235
[2023-03-31 16:15:46,992] [    INFO] - global step 800, epoch: 89, loss: 0.00009, speed: 3.81 step/s
[2023-03-31 16:15:47,439] [    INFO] - Evaluation precision: 0.91667, recall: 0.81481, F1: 0.86275
[2023-03-31 16:16:13,316] [    INFO] - global step 900, epoch: 100, loss: 0.00008, speed: 3.86 step/s
[2023-03-31 16:16:13,758] [    INFO] - Evaluation precision: 0.95833, recall: 0.85185, F1: 0.90196

結果展示:


引數說明:

  • train_path: 訓練集檔案路徑。
  • dev_path: 驗證集檔案路徑。
  • save_dir: 模型儲存路徑,預設為 "./checkpoint"。
  • learning_rate: 學習率,預設為 1e-5。
  • batch_size: 批處理大小,請結合機器情況進行調整,預設為 16。
  • max_seq_len: 文字最大切分長度,輸入超過最大長度時會對輸入文字進行自動切分,預設為 512。
  • num_epochs: 訓練輪數,預設為 100。
  • model: 選擇模型,程式會基於選擇的模型進行模型微調,可選有 "uie-base", "uie-medium", "uie-mini", "uie-micro" 和 "uie-nano",預設為 "uie-base"。
  • seed: 隨機種子,預設為 1000。
  • logging_steps: 日誌列印的間隔 steps 數,預設為 10。
  • valid_steps: evaluate 的間隔 steps 數,預設為 100。
  • device: 選用什麼裝置進行訓練,可選 "cpu" 或 "gpu"。
  • init_from_ckpt: 初始化模型引數的路徑,可從斷點處繼續訓練。

3.2 模型評估

在終端中執行以下指令碼進行模型評估。

輸出示例:

引數說明:

  • model_path: 進行評估的模型資料夾路徑,路徑下需包含模型權重檔案 model_state.pdparams 及配置檔案 model_config.json。
  • test_path: 進行評估的測試集檔案。
  • batch_size: 批處理大小,請結合機器情況進行調整,預設為 16。
  • max_seq_len: 文字最大切分長度,輸入超過最大長度時會對輸入文字進行自動切分,預設為 512。
  • debug: 是否開啟 debug 模式對每個正例類別分別進行評估,該模式僅用於模型除錯,預設關閉。

debug 模式輸出示例:

!python evaluate.py \
    --model_path ./checkpoint/model_best \
    --test_path ./data/dev.txt \
    --batch_size 16 \
    --max_seq_len 512
[2023-03-31 16:16:18,503] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load './checkpoint/model_best'.
W0331 16:16:18.530714  1666 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 8.0, Driver API Version: 11.2, Runtime API Version: 11.2
W0331 16:16:18.533171  1666 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.
[2023-03-31 16:16:24,551] [    INFO] - -----------------------------
[2023-03-31 16:16:24,551] [    INFO] - Class Name: all_classes
[2023-03-31 16:16:24,551] [    INFO] - Evaluation Precision: 0.95918 | Recall: 0.87037 | F1: 0.91262
!python evaluate.py \
    --model_path ./checkpoint/model_best \
    --test_path ./data/dev.txt \
    --debug
[2023-03-31 16:16:29,246] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load './checkpoint/model_best'.
W0331 16:16:29.278601  1707 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 8.0, Driver API Version: 11.2, Runtime API Version: 11.2
W0331 16:16:29.281224  1707 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.
[2023-03-31 16:16:34,944] [    INFO] - -----------------------------
[2023-03-31 16:16:34,944] [    INFO] - Class Name: 時間
[2023-03-31 16:16:34,944] [    INFO] - Evaluation Precision: 1.00000 | Recall: 0.90000 | F1: 0.94737
[2023-03-31 16:16:34,998] [    INFO] - -----------------------------
[2023-03-31 16:16:34,998] [    INFO] - Class Name: 地名
[2023-03-31 16:16:34,998] [    INFO] - Evaluation Precision: 0.95833 | Recall: 0.85185 | F1: 0.90196
[2023-03-31 16:16:35,022] [    INFO] - -----------------------------
[2023-03-31 16:16:35,022] [    INFO] - Class Name: 產品
[2023-03-31 16:16:35,022] [    INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000
[2023-03-31 16:16:35,048] [    INFO] - -----------------------------
[2023-03-31 16:16:35,048] [    INFO] - Class Name: 組織
[2023-03-31 16:16:35,049] [    INFO] - Evaluation Precision: 1.00000 | Recall: 0.50000 | F1: 0.66667
[2023-03-31 16:16:35,071] [    INFO] - -----------------------------
[2023-03-31 16:16:35,071] [    INFO] - Class Name: 人名
[2023-03-31 16:16:35,071] [    INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000
[2023-03-31 16:16:35,092] [    INFO] - -----------------------------
[2023-03-31 16:16:35,092] [    INFO] - Class Name: 天氣
[2023-03-31 16:16:35,092] [    INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000
[2023-03-31 16:16:35,109] [    INFO] - -----------------------------
[2023-03-31 16:16:35,109] [    INFO] - Class Name: 價格
[2023-03-31 16:16:35,109] [    INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000

3.3 微調後效果

my_ie = Taskflow("information_extraction", schema=schema, task_path='./checkpoint/model_best')  # task_path 指定模型權重檔案的路徑
pprint(my_ie("2K 與 Gearbox Software 宣佈,《小緹娜的奇幻之地》將於 6 月 24 日凌晨 1 點登入 Steam,此前 PC 平臺為 Epic 限時獨佔。在限定期間內,Steam 玩家可以在 Steam 入手《小緹娜的奇幻之地》,並在 2022 年 7 月 8 日前享有獲得黃金英雄鎧甲包。"))
[2023-03-31 16:16:39,383] [    INFO] - Converting to the inference model cost a little time.
[2023-03-31 16:16:46,661] [    INFO] - The inference model save in the path:./checkpoint/model_best/static/inference
[2023-03-31 16:16:48,783] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load './checkpoint/model_best'.


[{'產品': [{'end': 118,
          'probability': 0.9860396834664122,
          'start': 108,
          'text': '《小緹娜的奇幻之地》'},
         {'end': 35,
          'probability': 0.9870830377819004,
          'start': 25,
          'text': '《小緹娜的奇幻之地》'},
         {'end': 148,
          'probability': 0.9075236400717301,
          'start': 141,
          'text': '黃金英雄鎧甲包'}],
  '時間': [{'end': 52,
          'probability': 0.9998017644462607,
          'start': 38,
          'text': '6 月 24 日凌晨 1 點'},
         {'end': 137,
          'probability': 0.9875673117430104,
          'start': 122,
          'text': '2022 年 7 月 8 日前'}],
  '組織': [{'end': 2,
          'probability': 0.9888051241547942,
          'start': 0,
          'text': '2K'},
         {'end': 93,
          'probability': 0.9503029387182096,
          'start': 88,
          'text': 'Steam'},
         {'end': 75,
          'probability': 0.9819544449787045,
          'start': 71,
          'text': 'Epic'},
         {'end': 105,
          'probability': 0.7914398215948992,
          'start': 100,
          'text': 'Steam'},
         {'end': 60,
          'probability': 0.982935890915897,
          'start': 55,
          'text': 'Steam'},
         {'end': 21,
          'probability': 0.9994608274841141,
          'start': 5,
          'text': 'Gearbox Software'}]}]
pprint(my_ie("近日,量子計算專家、ACM計算獎得主Scott Aaronson透過部落格宣佈,將於本週離開得克薩斯大學奧斯汀分校(UT Austin)一年,並加盟人工智慧研究公司OpenAI。"))
[{'人名': [{'end': 32,
          'probability': 0.9990193078443497,
          'start': 18,
          'text': 'Scott Aaronson'}],
  '時間': [{'end': 2,
          'probability': 0.9998481327061199,
          'start': 0,
          'text': '近日'},
         {'end': 43,
          'probability': 0.9995744486620453,
          'start': 41,
          'text': '本週'}],
  '組織': [{'end': 66,
          'probability': 0.9900117066000078,
          'start': 57,
          'text': 'UT Austin'},
         {'end': 87,
          'probability': 0.9993381402363184,
          'start': 81,
          'text': 'OpenAI'},
         {'end': 56,
          'probability': 0.9968616126324434,
          'start': 45,
          'text': '得克薩斯大學奧斯汀分校'},
         {'end': 13,
          'probability': 0.8434502340745098,
          'start': 10,
          'text': 'ACM'}]}]

基於 50 條標註資料進行模型微調後,效果有所提升。

4.智慧標註:Machine Learning Backend 編寫教學

在基於UIE的命名實體識別的基礎上,進一步透過整合 Label Studio 的 Machine Learning Backend 實現互動式預註釋和模型訓練等功能。

環境安裝:

pip install label_studio_ml

pip uninstall attr

完整的 Machine Learning Backend 見 my_ml_backend.py 檔案。更多有關自定義機器學習後端編寫的內容可參考 Write your own ML backend

簡單來講,my_ml_backend.py 內主要包含一個繼承自 LabelStudioMLBase 的類,其內容可以分為以下三個主要部分:

  • init 方法,包含模型的載入和基本配置的初始化
  • predict 方法,用於為標註資料生成新的預測結果,其關鍵引數 tasks 就是 label studio 傳遞的原始資料
  • fit 方法,用於模型的訓練,當點選頁面上的 Train 按鈕時,會呼叫此方法(具體的位置在下文會提到),其關鍵引數 annotations 就是 label studio 傳遞的已經標註了的資料

4.1 init 初始化方法

  • 匯入依賴庫
import numpy as np
import os  
import json
from paddlenlp import Taskflow
from label_studio_ml.model import LabelStudioMLBase
  • 宣告並初始化一個類

首先建立一個類宣告,透過繼承 LabelStudioMLBase 建立一個與 Label Studio 相容的 ML 後端伺服器。

class MyModel(LabelStudioMLBase):

然後,在 __init__ 方法中定義和初始化需要的變數。LabelStudioMLBase 類提供了以下

  • self.label_config: 原始標籤配置。
  • self.parsed_label_config: 為專案提供結構化的 Label Studio 標籤配置。
  • self.train_output: 包含之前模型訓練執行的結果,與訓練呼叫部分中定義的 fit() 方法的輸出相同。

如本教程的例子中,標籤配置為:

<View>
  <Labels name="label" toName="text">
  <Label value="地名" background="#FFA39E"/>
  <Label value="人名" background="#D4380D"/>
  <Label value="組織" background="#FFC069"/>
  <Label value="時間" background="#AD8B00"/>
  <Label value="產品" background="#D3F261"/>
  <Label value="價格" background="#389E0D"/>
  <Label value="天氣" background="#5CDBD3"/>
  </Labels>
  <Text name="text" value="$text"/>
</View>

相對應的 parsed_label_config 如下所示:

{
	'label': {
		'type': 'Labels',
		'to_name': ['text'],
		'inputs': [{
			'type': 'Text',
			'value': 'text'
		}],
		'labels': ['地名', '人名', '組織', '時間', '產品', '價格', '天氣'],
		'labels_attrs': {
			'地名': {
				'value': '地名',
				'background': '#FFA39E'
			},
			'人名': {
				'value': '人名',
				'background': '#D4380D'
			},
			'組織': {
				'value': '組織',
				'background': '#FFC069'
			},
			'時間': {
				'value': '時間',
				'background': '#AD8B00'
			},
			'產品': {
				'value': '產品',
				'background': '#D3F261'
			},
			'價格': {
				'value': '價格',
				'background': '#389E0D'
			},
			'天氣': {
				'value': '天氣',
				'background': '#5CDBD3'
			}
		}
	}
}

根據需要從 self.parsed_label_config 變數中提取需要的資訊,並透過 PaddleNLP 的 Taskflow 載入用於預標註的模型。

def __init__(self, **kwargs):
    # don't forget to initialize base class...
    super(MyModel, self).__init__(**kwargs)

    # print("parsed_label_config:", self.parsed_label_config)
    self.from_name, self.info = list(self.parsed_label_config.items())[0]

    assert self.info['type'] == 'Labels'
    assert self.info['inputs'][0]['type'] == 'Text'

    self.to_name = self.info['to_name'][0]
    self.value = self.info['inputs'][0]['value']
    self.labels = list(self.info['labels'])
    self.model = Taskflow("information_extraction", schema=self.labels, task_path= './checkpoint/model_best')

4.2 使用ML Backend predict 預測方法(自動標註)

編寫程式碼覆蓋 predict(tasks, **kwargs) 方法。predict() 方法接受 [JSON 格式的 Label Studio 任務]返回預測。此外,還可以包含和自定義可用於主動學習迴圈的預測分數。

tasks 引數包含了有關要進行預註釋的任務的詳細資訊。具體的 task 格式如下所示:

{
	'id': 16,
	'data': {
		'text': '新華社都柏林6月28日電(記者張琪)第二屆“漢語橋”世界小學生中文秀愛爾蘭賽區比賽結果日前揭曉,來自都柏林市的小學五年級學生埃拉·戈爾曼獲得一等獎。'
	},
	'meta': {},
	'created_at': '2022-07-12T07:05:06.793411Z',
	'updated_at': '2022-07-12T07:05:06.793424Z',
	'is_labeled': False,
	'overlap': 1,
	'inner_id': 6,
	'total_annotations': 0,
	'cancelled_annotations': 0,
	'total_predictions': 0,
	'project': 2,
	'updated_by': None,
	'file_upload': 2,
	'annotations': [],
	'predictions': []
}

透過 Taskflow 進行預測需要從 ['data']['text'] 欄位提取出原始文字,返回的 uie 預測結果格式如下所示:

{
	'地名': [{
		'text': '愛爾蘭',
		'start': 34,
		'end': 37,
		'probability': 0.9999107139090313
	}, {
		'text': '都柏林市',
		'start': 50,
		'end': 54,
		'probability': 0.9997840536235998
	}, {
		'text': '都柏林',
		'start': 3,
		'end': 6,
		'probability': 0.9999684097596173
	}],
	'人名': [{
		'text': '埃拉·戈爾曼',
		'start': 62,
		'end': 68,
		'probability': 0.9999879598978225
	}, {
		'text': '張琪',
		'start': 15,
		'end': 17,
		'probability': 0.9999905824882092
	}],
	'組織': [{
		'text': '新華社',
		'start': 0,
		'end': 3,
		'probability': 0.999975681447097
	}],
	'時間': [{
		'text': '6月28日',
		'start': 6,
		'end': 11,
		'probability': 0.9997071721989244
	}, {
		'text': '日前',
		'start': 43,
		'end': 45,
		'probability': 0.9999804497706464
	}]
}

從 uie 預測結果中提取相應的欄位,構成 Label Studio 接受的預註釋格式。命名實體識別任務的具體預註釋示例可參考 [Import span pre-annotations for text]

更多其他型別任務的具體預註釋示例可參考 [Specific examples for pre-annotations]

def predict(self, tasks, **kwargs):
    from_name = self.from_name
    to_name = self.to_name
    model = self.model

    predictions = []
    for task in tasks:
        # print("predict task:", task)
        text = task['data'][self.value]
        uie = model(text)[0]
        # print("uie:", uie)

        result = []
        scores = []
        for key in uie:
            for item in uie[key]:
                result.append({
                    'from_name': from_name,
                    'to_name': to_name,
                    'type': 'labels',
                    'value': {
                        'start': item['start'],
                        'end': item['end'],
                        'score': item['probability'],
                        'text': item['text'],
                        'labels': [key]
                    }
                })
                scores.append(item['probability'])
        result = sorted(result, key=lambda k: k["value"]["start"])
        mean_score = np.mean(scores) if len(scores) > 0 else 0

        predictions.append({
            'result': result,
            # optionally you can include prediction scores that you can use to sort the tasks and do active learning
            'score': float(mean_score),
            'model_version': 'uie-ner'
        })
    return predictions

4.3 使用 ML Backend fit 訓練方法(根據標註好的資料再次最佳化訓練模型)

基於新註釋更新模型。

編寫程式碼覆蓋 fit() 方法。fit() 方法接受 [JSON 格式的 Label Studio 註釋]並返回任意一個可以儲存模型相關資訊的 JSON 字典。

def fit(self, annotations, workdir=None, **kwargs):
    """ This is where training happens: train your model given list of annotations, 
        then returns dict with created links and resources
    """
    # print("annotations:", annotations)
    dataset = convert(annotations)


    with open("./doccano_ext.jsonl", "w", encoding="utf-8") as outfile:
        for item in dataset:
            outline = json.dumps(item, ensure_ascii=False)
            outfile.write(outline + "\n")

    os.system('python doccano.py \
        --doccano_file ./doccano_ext.jsonl \
        --task_type "ext" \
        --save_dir ./data \
        --splits 0.8 0.2 0')

    os.system('python finetune.py \
        --train_path "./data/train.txt" \
        --dev_path "./data/dev.txt" \
        --save_dir "./checkpoint" \
        --learning_rate 1e-5 \
        --batch_size 4 \
        --max_seq_len 512 \
        --num_epochs 50 \
        --model "uie-base" \
        --init_from_ckpt "./checkpoint/model_best/model_state.pdparams" \
        --seed 1000 \
        --logging_steps 10 \
        --valid_steps 100 \
        --device "gpu"')

    return {
        'path': workdir
    }

6.總結

  • 人工標註的缺點主要有以下幾點:

    • 產能低:人工標註需要大量的人力物力投入,且標註速度慢,產能低,無法滿足大規模標註的需求。
    • 受限條件多:人工標註受到人力、物力、時間等條件的限制,無法適應所有的標註場景,尤其是一些複雜的標註任務。
    • 易受主觀因素影響:人工標註受到人為因素的影響,如標註人員的專業素養、標註態度、主觀判斷等,易受到人為誤差的干擾,導致標註結果不準確。
    • 難以滿足個性化需求:人工標註無法滿足所有標註場景和個性化需求,無法精確地標註出所有的關鍵資訊,需要使用者自行選擇和判斷。
  • 相比之下,智慧標註的優勢主要包括:

    • 效率更高:智慧標註可以自動化地進行標註,能夠快速地生成標註結果,減少了人工標註所需的時間和精力,提高了標註效率。
    • 精度更高:智慧標註採用了先進的人工智慧技術,能夠對影像進行深度學習和處理,能夠生成更加準確和精細的標註結果,特別是對於一些細節和特徵的標註,手動標註往往存在誤差較大的問題。
    • 自動糾錯:智慧標註可以自動檢測標註結果中的錯誤,並進行自動修正,能夠有效地避免標註錯誤帶來的影響,提高了標註的準確性。
    • 靈活性更強:智慧標註可以根據不同的應用場景和需求,生成不同型別的標註結果,能夠滿足使用者的多樣化需求,提高了標註的適用性。

總之,智慧標註相對於人工標註有著更高的效率、更高的精度、更強的靈活性和更好的適用性,可以更好地滿足使用者的需求。

6.1 碼源

智慧標註:基於Labelstudio的UIE半監督深度學習的智慧標註方案碼源

更多細節參考:人工智慧知識圖譜之資訊抽取:基於Labelstudio的UIE半監督深度學習的智慧標註方案(雲端版),提效。

相關文章