本文介绍构建和评估对话语言理解(CLU)模型的核心概念,包括如何测量模型性能、默认 None 意向以及 CLU 接受的数据格式。
评估指标
数据集分为两部分:一组用于训练,一组用于测试。 训练集用于训练模型,而测试集用作训练后的模型测试,以计算模型性能和评估。 测试集不会通过训练过程引入到模型中,以确保使用新数据测试模型。
成功完成训练后,将自动触发模型评估。 评估过程首先使用经过训练的模型来预测测试集中话语的用户定义意图和实体。 然后,将其与提供的标记进行比较,以建立真实的基线。 系统会返回结果,这样你便可以查看模型的性能。 对于评估,对话语言理解使用以下指标:
精准率:度量模型的精确度或准确度。 它是正确识别的正值(真正)与所有识别出的正值之间的比率。 精准率指标揭示了预测出的类别中有多少被正确标记。
Precision = #True_Positive / (#True_Positive + #False_Positive)召回率:衡量模型识别真实正类的能力。 它是预测为正且实际被标记为正的样本占所有被预测为正的样本的比率。 召回率这一指标揭示了预测出的类别中有多少是正确的。
Recall = #True_Positive / (#True_Positive + #False_Negatives)F1 分数:F1 分数是精准率和召回率的函数。 在精准率和召回率之间进行平衡时,需要用到它。
F1 Score = 2 * Precision * Recall / (Precision + Recall)
计算以下各项的精准率、召回率和 F1 分数:
- 每个单独的实体(实体级评估)。
- 分别针对每个意图(意图级评估)。
- 针对整个模型(模型级评估)。
在实体级、意图级和模型级评估中,精准率、召回率和评估的定义是相同的。 但是,真正例、假正例和假负例的数量可能不同。 例如,请考虑以下文本。
示例
- 回答“非常感谢你”。
- 回复说“是的”。
- 请检查我的电子邮件。
- 给辛西娅的电子邮件说,上周的晚餐很精彩。
- 向 Mike 发送电子邮件。
使用的意图是 Reply、sendEmail 和 readEmail。 实体是 contactName 和 message。
该模型可以做出以下预测:
| 话语 | 预测意图 | 实际意图 | 预测的实体 | 实际实体 |
|---|---|---|---|---|
| 回答“非常感谢” | 答复 | 答复 |
thank you very much 为 message |
thank you very much 为 message |
| 回复说“是” | sendEmail | 答复 | -- |
yes 为 message |
| 请检查我的电子邮件 | 读取电子邮件 | readEmail | -- | -- |
| 发给辛西娅的电子邮件中说,上周的晚餐很精彩。 | 答复 | sendEmail |
dinner last week was splendid 为 message |
cynthia 为 contactName,dinner last week was splendid 为 message |
| 向 Mike 发送电子邮件 | sendEmail | sendEmail |
mike 为 message |
mike 为 contactName |
回复意图的意图级评估
| 密钥 | 数量 | 说明 |
|---|---|---|
| 真正 | 1 | 话语 1 被正确预测为 Reply。 |
| 假阳性 | 1 | 话语 4 被错误地预测为 Reply。 |
| 假阴性 | 1 | 语句 2 被误预测为 sendEmail。 |
精确率 = #True_Positive / (#True_Positive + #False_Positive) = 1 / (1 + 1) = 0.5
召回率 = #True_Positive / (#True_Positive + #False_Negatives) = 1 / (1 + 1) = 0.5
F1 分数 = 2 * Precision * Recall / (Precision + Recall) = (2 * 0.5 * 0.5) / (0.5 + 0.5) = 0.5
sendEmail 意图的意图级评估
| 密钥 | 数量 | 说明 |
|---|---|---|
| 真正 | 1 | 话语 5 被正确预测为 sendEmail。 |
| 假阳性 | 1 | 语句 2 被误预测为 sendEmail。 |
| 假阴性 | 1 | 话语 4 被错误地预测为 Reply。 |
精确率 = #True_Positive / (#True_Positive + #False_Positive) = 1 / (1 + 1) = 0.5
召回率 = #True_Positive / (#True_Positive + #False_Negatives) = 1 / (1 + 1) = 0.5
F1 分数 = 2 * Precision * Recall / (Precision + Recall) = (2 * 0.5 * 0.5) / (0.5 + 0.5) = 0.5
针对 readEmail 意图的意图级评估
| 密钥 | 数量 | 说明 |
|---|---|---|
| 真正 | 1 | 话语 3 被正确预测为 readEmail。 |
| 假阳性 | 0 | -- |
| 假阴性 | 0 | -- |
精确率 = #True_Positive / (#True_Positive + #False_Positive) = 1 / (1 + 0) = 1
召回率 = #True_Positive / (#True_Positive + #False_Negatives) = 1 / (1 + 0) = 1
F1 分数 = 2 * Precision * Recall / (Precision + Recall) = (2 * 1 * 1) / (1 + 1) = 1
contactName 实体的实体级别评估
| 密钥 | 数量 | 说明 |
|---|---|---|
| 真正 | 1 | 在语句 4 中,cynthia 被正确预测为 contactName。 |
| 假阳性 | 0 | -- |
| 假阴性 | 1 | 在语句 5 中,mike 被错误预测为 message。 |
精确率 = #True_Positive / (#True_Positive + #False_Positive) = 1 / (1 + 0) = 1
召回率 = #True_Positive / (#True_Positive + #False_Negatives) = 1 / (1 + 1) = 0.5
F1 得分 = 2 * Precision * Recall / (Precision + Recall) = (2 * 1 * 0.5) / (1 + 0.5) = 0.67
针对消息实体的实体级评估
| 密钥 | 数量 | 说明 |
|---|---|---|
| 真正 | 2 | 在语句 1 中,thank you very much 被正确预测为 message,在语句 4 中,dinner last week was splendid 被正确预测为 message。 |
| 误报 | 1 | 在语句 5 中,mike 被错误预测为 message。 |
| 假阴性 | 1 | 在语句 2 中, yes 未被预测为 message。 |
精度 = #True_Positive / (#True_Positive + #False_Positive) = 2 / (2 + 1) = 0.67
召回率 = #True_Positive / (#True_Positive + #False_Negatives) = 2 / (2 + 1) = 0.67
F1 分数 = 2 * Precision * Recall / (Precision + Recall) = (2 * 0.67 * 0.67) / (0.67 + 0.67) = 0.67
对整体模型进行模型级评估
| 密钥 | 数量 | 说明 |
|---|---|---|
| 真正 | 6 | 所有意向和实体的真正之和。 |
| 假阳性 | 3 | 所有意图和实体的假阳性总和。 |
| 假阴性 | 4 | 所有意图和实体的假阴性总数。 |
精确率 = #True_Positive / (#True_Positive + #False_Positive) = 6 / (6 + 3) = 0.67
召回率 = #True_Positive / (#True_Positive + #False_Negatives) = 6 / (6 + 4) = 0.60
F1 分数 = 2 * Precision * Recall / (Precision + Recall) = (2 * 0.67 * 0.60) / (0.67 + 0.60) = 0.63
混淆矩阵
混淆矩阵是用于模型性能评估的 N x N 矩阵,其中 N 是实体或意向数目。 该矩阵将预期标签与模型预测的标签进行比较。 此矩阵为模型的性能以及它所犯的错误类型提供了整体视图。
可以使用混淆矩阵来识别彼此之间过于接近且经常被弄错(产生歧义)的意向或实体。 在这种情况下,请考虑将这些意向或实体合并在一起。 如果无法合并,请考虑添加这两个意向或实体的更多标记示例,帮助模型进行区分。
下图中突出显示的对角线是正确预测的实体,其中预测标记与实际标记相同。
可以根据混淆矩阵计算意向级别/实体级别和模型级别的评估指标:
- 对角线上的值是每个意图或实体的真阳性值。
- 意向或实体行(不包括对角线)中值的总和是模型的假正值。
- 意向或实体列(不包括对角线)中值的总和是模型的假负值。
同理:
- 模型的真正值是所有意向或实体的真正值的总和。
- 模型的假阳性数是所有意图或实体的假阳性数之和。
- 模型的假负值是所有意向或实体的假负值的总和。
指南
训练模型后,你会看到一些关于如何改进模型的指导和建议。 建议使用一个涵盖指南中所有要点的模型。
- 训练集有足够的数据:意向或实体在训练数据中的标记实例少于 15 个时,由于没有针对该意向对模型进行充分训练,可能会导致准确性降低。 在此情况下,请考虑在训练集中添加更多标记数据。 只有当你的实体具有学习组件时,才应考虑为其添加更多带标签的数据。 如果实体仅由列表、预生成和正则表达式组件定义,则此建议不适用。
- 测试集中包含所有意图和实体:如果测试数据中缺少某个意图或实体的标注实例,由于存在未测试到的场景,模型评估就不够全面。 请考虑为模型中的每个意向和实体提供测试数据,以确保测试所有内容。
- 意向或实体之间的区别不明确:如果不同意向或实体的数据相似,可能会导致准确性降低,因为它们可能经常被误分类为彼此。 查看以下意向和实体,如果它们相似,则考虑将其合并。 否则,请添加更多示例以更好地区分它们。 可以查看“混淆矩阵”选项卡以获取更多指南。 如果看到两个实体由于共享相同的列表、预生成的或正则表达式组件而不断被预测相同的范围,请确保为每个实体添加一个通过训练生成的组件,并将其设为必要项。 详细了解实体组件。
无意图
会话语言理解中的每个项目都包含一个默认的 None 意图。 None 意图是一个必需的意图,无法删除或重命名。 使用此意向对不属于您的任何其他自定义意向的话语进行归类。
如果评分意向的最高分数低于 None 评分阈值,则可将语句的意向预测为 None。 如果话语与您添加到 None 意图中的示例相似,模型也可以预测为 None 意图。
无分数阈值
转到任何 项目的项目设置 ,并设置 “无”分数阈值。 阈值为从 0.0 到 1.0 的小数分数。
对于任何查询和言语,如果最高评分意向最终 低于 阈值分数,则最高意向将自动替换为 None 意向。 其他所有意图的分数保持不变。
根据你自己观察到的预测分数来设定评分,因为预测分数可能因项目而异。 如果阈值分数较高,则语句与训练数据中的示例的相似度必须更高。
导出项目的 JSON 文件时,JSON 的 settings 参数中定义了 None 分数阈值作为 confidenceThreshold。 阈值接受介于 0.0 和 1.0 之间的小数值。
注释
在对测试集进行模型评估期间,不会应用 None 分数阈值。
为 None 意图添加示例
None 意图在您的项目中也会像其他任何意图一样被对待。 如果有要预测为 None 的语句,请考虑在训练数据中向其添加类似的示例。 如果要将对项目不重要的话语归类为 None,可将这些话语添加到你的意图中。 例如问候语、“是”与“否”的回答,以及对问题的回答,如提供号码。
请考虑在 None 意向中添加误判示例。 例如,在航班预订项目中,话语“I want to buy a book”很可能会被误识别为“Book Flight”意图。 可以添加“我想买书”或“我喜欢读书”作为 None 训练语句。 它们有助于将这类话语的预测结果调整为更倾向于 None 意图,而不是 Book Flight 意图。
数据格式
如果你要将数据上传到对话语言理解中,这些数据必须遵循特定的格式。 使用此部分了解有关接受的数据格式的详细信息。
导入项目文件格式
如果要 将项目导入 对话语言理解,请采用以下格式上传文件:
{
"projectFileVersion": "2022-10-01-preview",
"stringIndexType": "Utf16CodeUnit",
"metadata": {
"projectKind": "Conversation",
"projectName": "{PROJECT-NAME}",
"multilingual": true,
"description": "DESCRIPTION",
"language": "{LANGUAGE-CODE}",
"settings": {
"confidenceThreshold": 0
}
},
"assets": {
"projectKind": "Conversation",
"intents": [
{
"category": "intent1"
}
],
"entities": [
{
"category": "entity1",
"compositionSetting": "{COMPOSITION-SETTING}",
"list": {
"sublists": [
{
"listKey": "list1",
"synonyms": [
{
"language": "{LANGUAGE-CODE}",
"values": [
"{VALUES-FOR-LIST}"
]
}
]
}
]
},
"prebuilts": [
{
"category": "{PREBUILT-COMPONENTS}"
}
],
"regex": {
"expressions": [
{
"regexKey": "regex1",
"language": "{LANGUAGE-CODE}",
"regexPattern": "{REGEX-PATTERN}"
}
]
},
"requiredComponents": [
"{REQUIRED-COMPONENTS}"
]
}
],
"utterances": [
{
"text": "utterance1",
"intent": "intent1",
"language": "{LANGUAGE-CODE}",
"dataset": "{DATASET}",
"entities": [
{
"category": "ENTITY1",
"offset": 6,
"length": 4
}
]
}
]
}
}
| 密钥 | 占位符 | Value | 示例 |
|---|---|---|---|
{API-VERSION} |
要调用的 API 的版本。 | 2023-04-01 |
|
confidenceThreshold |
{CONFIDENCE-THRESHOLD} |
当意图被预测为None 意图时的阈值分数。 值的范围为 0 到 1。 |
0.7 |
projectName |
{PROJECT-NAME} |
项目名称。 此值区分大小写。 | EmailApp |
multilingual |
true |
一个布尔值,让你可以在数据集内使用多种语言的语句。 部署模型后,可以使用任何受支持的语言查询模型(不一定包含在训练文档中)。 有关支持的语言代码的详细信息,请参阅语言支持。 | true |
sublists |
[] |
包含子列表的数组。 每个子列表都包含一个键及其关联的值。 | [] |
compositionSetting |
{COMPOSITION-SETTING} |
定义如何在实体中管理多个组件的规则。 选项是 combineComponents 或 separateComponents。 |
combineComponents |
synonyms |
[] |
包含所有同义词的数组。 | 同义词 |
language |
{LANGUAGE-CODE} |
指定项目中所用语句、同义词和正则表达式的语言代码的字符串。 如果你的项目是多语言项目,请选择大多数语句的语言代码。 | en-us |
intents |
[] |
包含项目中所有意向的数组。 这些意向是从语句中分类的。 | [] |
entities |
[] |
包含项目中所有实体的数组。 这些实体是从语句中提取的。 可以在每个实体中定义其他可选组件:列表、预生成组件或正则表达式。 | [] |
dataset |
{DATASET} |
在训练之前拆分数据时,此话语所属的测试集。 若要详细了解数据拆分,请参阅训练对话语言理解模型。 此字段的可能值为 Train 和 Test. |
Train |
category |
|
与指定文本跨度关联的实体类型。 | Entity1 |
offset |
|
实体开头的非独占字符位置。 | 5 |
length |
|
实体的字符长度。 | 5 |
listKey |
|
在预测中要映射回的同义词列表的规范化值。 | Microsoft |
values |
{VALUES-FOR-LIST} |
完全匹配的、要提取并映射到列表键的字符串的逗号分隔列表。 | "msft", "microsoft", "MS" |
regexKey |
{REGEX-PATTERN} |
在预测中正则表达式要映射回的规范化值。 | ProductPattern1 |
regexPattern |
{REGEX-PATTERN} |
正则表达式。 | ^pre |
prebuilts |
{PREBUILT-COMPONENTS} |
可以提取常见类型的预生成组件。 有关可添加的预生成组件列表,请参阅支持的预生成实体组件。 | Quantity.Number |
requiredComponents |
{REQUIRED-COMPONENTS} |
一项设置,指定必须存在特定的组件才会返回实体。 有关详细信息,请参阅实体组件。 可能的值为 learned、regex、list 或 prebuilts。 |
"learned", "prebuilt" |
语句文件格式
对话语言理解提供了用于将语句直接上传到项目(而不是逐个键入语句)的选项。 可以在项目的数据标签页中找到此选项。
[
{
"text": "{Utterance-Text}",
"language": "{LANGUAGE-CODE}",
"dataset": "{DATASET}",
"intent": "{intent}",
"entities": [
{
"category": "{entity}",
"offset": 19,
"length": 10
}
]
},
{
"text": "{Utterance-Text}",
"language": "{LANGUAGE-CODE}",
"dataset": "{DATASET}",
"intent": "{intent}",
"entities": [
{
"category": "{entity}",
"offset": 20,
"length": 10
},
{
"category": "{entity}",
"offset": 31,
"length": 5
}
]
}
]
| 密钥 | 占位符 | Value | 示例 |
|---|---|---|---|
text |
{Utterance-Text} |
你的语句文本。 | Testing |
language |
{LANGUAGE-CODE} |
一个字符串,用于指定项目中所用语句的语言代码。 如果你的项目是多语言项目,请选择大多数语句的语言代码。 有关支持的语言代码的详细信息,请参阅语言支持。 | en-us |
dataset |
{DATASET} |
在训练之前拆分数据时,此话语所属的测试集。 若要详细了解数据拆分,请参阅训练对话语言理解模型。 此字段的可能值为 Train 和 Test. |
Train |
intent |
{intent} |
分配的意向。 | intent1 |
entity |
{entity} |
要提取的实体。 | entity1 |
category |
|
与指定文本跨度关联的实体类型。 | Entity1 |
offset |
|
文本开头的非独占字符位置。 | 0 |
length |
|
以 UTF16 字符表示的边界框长度。 训练仅考虑此区域的数据。 | 500 |