簡體   English   中英

如何使用bert嵌入來訓練神經網絡模型而不是像手套/ fasttext那樣的靜態嵌入?

[英]How to train a neural network model with bert embeddings instead of static embeddings like glove/fasttext?

我正在尋找一些能夠用動態生成的bert嵌入來訓練傳統神經網絡模型(BERT上下文嵌入,為不同的上下文生成相同單詞的嵌入)。

在正常的神經網絡模型中,我們將使用手套或快速文本嵌入來初始化模型,如

import torch.nn as nn 

embed = nn.Embedding(vocab_size, vector_size)

embed.weight.data.copy_(some_variable_containing_vectors)

我沒有像這樣復制靜態向量並將其用於訓練,而是希望將每個輸入傳遞給BERT模型並為動態的單詞生成嵌入,並將它們提供給模型進行訓練。

那么我是否應該改變模型中的前向函數來合並這些嵌入?

任何幫助,將不勝感激!

如果你使用的是Pytorch。 你可以使用https://github.com/huggingface/pytorch-pretrained-BERT這是Pytorch最流行的BERT實現(它也是一個pip包!)。 在這里,我將概述如何正確使用它。

對於這個特殊問題,有兩種方法 - 你顯然不能使用Embedding層:

  1. 您可以將生成BERT嵌入合並到數據預處理管道中。 您將需要使用BERT自己的tokenizer和word-to-id字典。 repo的README有預處理的例子。

你可以編寫一個循環來為這樣的字符串生成BERT令牌(假設 - 因為BERT消耗了大量的GPU內存):

(注意:為了更合適你還應該添加注意面具 - 這是1和0的LongTensor屏蔽句子長度)

import torch
from pytorch_pretrained_bert import BertTokenizer, BertModel

batch_size = 32
X_train, y_train = samples_from_file('train.csv') # Put your own data loading function here
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
X_train = [tokenizer.tokenize('[CLS] ' + sent + ' [SEP]') for sent in X_train] # Appending [CLS] and [SEP] tokens - this probably can be done in a cleaner way
bert_model = BertModel.from_pretrained('bert-base-uncased')
bert_model = bert_model.cuda()

X_train_tokens = [tokenizer.convert_tokens_to_ids(sent) for sent in X_train]
results = torch.zeros((len(X_test_tokens), bert_model.config.hidden_size)).long()
with torch.no_grad():
    for stidx in range(0, len(X_test_tokens), batch_size):
        X = X_test_tokens[stidx:stidx + batch_size]
        X = torch.LongTensor(X).cuda()
        _, pooled_output = bert_model(X)
        results[stidx:stidx + batch_size,:] = pooled_output.cpu()

之后,您將獲得包含計算嵌入的results張量,您可以將其用作模型的輸入。

這個完整的(更合適)提供代碼, 在這里

該方法的優點是不必在每個時期重新計算這些嵌入。

使用此方法,例如,對於分類,您的模型應僅包含Linear(bert_model.config.hidden_size, num_labels)圖層,模型的輸入應為上述代碼中的results張量

  1. 第二,可以說更清晰的方法:如果你看看repo ,你會發現有各種任務的包裝器(例如BertForSequenceClassification )。 實現從BertPretrainedModel繼承的自定義類並使用repo中的各種Bert類也應該很容易。

例如,您可以使用:

model = BertForSequenceClassification.from_pretrained('bert-base-uncased', labels=num_labels) # Where num_labels is the number of labels you need to classify.

之后,您可以繼續進行預處理,直到生成令牌ID。 然后你可以訓練整個模型(但學習率很低,例如對於batch_size = 32,亞當3e-5)

有了這個,你可以微調BERT的嵌入本身,或者使用諸如凍結BERT幾個時代的技術來訓練分類器,然后解凍微調等等。但它的計算成本也更高。

回購中還提供了一個例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM