章节七:RASA NLU组件介绍--意图分类器和实体提取器

目录

    • 一、前言
    • 二、意图分类器
      • MitieIntentClassifier
      • LogisticRegressionClassifier
      • SklearnIntentClassifier
      • KeywordIntentClassifier
      • DIETClassifier
      • FallbackClassifier
    • 三、实体提取器
      • MitieEntityExtractor
      • SpacyEntityExtractor
      • CRFEntityExtractor
      • DucklingEntityExtractor
      • DIETClassifier
      • RegexEntityExtractor
      • EntitySynonymMapper

一、前言

RASA在处理对话时,整体流程是pipeline结构,自然语言理解(NLU)、对话状态追踪(DST)以及对话策略学习(DPL)一系列流程处理下来,再判断执行下一个动作。其中,NLU组件主要是将用户的输入处理成结构化输出。该组件主要用途为实体抽取、意图分类、响应选择、预处理等。NLU组件也是一个可细分pipeline结构,过程是Tokenize->Featurize->Intent Classify->NER Extract。

意图分类器主要是对用户的每一次对话进行意图识别,确定用户的每次意图,确定客户每次问的意图是哪种,需要做什么。一般任务型对话中,意图识别都是确定的集合,需要人为先确定任务意图类型,然后在实际场景中进行意图分类。RASA的意图分类器主要是完成这一任务,本章主要是介绍RASA支持的意图分类器。

二、意图分类器

MitieIntentClassifier

该分类器主要是使用 MITIENLP 进行意图分类。底层分类器使用具有稀疏线性内核的多类线性 SVM(参见MITIE 训练代码
train_text_categorizer_classifier中的函数 )。输入就是单论用户的对话文本,输出就是单论用户的意图类型,并且带有置信度。

注意:这个分类器不依赖于任何特征化器,因为它自己提取特征。
该分类器配置方式:主要是在pipline中进行配置。样例如下:

pipeline:
- name: "MitieIntentClassifier"

该分类器返回的结果如下:

{
    "intent": {"name": "greet", "confidence": 0.98343}
}

LogisticRegressionClassifier

该分类器使用 scikit-learn 的逻辑回归实现来执行意图分类。它只能使用稀疏特征,但也会选择存在的任何密集特征。一般来说,DIET 需要准确率更好的效果,不过这个分类器训练得更快并且可以用作轻量级基准,就是可以作为benchmark。开发者使用时主要是基于 scikit-learn 来实现,class_weight这个参数主要是设置成"balanced"。

逻辑回归意图分类器主要是基于scikit-learn来实现,输出是意图或者意图的排序。该分类器配置方式:主要是在pipline中进行配置。样例如下:

pipeline:
  - name: LogisticRegressionClassifier
    max_iter: 100
    solver: lbfgs
    tol: 0.0001
    random_state: 42
    ranking_length: 10

下面简要说明配置参数。
max_iter:求解器收敛所需的最大迭代次数。
solver:要使用的求解器。对于非常小的数据集,您可能会考虑liblinear.
tol:优化器停止标准的容忍度。
random_state:用于在训练前打乱数据。
ranking_length:要报告的首要意图数。设置为 0 以报告所有意图
有关参数的更多详细信息,请参阅scikit-learn 文档页面。
该分类器返回的结果如下:

{
  "intent": {"name": "greet", "confidence": 0.780},
  "intent_ranking": [
    {
      "confidence": 0.780,
      "name": "greet"
    },
    {
      "confidence": 0.140,
      "name": "goodbye"
    },
    {
      "confidence": 0.080,
      "name": "restaurant_search"
    }
  ]
}

SklearnIntentClassifier

sklearn 意图分类器训练一个线性 SVM,它使用网格搜索进行优化。它还提供了没有“获胜”的标签的排名。SklearnIntentClassifier之前需要在管道中使用密集的特征化器。这个密集的特征化器创建用于分类的特征。有关算法本身的更多信息,请查看 GridSearchCV 文档。

