Transformer for Co-Reference
近期研究图谱问答并完成商业落地,接触到三个常用于图谱问答中的任务
- 指代消解:常用于多轮问答,本期文章讨论
- 信息抽取:从文本中抽取三元关系
- 实体消歧
由于在多轮对话中频繁出现代词,零指代词,会极大影响主任务模型的效果,使模型很难理解真正的意图
多轮对话样本中统计
对话中出现代词比例33.5%,零指代词比例52.4%
多轮对话举例
天气
对话1:北京今天天气怎么样
对话2:晴天
对话3:那明天呢
真实意图:那明天天气怎么样呢
电影
对话1:你有么有看过约会之夜啊
对话2:没有约会之夜谁演的
对话3:盖尔加朵
对话4:盖尔加朵1984年出生和我姐一样大
对话5:电影评分84看吗
真实意图:电影约会之夜评分84看吗
模型结构
Embedding
在原始Transformer结构上增加对话轮次特征
- w_i :n轮对话中的字(中文)
- WE:word embedding
- PE:position embedding
- TE:turn embedding
I(w_i) = WE(w_i) + PE(w_i) + TE(w_i)
Encode
使用Pre-Norm Transformer
因为接入蒸馏,所以在Transformer encode最后一层输出向量后接入fc,放大缩小特征长度
Decode
使用Pre-Norm Transformer
Pointer Network
Pointer Network论文,使用矩阵变换代替循环
with tf.compat.v1.variable_scope("pointer", reuse=tf.compat.v1.AUTO_REUSE):
last_enc_output = tf.layers.dense(
enc_output, args.d_model, use_bias=False, kernel_initializer=self.initializer) # bsz slen dim
last_enc_output = tf.expand_dims(
last_enc_output, 0) # 1 bsz slen dim
dec_output_trans = tf.transpose(
dec_output, [1, 0, 2]) # tlen bsz dim
dec_output_trans = tf.layers.dense(dec_output_trans, args.d_model, kernel_initializer=self.initializer,
use_bias=False, name="pointer_decode", reuse=tf.compat.v1.AUTO_REUSE) # tlen bsz dim
dec_output_trans = tf.expand_dims(
dec_output_trans, 2) # tlen bsz 1 dim
attn_encode = tf.nn.tanh(
dec_output_trans + last_enc_output) # tlen bsz slen dim
attn_encode = tf.layers.dense(attn_encode, 1, kernel_initializer=self.initializer,
use_bias=False, name="pointer_v", reuse=tf.compat.v1.AUTO_REUSE) # tlen bsz slen 1
attn_encode = tf.transpose(tf.squeeze(attn_encode, 3), [
1, 0, 2]) # bsz tlen slen
distributes = tf.nn.log_softmax(attn_encode, axis=-1)+1e-9
Distillation
蒸馏可以很好的利用预训练模型在大数量级样本中训练后的权重,更好的使学生模型理解语义,提升最终效果
Loss = MSE(f_bert(I(w_i) ),f_linear(f_encode(I(w_i)))
def distillation(self, enc_output, dist_encode):
args = self.args
with tf.compat.v1.variable_scope("distillation", reuse=tf.compat.v1.AUTO_REUSE):
enc_output = tf.layers.dense(
enc_output, args.dist_model, kernel_initializer=self.initializer)
distill_loss = tf.losses.mean_squared_error(
dist_encode, enc_output)
enc_output = tf.layers.dense(
enc_output, args.d_model, kernel_initializer=self.initializer)
return enc_output, distill_loss
训练流程
- 启用预训练,使encode输出分布尽量拟合BERT输出
效果
- 验证数据集中准确率96%,rouge-l分数93.3%
- 使用Beam Search预测,效果见【多轮对话举例】