CNN、RNN、Transformer 三大架构实战:图像、时序、文本任务代码对比

CNN、RNN、Transformer 三大架构实战:图像、时序、文本任务代码对比

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 x

Transformer核心优势

  • 自注意力机制:动态计算特征重要性
  • 位置编码:替代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 vocab

5. 三大架构对比分析

通过实际代码实现,我们可以总结出三种架构的关键差异:

特性CNNRNNTransformer
核心机制局部卷积+池化循环连接自注意力
数据依赖局部相关性时序依赖全局依赖
并行能力完全并行时间步串行完全并行
典型应用图像分类、目标检测时间序列预测、语音识别机器翻译、文本分类
内存效率中等较低较低(长序列时)
参数共享空间共享时间共享无显式共享

性能优化建议

  • 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建模时序
  • 多模态:各模态专用编码器+跨模态注意力