首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用经过预先训练的BERT字嵌入向量来初始化(初始化)其他网络?

如何使用经过预先训练的BERT字嵌入向量来初始化(初始化)其他网络?
EN

Stack Overflow用户
提问于 2021-01-20 03:43:21
回答 1查看 1.3K关注 0票数 0

当我过去使用textcnn进行分类工作时,我有经验使用预先训练过的单词嵌入(比如Word2Vec和fasttext文本)来细化textcnn。我用这个过程:

  1. 在textcnn
  2. 中创建一个嵌入层,加载Word2Vec或fasttext
  3. 使用的单词的嵌入矩阵,因为嵌入层的向量值在训练过程中会发生变化,网络正在细化。

最近我也想试试伯特。我想,“由于使用BERT预训练的嵌入到初始其他网络的嵌入层和细化应该没有什么不同,所以应该很容易!”但事实上,昨天我试了一整天,但还是做不到。

我发现,由于BERT的嵌入是一种上下文嵌入,特别是在提取单词嵌入时,每个单词的向量都会有所不同,因此似乎无法像通常那样使用该嵌入来初始化另一个网络的嵌入层。

最后,我想出了一个“finetuning”方法,如下所示:

首先,在textcnn.

  • Instead中不定义嵌入层使用嵌入层,在网络训练部分,我首先将序列标记传递给预先训练的sentence.

  • Put模型,得到每个sentence.

  • Put的单词嵌入从2到textcnn,并训练。

通过使用这种方法,我终于可以训练,但认真思考,我认为我根本没有做一个最后的……

因为正如你所看到的,每次当我开始新的训练循环时,从BERT生成的单词嵌入总是相同的向量,所以只要将这些不变的向量输入textcnn就不会让textcnn被细化,对吗?

更新:--我想出了一种新的方法,将伯特嵌入和“训练”BERT和textcnn放在一起使用。

我代码的一部分是:

代码语言:javascript
复制
    BERTmodel = AutoModel.from_pretrained('bert- 
                base-uncased',output_hidden_states=True).to(device)
    TextCNNmodel = TextCNN(EMBD_DIM, CLASS_NUM, KERNEL_NUM, 
                   KERNEL_SIZES).to(device)
    optimizer = torch.optim.Adam(TextCNNmodel.parameters(), lr=LR)
    loss_func = nn.CrossEntropyLoss()
代码语言:javascript
复制
  for epoch in range(EPOCH):
    TextCNNmodel.train()
    BERTmodel.train()
    for step, (token_batch, seg_batch, y_batch) in enumerate(train_loader):
        token_batch = token_batch.to(device)
        y_batch = y_batch.to(device)

        BERToutputs = BERTmodel(token_batch)
        # I want to use the second-to-last hidden layer as the embedding, so
        x_batch = BERToutputs[2][-2]

        output = TextCNNmodel(x_batch)
        output = output.squeeze()
        loss = loss_func(output, y_batch)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

我认为,在获得嵌入时,通过启用BERTmodel.train()和删除torch.no_grad(),损失梯度也可以返回到BERTmodel。TextCNNmodel的训练过程也进行顺利。

为了以后使用这个模型,我保存了TextCNNmodel和BERTmodel的参数。

然后,为了测试BERTmodel是否真的被训练和修改,在另一个程序中,我加载了BERTModel,并输入一个句子来测试BERTModel是否真的被训练了。

然而,我发现原来的‘bert-base’模型和我的'BERTmodel‘的输出(嵌入)是相同的,这是令人失望的.

我真的不知道为什么BERTmodel部分没有改变.

EN

回答 1

Stack Overflow用户

发布于 2021-01-20 15:23:09

在这里,我要感谢@Jindřich,谢谢您给我一个重要的提示!

当我使用更新的版本代码时,我想我已经快到了,但是我忘记为BERTmodel设置一个优化器。

在我设置了优化器并再次执行了培训过程之后,这一次当我加载我的BERTmodel时,我发现原始‘bert-base’模型和我的' BERTmodel‘的输出(嵌入)最终是不同的,这意味着这个BERTmodel被改变了,应该被细化。

这是我的最后密码,希望它也能帮到你。

代码语言:javascript
复制
    BERTmodel = AutoModel.from_pretrained('bert- 
                base-uncased',output_hidden_states=True).to(device)
    TextCNNmodel = TextCNN(EMBD_DIM, CLASS_NUM, KERNEL_NUM, 
                   KERNEL_SIZES).to(device)
    optimizer = torch.optim.Adam(TextCNNmodel.parameters(), lr=LR)
    optimizer_bert = torch.optim.Adamw(BERTmodel.parameters(), lr=2e-5, weight_decay=1e-2)
    loss_func = nn.CrossEntropyLoss()
代码语言:javascript
复制
  for epoch in range(EPOCH):
    TextCNNmodel.train()
    BERTmodel.train()
    for step, (token_batch, seg_batch, y_batch) in enumerate(train_loader):
        token_batch = token_batch.to(device)
        y_batch = y_batch.to(device)

        BERToutputs = BERTmodel(token_batch)
        # I want to use the second-to-last hidden layer as the embedding, so
        x_batch = BERToutputs[2][-2]

        output = TextCNNmodel(x_batch)
        output = output.squeeze()
        loss = loss_func(output, y_batch)

        optimizer.zero_grad()
        optimizer_bert.zero_grad()
        loss.backward()
        optimizer.step()
        optimizer_bert.step()

我将继续我的实验,看看我的BERTmodel是否真的被细化了。

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

https://stackoverflow.com/questions/65802782

复制
相关文章

相似问题

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