NLP【07】transformer原理、实现及如何与词向量做对接进行文本分类(附代码详解)
上一篇:NLP【06】RCNN原理及文本分類實戰(附代碼詳解)
下一篇:NLP【08】深度學習模型在NLP中的發展——從Word2vec到Bert的演變過程
完整代碼下載:https://github.com/ttjjlw/NLP/tree/main/Classify%E5%88%86%E7%B1%BB/rnn-cnn/tf1.x/models
一、前言
當前,bert橫行,而bert的基礎是transformer,自然,掌握transformer成為了基操。論文中的transformer是seq2seq模型,分為編碼和解碼,而在本文中,我所講的transformer主要是transformer中的attention,也就是利用transformer中的attention與位置編碼,替換cnn或者rnn部分完成文本分類。建議在看我這篇之前,先整體看一篇trnasformer的介紹,細節沒看明白的,再來瞧瞧我這篇。
二、transformer的簡單介紹
transformer分為encoder和decoder,這里主要講encoder的三部分Positional Encoding、multi-head attention以及殘差連接。Positional Encoding即位置編碼,也就是每個位置利用一個向量表示,具體公式如下:
這個公式怎么理解呢?pos就是詞的位置,2i或2i+1就是 詞向量的維度上的偶數或奇數的位置,舉個例子:定義一個長度為100的位置向量,位置向量的維度為64,那么最終這個位置向量pos_embs的shape即為(100,64),那么這個位置向量表怎么得到呢,就是通過上面的公式。具體就是pos_embs[pos][i%2==0]=sin()這一串,而pos_embs[pos][i%2==1]=cos()這一串。而pos取值是從0到99,i取值是從0到63。我想看到這,應該都明白了,如果沒明白,可以結合下面的代碼實現來理解。
第二部分就是multi-head attention,首先,對比一下以前self.attention的做法,在做文本分類時,lookup詞嵌入矩陣后,再經cnn或者rnn,會得到shape為(batch-size,seq_len,dim)的向量,記為M,然后我們是怎么做self.attention的呢?
1、先初始化一個可以訓練的權重,shape為(batch_size, dim,1),記為W?
2、然后M和W做矩陣相乘就的得到shape為(batch_size,seq_len)然后經softmax處理,就得到了每個詞的權重?
3、再把這個權重和原來的M做相乘(multiply),最后在seq_len的維度上做reduce_sum(),也就是output=reduce_sum(M,axis=1),則output的shape變為(batch-size,dim),也就是attention的最后輸出,以上省略了所有的reshape過程。
該過程實現可參考https://github.com/ttjjlw/NLP/blob/main/Classify%E5%88%86%E7%B1%BB/rnn-cnn/tf1.x/models/bilstmatten.py。那transformer中的self.attention又是怎么做的呢?
1、把M復制三份,命名為query,key,value
2、分別初始化三個矩陣q_w,k_w,v_w,然后query,keyvalue與對應的矩陣做矩陣相乘,得Q,K,V,此時三者的shape都為(batch_size,seq_len,dim)
3、如果head為1的話,那就是similarity=matmul(Q,K的轉置),所以similarity的shape為(batch_size,seq_len,seq_len),其這個矩陣記錄就是每個詞與所有詞的相似性
4、output=matmul(similarity,V),所以output 的shape為(batch_size,seq_len,dim)
第三部分殘差連接,殘差連接就簡單了:公式為 :H(x) = F(x) + x,這里就是H(x)=query+output,然后給H(x)進行層歸一化。
整個過程大概就是如此,其中省略些細節,如similarity的計算其實還要除于根號dim,防止softmax(similarity)后非0即1,不利于參數學習。舉個例子就明白了,softmax([1,10]) —>?[1.2339458e-04, 9.9987662e-01] 而 softmax([0.1,1.0]) —>?[0.2890505, 0.7109495]。
?三、代碼詳解
1、位置編碼
def _position_embedding(self):"""生成位置向量:return:"""batch_size = self.config["batch_size"]sequence_length = self.config["sequence_length"]embedding_size = self.config["embedding_size"]# 生成位置的索引,并擴張到batch中所有的樣本上position_index = tf.tile(tf.expand_dims(tf.range(sequence_length), 0), [batch_size, 1])position_embedding = np.zeros([sequence_length, embedding_size])for pos in range(sequence_length):for i in range(embedding_size):denominator = np.power(10000.0, i/ embedding_size)if i % 2 == 0:position_embedding[pos][i] = np.sin(pos / denominator)else:position_embedding[pos][i] = np.cos(pos / denominator)position_embedding = tf.cast(position_embedding, dtype=tf.float32)# 得到三維的矩陣[batchSize, sequenceLen, embeddingSize]embedded_position = tf.nn.embedding_lookup(position_embedding, position_index)return embedded_position?lookup后的詞向量與位置向量相加形成新的向量
embedded_words = tf.nn.embedding_lookup(embedding_w, self.inputs) embedded_position = self._position_embedding() embedded_representation = embedded_words + embedded_position?把添加了位置向量的詞向量,輸入到self._multihead_attention()中(該方法就是依次經過attention,殘差連接與層歸一化得到最終的向量,就是上面詳細介紹的2,3步過程),然后再經過self._feed_forward(), self._multihead_attention()與self._feed_forward()組成一層transformer
with tf.name_scope("transformer"):for i in range(self.config["num_blocks"]):with tf.name_scope("transformer-{}".format(i + 1)):with tf.name_scope("multi_head_atten"):# 維度[batch_size, sequence_length, embedding_size]multihead_atten = self._multihead_attention(inputs=self.inputs,queries=embedded_representation,keys=embedded_representation)with tf.name_scope("feed_forward"):# 維度[batch_size, sequence_length, embedding_size]embedded_representation = self._feed_forward(multihead_atten,[self.config["filters"],self.config["embedding_size"]])outputs = tf.reshape(embedded_representation,[-1, self.config["sequence_length"] * self.config["embedding_size"]])output_size = outputs.get_shape()[-1].value其中num_blocks就是設置要過幾層transformer,output就是最終的結果。
完整代碼下載:https://github.com/ttjjlw/NLP/tree/main/Classify%E5%88%86%E7%B1%BB/rnn-cnn/tf1.x/models
總結
以上是生活随笔為你收集整理的NLP【07】transformer原理、实现及如何与词向量做对接进行文本分类(附代码详解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 魅力化学 化学魅力
- 下一篇: @Resource注解