代码之家  ›  专栏  ›  技术社区  ›  Arjun Sankarlal

如何用bert嵌入代替glove/fasttext等静态嵌入训练神经网络模型?

  •  1
  • Arjun Sankarlal  · 技术社区  · 7 年前

    我正在寻找一些头脑,以训练一个传统的神经网络模型与伯特嵌入动态生成(伯特上下文化嵌入,它产生不同的嵌入同一个词时,在不同的上下文)。

    在正常的神经网络模型中,我们会用glow或fasttext嵌入来初始化模型,比如,

    import torch.nn as nn 
    
    embed = nn.Embedding(vocab_size, vector_size)
    
    embed.weight.data.copy_(some_variable_containing_vectors)
    

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

    任何帮助都将不胜感激!

    0 回复  |  直到 7 年前
        1
  •  9
  •   luungoc2005    7 年前

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

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

    1. 您可以将生成的BERT嵌入合并到数据预处理管道中。您将需要使用BERT自己的标记器和wordtoids字典。回购 README 有预处理的例子。

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

    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) 层,模型的输入应该是 上述代码中的张量

    1. repo ,您可以找到各种任务的包装(例如 BertForSequenceClassification ). 实现继承自 BertPretrainedModel

    例如,您可以使用:

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

    之后,您可以继续进行预处理,直到生成令牌ID为止。然后你可以训练整个模型(但是学习率很低,例如亚当3e-5 batch_size =32)

    有了这个你可以微调BERT的嵌入本身,或者使用一些技术,比如冻结BERT几个时期来只训练分类器,然后解冻到微调等等,但是它的计算成本也更高。

    中也提供了一个示例 repo

    推荐文章