首先是得到句子对应的双向的lstm后的表示,在这里,首先使用embedding_lookup函数找到句子中对应分词的embedding,在将分词list扔进前后向的lstm中,分别得到前向和后向的编码,再使用tf.nn.bidirectional_dynamic_rnn将前后向lstm编码的输出与分词list输入,输出是一个tuple(outputs, output_states),将输出的output_states的第二维进行concat,作为bilstm刷过后的输出;
两句话经过bilstm后,需要提取语义融合特征,语义融合特征有两种计算方式,分别是multiply和additive,multiply方式,是降过了bilstm后的两个句子的输出分别相乘;additive的方式,则是使用dense层将过了bilstm后的输出两个句子的输出先缩放到同一个维度,相加,最后加上偏置b进行激活;
在计算出了语义融合特征后,可以进一步融合数据挖掘特征;
在挖掘了两句话经过bilstm后的特征,并且引入了数据挖掘特征后,使用全连接层来对得到的特征进行降维,该部分的代码如下:
def inference_bilstm(self):
# 1.feature:bilstm
x1=self.bi_lstm(self.input_x1,1) # [batch_size,hidden_size*2]
x2=self.bi_lstm(self.input_x2,2) # [batch_size,hidden_size*2]
if self.similiarity_strategy == 'multiply':
print("similiarity strategy:", self.similiarity_strategy)
x1=tf.layers.dense(x1,self.hidden_size*2) # [None, hidden_size]
h_bilstm=tf.multiply(x1,x2) # [None,number_filters_total]
elif self.similiarity_strategy == 'additive':
print("similiarity strategy:",self.similiarity_strategy)
h_bilstm=self.additive_attention(x1,x2,self.hidden_size,"bilstm_attention")
# 2.feature:data mining feature
h_bluescore= tf.layers.dense(self.input_bluescores, self.hidden_size/2, use_bias=True)
h_bluescore= tf.nn.relu(h_bluescore)
# 3.concat feature
h = tf.concat([h_bilstm, h_bluescore], axis=1)
# 4.fully connected layer
h = tf.layers.dense(h, self.hidden_size, activation=tf.nn.relu, use_bias=True)
h = tf.nn.dropout(h, keep_prob=self.dropout_keep_prob)
with tf.name_scope("output"):
logits = tf.layers.dense(h, self.num_classes, use_bias=False)
return logits
2. 基于cnn的句子相似度计算模型
基于CNN的句子相似度计算模型和基于LSTM的相似,大体框架都是两个句子左右分别过一个计算模型,得到输出表示,计算其融合的语义特征,再与数据挖掘特征进行concat。这里有一点,就是代码里面用的是tf的conv2d来对序列建模的,但是因为在处理数据的时候,是[batch_size,sequence_length,embedding_size],expand_dim后就变成四维的了,当然必须指定是在哪一维上来进行expand。在经过了conv2d刷过一遍后,再计算其融合语义,也就是看和上文中一样使用additive的方式交互语义,该部分代码如下:
def inference_cnn(self):
"""main computation graph here: 1.get feature of input1 and input2; 2.multiplication; 3.linear classifier"""
# 1.feature: data mining features
h_bluescore = tf.layers.dense(self.input_bluescores, self.hidden_size / 2, use_bias=True)
h_bluescore = tf.nn.relu(h_bluescore)
# 2.featuere2: cnn features
x1 = self.conv_layers(self.input_x1, 1) # [None,num_filters_total]
x2 = self.conv_layers(self.input_x2, 1, reuse_flag=True) # [None,num_filters_total]
h_cnn = self.additive_attention(x1, x2, self.hidden_size / 2, "cnn_attention")
# 4.concat feature
h = tf.concat([h_cnn, h_bluescore], axis=1)
# 5.fully connected layer
h = tf.layers.dense(h, self.hidden_size, activation=tf.nn.relu, use_bias=True)
h = tf.nn.dropout(h, keep_prob=self.dropout_keep_prob)
# h,self.update_ema=self.batchnorm(h,self.tst, self.iter, self.b1)
with tf.name_scope("output"):
logits = tf.layers.dense(h, self.num_classes, use_bias=False)
self.update_ema = h # TODO need remove
return logits