一、簡介
Transformer是一種雖然比較新穎但已經相當成熟的深度神經網路結構。在很多自然語言處理任務中,Transformer已經展示出了驚人的效果。其中一個關鍵的結構就是位置編碼。本文將會介紹Transformer模型中的位置編碼,以及如何將其有效地添加到Transformer中,同時提供示例代碼。
二、位置編碼的介紹
在Transformer中,由於自注意力機制,模型需要對所有輸入的位置進行建模。構建位置編碼是Transformer模型中的一項非常重要的任務,目的是為了保證輸入序列中token之間的相對位置信息被編碼到了模型中。位置編碼的提出主要是為了解決針對位置信息無法適應序列長度變化的問題。沒有位置編碼,序列太短則模型將無法感知距離信息並容易出現過擬合;相反,如果序列太長,模型則會失去距離感知能力並容易欠擬合。
三、位置編碼的生成方式
在Transformer中,位置編碼實際上是一組固定的參數向量,可以通過一定的公式來計算得到。這個公式比較簡單,可以參考如下代碼:
import numpy as np # 獲取每個位置的位置編碼 def get_pos_encoding_matrix(max_len, d_emb): pos_enc = np.array([ [pos / np.power(10000, 2*i/d_emb) for i in range(d_emb)] if pos != 0 else np.zeros(d_emb) for pos in range(max_len)]) pos_enc[1:, 0::2] = np.sin(pos_enc[1:, 0::2]) # dim 2i pos_enc[1:, 1::2] = np.cos(pos_enc[1:, 1::2]) # dim 2i+1 return pos_enc
生成位置編碼的方式比較獨特。我們使用了一個根據位置、向量維度與一個常數10000的公式計算的數列,其中偶數維度使用sine函數,奇數維度使用cosine函數來生成,以保證豐富的位置信息與互不衝突的位置向量獨特性。
四、位置編碼的添加方式
我們可以通過加入位置編碼來直接改進Transformer模型,從而達到更好的預測結果。在添加位置編碼時,我們可以將其與token嵌入向量進行拼接,即在每個嵌入向量後面加上一個位置編碼向量,這樣就可以在訓練中不斷地更新模型中token的位置編碼信息。代碼可以參考如下:
import torch.nn as nn # 在每個token嵌入向量後面加上位置編碼 class TokenPositionEmbedding(nn.Module): def __init__(self, max_len, d_emb): super(TokenPositionEmbedding, self).__init__() self.pos_enc = nn.Embedding.from_pretrained( torch.from_numpy(get_pos_encoding_matrix(max_len, d_emb)), freeze=True) def forward(self, x): pos = torch.arange(x.size(1), device=x.device).expand(x.size(0), x.size(1)).to(x.dtype) return x + self.pos_enc(pos)
五、實現效果展示
我們在Transformer的機器翻譯任務上運用了位置編碼。我們使用了一個包括八層的Transformer,其中每個全連接層的維度為512,輸入embedding維度為128,同時每個feed forward層的dropout比率為0.1。在WMT「English to German」數據集的翻譯任務中,我們得到了50.95的BLEU分數(相對的,[Vaswani et al. (2017)](https://arxiv.org/abs/1706.03762)的論文中對於同樣的問題,他們得到了28.4的BLEU分數)。
六、小結
通過本文,我們詳細闡述了如何將位置編碼有效地添加到Transformer中,並介紹了一個生成位置編碼的簡單方法。在實際的機器翻譯任務中,我們取得了很好的效果。我們希望這篇文章能夠為有需要的讀者提供幫助,並進一步推動自然語言處理的發展。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/294091.html