《深度学习实战》第4集:Transformer 架构与自然语言处理(NLP)

《深度学习实战》第4集:Transformer 架构与自然语言处理(NLP)

在自然语言处理(NLP)领域,Transformer 架构的出现彻底改变了传统的序列建模方法。它不仅成为现代 NLP 的核心,还推动了诸如 BERT、GPT 等预训练模型的发展。本集将带你深入了解 Transformer 的工作原理,并通过实战项目微调 BERT 模型完成情感分析任务。


1. 自注意力机制与多头注意力

1.1 自注意力机制(Self-Attention)

自注意力机制是 Transformer 的核心组件,它允许模型在处理输入序列时关注不同位置的相关性。以下是其工作原理:
在这里插入图片描述

  1. 输入嵌入
    • 输入序列被转换为词向量表示。
  2. 计算注意力权重
    • 通过查询(Query)、键(Key)和值(Value)矩阵计算注意力分数。
    • 注意力分数公式:

在这里插入图片描述

  1. 加权求和
    • 根据注意力分数对值进行加权求和,得到上下文相关的表示。

在这里插入图片描述

1.2 多头注意力(Multi-Head Attention)

为了捕捉不同子空间中的特征,Transformer 使用多头注意力机制。每个“头”独立计算注意力,然后将结果拼接并线性变换。


2. Transformer 的编码器-解码器结构

Transformer 由编码器(Encoder)和解码器(Decoder)两部分组成:

2.1 编码器(Encoder)

  • 编码器由多个相同的层堆叠而成,每层包含:
    • 多头自注意力层:捕捉输入序列的全局依赖关系。
    • 前馈神经网络(FFN):进一步提取特征。
    • 残差连接与层归一化:稳定训练过程。
      在这里插入图片描述

2.2 解码器(Decoder)

  • 解码器同样由多层组成,但额外增加了:
    • 掩码多头注意力(Masked Multi-Head Attention):防止未来信息泄露。
    • 编码器-解码器注意力层:结合编码器输出生成目标序列。
      在这里插入图片描述

好的!为了让你更好地理解 自注意力机制(Self-Attention)多头注意力(Multi-Head Attention) 的底层结构和原理,我会用一个生活中的例子来类比,并逐步拆解它们的工作方式。


3. 自注意力机制:一场“会议讨论”的比喻

想象一下,你正在参加一场公司会议,会议的主题是“如何提高产品销量”。会议室里有几位同事,每个人都有自己的观点。你需要综合大家的意见,得出一个全面的结论。

3.1 每个人的观点

  • 假设会议室里的每个人代表输入序列中的一个单词。
  • 每个人的观点(比如市场分析、用户体验、技术改进等)就是这个单词的嵌入向量(Embedding Vector)。

3.2 问题来了:如何听取所有人的意见?

在会议中,你会根据每个人的发言内容,判断他们的观点对你当前思考的重要性。这就像自注意力机制的核心思想:计算每个单词对当前单词的相关性

具体步骤:
  1. 准备材料(生成 Query、Key 和 Value)

    • 每个人会准备三份材料:
      • Query(提问):你想问的问题,比如“你的建议对我有什么帮助?”
      • Key(关键词):每个人的核心观点,比如“市场分析”或“用户体验”。
      • Value(具体内容):每个人的具体建议,比如“我们需要增加广告预算”。
    • 这些材料通过线性变换(矩阵乘法)从原始观点(嵌入向量)生成。
  2. 打分(计算注意力分数)

    • 你拿着自己的 Query,去和每个人提供的 Key 对比,看看谁的观点和你的问题最相关。
    • 相关性通过点积计算,结果越大表示越相关。
    • 计算公式:
      [
      \text{Attention Score} = \frac{\text{Query} \cdot \text{Key}}{\sqrt{d_k}}
      ]
      (这里的 (\sqrt{d_k}) 是为了防止分数过大,保持数值稳定。)
  3. 加权求和(整合信息)

    • 根据每个人的得分,计算权重(通过 softmax 归一化)。
    • 然后,根据权重对每个人的 Value 进行加权求和,得到最终的结论。

3.3 总结:自注意力机制的作用

自注意力机制的核心是让每个单词都能“看到”整个句子中的其他单词,并根据它们的相关性调整自己的表示。这样,模型可以捕捉到全局的上下文信息。


4. 多头注意力:多个“视角”的讨论

回到刚才的会议场景,假设你不仅关心“如何提高产品销量”,还想知道“哪些用户群体最重要”、“竞争对手有哪些策略”等多个问题。这时,你可以邀请几个专家小组,分别从不同角度分析问题。

