用Python进行AI数据分析进阶教程76

深度学习的高级模型


关键词:卷积神经网络、循环神经网络、Transformer、自注意力机制、深度学习

摘要:本文系统介绍了深度学习中的三大高级模型:卷积神经网络(CNN)、循环神经网络(RNN)和Transformer。CNN适用于图像等网格数据,通过卷积、池化和全连接层提取空间特征,广泛应用于图像分类与检测。RNN及其变体LSTM、GRU擅长处理序列数据,能捕捉时序依赖,常用于文本和语音任务。Transformer基于自注意力机制,克服了RNN的串行瓶颈,支持并行计算与长距离依赖建模,已成为自然语言处理的主流架构。文章还对比了三者在输入类型、并行性、建模能力等方面的差异,并提供了PyTorch代码示例,帮助理解各模型的核心结构与实现要点。

👉 欢迎订阅🔗
《用Python进行AI数据分析进阶教程》专栏
《AI大模型应用实践进阶教程》专栏
《Python编程知识集锦》专栏
《字节跳动旗下AI制作抖音视频》专栏
《智能辅助驾驶》专栏
《工具软件及IT技术集锦》专栏


下面我将详细讲解深度学习中三大高级模型:卷积神经网络(CNN)、循环神经网络(RNN)和Transformer,分别从以下方面进行展开:

  1. 基本原理与结构
  2. 关键点与注意点
  3. 典型应用场景
  4. 代码示例(PyTorch实现)
  5. 重点语句解读

一、卷积神经网络(Convolutional Neural Network, CNN)

1. 基本原理与结构

CNN 是专为处理具有网格结构的数据(如图像)而设计的神经网络。其核心组件包括:

  • 卷积层(Conv Layer)通过滤波器(kernel)提取局部特征。
  • 池化层(Pooling Layer)降低空间维度,保留主要信息。
  • 激活函数(ReLU 等)引入非线性。
  • 全连接层(Fully Connected Layer)用于最终分类。

2. 关键点与注意点

关键点

注意点

局部感知野(Local Receptive Field)

卷积核大小不宜过大,避免计算量爆炸

参数共享(Parameter Sharing)

避免过拟合,可使用Dropout或BatchNorm

多通道输入输出(Channel-wise Convolution)

输入通道数必须与卷积核通道一致

3. 应用场景

  • 图像分类(如ResNet、VGG)
  • 目标检测(YOLO、Faster R-CNN)
  • 图像分割(U-Net)

4. 示例代码(PyTorch 实现一个简单的 CNN 分类器)

Python脚本

# 导入PyTorch核心库
import torch

# 导入神经网络模块
import torch.nn as nn


# 定义一个简单的CNN模型,继承自nn.Module
class SimpleCNN(nn.Module):
    def __init__(self, num_classes=10):
        # 调用父类构造函数
        super(SimpleCNN, self).__init__()

        # 特征提取部分:由两个卷积块组成
        self.features = nn.Sequential(
            # 第一卷积层:输入通道3,输出通道16,卷积核大小3x3,padding=1保持分辨率不变
            nn.Conv2d(
                in_channels=3,
                out_channels=16,
                kernel_size=3,
                stride=1,
                padding=1
            ),
            # ReLU激活函数
            nn.ReLU(),
            # 最大池化层:核大小2x2,步长2,将特征图缩小一半
            nn.MaxPool2d(kernel_size=2, stride=2),

            # 第二卷积层:输入通道16,输出通道32,卷积核3x3,padding=1保持分辨率不变
            nn.Conv2d(16, 32, kernel_size=3, padding=1),
            # ReLU激活函数
            nn.ReLU(),
            # 最大池化层:核大小2x2,步长2,再次将特征图缩小一半
            nn.MaxPool2d(kernel_size=2, stride=2)
        )

        # 分类器部分
        self.classifier = nn.Sequential(
            # 将特征图展平成向量,用于全连接层
            nn.Flatten(),
            # 全连接层:输入维度为32*8*8(来自前一层输出),输出128维
            nn.Linear(32 * 8 * 8, 128),
            # ReLU激活函数
            nn.ReLU(),
            # 输出层:将128维映射到num_classes个类别
            nn.Linear(128, num_classes)
        )

    # 定义前向传播过程
    def forward(self, x):
        # 输入数据经过特征提取层
        x = self.features(x)
        # 经过分类器得到最终输出
        x = self.classifier(x)
        return x


