认识Bert模型

BERT是一种强大的深度学习模型,基于Transformer,通过无监督预训练在上下文理解上超越传统模型。文章介绍了BERT的预训练方法(MLM和NSP)、优势和应用场景,以及其在自然语言处理领域的影响力。
摘要由CSDN通过智能技术生成

Bert的基本介绍

BERT(Bidirectional Encoder Representations from Transformers)是由Google于2018年发布的一种深度学习模型,用于自然语言处理任务。BERT模型基于Transformer架构,通过大规模的无监督预训练来学习句子的双向上下文表示。相较于传统的自然语言处理模型,BERT在理解上下文语境方面具有更好的表现。

BERT模型的预训练过程包括两个阶段:Masked Language Model(MLM)和Next Sentence Prediction(NSP)。在MLM阶段,模型需要学习如何处理被部分遮盖的输入,并预测被遮盖的词语;在NSP阶段,模型需要判断两个句子在语义上是否连贯。这种预训练方式使得BERT在各种自然语言处理任务上能够取得显著的表现,如文本分类、命名实体识别、问答系统等。

由于BERT模型的强大表现,它已成为自然语言处理领域中的重要里程碑,并为后续的模型发展提供了有力的借鉴。

Bert模型原理

BERT即双向Transformer的Encoder,因为Decoder是不能获要预测的信息的。

BERT = Encoder of Transformer

BERT的创新在于Transformer Decoder(包含Masked Multi-Head Attention)作为提取器,并使用与之配套的掩码训练方法。虽然使用了双编码使得BERT不具有文本生成能力,但BERT在对输入文本的编码过程中,利用了每个词的所有上下文信息,与只能使用前序信息提取语义的单向编码器相比,BERT的语义信息提取能力更强。

下面距离说明单向编码与双向编码在语义理解上的差异

将句子中的某个字或者词“挖”走,句子变为

分别从单向编码(如GPT)和双向编码(如BERT )的角度来考虑“{}”中应该填什么词。单向编码只会使用“今天天气很”这5个字的信息来推断“{}”的字或词,以人类的经验与智慧,使用概率最大的词应该是:“好”“不错”“差”“糟糕”,而这些词可以被划分为截然不同的两类。

通过这个例子我们可以直观地感觉到,不考虑模型的复杂度和训练数据量,双向编码与单向编码相比,可以利用更多的上下文信息来辅助当前的语义判断。在语义理解能力上,采用双向编码的方式是最科学的,而BERT的成功很大程度上有此决定。

BERT对比这两个算法的优点是只有BERT表征会基于所有层中的左右两侧语境

BERT能做到这一点得益于Transformer中Attention机制将任意位置的两个单词的距离转换成了1。

预训练任务

Task1: Masked LM
为了构建一个深层的真双向语言模型,但是标准的语言模型是使用了马尔可夫链进行的单向编码,即使使用 LTR 与 RTL,但也是假的双向编码,性能会受到极大的影响。使用完形填空机制可以避免标准的语言模型的编码瓶颈。

完形填空策略:随机的 mask 掉 15% 的单词,然后使用编码器最后的 hidden state 过一层 softmax 进行完形填空预测。

但是这种策略会有两个缺点,以下是内容和解决方案:
Downside 1: mismatch
这样做构造了一种 mismatch:因为 [MASK] 永运不会出现在 fine-tuning 阶段,所以 pre-training 与 fine-tuning 出现了 mismatch。

缓解方案:对于随机选择的 15% 待 mask 单词,不是直接将它替换为 [MASK],而是再做一次随机:
80%:将该词替换为 [MASK]
10%:将该词替换为一个随机的词语
10%:不替换

原因:Transformer Encoder 不知道哪个单词被要求做预测,哪个单词被随机替换掉了,所以对于每个输入的单词,它都必须保持上下文嵌入;而且,现在这种策略下随机替换掉的单词只有 1.5%,几乎不会影响模型的语言建模能力。

Downside 2: slower
现在使用的 MLM 模型,每个 batch 只有 15% 的单词被预测,所以收敛速度确实慢了。但是效果带来的提升却很大。

Task2: Next Sentence Prediction
NLP 中有很多句子关系性的任务,这部分的能力不能通过 Task1 的 MLM 来俘获到,所以加入了一个二分类任务进行多任务学习。
策略:50% 的句子对,将第二句替换为随机的句子来构建负样本。

其他细节
(1) 训练语料:BooksCorpus 800𝑀 words + English Wikipedia 2,500𝑀𝑤𝑜𝑟𝑑𝑠
(2) batch size:256
(3) Adam:γ \gammaγ=1e−4, β 1 \beta_1β 
1

 =0.9, β 2 \beta_2β 
2

 =−.999,warmup
(4) dropout:0.1
(5) GELU
(6) loss:两个任务的 loss 和

下游监督任务微调

基于句子对的分类任务
  • MNLI:给定一个前提 (Premise) ,根据这个前提去推断假设 (Hypothesis) 与前提的关系。该任务的关系分为三种,蕴含关系 (Entailment)、矛盾关系 (Contradiction) 以及中立关系 (Neutral)。所以这个问题本质上是一个分类问题,我们需要做的是去发掘前提和假设这两个句子对之间的交互信息。
  • QQP:基于Quora,判断 Quora上的两个问题句是否表示的是一样的意思。
  • QNLI:用于判断文本是否包含问题的答案,类似于我们做阅读理解定位问题所在的段落。
  • STS-B:预测两个句子的相似性,包括5个级别。
  • MRPC:也是判断两个句子是否是等价的。
  • RTE:类似于MNLI,但是只是对蕴含关系的二分类判断,而且数据集更小。
  • SWAG:从四个句子中选择为可能为前句下文的那个。
