Press "Enter" to skip to content

【RASA系列】语义理解(上)

Rasa是用于构建基于上下文的智能助手和聊天机器人的一套开源机器学习框架,Rasa有两个主要模块:

 

Rasa NLU :对用户消息进行语义理解,包括意图识别和实体识别,它会把用户的输入转换为结构化的数据。

 

Rasa Core:用于对话管理(Dialogue management),决策下一步应该执行什幺动作。

 

本篇主要介绍Rasa NLU的基本操作、训练数据格式、意图分类和实体识别。

 

基本操作

 

Rasa NLU是一种开源自然语言处理工具,用于聊天机器人中的意图识别,响应检索和实体抽取。例如

 

"I am looking for a Mexican restaurant in the center of town"

 

意图识别和实体抽取后结构化数据如下,

 

{

“intent”: “search_restaurant”,

“entities”: {

“cuisine” : “Mexican”,

“location” : “center”

}

}

 

Rasa NLU曾经是一个单独的库,但现在是Rasa框架的一部分。

 

我们可以仅仅使用RASA训练NLU模型,只要运行如下命令:

 

rasa train nlu

 

这将在 data/
目录中查找NLU训练数据文件,并将训练后的模型保存在 models/
目录中。模型的名字将以 nlu-
开头。

 

训练好模型之后,让我们来测试一下NLU模型,使用以下命令

 

rasa shell nlu

 

这将启动rasa shell,并要求输入消息进行测试。另外,可以省略 nlu
参数并直接传入NLU模型:

 

rasa shell -m models/nlu-20191007-094608.tar.gz

 

要使用NLU模型启动服务器,在运行时传递模型名字:

 

rasa run --enable-api -m models/nlu-20191007-094608.tar.gz

 

然后,我们可以访问 localhost:5005/model/parse
URL请求。为此,运行下面的例子:

 

curl localhost:5005/model/parse -d '{"text":"hello"}'

 

训练数据格式

 

数据格式: 支持Markdown或JSON,单个文件或包含多个文件的目录的形式提供训练数据。但是,我们知道Markdown通常更易于使用。

 

Markdown Format:Markdown是我们最容易阅读和书写的Rasa NLU格式。有对Markdown语法不熟悉的可以查阅相关资料了解一下,整体是非常简洁的。实例按意图分组,而实体则标注为Markdown链接,例如。 [entity](entity name)

 

## intent:check_balance

– what is my balance <!– no entity –>

– how much do I have on my [savings](source_account) <!– entity “source_account” has value “savings” –>

– how much do I have on my [savings account](source_account:savings) <!– synonyms, method 1–>

– Could I pay in [yen](currency)? <!– entity matched by lookup table –>

## intent:greet

– hey

– hello

## synonym:savings <!– synonyms, method 2 –>

– pink pig

## regex:zipcode

– [0-9]{5}

## lookup:currencies <!– lookup table list –>

– Yen

– USD

– Euro

## lookup:additional_currencies <!– no list to specify lookup table file –>

path/to/currencies.txt

 

Rasa NLU的训练数据分为以下几个部分:

 

通用示例

 

同义词

 

正则表达式

 

查找表

 

虽然通用示例是唯一必需的部分,但包括其他示例将帮助NLU模型更好的学习领域,并有助于对其预测更有帮助。

 

同义词会将提取的实体映射到相同的名称,例如,将“我的储蓄帐户”映射为简单的“储蓄”。但是,这仅
提取实体 之后
才发生,因此需要提供带有存在同义词的示例,以便Rasa可以学习并将其提取。

 

查找表可以直接指定为列表,也可以指定为包含换行符分隔的单词或短语的txt文件。加载训练数据后,这些文件用于生成不区分大小写的正则表达式模式,该模式会添加到正则表达式功能中。例如,在这种情况下,将提供名称列表,以便更轻松地选择该实体。

 

JSON格式:JSON格式由被称为顶层对象的 rasa_nlu_data
,与键 common_examples
entity_synonyms
regex_features
。最重要的是 common_examples

 

{

“rasa_nlu_data”: {

“common_examples”: [],

“regex_features” : [],

“lookup_tables” : [],

“entity_synonyms”: []

}

}

 

common_examples
是用来训练模型。将所有训练示例放在 common_examples
数组中。正则表达式功能是帮助分类器检测实体或意图并提高性能的工具。

 

提高意图分类和实体识别

 

通用示例: 由三个组成部分: text
intent
entities
。前两个是字符串,最后一个是数组。

 

文本
是用户消息[必须]

 

意图
是,应与文字相关的意图[可选]

 

实体
是需要被识别的文本的特定部分[可选]

 

实体用 start
end
值指定,指定了实体开始和结束的位置,例如在下面的示例中,text=”show me chinese restaurants”,text[8:15] == ‘chinese’。实体可以跨越多个单词,实际上,该字段不必与示例中的子字符串完全对应。这样,可以将同义词或拼写错误映射到同一个。

 

## intent:restaurant_search

– show me [chinese](cuisine) restaurants

 

正则表达式:正则表达式可用于支持意图分类和实体提取。例如,如果实体具有确定性结构(例如邮政编码或电子邮件地址),则可以使用正则表达式来简化对该实体的抽取。对于邮政编码示例,它可能如下所示:

 

## regex:zipcode

– [0-9]{5}

## regex:greet

– hey[^\\s]*

 

名称没有定义实体,也没有定义意图,它只是人类可读的描述,可以记住该正则表达式的用途,并且是相应模式特征的标题。如上例所示,还可以使用正则表达式功能来改善意图分类性能。

 

尝试以使其与尽可能少的单词匹配的方式创建正则表达式。例如,使用 hey[^\s]*
而不是 hey.*
,因为后一个可能匹配整个消息,而第一个可能只匹配一个单词。

 

目前只有 CRFEntityExtractor
组件支持用于实体提取的正则表达式功能!因此,其他实体提取器像 MitieEntityExtractor
SpacyEntityExtractor
不使用生成的特征,并且它们的存在不会提高这些提取器的实体识别度。当前,所有意图分类器都支持正则表达式功能。

 

查找表:训练数据中也可以指定外部文件形式的查找表或元素列表。外部提供的查找表必须采用换行符分隔。例如, data/test/lookup_tables/plates.txt
可能包含:

 

tacos

beef

mapo tofu

burrito

lettuce wrap

 

可以加载为:

 

## lookup:plates

data/test/lookup_tables/plates.txt

 

或者,可以将查找元素直接包含在列表中

 

## lookup:plates

– beans

– rice

– tacos

– cheese

 

在训练数据中提供查找表时,内容将组合成一个大写,不区分大小写的正则表达式模式,该模式在训练示例中查找完全匹配的内容。这些正则表达式可匹配多个,因此lettuce wrap将匹配 get me a lettuce wrap ASAP
[0 0 0 1 1 0]
。这些正则表达式的处理方式与直接在训练数据中指定的常规正则表达式样式相同。

 

数据标准化

 

实体同义词:如果将实体定义为具有相同的值,则它们将被视为同义词。这是一个例子:

 

## intent:search

– in the center of [NYC](city:New York City)

– in the centre of [New York City](city)

 

如你所见,在两个示例中均 city
具有值。通过将value属性定义为与实体的开始索引和结束索引之间的文本中找到的值不同,可以定义同义词。每当找到相同的文本时,该值将使用同义词代替消息中的实际文本。

 

要使用训练数据中定义的同义词,您需要确保管道包含 EntitySynonymMapper
组件。

 

另外,您可以添加一个“ entity_synonyms”数组来为一个实体值定义多个同义词。如下:

 

## synonym:New York City

– NYC

– nyc

– the big apple

 

有时生成一堆实体示例会很有帮助,例如,如果您有餐厅名称数据库。社区构建了一些工具来帮助实现这一目标。可以使用Chatito为rasa 创建训练数据集。但是,创建综合示例通常会导致过拟合,如果您有大量实体值,则最好使用查找表。

 

选择Pipeline

 

选择NLU Pipeline可以自定义模型并在数据集上进行微调。如果训练数据少于1000,并且语言支持spaCy模型,请使用 pretrained_embeddings_spacy Pipeline

 

language: “en”

pipeline: “pretrained_embeddings_spacy”

 

如果您有1000或更多带标签训练数据,请使用 supervised_embeddings Pipeline

 

language: “en”

pipeline: “supervised_embeddings”

 

最重要的两个管道是 supervised_embeddings
pretrained_embeddings_spacy
。它们之间的最大区别是 pretrained_embeddings_spacy
使用来自GloVe或fastText的预训练词向量。但是, supervised_embeddings
不使用任何预先训练的词向量。

 

pretrained_embeddings_spacy
pipeline的优势在于,如果您有一个训练数据,例如:“I want to buy apples”,并且要求Rasa预测“get pears”的意图,那幺模型已经知道“apples”和“pears”这两个词非常相似。如果没有太多的训练数据,这将特别有用。

 

supervised_embeddings
pipeline的优势在于,将针对领域自定义单词向量。例如,在通用英语中,“balance”一词与“symmetry”密切相关,但与“cash”一词有很大不同。在银行领域中,“balance”和“cash”密切相关,希望模型能够做到这一点。该pipeline不使用特定于语言的模型,因此它将与您可以标记化的任何语言一起使用。

 

也可以在管道中使用MITIE作为单词向量的来源,MITIE后端对于小型数据集表现良好,但是如果有数百个以上的数据,则训练可能会花费很长时间。不建议使用它,因为在将来的版本中可能会不再支持mitie支持。

 

类不平衡

 

如果类别失衡很大,例如,如果有很多针对某些意图的训练数据而很少有针对其他意图的训练数据,则分类算法通常不会表现良好。为了缓解此问题,rasa的 supervised_embeddings
管道使用了 balanced
批处理策略。该算法确保在每个批次中或至少在尽可能多的后续批次中代表所有类别,仍然模仿某些类别比其他类别更频繁的事实。默认情况下使用平衡批处理。为了将其关闭并使用经典的批处理策略,请在您的配置文件中添加该策略 。 batch_strategy: sequence

 

language: “en”

pipeline:

– name: “CountVectorsFeaturizer”

– name: “EmbeddingIntentClassifier”

batch_strategy: sequence

 

多意图

 

如果要将意图拆分为多个标签(例如,用于预测多个意图或为分层意图结构建模),则只能使用受监督的嵌入管道来执行此操作。为此,请在中使用这些标志: Whitespace Tokenizer

intent_split_symbol
:设置分隔符字符串以拆分意图标签。默认 _

language: “en”

pipeline:

– name: “WhitespaceTokenizer”

intent_split_symbol: “_”

– name: “CountVectorsFeaturizer”

– name: “EmbeddingIntentClassifier”

 

了解Rasa NLU管道

 

在Rasa NLU中,传入消息由一系列组件处理。这些组件在所谓的处理管道中一个接一个地执行。有用于实体提取,意图分类,响应选择,预处理等的组件,也支持自定义组件。

 

每个组件都处理输入并创建输出。输出可以由管道中该组件之后的任何组件使用。有一些组件仅生成流水线中其他组件使用的信息,还有其他一些组件会生成 Output
属性,这些属性将在处理完成后返回。例如,对于该句子,输出为: "I am looking for Chinese food"

 

{

“text”: “I am looking for Chinese food”,

“entities”: [

{“start”: 8, “end”: 15, “value”: “chinese”, “entity”: “cuisine”, “extractor”: “CRFEntityExtractor”, “confidence”: 0.864}

],

“intent”: {“confidence”: 0.6485910906220309, “name”: “restaurant_search”},

“intent_ranking”: [

{“confidence”: 0.6485910906220309, “name”: “restaurant_search”},

{“confidence”: 0.1416153159565678, “name”: “affirm”}

]

}

 

