DSSM 代码解析

代码github地址:
数据输入:
with tf.name_scope('input'):
    # 预测时只用输入query即可,将其embedding为向量。
    query_batch = tf.placeholder(tf.int32, shape=[None, None], name='query_batch')
    doc_pos_batch = tf.placeholder(tf.int32, shape=[None, None], name='doc_positive_batch')
    doc_neg_batch = tf.placeholder(tf.int32, shape=[None, None], name='doc_negative_batch')
    query_seq_length = tf.placeholder(tf.int32, shape=[None], name='query_sequence_length')
    pos_seq_length = tf.placeholder(tf.int32, shape=[None], name='pos_seq_length')
    neg_seq_length = tf.placeholder(tf.int32, shape=[None], name='neg_sequence_length')
    on_train = tf.placeholder(tf.bool)
    drop_out_prob = tf.placeholder(tf.float32, name='drop_out_prob')

假设:batch_szie=10,一个正样本对应2条负样本

则query_batch的shape为(10,max_len)

doc_pos_batch的shape为(10,max_len)

doc_neg_batch 的shape为(20,max_len)

正负样本整合:

with tf.name_scope('Merge_Negative_Doc'):
    # 合并负样本,tile可选择是否扩展负样本。
    # doc_y = tf.tile(doc_positive_y, [1, 1])
    doc_y = tf.tile(doc_pos_rnn_output, [1, 1])

    for i in range(NEG):
        for j in range(query_BS):
            # slice(input_, begin, size)切片API
            # doc_y = tf.concat([doc_y, tf.slice(doc_negative_y, [j * NEG + i, 0], [1, -1])], 0)
            doc_y = tf.concat([doc_y, tf.slice(doc_neg_rnn_output, [j * NEG + i, 0], [1, -1])], 0)

原本 正样本为[+1,+2,+3,+4,...+10]

原本负样本为[-1,-1,-2,-2,-3,-3,...-10,-10]

整合后变成[+1,+2,+3,...+10,-1,-2,-3,...-10,-1,-2,-3,...-10]

计算相似性:
with tf.name_scope('Cosine_Similarity'):
    # Cosine similarity
    # query_norm = sqrt(sum(each x^2))
    query_norm = tf.tile(tf.sqrt(tf.reduce_sum(tf.square(query_rnn_output), 1, True)), [NEG + 1, 1])
    # doc_norm = sqrt(sum(each x^2))
    doc_norm = tf.sqrt(tf.reduce_sum(tf.square(doc_y), 1, True))

    prod = tf.reduce_sum(tf.multiply(tf.tile(query_rnn_output, [NEG + 1, 1]), doc_y), 1, True)
    norm_prod = tf.multiply(query_norm, doc_norm)

    # cos_sim_raw = query * doc / (||query|| * ||doc||)
    cos_sim_raw = tf.truediv(prod, norm_prod)
    # gamma = 20
    cos_sim = tf.transpose(tf.reshape(tf.transpose(cos_sim_raw), [NEG + 1, query_BS])) * 20

原本query为[q1,q2,q3,...,q10]

tf.tile后query为[q1,q2,q3,...q10,q1,q2,q3...,q10,q1,q2,q3...q10]

把扩充后的query与整合后的正负样本进行multiply

即[q1,q2,q3,...q10,q1,q2,q3...,q10,q1,q2,q3...q10]*[+1,+2,+3,...+10,-1,-2,-3,...-10,-1,-2,-3,...-10]结果为

[p1,p2,p3,...p10,n1,n2,n3,...n10,n1',n2',n3'...n10']

经reshape和transpose后得到最后的cos_sim=[[p1,n1,n1'],[p2,n2,n2'],....[p10,n10,n10']]

计算loss:

with tf.name_scope('Loss'):
    # Train Loss
    # 转化为softmax概率矩阵。
    prob = tf.nn.softmax(cos_sim)
    # 只取第一列,即正样本列概率。
    hit_prob = tf.slice(prob, [0, 0], [-1, 1])
    loss = -tf.reduce_sum(tf.log(hit_prob))
    tf.summary.scalar('loss', loss)

prob=[[+l1,-l1,-l1'],

          [+l2,-l2,-l2']

          ...

          [+l10,-l10,-l10']

         ]

然后最大化第一列,即正样本的概率(因为每一对正负样本概率总和为1,最大化正样本的概率,即就是最小化负样本的概率,也就是query越与正样本相似)

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值