# 实例化模型
model = SimpleCNN()

# 构造一个随机输入张量,模拟一个batch的数据:16张3通道32x32的图片
x = torch.randn(16, 3, 32, 32)

# 前向传播,得到输出
output = model(x)

# 打印输出形状,预期为 [batch_size, num_classes] -> [16, 10]
print(output.shape)  # 输出: torch.Size([16, 10])

5. 重点语句解读

  • nn.Conv2d(...):定义一个卷积层,in_channels=3表示RGB图像,out_channels=16表示生成16个特征图。
  • nn.MaxPool2d(...):最大池化操作,降维但保留主要特征。
  • nn.Linear(32*8*8, 128):将卷积后的结果展平后输入全连接层,注意尺寸要匹配。

二、循环神经网络(Recurrent Neural Network, RNN)

1. 基本原理与结构

RNN 专门用于处理序列数据(如文本、时间序列),能够捕捉序列中的时序依赖关系。

  • 隐藏状态(Hidden State)记忆前面的信息。
  • 常见变种LSTM(Long Short-Term Memory)
    • GRU(Gated Recurrent Unit)

2. 关键点与注意点

关键点

注意点

能建模序列依赖

梯度消失/爆炸问题严重(推荐LSTM/GRU)

可以是单向或双向

不适合长距离依赖(除非使用LSTM等)

输入为序列形式

批次长度可能不固定,需使用pack_padded_sequence

3. 应用场景

  • 文本分类、机器翻译
  • 时间序列预测
  • 语音识别

4. 示例代码(PyTorch 实现一个简单的 LSTM 分类器)

Python脚本

# 导入 PyTorch 和神经网络模块
import torch
import torch.nn as nn


# 定义一个文本分类模型 TextClassifier,继承自 nn.Module
class TextClassifier(nn.Module):
    """
    简单的基于 LSTM 的文本分类模型
    """

    # 初始化方法,定义模型结构所需参数
    def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes):
        # 调用父类 nn.Module 的初始化方法
        super(TextClassifier, self).__init__()

        # 创建词嵌入层:将输入的词索引转换为固定维度的向量表示
        # vocab_size: 词汇表大小;embed_dim: 嵌入向量维度
        self.embedding = nn.Embedding(vocab_size, embed_dim)  # (1)

        # 创建 LSTM 层:处理序列数据
        # embed_dim: 输入特征维度;hidden_dim: 隐藏层维度
        # bidirectional=False 表示使用单向 LSTM;
        # batch_first=True 表示输入形状为 [batch_size, seq_len, embed_dim]
        self.lstm = nn.LSTM(
            embed_dim,
            hidden_dim,
            bidirectional=False,
            batch_first=True
        )  # (2)

        # 全连接层,用于分类:将 LSTM 输出的隐藏状态映射到类别空间
        # hidden_dim: 输入维度;num_classes: 分类数量
        self.fc = nn.Linear(hidden_dim, num_classes)

    # 前向传播函数,定义数据如何通过网络
    def forward(self, x):
        """
        前向传播函数
        x: 输入张量,形状为 [batch_size, seq_len],表示词索引序列
        返回: 分类 logits,形状为 [batch_size, num_classes]
        """
        # 将输入 x 映射为词向量
        # 输出形状:[batch_size, seq_len, embed_dim]
        x = self.embedding(x)

        # 将词向量送入 LSTM 网络
        # lstm_out: 所有时间步的输出;h_n: 最终的隐藏状态;c_n: 最终的细胞状态
        # 如果 batch_first=True,则输出形状为 [batch_size, seq_len, hidden_dim]
        lstm_out, (h_n, c_n) = self.lstm(x)

        # 使用最后一个时间步的隐藏状态进行分类
        # h_n 形状为 [num_layers * num_directions, batch_size, hidden_dim]
        # 因为是单向 LSTM 且 num_layers=1,所以取 h_n[-1] 即最后一个层的隐藏状态
        out = self.fc(h_n[-1])

        return out


