郑州网站建设、,石家庄规划建设局网站,iis7如何部署网站,软件开发文档管理软件文章目录1 项目介绍1.1 背景知识介绍1.2 数据集介绍1.3 评价指标2 技术方案梳理2.1 模型目标2.2 模型介绍2.3 模型实现2.3.1 数据处理2.3.2 构建dataset2.3.3 模型定义2.3.4 训练相关参数2.3.5 训练结果3 项目总结1 项目介绍
1.1 背景知识介绍
对话系统按领域分类#xff0c…
文章目录1 项目介绍1.1 背景知识介绍1.2 数据集介绍1.3 评价指标2 技术方案梳理2.1 模型目标2.2 模型介绍2.3 模型实现2.3.1 数据处理2.3.2 构建dataset2.3.3 模型定义2.3.4 训练相关参数2.3.5 训练结果3 项目总结1 项目介绍
1.1 背景知识介绍
对话系统按领域分类分为任务型和闲聊型。闲聊型对话系统有Siri、微软小冰、小度等。它们实现可以以任意话题跟人聊天。任务型对话系统是以完成特定任务为目标的对话系统。例如可以以订机票为一个特定的任务实现的对话系统。我们这里重点关注任务型对话系统。
任务型对话系统分为语音识别、自然语言理解NLU、对话管理DM、自然语言生成NLG、语音合成几个部分。与NLP领域相关的是NLU、DM、NLG三个部分。本次报告详细描述的是NLU这个部分。
NLU是从用户输入的一句话中提取出领域、意图以及槽值三部分。通过领域识别和意图识别理解用户想要进行的操作。槽值填充能够提取与意图相关的关键词。例如一句话帮我订一张去北京的票。其领域是机票意图是订机票语义槽值有到达地北京。 NLU理解到的领域意图、槽值之后会给到DM模块进行后续处理。DM模块往往也业务是强相关的。目前大多数系统通过堆规则的方式实现可以借助有限状态机来实现。
领域识别和意图识别都是分类问题。槽值填充是序列标注问题。
1.2 数据集介绍
SMP2019 中文人机对话技术评测The Evaluation of Chinese Human-Computer Dialogue TechnologySMP2019-ECDT是由全国社会媒体处理大会Social Media ProcessingSMP主办的专注于以社会媒体处理为主题的科学研究与工程开发为传播社会媒体处理最新的学术研究与技术成果提供广泛的交流平台。
本次使用的数据集共包含 2579个数据对其中 2000个用于训练数据集579个用于验证数据集。
原始数据样例
原始数据是JSON结构。每条数据有文本、领域、意图还有对应的槽的名称、以及槽值。例如数据中文本请帮我打开uc领域app意图LAUNCH槽的名称name槽值uc。
1.3 评价指标
对于领域分类、意图识别我们采用准确率acc来评价对于语义槽填充我们通常采用F值来评价。对于domain当预测的值与标准答案相同时即为正确。对于intent来说当domain预测正确且intent的预测的值与标准答案相同时才为正确。对于slots来说我们采用F值作为评价指标当预测的slots的一个key-value组合都符合标准答案的一个key-value组合才为正确(domain和intent的也必须正确)。
为了综合考虑模型的能力我们通常采用句准确率sentence acc来衡量一句话领域分类、意图识别和语义槽填充的综合能力即以上三项结果全部正确时候才算正确其余均算错误。
在项目中我们将领域和意图一起识别使用准确率acc评价。对于语义槽使用句准确率评价。在计算句准确率的时候没有考虑领域、意图的准确率。
2 技术方案梳理
2.1 模型目标
通常来说实现一个对话系统中的 NLU 任务要分三步第一步领域识别第二步意图识别 第三步槽值填充。如果不考虑未来系统中领域的扩展我们可以将第一步和第二步合并起来那么合并之后就有两步要做第一步意图识别第二步槽值填充“三步并作两步”。我们的目标是进一步提高效率同时完成意图识别和槽值填充这两个步骤“两步合成一步”。具体模型介绍参考论文参考《BERT for Joint Intent Classifification and Slot Filling》。
2.2 模型介绍 本次模型使用BERTCRF完成NLU任务。BERT具体使用chinese-roberta-wwm-ext预训练模型。 BERT是一个机遇Transfer模型的多层双向self-attention Transformer 编码器结构。其输入部分由token embedding词嵌入向量、segment embedding句子编码向量以及position embedding位置编码向量三部分组成。这三部分相加组成了最终的BERT输入向量。 BERT使用Word Piece方式分词。对于中文而言基本相当于单字分词。 本次任务的数据是单句分类。输入格式[CLS] 句子[SEP]。 BERT模型输出层CLS所对应的token被认为是代表了句子的向量。我们使用CLS的token进行领域-意图识别。每个单词对应的Token代表了这个单词用于槽值分类。 BERT是一种预训练模型。在BERT的输出层加一层线性层对CLS token计算得到该句子在各个分类上的概率。
对于槽值分类我们使用BIO标记法。例如
012345678CLS请帮我打开ucSEPOOOOOOB-nameI-nameO
在BERT的输出层加一层线性层计算各个词在所有槽值类型上的概率。一般来说这样也可以实现。但是BERT不能很好地捕捉时序之间的关系。如果能将这一步的输出作为输入送入CRF模型中CRF模型将能很好地学习到标签的依赖关系。所以对于槽值分类将使用BERT线性层CRF的结构。 第一部分是标签依赖关系是CRF学到的。第二部分是每个位置属于槽值分类的概率由BERT线性层模型学习。
2.3 模型实现
2.3.1 数据处理
需要将JSON格式的文件处理为后面方便读取的格式applaunch 请帮我打开uc o o o o o b-name i-name 此外将数据集分为训练集和验证集数据量分别为2000、579。 提取出所有的领域-意图标签。 提取出所有的槽值标签。 这样就得到了train.tsv,test.tsv,cls_vocab,slot_vocab。在数据使用过程中会将标签数据都转小写。
train.tsv,test.tsv部分数据展示
cls_vocab部分数据展示 slot_vocab部分数据展示
2.3.2 构建dataset
按照2.2分析的模型构建数据集使用[pad]做batch对齐。这里需要说明的是使用了pin_memory可以在数据从CPU搬移到GPU的过程中继续做其他事情。
class PinnedBatch:def __init__(self, data):self.data datadef __getitem__(self, k):return self.data[k]def pin_memory(self):for k in self.data.keys():self.data[k] self.data[k].pin_memory()return self2.3.3 模型定义
模型定义基于BertPreTrainedModel使用BERT预训练模型。
class NLUModule(BertPreTrainedModel):def __init__(self, config):super().__init__(config)self.num_intent_labels config.num_intent_labelsself.num_slot_labels config.num_slot_labelsself.use_crf config.use_crfself.bert BertModel(config)self.dropout nn.Dropout(config.hidden_dropout_prob)self.intent_classifier nn.Linear(config.hidden_size, config.num_intent_labels)self.slot_classifier nn.Linear(config.hidden_size, config.num_slot_labels)self.crf CRF(num_tagsconfig.num_slot_labels, batch_firstTrue)self.init_weights()def forward(self,input_idsNone,attention_maskNone,token_type_idsNone,position_idsNone,head_maskNone,inputs_embedsNone,output_attentionsNone,output_hidden_statesNone,slot_labelsNone):rlabels (:obj:torch.LongTensor of shape :obj:(batch_size,), optional):Labels for computing the sequence classification/regression loss.Indices should be in :obj:[0, ..., config.num_labels - 1].If :obj:config.num_labels 1 a regression loss is computed (Mean-Square loss),If :obj:config.num_labels 1 a classification loss is computed (Cross-Entropy).outputs self.bert(input_ids,attention_maskattention_mask,token_type_idstoken_type_ids,position_idsposition_ids,head_maskhead_mask,inputs_embedsinputs_embeds,output_attentionsoutput_attentions,output_hidden_statesoutput_hidden_states,)pooled_output outputs[1]seq_encoding outputs[0]pooled_output self.dropout(pooled_output)intent_logits self.intent_classifier(pooled_output)slot_logits self.slot_classifier(seq_encoding)if self.use_crf and slot_labels is not None:crf_loss self.crf(slot_logits, slot_labels, maskattention_mask.byte(), reductionmean)crf_loss -1 * crf_loss # negative log-likelihoodreturn intent_logits, slot_logits, crf_losselse:return intent_logits, slot_logits, None2.3.4 训练相关参数
优化方式。优化方式使用Admwarm up的方式。初始学习率8e-6warmup200。
loss计算。使用交叉熵损失mean计算loss。在计算槽值损失的时候要去掉mask的部分。当使用CRF层的时候槽值损失就是CRF计算得到的损失。在计算总的损失的时候是将领域-意图损失槽值损失。也可以为他们分配不同的比例。在项目中发现如果不加CRF层需要调整比例模型才能学到更好的槽值分类。
使用batch_split使用时间换空间策略。有时候我们的GPU内存不够大每一个batch的数量不能很大本项目中是30这个时候可以多做几次前向传播再做一次梯度更新。用更多的数据可以让梯度更新的值更准确收敛得更快。
本项目中训练了30轮。每训练40步做一次验证。
2.3.5 训练结果
intent_loss0.00402, intent_acc1, slot_loss0.0344, slot_acc1 dev_intent_loss 0.2449, dev_slot_loss 0.0817, dev_intent_acc 0.9430, dev_slot_acc 0.8325
在本项目中也做不了加CRF的训练。dev_intent_acc0.9309dev_slot_acc0.8083。能够看出添加CRF对于槽值分类提高了2个百分点。
3 项目总结
NLU不但可以用在对话系统中同样也可以用于知识图谱搜索中。当识别到用户的意图和槽值之后可以使用固定的搜索模板填充槽值返回搜索结果。 本项目已经上传到git。框架代码来源于silverriver。CRF部分参考monologg。