4.1 多个“专家小组”

  • 每个专家小组相当于一个多头注意力的一个“头”。
  • 每个小组会独立地进行讨论,生成自己的结论。

4.2 如何整合多个小组的意见?

  • 每个小组的讨论结果(即每个头的输出)会被拼接在一起。
  • 然后通过一个线性变换(矩阵乘法),将这些结果融合成一个最终的结论。

4.3 多头注意力的好处

  • 不同的“头”可以关注输入的不同部分。例如:
    • 一个头可能专注于语法关系(主语和谓语的联系)。
    • 另一个头可能关注语义关系(情感或主题)。
  • 通过多头注意力,模型可以从多个角度提取特征,从而更全面地理解输入。

图解:会议讨论与注意力机制的对应关系

会议讨论注意力机制
每个人的观点输入序列中的单词嵌入向量
提问(Query)查询向量(Query Vector)
关键词(Key)键向量(Key Vector)
具体内容(Value)值向量(Value Vector)
打分并加权求和注意力分数计算 + 加权求和
多个专家小组分别讨论多头注意力的多个“头”

一个具体的例子:翻译句子

假设我们要翻译一句话:“The cat sat on the mat.”(猫坐在垫子上)。

自注意力机制的作用

  • 当处理单词“cat”时,自注意力机制会让它“看到”整个句子。
  • 它会发现“sat”和“mat”与自己高度相关,因为它们描述了猫的动作和位置。

多头注意力的作用

  • 一个头可能专注于语法关系(“cat”是主语,“sat”是谓语)。
  • 另一个头可能专注于语义关系(“cat”和“mat”之间存在空间关系)。
  • 最终,这些信息被整合起来,帮助模型生成更准确的翻译。

关于自注意力机制和多头注意力的总结

  • 自注意力机制:就像你在会议上听取每个人的意见,计算出谁的观点最重要,并据此做出决策。
  • 多头注意力:就像你邀请多个专家小组,从不同角度分析问题,最后整合所有意见。

通过这种机制,Transformer 模型能够高效地捕捉输入序列中的全局依赖关系,从而在自然语言处理任务中表现出色。


5. BERT、GPT 等预训练模型的原理与应用

5.1 BERT(Bidirectional Encoder Representations from Transformers)

  • 特点
    • 双向编码:同时考虑上下文信息。
    • 预训练任务:
      • Masked Language Model(MLM):预测被遮挡的单词。
      • Next Sentence Prediction(NSP):判断句子对是否连续。
  • 应用场景
    • 文本分类、命名实体识别、问答系统等。

5.2 GPT(Generative Pre-trained Transformer)

  • 特点
    • 单向解码:从左到右生成文本。
    • 基于自回归语言模型。
  • 应用场景
    • 文本生成、对话系统、代码补全等。

6. 实战项目:使用 Hugging Face Transformers 微调 BERT 模型

我们将使用 Hugging Face 的 transformers 库微调 BERT 模型,完成情感分析任务。

6.1 数据准备

下载 SST-2数据集,链接如下:SST-2下载链接

import pandas as pd
from sklearn.model_selection import train_test_split
import os
from transformers import BertTokenizer, BertForSequenceClassification
import torch# 设置代理(如果需要)
# os.environ["HTTP_PROXY"] = "http://your_proxy:port"
# os.environ["HTTPS_PROXY"] = "http://your_proxy:port"# 设置离线模式,使用本地文件
# 定义文件路径(根据你的实际路径修改)
train_file = "SST-2/SST-2/train.tsv"
dev_file = "SST-2/SST-2/dev.tsv"

6.2 数据预处理