# ------------------------------ 测试代码 ------------------------------
if __name__ == "__main__":
    # 模型参数
    vocab_size = 10000      # 词汇表大小
    embed_dim = 128         # 词嵌入维度
    hidden_dim = 256        # LSTM 隐藏层维度
    num_classes = 2         # 分类数量(如二分类)

    # 创建模型实例
    model = TextClassifier(
        vocab_size=vocab_size,
        embed_dim=embed_dim,
        hidden_dim=hidden_dim,
        num_classes=num_classes
    )

    # 构造一个随机输入张量:模拟一批文本数据
    # 每个样本包含 20 个词,词索引范围在 [0, vocab_size)
    x = torch.randint(0, vocab_size, (32, 20))  # batch_size=32, seq_len=20

    # 进行一次前向传播,获取输出
    output = model(x)

    # 打印输出张量的形状,应为 [batch_size, num_classes]
    print(output.shape)  # 输出: torch.Size([32, 2])

5. 重点语句解读

  • nn.Embedding(...):将词索引转换为词向量。
  • nn.LSTM(...):定义LSTM层,bidirectional=True可变为双向LSTM。
  • lstm_out, (h_n, c_n):返回所有时刻的输出以及最后时刻的隐藏状态和细胞状态。

三、Transformer

1. 基本原理与结构

Transformer 是一种完全基于注意力机制的模型,解决了RNN在长序列上的瓶颈问题。

  • 自注意力机制(Self-Attention)让每个位置关注整个序列。
  • 多头注意力(Multi-head Attention)
  • 位置编码(Positional Encoding)补充序列顺序信息
  • 前馈网络(Feed Forward Network)

2. 关键点与注意点

关键点

注意点

并行计算能力强

对长序列计算复杂度高(O(n²))

支持长距离依赖

需要位置编码来获取顺序信息

多头机制增强表达能力

容易过拟合,需要正则化(如Dropout)

3. 应用场景

  • 自然语言处理(BERT、GPT系列)
  • 图像处理(Vision Transformer)
  • 视频理解、音频识别

4. 示例代码(PyTorch 实现一个简化版 Transformer 编码器)

Python脚本

# 导入必要的库
import torch
import torch.nn as nn


# 定义位置编码类,为词嵌入添加序列位置信息
class PositionalEncoding(nn.Module):
    def __init__(self, d_model, dropout=0.1, max_len=5000):
        """
        初始化位置编码层。
        
        Args:
            d_model: 模型的嵌入维度
            dropout: Dropout 概率,用于防止过拟合
            max_len: 序列最大长度
        """
        super(PositionalEncoding, self).__init__()
        
        # 定义 Dropout 层
        self.dropout = nn.Dropout(p=dropout)

        # 创建位置编码矩阵 [max_len, d_model]
        pe = torch.zeros(max_len, d_model)

        # 生成位置索引 [max_len, 1]
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)

        # 计算分母项:div_term = 1 / (10000^(2i/d_model))
        # 使用对数避免数值溢出
        div_term = torch.exp(
            torch.arange(0, d_model, 2).float() * 
            (-torch.log(torch.tensor(10000.0)) / d_model)
        )

        # 偶数维度使用 sin 编码
        pe[:, 0::2] = torch.sin(position * div_term)

        # 奇数维度使用 cos 编码
        pe[:, 1::2] = torch.cos(position * div_term)

        # 扩展 batch 维度 -> [1, max_len, d_model]
        pe = pe.unsqueeze(0)

        # 注册为 buffer:保存时非参数,但会随设备移动(如 GPU)
        self.register_buffer('pe', pe)

    def forward(self, x):
        """
        前向传播:将位置编码加到输入张量上。
        
        Args:
            x: 输入张量,形状为 [batch_size, seq_len, d_model]
        
        Returns:
            经过位置编码和 Dropout 后的输出
        """
        # 将位置编码截取到当前序列长度并加到输入上
        x = x + self.pe[:, :x.size(1)]
        
        # 应用 Dropout
        return self.dropout(x)