Sklearn 意图分类器主要是基于scikit-learn来实现,输出是意图以及意图排序。在 SVM 的训练过程中,运行超参数搜索以找到最佳参数集。在配置中,开发者可以指定要尝试的参数。分类器配置方式:主要是在pipline中进行配置。样例如下:

pipeline:
  - name: "SklearnIntentClassifier"
    # Specifies the list of regularization values to
    # cross-validate over for C-SVM.
    # This is used with the ``kernel`` hyperparameter in GridSearchCV.
    C: [1, 2, 5, 10, 20, 100]
    # Specifies the kernel to use with C-SVM.
    # This is used with the ``C`` hyperparameter in GridSearchCV.
    kernels: ["linear"]
    # Gamma parameter of the C-SVM.
    "gamma": [0.1]
    # We try to find a good number of cross folds to use during
    # intent training, this specifies the max number of folds.
    "max_cross_validation_folds": 5
    # Scoring function used for evaluating the hyper parameters.
    # This can be a name or a function.
    "scoring_function": "f1_weighted"

该分类器返回的结果如下:

{
  "intent": {"name": "greet", "confidence": 0.780},
  "intent_ranking": [
    {
      "confidence": 0.780,
      "name": "greet"
    },
    {
      "confidence": 0.140,
      "name": "goodbye"
    },
    {
      "confidence": 0.080,
      "name": "restaurant_search"
    }
  ]
}

KeywordIntentClassifier

简单的关键字匹配意图分类器,适用于小型、短期项目。该分类器通过在消息中搜索关键字来工作。默认情况下,匹配区分大小写,并且仅搜索与用户消息中的关键字字符串完全匹配的内容。意图的关键字是 NLU 训练数据中该意图的示例。这意味着整个示例都是关键字,而不是示例中的单个单词。

此分类器仅适用于小型项目或入门。如果开发者的 NLU 训练数据很少,可以查看 Tuning Your Model中推荐的流水线。分类器配置方式:主要是在pipline中进行配置。样例如下:

pipeline:
- name: "KeywordIntentClassifier"
  case_sensitive: True

该分类器返回的结果如下:

{
    "intent": {"name": "greet", "confidence": 1.0}
}

DIETClassifier

DIET(Dual Intent and Entity Transformer)是一种用于意图分类和实体识别的多任务架构。该架构基于为两个任务共享的转换器。一系列实体标签是通过条件随机场 (CRF) 标记层预测的,位于对应于令牌输入序列的转换器输出序列之上。对于意图标签,完整话语和意图标签的转换器输出被嵌入到单个语义向量空间中。我们使用点积损失来最大化与目标标签的相似性并最小化与负样本的相似性。

DIET 不提供预训练的词嵌入或预训练的语言模型,但如果将它们添加到管道中,它就能够使用这些功能。如果您想了解有关该模型的更多信息,请查看 YouTube 上的算法白板系列,我们在其中详细解释了模型架构。

该分类器的输出主要是实体、意图以及意图排序集合。

如果要使用DIETClassifier仅用于意图分类,请设置entity_recognition为False。如果只想做实体识别,设置intent_classification为False。默认情况下DIETClassifier两者都做,即entity_recognition和intent_classification都设置为 True。开发者可以定义许多超参数来调整模型。如果要调整模型,可以修改以下参数:

epochs:此参数设置算法将看到训练数据的次数(默认值:)300。一次epoch等于所有训练样例的一次前向传播和一次反向传播。有时模型需要更多的 epoch 才能正确学习。有时更多的时代不会影响性能。epoch 的数量越少,模型训练得越快。
hidden_layers_sizes:此参数允许您定义前馈层的数量及其用户消息和意图的输出维度(默认值:)text: [], label: []。列表中的每个条目都对应一个前馈层。例如,如果您设置text: [256, 128],我们将在变压器前面添加两个前馈层。输入标记的向量(来自用户消息)将传递到这些层。第一层的输出维度为 256,第二层的输出维度为 128。如果使用空列表(默认行为),则不会添加前馈层。确保仅使用正整数值。通常,使用 2 的幂数。此外,通常的做法是列表中的值递减:下一个值小于或等于之前的值。
embedding_dimension:此参数定义模型内部使用的嵌入层的输出维度(默认值:)20。我们在模型架构中使用多个嵌入层。例如,完整话语和意图的向量在比较和计算损失之前被传递到嵌入层。
○ number_of_transformer_layers:此参数设置要使用的变压器层数(默认值:)2。变压器层数对应于用于模型的变压器块。
transformer_size:此参数设置变压器中的单元数(默认值:)256。来自变压器的矢量将具有给定的transformer_size.
connection_density:此参数定义了模型中所有前馈层设置为非零值的内核权重的分数(默认值:)0.2。该值应介于 0 和 1 之间。如果设置connection_density 为 1,则不会将任何内核权重设置为 0,该层充当标准前馈层。您不应设置connection_density为 0,因为这会导致所有内核权重为 0,即模型无法学习。
constrain_similarities:此参数设置为True对所有相似项应用 sigmoid 交叉熵损失。这有助于将输入标签和负标签之间的相似性保持在较小的值。这应该有助于更好地将模型推广到现实世界的测试集。
○ model_confidence:此参数允许用户配置在推理期间如何计算置信度。它只能将一个值作为输入,即softmax1。在softmax中,置信度在范围内[0, 1]。计算出的相似度用softmax激活函数归一化。

开发者可以配置该以上参数,以方便开发者开发出来更适合场景的模型。
该分类器返回的结果如下:


{
    "intent": {"name": "greet", "confidence": 0.7800},
    "intent_ranking": [
        {
            "confidence": 0.7800,
            "name": "greet"
        },
        {
            "confidence": 0.1400,
            "name": "goodbye"
        },
        {
            "confidence": 0.0800,
            "name": "restaurant_search"
        }
    ],
    "entities": [{
        "end": 53,
        "entity": "time",
        "start": 48,
        "value": "2017-04-10T00:00:00.000+02:00",
        "confidence": 1.0,
        "extractor": "DIETClassifier"
    }]
}

FallbackClassifier

如果NLU意图分类不是很明确的话,那也可以使用nlu_fallback对消息进行分类。置信度与 fallback threshold 设置相同。该分类器的输出也是实体、意图以及意图类型集合。

如果先前的意图分类器无法正常对意图进行分类,则可以使用FallbackClassifier对用户消息进行分类。当两个排名靠前的意图的置信度分数接近于 ambiguity_threshold 时,它还可以预测回退意图。开发者可以使用FallbackClassifier来处理具有不确定 NLU 预测的回退操作。

rules:
- rule: Ask the user to rephrase in case of low NLU confidence
  steps:
  - intent: nlu_fallback
  - action: utter_please_rephrase

开发者可以定义许多超参数来调整模型。如果要调整模型,可以修改以下参数,只有在没有预测出来其他意图或者置信度没有大于或等于threshold的情况下,FallbackClassifier分类器通过可以使用nlu_fallback来进行意图分类。

  • threshold:此参数设置预nlu_fallback意图的阈值。如果先前意图分类器预测的意图没有大于或等于threshold的置信度,FallbackClassifier则将设置一个nlu_fallback意图并且置信度为1.0。
  • ambiguity_threshold:如果开发者配置了 ambiguity_threshold,则 FallbackClassifier 还将预测 nlu_fallback 意图,以防两个排名最高意图的置信度分数之差小于 ambiguity_threshold。
    该分类器返回的结果如下:
{
    "intent": {"name": "nlu_fallback", "confidence": 0.7183846840434321},
    "intent_ranking": [
        {
            "confidence": 0.7183846840434321,
            "name": "nlu_fallback"
        },
        {
            "confidence": 0.28161531595656784,
            "name": "restaurant_search"
        }
    ],
    "entities": [{
        "end": 53,
        "entity": "time",
        "start": 48,
        "value": "2017-04-10T00:00:00.000+02:00",
        "confidence": 1.0,
        "extractor": "DIETClassifier"
    }]
}

三、实体提取器