from transformers import BertTokenizer
# 使用 Pandas 读取 TSV 文件
try:train_data = pd.read_csv(train_file, sep='\t')test_data = pd.read_csv(dev_file, sep='\t')print("成功加载本地数据集")print(train_data.head())
except Exception as e:print(f"加载本地数据集失败: {e}")print("请确保数据文件路径正确")# 尝试加载本地分词器或使用备选方案
try:# 尝试从本地缓存加载cache_dir = "./models_cache"os.makedirs(cache_dir, exist_ok=True)# 使用本地缓存目录tokenizer = BertTokenizer.from_pretrained("bert-base-uncased", cache_dir=cache_dir,local_files_only=False,  # 允许在线下载use_fast=True)print("成功加载分词器")
except OSError as e:print(f"无法加载BERT分词器: {e}")print("尝试使用备选方案...")# 备选方案:使用简单的分词方法from sklearn.feature_extraction.text import CountVectorizervectorizer = CountVectorizer(max_features=10000)print("已切换到简单分词器 (CountVectorizer)")# 定义预处理函数
def preprocess_data(data):sentences = data["sentence"].tolist()labels = data["label"].tolist()try:# 如果BERT分词器加载成功if 'tokenizer' in locals():# 对句子进行分词和编码encodings = tokenizer(sentences,truncation=True,padding="max_length",max_length=128,return_tensors="pt")return encodings, labels, True  # 返回True表示使用BERTelse:# 使用备选分词方法# 注意:这里只对训练数据进行fit_transformif 'vectorizer_fitted' not in globals():global vectorizer_fittedvectorizer_fitted = Truefeatures = vectorizer.fit_transform(sentences)else:# 对于测试数据,只进行transformfeatures = vectorizer.transform(sentences)return features, labels, False  # 返回False表示使用备选方案except Exception as e:print(f"预处理数据时出错: {e}")return None, labels, False# 预处理训练集和测试集
if 'train_data' in locals() and 'test_data' in locals():print("开始预处理数据...")train_features, train_labels, using_bert = preprocess_data(train_data)test_features, test_labels, _ = preprocess_data(test_data)print("数据预处理完成")

6.3 模型定义与训练

import torch
from torch.utils.data import Dataset
import numpy as np
from sklearn.linear_model import LogisticRegressionclass SSTDataset(Dataset):def __init__(self, encodings, labels):self.encodings = encodingsself.labels = labelsself.is_bert_encoding = isinstance(encodings, dict)def __len__(self):if self.is_bert_encoding:return len(self.labels)else:return self.encodings.shape[0]def __getitem__(self, idx):if self.is_bert_encoding:item = {key: val[idx] for key, val in self.encodings.items()}item["labels"] = torch.tensor(self.labels[idx])return itemelse:# 对于非BERT编码,返回稀疏向量的密集表示和标签features = torch.tensor(self.encodings[idx].toarray()[0], dtype=torch.float)label = torch.tensor(self.labels[idx])return {"features": features, "labels": label}# 创建数据集实例
train_dataset = SSTDataset(train_features, train_labels)
test_dataset = SSTDataset(test_features, test_labels)# 根据使用的分词器选择不同的模型训练方法
if using_bert:from transformers import BertForSequenceClassification, Trainer, TrainingArguments# 加载预训练的 BERT 模型(用于二分类任务)model = BertForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=2)# 定义训练参数training_args = TrainingArguments(output_dir="./results",          # 输出目录evaluation_strategy="epoch",     # 每个 epoch 后评估模型per_device_train_batch_size=16,  # 训练时的批量大小per_device_eval_batch_size=16,   # 验证时的批量大小num_train_epochs=3,              # 训练轮数weight_decay=0.01,               # 权重衰减logging_dir="./logs",            # 日志目录logging_steps=10                 # 每 10 步记录一次日志)# 定义 Trainertrainer = Trainer(model=model,args=training_args,train_dataset=train_dataset,eval_dataset=test_dataset)# 开始训练trainer.train()

6.4 测试模型

 # 测试单句预测test_sentence = "This movie was absolutely fantastic!"inputs = tokenizer(test_sentence, return_tensors="pt", truncation=True, padding=True, max_length=128)outputs = model(**inputs)prediction = outputs.logits.argmax(dim=-1).item()# 输出结果print("情感分析结果:", "积极" if prediction == 1 else "消极")
else:print("使用备选方案 (LogisticRegression) 进行训练...")# 将稀疏矩阵转换为numpy数组进行训练X_train = train_features.toarray()X_test = test_features.toarray()# 使用逻辑回归作为备选模型clf = LogisticRegression(max_iter=1000)clf.fit(X_train, train_labels)# 评估模型accuracy = clf.score(X_test, test_labels)print(f"测试集准确率: {accuracy:.4f}")# 测试单句预测test_sentence = "This movie was absolutely fantastic!"# 使用已经训练好的vectorizer进行转换test_features = vectorizer.transform([test_sentence])prediction = clf.predict(test_features)[0]# 输出结果print("情感分析结果:", "积极" if prediction == 1 else "消极")

程序运行结果:

2025-02-27 23:52:05.928189: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2025-02-27 23:52:07.648400: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
成功加载本地数据集sentence  label
0       hide new secretions from the parental units       0
1               contains no wit , only labored gags       0
2  that loves its characters and communicates som...      1
3  remains utterly satisfied to remain the same t...      0
4  on the worst revenge-of-the-nerds clichés the ...      0
无法加载BERT分词器: (MaxRetryError("HTTPSConnectionPool(host='huggingface.co', port=443): Max retries exceeded with url: /bert-base-uncased/resolve/main/tokenizer_config.json (Caused by ProxyError('Unable to connect to proxy', FileNotFoundError(2, 'No such file or directory')))"), '(Request ID: 3fff21e5-ab5a-4c4c-8695-70d49bb4ebdf)')
尝试使用备选方案...
已切换到简单分词器 (CountVectorizer)
开始预处理数据...
数据预处理完成
使用备选方案 (LogisticRegression) 进行训练...
测试集准确率: 0.8131
情感分析结果: 积极


7. 前沿关联:超大规模语言模型的能力与挑战

7.1 超大规模模型

  • GPT-4PaLM 等模型拥有数千亿参数,能够生成高质量的文本、代码甚至图像描述。
  • 能力
    • 上下文理解、多语言支持、零样本学习。
  • 挑战
    • 计算资源需求高。
    • 模型可解释性差。
    • 潜在的偏见与伦理问题。

7.2 未来方向

  • 更高效的训练方法(如稀疏激活、知识蒸馏)。
  • 提升模型的可控性与安全性。

总结

Transformer 架构以其强大的自注意力机制和灵活的编码器-解码器结构,成为 NLP 领域的基石。通过实战项目,我们学会了如何使用 Hugging Face 的工具微调 BERT 模型。同时,我们也探讨了超大规模语言模型的潜力与挑战。

希望这篇博客能帮助你更好地理解 Transformer 的原理与应用!如果需要进一步扩展或优化,请随时告诉我!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jeecgboot项目idea启动项目(二)

文章目录 一、IntelliJ IDEA1.安装2.配置maven3.配置jdk 二、IDEA启动项目三、IDEA2024.1.4破解 一、IntelliJ IDEA ‌IntelliJ IDEA是一款由JetBrains开发的集成开发环境(IDE),主要用于Java和Kotlin编程,但也支持多种其他编程语…

fody引用c++的dll合并后提示找不到

fody引用c的dll合并后提示找不到 解决方案&#xff1a; 在 FodyWeavers.xml 文件中添加配置 CreateTemporaryAssemblies‘true’ 官方文档&#xff1a;https://github.com/Fody/Costura <Weavers xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:noN…

DeepSeek R1满血+火山引擎详细教程

DeepSeek R1满血火山引擎详细教程 一、安装Cherry Studio。 Cherry Studio AI 是一款强大的多模型 AI 助手,支持 iOS、macOS 和 Windows 平台。可以快速切换多个先进的 LLM 模型,提升工作学习效率。下载地址 https://cherry-ai.com/ 认准官网&#xff0c;无强制注册。 这…

TP-LINK路由器如何设置网段、网关和DHCP服务

目标 ①将路由器的网段由192.168.1.XXX改为192.168.5.XXX ②确认DHCP是启用的&#xff0c;并将DHCP的IP池的范围设置为排除自己要手动指定的IP地址&#xff0c;避免IP冲突。 01-复位路由器 路由器按住复位键10秒以上进行重置操作 02-进入路由器管理界面 电脑连接到路由器&…

【C/C++】如何求出类对象的大小----类结构中的内存对齐

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 通过本章你能具体的了解到&#xff0c;如何计算出一个类的大小&#xff0c;并且了解其中到底是如何算的以及了解到为什么需要内存对齐这种算&#xff0…

鸿蒙开发第4篇__关于在鸿蒙应用中使用Java语言进行设计

本博文很重要 HarmonyOS从 API8 开始不再支持使用Java作为开发语言&#xff0c;未来的新功能将在ArkTS中实现. API 8对应的是HarmonyOS 3.0.0版本。请看下图&#xff1a; 因此&#xff0c; 读者如果看到类似《鸿蒙应用程序开发》(2021年版本 清华大学出版计)书 还使用Java语言…

【图文详解】论文《Attention Is All You Need》中位置嵌入(Positional Encoding)的流程和作用

文章目录 前言一、位置嵌入&#xff08;Positional Encoding&#xff09;的流程二、位置嵌入的作用三、为什么采用正弦和余弦函数四、位置嵌入示例五、结论 前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加关注哦&#xff0c…

SpringBoot 使用 spring.profiles.active 来区分不同环境配置

