Attention 扫盲:注意力机制及其 PyTorch 应用实现
點擊上方“MLNLP”,選擇“星標”公眾號
重磅干貨,第一時間送達
來自 |?知乎
作者 |?Lucas
地址 | https://zhuanlan.zhihu.com/p/88376673
專欄?| 深度學習與情感計算
編輯?|?機器學習算法與自然語言處理
Attention 掃盲:注意力機制及其 PyTorch 應用實現
仿生人腦注意力模型->計算資源分配
深度學習attention 機制是對人類視覺注意力機制的仿生,本質上是一種資源分配機制。生理原理就是人類視覺注意力能夠以高分辨率接收于圖片上的某個區域,并且以低分辨率感知其周邊區域,并且視點能夠隨著時間而改變。換而言之,就是人眼通過快速掃描全局圖像,找到需要關注的目標區域,然后對這個區域分配更多注意,目的在于獲取更多細節信息和抑制其他無用信息。提高 representation 的高效性。例如,對于下面一張圖,我的主要關注點就在于中間的 icon 和 ATTENTION 文字,對于邊框上的條紋就不太關注,而且看一眼還有點暈。
Encoder-Decoder框架==sequence to sequence 條件生成框架
Encoder-Decoder框架,也被稱為 sequence to sequence 條件生成框架[1],是一種文本處理領域的研究模式。常規的 encoder-decoder方法,第一步,將輸入句子序列 X通過神經網絡編碼為固定長度的上下文向量C,也就是文本的語義表示;第二步,由另外一個神經網絡作為解碼器根據當前已經預測出來的詞記憶編碼后的上下文向量 C,來預測目標詞序列,過程中編碼器和解碼器的 RNN 是聯合訓練的,但是監督信息只出現在解碼器 RNN 一端,梯度隨著反向傳播到編碼器 RNN 一端。使用 LSTM 進行文本建模時當前流行的有效方法[2]。
attention 機制的最典型應用是統計機器翻譯。給定任務,輸入是“Echt”, “Dicke” and “Kiste”進 encoder,使用 rnn 表示文本為固定長度向量 h3。但問題就在于,當前 decoder 生成 y1 時僅僅依賴于最后一個隱層狀態h3,也就是 sentence_embedding。那么這個 h3 必須 encode 輸入句子中的全部信息才行。可實際上,傳統Encoder-Decoder模型并不能達到這個功能。那 LSTM [3]不就是用來解決長期依賴信息問題的嘛?但事實上,長短期記憶網絡仍然存在問題。我們說,RNN在長期信息訪問當前處理單元之前,需要按順序地通過所有之前的單元。這意味著它很容易遭遇梯度消失問題。然后引入 LSTM,使用門控某種程度上解決這個問題。的確,LSTM、GRU 和其變體能學習大量的長期信息,但它們最多只能記住相對長的信息,而不是更大更長。
使用 RNN 文本表示與生成所以,我們來總結一下傳統 encoder-decoder的一般范式及其問題:任務是翻譯中文“我/愛/賽爾”到英文。傳統 encoder-decoder 先把整句話輸入進去,編碼最后一個詞“賽爾”結束之后,使用 RNN生成一個整句話的表示-向量 C,在條件生成時,當翻譯到第 2個詞“賽爾”的時候,需要退 1 步找到已經預測出來的h_1以及上下文表示 C, 然后 decode 輸出。
從注意力均等到注意力集中
在傳統Encoder-Decoder 框架下:由解碼器根據當前已經預測出來的詞記憶編碼后的上下文向量 C,來預測目標詞序列。也就是說,不論生成那個詞,我們使用的句子編碼表示 C 都是一樣的。換句話說,句子中任意單詞對生成某個目標單詞P_yi來說影響力都是相同的,也就是注意力均等。很顯然這不符合直覺。直覺應該:我翻譯哪個部分,哪個部分就應該把注意力集中于我的翻譯的原文,翻譯到第一個詞,就應該多關注原文中的第一個詞是什么意思。詳見偽代碼和下圖:
P_y1 = F(E<start>,C), P_y2 = F((E<the>,C) P_y3 = F((E<black>,C)傳統 Encoder-Decoder 框架下的 RNN 進行文本翻譯,一直使用同一個 c接下來觀察上下兩個圖的區別:相同的上下文表示C會替換成根據當前生成單詞而不斷變化的Ci。
融合 attention 機制的RNN 模型進行文本翻譯每個時刻生成不同的 c文本翻譯過程變為:
P_y1 = F(E<start>,C_0), P_y2 = F((E<the>,C_1) P_y3 = F((E<black>,C_2)Encoder-Decoder框架的代碼實現[4]
class EncoderDecoder(nn.Module):"""A standard Encoder-Decoder architecture. Base for this and manyother models."""def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):super(EncoderDecoder, self).__init__()self.encoder = encoderself.decoder = decoderself.src_embed = src_embedself.tgt_embed = tgt_embedself.generator = generatordef forward(self, src, tgt, src_mask, tgt_mask):"Take in and process masked src and target sequences."return self.decode(self.encode(src, src_mask), src_mask,tgt, tgt_mask)def encode(self, src, src_mask):return self.encoder(self.src_embed(src), src_mask)def decode(self, memory, src_mask, tgt, tgt_mask):return self.decoder(self.tgt_embed(tgt), memory, src_mask, tgt_mask)考慮可解釋性
不含注意力模型的傳統encoder-decoder 可解釋差:對于編碼向量中究竟編碼了什么信息,如何利用這些信息以及解碼器特定行為的原因是什么我們并沒有明確的認識。包含注意力機制的結構提供了一張相對簡單的方式讓我們了解解碼器的推理過程以及模型究竟在學習什么內容,學到那些東西。盡管是一種弱可解釋性,但是已經 make sense 了。
直面 attention 的核心公式
在預測目標語言的第i個詞時,源語言第j個詞的權重為??, 權重的大小可i以j 看做是一種源語言和目標語言的軟對齊信息。?
總結
使用 attention 方法實際上就在于預測一個目標詞 yi 時,自動獲取原句中不同位置的語義信息,并給每個位置信息的語義賦予的一個權重,也就是“軟”對齊信息,將這些信息整理起來計算對于當前詞 yi 的原句向量表示 c_i。
Attention 的 PyTorch應用實現
import torch import torch.nn as nnclass BiLSTM_Attention(nn.Module):def __init__(self):super(BiLSTM_Attention, self).__init__()self.embedding = nn.Embedding(vocab_size, embedding_dim)self.lstm = nn.LSTM(embedding_dim, n_hidden, bidirectional=True)self.out = nn.Linear(n_hidden * 2, num_classes)# lstm_output : [batch_size, n_step, n_hidden * num_directions(=2)], F matrixdef attention_net(self, lstm_output, final_state):hidden = final_state.view(-1, n_hidden * 2, 1) # hidden : [batch_size, n_hidden * num_directions(=2), 1(=n_layer)]attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # attn_weights : [batch_size, n_step]soft_attn_weights = F.softmax(attn_weights, 1)# [batch_size, n_hidden * num_directions(=2), n_step] * [batch_size, n_step, 1] = [batch_size, n_hidden * num_directions(=2), 1]context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2)return context, soft_attn_weights.data.numpy() # context : [batch_size, n_hidden * num_directions(=2)]def forward(self, X):input = self.embedding(X) # input : [batch_size, len_seq, embedding_dim]input = input.permute(1, 0, 2) # input : [len_seq, batch_size, embedding_dim]hidden_state = Variable(torch.zeros(1*2, len(X), n_hidden)) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]cell_state = Variable(torch.zeros(1*2, len(X), n_hidden)) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]# final_hidden_state, final_cell_state : [num_layers(=1) * num_directions(=2), batch_size, n_hidden]output, (final_hidden_state, final_cell_state) = self.lstm(input, (hidden_state, cell_state))output = output.permute(1, 0, 2) # output : [batch_size, len_seq, n_hidden]attn_output, attention = self.attention_net(output, final_hidden_state)return self.out(attn_output), attention # model : [batch_size, num_classes], attention : [batch_size, n_step]github地址:
https://github.com/zy1996code/nlp_basic_model/blob/master/lstm_attention.py
參考
^《Neural Network Methods in Natural Language Processing》
^Sequence to Sequence Learning with Neural Networks?https://arxiv.org/pdf/1409.3215.pdf
^LSTM 掃盲:長短期記憶網絡解讀及其 PyTorch 實現 https://zhuanlan.zhihu.com/p/86876988
^The Annotated Transformer?https://nlp.seas.harvard.edu/2018/04/03/attention.html
推薦閱讀:
一戰賺了1090億,恐怖的張一鳴!
教育部官宣:985/211已成為歷史!
超越ReLU卻鮮為人知,3年后被挖掘:BERT、GPT-2等都在用的激活函數
備注:公眾號菜單包含了整理了一本AI小抄,非常適合在通勤路上用學習。
往期精彩回顧2019年公眾號文章精選適合初學者入門人工智能的路線及資料下載機器學習在線手冊深度學習在線手冊AI基礎下載(第一部分)備注:加入本站微信群或者qq群,請回復“加群”加入知識星球(4500+用戶,ID:92416895),請回復“知識星球”喜歡文章,點個在看
總結
以上是生活随笔為你收集整理的Attention 扫盲:注意力机制及其 PyTorch 应用实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我最佩服的一位同学!他是哈工大在读NLP
- 下一篇: AAAI论文首发:几何驱动的自监督的人体