我想找一些人来训练一个传统的神经网络模型,它的bert嵌入是动态生成的(BERT上下文化嵌入,它为相同的单词生成不同的嵌入,当不同的上下文出现时,它会产生不同的嵌入)。
在正常的神经网络模型中,我们会用手套或快速文本嵌入来初始化模型,
import torch.nn as nn
embed = nn.Embedding(vocab_size, vector_size)
embed.weight.data.copy_(some_variable_containing_vectors)我不想复制像这样的静态向量并使用它进行训练,而是将每一个输入传递给一个BERT模型,并生成动态的单词嵌入,并将它们提供给训练模型。
那么,我应该改变模型中包含这些嵌入的前向函数吗?
任何帮助都将不胜感激!
发布于 2019-03-27 09:23:07
如果你用的是毕道尔。您可以使用https://github.com/huggingface/pytorch-pretrained-BERT,这是Pytorch最流行的BERT实现(它也是一个pip包!)在这里,我将概述如何正确地使用它。
对于这个特定的问题,有两种方法--显然不能使用Embedding层:
您可以编写一个循环来为这样的字符串生成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张量。
BertForSequenceClassification)。还应该很容易实现您的自定义类,这些类继承自BertPretrainedModel并利用来自回购的各种Bert类。例如,您可以使用:
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', labels=num_labels) # Where num_labels is the number of labels you need to classify.之后,可以继续进行预处理,直到生成令牌ids为止。然后你可以训练整个模型(但是学习速度很低,比如batch_size =32的Adam 3e-5 )。
有了这个,你可以微调伯特的嵌入本身,或者使用诸如冻结伯特几个时代的技术,只训练分类器,然后解冻到微调等,但它也是更昂贵的计算。
在存储库中也提供了一个示例。
https://stackoverflow.com/questions/55369821
复制相似问题