1. 程式人生 > 其它 >Bert獲取詞向量的過程

Bert獲取詞向量的過程

參考部落格:https://blog.csdn.net/u011984148/article/details/99921480

1.把我們要獲取詞向量的句子進行分詞處理,再根據模型中的vocab.txt獲取每個詞的對應的索引。

token初始化

tokenized_text = tokenizer.tokenize(marked_text)	
print (tokenized_text)	
['[CLS]', 'after', 'stealing', 'money', 'from', 'the', 'bank', 'vault', ',', 'the', 'bank', 'robber', 'was', 'seen', 'fishing', 'on', 'the', 'mississippi', 'river', 'bank', '.', '[SEP]']

 

通過分詞後的token獲取詞表中對應的索引

indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)	
for tup in zip(tokenized_text, indexed_tokens):	
  print (tup)	
('[CLS]', 101)	
('after', 2044)	
('stealing', 11065)	
('money', 2769)	
('from', 2013)	
('the', 1996)	
('bank', 2924)	
('vault', 11632)	
(',', 1010)	
('the', 1996)	
('bank', 2924)	
('robber', 27307)	
('was', 2001)	
('seen', 2464)	
('fishing', 5645)	
('on', 2006)	
('the', 1996)	
('mississippi', 5900)	
('river', 2314)	
('bank', 2924)	
('.', 1012)	
('[SEP]', 102)

2.生成句子的位置編碼,bert以一個或者兩個句子作為輸入,要對句子進行處理,獲取他們的位置編碼。

segments_ids = [1] * len(tokenized_text)	
print (segments_ids)	
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

3.

接下來,我們需要將資料轉換為torch張量並呼叫BERT模型。BERT PyTorch介面要求資料使用torch張量而不是Python列表,所以我們在這裡轉換列表——這不會改變形狀或資料。

eval()將我們的模型置於評估模式,而不是訓練模式。在這種情況下,評估模式關閉了訓練中使用的dropout正則化。


呼叫 from_pretrained 將從網上獲取模型。當我們載入 bert-base-uncased時,我們會在日誌中看到列印的模型定義。該模型是一個12層的深度神經網路!

# Convert inputs to PyTorch tensors	
tokens_tensor = torch.tensor([indexed_tokens])	
segments_tensors = torch.tensor([segments_ids])	
# Load pre-trained model (weights)	
model = BertModel.from_pretrained('bert-base-uncased')	
# Put the model in "evaluation" mode, meaning feed-forward operation.	
model.eval()

4.接下來,讓我們獲取網路的隱藏狀態。encode_layers隱藏狀態是一個四維的張量,分別是隱藏層的層數、batch(批處理的大小)、一個輸入的句子(一個樣本),句子中每個token的編碼(768維的向量)

torch.no_grad禁用梯度計算,節省記憶體,並加快計算速度(我們不需要梯度或反向傳播,因為我們只是執行向前傳播)。

# Predict hidden states features for each layer	
with torch.no_grad():	
    encoded_layers, _ = model(tokens_tensor, segments_tensors)
print ("Number of layers:", len(encoded_layers))	
layer_i = 0	
print ("Number of batches:", len(encoded_layers[layer_i]))	
batch_i = 0	
print ("Number of tokens:", len(encoded_layers[layer_i][batch_i]))	
token_i = 0	
print ("Number of hidden units:", len(encoded_layers[layer_i][batch_i][token_i]))	
Number of layers: 12	
Number of batches: 1	
Number of tokens: 22	
Number of hidden units: 768

5.對獲取的隱藏狀態進行重構,獲取的token_embeddings是一個三維的張量,是一個樣本中每個token在神經網路每一層對應的編碼,對應的維度分別是句子中的token個數,神經網路的層數,每個token對應的編碼。

    [# tokens, # layers, # features]	
# Convert the hidden state embeddings into single token vectors	
# Holds the list of 12 layer embeddings for each token	
# Will have the shape: [# tokens, # layers, # features]	
token_embeddings = [] 	
# For each token in the sentence...	
for token_i in range(len(tokenized_text)):	
  # Holds 12 layers of hidden states for each token	
  hidden_layers = [] 	
  # For each of the 12 layers...	
  for layer_i in range(len(encoded_layers)):	
    # Lookup the vector for `token_i` in `layer_i`	
    vec = encoded_layers[layer_i][batch_i][token_i]	
    hidden_layers.append(vec)	
  token_embeddings.append(hidden_layers)	
# Sanity check the dimensions:	
print ("Number of tokens in sequence:", len(token_embeddings))	
print ("Number of layers per token:", len(token_embeddings[0]))	
Number of tokens in sequence: 22	
Number of layers per token: 12

6.構建詞向量和句向量,詞向量是根據神經網路的最後四層來進行構建的,因為最後四層的效果最好,可以使用拼接的方式,也可以使用求和取平均的方式來獲取詞向量的編碼。句向量是是對每個token的倒數第二個隱藏層求平均,生成一個768長度的向量。具體程式碼見上面部落格連線。

總結,通過預訓練模型來獲取詞向量,就是先對句子分詞,根據token獲取詞表中對應的索引,之後再獲取位置編碼,將它們輸入到模型之中,(模型可以設定成評估模式,關閉訓練過程中的正則化,同時去掉反向傳播)模型就會返回每個隱藏層中的token的編碼,之後在對其進行處理,比如用最後四層的token編碼來計算最終的token表示。