前言
之前的教程中,有同學要求將講解的代碼開源,以方便使用。本文將會用最精簡的框架去介紹來自頂級公司的pytorch模型的整個框架及流程,並整理開源爲通用的模型框架,供研究使用。(如果你還沒有閱讀過之前的基礎知識,建議通過傳送門大概瞭解一下。)
本文的模型框架主要來源於谷歌的BERT開源代碼、大名鼎鼎的Huggingface、AllenNlp以及Albert中文版等,通讀完這些代碼,你會發現有很多相似的部分,本文主要依照它們的設計思想及具體代碼,構建出一個常見的、完整的pytorch訓練流程,你只需要完成模型的設計、語料的準備、以及主程序中相應代碼的修改,就可以完成一個非常成熟的深度學習過程,包括完整的日誌記錄系統、評估系統、預處理系統等。
本文的模型框架經過親自實踐證明是有用的,並會在未來進行改進和擴充。目前主要針對與自然語言處理(NLP)基於預訓練模型的相關分類實驗。我們接下來一一講解其框架的各個組成部分,部分需要補課的同學可以傳送至之前的文章:《轉戰pytorch(1)——清點裝備》,《轉戰pytorch(2)——“簡單”訓練》,《轉戰pytorch(3)——跟上腳步(以Albert爲例)》,《轉戰pytorch——實現自己的任務(4)》。
整體框架
整個模型框架如上圖所示,主要包含analysis
,dataset
,metrics
,model
,module
,outputs
,prev_trained_model
,processors
幾個部分,由於callback
和tools
不是我們實驗的主體部分,也沒什麼變化,因此我們這裏忽略講解,詳情可以看一看代碼。下面以一個關係識別的任務爲背景,對於框架的每個部分進行一個詳細的介紹。
語料準備
語料主要以任務名爲文件夾,放置在dataset中,分別以train.tsv
,dev.tsv
,test.tsv
爲例子完成初始數據的準備。如果你的原始數據不是這樣的,建議增加一個create_tsv.py
文件完成語料格式的轉換。
由於語料的不同以及版權問題,我們在上傳的資源裏移除了真實的語料文件,需要自己準備。
處理器
當處理數據送到模型前的操作,都在processors
文件夾裏,這個文件夾主要有兩個部分,一個是與任務相關的glue
,這裏規定了不同任務的處理器的具體流程、標籤的數目以及輸出的類型;另一個是工具類utils
,主要規定了輸入的樣例的類和特徵的類。
評估指標
對於實驗結果的評估,我們主要放置在metrics
文件夾中,其中有兩個文件,一個用於真正的計算方法的實現(custom_metrics.py
),另一個則是將任務預評估方法對應起來(glue_custom_metrics.py
).
模型構建
我們構建的模型主要在model
文件夾中,對於現在常見的預訓練模型,我們主要構建config
、modeling
、tokenization
三個部分,你也可以根據自己的模型構建屬於自己的文件。
另一個與模型相關的文件夾爲module
,這個文件夾主要放模型的子模塊,可以將常用的模塊先封裝至module
中,然後再在model
中構建自己的模型中調用,增強模型的複用性。
如果你使用的是huggingface的一些內置模型的話,這裏可以是空的。
結果的輸出
結果一般輸出到outputs
中,以任務爲文件夾名分開存放。
預訓練模型
預訓練模型都存放於prev_trained_model
文件夾中。很多與訓練模型都可以在網上找到。這裏提供albert中文版和bert中文版的來源,以及Huggingface的model cards。
實驗主過程
實驗主過程就如之前教程中講的那樣,是獨立的一個Py文件,這裏爲run_classfication_relation.py
,大致分爲以下4步:
- 前期準備(參數、數據、模型等初始化)
- 訓練過程
- 評估過程
- 測試過程
以上四個內容,在本文的代碼中,都集中在main
函數中。在其中,我們只對於config,model和tokenizer部分進行了bert和albert的替換,我們也可以替換成自己的模型。
如果你只是專注一個簡單的分類任務,或者是迴歸任務,那麼這個過程就完全的夠用了,但如果你是做parsing或者其他需要模型作爲一個決策者參與到整個系統中時,則需要額外構建一個系統來進行實驗。
分析過程
對於實驗結果,我們需要有針對性的進行分析,因此,在這裏強烈建議將實驗結果完整的保存下來,這樣以便於我們回溯的時候可以更加方便地進行分析。所有地分析代碼都在analysis
文件夾中。
運行腳本
運行的腳本我們可以存放於一個.sh文件中,一方面,我們可以直接執行,另一方面,我們也可以方便的修改。就算最笨的辦法也相當於一個粘貼板,需要的時候複製裏面的代碼粘貼到命令行中即可。
# bert model
CUDA_VISIBLE_DEVICES=0 python3 run_classifier_relation.py \
--model_type=bert \
--model_name_or_path=./prev_trained_model/bert-base-chinese/pytorch_model.bin \
--vocab_file=./prev_trained_model/bert-base-chinese/bert-base-chinese-vocab.txt \
--config_name=./prev_trained_model/bert-base-chinese/bert_config.json \
--task_name=relation \
--do_train \
--do_eval \
--do_predict \
--predict_all_checkpoints \
--do_lower_case \
--data_dir=./dataset/relation/ \
--max_seq_length=512 \
--per_gpu_train_batch_size=2 \
--per_gpu_eval_batch_size=2 \
--learning_rate=1e-5 \
--num_train_epochs=5.0 \
--logging_steps=1192 \
--save_steps=1192 \
--output_dir=./outputs/relation_output/ \
--overwrite_output_dir \
--seed=42
額外收穫(Albert 和BERT的差異)
在親自實驗的任務(篇章關係識別)中,我們發現,正如論文中所講的那樣,儘管Albert和BERT在同一任務、同一語料下,同等參數設置下,性能大致相當(BERT 58.58F1,Albert 57.5F1),但是BERT能夠識別出更多的類型標籤(BERT 識別 6-7個類別,但是Albert只能識別最多的3個類別,總計15個類型)。對於預訓練模型評測的8個任務,其標籤的類型數都是2-3個,兩者的直觀性能沒有太多的差距,但是顯然更大的BERT模型能夠捕獲到更加多樣的特徵表示。
小結
通過一個關係分類的實例,我們對於這個最簡易但非常完整的框架有了進一步的認識,它具有很多優點,例如訓練過程全程可控、操作日誌全記錄、以及無需配置,容易擴展等。在將來,我們將會對此進行一些實用的功能擴展。