(五)RASA NLU特征生成器
作者簡(jiǎn)介
原文:https://zhuanlan.zhihu.com/p/332420794
轉(zhuǎn)載者:楊夕
面筋地址:https://github.com/km1994/NLP-Interview-Notes
個(gè)人筆記:https://github.com/km1994/nlp_paper_study

總體上RASA Featurizer分為兩類:稀疏向量如One-hot和稠密向量如Bert。稀疏Featurizer是返回具有很多缺失值(例如零)的特征向量,為了節(jié)省空間,稀疏特征僅存儲(chǔ)非零值及其在向量中的位置。
所有Featurizer都可以返回兩種不同的特征:序列特征和句子特征。序列特征是(number-of-tokens x feature-dimension)維度的矩陣,矩陣包含了句子中每個(gè)Token的特征向量,我們用這個(gè)特征去訓(xùn)練序列模型,如實(shí)體識(shí)別。句子特征由(1 x feature-dimension)大小矩陣表示,它包含完整對(duì)話的特征向量,可以用于意圖分類等。句子特征可以在任何詞袋模型中使用。具體在系統(tǒng)中使用哪種類型的特征值由使用的分類器決定。
RASA支持的特征生成器:
MitieFeaturizer
輸出為稠密向量,可以被其他意圖分類器使用。需要在pipeline中引入MitieNLP語(yǔ)言模型。但是有意思的是,該特征器并沒有被MitieIntentClassifier使用,因?yàn)镸itieIntentClassifier里面實(shí)現(xiàn)了所有分詞,特征提取功能。
MitieFeaturizer是對(duì)每個(gè)Token輸出一個(gè)feature-dimension維度的向量,那么生成句子向量的做法是通過pooling技術(shù),這里可以選擇max pooling和mean pooling,這個(gè)參數(shù)可以在配置文件中指定。最終會(huì)生成一個(gè)1 x feature-dimension的句子向量。max pooling算法就是取每個(gè)token中相同維度,最大的值作為句子向量的這個(gè)維度的值,那么mean pooling就好理解了,句子向量是每個(gè)token的均值。
SpacyFeaturizer
同Mitie類似,Spacy也輸出稠密向量,可以被其他意圖分類器使用。SpacyFeaturizer需要在pipeline中引入SpacyNLP語(yǔ)言模型。
因?yàn)镾pacyFeaturizer也是對(duì)每個(gè)Token輸出一個(gè)feature-dimension維度的向量,那么生成句子向量的做法是通過pooling技術(shù),這里可以選擇max pooling和mean pooling,可以在配置文件中指定。最終會(huì)生成一個(gè)1 x feature-dimension的句子向量。
配置方式如下:
pipeline:
- name:"SpacyNLP"
model:"en_core_web_md"
- name: "SpacyTokenizer"
"intent_tokenization_flag": False
"intent_split_symbol": "_"
"token_pattern": None
- name: "SpacyFeaturizer"
"pooling": "mean"ConveRTFeaturizer
使用ConveRT模型生成句子的特征表示。輸出為稠密變量。因?yàn)镃onveRT模型只有英文模型,因此中文對(duì)話機(jī)器人不能使用ConveRTFeaturizer,除非你想自己訓(xùn)練一個(gè)ConveRT模型。使用該Featurizer的時(shí)候,需要使用model_url參數(shù)配置模型文件的路徑,否則訓(xùn)練的時(shí)候會(huì)報(bào)錯(cuò)。ConveRTFeaturizer已經(jīng)實(shí)現(xiàn)了ConveRTTokenizer的功能,所以Pipeline可以配置任意的Tokenizer。從代碼里面看ConveRTTokenizer,LanguageModelTokenizer都是繼承WhitespaceTokenizer,并沒有做特殊處理,而用WhitespaceTokenizer在中文的時(shí)候,會(huì)提示不支持中文錯(cuò)誤,所以可選的分詞器并不多,只有MitieTokenizer和SpcayTokenizer。
簡(jiǎn)單介紹下ConveRT模型,下面是論文連接
LanguageModelFeaturizer
這就是著名的BERT模型了,輸入為用戶消息,響應(yīng)消息等,輸出為稠密變量。使用LanguageModelFeaturizer,首先要根據(jù)機(jī)器人的是中文的還是英文的,選擇預(yù)訓(xùn)練模型。下表是目前支持的預(yù)訓(xùn)練模型。因?yàn)長(zhǎng)anguageModelFeaturizer里面已經(jīng)實(shí)現(xiàn)了分詞功能,因?yàn)閜ipeline里面可以配置任意Tokenizer。但注意要是稠密向量,所以不能配置WhitespaceTokenizer和JiebaTokenizer。而LanguageModelTokenizer又不支持中文,所以只有MitieTokenizer和SpcayTokenizer。這里配置什么分詞器并不影響最終結(jié)果。
注:這里可以從Tokenizer類自定義個(gè)空分詞器NullTokenizer,里面什么都不做,然后LanguageModelFeaturizer這類不需要分詞器的,pipeline里面都配置NullTokenizer。其實(shí)LanguageModelTokenizer和ConveRTTokenizer就什么都沒有做,只是繼承與WhitespaceTokenizer,而WhitespaceTokenizer有句話not_supported_language_list = ["zh", "ja", "th"],所以LanguageModelFeaturizer就不支持中文了。
LanguageModelFeaturizer支持的預(yù)訓(xùn)練模型有:

