BERT和GPT作为Transformer架构的杰出代表,分别擅长双向编码和单向生成任务。BERT通过同时关注上下文信息,实现全面的语言理解,适用于分类、问答等任务;GPT则依据单向生成机制,逐词预测生成文本,更适用于对话生成、文本续写等场景。本文深入剖析了BERT和GPT的架构特点、训练方法及实际应用,并通过代码示例展示了它们在自然语言处理领域的强大能力,为读者提供了理解与创造的双子星技术解析。


BERT(Bidirectional Encoder Representations from Transformers)和 GPT(Generative Pre-trained Transformer)作为 Transformer 架构的两大代表性模型,分别在双向编码和单向生成任务中展现了独特优势。BERT 采用双向编码器结构,能够同时关注上下文信息,适用于分类、问答等需要全面理解输入文本的任务;GPT 则基于单向生成器结构,按照从左到右的顺序生成文本,更擅长对话生成、文本续写等任务。

两者在任务适用性和信息处理方式上各有千秋,共同丰富了 Transformer 架构在自然语言处理领域的应用场景。

一、BERT 架构:双向理解的语言高手

BERT 架构基于双向编码器设计,通过同时关注上下文的前后信息,实现了全面的信息编码。其架构由多个 Transformer 编码层堆叠而成,每层包含自注意力机制和前馈神经网络(Feed-Forward Network),使模型能够捕获深层的语义信息。BERT 结构如图 1 所示。

图1 BERT 语言模型结构图

BERT 通过掩码语言模型(Masked Language Model,MLM)任务进行预训练:在输入序列中随机掩盖部分词,然后根据上下文预测被掩盖的词。这种训练方式让模型学会了真正“理解”语言。

如果把 BERT 比作一位优秀的“语言理解高手”,它的任务就是通过阅读上下文,全面把握句子的含义。名字中的“Bidirectional”(双向)表明,它在理解句子时会同时考虑单词前后的信息,而非单向处理。

想象你正在玩一个拼图游戏,每一块拼图代表句子中的一个单词,只有正确组合才能完整表达句子的含义。BERT 就像一个“聪明的拼图助手”,它会仔细观察每一块拼图,分析它跟周围拼图的关系,最终帮你把句子拼完整。具体来说:

  • Transformer 编码器:BERT 完全由一组 Transformer 编码器组成,每个编码器就像一个“拼图分析师”,关注每个单词与其他单词的关系。
  • 自注意力机制:通过自注意力机制,BERT 可以为每个单词生成“权重分布”,告诉模型哪些单词对当前单词更重要。例如,在句子“我喜欢吃苹果”中,“喜欢”会特别关注“吃”和“苹果”,而对“我”的关注相对较少。
  • 多层编码:BERT 有多层编码器(如12层或24层),每一层都会对单词和上下文关系进行更深层次的分析,就像“拼图助手”一遍遍检查拼图的组合方式。

此外,BERT 在句子对任务中引入了下一句预测(Next Sentence Prediction)任务,使其更适用于分类、问答等自然语言理解场景。以下代码展示了 BERT 架构的基本应用,包括模型加载、文本嵌入和双向信息编码。