实体提取器主要是从用户消息中提取实体,例如人名或位置。如果开发者想使用多个实体提取器,我们建议每个提取器都针对一组独立的实体类型。例如,使用Duckling提取日期和时间, 使用DIETClassifier提取人名。否则,如果多个提取器针对相同的实体类型,很可能会多次提取实体。例如,如果开发者使用两个或多个通用提取器,如MitieEntityExtractor、 DIETClassifier或CRFEntityExtractor,则训练数据中的实体类型将由它们全部找到并提取。如果填充的槽类型都是text类型 ,那么管道中的只有最后一个提取器是起作用的。如果插槽的类型为list,则所有结果都将添加到列表中,包括重复项。

另一个不太明显的重复/重叠提取案例可能会发生,即使提取器专注于不同的实体类型。想象一个送餐机器人和一条用户消息,例如I would like to order the Monday special。假设地,如果你的时间提取器的性能不是很好,它可能会提取Monday这里作为订单的时间,而你的其他提取器可能会Monday special作为膳食提取。如果您难以处理此类重叠实体,添加额外的训练数据以改进您的提取器可能是有意义的。如果这还不够,您可以添加一个 自定义组件,根据您自己的逻辑解决实体提取中的冲突。

MitieEntityExtractor

MitieEntityExtractor 主要是用MITIE 实体提取器提取信息中的实体。底层提取器主要是用稀疏线性核和自定义特征的多类线性 SVM。MITIE 不提供实体的置信度值。提取器配置方式:主要是在pipline中进行配置。样例如下:

pipeline:
	- name: "MitieEntityExtractor"

该提取器返回的结果如下:

{
    "entities": [{
        "value": "New York City",
        "start": 20,
        "end": 33,
        "confidence": null,
        "entity": "city",
        "extractor": "MitieEntityExtractor"
    }]
}

SpacyEntityExtractor

spacyentityextractor 使用 spaCy 这个组件来提取消息中的实体。spaCy 主要是使用统计 BILOU 转换模型。到目前为止,该组件只能使用 spaCy 内置的实体提取模型,无法重新训练。此外,提取器不提供任何置信度分数。您可以在此交互式演示中测试 spaCy 的实体提取模型。请注意,某些 spaCy 模型高度区分大小写。并且提取器SpacyEntityExtractor不提供confidence级别并将始终返回null。

提取器配置方式,主要是在pipline中进行配置,需要配置 spaCy 组件提取的实体类型列表。可以在spaCy 文档中找到可用维度的完整列表。如果不指定维度选项,默认将提取所有可用实体类型。样例如下:

pipeline:
- name: "SpacyEntityExtractor"
  # dimensions to extract
  dimensions: ["PERSON", "LOC", "ORG", "PRODUCT"]
该提取器返回的结果如下:
{
    "entities": [{
        "value": "New York City",
        "start": 20,
        "end": 33,
        "confidence": null,
        "entity": "city",
        "extractor": "MitieEntityExtractor"
    }]
}

CRFEntityExtractor

该提取器利用条件随机 (CRF) 来进行命名实体识别。CRF 可以被认为是一个无向马尔可夫链,其中时间步长是单词,状态是实体类。单词的特征(大写、词性标记等)给出了某些实体类的概率,相邻实体标签之间的转换也是如此:然后计算并返回最有可能的标签集。

如果开发者想将自定义特征(例如预训练的词嵌入)传递给 CRFEntityExtractor,可以在 CRFEntityExtractor之前将任何稠密特征器添加到管道中,然后 CRFEntityExtractor 通过配置‘text_dense_feature’参数来使用密集特征。
CRFEntityExtractor 可以自动找到额外的密集特征并检查密集特征是否是len(tokens) 的可迭代,并且每条数据都是一个向量。如果检查失败,将提示警告。但是,CRFEntityExtractor 将在没有附加自定义功能的情况下继续训练。如果存在密集特征,CRFEntityExtractor 会将密集特征传递给 sklearn_crfsuite 并使用它们进行训练。

CRFEntityExtractor 有默认功能列表。默认的功能列表如下:

===================  ==========================================================================================
Feature Name         Description
===================  ==========================================================================================
low                  word identity - use the lower-cased token as a feature.
upper                Checks if the token is upper case.
title                Checks if the token starts with an uppercase character and all remaining characters are
                     lowercased.