基于单个句子的分类任务
  • SST-2:电影评价的情感分析。
  • CoLA:句子语义判断,是否是可接受的(Acceptable)。

对于GLUE数据集的分类任务(MNLI,QQP,QNLI,SST-B,MRPC,RTE,SST-2,CoLA),BERT的微调方法是根据[CLS]标志生成一组特征向量C CC,并通过一层全连接进行微调。损失函数根据任务类型自行设计,例如多分类的softmax或者二分类的sigmoid。

SWAG的微调方法与GLUE数据集类似,只不过其输出是四个可能选项的softmax:

BERT 实现情感分析

数据预处理

读取文件中的评论信息,并对数据进行去重

读取数据集信息,并输出样本的长度

定义训练函数与评估函数
"""
评估函数,用以评估数据集在神经网络下的精确度
"""
def evaluate(net, comments_data, labels_data):
    
    sum_correct, i = 0, 0
    
    while i <= len(comments_data):
        
        comments = comments_data[i: min(i + 8, len(comments_data))]
        
        tokens_X = tokenizer(comments, padding=True, truncation=True, return_tensors='pt').to(device=device)

        res = net(tokens_X)                                          # 获得到预测结果

        y = torch.tensor(labels_data[i: min(i + 8, len(comments_data))]).reshape(-1).to(device=device)

        sum_correct += (res.argmax(axis=1) == y).sum()              # 累加预测正确的结果
        i += 8

    return sum_correct/len(comments_data)                           # 返回(总正确结果/所有样本),精确率



"""
训练bert_classifier分类器
"""
def train_bert_classifier(net, tokenizer, loss, optimizer, train_comments, train_labels, test_comments, test_labels,
                          device, epochs):
    max_acc = 0.5  # 初始化模型最大精度为0.5

    # 先测试未训练前的模型精确度
    train_acc = evaluate(net, train_comments, train_labels)
    test_acc = evaluate(net, test_comments, test_labels)

    # 输出精度
    print('--epoch', 0, '\t--train_acc:', train_acc, '\t--test_acc', test_acc)


    # 累计训练18万条数据 epochs 次,优化模型
    for epoch in tqdm(range(epochs)):

        i, sum_loss = 0, 0  # 每次开始训练时, i 为 0 表示从第一条数据开始训练


        # 开始训练模型
        while i < len(train_comments):
            comments = train_comments[i: min(i + 8, len(train_comments))]  # 批量训练,每次训练8条样本数据

            # 通过 tokenizer 数据化输入的评论语句信息,准备输入bert分类器
            tokens_X = tokenizer(comments, padding=True, truncation=True, return_tensors='pt').to(device=device)

            # 将数据输入到bert分类器模型中,获得结果
            res = net(tokens_X)

            # 批量获取实际结果信息
            y = torch.tensor(train_labels[i: min(i + 8, len(train_comments))]).reshape(-1).to(device=device)

            optimizer.zero_grad()  # 清空梯度
            l = loss(res, y)  # 计算损失
            l.backward()  # 后向传播
            optimizer.step()  # 更新梯度

            sum_loss += l.detach()  # 累加损失
            i += 8  # 样本下标累加


        # 计算训练集与测试集的精度
        train_acc = evaluate(net, train_comments, train_labels)
        test_acc = evaluate(net, test_comments, test_labels)

        # 输出精度
        print('\n--epoch', epoch+1, '\t--loss:', sum_loss / (len(train_comments) / 8), '\t--train_acc:', train_acc,
              '\t--test_acc', test_acc)

        # 如果测试集精度 大于 之前保存的最大精度,保存模型参数,并重设最大值
        if test_acc > max_acc:
            # 更新历史最大精确度
            max_acc = test_acc

            # 保存模型
            torch.save(net.state_dict(), 'bert.parameters')

总结


优点

使用Transformer的结构将已经走向瓶颈期的Word2Vec带向了一个新的方向,并再一次炒火了《Attention is All you Need》这篇论文;
11个NLP任务的精度大幅提升足以震惊整个深度学习领域;
无私的开源了多种语言的源码和模型,具有非常高的商业价值。
迁移学习又一次胜利,而且这次是在NLP领域的大胜,狂胜。
BERT算法还有很大的优化空间,例如我们在Transformer中讲的如何让模型有捕捉Token序列关系的能力,而不是简单依靠位置嵌入。BERT的训练在目前的计算资源下很难完成,论文中说 [公式] 的训练需要在64块TPU芯片上训练4天完成,而一块TPU的速度约是目前主流GPU的7-8倍。非常幸运的是谷歌开源了各种语言的模型,免去了我们自己训练的工作。

缺点

MLM预训练时的mask问题:

[MASK]标记在实际预测中不会出现,训练时用过多[MASK]影响模型表现
每个batch只有15%的token被预测,所以BERT收敛得比left-to-right模型要慢(它们会预测每个token)

 内容数据来源:BERT模型原理的详细介绍_bert 知乎-CSDN博客

                          BERT模型-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值