# 定义基于 Transformer 的文本分类模型
class TransformerModel(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_heads, num_layers, num_classes):
        """
        初始化 Transformer 分类模型。
        
        Args:
            vocab_size: 词汇表大小
            embed_dim: 词嵌入维度
            num_heads: 多头注意力头数
            num_layers: Transformer 编码器层数
            num_classes: 分类类别数
        """
        super(TransformerModel, self).__init__()

        # 词嵌入层
        self.embedding = nn.Embedding(vocab_size, embed_dim)

        # 位置编码层
        self.positional_encoding = PositionalEncoding(embed_dim, dropout=0.1)

        # 定义单层 Transformer Encoder Layer
        encoder_layer = nn.TransformerEncoderLayer(
            d_model=embed_dim,
            nhead=num_heads
        )

        # 堆叠多层 Transformer Encoder
        self.transformer_encoder = nn.TransformerEncoder(
            encoder_layer,
            num_layers=num_layers
        )

        # 全连接分类层
        self.fc = nn.Linear(embed_dim, num_classes)

    def forward(self, src):
        """
        前向传播函数。
        
        Args:
            src: 输入张量,形状为 [batch_size, seq_len]
        
        Returns:
            分类输出,形状为 [batch_size, num_classes]
        """
        # 获取 batch_size 和 seq_len
        batch_size, seq_len = src.shape

        # 词嵌入: [batch_size, seq_len] -> [batch_size, seq_len, embed_dim]
        x = self.embedding(src)

        # 添加位置编码
        x = self.positional_encoding(x)

        # 调整维度以适应 Transformer 输入格式: [seq_len, batch_size, embed_dim]
        x = x.permute(1, 0, 2)

        # 通过 Transformer Encoder
        x = self.transformer_encoder(x)

        # 对序列维度取平均,得到句子级表示: [batch_size, embed_dim]
        x = x.mean(dim=0)

        # 通过全连接层进行分类
        out = self.fc(x)

        return out


# -------------------------- 超参数设置 --------------------------
vocab_size = 10000      # 词汇表大小
embed_dim = 512         # 词向量维度
num_heads = 8           # 多头注意力头数
num_layers = 3          # Transformer 层数
num_classes = 2         # 分类类别数(例如:正面/负面)

# -------------------------- 模型实例化 --------------------------
model = TransformerModel(
    vocab_size=vocab_size,
    embed_dim=embed_dim,
    num_heads=num_heads,
    num_layers=num_layers,
    num_classes=num_classes
)

# -------------------------- 模拟输入测试 --------------------------
# 生成随机输入数据:batch_size=32, seq_len=20
batch_size = 32
seq_len = 20
x = torch.randint(low=0, high=vocab_size, size=(batch_size, seq_len))

# 前向传播
output = model(x)

# 输出结果形状应为 [32, 2]
print(output.shape)  # 输出: torch.Size([32, 2])

5. 重点语句解读

  • PositionalEncoding:给输入加上位置信息,因为Transformer本身不考虑顺序。
  • nn.TransformerEncoderLayer(...):构建一个Transformer编码层。
  • x = x.permute(...):调整张量维度以适配PyTorch内置的Transformer模块要求(seq_len first)。
  • x.mean(dim=0):取所有token的平均值作为整个句子的表示。

总结对比表

特性

CNN

RNN

Transformer

输入类型

图像、网格数据

序列

序列

并行性

弱(串行)

极强

序列建模能力

计算复杂度

O(n)

O(n)

O(n²)

典型应用

图像分类

文本处理

NLP、视觉

——The END——


🔗 欢迎订阅专栏

序号 专栏名称 说明
1 用Python进行AI数据分析进阶教程 《用Python进行AI数据分析进阶教程》专栏
2 AI大模型应用实践进阶教程 《AI大模型应用实践进阶教程》专栏
3 Python编程知识集锦 《Python编程知识集锦》专栏
4 字节跳动旗下AI制作抖音视频 《字节跳动旗下AI制作抖音视频》专栏
5 智能辅助驾驶 《智能辅助驾驶》专栏
6 工具软件及IT技术集锦 《工具软件及IT技术集锦》专栏

👉 关注我 @理工男大辉郎 获取实时更新

欢迎关注、收藏或转发。
敬请关注 我的
微信搜索公众号:cnFuJH
CSDN博客:理工男大辉郎
抖音号:31580422589

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