关于人工智能:此苹果非彼苹果看意图识别的那些事儿

34次阅读

共计 4062 个字符,预计需要花费 11 分钟才能阅读完成。

我的项目简介

“手把手带你学 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/PaddlePadd…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 联合即可实现多任务学习。

    from src.models import JointErnie
    model = JointErnie.from_pretrained( 'ernie-1.0' , 
                               intent_dim=len(intent2id), 
                               slot_dim=len(slot2id), 
                               dropout=0.1, 
                               use_history=use_history)

2. 设计 loss function
JointErnie 模型会取出 ErnieModel 的 sequence_output 接入一个输入维度为槽位类别数的线性层失去 slot_logits,并将 pooled_output 接入一个输入维度为用意类别数的线性层失去 intent_logit。

所以本示例中的 loss 由 slot_loss 和 intent_loss 两局部组成,咱们须要本人定义 loss function。

槽位填充相当于在每个 token 的地位进行一次多分类工作,用意辨认相当于对整句话做一个多标签分类工作。所以设计的 loss function 如下:

# 结构损失函数
class NLULoss(paddle.nn.Layer):
def __init__(self, pos_weight):
    super(NLULoss, self).__init__()

    self.intent_loss_fn = paddle.nn.BCEWithLogitsLoss(pos_weight=paddle.to_tensor(pos_weight))
    self.slot_loss_fct = paddle.nn.CrossEntropyLoss()

def forward(self, logits, slot_labels, intent_labels):
    slot_logits, intent_logits = logits

    slot_loss = self.slot_loss_fct(slot_logits, slot_labels)
    intent_loss = self.intent_loss_fn(intent_logits, intent_labels)

    return slot_loss + intent_loss

抉择网络结构后,咱们须要设置 Fine-Tune 优化策略。

2.3 设置 Fine-Tune 优化策略

实用于 ERNIE/BERT 这类 Transformer 模型的学习率为 warmup 的动静学习率。

动静学习率示意图

# 训练过程中的最大学习率
learning_rate = 3e-5 
# 训练轮次
epochs = 10
# 学习率预热比例
warmup_proportion = 0.0
# 权重衰减系数,相似模型正则项策略,防止模型过拟合
weight_decay = 0.0
max_grad_norm = 1.0
num_training_steps = len(train_data_loader) * epochs
# 学习率衰减策略
lr_scheduler = paddlenlp.transformers.LinearDecayWithWarmup(learning_rate, num_training_steps,warmup_proportion)

decay_params = [p.name for n, p in model.named_parameters()
    if not any(nd in n for nd in ["bias", "norm"])
]
# 定义优化器
optimizer = paddle.optimizer.AdamW(
learning_rate=lr_scheduler,
parameters=model.parameters(),
weight_decay=weight_decay,
apply_decay_param_fun=lambda x: x in decay_params,
grad_clip=paddle.nn.ClipGradByGlobalNorm(max_grad_norm))

当初万事俱备,咱们能够开始训练模型。

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 的所有畅想,在这里都能够实现!

扫描下方二维码,增加小助手微信「京东卡、小度定制周边、神秘礼盒、行李箱」等更多福利你来拿~

正文完
 0