import torchimport torch.nn as nnimport os# 设置 Hugging Face 镜像源,解决国内网络访问问题os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'from transformers import BertModel, BertTokenizer# 定义 BERT 分类模型class BERTClassifier(nn.Module):    """    BERT 分类器模型    在预训练的 BERT 基础上添加一个分类头,用于文本分类任务    """    def __init__(self, bert_model_name, num_classes):        """        初始化 BERT 分类器        参数:            bert_model_name: str, 预训练 BERT 模型名称,如 'bert-base-uncased'            num_classes: int, 分类的类别数量        """        super(BERTClassifier, self).__init__()        # 加载预训练的 BERT 模型        # from_pretrained 会从 Hugging Face 下载模型权重(如果本地没有缓存)        self.bert = BertModel.from_pretrained(bert_model_name)        # 全连接分类层        # bert.config.hidden_size 是 BERT 隐藏层维度,对于 bert-base-uncased 是 768        # 将 768 维的 BERT 输出映射到 num_classes 维,得到每个类别的分数        self.fc = nn.Linear(self.bert.config.hidden_size, num_classes)        # Dropout 层,防止过拟合        # 以 0.3 的概率随机丢弃神经元,增强模型的泛化能力        self.dropout = nn.Dropout(0.3)    def forward(self, input_ids, attention_mask):        """        前向传播函数        参数:            input_ids: tensor, 形状 [batch_size, seq_len],文本的 token ID 序列            attention_mask: tensor, 形状 [batch_size, seq_len],注意力掩码,1 表示真实 token,0 表示 padding        返回:            out: tensor, 形状 [batch_size, num_classes],每个类别的分数(logits)        """        # 1. 通过 BERT 模型获取上下文表示        # outputs 包含多个元素:last_hidden_state, pooler_output, hidden_states 等        outputs = self.bert(            input_ids=input_ids,            attention_mask=attention_mask        )        # 2. 提取 [CLS] 标记的隐藏状态        # BERT 的第一个 token 是 [CLS],它的输出被设计用于分类任务        # outputs.last_hidden_state 形状: [batch_size, seq_len, hidden_size]        # [:, 0, :] 表示取所有样本的第一个 token([CLS])的所有隐藏维度        cls_output = outputs.last_hidden_state[:, 0, :]  # 形状: [batch_size, hidden_size]        # 3. 应用 Dropout 防止过拟合        cls_output = self.dropout(cls_output)        # 4. 通过全连接层得到分类分数(logits)        out = self.fc(cls_output)  # 形状: [batch_size, num_classes]        return out# ==================== 模型加载和推理部分 ====================# 加载 BERT 分词器和模型bert_model_name = 'bert-base-uncased'# BERT base 模型,uncased 表示不区分大小写print("正在加载模型和分词器...")# 加载分词器:将文本转换为 BERT 可接受的输入格式tokenizer = BertTokenizer.from_pretrained(bert_model_name)# 创建 BERT 分类器实例# num_classes=2 表示二分类任务(正面/负面情感分类)model = BERTClassifier(bert_model_name, num_classes=2)# 输入文本示例texts = [    "This is a positive example.",  # 正面情感示例    "This is a negative example."# 负面情感示例]# 对文本进行编码,转换为模型输入格式encodings = tokenizer(    texts,  # 待编码的文本列表    return_tensors="pt",  # 返回 PyTorch 张量格式    padding=True,  # 对较短的序列进行填充,使所有序列长度一致    truncation=True,  # 对过长的序列进行截断    max_length=32# 设置最大序列长度为 32)# 设置模型为评估模式# eval() 会关闭 dropout 和 batch normalization 的训练模式,使用固定的参数# 这对于推理非常重要,确保每次推理结果一致model.eval()# 模型推理(不计算梯度,节省内存和计算资源)# torch.no_grad() 上下文管理器会禁用梯度计算,大幅减少内存占用with torch.no_grad():    input_ids = encodings["input_ids"]  # 获取 token IDs    attention_mask = encodings["attention_mask"]  # 获取注意力掩码    output = model(input_ids, attention_mask)  # 前向传播,得到 logits# ==================== 输出结果解释 ====================print("\n" + "=" * 50)print("BERT模型输出详解")print("=" * 50)print("\nBERT模型输出形状:", output.shape)print("输出形状解释:")print(f"  - 第0维({output.shape[0]}):批次大小(batch size),表示同时处理了 {output.shape[0]} 个样本")print(f"  - 第1维({output.shape[1]}):类别数量,表示模型为每个样本预测 {output.shape[1]} 个类别的分数")print("\nBERT模型输出(logits):")print(output)print("\nLogits 解释:")print("  - Logits 是模型最后一层全连接层的原始输出,取值范围是 (-∞, +∞)")print("  - 数值越大表示模型认为该样本属于对应类别的可能性越大")print(f"  - 第一个样本(正面示例):类别0分数={output[0][0]:.4f},类别1分数={output[0][1]:.4f}")print(f"  - 第二个样本(负面示例):类别0分数={output[1][0]:.4f},类别1分数={output[1][1]:.4f}")# 应用 softmax 获取概率分布# Softmax 将 logits 转换为概率分布,确保所有类别的概率和为 1probabilities = torch.softmax(output, dim=-1)print("\n" + "=" * 50)print("概率分布详解")print("=" * 50)print("\n概率分布:", probabilities)print("\n概率分布解释:")print("  - Softmax 将 logits 转换为 [0, 1] 范围内的概率值")print("  - 所有类别的概率之和为 1")print(f"  - 第一个样本:类别0(负面)概率={probabilities[0][0]:.4f},类别1(正面)概率={probabilities[0][1]:.4f}")print(    f"    → 预测为 {'正面' if probabilities[0][1] > probabilities[0][0] else '负面'},置信度={max(probabilities[0]):.2%}")print(f"  - 第二个样本:类别0(负面)概率={probabilities[1][0]:.4f},类别1(正面)概率={probabilities[1][1]:.4f}")print(    f"    → 预测为 {'正面' if probabilities[1][1] > probabilities[1][0] else '负面'},置信度={max(probabilities[1]):.2%}")# 获取预测类别(取概率最大的类别索引)predictions = torch.argmax(probabilities, dim=-1)print("\n" + "=" * 50)print("最终预测结果")print("=" * 50)print("\n预测类别:", predictions)print("\n预测类别解释:")print(f"  - 第一个样本('This is a positive example.')预测为类别 {predictions[0].item()}")print(f"    → 类别映射:0=负面,1=正面,因此预测结果为:{'正面' if predictions[0].item() == 1 else '负面'}")print(f"  - 第二个样本('This is a negative example.')预测为类别 {predictions[1].item()}")print(f"    → 类别映射:0=负面,1=正面,因此预测结果为:{'正面' if predictions[1].item() == 1 else '负面'}")