其中預(yù)訓(xùn)練模型的名稱使用model_weights參數(shù)配置,對(duì)于BERT模型,model_weights可選參數(shù)有:
bert-base-uncased
bert-large-uncased
bert-base-cased
bert-large-cased
bert-base-multilingual-uncased
bert-base-multilingual-cased
bert-base-chinese
bert-base-german-cased
bert-large-uncased-whole-word-masking
bert-large-cased-whole-word-masking
bert-large-uncased-whole-word-masking-finetuned-squad
bert-large-cased-whole-word-masking-finetuned-squad
bert-base-cased-finetuned-mrpc
bert-base-german-dbmdz-cased
bert-base-german-dbmdz-uncased
TurkuNLP/bert-base-finnish-cased-v1
TurkuNLP/bert-base-finnish-uncased-v1
wietsedv/bert-base-dutch-casedroberta模型的model_weights參數(shù)可以選
roberta-base
roberta-large
roberta-large-mnli
distilroberta-base
roberta-base-openai-detector
roberta-large-openai-detectorxlnet模型的model_weights參數(shù)可選xlnet-base-cased, xlnet-large-cased
比如,我訓(xùn)練中文機(jī)器人,pipeline的配置:
# Configuration for Rasa NLU.
# https://rasa.com/docs/rasa/nlu/components/
language: zh
pipeline:
- name: JiebaTokenizer
- name: RegexFeaturizer
- name: LexicalSyntacticFeaturizer
- name: LanguageModelFeaturizer
model_name: bert
model_weights: bert-base-chinese
- name: DIETClassifier
epochs: 100
- name: EntitySynonymMapper
- name: ResponseSelector
epochs: 100
- name: FallbackClassifier
threshold: 0.3
ambiguity_threshold: 0.1
policies:
- name: MemoizationPolicy
- name: TEDPolicy
max_history: 5
epochs: 100
- name: RulePolicyPolicies# Configuration for Rasa NLU.
RegexFeaturizer
使用正則表達(dá)式創(chuàng)建一個(gè)消息表示,注意輸入只能是用戶消息,這個(gè)和其他幾個(gè)Featurizer不同,輸出的內(nèi)容是一個(gè)稀疏向量。
在訓(xùn)練階段,根據(jù)配置會(huì)生成一個(gè)符合輸入句子的正則表達(dá)式列表,當(dāng)運(yùn)行階段,針對(duì)用戶消息,會(huì)對(duì)每一個(gè)正則表達(dá)式都匹配一次,如果匹配這個(gè)正則表達(dá)式就會(huì)創(chuàng)建一個(gè)特征,然后所有這些特征形成一個(gè)列表,輸出到分類器和提取器里面。那么分類器和實(shí)體提取器會(huì)根據(jù)這個(gè)特征指示知道已經(jīng)找到分類標(biāo)簽或者實(shí)體了,然后會(huì)直接使用分類標(biāo)簽和實(shí)體。
注意,目前只有CRFEntityExtractor和DIETClassifier這兩個(gè)才支持RegexFeaturizer。
RegexFeaturizer的配置在nlu的pipeline里面配置,具體正則表達(dá)式的配置在訓(xùn)練數(shù)據(jù)里面配置。
##Regex的配置方式
nlu:
- regex: account_number
examples: |
- \d{10,12}CountVectorsFeaturizer
把用戶消息,意圖,響應(yīng)消息創(chuàng)建一個(gè)詞袋模型表示。輸出也是稀疏矩陣。
CountVectorizer生成算法是使用sklearn's CountVectorizer。配置參數(shù)具體可以參考sklearn's CountVectorizer的文檔。下面將幾個(gè)關(guān)鍵參數(shù)做個(gè)解釋。
analyzer,min-ngram,max-ngram:analyzer可選值為word,char,char_wb。這個(gè)參數(shù)指定是用word的n-grams還是char的n-grams。例如,對(duì)于“中國(guó)北京“這個(gè)詞,如果analyzer是word,那特征有“中國(guó)”,“北京”;如果analyzer配置為char,特征就有“中”,“國(guó)”,“北”,“京”四個(gè)token。如果min-ngram為1,max-ngram為2,依舊對(duì)于中國(guó)北京“這個(gè)詞,如果analyzer是word,特征有“中國(guó)”,“北京”,“中國(guó)北京”;如果analyzer配置問char,特征就有“中”,“國(guó)”,“北”,“京”,“中國(guó)”,“國(guó)北”,“北京”。char_wb和char區(qū)別在于邊界處理上,當(dāng)analyzer為char_wb,單詞邊緣的n-gram用空格填充,例如,當(dāng)min-ngram為1,max-ngram為2時(shí),“中國(guó)北京”具有的特征有“中”,“國(guó)”,“北”,“京”,“中國(guó)”,“國(guó)北”,“北京”,“京 ”。
use_lemma:可選值為True和False,主要對(duì)于英文語(yǔ)言提取特征,因?yàn)橛⑽挠袝r(shí)態(tài)和語(yǔ)態(tài)問題,同一個(gè)單詞有不同的表現(xiàn)方式,因此當(dāng)use_lemma為True時(shí)候,use和used是一個(gè)特征。目前只有SpacyTokenizer支持,可以通過設(shè)置use_lemma為False來(lái)關(guān)閉。
需要注意的是,所有的純數(shù)字都會(huì)編碼為同一個(gè)特征向量。
OOV_token,OOV_words:由于訓(xùn)練數(shù)據(jù)是有限的詞匯表,因此不能保證在預(yù)測(cè)過程中算法遇到所有詞都在訓(xùn)練數(shù)據(jù)中心出現(xiàn),為了教算法如何處理這些集外詞,這里提供了兩個(gè)配置參數(shù)OOV_token和OOV_words。
OOV_token是一個(gè)字符串,例如"__oov__",在預(yù)測(cè)期間,所有未知單詞都將被視為OOV_token對(duì)應(yīng)的那個(gè)單詞。我們可以在訓(xùn)練數(shù)據(jù)中編寫一個(gè)intent,例如叫intent _out_of_scope,包含一定數(shù)量的OOV_token和其他單詞,這樣在預(yù)測(cè)期間,算法將將含有未知單詞的消息歸類為這個(gè)意圖。
OOV_words是一個(gè)單詞列表,所有訓(xùn)練數(shù)據(jù)在此列表中的詞,都被認(rèn)為是OOV_token。這個(gè)東西有什么用途呢?假如,有一個(gè)詞,不是很關(guān)鍵,我們想吧他設(shè)為集外詞,那么我們要找訓(xùn)練數(shù)據(jù),一條一條的找,把這個(gè)詞改成_oov_,那么,有了OOV_words這個(gè)工具,我們只需要吧這個(gè)詞添加到OOV_words配置里面就可以了。如果配置OOV_words,首先需要配置OOV_token。
需要注意的是,CountVectorsFeaturizer是通過計(jì)算詞頻來(lái)創(chuàng)建一個(gè)詞袋表示的,因此對(duì)句子中OOV_token的數(shù)量很敏感。
use_shared_vocab:如果要在用戶消息和意圖之間共享詞匯表,則需要將選項(xiàng)use_shared_vocab設(shè)置為True。
additional_vocabulary_size:稠密特征是固定長(zhǎng)度,但是稀疏特征的長(zhǎng)度是變的,比如新編寫的訓(xùn)練數(shù)據(jù)多了一個(gè)新詞,那么向量就變長(zhǎng)了,為了能固定稀疏特征的長(zhǎng)度,引入additional_vocabulary_size配置參數(shù)。本質(zhì)上就是為新詞填充一些槽位,在沒有新詞的時(shí)候,這些槽位就填占位符,有新詞就用新詞替換占位符。例如
pipeline:
- name: CountVectorsFeaturizer
additional_vocabulary_size:
text: 1000
response: 1000
action_text: 1000在上面的示例中,為文本(用戶消息)、響應(yīng)(ResponseSelector使用的bot響應(yīng))和操作文本(ResponseSelector未使用的bot響應(yīng))中的每一類定義額外的詞匯表大小。如果use_shared_vocab=True,只需定義text屬性一個(gè)值。如果用戶未配置任何屬性,additional_vocabulary_size的默認(rèn)值是當(dāng)前詞匯表的一半。為了避免在增量訓(xùn)練中過于頻繁地用完額外的詞匯表,這個(gè)數(shù)字至少保持在1000。一旦組件用完了額外的詞匯表槽,新的詞匯表標(biāo)記就會(huì)被丟棄,這時(shí)候就需要從頭開始訓(xùn)練模型了,不能增量訓(xùn)練了。
好了,終于將CountVectorsFeaturizer的方方面面講完了,下面是CountVectorsFeaturizer的配置示例。
pipeline:
- name: "CountVectorsFeaturizer"
additional_vocabulary_size:
text: 1000
response: 1000
action_text: 1000
# Analyzer to use, either 'word', 'char', or 'char_wb'
"analyzer": "word"
# Set the lower and upper boundaries for the n-grams
"min_ngram": 1
"max_ngram": 1
# Set the out-of-vocabulary token
"OOV_token": "_oov_"
"OOV_words": []
# Whether to use a shared vocab
"use_shared_vocab": False前文沒有介紹到參數(shù),可以參考下文
+-------------------+----------------------+--------------------------------------------------------------+
| Parameter | Default Value | Description |
+===================+======================+==============================================================+
| use_shared_vocab | False | If set to 'True' a common vocabulary is used for labels |
| | | and user message. |
+-------------------+----------------------+--------------------------------------------------------------+
| analyzer | word | Whether the features should be made of word n-gram or |
| | | character n-grams. Option 'char_wb' creates character |
| | | n-grams only from text inside word boundaries; |
| | | n-grams at the edges of words are padded with space. |
| | | Valid values: 'word', 'char', 'char_wb'. |
+-------------------+----------------------+--------------------------------------------------------------+
| strip_accents | None | Remove accents during the pre-processing step. |
| | | Valid values: 'ascii', 'unicode', 'None'. |
+-------------------+----------------------+--------------------------------------------------------------+
| stop_words | None | A list of stop words to use. |
| | | Valid values: 'english' (uses an internal list of |
| | | English stop words), a list of custom stop words, or |
| | | 'None'. |
+--------------+----------------------+--------------------------------------------------------------+
| min_df | 1 | When building the vocabulary ignore terms that have a |
| | | document frequency strictly lower than the given threshold. |
+--------------+----------------------+--------------------------------------------------------------+
| max_df | 1 | When building the vocabulary ignore terms that have a |
| | | document frequency strictly higher than the given threshold |
| | | (corpus-specific stop words). |
+--------------+----------------------+--------------------------------------------------------------+
| min_ngram | 1 | The lower boundary of the range of n-values for different |
| | | word n-grams or char n-grams to be extracted. |
+--------------+----------------------+--------------------------------------------------------------+
| max_ngram | 1 | The upper boundary of the range of n-values for different |
| | | word n-grams or char n-grams to be extracted. |
+--------------+----------------------+--------------------------------------------------------------+
| max_features | None | If not 'None', build a vocabulary that only consider the top |
| | | max_features ordered by term frequency across the corpus. |
+--------------+----------------------+--------------------------------------------------------------+
| lowercase | True | Convert all characters to lowercase before tokenizing. |
+--------------+----------------------+--------------------------------------------------------------+
| OOV_token | None | Keyword for unseen words. |
+--------------+----------------------+--------------------------------------------------------------+
| OOV_words | [] | List of words to be treated as 'OOV_token' during training. |
+--------------+----------------------+--------------------------------------------------------------+
| alias | CountVectorFeaturizer| Alias name of featurizer. |
+--------------+----------------------+--------------------------------------------------------------+
| use_lemma | True | Use the lemma of words for featurization. |
+--------------+----------------------+--------------------------------------------------------------+LexicalSyntacticFeaturizer
將輸入的消息創(chuàng)建詞法和語(yǔ)法特征,用于后續(xù)的實(shí)體識(shí)別。輸入是用戶輸入消息,輸出是稀疏向量。

特征提取器是后續(xù)計(jì)算的基礎(chǔ),信息越多越有利于后面的計(jì)算,所以常常都是幾種辦法組合使用。尤其RegexFeaturizer是最常用的。LexicalSyntacticFeaturizer也會(huì)提供一些有益的信息。值得注意的是,在后續(xù)說到的分類器會(huì)對(duì)特征有要求,是稀疏向量還是稠密向量。
總結(jié)
可以對(duì)接多個(gè)Featurizer來(lái)完成特征提取,最常見的是RegexFeaturizer,再加上一個(gè)稠密特征器。