digit                Checks if the token contains just digits.
prefix5              Take the first five characters of the token.
prefix2              Take the first two characters of the token.
suffix5              Take the last five characters of the token.
suffix3              Take the last three characters of the token.
suffix2              Take the last two characters of the token.
suffix1              Take the last character of the token.
pos                  Take the Part-of-Speech tag of the token (``SpacyTokenizer`` required).
pos2                 Take the first two characters of the Part-of-Speech tag of the token
                     (``SpacyTokenizer`` required).
pattern              Take the patterns defined by ``RegexFeaturizer``.
bias                 Add an additional "bias" feature to the list of features.
text_dense_features  Adds additional features from a dense featurizer.
===================  ==========================================================================================

当特征化器使用滑动窗口在用户消息中的标记上移动时,您可以为滑动窗口中的先前标记、当前标记和下一个标记定义特征。您将特征定义为[before, token, after]数组。另外,您可以设置一个标志来确定是否使用 BILOU 标记模式。BILOU_flag确定是否使用 BILOU 标记。默认True。
提取器配置方式,主要是在pipline中进行配置,样例如下:

pipeline:
- name: "CRFEntityExtractor"
  # BILOU_flag determines whether to use BILOU tagging or not.
  "BILOU_flag": True
  # features to extract in the sliding window
  "features": [
    ["low", "title", "upper"],
    [
      "bias",
      "low",
      "prefix5",
      "prefix2",
      "suffix5",
      "suffix3",
      "suffix2",
      "upper",
      "title",
      "digit",
      "pattern",
      "text_dense_features"
    ],
    ["low", "title", "upper"],
  ]
  # The maximum number of iterations for optimization algorithms.
  "max_iterations": 50
  # weight of the L1 regularization
  "L1_c": 0.1
  # weight of the L2 regularization
  "L2_c": 0.1
  # Name of dense featurizers to use.
  # If list is empty all available dense features are used.
  "featurizers": []
  # Indicated whether a list of extracted entities should be split into individual entities for a given entity type
  "split_entities_by_comma":
      address: False
      email: True

注意:

  • 如果使用 POS 功能(pos或pos2),开发者就需要在pipline中配置SpacyTokenizer 。
  • 如果使用功能pattern,开发者则需要在pipline中配置 RegexFeaturizer 。
  • 如果使用特征text_dense_features,开发者需要在pipline中pipline中配置一个稠密的特征化器(例如 LanguageModelFeaturizer)。

该提取器返回的结果如下:

{
    "entities": [{
        "value": "New York City",
        "start": 20,
        "end": 33,
        "entity": "city",
        "confidence": 0.874,
        "extractor": "CRFEntityExtractor"
    }]
}

DucklingEntityExtractor

Duckling 工具可让开发者以多种语言来提取常见实体,例如日期、金额、距离等。

如果要使用此工具,需要先运行一个Duckling 服务。最简单的使用是用docker来部署。例如 docker run -p 8000:8000 rasa/duckling,或者可以直接在您的机器上安装 duckling并启动服务器。

Duckling 允许识别日期、数字、距离和其他结构化实体并对其进行规范化。请注意,duckling工具不提供排名的情况下尝试提取尽可能多的实体类型。例如I will be there in 10 minutes,如果您为Duckling同时指定number和time作为维度,则该组件将提取两个实体:10作为数字和 in 10 minutes作为文本中的时间。在这种情况下,您的应用程序必须决定哪种实体类型是正确的。提取器将始终返回 1.0 作为置信度,因为它是一个基于规则的系统。可以在 Duckling GitHub 存储库中找到支持的语言列表。

提取器配置方式,主要是在pipline中进行配置,需要配置 Duckling 组件提取的实体类型列表。可以在小鸭项目自述 中找到可用维度的完整列表。如果不指定维度选项,默认将提取所有可用实体类型。样例如下:

pipeline:
- name: "DucklingEntityExtractor"
  # url of the running duckling server
  url: "http://localhost:8000"
  # dimensions to extract
  dimensions: ["time", "number", "amount-of-money", "distance"]
  # allows you to configure the locale, by default the language is
  # used
  locale: "de_DE"
  # if not set the default timezone of Duckling is going to be used
  # needed to calculate dates from relative expressions like "tomorrow"
  timezone: "Europe/Berlin"
  # Timeout for receiving response from http url of the running duckling server
  # if not set the default timeout of duckling http url is set to 3 seconds.
  timeout : 3

该提取器返回的结果如下:

{
    "entities": [{
        "end": 53,
        "entity": "time",
        "start": 48,
        "value": "2017-04-10T00:00:00.000+02:00",
        "confidence": 1.0,
        "extractor": "DucklingEntityExtractor"
    }]
}

DIETClassifier

DIET提取器用于意图分类和实体提取的,可以在意图分类器部分找到DIETClassifier的详细描述。在这个地方就不再赘述。可以参考意图分类器中的 DIETClassifier。

RegexEntityExtractor

RegexEntityExtractor 实体提取器主要是用训练数据中定义的查找表和正则表达式提取实体。该组件检查用户消息是否包含其中一个查找表的条目或匹配其中一个正则表达式。如果找到匹配项,则将该值提取为实体。

该组件只会是用那些出现在训练数据中的正则表达式特征。所以需要确保每个实体类型至少有一条训练数据。

当开发者将此提取器与MitieEntityExtractor、 CRFEntityExtractor或DIETClassifier结合使用时,它可能会导致多次提取实体。有关多重提取的更多信息,请参阅实体提取器部分开头的说明 。

如果开发者想同时使用 RegexEntityExtractor 和上述其他的实体提取器,我们建议考虑以下两个选择。

  • 选择1: 为每一种实体类型都配置有独立的实体提取器。为确保提取器之间不会相互干扰,只为每个正则表达式/查找实体类型标注一个训练样例,但不要更多。
  • 选择2: 只是将 RegexEntityExtractor 作为其他实体提取器的补充,但没有单独的实体类型。需要满足三个要求:
    1. 在pipline中配置 RegexFeaturizer
    2. 在训练数据中标注所有实体示例
    3. 从pipline中删除 RegexEntityExtractor。这样,提取器将收到有关正则表达式匹配到的额外信号,并且能够统计确定何时依赖这些匹配,何时不依赖。

配置方式主要是在pipline中进行配置,通过添加选项使实体提取器区分大小写case_sensitive: True,默认为 case_sensitive: False。
要正确处理中文等不使用空格分隔单词的语言,用户需要添加该use_word_boundaries: False选项,默认为use_word_boundaries: True.

pipeline:
- name: RegexEntityExtractor
  # text will be processed with case insensitive as default
  case_sensitive: False
  # use lookup tables to extract entities
  use_lookup_tables: True
  # use regexes to extract entities
  use_regexes: True
  # use match word boundaries for lookup table
  use_word_boundaries: True

EntitySynonymMapper

如果训练数据包含定义的同义词,此组件将确保检测到的实体值映射到相同的值。例如,如果您的训练数据包含以下示例:

[
  {
    "text": "I moved to New York City",
    "intent": "inform_relocation",
    "entities": [{
      "value": "nyc",
      "start": 11,
      "end": 24,
      "entity": "city",
    }]
  },
  {
    "text": "I got a new flat in NYC.",
    "intent": "inform_relocation",
    "entities": [{
      "value": "nyc",
      "start": 20,
      "end": 23,
      "entity": "city",
    }]
  }
]

该组件将允许您将实体New York City和NYC映射到nyc. 即使消息包含NYC,实体提取也会返回nyc。当该组件更改现有实体时,它会将自己附加到该实体的处理器列表中。

配置方式,在pipline中进行配置,样例如下:

pipeline:
- name: "EntitySynonymMapper"

当EntitySynonymMapper作为 NLU pipline的一部分使用时,需要将其放置在配置文件中的任何实体提取器后面。

你可能感兴趣的:(多轮对话,自然语言处理(NLP),人工智能)