运行结果如下:

==================================================BERT模型输出详解==================================================BERT模型输出形状: torch.Size([2, 2])输出形状解释:  - 第0维(2):批次大小(batch size),表示同时处理了 2 个样本  - 第1维(2):类别数量,表示模型为每个样本预测 2 个类别的分数BERT模型输出(logits):tensor([[0.0925, 0.6015],        [0.0993, 0.5602]])Logits 解释:  - Logits 是模型最后一层全连接层的原始输出,取值范围是 (-∞, +∞)  - 数值越大表示模型认为该样本属于对应类别的可能性越大  - 第一个样本(正面示例):类别0分数=0.0925,类别1分数=0.6015  - 第二个样本(负面示例):类别0分数=0.0993,类别1分数=0.5602==================================================概率分布详解==================================================概率分布: tensor([[0.3754, 0.6246],        [0.3868, 0.6132]])概率分布解释:  - Softmax 将 logits 转换为 [0, 1] 范围内的概率值  - 所有类别的概率之和为 1  - 第一个样本:类别0(负面)概率=0.3754,类别1(正面)概率=0.6246    → 预测为 正面,置信度=62.46%  - 第二个样本:类别0(负面)概率=0.3868,类别1(正面)概率=0.6132    → 预测为 正面,置信度=61.32%==================================================最终预测结果==================================================预测类别: tensor([1, 1])预测类别解释:  - 第一个样本('This is a positive example.')预测为类别 1    → 类别映射:0=负面,1=正面,因此预测结果为:正面  - 第二个样本('This is a negative example.')预测为类别 1    → 类别映射:0=负面,1=正面,因此预测结果为:正面进程已结束,退出代码为 0

注意:由于分类头是随机初始化的(未经过训练),预测结果可能与预期不符。只有经过充分训练后,模型才能实现正确的分类。以上代码仅为示例演示。

