大语言模型系列——Transformer 介绍与使用

引言

自从 Google 在 2017 年发表了一篇题为《Attention Is All You Need》的论文以来,Transformer 已经成为了自然语言处理领域的一个重要里程碑。与传统的 RNN 和 LSTM 不同,Transformer 通过自注意力机制(Self-Attention Mechanism)实现了更快、更高效的数据处理方式。本文将详细介绍 Transformer 的原理、架构以及如何在实际项目中使用 Transformer 模型。

1. Transformer 的背景

在 Transformer 问世之前,大多数 NLP 任务都是基于循环神经网络(RNN)或长短期记忆网络(LSTM)完成的。这些模型能够很好地处理序列数据,但在训练大型数据集时存在效率低下和难以并行化的问题。Transformer 的出现解决了这些问题,同时也极大地推动了自然语言处理的发展。

2. Transformer 的核心概念
  • 自注意力机制:Transformer 使用自注意力机制来捕捉输入序列中的全局上下文关系。
  • 位置编码:由于 Transformer 没有像 RNN 那样的序列依赖性,因此需要位置编码来保留序列的位置信息。
  • 编码器-解码器架构:Transformer 采用了编码器-解码器架构,其中编码器负责处理输入序列,而解码器则负责生成输出序列。
3. Transformer 的架构

Transformer 的架构主要包括以下几个部分:

  • 编码器(Encoder):由多层相同的子层组成,每一层包括一个多头自注意力机制和一个前馈神经网络。
  • 解码器(Decoder):同样由多层相同的子层组成,除了多头自注意力机制和前馈神经网络外,还包括一个额外的多头注意力层,用于关注编码器的输出。
  • 多头注意力(Multi-Head Attention):通过将注意力分成多个头,每个头独立计算注意力权重,从而提高模型的并行性和表达能力。
  • 前馈网络(Feed Forward Network):每个子层之后都有一个前馈网络,用于增加模型的非线性变换能力。
  • 残差连接与层归一化(Residual Connections & Layer Normalization):每个子层前后都加入了残差连接,并在其之后使用了层归一化来加速训练过程。
4. Transformer 的工作流程
  1. 输入嵌入:每个输入词被转换为一个固定大小的向量。
  2. 位置编码:为了保留词的位置信息,添加了位置编码。
  3. 多头自注意力:编码器和解码器的第一步是通过多头自注意力机制来处理输入序列。
  4. 前馈网络:通过前馈网络进行非线性变换。
  5. 解码器处理:解码器不仅处理自己的输入序列,还通过多头注意力层关注编码器的输出。
5. 使用 Transformer 的实践

为了展示如何在实际项目中使用 Transformer,我们将使用 Python 和 PyTorch 框架来构建一个简单的翻译模型。

5.1 环境搭建

确保你的环境中已安装 Python 和 PyTorch。你可以通过 pip 安装 PyTorch:

Bash

1pip install torch
5.2 数据准备

使用一个简单的翻译数据集,例如英语到法语的翻译数据集。

Python

1import torch
2from torchtext.data import Field, TabularDataset, BucketIterator
3from torchtext.data.metrics import bleu_score
4
5# 定义字段
6SRC = Field(tokenize='spacy', tokenizer_language='en_core_web_sm', init_token='<sos>', eos_token='<eos>', lower=True)
7TRG = Field(tokenize='spacy', tokenizer_language='fr_core_news_sm', init_token='<sos>', eos_token='<eos>', lower=True)
8
9# 加载数据
10train_data, valid_data, test_data = TabularDataset.splits(
11    path='data/', train='train.csv', validation='val.csv', test='test.csv',
12    format='csv', fields=[('src', SRC), ('trg', TRG)])
13
14# 构建词汇表
15SRC.build_vocab(train_data, min_freq=2)
16TRG.build_vocab(train_data, min_freq=2)
17
18# 创建迭代器
19device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
20train_iterator, valid_iterator, test_iterator = BucketIterator.splits(
21    (train_data, valid_data, test_data), batch_size=128, device=device)
5.3 构建 Transformer 模型

接下来,我们将定义 Transformer 模型。

Python