很多时候&#xff0c;我们项目在开发环境和生产环境的配置是不一样的&#xff0c;例如&#xff0c;数据库配置&#xff0c;在开发的时候&#xff0c;我们一般用测试数据库&#xff0c;而在生产环境&#xff0c;我们要用生产数据库&#xff0c;这时候&#xff0c;我们可以利用 p…

Android 常用命令和工具解析之存储相关

1 基本概念 2 命令解读 2.1 adb shell df df 命令主要用于需要检查文件系统上已使用和可用的磁盘空间的数量。如果没有指定文件名&#xff0c;则显示在当前所有挂载的文件系统上可用的空间。其原理是从proc/mounts 或 /etc/mtab 中检索磁盘信息。 注意&#xff1a;df命令并…

基于springboot+vue的融合多源高校画像数据与协同过滤算法的高考择校推荐系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

4个小时开发DeepSeek+baiduNaotu一键生成思维导图

一、引言 最近发现AI生成思维导图的解决方案普遍存在两个断层&#xff1a;用户需手动复制模型输出的JSON数据到脑图软件&#xff0c;且缺乏实时可视化反馈。基于日常使用的BaiduNaotu框架&#xff08;其轻量级架构与简洁的UI设计已满足基础需求&#xff09;&#xff0c;我决定…

【洛谷贪心算法题】P1094纪念品分组

该题运用贪心算法&#xff0c;核心思想是在每次分组时&#xff0c;尽可能让价格较小和较大的纪念品组合在一起&#xff0c;以达到最少分组的目的。 【算法思路】 输入处理&#xff1a;首先读取纪念品的数量n和价格上限w&#xff0c;然后依次读取每件纪念品的价格&#xff0c;…

【Azure 架构师学习笔记】- Terraform创建Azure 资源

本文属于【Azure 架构师学习笔记】系列。 前言 在实际的企业环境中&#xff0c;很少甚至可以说禁止手动创建资源&#xff0c;因为很容易出错&#xff0c;并且大规模部署时会非常低效。因此大部分企业都会使用工具或者某些服务来实现这种可控&#xff0c;可复用&#xff0c;具有…

JavaAPI(线程)

线程简介 进程&#xff08;Process&#xff09; 进程&#xff0c;是正在运行的程序实例&#xff0c;是操作系统进行资源分配的最小单位。 每个进程都有它自己的地址空间和系统资源&#xff08;比如CPU时间&#xff0c;内存空间&#xff0c;磁盘IO等&#xff09;。 多个进程…

冯诺依曼体系结构 ──── linux第8课

目录 冯诺依曼体系结构 关于冯诺依曼&#xff0c;必须强调几点&#xff1a; 冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系 输入单元&#xff1a;包括键盘, 鼠标&#xff0c;网卡,扫…

7.1 线性代数进行图像处理

一、图像的奇异值分解介绍 A A A 的奇异值定理就是 A T A A^TA ATA 和 A A T AA^T AAT 的特征值定理。 这是本章的内容的预览。 A A A 有两个奇异向量的集合&#xff08; A T A A^TA ATA 和 A A T AA^T AAT 的特征向量&#xff09;&#xff0c;有一个是正奇异值的集合&#…

Java 大视界 -- Java 大数据在智慧环保污染源监测与预警中的应用(104)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

「慢思考」机理分析:从雪球误差到正确推理概率

在大语言模型&#xff08;LLMs&#xff09;的发展历程中&#xff0c; Scaling Laws [1] 一直是推动性能提升的核心策略。研究表明&#xff0c;随着模型规模和训练数据的增长&#xff0c;LLMs 的表现会不断优化 [2]。然而&#xff0c;随着训练阶段规模的进一步扩大&#xff0c;性…

面试问题——如何解决移动端1px 边框问题?

面试问题——如何解决移动端1px 边框问题&#xff1f; 最近&#xff0c;不少小伙伴向我反映&#xff0c;他们在面试中频繁被问到关于1px边框的问题。这个看似老生常谈的话题&#xff0c;没想到在面试中的出现率依然这么高&#xff0c;着实让我有些意外。对于那些对这个问题感到…

全星研发项目管理APQP软件系统:汽车电子与半导体行业的研发管理利器

全星研发项目管理APQP软件系统&#xff1a;汽车电子与半导体行业的研发管理利器 1. 集成化管理优势 1.1 数据一致性 无缝数据流转&#xff1a;集成平台确保数据在不同模块间无缝流转&#xff0c;避免因工具切换导致的数据错误和重复工作。案例&#xff1a;某汽车电子企业使用…