深度学习十大核心算法实战:CNN、Transformer、GAN与扩散模型对比解析
深度学习领域的技术迭代速度令人眼花缭乱但真正决定项目成败的往往不是最新潮的算法而是对基础模型本质差异的深刻理解。当你面对图像分类任务时是选择CNN还是Transformer处理时序数据时RNN真的过时了吗GAN和扩散模型在生成质量上究竟有何本质区别这些问题背后是每个深度学习工程师必须跨越的认知鸿沟。本文不会简单罗列算法原理而是从工程实践角度深入剖析CNN、RNN、Transformer、GAN、扩散模型、注意力机制等十大核心算法的适用场景、实现细节和避坑指南。通过完整的项目实战演示你将掌握如何根据具体任务需求选择合适的模型架构避免陷入算法崇拜的误区。1. 这篇文章真正要解决的问题在实际项目开发中深度学习算法的选择往往面临三个核心痛点首先是概念混淆很多开发者对CNN、RNN、Transformer的边界认知模糊其次是实践脱节理论理解无法有效转化为可运行的代码最后是选型困难面对相似任务时不知道如何评估不同算法的优劣。本文要解决的正是在有限的计算资源和时间成本下如何快速建立清晰的算法选型思维框架。无论是计算机视觉、自然语言处理还是生成式AI任务都需要基于数据特性、计算约束和业务目标做出理性选择。例如处理图像数据时CNN的局部连接和权重共享特性使其在计算效率上天然优于全连接网络而处理长序列数据时Transformer的自注意力机制相比RNN的序列处理更有优势。更重要的是本文将揭示这些算法背后的统一数学原理。你会发现从CNN的卷积核到Transformer的注意力头从GAN的对抗训练到扩散模型的去噪过程本质上都是在解决不同形式的数据表示和学习问题。2. 基础概念与核心原理2.1 CNN计算机视觉的基石卷积神经网络CNN的核心思想是局部连接和权重共享。与传统全连接网络相比CNN通过卷积核在输入数据上的滑动有效提取局部特征并大幅减少参数量。这种设计使其特别适合处理图像、视频等网格化数据。关键组件解析卷积层使用可学习的滤波器提取特征每个滤波器对应一个特征图池化层降低特征图尺寸增强模型平移不变性全连接层将学习到的特征映射到最终输出空间import torch import torch.nn as nn class SimpleCNN(nn.Module): def __init__(self, num_classes10): super(SimpleCNN, self).__init__() self.conv1 nn.Conv2d(3, 32, kernel_size3, stride1, padding1) self.relu nn.ReLU() self.pool nn.MaxPool2d(kernel_size2, stride2) self.conv2 nn.Conv2d(32, 64, kernel_size3, stride1, padding1) self.fc nn.Linear(64 * 8 * 8, num_classes) # 假设输入为32x32图像 def forward(self, x): x self.conv1(x) x self.relu(x) x self.pool(x) x self.conv2(x) x self.relu(x) x self.pool(x) x x.view(x.size(0), -1) x self.fc(x) return x # 模型使用示例 model SimpleCNN() input_tensor torch.randn(1, 3, 32, 32) # batch_size1, channels3, height32, width32 output model(input_tensor) print(f输出形状: {output.shape}) # torch.Size([1, 10])2.2 RNN序列建模的经典方案循环神经网络RNN通过隐藏状态传递历史信息使其能够处理变长序列数据。然而标准RNN存在梯度消失/爆炸问题这在长序列任务中尤为明显。RNN变体演进LSTM引入门控机制输入门、遗忘门、输出门控制信息流动GRU简化版LSTM只有重置门和更新门计算效率更高class SimpleLSTM(nn.Module): def __init__(self, input_size, hidden_size, num_layers, num_classes): super(SimpleLSTM, self).__init__() self.hidden_size hidden_size self.num_layers num_layers self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue) self.fc nn.Linear(hidden_size, num_classes) def forward(self, x): # 初始化隐藏状态 h0 torch.zeros(self.num_layers, x.size(0), self.hidden_size) c0 torch.zeros(self.num_layers, x.size(0), self.hidden_size) # 前向传播 out, _ self.lstm(x, (h0, c0)) out self.fc(out[:, -1, :]) # 取最后一个时间步的输出 return out # 示例处理长度为10的序列每个时间步特征维度为5 model SimpleLSTM(input_size5, hidden_size10, num_layers2, num_classes3) input_sequence torch.randn(1, 10, 5) # batch_size1, seq_length10, input_size5 output model(input_sequence) print(fLSTM输出形状: {output.shape}) # torch.Size([1, 3])2.3 Transformer注意力机制的革命Transformer完全基于自注意力机制摒弃了RNN的序列处理方式支持并行计算且能捕获长距离依赖关系。其核心是多头注意力机制允许模型同时关注不同表示子空间的信息。核心组件深度解析自注意力机制计算序列中每个位置与其他位置的关联度位置编码为输入序列添加位置信息弥补注意力机制的位置不敏感性前馈网络对每个位置的特征进行非线性变换class MultiHeadAttention(nn.Module): def __init__(self, d_model, num_heads): super(MultiHeadAttention, self).__init__() assert d_model % num_heads 0 self.d_model d_model self.num_heads num_heads self.d_k d_model // num_heads self.w_q nn.Linear(d_model, d_model) self.w_k nn.Linear(d_model, d_model) self.w_v nn.Linear(d_model, d_model) self.w_o nn.Linear(d_model, d_model) def forward(self, query, key, value, maskNone): batch_size query.size(0) # 线性变换并分头 Q self.w_q(query).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2) K self.w_k(key).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2) V self.w_v(value).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2) # 计算注意力权重 scores torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k) if mask is not None: scores scores.masked_fill(mask 0, -1e9) attn_weights torch.softmax(scores, dim-1) # 应用注意力权重 context torch.matmul(attn_weights, V) context context.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model) return self.w_o(context) # 使用示例 attention MultiHeadAttention(d_model512, num_heads8) x torch.randn(1, 10, 512) # batch_size1, seq_length10, d_model512 output attention(x, x, x) print(f多头注意力输出形状: {output.shape}) # 保持输入形状3. 环境准备与前置条件深度学习项目的成功很大程度上取决于环境的正确配置。以下是进行本文所述算法实践所需的完整环境设置。3.1 硬件要求与推荐配置最低配置CPU4核以上支持AVX指令集内存16GB RAM存储50GB可用空间用于数据集和模型缓存推荐配置适合完整项目实践GPUNVIDIA RTX 3060 12GB或更高CUDA计算能力7.0内存32GB RAM存储NVMe SSD500GB可用空间3.2 软件环境详细配置# 创建conda环境推荐 conda create -n dl-tutorial python3.9 conda activate dl-tutorial # 安装PyTorch根据CUDA版本选择 # CUDA 11.3版本 pip install torch1.12.1cu113 torchvision0.13.1cu113 torchaudio0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113 # 或者CPU版本 pip install torch1.12.1cpu torchvision0.13.1cpu torchaudio0.12.1 --extra-index-url https://download.pytorch.org/whl/cpu # 安装其他依赖 pip install numpy pandas matplotlib seaborn jupyter notebook pip install scikit-learn opencv-python pillow pip install transformers datasets tensorboard3.3 环境验证脚本创建验证脚本确保环境配置正确# environment_check.py import torch import torchvision import numpy as np import sklearn print( 深度学习环境验证 ) print(fPyTorch版本: {torch.__version__}) print(fCUDA可用: {torch.cuda.is_available()}) if torch.cuda.is_available(): print(fCUDA版本: {torch.version.cuda}) print(fGPU设备: {torch.cuda.get_device_name(0)}) print(fNumPy版本: {np.__version__}) print(fScikit-learn版本: {sklearn.__version__}) # 简单模型测试 x torch.randn(2, 3, 224, 224) model torchvision.models.resnet18(pretrainedFalse) output model(x) print(fResNet测试输出形状: {output.shape}) print(环境验证完成)运行验证脚本应看到类似输出 深度学习环境验证 PyTorch版本: 1.12.1cu113 CUDA可用: True CUDA版本: 11.3 GPU设备: NVIDIA GeForce RTX 3060 NumPy版本: 1.21.6 Scikit-learn版本: 1.0.2 ResNet测试输出形状: torch.Size([2, 1000]) 环境验证完成4. CNN项目实战图像分类完整流程4.1 数据集准备与预处理使用CIFAR-10数据集进行实战该数据集包含10个类别的60000张32x32彩色图像。import torch from torchvision import datasets, transforms from torch.utils.data import DataLoader # 数据预处理管道 transform transforms.Compose([ transforms.RandomHorizontalFlip(), # 数据增强 transforms.RandomCrop(32, padding4), transforms.ToTensor(), transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)) ]) # 加载数据集 train_dataset datasets.CIFAR10(root./data, trainTrue, downloadTrue, transformtransform) test_dataset datasets.CIFAR10(root./data, trainFalse, downloadTrue, transformtransform) # 创建数据加载器 train_loader DataLoader(train_dataset, batch_size128, shuffleTrue, num_workers4) test_loader DataLoader(test_dataset, batch_size100, shuffleFalse, num_workers4) # 类别名称 classes (plane, car, bird, cat, deer, dog, frog, horse, ship, truck)4.2 改进的CNN模型架构import torch.nn as nn import torch.nn.functional as F class AdvancedCNN(nn.Module): def __init__(self, num_classes10): super(AdvancedCNN, self).__init__() # 特征提取部分 self.features nn.Sequential( nn.Conv2d(3, 64, kernel_size3, padding1), nn.BatchNorm2d(64), nn.ReLU(inplaceTrue), nn.Conv2d(64, 64, kernel_size3, padding1), nn.BatchNorm2d(64), nn.ReLU(inplaceTrue), nn.MaxPool2d(kernel_size2, stride2), nn.Conv2d(64, 128, kernel_size3, padding1), nn.BatchNorm2d(128), nn.ReLU(inplaceTrue), nn.Conv2d(128, 128, kernel_size3, padding1), nn.BatchNorm2d(128), nn.ReLU(inplaceTrue), nn.MaxPool2d(kernel_size2, stride2), nn.Conv2d(128, 256, kernel_size3, padding1), nn.BatchNorm2d(256), nn.ReLU(inplaceTrue), nn.Conv2d(256, 256, kernel_size3, padding1), nn.BatchNorm2d(256), nn.ReLU(inplaceTrue), nn.MaxPool2d(kernel_size2, stride2), ) # 分类器部分 self.classifier nn.Sequential( nn.Dropout(0.5), nn.Linear(256 * 4 * 4, 512), nn.ReLU(inplaceTrue), nn.Dropout(0.5), nn.Linear(512, num_classes) ) def forward(self, x): x self.features(x) x x.view(x.size(0), -1) x self.classifier(x) return x model AdvancedCNN() print(f模型参数量: {sum(p.numel() for p in model.parameters())})4.3 训练流程与优化策略import torch.optim as optim from torch.optim.lr_scheduler import StepLR def train_model(model, train_loader, test_loader, epochs50): device torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device) criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.parameters(), lr0.001, weight_decay1e-4) scheduler StepLR(optimizer, step_size20, gamma0.1) train_losses [] test_accuracies [] for epoch in range(epochs): # 训练阶段 model.train() running_loss 0.0 for batch_idx, (data, target) in enumerate(train_loader): data, target data.to(device), target.to(device) optimizer.zero_grad() output model(data) loss criterion(output, target) loss.backward() optimizer.step() running_loss loss.item() if batch_idx % 100 0: print(fEpoch: {epoch1} [{batch_idx * len(data)}/{len(train_loader.dataset)}] f Loss: {loss.item():.6f}) # 测试阶段 model.eval() correct 0 total 0 with torch.no_grad(): for data, target in test_loader: data, target data.to(device), target.to(device) outputs model(data) _, predicted torch.max(outputs.data, 1) total target.size(0) correct (predicted target).sum().item() accuracy 100 * correct / total test_accuracies.append(accuracy) avg_loss running_loss / len(train_loader) train_losses.append(avg_loss) print(fEpoch {epoch1}: Loss: {avg_loss:.4f}, Test Accuracy: {accuracy:.2f}%) scheduler.step() return train_losses, test_accuracies # 开始训练 train_losses, test_accuracies train_model(model, train_loader, test_loader, epochs30)5. Transformer实战文本分类任务5.1 数据预处理与词嵌入import torch from torchtext.legacy import data from torchtext.legacy import datasets import spacy # 定义字段处理 TEXT data.Field(tokenizespacy, lowerTrue, include_lengthsTrue) LABEL data.LabelField(dtypetorch.float) # 加载IMDB电影评论数据集 train_data, test_data datasets.IMDB.splits(TEXT, LABEL) # 构建词汇表 MAX_VOCAB_SIZE 25000 TEXT.build_vocab(train_data, max_sizeMAX_VOCAB_SIZE, vectorsglove.6B.100d, unk_inittorch.Tensor.normal_) LABEL.build_vocab(train_data) # 创建迭代器 BATCH_SIZE 64 device torch.device(cuda if torch.cuda.is_available() else cpu) train_iterator, test_iterator data.BucketIterator.splits( (train_data, test_data), batch_sizeBATCH_SIZE, sort_within_batchTrue, sort_keylambda x: len(x.text), devicedevice)5.2 Transformer文本分类模型import torch.nn as nn import math class TransformerClassifier(nn.Module): def __init__(self, vocab_size, embed_dim, num_heads, hidden_dim, num_layers, num_classes, max_length512, dropout0.1): super(TransformerClassifier, self).__init__() self.embedding nn.Embedding(vocab_size, embed_dim) self.pos_encoding PositionalEncoding(embed_dim, max_length) encoder_layer nn.TransformerEncoderLayer( d_modelembed_dim, nheadnum_heads, dim_feedforwardhidden_dim, dropoutdropout ) self.transformer_encoder nn.TransformerEncoder(encoder_layer, num_layers) self.classifier nn.Linear(embed_dim, num_classes) self.dropout nn.Dropout(dropout) def forward(self, text, text_lengths): # text形状: [seq_len, batch_size] embedded self.embedding(text) * math.sqrt(self.embedding.embedding_dim) embedded self.pos_encoding(embedded) # Transformer需要处理填充的mask src_key_padding_mask self.create_mask(text) encoded self.transformer_encoder(embedded, src_key_padding_masksrc_key_padding_mask) # 取第一个token的输出作为分类特征 features encoded[0, :, :] output self.classifier(self.dropout(features)) return output def create_mask(self, text): # 创建填充mask return (text 0).transpose(0, 1) class PositionalEncoding(nn.Module): def __init__(self, d_model, max_length5000): super(PositionalEncoding, self).__init__() pe torch.zeros(max_length, d_model) position torch.arange(0, max_length, dtypetorch.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) pe pe.unsqueeze(0).transpose(0, 1) self.register_buffer(pe, pe) def forward(self, x): return x self.pe[:x.size(0), :] # 模型实例化 VOCAB_SIZE len(TEXT.vocab) EMBED_DIM 100 NUM_HEADS 5 HIDDEN_DIM 200 NUM_LAYERS 3 NUM_CLASSES 1 # 二分类问题 model TransformerClassifier(VOCAB_SIZE, EMBED_DIM, NUM_HEADS, HIDDEN_DIM, NUM_LAYERS, NUM_CLASSES)6. GAN与扩散模型对比实战6.1 GAN生成对抗网络实现import torch import torch.nn as nn import torch.optim as optim import torchvision.utils as vutils class Generator(nn.Module): def __init__(self, latent_dim, img_channels, feature_map_size64): super(Generator, self).__init__() self.main nn.Sequential( # 输入: latent_dim维噪声 nn.ConvTranspose2d(latent_dim, feature_map_size * 8, 4, 1, 0, biasFalse), nn.BatchNorm2d(feature_map_size * 8), nn.ReLU(True), nn.ConvTranspose2d(feature_map_size * 8, feature_map_size * 4, 4, 2, 1, biasFalse), nn.BatchNorm2d(feature_map_size * 4), nn.ReLU(True), nn.ConvTranspose2d(feature_map_size * 4, feature_map_size * 2, 4, 2, 1, biasFalse), nn.BatchNorm2d(feature_map_size * 2), nn.ReLU(True), nn.ConvTranspose2d(feature_map_size * 2, feature_map_size, 4, 2, 1, biasFalse), nn.BatchNorm2d(feature_map_size), nn.ReLU(True), nn.ConvTranspose2d(feature_map_size, img_channels, 4, 2, 1, biasFalse), nn.Tanh() ) def forward(self, input): return self.main(input) class Discriminator(nn.Module): def __init__(self, img_channels, feature_map_size64): super(Discriminator, self).__init__() self.main nn.Sequential( # 输入: img_channels x 64 x 64 nn.Conv2d(img_channels, feature_map_size, 4, 2, 1, biasFalse), nn.LeakyReLU(0.2, inplaceTrue), nn.Conv2d(feature_map_size, feature_map_size * 2, 4, 2, 1, biasFalse), nn.BatchNorm2d(feature_map_size * 2), nn.LeakyReLU(0.2, inplaceTrue), nn.Conv2d(feature_map_size * 2, feature_map_size * 4, 4, 2, 1, biasFalse), nn.BatchNorm2d(feature_map_size * 4), nn.LeakyReLU(0.2, inplaceTrue), nn.Conv2d(feature_map_size * 4, feature_map_size * 8, 4, 2, 1, biasFalse), nn.BatchNorm2d(feature_map_size * 8), nn.LeakyReLU(0.2, inplaceTrue), nn.Conv2d(feature_map_size * 8, 1, 4, 1, 0, biasFalse), nn.Sigmoid() ) def forward(self, input): return self.main(input).view(-1) # GAN训练函数 def train_gan(generator, discriminator, dataloader, num_epochs50): device torch.device(cuda if torch.cuda.is_available() else cpu) # 损失函数和优化器 criterion nn.BCELoss() lr 0.0002 g_optimizer optim.Adam(generator.parameters(), lrlr, betas(0.5, 0.999)) d_optimizer optim.Adam(discriminator.parameters(), lrlr, betas(0.5, 0.999)) fixed_noise torch.randn(64, 100, 1, 1, devicedevice) real_label 1.0 fake_label 0.0 for epoch in range(num_epochs): for i, (real_images, _) in enumerate(dataloader): batch_size real_images.size(0) real_images real_images.to(device) # 训练判别器 discriminator.zero_grad() label torch.full((batch_size,), real_label, devicedevice) output discriminator(real_images) errD_real criterion(output, label) errD_real.backward() noise torch.randn(batch_size, 100, 1, 1, devicedevice) fake_images generator(noise) label.fill_(fake_label) output discriminator(fake_images.detach()) errD_fake criterion(output, label) errD_fake.backward() errD errD_real errD_fake d_optimizer.step() # 训练生成器 generator.zero_grad() label.fill_(real_label) output discriminator(fake_images) errG criterion(output, label) errG.backward() g_optimizer.step() if i % 100 0: print(f[{epoch}/{num_epochs}][{i}/{len(dataloader)}] fLoss_D: {errD.item():.4f} Loss_G: {errG.item():.4f})6.2 扩散模型去噪扩散概率模型import torch import torch.nn as nn import numpy as np class DiffusionModel(nn.Module): def __init__(self, image_size, channels3, timesteps1000): super(DiffusionModel, self).__init__() self.timesteps timesteps self.image_size image_size # 定义噪声调度 self.betas self.linear_beta_schedule(timesteps) self.alphas 1. - self.betas self.alphas_cumprod torch.cumprod(self.alphas, dim0) self.sqrt_alphas_cumprod torch.sqrt(self.alphas_cumprod) self.sqrt_one_minus_alphas_cumprod torch.sqrt(1. - self.alphas_cumprod) # 噪声预测网络U-Net架构 self.denoise_net UNet(channels, channels) def linear_beta_schedule(self, timesteps, beta_start0.0001, beta_end0.02): return torch.linspace(beta_start, beta_end, timesteps) def forward(self, x, t): # 前向扩散过程添加噪声 sqrt_alpha_cumprod self.sqrt_alphas_cumprod[t].view(-1, 1, 1, 1) sqrt_one_minus_alpha_cumprod self.sqrt_one_minus_alphas_cumprod[t].view(-1, 1, 1, 1) noise torch.randn_like(x) noisy_x sqrt_alpha_cumprod * x sqrt_one_minus_alpha_cumprod * noise return noisy_x, noise def reverse_process(self, x, t): # 反向去噪过程 predicted_noise self.denoise_net(x, t) return predicted_noise class UNet(nn.Module): def __init__(self, in_channels, out_channels): super(UNet, self).__init__() # 简化的U-Net架构实现 self.encoder nn.Sequential( nn.Conv2d(in_channels, 64, 3, padding1), nn.ReLU(), nn.Conv2d(64, 64, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(64, 128, 3, padding1), nn.ReLU(), nn.Conv2d(128, 128, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), ) self.decoder nn.Sequential( nn.Conv2d(128, 64, 3, padding1), nn.ReLU(), nn.Conv2d(64, 64, 3, padding1), nn.ReLU(), nn.Upsample(scale_factor2), nn.Conv2d(64, out_channels, 3, padding1), ) def forward(self, x, t): # 时间步t的嵌入 t_embed self.get_timestep_embedding(t, x.shape[1]) t_embed t_embed.view(x.shape[0], -1, 1, 1).expand(-1, -1, x.shape[2], x.shape[3]) x torch.cat([x, t_embed], dim1) x self.encoder(x) x self.decoder(x) return x def get_timestep_embedding(self, timesteps, dim): # 将时间步转换为正弦嵌入 half_dim dim // 2 emb np.log(10000) / (half_dim - 1) emb torch.exp(torch.arange(half_dim, dtypetorch.float32) * -emb) emb timesteps.float()[:, None] * emb[None, :] emb torch.cat([torch.sin(emb), torch.cos(emb)], dim1) return emb # 扩散模型训练示例 def train_diffusion(model, dataloader, num_epochs100): optimizer optim.Adam(model.parameters(), lr1e-4) for epoch in range(num_epochs): for batch_idx, (images, _) in enumerate(dataloader): optimizer.zero_grad() # 随机选择时间步 t torch.randint(0, model.timesteps, (images.size(0),), deviceimages.device) # 前向扩散过程 noisy_images, true_noise model.forward(images, t) # 预测噪声 predicted_noise model.reverse_process(noisy_images, t) # 计算损失 loss nn.MSELoss()(predicted_noise, true_noise) loss.backward() optimizer.step() if batch_idx % 100 0: print(fEpoch [{epoch}/{num_epochs}] Batch [{batch_idx}/{len(dataloader)}] Loss: {loss.item():.4f})7. 注意力机制深度解析与实现7.1 自注意力机制数学原理自注意力机制的核心是通过查询Query、键Key、值Value三个矩阵的交互计算注意力权重。给定输入序列$X \in \mathbb{R}^{n \times d}$首先通过线性变换得到Q、K、V矩阵$$Q XW^Q, \quad K XW^K, \quad V XW^V$$注意力权重计算$$\text{Attention}(Q, K, V) \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$其中$d_k$是键向量的维度缩放因子$\sqrt{d_k}$用于防止点积过大导致softmax梯度消失。7.2 多头注意力实现细节class MultiHeadAttentionDetailed(nn.Module): def __init__(self, d_model, num_heads, dropout0.1): super(MultiHeadAttentionDetailed, self).__init__() assert d_model % num_heads 0 self.d_model d_model self.num_heads num_heads self.d_k d_model // num_heads # 线性变换矩阵 self.w_q nn.Linear(d_model, d_model) self.w_k nn.Linear(d_model, d_model) self.w_v nn.Linear(d_model, d_model) self.w_o nn.Linear(d_model, d_model) self.dropout nn.Dropout(dropout) self.scale math.sqrt(self.d_k) def forward(self, query, key, value, maskNone): batch_size query.size(0) # 线性变换 Q self.w_q(query) # [batch_size, seq_len, d_model] K self.w_k(key) # [batch_size, seq_len, d_model] V self.w_v(value) # [batch_size, seq_len, d_model] # 分头处理 Q Q.view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2) K K.view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2) V V.view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2) # 计算注意力分数 scores torch.matmul(Q, K.transpose(-2, -1)) / self.scale # 应用mask如需要 if mask is not None: scores scores.masked_fill(mask 0, -1e9) # 计算注意力权重 attn_weights torch.softmax(scores, dim-1) attn_weights self.dropout(attn_weights) # 应用注意力权重到值向量 context torch.matmul(attn_weights, V) # 合并多头输出 context context.transpose(1, 2).contiguous().view( batch_size, -1, self.num_heads * self.d_k) # 最终线性变换 output self.w_o(context) return output, attn_weights # 注意力机制可视化示例 def visualize_attention(text, model, tokenizer): 可视化文本的注意力权重分布 tokens tokenizer.encode(text, return_tensorspt) with torch.no_grad(): outputs model(tokens, output_attent