这是预配置管道中不同组件的结果的组合 pretrained_embeddings_spacy
。例如, entities
属性是由 CRFEntityExtractor
组件创建的。

 

预先配置的管道

 

模板只是完整组件列表的快捷方式。例如,这两个配置是等效的:

 

language: “en”

pipeline: “pretrained_embeddings_spacy”

language: “en”

pipeline:

– name: “SpacyNLP”

– name: “SpacyTokenizer”

– name: “SpacyFeaturizer”

– name: “RegexFeaturizer”

– name: “CRFEntityExtractor”

– name: “EntitySynonymMapper”

– name: “SklearnIntentClassifier”

 

以下是所有带有定制信息的预配置管道模板的列表。

 

supervised_embeddings:要以首选语言训练Rasa模型,请 supervised_embeddings
在您 config.yml
或其他配置文件中将管道定义为 管道:

 

language: “en”

pipeline: “supervised_embeddings”

 

supervised_embeddings
管道的支持可以符号化的任何语言。默认情况下,它使用空格进行标记化。可以通过添加或更改组件来自定义此管道的设置。以下是构成 supervised_embeddings
管道的默认组件:

 

language: “en”

pipeline:

– name: “WhitespaceTokenizer”

– name: “RegexFeaturizer”

– name: “CRFEntityExtractor”

– name: “EntitySynonymMapper”

– name: “CountVectorsFeaturizer”

– name: “CountVectorsFeaturizer”

analyzer: “char_wb”

min_ngram: 1

max_ngram: 4

– name: “EmbeddingIntentClassifier”

 

因此,例如,如果您选择的语言没有使用空格标记(单词之间没有空格),则可以用 WhitespaceTokenizer
自己的标记器替换。管道使用的两个实例 CountVectorsFeaturizer
。第一个将基于单词的文本特征化。第二个基于字符n-gram对文本进行特征化处理,保留单词边界。

 

pretrained_embeddings_spacy:要使用 pretrained_embeddings_spacy
模板:

 

language: “en”

pipeline: “pretrained_embeddings_spacy”

language: “en”

pipeline:

– name: “SpacyNLP”

– name: “SpacyTokenizer”

– name: “SpacyFeaturizer”

– name: “RegexFeaturizer”

– name: “CRFEntityExtractor”

– name: “EntitySynonymMapper”

– name: “SklearnIntentClassifier”

 

自定义管道:也可以不必使用模板,通过列出要使用的组件的名称来运行完全自定义的管道:

 

pipeline:

– name: “SpacyNLP”

– name: “CRFEntityExtractor”

– name: “EntitySynonymMapper”

 

这将创建仅执行实体识别但不进行意图分类的管道。因此,Rasa NLU不会预测任何意图。

 

语言支持

 

可以使用Rasa以所需的任何语言构建助手!Rasa的 supervised_embeddings
pipeline可以用于 任何语言的
训练数据。该pipeline使用提供的数据从头开始创建单词嵌入。此外,我们还支持预训练的单词嵌入,例如spaCy。

 

支持任何语言训练模型:Rasa的 supervised_embeddings
pipeline可用于以任何语言训练模型,因为它使用自己的训练数据来创建自定义单词嵌入。这意味着任何特定单词的向量表示形式将取决于其与训练数据中其他单词的关系。这种定制还意味着,该pipeline非常适合依赖特定于域的数据的用例,例如那些需要提取特定产品名称的用例。

 

要使用首选语言训练Rasa模型,在 config.yml
中设置 supervised_embeddings
。定义 supervised_embeddings
处理pipeline并 使用该语言生成一些NLU训练数据后,使用下面命令训练。

 

rasa shell nlu

 

译者介绍

 

王文彬,2018年毕业于中国科学院大学。毕业后加入贝壳找房语言智能与搜索部,主要从事NLP、强化学习和搜索推荐相关工作。

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注