二、GPT 架构:单向生成的创作大师

GPT 基于单向生成器架构,通过从左到右的顺序预测下一个词来生成文本。与 BERT 的双向注意力机制不同,GPT 采用单向注意力机制,仅依赖先前的上下文信息,这使得它天然适合自然语言生成任务,如文本续写和对话生成。GPT 架构由多个 Transformer 解码层堆叠而成,每层包含自注意力机制和前馈神经网络。

以下代码展示了 GPT 的基本应用,包括模型加载、输入编码、文本生成等,充分展现了GPT在生成任务中的强大能力。

# ==================== 导入必要的库 ====================import torch  # PyTorch深度学习框架,用于张量计算和神经网络import torch.nn as nn  # PyTorch的神经网络模块import os  # 操作系统接口,用于设置环境变量import sys  # 系统相关功能,用于程序退出控制# ==================== 配置环境 ====================# 设置 Hugging Face 镜像源,解决国内网络访问问题# HF_ENDPOINT 环境变量指定 Hugging Face 模型的下载源# 使用镜像站可以大幅提高国内用户的下载速度os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'# 从 transformers 库导入 GPT-2 模型和分词器# transformers 是 Hugging Face 开发的预训练模型库# GPT2LMHeadModel: GPT-2 语言模型,专门用于文本生成任务# GPT2Tokenizer: GPT-2 的分词器,负责文本和token之间的转换from transformers import GPT2LMHeadModel, GPT2Tokenizer# ==================== 模型加载部分 ====================print("开始加载 GPT-2 模型...")print("首次运行会下载模型文件(约500MB),请耐心等待...")try:    # ---------- 加载分词器 ----------    # Tokenizer(分词器)的作用:    # 1. 将文本字符串转换为模型可理解的数字ID序列    # 2. 处理特殊token(如开始符、结束符、填充符等)    # 3. 管理词汇表(GPT-2的词汇表大小约50,000)    tokenizer = GPT2Tokenizer.from_pretrained(        "gpt2",  # 模型名称,可选值: "gpt2", "gpt2-medium", "gpt2-large", "gpt2-xl"        # resume_download=True,  # 注意:此参数在新版transformers中已移除,自动支持断点续传        # use_auth_token=False   # 注意:此参数已废弃,无需指定    )    # from_pretrained() 会:    # - 检查本地缓存中是否有模型    # - 如果没有,从 Hugging Face 下载    # - 自动处理断点续传    print("✓ 分词器加载完成")        # ---------- 加载模型 ----------    # GPT-2 模型架构:    # - 12层 Transformer 解码器(基础版)    # - 768维隐藏层    # - 12个注意力头    # - 约1.24亿参数    model = GPT2LMHeadModel.from_pretrained(        "gpt2",  # 与分词器使用相同的模型版本    )    print("✓ 模型加载完成")    except Exception as e:    # 如果加载失败,打印错误信息并退出    print(f"加载失败: {e}")    print("请检查网络连接或尝试其他方法")    print("\n解决方案建议:")    print("1. 检查网络连接是否正常")    print("2. 尝试使用VPN或代理")    print("3. 手动下载模型: pip install huggingface_hub && huggingface-cli download gpt2")    sys.exit(1)  # 使用状态码1表示异常退出# ==================== 模型配置 ====================# 设置填充token(Padding Token)# GPT-2 模型默认没有设置 pad_token,需要手动配置# 填充token的作用:# - 使同一个batch中的序列长度一致# - 在生成时用于指定停止位置if tokenizer.pad_token isNone:    # 使用结束符(End Of Sentence)作为填充符    # eos_token: 表示文本结束的特殊token,通常是 "<|endoftext|>"    tokenizer.pad_token = tokenizer.eos_token    print(f"已设置 pad_token: {tokenizer.pad_token}")# ==================== 输入准备 ====================# 定义输入文本作为生成的起点(提示词)input_text = "Once upon a time in a distant land,"# 将输入文本转换为token ID序列# encode() 方法的工作流程:# 1. 将文本分割成tokens(使用Byte-Pair Encoding)# 2. 将每个token映射到词汇表中的数字ID# 3. 添加特殊token(如开始符)# return_tensors="pt": 指定返回PyTorch张量格式# pt = PyTorch, tf = TensorFlow, np = NumPyinput_ids = tokenizer.encode(input_text, return_tensors="pt")# 查看输入信息的形状和内容(可选调试信息)print(f"\n输入文本: {input_text}")print(f"输入token数量: {input_ids.shape[1]}")  # shape: [batch_size, sequence_length]print("开始生成文本...")# ==================== 文本生成 ====================# generate() 方法:GPT-2的核心生成函数# 使用自回归方式生成文本,即逐个预测下一个token# 生成过程:输入 -> 预测下一个token -> 拼接到输入 -> 重复直到满足条件output_sequences = model.generate(    # ----- 基础参数 -----    input_ids=input_ids,  # 输入的token ID序列,形状为 [1, 输入长度]                         # 这是生成的起点        max_length=50,  # 生成的最大总长度(包括输入文本)                    # 例如:输入10个token,最多生成40个新token                    # 当达到此长度时停止生成        num_return_sequences=1,  # 返回的生成序列数量                              # 可以设置为 >1 生成多个不同的续写结果                              # 每个序列独立采样        # ----- 防止重复参数 -----    no_repeat_ngram_size=2,  # 防止重复的n-gram                             # 2表示禁止任何2-gram(连续两个token)重复出现                             # 例如:如果已经出现"the cat",就不能再次出现"the cat"                             # 这样可以提高生成文本的多样性,避免循环        # ----- 采样策略参数 -----    top_k=50,  # Top-K 采样               # 原理:只从概率最高的K个token中进行采样               # 设置50:只考虑概率最高的50个候选token               # 优点:过滤掉低概率的不合理token               # 缺点:可能会过滤掉一些创意性的选择               # 常用范围:10-100        top_p=0.95,  # Top-P(核)采样                 # 原理:选择概率最高的token,直到累计概率达到p                 # 设置0.95:选择一组token,使其总概率达到95%                 # 与top_k结合使用,动态调整候选token数量                 # 常用范围:0.8-1.0        temperature=0.7,  # 温度参数                      # 原理:控制概率分布的平滑程度                      # 公式:p'(x) = exp(log(p(x))/temperature)                      #                       # 效果:                      # - 温度 < 1:使分布更陡峭,高概率token更高,生成更确定                      # - 温度 = 1:原始概率分布                      # - 温度 > 1:使分布更平滑,低概率token概率提高,生成更有创意                      #                      # 常用值:                      # - 0.3-0.5:保守、确定性生成                      # - 0.7-0.9:平衡创意和质量(推荐)                      # - 1.0-1.2:创意性生成        # ----- 其他参数 -----    pad_token_id=tokenizer.pad_token_id,  # 填充token的ID                                          # 用于确保所有序列长度一致                                          # 生成时遇到pad_token会停止)# ==================== 结果解码 ====================# 将生成的token ID序列解码回可读文本# output_sequences[0]: 获取第一个生成序列(因为num_return_sequences=1)# decode() 的工作流程:# 1. 将每个token ID映射回对应的文本token# 2. 将tokens拼接成完整的字符串# 3. 处理特殊tokengenerated_text = tokenizer.decode(    output_sequences[0],  # 要解码的token序列    skip_special_tokens=True# 跳过特殊token(如<|endoftext|>、<pad>等)                              # 只保留实际文本内容)# ==================== 输出结果 ====================print("\n" + "=" * 50)print("GPT 模型生成的文本:")print(generated_text)print("=" * 50)# ==================== 附加统计信息 ====================# 打印生成过程的统计信息,帮助理解生成效果input_token_count = input_ids.shape[1]  # 输入token的数量output_token_count = output_sequences.shape[1]  # 输出总token数量new_token_count = output_token_count - input_token_count  # 新生成的token数量print(f"\n生成统计信息:")print(f"- 输入文本长度: {len(input_text)} 字符")print(f"- 输出文本长度: {len(generated_text)} 字符")print(f"- 输入token数量: {input_token_count}")print(f"- 输出总token数量: {output_token_count}")print(f"- 新生成token数量: {new_token_count}")

