- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在寻找一些提示来训练具有动态生成的 bert 嵌入的传统神经网络模型(BERT 上下文化嵌入,当出现在不同的上下文中时,它会为同一个词生成不同的嵌入)。
在普通的神经网络模型中,我们会用 glove 或 fasttext 嵌入来初始化模型,比如,
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
层:
您可以编写一个循环来为这样的字符串生成 BERT token (假设 - 因为 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
张量,您可以将其用作模型的输入。
提供了完整的(和更合适的)代码 here
这种方法的优点是不必在每个时期都重新计算这些嵌入。
使用这种方法,例如,对于分类,您的模型应该只包含一个Linear(bert_model.config.hidden_size, num_labels)
层,模型的输入应该是结果
上面代码中的张量
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.
之后您可以继续进行预处理,直到生成 token ID。然后你可以训练整个模型(但学习率较低,例如 Adam 3e-5 for batch_size
= 32)
有了它,您可以微调 BERT 的嵌入本身,或使用诸如将 BERT 卡住几个时期以仅训练分类器,然后解冻以进行微调等技术。但它的计算成本也更高。
repo 中也提供了一个例子
关于python - 如何使用 bert 嵌入而不是 glove/fasttext 等静态嵌入来训练神经网络模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55369821/
我是一名优秀的程序员,十分优秀!