孪生网络图像相似度_文本蕴含之孪生网络(Siamese Network)
最近一直在分享自然語言推理和文本蘊含的相關論文,并且之前已經分享過三篇,分別是bilateral multi-perspective matching (BiMPM)模型、Enhanced Sequential Inference Model(ESIM)模型和Densely Interactive Inference Network(DIIN)模型。這次分享一下最經典的文本蘊含模型,也就是孿生網絡(Siamese Network)。
劉聰NLP:論文閱讀筆記:文本蘊含之BiMPM?zhuanlan.zhihu.com劉聰NLP:論文閱讀筆記:文本蘊含之ESIM?zhuanlan.zhihu.com劉聰NLP:論文閱讀筆記:文本蘊含之DIIN?zhuanlan.zhihu.com一、背景介紹
孿生網絡一開始提出是在圖像識別領域(例如人臉識別),來求解兩張圖片(兩張人臉圖像)相似度,判斷兩張圖片是否相似。如下圖所示1,輸入兩張圖片,將兩張圖片經過同一個卷積神經網絡,得到每張圖片的向量表示,最后求解兩個向量的編輯距離(可以是余弦距離,歐式距離,等等),根據得到的編輯距離判斷兩張圖片是否相似。
孿生網絡原文鏈接?www.cs.utoronto.ca那么從哪里體現出孿生網絡的“孿生”二字呢?從圖1中,我們可以看到,其實每張圖片是經過了各自的卷積神經網絡,但是兩個卷積神經網絡的所有權值(所有參數)都是共享的,這就像一對雙胞胎一樣,因此我們管這種權值共享的網絡稱之為孿生網絡。而權值共享的目的有兩個:(1)減少參數量,減小模型的復雜度;(2)將兩個不同空間維度的向量映射到同一個空間維度上,使其數據分布保持一致,在同一空間維度上對不同向量進行編碼。
圖1 基于孿生網絡的圖像相似度求解圖二、孿生網絡在文本蘊含中的使用
在機器學習中,很多算法在圖像和自然語言處理兩個領域是可以互通的(可以相互借鑒的)。根據上一節的描述,我們可以看出,該任務和我們文本蘊含任務很像;都是輸入兩個不同的特征向量,最后判斷兩個特征向量之間的關系。如圖2所示,我們將孿生網絡應用在文本蘊含領域。
圖2 文本蘊含之孿生網絡主要包含四層:詞表示層(Embedding Layer)、編碼層(Encoder Layer)、融合層(Aggregated Layer)和預測層(Predict Layer)。
下面通過代碼詳細介紹:
首先定義模型固定參數和其輸入,其中forward()函數包含上文所提到的四層。
class SIAMESE(object):def __int__(self, config, word_embedding_matrix=None):self.word_embedding_dim = config.word_dimself.rnn_hidden_size = config.rnn_hidden_sizeself.fine_tune_embedding = config.fine_tune_embeddingself.num_sentence_words = config.max_length_contentself.learning_rate = config.learning_rateself.rnn_layers = config.rnn_layerswith tf.variable_scope("input"):self.sentence_one_word = tf.placeholder(tf.int32, [None, self.num_sentence_words], name="sentence_one_word")self.sentence_two_word = tf.placeholder(tf.int32, [None, self.num_sentence_words], name="sentence_two_word")self.y_true = tf.placeholder(tf.int32, [None, 2], name="true_labels")self.is_train = tf.placeholder(tf.bool, [], name="is_train")self.dropout_rate = tf.cond(self.is_train, lambda: config.dropout_rate, lambda: 0.0)self.word_mat = tf.get_variable("word_mat", initializer=tf.constant(word_embedding_matrix, dtype=tf.float32), trainabel=self.fine_tune_embedding)self.forward()1、詞表示層(Embedding Layer)
在這一層中,我們將在句子P和句子Q中的每個詞映射成一個d維的向量,這d維的向量由word embedding組成,word embedding來自提前預訓練好的詞向量。
with tf.variable_scope("embedding_layer"):word_embedded_sentence_one = tf.nn.embedding_lookup(self.word_mat, self.sentence_one_word)word_embedded_sentence_two = tf.nn.embedding_lookup(self.word_mat, self.sentence_two_word)2、編碼層(Encoder Layer)
在這一層中,我們對上一層得到的詞表示向量進行上下文編碼,使用一個雙向LSTM(權值共享)分別編碼前提句和假設句的詞表示向量,得到其上下文表征向量。
由于使用多層動態雙向LSTM,因此首先獲取每個句子的實際長度;
with tf.variable_scope("get_length_layer"):self.batch_size = tf.shape(self.sentence_one_word)[0]self.sentence_one_wordlevel_mask = tf.sign(self.sentence_one_word, name="sentence_one_wordlevel_mask")self.sentence_two_wordlevel_mask = tf.sign(self.sentence_two_word, name="sentence_two_wordlevel_mask")self.sentence_one_len = tf.reduce_sum(self.sentence_one_wordlevel_mask,1)self.sentence_two_len = tf.reduce_sum(self.sentence_two_wordlevel_mask,1)然后對其編碼,得到雙向LSTM最后一個time step作為是該句子的句子表征向量;
with tf.variable_scope("sequence_encoder_layer"):one_fw_outputs, one_bw_outputs = self.my_bilstm(inputs=word_embedded_sentence_one,dropout=self.dropout_rate,n_layers=self.rnn_layers,scope="bilstm",sequence_length=self.sentence_one_len,hidden_units=self.rnn_hidden_size)two_fw_outputs, two_bw_outputs = self.my_bilstm(inputs=word_embedded_sentence_two,dropout=self.dropout_rate,n_layers=self.rnn_layers,scope="bilstm",sequence_length=self.sentence_two_len,hidden_units=self.rnn_hidden_size,reuse=True)last_one_fw_output = self.last_relevant_output(one_fw_outputs, self.sentence_one_len)last_one_bw_output = self.last_relevant_output(one_bw_outputs, self.sentence_one_len)last_one_output = tf.concat([last_one_fw_output, last_one_bw_output], axis=-1)last_two_fw_output = self.get_last_output(two_fw_outputs, self.sentence_two_len)last_two_bw_output = self.get_last_output(two_bw_outputs, self.sentence_ontwo_len)last_two_output = tf.concat([last_two_fw_output, last_two_bw_output], axis=-1)多層動態雙向LSTM代碼如下:
def my_bilstn(self, inputs, dropout, n_layers, scope, sequence_length, hidden_size, reuse=None):with tf.variable_scope("fw"+scope, reuse=reuse):stacked_rnn_fw = []for _ in range(n_layers):fw_cell = LSTMCell(hidden_size)lstm_fw_cell = DropoutWrapper(fw_cell, output_keep_prob=1-dropout)stacked_rnn_fw.append(lstm_fw_cell)lstm_fw_cell_m = tf.nn.rnn_cell.MultiRNNCell(cells=stacked_rnn_fw, state_is_tuple=True)with tf.variable_scope("bw"+scope, reuse=reuse):stacked_rnn_bw = []for _ in range(n_layers):bw_cell = LSTMCell(hidden_size)lstm_bw_cell = DropoutWrapper(bw_cell, output_keep_prob=1-dropout)stacked_rnn_bw.append(lstm_bw_cell)lstm_bw_cell_m = tf.nn.rnn_cell.MultiRNNCell(cells=stacked_rnn_bw, state_is_tuple=True) with tf.variable_scope(scope, reuse=reuse):(fw_outputs, bw_outputs), _ = tf.nn.bidirectional_dynamic_rnn(cell_fw=lstm_fw_cell_m,cell_bw=lstm_bw_cell_m,inputs=inputs,sequence_length=sequence_length,dtype=tf.float32)return fw_outputs, bw_outputs獲取動態雙向LSTM最后一個time step向量代碼如下:
def get_last_output(self, output, sequence_length):with tf.name_scope("get_last_output"):batch_size = tf.shape(output)[0]max_length = tf.shape(output)[-2]out_size = int(output.get_shape()[-1])index = tf.range(0, batch_size)*max_length + (sequence_length-1)flat = tf.reshape(output, [-1, out_size])last_output = tf.gather(flat, index)return last_output3、融合層(Aggregated Layer)和預測層(Predict Layer)
在這一層中,我們將上文得到的兩個句子的句子表征向量進行拼接([P,H,P*H,P-H]),然后通過兩個全連接層去預測,兩個句子是否存在蘊含關系。
with tf.variable_scope("output_layer"):aggregated_representation = tf.concat([last_one_output, last_two_output, last_one_output*last_two_output, last_one_output-last_two_output], axis=-1)predict_one_layer = tf.layers.dense(aggregated_representation,units=aggregated_representation.get_shape().as_list()[1],activation=tf.nn.tanh,name="predict_one_layer")d_predict_one_layer = tf.layers.dropout(predict_one_layer, rate=self.dropout_rate, training=self.is_train, name="predict_one_layer_dropout")self.predict_two_layer = tf.layers.dense(d_predict_one_layer, units=2, name="predict_two_layer")self.y_pred = tf.nn.softmax(self.predict_two_layer, name="scores")self.predictions = tf.arg_max(self.y_pred, axis=1, name="predictions")三、總結
本人認為,孿生網絡的精髓就是兩個編碼器的參數共享,而孿生網絡做文本蘊含應該是文本蘊含的開端;像是BiMPM、DIIN和ESIM,都是孿生網絡的改進版,對其編碼后的句子向量不是做簡單的拼接,而是對其進行注意力提取和句子信息交互,使其結果更好。
以上就是我對孿生網絡的理解,如果有不對的地方,請大家見諒并多多指教。
總結
以上是生活随笔為你收集整理的孪生网络图像相似度_文本蕴含之孪生网络(Siamese Network)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Castle
- 下一篇: Datawhale-零基础入门NLP-新