运行结果示例:

从运行结果可以看出,GPT 模型能够基于给定的开头,生成连贯流畅的故事文本,充分展现了其在自然语言生成任务中的卓越能力。

三、总结:理解与创造的双子星

BERT 和 GPT 代表了 Transformer 架构在自然语言处理领域的两个重要方向:

  • BERT 像一位严谨的学者:通过双向理解,全面把握文本含义,在分类、问答等理解型任务中表现出色。
  • GPT 像一位富有创意的作家:通过单向生成,源源不断地创造新文本,在续写、对话等生成型任务中独树一帜。

两者各有所长,相辅相成。理解它们的设计哲学和适用场景,能够帮助我们在实际应用中做出更明智的模型选择。随着大模型技术的不断发展,BERT 和 GPT 的思想也深深影响着后续模型的设计,成为现代自然语言处理不可或缺的基础。

AI行业迎来前所未有的爆发式增长:从DeepSeek百万年薪招聘AI研究员,到百度、阿里、腾讯等大厂疯狂布局AI Agent,再到国家政策大力扶持数字经济和AI人才培养,所有信号都在告诉我们:AI的黄金十年,真的来了!

在行业火爆之下,AI人才争夺战也日趋白热化,其就业前景一片蓝海!

我给大家准备了一份全套的《AI大模型零基础入门+进阶学习资源包》,包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。😝有需要的小伙伴,可以VX扫描下方二维码免费领取🆓

