BERT 全名為 Bidirectional Encoder Representations from Transformers,是 Google 以無監督的方式利用大量無標註文本「煉成」的語言代表模型,其架構為 Transformer 中的 Encoder。
Goole的源碼在這 /bert,而我們會使用句子分類的部分 Sentence (and sentence-pair) classification tasks,但使用之前別忘了先去準備預訓練模型,而Google已經將預訓練的模型載點都公開了(Pre-trained models),下載即可。而既然我們要做中文的意圖分類,當然要下載中文的模型(BERT-Base, Chinese)囉
。
我也附上個人實作的代碼:Github
那我們來看看怎麼啟動這個模型吧
首先我有兩個資料夾
- Chunshan-Theta/bert-classify-chinese
|- model_train
|- pre-process-classify
從命名就可以看出來,一個是用來準備資料的,一個是訓練模型的。
準備資料
那先從資料準備開始 我們進入pre-process-classify
資料夾,裡面有兩個資料夾與一個python檔案。
簡單來說,這就是一個調整訓練資料格式的腳本。我們原始資料放在to_csv
資料夾裡,格式如下:(格式:<標籤> \t <內容>)
無法提供完整訓練集 盡請見諒
詢價 這個茶壺多少錢?
其他 你們營業時間是幾點
生氣 钱已经充到你们平台了,没金币玩屎呀
詢價 買這整組多少錢
詢價 買兩組的話多少
生氣 你再開玩笑嗎?
生氣 為什麼沒有打折?當初不是說只要800
生氣 你們都是骗子嗎
其他 妹仔多大啦
然後執行count.py
後會在output_for_model
資料夾中產生兩個檔案
- combined_chinese.csv: 整合所有資料來源為一個檔案。
- for_train.csv:將標籤轉換成編號形式。(請自己切測試集與訓練集,可參考此工具
sklearn.model_selection.train_test_split
)
基本上這樣就準備完資料了,接著我們看訓練。
訓練前準備
- 將預模型放在
base_model
使用模型的下載來源-> 下載
./base_model |- chinese-wwm_L-12_H-768_A-12 |- bert_config.json |- bert_model.ckpt.data-00000-of-00001 |- bert_model.ckpt.index |- bert_model.ckpt.meta |- vocab.txt
- 將準備好的資料放在
data
資料夾中./data |- for_dev_and_test.csv |- for_train.csv
- 調整腳本
vim run.sh
要調整的部分有:
- num_labels 標籤數量
- label_index 標籤編號與對應中文標籤
export BERT_BASE_DIR=./base_model/chinese-wwm_L-12_H-768_A-12 export GLUE_DIR=./data export TRAINED_CLASSIFIER=./output python3 run_mobile.py \ --task_name=customized \ --do_train=true \ --do_eval=true \ --do_predict=true \ --data_dir=$GLUE_DIR \ --vocab_file=$BERT_BASE_DIR/vocab.txt \ --bert_config_file=$BERT_BASE_DIR/bert_config.json \ --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \ --max_seq_length=32 \ --train_batch_size=16 \ --learning_rate=5e-5 \ --num_train_epochs=3 \ --output_dir=$TRAINED_CLASSIFIER \ --num_labels=4 \ --label_index=\{\"0\":\"問候\",\"1\":\"詢價\",\"2\":\"其他\",\"3\":\"生氣\"\}
執行訓練
sh run.sh
- 部分過程輸出:
I0817 01:06:30.408478 140735690490752 estimator.py:1147] Done calling model_fn. I0817 01:06:30.410821 140735690490752 basic_session_run_hooks.py:541] Create CheckpointSaverHook. I0817 01:06:35.448922 140735690490752 monitored_session.py:240] Graph was finalized. I0817 01:06:42.216624 140735690490752 session_manager.py:500] Running local_init_op. I0817 01:06:42.493341 140735690490752 session_manager.py:502] Done running local_init_op. I0817 01:06:54.641889 140735690490752 basic_session_run_hooks.py:606] Saving checkpoints for 0 into ./output/model.ckpt. I0817 01:07:29.678798 140735690490752 tpu_estimator.py:2159] global_step/sec: 0.0689326 I0817 01:07:29.679122 140735690490752 tpu_estimator.py:2160] examples/sec: 1.10292 W0817 01:07:29.679260 140735690490752 basic_session_run_hooks.py:724] It seems that global step (tf.train.get_global_step) has not been increased. Current value (could be stable): 1 vs previous value: 1. You could increase the global step by passing tf.train.get_global_step() to Optimizer.apply_gradients or Optimizer.minimize. I0817 01:07:38.968907 140735690490752 tpu_estimator.py:2159] global_step/sec: 0.107641 I0817 01:07:38.969228 140735690490752 tpu_estimator.py:2160] examples/sec: 1.72226 I0817 01:07:48.229242 140735690490752 tpu_estimator.py:2159] global_step/sec: 0.107988 I0817 01:07:48.229606 140735690490752 tpu_estimator.py:2160] examples/sec: 1.72781
- 結果觀察
- ./output/eval_results.txt
# 範例格式. eval_accuracy = 0.8792814 eval_f1 = 0.8148148
- ./output/test_samples_results.csv
# 範例格式 o,答案: 1,詢價,這個茶壺多少錢?,預測: 1,詢價,"0.29443625 0.31483293 0.24977936 0.14095142