1import torch.nn as nn
2
3class Transformer(nn.Module):
4    def __init__(self, input_dim, output_dim, hid_dim, n_layers, n_heads, pf_dim, dropout, device, max_length=100):
5        super().__init__()
6        
7        self.tok_embedding = nn.Embedding(input_dim, hid_dim)
8        self.pos_embedding = nn.Embedding(max_length, hid_dim)
9        
10        self.layers = nn.ModuleList([EncoderLayer(hid_dim, n_heads, pf_dim, dropout, device) for _ in range(n_layers)])
11        
12        self.fc_out = nn.Linear(hid_dim, output_dim)
13        self.dropout = nn.Dropout(dropout)
14        self.device = device
15        
16    def forward(self, src, src_mask):
17        # src = [batch size, src len]
18        # src_mask = [batch size, 1, 1, src len]
19        
20        batch_size = src.shape[0]
21        src_len = src.shape[1]
22        
23        pos = torch.arange(0, src_len).unsqueeze(0).repeat(batch_size, 1).to(self.device)
24        
25        # pos = [batch size, src len]
26        
27        src = self.dropout((self.tok_embedding(src) + self.pos_embedding(pos)))
28        
29        # src = [batch size, src len, hid dim]
30        
31        for layer in self.layers:
32            src = layer(src, src_mask)
33            
34        # src = [batch size, src len, hid dim]
35            
36        output = self.fc_out(src)
37        
38        # output = [batch size, src len, output dim]
39        
40        return output
41
42class EncoderLayer(nn.Module):
43    def __init__(self, hid_dim, n_heads, pf_dim, dropout, device):
44        super().__init__()
45        
46        self.self_attn_layer_norm = nn.LayerNorm(hid_dim)
47        self.ff_layer_norm = nn.LayerNorm(hid_dim)
48        self.self_attention = MultiHeadAttentionLayer(hid_dim, n_heads, dropout, device)
49        self.positionwise_feedforward = PositionwiseFeedforwardLayer(hid_dim, pf_dim, dropout)
50        self.dropout = nn.Dropout(dropout)
51        
52    def forward(self, src, src_mask):
53        # src = [batch size, src len, hid dim]
54        # src_mask = [batch size, 1, 1, src len]
55        
56        _src, _ = self.self_attention(src, src, src, src_mask)
57        
58        # _src = [batch size, src len, hid dim]
59        
60        src = self.self_attn_layer_norm(src + self.dropout(_src))
61        
62        # src = [batch size, src len, hid dim]
63        
64        _src = self.positionwise_feedforward(src)
65        
66        # _src = [batch size, src len, hid dim]
67        
68        src = self.ff_layer_norm(src + self.dropout(_src))
69        
70        # src = [batch size, src len, hid dim]
71        
72        return src
5.4 训练模型

现在我们来训练我们的 Transformer 模型。

Python

1import math
2
3def train(model, iterator, optimizer, criterion, clip):
4    model.train()
5    
6    epoch_loss = 0
7    
8    for i, batch in enumerate(iterator):
9        src = batch.src
10        trg = batch.trg
11        
12        optimizer.zero_grad()
13        
14        output = model(src, trg[:, :-1])
15                
16        # output = [batch size, trg len - 1, output dim]
17        # trg = [batch size, trg len]
18            
19        output_dim = output.shape[-1]
20            
21        output = output.contiguous().view(-1, output_dim)
22        trg = trg[:, 1:].contiguous().view(-1)
23                
24        # output = [batch size * trg len - 1, output dim]
25        # trg = [batch size * trg len - 1]
26            
27        loss = criterion(output, trg)
28        loss.backward()
29        
30        torch.nn.utils.clip_grad_norm_(model.parameters(), clip)
31        
32        optimizer.step()
33        epoch_loss += loss.item()
34        
35    return epoch_loss / len(iterator)
36
37def evaluate(model, iterator, criterion):
38    model.eval()
39    
40    epoch_loss = 0
41    
42    with torch.no_grad():
43        for i, batch in enumerate(iterator):
44            src = batch.src
45            trg = batch.trg
46
47            output = model(src, trg[:, :-1])
48            
49            # output = [batch size, trg len - 1, output dim]
50            # trg = [batch size, trg len]
51            
52            output_dim = output.shape[-1]
53            
54            output = output.contiguous().view(-1, output_dim)
55            trg = trg[:, 1:].contiguous().view(-1)
56            
57            # output = [batch size * trg len - 1, output dim]
58            # trg = [batch size * trg len - 1]
59            
60            loss = criterion(output, trg)
61
62            epoch_loss += loss.item()
63        
64    return epoch_loss / len(iterator)
65
66def epoch_time(start_time, end_time):
67    elapsed_time = end_time - start_time
68    elapsed_mins = int(elapsed_time / 60)
69    elapsed_secs = int(elapsed_time - (elapsed_mins * 60))
70    return elapsed_mins, elapsed_secs
71
72INPUT_DIM = len(SRC.vocab)
73OUTPUT_DIM = len(TRG.vocab)
74HID_DIM = 256
75ENC_LAYERS = 3
76DEC_LAYERS = 3
77ENC_HEADS = 8
78DEC_HEADS = 8
79ENC_PF_DIM = 512
80DEC_PF_DIM = 512
81ENC_DROPOUT = 0.1
82DEC_DROPOUT = 0.1
83
84enc = Encoder(INPUT_DIM, HID_DIM, ENC_LAYERS, ENC_HEADS, ENC_PF_DIM, ENC_DROPOUT, device)
85dec = Decoder(OUTPUT_DIM, HID_DIM, DEC_LAYERS, DEC_HEADS, DEC_PF_DIM, DEC_DROPOUT, device)
86
87model = Seq2Seq(enc, dec, device).to(device)
88
89def count_parameters(model):
90    return sum(p.numel() for p in model.parameters() if p.requires_grad)
91
92print(f'The model has {count_parameters(model):,} trainable parameters')
93
94optimizer = torch.optim.Adam(model.parameters())
95
96PAD_IDX = TRG.vocab.stoi['<pad>']
97
98criterion = nn.CrossEntropyLoss(ignore_index=PAD_IDX)
99
100N_EPOCHS = 10
101CLIP = 1
102
103best_valid_loss = float('inf')
104
105for epoch in range(N_EPOCHS):
106    
107    start_time = time.time()
108    
109    train_loss = train(model, train_iterator, optimizer, criterion, CLIP)
110    valid_loss = evaluate(model, valid_iterator, criterion)
111    
112    end_time = time.time()
113    
114    epoch_mins, epoch_secs = epoch_time(start_time, end_time)
115    
116    if valid_loss < best_valid_loss:
117        best_valid_loss = valid_loss
118        torch.save(model.state_dict(), 'tut6-model.pt')
119    
120    print(f'Epoch: {epoch+1:02} | Time: {epoch_mins}m {epoch_secs}s')
121    print(f'\tTrain Loss: {train_loss:.3f} | Train PPL: {math.exp(train_loss):7.3f}')
122    print(f'\t Val. Loss: {valid_loss:.3f} |  Val. PPL: {math.exp(valid_loss):7.3f}')
6. 结论

