首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用bert嵌入来训练神经网络模型,而不是像手套/快速文本那样的静态嵌入?

如何用bert嵌入来训练神经网络模型,而不是像手套/快速文本那样的静态嵌入?
EN

Stack Overflow用户
提问于 2019-03-27 04:27:51
回答 1查看 8K关注 0票数 6

我想找一些人来训练一个传统的神经网络模型,它的bert嵌入是动态生成的(BERT上下文化嵌入,它为相同的单词生成不同的嵌入,当不同的上下文出现时,它会产生不同的嵌入)。

在正常的神经网络模型中,我们会用手套或快速文本嵌入来初始化模型,

代码语言:javascript
复制
import torch.nn as nn 

embed = nn.Embedding(vocab_size, vector_size)

embed.weight.data.copy_(some_variable_containing_vectors)

我不想复制像这样的静态向量并使用它进行训练,而是将每一个输入传递给一个BERT模型,并生成动态的单词嵌入,并将它们提供给训练模型。

那么,我应该改变模型中包含这些嵌入的前向函数吗?

任何帮助都将不胜感激!

EN

回答 1

Stack Overflow用户

发布于 2019-03-27 09:23:07

如果你用的是毕道尔。您可以使用https://github.com/huggingface/pytorch-pretrained-BERT,这是Pytorch最流行的BERT实现(它也是一个pip包!)在这里,我将概述如何正确地使用它。

对于这个特定的问题,有两种方法--显然不能使用Embedding层:

  1. 您可以将生成BERT嵌入合并到数据预处理管道中。您需要使用伯特自己的记号器和字到ids字典。回购的自述文件有关于预处理的例子。

您可以编写一个循环来为这样的字符串生成BERT令牌(假设-因为BERT消耗了大量GPU内存):

(注:更恰当的是,你还应该添加注意力掩码-这是1&0的LongTensor,掩盖了句子的长度)

代码语言:javascript
复制
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. 第二,也可以说是更简洁的方法:如果您签出存储库,您会发现有各种任务的包装器(例如,BertForSequenceClassification)。还应该很容易实现您的自定义类,这些类继承自BertPretrainedModel并利用来自回购的各种Bert类。

例如,您可以使用:

代码语言:javascript
复制
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 )。

有了这个,你可以微调伯特的嵌入本身,或者使用诸如冻结伯特几个时代的技术,只训练分类器,然后解冻到微调等,但它也是更昂贵的计算。

存储库中也提供了一个示例。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55369821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档