多轮对话-2020:DialoGPT【生成式多轮对话模型】

语料简介
这里简单介绍一下LCCC这个数据集(Large-scale) , 具体细节大家可以去上看 , 下载链接也在上面 。LCCC分base和large两个版本 , base主要是来源于微博对话 , large则是在base的基础上融合了其他开源对话语料 , 按照作者的说法 , LCCC经过了严格的清洗过程 , 所以整体质量看上去还是很不错的 。
为了简化任务 , 所有样本都被处理成双人对话 。下面是一些样本示例:
A: 等过年咱们回去买点兔头好好吃顿火锅B: 太原就没看见有好吃的兔头A: 我从虹桥给你带个回去那天瞅到一正宗的B: 最爱你了A: 那是必须A: 嗯嗯 , 我再等等!你现在在上海吧?上海风好像比南京还大呢 , 少出门吧B: 对啊 , 我在家 , 没事儿 。一定要小心啊!A: 我去年也去转了一圈 , 还碰见以前的体育老师了 , 合了个影B: 哈哈我还去找高一时侯的英语老师没找到她刚好有事情没在学校~A: 你也是真心找回忆了哦B: 哈哈毕业了没去过想去看看啊
模型设计
知道了数据长什么样之后 , 我们接下来就要去设计模型了 。显然 , 我们需要做的就是训练一个模型 , 预测下一个该回复什么 。既然语料里包含了多轮对话 , 那么我们还要求这个模型支持多轮对话 。考虑对话历史的最简单的方式 , 就是把直到当前句的所有历史对话都拼接成单句文本 , 来作为模型的输入信息 。
给定一些输入 , 预测一个输出 , 从形式上来看我们应该用模型 。直接用其实问题也不大 , 但标准的一般用于形式比较固定的输入输出 , 比如输入的文本长度应该是集中在某个范围内 , 不宜变化太大 , 但考虑多轮对话的话 , 理论上我们也不知道前面有多少轮对话 , 因此原则上输入文本长度是无限制的 。用的话 , 还有训练效率低的问题 , 就是我们每轮对话每次我们只能训练一句回复 , 如果一个多轮对话有n句回复 , 那么就要拆分为n个样本来训练了 。
因此 , 我们需要一个长度能相当自由地变化的、同时能预测整个多轮对话的模型 , 实现这个需求的比较适当的选择就是单向语言模型(LM、GPT) , 做法如下图:
如图所示 , 我们选择当前主流的模型 , 按照BERT的常规输入格式 , 将每句对话用[SEP]拼接起来 , 然后就训练一个从左往右的单向语言模型 。为了区分不同的说话角色 , 我们对不同的说话者用不同的 Id区分 。此外 , 考虑到BERT和GPT都是用了绝对位置编码 , 可处理的文本长度存在一个上限 , 而对话轮数理论上是无限的 , 所以这里我们采用了相对位置编码的NEZHA作为基本结构 , 并使用NEZHA的预训练权重作为模型的初始化权重 。
说白了 , 就是往NEZHA里边加入了下三角形式的 Mask , 使其变为一个语言模型 , 相关介绍请参考《从语言模型到:如戏 , 全靠Mask》[1] 。
训练细节
首先 , 给出笔者的参考实现以及训练好的模型:
代码基于实现 , 基本结构是NEZHA Base 。为了使得训练更加“平民化” , 笔者只用了一张卡(22G的RTX)配合梯度累积来训练 , 显存不够大的读者可以缩小 。开源的模型是用
的学习率、0.01的权重衰减率的Adam优化器进行训练的 , 训练了1000万步(20多天) , 单步为16 , 累积梯度步数为16 , 所以相当于以256的训练了62.5万步 , 最终的loss大概是2.83(平均每个token的交叉熵) 。