Transformer 模型彻底改变了自然语言处理领域的面貌,它不仅提高了模型的训练速度,而且在许多任务上取得了显著的效果。通过本文的介绍,你应该对 Transformer 的原理和使用有了更深入的理解,并能够将其应用于实际项目中。如果你有任何疑问或想要了解更多细节,请随时查阅官方文档或社区资源。

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

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

相关文章

使用eclipse在新建的java项目中编辑xml文件时Unhandled event loop exception No more handles

处理方法&#xff1a;更换xml编辑器 Window ——》Preferences ——》General ——》Editors ——》File Associations 如果File types里面没有*.xml&#xff0c;则点击Add进行新增 选中*.xml&#xff0c;然后在Associated editors 选中想用的编辑器&#xff0c;设置为defaul…

Selenium---Xpath选择器

XPath (XML Path Language) 是由国际标准化组织W3C指定的&#xff0c;用来在 XML 和 HTML 文档中选择节点的语言。 xpath 语法中&#xff0c;整个HTML文档根节点用/表示&#xff0c;如果我们想选择的是根节点下面的html节点&#xff0c;则可以在搜索框输入 /html如果输入下面…

vpp中的不同节点的数据传输,使用vpp中的回调函数,相同的原理也可以实现,不同节点的函数的调用

vpp中的不同节点的数据传输&#xff0c;使用vpp中的回调函数&#xff0c;相同的原理也可以实现&#xff0c;不同节点的函数的调用 1.实现数据传输所需要用到的函数2.具体实现 1.实现数据传输所需要用到的函数 需要用到的一个宏__clib_export 作用&#xff1a;就是将这后边的…

小白也能读懂的ConvLSTM!(开源pytorch代码)

ConvLSTM 1. 算法简介与应用场景2. 算法原理2.1 LSTM基础2.2 ConvLSTM原理2.2.1 ConvLSTM的结构2.2.2 卷积操作的优点 2.3 LSTM与ConvLSTM的对比分析2.4 ConvLSTM的应用 3. PyTorch代码参考文献 仅需要网络源码的可以直接跳到末尾即可 1. 算法简介与应用场景 ConvLSTM&#x…

app-routing.module.ts 简单介绍

Angular的路由是一种功能&#xff0c;它允许应用程序响应不同的URL路径或参数并根据这些路径加载不同的组件。app-routing.module.ts是Angular项目中负责设置应用程序路由的文件。 以下是一个简单的app-routing.module.ts文件示例&#xff0c;它配置了三个路由&#xff1a; i…

SAPUI5基础知识22 - 图标(Icons)

1. 背景 SAPUI5 提供了一套丰富的图标库&#xff0c;可以用于增强应用程序的视觉吸引力和用户体验。这些图标是矢量图形&#xff0c;可以在任何分辨率下保持清晰&#xff0c;并且可以自定义颜色和大小。 2. 示例 在 SAPUI5 中&#xff0c;图标可以通过 sap.ui.core.Icon 控件…

Redis快速入门基础

