訓練之前,要搭建環境,參考:

水中的魚:多輪對話框架Rasa代碼解讀--環境搭建?

zhuanlan.zhihu.com
圖標

一.訓練入口解讀

訓練過程的命令為:

python __main__.py  train --domain domain.yml --data data --config config.yml --out models

真心為rasa的代碼點贊,因為它使用Python3新特性類型註解, 提高代碼可讀性.

我們知道 Python 是一種動態語言,變數以及函數的參數是不區分類型。.

Python解釋器會在運行的時候動態判斷變數和參數的類型,這樣的好處是編寫代碼速度很快,很靈活,但是壞處也很明顯,不好維護,可能代碼寫過一段時間重新看就很難理解了,因為那些變數、參數、函數返回值的類型,全都給忘記了。而且當你在讀別人的代碼的時候,也無法一眼看出變數或者參數的類型,經常要自己推敲,這樣給學習帶來了很大的障礙。

在59-66行,主要是argparse模塊構造命令行的參數。argparse模塊的用法,這裡不詳述。重點在68-70行。

cmdline_arguments.func(cmdline_arguments),這行代碼到底執行的是那個函數呢?

這裡直接給出設置的地方:create_argument_parser()--train.add_subparser--train_parser.set_defaults(func=train),這樣調用的就是train。

也就是rasa_chatbot_cn/venv/lib/python3.5/site-packages/rasa/train.py文件中的train函數。

train_async函數是訓練的真正入口,先看看參數:

domain=domain.yml

config=config.yml

training_files= [data]

output_path=models

force_training=False

fixed_model_name=None

kwargs=<class dict>: {augmentation_factor: 50, dump_stories: False, debug_plots: False}

在調用_do_training,入參和上述不同的地方在於domain不再是一個字元串,而是一個Domain對象,主要是把domain.yml文件中的內容變成字典from_dict。

然後分別用_train_core_with_validated_data訓練core,用_train_nlu_with_validated_data訓練nlu.

之前講過,Core 包含對話管理,也就是對話上下文的管理,語句生成。nlu包括包含意圖識別和實體提取。按照對話的流程

我們先看訓練NLU的部分。

二. 訓練NLU的部分

入口是rasa.nlu.train。處理邏輯:

載入配置文件---構造訓練組件的對象---載入訓練數據---每個組件依次對訓練數據進行處理和訓練---模型的持久化

1. 載入配置文件

調用config.load,將配置文件config.yml的文件內容讀出來,並保存到RasaNLUModelConfig對象中,看下這個對象的詳細信息:

可以看到,和配置文件的內容是基本一致的。

2. 構造訓練組件的對象

在Trainer類的構造函數中,主要是構造pipeline,也就是說根據配置文件config.yml中的pipeline中的每個類,依次調用類的構造函數。那麼配置文件中的名稱和類的名稱的對應關係在registry.py中的component_classes變數中。

3. 載入訓練數據

load_data會讀取訓練數據,都保存在TrainingData對象中,

training_examples,對應數據中common_examples

entity_synonyms,對應數據中entity_synonyms,目前樣例為空。

regex_features,對應數據中regex_features,目前樣例為空

lookup_tables,目前樣例為空

在看看數據結構的定義,training_examples是一個列表,每個元素是一個Message對象。

原始訓練數據中的每條:

分別對應Message對象中的text ,data["intent"],data["entities"] ,data是一個字典。

4. 每個組件依次對訓練數據進行處理和訓練

trainer.train,依次調用pipeline每個組件的預處理函數和訓練函數,這裡需要理解過程中訓練的結果保存到哪裡?

這裡採用一個字典context,在訓練開始前,每個組件都通過provide_context將需要提供的上下文信息更新到context中,大部分組件不需要提供預置信息。比如MITIE , spacy需要提供框架的環境變數,比如詞向量。

組件JiebaTokenizer的訓練:將training_examples中的每個Message對象中的text 進行分詞,並將分詞結果保存到data["tokens"]中。

組件CRFEntityExtractor的訓練,訓練過程涉及需要詳細講解的演算法,準備用一個單獨的一篇來講解。這裡只說下輸出:保存到data["entities"]中。

組件JiebaPsegExtractor,沒有定義訓練過程,無需訓練。

組件BertVectorsFeaturizer,準備用一個單獨的一篇來講解

組件EmbeddingBertIntentClassifier,準備用一個單獨的一篇來講解

5. 模型的持久化

將模型的輸出打包成一個zip文件,fingerprint的作用是,保存模型和訓練數據的對應關係。當訓練數據沒有變化時,fingerprint也是一致的,就不用重新訓練。


推薦閱讀:
相關文章