Transformer for Co-Reference

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预测,效果见【多轮对话举例】
Nevermore Written by:

步步生姿,空锁满庭花雨。胜将娇花比。