Redis入门 Redis是一个基于内存的 key-value 结构数据库。mysql是二维表的接口数据库 优点&#xff1a; 基于内存存储&#xff0c;读写性能高 适合存储热点数据(热点商品、资讯、新闻) 企业应用广泛 官网:https://redis.io 中文网:https://www.redis.net.cn/ Redis下载与…

Spring缓存注解

Spring缓存注解 EnableCaching | 来启动缓存注解Cached | 用来表示某一个方法的结果可以被缓存 Cached(name “testCache:id1:”, key “#testId”, cacheType CacheType.REMOTE, localLimit CustomerConstants.DEFAULT_LIMIT, expire 1800)方法方法上。 #相关参数&#…

The Llama 3 Herd of Models 第6部分推理部分全文

第1,2,3部分 介绍,概览和预训练 第4部分 后训练 第5部分 结果 6 Inference 推理 我们研究了两种主要技术来提高Llama 3405b模型的推理效率:(1)管道并行化和(2)FP8量化。我们已经公开发布了FP8量化的实现。 6.1 Pipeline Parallelism 管道并行 当使用BF16数字表示模型参数时…

家具购物小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;家具分类管理&#xff0c;家具新品管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;家具新品&#xff0c;家具公告&#xff0…

【开发学习笔记】git的工作区与分支

Git是一款分布式版本控制系统&#xff0c;被广泛应用于软件开发中&#xff0c;用于跟踪和管理项目的源代码。在Git中&#xff0c;工作区与分支是两个核心概念&#xff0c;它们在Git的工作流程中扮演着不同的角色。 工作区的概念 工作区&#xff08;Working Directory&#xf…

Linux网络——深入理解传入层协议TCP

目录 一、前导知识 1.1 TCP协议段格式 1.2 TCP全双工本质 二、三次握手 2.1 标记位 2.2 三次握手 2.3 捎带应答 2.4 标记位 RST 三、四次挥手 3.1 标记位 FIN 四、确认应答(ACK)机制 五、超时重传机制 六 TCP 流量控制 6.1 16位窗口大小 6.2 标记位 PSH 6.3 标记…

YOLOv5改进 | 卷积模块 | 无卷积步长用于低分辨率图像和小物体的新 CNN 模块SPD-Conv

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录&#xff1a; 《YOLOv5入门 改…

[ WARN:0@0.014] global loadsave.cpp:248 cv::findDecoder imread_

[ WARN:00.014] global loadsave.cpp:248 cv::findDecoder imread_ 目录 [ WARN:00.014] global loadsave.cpp:248 cv::findDecoder imread_ 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰…

20240729 每日AI必读资讯

Meta科学家最新采访&#xff0c;揭秘Llama 3.1是如何炼成的 - Llama 3.1都使用了哪些数据&#xff1f;其中有多少合成数据&#xff1f;为什么不使用MoE架构&#xff1f;后训练与RLHF流程是如何进行的&#xff1f;模型评估是如何进行的&#xff1f; - 受访者Thomas Scialom现任…

ReactHooks(二)

上期在这~ ReactHooks【二】 一.useReducer1.1 useReducer 的语法格式1.2 定义组件的基础结构1.3 定义 useReducer 的基础结构1.3.1按需导入 useReducer 函数1.3.2定义初始数据1.3.3 定义 reducer 函数根据旧状态&#xff0c;进行一系列处理&#xff0c;最终返回新状态&#x…

Go语言教程(一看就会)

全篇文章 7000 字左右&#xff0c; 建议阅读时长 1h 以上。 Go语言是一门开源的编程语言&#xff0c;目的在于降低构建简单、可靠、高效软件的门槛。Go平衡了底层系统语言的能力&#xff0c;以及在现代语言中所见到的高级特性。它是快速的、静态类型编译语言。 第一个GO程序…

嵌入式人工智能(32-基于树莓派4B的旋转编码器-EnCoder11)

1、旋转编码器 旋转编码器是一种输入设备&#xff0c;通常用于测量和控制旋转运动。它由一个旋转轴和一系列编码器组成。旋转编码器可以根据旋转轴的位置和方向来测量旋转角度&#xff0c;并将其转化为电子信号输出。 旋转编码器通常分为两种类型&#xff1a;绝对值编码器和增…

【ai】Easy-RAG 4: 修复依赖项:numpy numba omegaconf 等

numpy 2.0.1 这个版本太高了 chromadb 0.5.5 requires numpy<2.0.0,>=1.22.5,but you have numpy 2.0.1 which is incompatible.gradio 4.29.0 requires numpy~=1.0, but you have numpy 2.0.1 which is incompatible.langchain 0.2.6 requires numpy<2,>=1; pytho…

力扣面试题(一)

1、给你两个字符串 word1 和 word2 。请你从 word1 开始&#xff0c;通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长&#xff0c;就将多出来的字母追加到合并后字符串的末尾。 char * mergeAlternately(char * word1, char * word2){int len1 strlen(word1);i…