在这里插入图片描述

人才缺口巨大

人力资源社会保障部有关报告显示,据测算,当前,****我国人工智能人才缺口超过500万,****供求比例达1∶10。脉脉最新数据也显示:AI新发岗位量较去年初暴增29倍,超1000家AI企业释放7.2万+岗位……

单拿今年的秋招来说,各互联网大厂释放出来的招聘信息中,我们就能感受到AI浪潮,比如百度90%的技术岗都与AI相关!
图片

就业薪资超高

在旺盛的市场需求下,AI岗位不仅招聘量大,薪资待遇更是“一骑绝尘”。企业为抢AI核心人才,薪资给的非常慷慨,过去一年,懂AI的人才普遍涨薪40%+!

脉脉高聘发布的《2025年度人才迁徙报告》显示,在2025年1月-10月的高薪岗位Top20排行中,AI相关岗位占了绝大多数,并且平均薪资月薪都超过6w!

在去年的秋招中,小红书给算法相关岗位的薪资为50k起,字节开出228万元的超高年薪,据《2025年秋季校园招聘白皮书》,AI算法类平均年薪达36.9万,遥遥领先其他行业!

图片

总结来说,当前人工智能岗位需求多,薪资高,前景好。在职场里,选对赛道就能赢在起跑线。抓住AI风口,轻松实现高薪就业!

但现实却是,仍有很多同学不知道如何抓住AI机遇,会遇到很多就业难题,比如:

❌ 技术过时:只会CRUD的开发者,在AI浪潮中沦为“职场裸奔者”;

❌ 薪资停滞:初级岗位内卷到白菜价,传统开发3年经验薪资涨幅不足15%;

❌ 转型无门:想学AI却找不到系统路径,83%自学党中途放弃。

他们的就业难题解决问题的关键在于:不仅要选对赛道,更要跟对老师!

我给大家准备了一份全套的《AI大模型零基础入门+进阶学习资源包》,包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。😝有需要的小伙伴,可以VX扫描下方二维码免费领取🆓

在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