“此苹果非彼苹果”看意图识别的那些事儿
项目简介
“手把手带你学 NLP”是基于飞桨 PaddleNLP 的系列实战项目。本系列由百度多位资深工程师精心打造,提供了从词向量、预训练语言模型,到信息抽取、情感分析、文本问答、结构化数据问答、文本翻译、机器同传、对话系统等实践项目的全流程讲解,旨在帮助开发者更全面清晰地掌握百度飞桨框架在 NLP 领域的用法,并能够举一反三、灵活使用飞桨框架和 PaddleNLP 进行 NLP 深度学习实践。
6 月,百度飞桨 & 自然语言处理部携手推出了 12 节 NLP 视频课,课程中详细讲解了本实践项目。
观看课程回放请戳:https://aistudio.baidu.com/aistudio/course/introduce/24177
欢迎来课程 QQ 群(群号:758287592)交流吧~~
意图识别原来如此
意图识别是指分析用户的核心需求,输出与查询输入最相关的信息,例如在搜索中要找电影、查快递、市政办公等需求,这些需求在底层的检索策略会有很大的不同,错误的识别几乎可以确定找不到能满足用户需求的内容,导致产生非常差的用户体验;在对话过程中要准确理解对方所想表达的意思,这是具有很大挑战性的任务。
例如用户输入查询“仙剑奇侠传”时,我们知道“仙剑奇侠传”既有游戏又有电视剧还有新闻、图片等等,如果我们通过用户意图识别发现该用户是想看“仙剑奇侠传”电视剧的,那我们直接把电视剧作为结果返回给用户,就会节省用户的搜索点击次数,缩短搜索时间,大大提升使用体验。而在对话中如果对方说“我的苹果从不出现卡顿”,那么我们就能通过意图识别判断出此刻的苹果是一个电子设备,而非水果,这样对话就能顺利进行下去。
总之,意图识别的准确性能在很大程度上影响着搜索的准确性和对话系统的智能性。
本示例将展示如何使用 ERNIE 预训练模型完成任务型对话中的槽位填充和意图识别任务,这两个任务是一个 pipeline 型任务对话系统的基石。
本示例使用的数据集为 CrossWOC 中文对话数据集。该数据集包含多个领域,包括景点,餐馆,酒店,交通等。
快速实践
本项目基于飞桨 PaddleNLP 完成,记得给 PaddleNLP 点个小小的 Star⭐
开源不易,希望大家多多支持~
GitHub 地址:
https://github.com/PaddlePaddle/PaddleNLP
PaddleNLP 文档:
https://paddlenlp.readthedocs.io
与大多数 NLP 任务相同,本次示例的展示流程分为以下四步:
2.1 数据准备
数据准备流程如下:
1.使用 load_dataset()自定义数据集
使用官方脚本预处理过的数据集已经上传至 AI Studio 中此项目中(项目链接在文末),通过观察数据集格式,我们可以写出数据文件读取函数,传入 load_dataset()。即可创建数据集。
2.加载 paddlenlp.transformers.ErnieTokenizer 用于数据处理文本数据在输入 ERNIE 预训练模型之前,需要经过数据处理转化为 Feature。这一过程通常包括分词,token to id,add special token 等步骤。
PaddleNLP 对于各种预训练模型已经内置了相应的 tokenizer,指定想要使用的模型名字即可加载对应的 tokenizer。
可以通过调用 tokenizer 中的方法简单的完成上述数据处理。
3.调用 map()方法批量处理数据
由于我们传入了 lazy=False,所以我们使用 load_dataset()自定义的数据集是 MapDataset 对象。
MapDataset 是 paddle.io.Dataset 的功能增强版本。其内置的 map()方法适合用来进行批量数据集处理。
map()方法传入的是一个用于数据处理的 function。正好可以与 tokenizer 相配合。
4.Batchify 和数据读入
使用 paddle.io.BatchSampler 和 paddlenlp.data 中提供的方法把数据组成 batch。
然后使用 paddle.io.DataLoader 接口多线程异步加载数据。
Batchify 功能详解:
到这里数据集准备就全部完成了,下一步我们需要组网并设计 loss function。
2.2 模型结构
1.使用 PaddleNLP 一键加载预训练模型以下项目以 ERNIE 为例,介绍如何将预训练模型多任务学习同时完成意图识别和槽位填充任务。
本例中的意图识别和槽位填充本质上是一个句子分类任务和一个序列标注任务。将两者的 loss 结合即可实现多任务学习。
2.设计 loss functionJointErnie 模型会取出 ErnieModel 的 sequence_output 接入一个输出维度为槽位类别数的线性层得到 slot_logits,并将 pooled_output 接入一个输出维度为意图类别数的线性层得到 intent_logit。
所以本示例中的 loss 由 slot_loss 和 intent_loss 两部分组成,我们需要自己定义 loss function。
槽位填充相当于在每个 token 的位置进行一次多分类任务,意图识别相当于对整句话做一个多标签分类任务。所以设计的 loss function 如下:
选择网络结构后,我们需要设置 Fine-Tune 优化策略。
2.3 设置 Fine-Tune 优化策略
适用于 ERNIE/BERT 这类 Transformer 模型的学习率为 warmup 的动态学习率。
动态学习率示意图
现在万事俱备,我们可以开始训练模型。
2.4 模型训练与评估
模型训练的过程通常有以下步骤:
从 dataloader 中取出一个 batch data;将 batch data 喂给 model,做前向计算;将前向计算结果传给损失函数,计算 loss;loss 反向回传,更新梯度。重复以上步骤。每训练一个 epoch 后,程序对调用 evaluation()方法分别计算两个任务的 F1 score。
动手试一试
是不是觉得很有趣呀。小编强烈建议初学者参考上面的代码亲手敲一遍,因为只有这样,才能加深你对代码的理解呦。
本次项目对应的代码:
https://aistudio.baidu.com/aistudio/projectdetail/2017202
更多 PaddleNLP 信息,欢迎访问 GitHub 点 star 收藏后体验:
https://github.com/PaddlePaddle/PaddleNLP
百度 AI 开发者社区https://ai.baidu.com/forum ,为全国各地开发者提供一个交流、分享、答疑解惑的平台,让开发者在研发路上不再“孤军奋战”,通过不断地交流与探讨找出更好的技术解决方案。如果你想尝试各种人工智能技术、开拓应用场景,赶快加入百度 AI 社区,你对 AI 的所有畅想,在这里都可以实现!
扫描下方二维码,添加小助手微信「京东卡、小度定制周边、神秘礼盒、行李箱」等更多福利你来拿~
版权声明: 本文为 InfoQ 作者【百度大脑】的原创文章。
原文链接:【http://xie.infoq.cn/article/00287eb5cd290a20b2d1551af】。文章转载请联系作者。
评论