CNN、RNN、Transformer 三大架构实战:图像、时序、文本任务代码对比
📅 2026/7/9 22:22:31
👁️ 阅读次数
📝 编程学习
CNN、RNN、Transformer 三大架构实战:图像、时序、文本任务代码对比
深度学习领域的三驾马车——卷积神经网络(CNN)、循环神经网络(RNN)和Transformer架构,各自在特定数据类型上展现出独特优势。本文将带您深入实战,通过PyTorch代码对比这三种架构在图像分类、股票预测和情感分析任务中的实现差异,揭示模型设计背后的核心思想与技术细节。
1. 环境准备与数据加载
在开始构建模型前,我们需要配置统一的开发环境。推荐使用Python 3.8+和PyTorch 1.12+环境,所有示例代码均可在Colab或本地GPU服务器上运行。
import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torchvision import transforms import numpy as np import pandas as pd from sklearn.model_selection import train_test_split # 检查GPU可用性 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print(f"Using device: {device}")1.1 数据集准备
我们将使用三种典型数据集:
- 图像数据:CIFAR-10(10类物体分类)
- 时序数据:Yahoo股票价格数据集
- 文本数据:IMDb电影评论情感分析
# 图像数据加载示例 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) # 时序数据预处理函数 def create_sequences(data, seq_length): sequences = [] targets = [] for i in range(len(data)-seq_length): seq = data[i:i+seq_length] label = data[i+seq_length] sequences.append(seq) targets.append(label) return np.array(sequences), np.array(targets) # 文本数据分词处理 from torchtext.data import get_tokenizer tokenizer = get_tokenizer("basic_english")2. CNN图像分类实战
卷积神经网络通过局部感受野和权值共享特性,成为处理网格状数据(如图像)的首选架构。下面我们实现一个经典的CNN分类器。
2.1 模型架构设计
class CNNClassifier(nn.Module): def __init__(self, num_classes=10): super(CNNClassifier, self).__init__() self.features = nn.Sequential( nn.Conv2d(3, 64, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), nn.Conv2d(64, 128, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), nn.Conv2d(128, 256, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.Conv2d(256, 256, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), ) self.classifier = nn.Sequential( nn.Linear(256 * 4 * 4, 1024), nn.ReLU(inplace=True), nn.Dropout(p=0.5), nn.Linear(1024, num_classes), ) def forward(self, x): x = self.features(x) x = torch.flatten(x, 1) x = self.classifier(x) return x关键组件解析:
Conv2d:二维卷积层,提取局部特征MaxPool2d:下采样操作,增强平移不变性ReLU:非线性激活函数Dropout:正则化防止过拟合
2.2 训练流程对比
CNN的训练过程强调数据增强和批量归一化:
def train_cnn(model, train_loader, criterion, optimizer, epochs=10): model.train() for epoch in range(epochs): running_loss = 0.0 for i, (inputs, labels) in enumerate(train_loader): inputs, labels = inputs.to(device), labels.to(device) # 数据增强 augmented_inputs = augment_images(inputs) optimizer.zero_grad() outputs = model(augmented_inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")提示:图像数据通常需要应用随机裁剪、水平翻转等增强技术,这能显著提升模型泛化能力。
3. RNN时序预测实战
循环神经网络通过隐状态记忆历史信息,特别适合处理序列数据。我们以股票价格预测为例展示LSTM的实现。
3.1 LSTM模型构建
class StockPredictor(nn.Module): def __init__(self, input_size=1, hidden_size=64, num_layers=2): super(StockPredictor, self).__init__() self.hidden_size = hidden_size self.num_layers = num_layers self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) self.fc = nn.Linear(hidden_size, 1) def forward(self, x): h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device) c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device) out, _ = self.lstm(x, (h0, c0)) out = self.fc(out[:, -1, :]) return out时序数据处理要点:
- 序列标准化:使用滑动窗口归一化
- 教师强制:训练时使用真实值作为下一步输入
- 多步预测:递归预测或序列到序列架构
3.2 差异化的训练策略
def train_rnn(model, train_loader, criterion, optimizer, epochs=50): model.train() for epoch in range(epochs): for seq, targets in train_loader: seq, targets = seq.float().to(device), targets.float().to(device) optimizer.zero_grad() outputs = model(seq.unsqueeze(-1)) loss = criterion(outputs, targets.unsqueeze(-1)) # 梯度裁剪防止爆炸 nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) loss.backward() optimizer.step() if epoch % 10 == 0: print(f"Epoch {epoch}, Loss: {loss.item():.4f}")RNN训练特有的技术:
- 梯度裁剪:缓解梯度爆炸问题
- 序列采样:处理变长序列
- 双向结构:捕获前后文信息
4. Transformer文本分类实战
Transformer凭借自注意力机制,在自然语言处理领域取得突破。我们实现一个简化版的Transformer用于情感分析。
4.1 模型架构创新
class TextTransformer(nn.Module): def __init__(self, vocab_size, embed_dim, num_heads, num_layers, num_classes): super(TextTransformer, self).__init__() self.embedding = nn.Embedding(vocab_size, embed_dim) self.pos_encoder = PositionalEncoding(embed_dim) encoder_layer = nn.TransformerEncoderLayer( d_model=embed_dim, nhead=num_heads ) self.transformer_encoder = nn.TransformerEncoder( encoder_layer, num_layers=num_layers ) self.classifier = nn.Linear(embed_dim, num_classes) def forward(self, x): x = self.embedding(x) x = self.pos_encoder(x) x = self.transformer_encoder(x) x = x.mean(dim=1) # 全局平均池化 return self.classifier(x) class PositionalEncoding(nn.Module): def __init__(self, d_model, max_len=5000): super(PositionalEncoding, self).__init__() pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) self.register_buffer('pe', pe) def forward(self, x): x = x + self.pe[:x.size(1), :] return xTransformer核心优势:
- 自注意力机制:动态计算特征重要性
- 位置编码:替代RNN的顺序处理能力
- 并行计算:显著提升训练效率
4.2 文本处理流程
def preprocess_text(text, vocab, max_length=256): tokens = tokenizer(text) indexed = [vocab[token] if token in vocab else vocab["<unk>"] for token in tokens] if len(indexed) < max_length: indexed += [vocab["<pad>"]] * (max_length - len(indexed)) else: indexed = indexed[:max_length] return torch.tensor(indexed) # 示例词表构建 from collections import Counter def build_vocab(texts, max_size=20000): counter = Counter() for text in texts: counter.update(tokenizer(text)) vocab = {"<pad>": 0, "<unk>": 1} vocab.update({token: i+2 for i, (token, _) in enumerate(counter.most_common(max_size))}) return vocab5. 三大架构对比分析
通过实际代码实现,我们可以总结出三种架构的关键差异:
| 特性 | CNN | RNN | Transformer |
|---|---|---|---|
| 核心机制 | 局部卷积+池化 | 循环连接 | 自注意力 |
| 数据依赖 | 局部相关性 | 时序依赖 | 全局依赖 |
| 并行能力 | 完全并行 | 时间步串行 | 完全并行 |
| 典型应用 | 图像分类、目标检测 | 时间序列预测、语音识别 | 机器翻译、文本分类 |
| 内存效率 | 中等 | 较低 | 较低(长序列时) |
| 参数共享 | 空间共享 | 时间共享 | 无显式共享 |
性能优化建议:
- CNN:使用深度可分离卷积减少参数量
- RNN:采用GRU单元平衡效果与效率
- Transformer:使用线性注意力降低复杂度
6. 跨架构迁移技巧
虽然三种架构设计初衷不同,但现代深度学习实践中常出现架构融合:
class HybridModel(nn.Module): """CNN+Transformer混合架构示例""" def __init__(self): super().__init__() self.cnn = nn.Sequential( nn.Conv2d(3, 32, 3), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(32, 64, 3), nn.ReLU(), nn.MaxPool2d(2) ) self.transformer = nn.TransformerEncoderLayer( d_model=64, nhead=4 ) self.classifier = nn.Linear(64, 10) def forward(self, x): x = self.cnn(x) # [B, C, H, W] x = x.flatten(2).permute(2, 0, 1) # [L, B, C] x = self.transformer(x) x = x.mean(dim=0) return self.classifier(x)实际项目中根据数据特性选择架构:
- 图像+文本:CNN处理图像,Transformer处理文本
- 视频分析:3D CNN提取空间特征,LSTM建模时序
- 多模态:各模态专用编码器+跨模态注意力
编程学习
技术分享
实战经验