pytorch元素相乘_bert_pytorch学习(1)
本文主要是記錄學習bert的pytorch實現代碼的一些心得
dataset
1. vocab
繼承關系:TorchVocab --> Vocab --> WordVocab
- TorchVocab
該類主要是定義了一個詞典對象,包含如下三個屬性:
freqs:是一個collections.Counter對象,能夠記錄數據集中不同token所出現的次數
stoi:是一個collections.defaultdict對象,將數據集中的token映射到不同的index
itos:是一個列表,保存了從index到token的映射信息
代碼中sort與sorted的區別:
sort 是應用在 list 上的方法,sorted 可以對所有可迭代的對象進行排序操作。
list 的 sort 方法返回的是對已經存在的列表進行操作,而內建函數 sorted 方法返回的是一個新的 list,而不是在原來的基礎上進行的操作。
sorted的語法:
sorted(iterable, key=None, reverse=False)
iterable -- 可迭代對象。
key -- 主要是用來進行比較的元素,只有一個參數,具體的函數的參數就是取自于可迭代對象中,指定可迭代對象中的一個元素來進行排序。
reverse -- 排序規則,reverse = True 降序 , reverse = False 升序(默認)。
- Vocab
Vocab繼承TorchVocab,該類主要定義了一些特殊token的表示
這里用到了一個裝飾器,簡單地說:裝飾器就是修改其他函數的功能的函數。這里包含了一個序列化的操作
- WordVocab
WordVocab繼承自Vocab,里面包含了兩個方法to_seq和from_seq分別是將token轉換成index和將index轉換成token表示
2. dataset
主要實現了一個BERTDataset類,繼承自torch.utils.data.Dataset,里面一些操作都是根據論文中的兩種訓練模型構建的:masked words 和 next sentence predict
model
1. attention
這里首先定義了一個單注意力的類,然后通過該類疊加構造一個多頭注意力的類。
矩陣相乘有torch.mm和torch.matmul兩個函數。其中前一個是針對二維矩陣,后一個是高維。當torch.mm用于大于二維時將報錯。
masked_fill:a.masked_fill(mask == 0, value) mask必須是一個 ByteTensor 而且shape必須和 a一樣 并且元素只能是 0或者1 ,是將 mask中為1的 元素所在的索引,在a中相同的的索引處替換為 value ,mask value必須同為tensor
2. embedding
bert的embedding由三個部分組成:TokenEmbedding、PositionalEmbedding、SegmentEmbedding
pytorch中詞嵌入使用nn.Embedding,只需要調用 torch.nn.Embedding(m, n) 就可以了,m 表示單詞的總數目,n 表示詞嵌入的維度,其實詞嵌入就相當于是一個大矩陣,矩陣的每一行表示一個單詞,默認是隨機初始化的,不過也可以使用已經訓練好的詞向量。不理解的話可以自己用簡單的例子嘗試一下即可
這里的位置編碼是寫死的,不會隨著訓練進行更新,這是論文 attention is all you need 中的做法,而bert模型的官方TensorFlow源碼是將位置編碼position embedding直接初始化成可訓練的參數并通過訓練進行學習的,所以此處的實現和bert模型不同
import torch.nn as nn import torch import mathclass PositionalEmbedding(nn.Module):def __init__(self, d_model, max_len=512):super().__init__()# Compute the positional encodings once in log space.pe = torch.zeros(max_len, d_model).float()pe.require_grad = Falseposition = torch.arange(0, max_len).float().unsqueeze(1)div_term = (torch.arange(0, d_model, 2).float() * -(math.log(10000.0) / d_model)).exp()pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0)self.register_buffer('pe', pe)def forward(self, x):return self.pe[:, :x.size(1)]代碼中對positionembedding的實現一開始看有點懵,感覺和原文中的表達式不太一樣,后來查找資料發現是對原公式做了如下變換:
$$ 1/10000^{2i/d_{model}} = e^{log{10000^{-2i/d_{model}}}} = e^{-2i/d_{model}log{10000}} = e^{2i(-log^{10000}/d_{model})} $$
這樣一來便和代碼中的實現一致了,為什么要這么做,代碼注釋中說這樣可以使用log空間一次性計算position embedding,即能夠節省一定的內存開銷
3. utils
這部分主要是實現了模型中的一些組件:FNN,gelu激勵函數,layernorm正則化以及sublayer連接,理論部分論文中都介紹得很詳細,可以結合論文原文學習這部分的實現應該比較好理解
bert語言模型構建
接下來就是bert模型的具體實現了:
首先是構造transformer block。然后組成bert模型
這里要復習一下repeat()方法:torch.Tensor有兩個實例方法可以用來擴展某維的數據的尺寸,分別是repeat()和expand():
expand()方法返回當前張量在某維擴展更大后的張量。擴展(expand)張量不會分配新的內存,只是在存在的張量上創建一個新的視圖(view),一個大小(size)等于1的維度擴展到更大的尺寸。
repeat()方法沿著特定的維度重復這個張量,和expand()不同的是,這個函數拷貝張量的數據,而不是在原來的張量上修改。
trainer
主要設置了optim以及封裝了訓練迭代的操作
總結
以上是生活随笔為你收集整理的pytorch元素相乘_bert_pytorch学习(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百度seo排名规则_百度关键词seo优化
- 下一篇: 加载中图片 转圈_对话洛可可平面设计师: