自学大语言模型之Bert和GPT的区别

news2024/11/25 0:43:21

Bert和GPT的区别

起源

2018 年,Google 首次推出 BERT(Bidirectional Encoder Representations from Transformers)。该模型是在大量文本语料库上结合无监督和监督学习进行训练的。 BERT 的目标是创建一种语言模型,可以理解句子中单词的上下文和含义,同时考虑到它前后出现的单词。

2018 年,OpenAI 首次推出 GPT(Generative Pre-trained Transformer)。与 BERT 一样,GPT 也是一种大规模预训练语言模型。但是,GPT 是一种生成模型,它能够自行生成文本。 GPT 的目标是创建一种语言模型,该模型可以生成连贯且适当的上下文文本。

在这里插入图片描述

区别

BERT和GPT是两种不同的预训练语言模型,它们在原理和应用方面存在一些显著的区别。

目标任务:

  • BERT:BERT是一种基于Transformer的预训练模型,它的目标是通过双向语言模型预训练来学习上下文相关的词表示。在预训练过程中,BERT通过掩码语言模型(Masked Language Model,MLM)和下一句预测(Next Sentence Prediction,NSP)任务进行训练。

    • 掩码语言模型(Masked Language Model,MLM):在输入序列中,BERT随机掩盖一些词语,然后要求模型预测这些被掩盖的词语。通过这个任务,BERT可以学习到在给定上下文的情况下,预测缺失词语的能力。这使得BERT能够理解词语的语义和上下文信息。具体来说,对于每个输入序列,BERT会随机选择一些词语进行掩码。通常,选择的词语占总词语数量的15%左右。对于被选择的词语,有以下三种方式来处理:

      • 80%的情况下,将被选择的词语替换为特殊的掩码标记 [MASK]。例如,将句子 “I love apples” 中的 “apples” 替换为 “[MASK] love [MASK]”。“this movie is great”变为“this movie is [MASK]”;

      • 10%的情况下,将被选择的词语随机替换为其他词语。这样模型不仅需要理解上下文,还需要具备词语替换和词义推断的能力。例如,“this movie is great”变为“this movie is drink”

      • 10%的情况下,保持被选择的词语不变。这样做是为了让模型学习到如何处理未被掩码的词语。“this movie is great”变为“this movie is great”

      • 接下来,BERT将处理过的输入序列输入到模型中,然后使用Transformer的编码器结构进行编码。在编码过程中,模型会同时考虑到被掩码的词语和其它上下文中的信息。最终,模型会生成一组对应被掩码的词语的预测结果。

    • 下一句预测(Next Sentence Prediction,NSP):在一些自然语言处理任务中,理解句子之间的关系是很重要的。为了让模型学习句子级别的关系,BERT使用了NSP任务。该任务要求模型判断两个句子是否是连续的,即一个句子是否是另一个句子的下一句。通过这个任务,BERT能够学习到句子级别的语义关系和推理能力。显式地建模文本对之间的逻辑关系。具体以下方式来处理:

      • 对于每个训练样本,BERT会随机选择两个句子A和B。其中,50%的情况下,句子B是句子A的下一句,而另外50%的情况下,句子B是从语料库中随机选择的其他句子。。

      • 为了进行NSP任务,BERT引入了一种特殊的输入编码方式。对于每个输入序列,BERT会将句子A和句子B之间插入一个特殊的分隔标记 [SEP],并在输入的开始处添加一个特殊的句子标记 [CLS]。

        [CLS] 句子A [SEP] 句子B [SEP]

      • 接下来,BERT将这个编码后的序列输入到模型中,并使用Transformer的编码器结构对其进行编码。编码器会根据上下文信息对句子A和句子B的表示进行学习。

      • 在编码过程中,模型会将整个序列作为输入,并在特殊的 [CLS] 标记上进行预测。这个预测任务可以是一个分类任务,用于判断句子A和句子B是否是连续的。通常,模型会使用一个全连接层将 [CLS] 的隐藏状态映射到一个二分类问题上,例如使用sigmoid激活函数来预测两个句子的连续性。

  • GPT:GPT是一种基于Transformer的生成式预训练模型,其目标是通过自回归语言模型预训练来学习生成连贯文本的能力。GPT采用了自回归语言模型的预训练方式。在预训练过程中,GPT使用大规模的文本数据,并通过自回归的方式逐步生成下一个词语。模型根据已生成的上文预测下一个词语,通过最大似然估计来优化模型参数。这使得GPT能够学习到生成连贯、有逻辑性的文本的能力。GPT实现过程大致如下:

    • GPT将文本数据分割成词语或子词的过程通常是通过分词(tokenization)来实现的。在分词过程中,常用的方法有两种:

      • 基于词语的分词(Word-based Tokenization):这种方法将文本划分为独立的词语单元。例如,对于句子"I love natural language processing",基于词语的分词将它划分为[“I”, “love”, “natural”, “language”, “processing”]。
      • 基于子词的分词(Subword-based Tokenization):这种方法将文本划分为更小的子词单元。它可以处理词语的内部结构和复杂性,更适用于处理未登录词(out-of-vocabulary)和稀有词(rare words)。例如,对于句子"I love natural language processing",基于子词的分词可以将它划分为[“I”, “love”, “nat”, “ural”, “language”, “pro”, “cess”, “ing”]。
    • 无论是基于词语还是基于子词的分词,最终的目标是将文本分割成离散的标记单元,每个标记单元对应一个词语或子词。

    • Embedding词嵌入:将token编码为向量。即每个词语或子词都会被转换为对应的嵌入向量表示嵌入向量是一种连续的实数向量,用于表示词语或子词在语义空间中的位置。常见的方法是使用预训练的词向量模型,如Word2Vec、GloVe或FastText,将词语或子词映射到固定维度的实数向量。

    • Transformer架构:GPT采用了Transformer作为其基础架构。Transformer是一种强大的深度学习模型,其核心机制是自注意力机制。它能够在处理序列数据时捕捉全局依赖关系,同时具有并行计算的能力。

    • 自回归语言模型:在预训练过程中,GPT使用自回归语言模型进行训练。具体而言,模型逐步生成下一个词语,以此生成连贯的文本。在生成第i个词语时,模型使用已生成的前i-1个词语作为上文来预测下一个词语。

    • 学习预训练参数:在自回归语言模型中,GPT的目标是最大化生成真实训练样本的概率。通过最大似然估计,模型的参数被优化以最大化真实训练样本的生成概率。通过大规模的预训练数据和迭代的优化过程,GPT能够学习到语言的统计规律和结构,从而能够生成连贯、有逻辑性的文本。

    • 生成文本:在预训练完成后,GPT可以生成文本。给定一个初始文本或种子句子,模型会逐步生成下一个词语,将其添加到已生成的文本中,然后再用生成的文本作为上文来预测下一个词语。通过重复这个过程,模型可以生成连贯、有逻辑性的文本。

训练方式:

BERT:BERT使用了双向语言模型的训练策略。在输入序列中,BERT随机掩盖一些词语,并让模型预测这些被掩盖的词语。这种方式使BERT能够从上下文中学习词语的语义和语境信息。
GPT:GPT使用了自回归语言模型的训练方式。它通过让模型预测当前位置的词语来学习生成文本的能力。在预训练过程中,GPT逐步生成下一个词语,并优化参数以最大化下一个词语的概率。

上下文理解能力:
两种基于Transformer架构的预训练模型,它们在上下文理解能力和应用领域上有所不同。

  • BERT:由于BERT采用双向模型,通过预测被掩盖的词语和判断句子之间的关系。它可以从上下文中获取更丰富的信息,并具有较强的上下文理解能力。这使得BERT在词语级别的任务中表现出色,如命名实体识别、问答等。
  • GPT:GPT是一个单向模型,它只能依赖已生成的上文来预测下一个词语。在预训练过程中,GPT使用自回归语言模型进行训练,通过逐步生成下一个词语来学习生成连贯的文本。由于单向模型的限制,GPT在生成式任务中表现较好,如对话生成、文本生成等。GPT能够生成具有上下文连贯性和逻辑性的文本,因为它在生成每个词语时都能考虑之前已生成的上文。

下游任务适用性:

  • BERT:由于BERT具有强大的上下文理解能力和双向模型的特点,它在各种下游任务中表现优秀,如文本分类、命名实体识别、语义关系判断等。
  • GPT:GPT主要用于生成式任务,如对话生成、文本生成和机器翻译等。它能够生成自然流畅的文本,但在一些需要输入-输出对齐的任务中效果较弱。预训练的GPT模型是生成式的,而在具体应用中,可以通过微调(fine-tuning)将GPT用于特定的下游任务。在微调阶段,可以添加任务特定的层或结构,并使用有标签的任务数据来进一步调整模型,使其适应特定任务的要求。

总体而言,BERT和GPT在目标任务、训练方式、上下文理解能力和适用性上存在差异。BERT适用于各种下游任务,而GPT主要用于生成式任务。选择哪种模型取决于具体的任务需求和应用场景。

代码

Bert实现代码。在这里使用动手学深度学习提供的代码讲解

import torch
from torch import nn
from d2l import torch as d2l

#@save
def get_tokens_and_segments(tokens_a, tokens_b=None):
    """获取输入序列的词元及其片段索引"""
    tokens = ['<cls>'] + tokens_a + ['<sep>']
    # 0和1分别标记片段A和B
    segments = [0] * (len(tokens_a) + 2)
    if tokens_b is not None:
        tokens += tokens_b + ['<sep>']
        segments += [1] * (len(tokens_b) + 1)
    return tokens, segments

#@save
class BERTEncoder(nn.Module):
    """BERT编码器"""
    def __init__(self, vocab_size, num_hiddens, norm_shape, ffn_num_input,
                 ffn_num_hiddens, num_heads, num_layers, dropout,
                 max_len=1000, key_size=768, query_size=768, value_size=768,
                 **kwargs):
        super(BERTEncoder, self).__init__(**kwargs)
        self.token_embedding = nn.Embedding(vocab_size, num_hiddens)
        self.segment_embedding = nn.Embedding(2, num_hiddens)
        self.blks = nn.Sequential()
        for i in range(num_layers):
            self.blks.add_module(f"{i}", d2l.EncoderBlock(
                key_size, query_size, value_size, num_hiddens, norm_shape,
                ffn_num_input, ffn_num_hiddens, num_heads, dropout, True))
        # 在BERT中,位置嵌入是可学习的,因此我们创建一个足够长的位置嵌入参数
        self.pos_embedding = nn.Parameter(torch.randn(1, max_len,
                                                      num_hiddens))

    def forward(self, tokens, segments, valid_lens):
        # 在以下代码段中,X的形状保持不变:(批量大小,最大序列长度,num_hiddens)
        X = self.token_embedding(tokens) + self.segment_embedding(segments)
        X = X + self.pos_embedding.data[:, :X.shape[1], :]
        for blk in self.blks:
            X = blk(X, valid_lens)
        return X


#@save
class MaskLM(nn.Module):
    """BERT的掩蔽语言模型任务"""
    def __init__(self, vocab_size, num_hiddens, num_inputs=768, **kwargs):
        super(MaskLM, self).__init__(**kwargs)
        self.mlp = nn.Sequential(nn.Linear(num_inputs, num_hiddens),
                                 nn.ReLU(),
                                 nn.LayerNorm(num_hiddens),
                                 nn.Linear(num_hiddens, vocab_size))

    def forward(self, X, pred_positions):
        num_pred_positions = pred_positions.shape[1]
        pred_positions = pred_positions.reshape(-1)
        batch_size = X.shape[0]
        batch_idx = torch.arange(0, batch_size)
        # 假设batch_size=2,num_pred_positions=3
        # 那么batch_idx是np.array([0,0,0,1,1,1])
        batch_idx = torch.repeat_interleave(batch_idx, num_pred_positions)
        masked_X = X[batch_idx, pred_positions]
        masked_X = masked_X.reshape((batch_size, num_pred_positions, -1))
        mlm_Y_hat = self.mlp(masked_X)
        return mlm_Y_hat

#@save
class NextSentencePred(nn.Module):
    """BERT的下一句预测任务"""
    def __init__(self, num_inputs, **kwargs):
        super(NextSentencePred, self).__init__(**kwargs)
        self.output = nn.Linear(num_inputs, 2)

    def forward(self, X):
        # X的形状:(batchsize,num_hiddens)
        return self.output(X)


#@save
class BERTModel(nn.Module):
    """BERT模型"""
    def __init__(self, vocab_size, num_hiddens, norm_shape, ffn_num_input,
                 ffn_num_hiddens, num_heads, num_layers, dropout,
                 max_len=1000, key_size=768, query_size=768, value_size=768,
                 hid_in_features=768, mlm_in_features=768,
                 nsp_in_features=768):
        super(BERTModel, self).__init__()
        self.encoder = BERTEncoder(vocab_size, num_hiddens, norm_shape,
                    ffn_num_input, ffn_num_hiddens, num_heads, num_layers,
                    dropout, max_len=max_len, key_size=key_size,
                    query_size=query_size, value_size=value_size)
        self.hidden = nn.Sequential(nn.Linear(hid_in_features, num_hiddens),
                                    nn.Tanh())
        self.mlm = MaskLM(vocab_size, num_hiddens, mlm_in_features)
        self.nsp = NextSentencePred(nsp_in_features)

    def forward(self, tokens, segments, valid_lens=None,
                pred_positions=None):
        encoded_X = self.encoder(tokens, segments, valid_lens)
        if pred_positions is not None:
            mlm_Y_hat = self.mlm(encoded_X, pred_positions)
        else:
            mlm_Y_hat = None
        # 用于下一句预测的多层感知机分类器的隐藏层,0是“<cls>”标记的索引
        nsp_Y_hat = self.nsp(self.hidden(encoded_X[:, 0, :]))
        return encoded_X, mlm_Y_hat, nsp_Y_hat

GPT代码。此处以GPT2作为代码解释

import torch
import torch.nn as nn
from transformers import GPT2Model, GPT2Tokenizer

class GPT2(nn.Module):
    def __init__(self, num_layers, d_model, num_heads, d_ff, vocab_size, max_sequence_length):
        super(GPT2, self).__init__()
        self.tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
        self.embedding = nn.Embedding(vocab_size, d_model)
        self.transformer = GPT2Model(
            num_layers=num_layers,
            d_model=d_model,
            nhead=num_heads,
            dim_feedforward=d_ff,
            max_position_embeddings=max_sequence_length
        )
        self.fc = nn.Linear(d_model, vocab_size)
    
    def forward(self, inputs):
        embedded = self.embedding(inputs)
        outputs = self.transformer(embedded)
        logits = self.fc(outputs.last_hidden_state)
        return logits

# GPT-2 hyperparameters
num_layers = 12
d_model = 768
num_heads = 12
d_ff = 3072
vocab_size = 50257
max_sequence_length = 1024

# Create GPT-2 model instance
model = GPT2(num_layers, d_model, num_heads, d_ff, vocab_size, max_sequence_length)

# Example input
input_ids = torch.tensor([[31, 51, 99, 18, 42, 62]])  # Input token IDs

# Forward pass
logits = model(input_ids)

上述代码是一个简化的实现示例,使用了PyTorch和Hugging Face的transformers库。GPT-2模型使用了GPT-2的预训练权重,其中的GPT2Model是GPT-2的主体Transformer模型,GPT2Tokenizer用于将文本转换为模型所需的输入。

未完待续!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/613367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(Day1)配置云开发提供的模板

创建云开发项目 打开微信开发者工具&#xff1b;点击“项目”->“新建项目”&#xff1b;输入项目名称和选择项目所要保存的目录&#xff1b;输入自己的AppID&#xff1b; AppID的获取&#xff0c;需要登陆微信公众平台&#xff0c;并点击“开发管理”->"开发设置…

凸优化系列——凸函数

1.凸函数的定义 凸函数直观上来说&#xff0c;就是两点之间的函数值小于两点连线的函数值 常见凸函数 线性函数既是凸函数&#xff0c;也是凹函数 对于二次函数&#xff0c;如果Q矩阵是半正定矩阵&#xff0c;那么它的二阶导为Q为半正定矩阵&#xff0c;根据凸性判定的二阶条…

SpringCloud微服务架构 --- 高级篇

一、初识Sentinel 1.1、雪崩问题及解决方案 1.1.1、雪崩问题 微服务调用链路中的某个服务故障&#xff0c;引起整个链路中的所有微服务都不可用&#xff0c;这就是雪崩。 1.1.2、解决雪崩问题的常见方式有四种 1.1.2.1、超时处理 设定超时时间&#xff0c;请求超过一定时间…

Swagger原理

最近在基于Swagger进行二次开发&#xff0c; 来对项目的接口进行管理&#xff0c;功能实现了&#xff0c;但是不清楚swagger的工作原理&#xff0c;为了后续能更好利用Swagger来管理接口&#xff0c;而且能借鉴Swagger的原理&#xff0c;将项目中其他信息可视化展示&#xff0c…

什么是测试驱动开发?测试驱动开发有什么优点?

目录 前言 什么是TDD或测试驱动开发&#xff1f; 什么是软件单元测试&#xff1f; 什么是TDD&#xff1f; 测试驱动开发的好处 最后的想法 前言 测试是任何软件开发项目中最重要的步骤之一。如果跳过此过程&#xff0c;则结果可能是灾难性的-对项目和公司而言。但是什么时…

K8s in Action 阅读笔记——【11】Understanding Kubernetes internals

K8s in Action 阅读笔记——【11】Understanding Kubernetes internals 11.1 Understanding the architecture Kubernetes集群分为两个部分&#xff1a; k8s控制平面工作节点 控制平面的组件 构成控制平面的组件有&#xff1a; etcd&#xff1a;etcd是一个分布式的持久化键…

javascrip基础二十八:说说函数节流和防抖?有什么区别?如何实现?

一、是什么 本质上是优化高频率执行代码的一种手段 如&#xff1a;浏览器的 resize、scroll、keypress、mousemove 等事件在触发时&#xff0c;会不断地调用绑定在事件上的回调函数&#xff0c;极大地浪费资源&#xff0c;降低前端性能 为了优化体验&#xff0c;需要对这类事…

类与对象知识总结+构造函数和析构函数 C++程序设计与算法笔记总结(二) 北京大学 郭炜

类和对象 结构化程序设计 C语言使用结构化程序设计&#xff1a; 程序 数据结构 算法 程序由全局变量以及众多相互调用的函数组成。 算法以函数的形式实现&#xff0c;用于对数据结构进行操作。 结构化程序设计的不足&#xff1a; 结构化程序设计中&#xff0c;函数和其所…

《嵌入式系统》知识总结11:STM32串口

串行通信vs并行通信 • 并行&#xff1a;使用8根数据线一次传送一个字节&#xff08;或使用16根数据线一次传送2个字节&#xff0c;...&#xff09; • 串行&#xff1a;使用少量数据信号线&#xff08;8根以下&#xff09;&#xff0c;将数据逐位分时传送 • 并行vs串行&…

路径规划算法:基于秃鹰优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于秃鹰优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于秃鹰优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法秃鹰…

【三维编辑】Removing Objects From Neural Radiance Fields论文解读

题目&#xff1a;Removing Objects From NeRF 从神经辐射场中移除对象 论文&#xff1a;https://arxiv.org/abs/2212.11966 作者:Silvan Weder,Guillermo Niantic, ETH Zurich, University College London, nianticlabs.github.ionerf-object-removal 文章目录 摘要一、前言二、…

Batch Normalization原理

首先我们提出一个问题&#xff0c;为什么要有Batch Normalization这样神奇的操作&#xff1f;原有的深度神经网络是有什么问题吗&#xff1f; 还真有问题&#xff0c;那就要提到各位炼丹师们的困境&#xff0c;在深度学习中&#xff0c;模型的层数往往非常的巨大&#xff0c;尤…

SpringBootWeb AOP(下)

3. AOP进阶 AOP的基础知识学习完之后&#xff0c;下面我们对AOP当中的各个细节进行详细的学习。主要分为4个部分&#xff1a; 通知类型通知顺序切入点表达式连接点 我们先来学习第一部分通知类型。 3.1 通知类型 在入门程序当中&#xff0c;我们已经使用了一种功能最为强大…

磁盘配额与进阶文件系统管理(二)

逻辑卷管理(Logical Volume Manager) 简介&#xff1a;lvm可以弹性调节filesystem容量&#xff1b;lvm可以整合多个实体partion在一起&#xff0c;使得多个partion看起来像一个磁盘。 LVM基本概念 PV&#xff1a;物理卷 PE&#xff1a;实体范围区块 VG&#xff1a;卷组 …

前端食堂技术周刊第 85 期:5 月浏览器更新、TypeScript 5.1、Rspack 0.2.0、Parcel v2.9.0、Next.js 企业级模板

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;龙井酥 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 本期摘要 5 月登陆浏览器的新功能TypeScript 5.1Rspack 0.2.0Parcel v2.9.0Next.js 企…

DINO代码学习笔记(四)

DINO代码学习笔记&#xff08;一&#xff09;中已经将输入transformer之前的参数处理给捋了一遍 DINO代码学习笔记&#xff08;二&#xff09;中将encoder部分给捋了一遍 DINO代码学习笔记&#xff08;三&#xff09;中将decoder部分给捋了一遍&#xff0c;以上将DINO的主体部…

聊一聊Spring Security的那些事

一.什么是Spring Security S[ing Security是一个基于Java EE框架Spring的安全性框架&#xff0c;它提供了身份认证和授权功能&#xff0c;用于保护应用程序中的资源。同时&#xff0c;它也支持许多常见的身份验证机制&#xff0c;并提供了预防常见攻击&#xff0c;如跨站请求伪…

[230603]托福听力精听|TPO66C2|Financial Advice

tuition bill 学费 add up 加总 allowance 补贴 budget 预算 document 文件 expense 费用&#xff1b;开销 semester 学期 dorm 宿舍 own 拥有&#xff1b;自己的 bulletin board…

SpringCloud微服务架构 --- 基础篇

一、认识微服务 1.1、服务架构演变 1.1.1、单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 单体架构的优缺点如下&#xff1a; 优点&#xff1a; 架构简单部署成本低 缺点&#xff1a; 耦合度高&#xff08;维护困难、…

基于Xilinx K7-410T的高速DAC之AD9129开发笔记(一)

引言&#xff1a;从本文开始&#xff0c;我们介绍下项目中设计的并行LVDS高速DAC接口设计&#xff0c;包括DAC与FPGA硬件接口设计、软件设计等。项目设计高速DAC采用了ADI公司的AD9129&#xff0c;该芯片最大更新速率5.7Gsps&#xff0c;该芯片在宽带通信应用、LTE、雷达信号产…