深度学习

最近学习了深度学习,感觉内容非常丰富,目前还在消化吸收中。写这篇博客主要是为了梳理我这几天所学,记录学习足迹,也欢迎各位读者指出不足之处!

一、 什么是深度学习:特征提取的艺术

简单来说,深度学习是机器学习的一个分支,其核心在于如何让机器自动地从数据中学习和提取有效的特征,进而完成复杂的任务(如分类、识别、预测等)。

举个例子:为了实现为每个用户推送最合适的抖音视频内容,我们可以构建一个神经网络模型。这个模型的输入是用户历史观看行为数据(数据中蕴含海量特征),输出则是模型学习到的、代表用户对不同内容特征偏好程度的权重(例如,特征A占30%,特征B占50%...)。后续推送就可以侧重这些高权重特征相关的视频。

那么,这个模型是如何构建和工作的呢?

  1. 模型基础: 类似于函数 y = w * x + b。数据x输入模型,经过一系列计算得到输出y
  2. 参数学习: w(权重参数) 决定了输入特征x对结果y的影响大小(w越大,该特征越重要);b(偏置项) 是模型的偏移量。
  3. 训练过程: 如何让模型预测更准确?需要输入大量的训练数据进行训练
    • 初始化: 首先构建模型的基本框架(网络结构),其中的wb初始值通常随机生成。
    • 前向传播: 将训练数据输入模型,数据流经网络各层进行计算,最终得到预测输出y_pred
    • 计算损失: 将模型的预测输出y_pred与真实的标签y_true进行比较,使用损失函数 (如均方误差MSE、交叉熵CrossEntropy)计算它们之间的差异(损失值loss)。
    • 反向传播: 核心步骤!利用链式法则,计算损失函数loss相对于模型每个参数(w, b)的梯度 (偏导数 ∂loss/∂w, ∂loss/∂b)。梯度指示了参数需要调整的方向和幅度(减少loss的方向)。
    • 参数更新: 使用优化器 (如SGD, Adam)根据计算出的梯度更新模型的wb值(例如:w = w - learning_rate * ∂loss/∂w)。
  4. 迭代优化: 重复执行前向传播->计算损失->反向传播->更新参数这个过程数千次甚至上万次(称为"迭代"或"轮次"),模型参数(w, b)会逐渐调整到最优状态,使得模型在训练数据上的预测越来越准确(损失越来越小)。

总结: 深度学习就是通过设计神经网络结构,利用大量的数据和反向传播算法,不断迭代优化模型内部的参数(w, b),最终让模型具备强大的、自动化的特征提取和模式识别 能力。整个过程的核心就是"前向传播计算输出 -> 计算损失 -> 反向传播计算梯度 -> 优化器更新参数"的循环。

二、 模型搭建的关键要素

1. 数据预处理:模型的基石

原始数据通常五花八门,格式各异。在输入模型之前,必须进行数据预处理

  • 数据清洗: 处理缺失值、去除异常值或无效数据、处理重复数据等。
  • 标准化/归一化: 将不同尺度的特征缩放到一个相对统一的范围内(如[0, 1]或均值为0、方差为1)。这能显著加速模型收敛并提高性能。
  • 数据集划分: 将处理后的数据划分为:
    • 训练集 (Training Set): 用于训练模型参数(占比最大,如70%)。
    • 验证集 (Validation Set): 用于在训练过程中监控模型性能、调整超参数(如学习率、网络层数)和进行早停(Early Stopping)以防止过拟合(如20%)。
    • 测试集 (Test Set): 用于在模型训练和调优完成后,最终、独立地评估模型的泛化能力(如10%)。比例(如7:2:1)可根据数据量和任务调整。

2. 神经网络的核心:层 (Layers)

搭建模型的核心是定义神经网络的层结构。一个神经网络必然包含:

  • 输入层 (Input Layer): 接收原始数据。其大小(神经元数量)由输入数据的维度决定(例如,一张28x28的灰度图像展开成784个像素点输入,对应784个神经元)。
  • 输出层 (Output Layer): 产生模型的最终预测结果。其大小和激活函数由任务性质决定(例如,10分类任务通常有10个神经元,使用Softmax激活)。
  • 隐藏层 (Hidden Layers): 位于输入层和输出层之间。层数和每层的神经元数量(宽度)由我们设计决定。它们是模型学习特征表示的核心部分。

层与层之间的连接: 通常,前一层的所有神经元(数量记为 x)会连接到下一层的所有神经元(数量记为 y)。这会产生 x * y 个权重参数 (w) 和 y 个偏置参数 (b)。

常见的隐藏层类型:

  1. 全连接层 (Fully Connected Layer / Dense Layer)

    • 作用: 对输入数据进行线性变换 (y = w*x + b) 后接非线性激活函数(如ReLU、Sigmoid、Tanh),提取更高级别的特征。是网络中最基础的层类型。

    • 结构: 每个神经元的输出是前一层所有神经元输入的加权和 + 偏置项,再通过激活函数。

    • 应用场景: 处理一维特征向量(如图像分类任务中卷积层提取特征后的向量、自然语言处理中的词嵌入向量)。

    • PyTorch 示例:

      python 复制代码
      import torch.nn as nn
      fc_layer = nn.Linear(in_features=128, out_features=64)  # 输入128维,输出64维
  2. 卷积层 (Convolutional Layer)

    • 作用: 卷积神经网络(CNN)的核心。使用卷积核(滤波器) 在输入数据(通常是图像)上滑动,提取局部空间特征(如边缘、纹理)。模拟了人类视觉系统逐层提取特征的过程。卷积核的数量决定了输出特征图的通道数(深度)。

    • 结构: 输入数据(如H x W x C的图像)与卷积核进行卷积运算,生成特征图(Feature Map)。每个卷积核学习提取一种特定的局部特征模式。

    • 应用场景: 图像处理、计算机视觉(图像分类、目标检测、语义分割等)。

    • PyTorch 示例与参数详解:

      python 复制代码
      import torch.nn as nn
      # 定义一个卷积层: 输入3通道(如RGB图像), 输出16个特征图(即用16个卷积核), 卷积核大小3x3, 滑动步长1, 边缘填充1圈(保持尺寸)
      conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)
      
      # 输出尺寸计算 (假设输入尺寸 H_in x W_in):
      # H_out = floor((H_in + 2*padding - kernel_size) / stride) + 1
      # W_out = floor((W_in + 2*padding - kernel_size) / stride) + 1
      # 当 padding = kernel_size // 2 且 stride=1 时,通常能保持 H_out = H_in, W_out = W_in。
      • in_channels: 输入数据的通道数 (C_in)。RGB图像为3,灰度图为1。
      • out_channels: 输出特征图的通道数/数量 (C_out)。即使用的卷积核数量。
      • kernel_size: 卷积核的空间尺寸(高度x宽度)。整数表示正方形核。
      • stride: 卷积核在输入上滑动的步长。控制输出特征图尺寸的缩减程度。
      • padding: 在输入数据边缘填充的像素圈数(通常用0填充)。常用于控制输出特征图尺寸,特别当stride=1时,padding=1配合kernel_size=3可保持输入输出宽高不变。
  3. 池化层 (Pooling Layer)

    • 作用: 通常跟在卷积层后。对局部区域进行下采样 ,降低特征图的空间分辨率(宽度和高度),减少计算量和参数数量 ,同时保留重要特征(如最大池化保留最显著特征),并赋予模型一定的平移不变性

    • 结构:

      • 最大池化 (Max Pooling): 取局部区域内的最大值。
      • 平均池化 (Average Pooling): 取局部区域内的平均值。
    • 应用场景: 图像处理、计算机视觉任务。

    • PyTorch 示例:

      python 复制代码
      import torch.nn as nn
      # 定义一个最大池化层: 池化窗口2x2, 滑动步长2 (通常步长等于窗口大小,实现减半下采样)
      max_pool_layer = nn.MaxPool2d(kernel_size=2, stride=2)
  4. 循环层 (Recurrent Layer)

    • 作用: 循环神经网络(RNN)的核心。设计用于处理序列数据 (如时间步、单词序列)。神经元不仅接收当前时间步的输入,还接收前一个时间步自身的输出(隐藏状态),具有记忆功能,能捕捉序列中的时间依赖关系。

    • 结构变体:

      • 简单RNN (RNN): 基础循环单元,易受梯度消失/爆炸问题影响。
      • 长短期记忆网络 (LSTM): 引入"门"机制(输入门、遗忘门、输出门),有效解决长序列依赖问题。
      • 门控循环单元 (GRU): LSTM的简化版,合并了部分门,计算效率更高。
    • 应用场景: 时间序列预测(股票、天气)、自然语言处理(文本生成、机器翻译、情感分析)、语音识别。

    • PyTorch 示例:

      python 复制代码
      import torch.nn as nn
      # 定义一个LSTM层: 输入维度128, 隐藏状态维度64, 堆叠2层, batch维度为第一维(batch_first=True)
      lstm_layer = nn.LSTM(input_size=128, hidden_size=64, num_layers=2, batch_first=True)
  5. 批归一化层 (Batch Normalization Layer)

    • 作用: 对每一层的输入进行归一化 处理(使其均值接近0,标准差接近1),然后进行缩放和偏移。加速训练收敛 ,减少对参数初始化的依赖,提高模型稳定性和泛化能力,并允许使用更高的学习率。

    • 应用场景: 几乎应用于所有类型的深度神经网络,尤其是在深层网络中效果显著。

    • PyTorch 示例:

      python 复制代码
      import torch.nn as nn
      # 定义一个2D BatchNorm层: 对具有16个通道的特征图进行归一化
      bn_layer = nn.BatchNorm2d(num_features=16)
  6. Dropout 层

    • 作用: 一种强大的正则化 技术。在训练过程中,随机丢弃 (暂时置零)一部分神经元的输出(通常按概率p,如0.5)。迫使网络不依赖于少数特定的神经元,防止过拟合 ,提高模型的鲁棒性。在测试或推理阶段,所有神经元都参与计算,但输出值需要乘以 (1-p) 进行缩放(在PyTorch中,nn.Dropout层在训练时应用dropout,在eval()模式下自动关闭并缩放)。

    • 应用场景: 广泛应用于各种网络结构,尤其在全连接层之后。

    • PyTorch 示例:

      python 复制代码
      import torch.nn as nn
      # 定义一个Dropout层: 随机丢弃神经元的概率为0.5
      dropout_layer = nn.Dropout(p=0.5)
  7. 注意力层 (Attention Layer)

    • 作用: 一种机制,使模型在处理信息(尤其是序列或集合)时,能够动态地关注与当前任务最相关的部分,忽略不重要的部分。显著提升模型(特别是RNN/Transformer)在理解上下文和长距离依赖关系上的能力。

    • 结构: 核心是计算输入元素(如序列中每个单词)的重要性权重(Attention Score) ,然后对输入进行加权求和,生成一个浓缩了关键信息的上下文向量

    • 应用场景: 自然语言处理(机器翻译、文本摘要、问答系统)、计算机视觉(图像描述生成)。

    • PyTorch 概念示例:

      python 复制代码
      import torch
      import torch.nn as nn
      import torch.nn.functional as F
      
      class SimpleAttention(nn.Module):
          def __init__(self, hidden_size):
              super(SimpleAttention, self).__init__()
              self.attn = nn.Linear(hidden_size, hidden_size)  # 学习权重参数
              self.v = nn.Parameter(torch.randn(hidden_size))  # 可学习的向量
      
          def forward(self, hidden, encoder_outputs):
              # hidden: 当前解码器状态 (batch_size, hidden_size)
              # encoder_outputs: 编码器所有时间步的输出 (batch_size, seq_len, hidden_size)
              energy = torch.tanh(self.attn(encoder_outputs))  # (batch_size, seq_len, hidden_size)
              energy = energy @ self.v  # (batch_size, seq_len) 计算未归一化的注意力分数
              attn_weights = F.softmax(energy, dim=1)  # (batch_size, seq_len) 归一化权重
              context = torch.sum(attn_weights.unsqueeze(2) * encoder_outputs, dim=1)  # (batch_size, hidden_size) 加权求和
              return context, attn_weights
  8. Transformer 层

    • 作用: 革命性的架构,完全基于自注意力机制 (Self-Attention)多头注意力 (Multi-Head Attention) ,摒弃了RNN的循环结构。能够并行处理整个序列,极大提高训练效率,并擅长捕捉长距离依赖关系。已成为NLP领域的基石模型(如BERT, GPT),并扩展到CV(如Vision Transformer)。

    • 核心结构 (以Encoder为例):

      • 多头自注意力 (Multi-Head Self-Attention): 允许模型同时关注输入序列不同位置的不同表示子空间。
      • 前馈神经网络 (Position-wise Feed-Forward Network): 对每个位置独立应用相同的全连接层进行变换。
      • 残差连接 (Residual Connection) 与 层归一化 (Layer Normalization): 围绕子层(注意力、前馈)添加,缓解梯度消失,稳定训练。
    • 应用场景: 自然语言处理(机器翻译、文本生成、问答系统、文本分类)、计算机视觉(图像分类、目标检测)。

    • PyTorch 概念示例 (简化版MultiHeadAttention):

      python 复制代码
      import torch
      import torch.nn as nn
      import torch.nn.functional as F
      
      class MultiHeadAttention(nn.Module):
          def __init__(self, embed_size, heads):
              super(MultiHeadAttention, self).__init__()
              self.embed_size = embed_size
              self.heads = heads
              self.head_dim = embed_size // heads
              # 确保embed_size能被heads整除
              assert self.head_dim * heads == embed_size, "Embed size needs to be divisible by heads"
      
              # 线性变换层 (投影到Q, K, V空间)
              self.values = nn.Linear(self.head_dim, self.head_dim, bias=False)
              self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)
              self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)
              # 合并多头输出的线性层
              self.fc_out = nn.Linear(heads * self.head_dim, embed_size)
      
          def forward(self, values, keys, query):
              # 获取batch大小
              N = query.shape[0]
              # 获取序列长度
              value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]
      
              # 分割嵌入维度到多个头 (Split the embedding into self.heads different pieces)
              values = values.reshape(N, value_len, self.heads, self.head_dim)
              keys = keys.reshape(N, key_len, self.heads, self.head_dim)
              queries = query.reshape(N, query_len, self.heads, self.head_dim)
      
              # 线性投影到Q, K, V空间
              values = self.values(values)
              keys = self.keys(keys)
              queries = self.queries(queries)
      
              # 计算注意力能量 (energy) 使用einsum高效计算矩阵乘法
              # Q的形状: (N, query_len, heads, head_dim) -> 看作 (nqhd)
              # K的形状: (N, key_len, heads, head_dim) -> 看作 (nkhd)
              # 结果: (N, heads, query_len, key_len) -> 看作 (nhqk)
              energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])
      
              # 缩放点积注意力 (Scale dot-product attention)
              energy = energy / (self.embed_size ** (1 / 2))  # 除以sqrt(d_k)
              # 计算注意力权重 (Softmax over the key dimension)
              attention = torch.softmax(energy, dim=3)  # dim=3 is key_len dimension
      
              # 应用注意力权重到Value上
              # attention: (N, heads, query_len, key_len) -> (nhql)
              # values: (N, value_len, heads, head_dim) -> (nlhd) [value_len usually equals key_len]
              # 结果: (N, query_len, heads, head_dim) -> (nqhd)
              out = torch.einsum("nhql,nlhd->nqhd", [attention, values])
              # 合并多头输出: 将最后两个维度(heads * head_dim)展平 -> (N, query_len, heads * head_dim)
              out = out.reshape(N, query_len, self.heads * self.head_dim)
              # 通过最终的线性层投影回原始嵌入维度
              out = self.fc_out(out)
              return out
      • Transformer 通常由多个 Encoder BlockDecoder Block 堆叠而成。每个 Encoder Block 包含一个多头自注意力层和一个前馈层(均带残差连接和层归一化)。Decoder Block 包含一个带掩码的多头自注意力层(防止看到未来信息)、一个编码器-解码器注意力层(关注编码器输出)和一个前馈层。
  9. 自定义层

    • 除了标准层,可以根据特定任务需求设计自定义层,例如在全连接层中使用特殊激活函数,或在卷积层中使用特定形状的卷积核。

3. 防止模型过拟合:提升泛化能力

过拟合是指模型在训练数据上表现优异,但在未见过的新数据(验证集/测试集)上表现显著下降。防止过拟合是深度学习的核心挑战之一。常用策略包括:

  1. 正则化 (Regularization):

    • L1 正则化: 在损失函数中添加权重的绝对值之和 λ * Σ|w|。鼓励模型产生稀疏权重(部分w为0),自动进行特征选择。

    • L2 正则化 (权重衰减): 在损失函数中添加权重的平方和 λ * Σw²惩罚大的权重值 ,鼓励模型使用更小的权重,降低模型复杂度。PyTorch优化器通常直接通过 weight_decay 参数实现。

      python 复制代码
      optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=0.01)  # L2正则化强度0.01
  2. Dropout: (如前所述) 训练时随机丢弃神经元,强制网络学习更鲁棒的特征表示。

  3. 批归一化 (Batch Normalization): (如前所述) 通过稳定层输入的分布来加速训练并间接提升泛化能力。

  4. 数据增强 (Data Augmentation): 在训练过程中,对输入数据应用随机但合理的变换 (如图像的旋转、翻转、裁剪、缩放、颜色抖动;文本的回译、同义词替换等),生成"新"的训练样本。增加数据多样性,使模型学习到更本质的特征,而不是训练数据的特定细节。

    python 复制代码
    from torchvision import transforms
    # 图像数据增强示例
    train_transform = transforms.Compose([
        transforms.RandomHorizontalFlip(),  # 随机水平翻转
        transforms.RandomRotation(10),     # 随机旋转 ±10度
        transforms.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1, hue=0.1),  # 随机颜色抖动
        transforms.RandomCrop(32, padding=4),  # 随机裁剪(32x32)带4像素填充
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ])
  5. 早停法 (Early Stopping): 在训练过程中持续监控验证集上的性能 (如验证损失或准确率)。当验证集性能在连续若干个轮次(Patience)内不再提升(甚至开始下降)时,提前终止训练,并回滚到验证集性能最好的模型参数。有效防止在训练集上过度优化。

    python 复制代码
    patience = 5  # 容忍验证损失不下降的轮次
    best_val_loss = float('inf')
    counter = 0
    
    for epoch in range(num_epochs):
        # ... 训练一个epoch ...
        # ... 在验证集上评估 ...
        val_loss = evaluate(model, val_loader, criterion)
    
        if val_loss < best_val_loss:
            best_val_loss = val_loss
            torch.save(model.state_dict(), 'best_model.pth')  # 保存当前最佳模型
            counter = 0  # 重置计数器
        else:
            counter += 1
            if counter >= patience:
                print(f'Early stopping triggered at epoch {epoch}')
                break  # 提前停止训练
    
    # 训练结束后,加载验证集上表现最好的模型
    model.load_state_dict(torch.load('best_model.pth'))
  6. 减少模型复杂度: 如果模型在训练集上就难以拟合(欠拟合),可能需要增加复杂度。但如果模型过拟合,一个直接的方法是减少网络的容量:减少隐藏层的数量或减少每层神经元的数量。让模型的学习能力与任务的复杂性相匹配。

  7. 交叉验证 (Cross-Validation): 尤其在数据量有限时常用(如K-Fold)。将训练集分成K份,轮流用其中K-1份训练,1份验证。循环K次后取平均性能。提供更可靠的模型性能估计,并帮助选择最佳超参数。

    python 复制代码
    from sklearn.model_selection import KFold
    kfold = KFold(n_splits=5, shuffle=True)
    
    for fold, (train_idx, val_idx) in enumerate(kfold.split(train_data)):
        train_subsampler = torch.utils.data.SubsetRandomSampler(train_idx)
        val_subsampler = torch.utils.data.SubsetRandomSampler(val_idx)
    
        train_loader = DataLoader(train_data, batch_size=64, sampler=train_subsampler)
        val_loader = DataLoader(train_data, batch_size=64, sampler=val_subsampler)
    
        # 在当前的训练/验证划分上训练和评估模型
        ...
  8. 集成学习 (Ensemble Learning): 训练多个不同的模型 (不同结构、不同初始化、不同训练数据子集),然后组合它们的预测结果(如投票、平均)。集成方法通常能显著降低预测方差,提高最终模型的泛化能力。常见方法有Bagging、Boosting、Stacking。

    python 复制代码
    # 概念示例 (模型平均)
    model1 = SimpleCNN()
    model2 = AnotherCNN()
    model3 = YetAnotherCNN()
    
    # 训练每个模型...
    # ...
    
    # 预测时取平均
    outputs = (model1(input) + model2(input) + model3(input)) / 3.0

4. 损失函数、激活函数与优化器:模型的驱动力

在定义好网络结构后,还需要指定三个关键组件:

  • 激活函数 (Activation Functions): 引入非线性,使神经网络能够拟合复杂函数。常见于隐藏层输出和输出层。
  • 损失函数 (Loss Functions / Cost Functions): 量化模型的预测值真实值之间的差距。指导模型优化的方向。
  • 优化器 (Optimizers): 根据损失函数计算出的梯度 ,决定如何更新模型参数以最小化损失。

常见激活函数

  1. ReLU (Rectified Linear Unit): f(x) = max(0, x)。最常用,计算高效,缓解梯度消失(正区间)。缺点:负区间梯度为0("死亡ReLU"问题)。
  2. Sigmoid: f(x) = 1 / (1 + exp(-x))。输出范围(0,1)。常用于二分类输出层。缺点:易饱和导致梯度消失,输出非零中心。
  3. Tanh (Hyperbolic Tangent): f(x) = tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))。输出范围(-1,1),零中心。常用于隐藏层。缺点:同样存在饱和问题。
  4. Leaky ReLU: f(x) = max(αx, x) (α是一个小的正数,如0.01)。解决ReLU负区间"死亡"问题。
  5. Softmax: f(x_i) = exp(x_i) / Σ_j exp(x_j)。将多个神经元的输出转换为概率分布 (和为1)。专用于多分类任务输出层

常见损失函数

  1. 均方误差 (MSE, Mean Squared Error): (1/N) * Σ(y_true - y_pred)²回归任务标准损失函数。对离群点敏感。
  2. 交叉熵损失 (Cross-Entropy Loss):
    • 二分类交叉熵 (BCE): -(1/N) * Σ [y_true * log(y_pred) + (1-y_true) * log(1-y_pred)]。用于二分类任务(输出层Sigmoid)。
    • 多分类交叉熵 (CCE / CE): -(1/N) * Σ Σ y_true_i * log(y_pred_i)。用于多分类 任务(输出层Softmax)。PyTorch的nn.CrossEntropyLoss内部已包含Softmax,输入应是未归一化的分数(logits),标签是类别索引。
  3. 二元交叉熵 (带Logits, BCEWithLogitsLoss): PyTorch提供。结合了Sigmoid + BCE Loss,数值计算更稳定。用于二分类(输入是logits)。
  4. Hinge Loss (合页损失): max(0, 1 - y_true * y_pred)。常用于支持向量机 (SVM) 和某些分类任务。
  5. Smooth L1 Loss: 对离群点比MSE更鲁棒。常用于目标检测中的边界框回归。

常见优化器

  1. SGD (Stochastic Gradient Descent): w = w - lr * ∇w。最基础。可添加动量 (Momentum) 加速收敛并抑制振荡:v = momentum * v - lr * ∇w; w = w + v
  2. Adam (Adaptive Moment Estimation): 结合了动量自适应学习率 (类似RMSprop)。计算每个参数的自适应学习率。最常用 ,通常收敛快且鲁棒性好。optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999))
  3. RMSprop: 通过除以梯度的平方的指数移动平均值 来调整每个参数的学习率。适合处理非平稳目标。optim.RMSprop(model.parameters(), lr=0.01, alpha=0.99)
  4. Adagrad: 为每个参数累积历史梯度的平方,据此调整学习率(历史梯度大的参数学习率小)。适合稀疏数据(如NLP),但学习率会单调下降至过小。optim.Adagrad(model.parameters(), lr=0.01)
  5. Adadelta: Adagrad的改进,限制历史梯度累计窗口(使用滑动平均),避免学习率过早衰减。optim.Adadelta(model.parameters(), lr=1.0, rho=0.9)

选择指南:

  • 损失函数: 回归任务选MSE/SmoothL1;二分类选BCE/BCEWithLogitsLoss;多分类选CrossEntropyLoss。
  • 激活函数: 隐藏层首选ReLU或其变体(Leaky ReLU);二分类输出层用Sigmoid;多分类输出层用Softmax(或让CrossEntropyLoss内部处理)。
  • 优化器: Adam通常是很好的默认选择。对某些任务或追求极致性能时,可尝试带动量的SGD或RMSprop。

三、 Python深度学习生态系统

Python拥有丰富的库支持深度学习研究和开发:

  1. 核心框架:
    • PyTorch: 由Facebook开发。动态计算图 (Eager Execution),灵活易调试,研究首选。API设计直观。pip install torch torchvision torchaudio
    • TensorFlow: 由Google开发。支持静态图 (Graph Mode)和动态图 (Eager Mode)。生产部署工具链成熟(TF Serving, TFLite)。高级API Keras 已紧密集成。pip install tensorflow
    • JAX: 由Google开发。基于函数式编程和自动微分。强调可组合函数变换(grad, jit, vmap, pmap)。高性能(尤其适合科学计算),研究前沿。
  2. 高层API/封装:
    • Keras: 最初独立,现为TensorFlow官方高级API。极简设计,快速原型开发。也可作为独立库使用(pip install keras)。
  3. 数据处理与科学计算:
    • NumPy: 科学计算基石,提供高效多维数组操作。pip install numpy
    • Pandas: 数据处理和分析利器,核心数据结构DataFramepip install pandas
    • SciPy: 基于NumPy,提供科学计算工具(优化、积分、插值、信号处理等)。pip install scipy
  4. 数据可视化:
    • Matplotlib: 最基础的2D绘图库,高度可定制。pip install matplotlib
    • Seaborn: 基于Matplotlib的高级统计绘图库,默认样式美观,API简洁。pip install seaborn
    • Plotly / Bokeh: 交互式可视化库,适合创建Web交互图表。
  5. 工具库:
    • Scikit-learn: 经典机器学习库(分类、回归、聚类、降维、模型选择等)。包含大量实用工具(数据预处理、评估指标)。pip install scikit-learn
    • OpenCV (cv2): 计算机视觉基础库(图像/视频处理、特征提取、对象检测等)。pip install opencv-python
    • NLTK / spaCy: 自然语言处理工具包。

四、 PyTorch实战:从搭建到训练

PyTorch是一个基于Python的开源深度学习框架,以其动态计算图 (定义即执行,易于调试)和直观的面向对象设计而深受研究人员喜爱。

PyTorch核心组件

  1. 张量 (Tensor): 基础数据结构,类似NumPy数组,但支持GPU加速和自动求导。x = torch.tensor([1.0, 2.0], requires_grad=True)

  2. 自动求导 (Autograd): 引擎,自动计算张量的梯度(backward())。y = x.sum(); y.backward(); print(x.grad)

  3. 神经网络模块 (nn.Module): 所有自定义模型的基类 。必须实现__init__(定义层和参数)和forward(定义前向传播逻辑)。负责管理参数、子模块、设备转移等。不重写forward方法是不可行的!

    python 复制代码
    import torch.nn as nn
    class MyModel(nn.Module):
        def __init__(self):
            super().__init__()
            self.layer1 = nn.Linear(10, 20)  # 定义层/参数
            self.layer2 = nn.Linear(20, 1)
    
        def forward(self, x):  # 必须重写: 定义数据如何流经网络
            x = torch.relu(self.layer1(x))
            x = self.layer2(x)
            return x
    model = MyModel()
  4. 优化器 (optim): 管理参数更新。optimizer = optim.Adam(model.parameters(), lr=0.001)

  5. 数据加载 (Dataset & DataLoader): 高效加载和批处理数据。

    • Dataset: 抽象类,需实现__len____getitem__
    • DataLoader: 包装Dataset,提供迭代器、批处理、打乱、多进程加载。
  6. 损失函数 (nn): 如前所述,nn.MSELoss(), nn.CrossEntropyLoss()等。

PyTorch模型训练全流程 (以图像分类为例)

  1. 准备数据

    python 复制代码
    import torch
    import torchvision
    import torchvision.transforms as transforms
    
    # 1. 定义数据预处理/增强
    transform_train = transforms.Compose([
        transforms.RandomHorizontalFlip(),
        transforms.RandomCrop(32, padding=4),
        transforms.ToTensor(),
        transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),  # CIFAR10均值和标准差
    ])
    transform_test = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
    ])
    
    # 2. 加载数据集
    train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train)
    test_dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test)
    
    # 3. 创建数据加载器
    train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=2)
    test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=100, shuffle=False, num_workers=2)
  2. 定义模型

    python 复制代码
    import torch.nn as nn
    import torch.nn.functional as F
    
    class SimpleCNN(nn.Module):
        def __init__(self):
            super(SimpleCNN, self).__init__()
            self.conv1 = nn.Conv2d(3, 32, 3, padding=1)  # 输入3通道(RGB), 输出32特征图, 3x3卷积核, padding=1保持尺寸
            self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
            self.pool = nn.MaxPool2d(2, 2)  # 2x2池化, 步长2 (尺寸减半)
            self.fc1 = nn.Linear(64 * 8 * 8, 512)  # CIFAR10经过两次池化: 32x32 -> 16x16 -> 8x8
            self.fc2 = nn.Linear(512, 10)  # 输出10类 (CIFAR10)
    
        def forward(self, x):
            x = self.pool(F.relu(self.conv1(x)))  # Conv1 -> ReLU -> Pool
            x = self.pool(F.relu(self.conv2(x)))  # Conv2 -> ReLU -> Pool
            x = x.view(-1, 64 * 8 * 8)  # 展平: -1表示自动计算batch_size维度, 64*8*8=4096
            x = F.relu(self.fc1(x))      # FC1 -> ReLU
            x = self.fc2(x)              # FC2 (输出层)
            return x
    
    model = SimpleCNN()
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    model.to(device)  # 将模型移动到GPU (如果可用)
  3. 定义损失函数和优化器

    python 复制代码
    import torch.optim as optim
    
    criterion = nn.CrossEntropyLoss()  # 多分类交叉熵损失
    optimizer = optim.Adam(model.parameters(), lr=0.001)
  4. 训练循环

    python 复制代码
    num_epochs = 20
    
    for epoch in range(num_epochs):
        model.train()  # 设置为训练模式 (启用Dropout/BatchNorm训练行为)
        running_loss = 0.0
        correct = 0
        total = 0
    
        for i, (inputs, labels) in enumerate(train_loader, 0):
            inputs, labels = inputs.to(device), labels.to(device)  # 移动数据到设备
    
            # 梯度清零 (重要!)
            optimizer.zero_grad()
    
            # 前向传播
            outputs = model(inputs)
            loss = criterion(outputs, labels)
    
            # 反向传播 + 参数更新
            loss.backward()
            optimizer.step()
    
            # 统计训练损失和准确率
            running_loss += loss.item()
            _, predicted = outputs.max(1)
            total += labels.size(0)
            correct += predicted.eq(labels).sum().item()
    
            # 定期打印训练状态
            if i % 100 == 99:  # 每100个batch打印一次
                print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], '
                      f'Loss: {running_loss / 100:.4f}, Acc: {100. * correct / total:.2f}%')
                running_loss = 0.0
    
        # 可选: 每个epoch结束后在验证集/测试集上评估一次
        model.eval()  # 设置为评估模式 (关闭Dropout, 固定BatchNorm统计量)
        test_loss = 0
        test_correct = 0
        test_total = 0
        with torch.no_grad():  # 禁用梯度计算,节省内存和计算
            for inputs, labels in test_loader:
                inputs, labels = inputs.to(device), labels.to(device)
                outputs = model(inputs)
                loss = criterion(outputs, labels)
                test_loss += loss.item()
                _, predicted = outputs.max(1)
                test_total += labels.size(0)
                test_correct += predicted.eq(labels).sum().item()
        print(f'Epoch [{epoch+1}/{num_epochs}] Test Loss: {test_loss / len(test_loader):.4f}, '
              f'Test Acc: {100. * test_correct / test_total:.2f}%')
    
    print('Finished Training')
  5. 评估模型

    python 复制代码
    model.eval()  # 确保在评估模式
    correct = 0
    total = 0
    with torch.no_grad():
        for (inputs, labels) in test_loader:
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            _, predicted = torch.max(outputs.data, 1)  # 获取预测类别 (dim=1上最大值的索引)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    print(f'Final Test Accuracy: {100 * correct / total:.2f}%')
  6. 保存和加载模型

    python 复制代码
    # 保存模型状态字典 (推荐)
    torch.save(model.state_dict(), 'cifar10_cnn_model.pth')
    
    # 加载模型 (需要先实例化相同结构的模型)
    loaded_model = SimpleCNN()
    loaded_model.load_state_dict(torch.load('cifar10_cnn_model.pth'))
    loaded_model.to(device)
    loaded_model.eval()  # 加载后用于预测前务必设置为eval模式

五、 常见神经网络模型类型

不同的任务和数据特性需要不同的网络结构:

  1. 卷积神经网络 (CNN): 图像处理王者 。核心组件:卷积层(提取局部特征)、池化层(下采样)、全连接层(分类/回归)。应用:图像分类、目标检测、语义分割、人脸识别。 (见上文的SimpleCNN示例)
  2. 循环神经网络 (RNN) / 长短时记忆网络 (LSTM) / 门控循环单元 (GRU): 序列数据专家 。具有记忆功能,能处理变长序列,捕捉时间依赖。应用:自然语言处理(机器翻译、文本生成、情感分析)、时间序列预测(股票、天气)、语音识别。 (见上文RNN/LSTM层描述及示例)
  3. Transformer: 序列建模新范式 。完全基于自注意力机制 ,并行处理能力强,擅长捕捉长距离依赖。已成为NLP事实标准(BERT, GPT, T5),并进军CV(ViT, DETR)。核心:多头注意力、位置编码、前馈网络、残差连接、层归一化。应用:机器翻译、文本摘要、问答系统、图像分类、目标检测。 (见上文Transformer层描述及示例)
  4. 生成对抗网络 (GAN): 生成模型代表 。由生成器 (Generator)判别器 (Discriminator) 对抗训练。生成器学习生成逼真数据,判别器学习区分真实数据和生成数据。应用:图像生成、图像超分辨率、风格迁移、数据增强。 (见上文GAN示例)
  5. 自编码器 (Autoencoder): 无监督特征学习/降维 。由编码器 (Encoder) 将输入压缩为低维潜在表示 (Latent Representation / Code)解码器 (Decoder) 从潜在表示重建输入。目标是最小化重建误差。应用:降维、异常检测、图像去噪、特征提取。 (见上文Autoencoder示例)
  6. 图神经网络 (GNN): 图结构数据建模 。将神经网络应用于图数据(节点、边)。核心思想是聚合邻居节点信息来更新节点表示。应用:社交网络分析、推荐系统、分子性质预测、知识图谱。 (见上文GNN示例)

结语

深度学习是一个庞大且快速发展的领域。这篇博客梳理了我近期学习的核心概念:从理解深度学习本质(特征提取与参数优化)、模型构建的关键要素(数据、层、防过拟合、损失函数、优化器)、必备的Python工具,到使用PyTorch进行实战(数据加载、模型定义、训练循环、评估保存)。最后概述了主流的神经网络架构及其适用场景。

学习过程中,动手实践(敲代码、调模型)至关重要。虽然内容繁多,难免懵懂,但通过不断梳理、实践和总结,理解会逐步深入。这篇博客是我学习路上的一个小小里程碑,希望能对同样入门的朋友有所帮助。文中难免有理解不深或表述不当之处,恳请各位读者不吝指正!

相关推荐
慌ZHANG6 分钟前
人工智能如何重构能源系统以应对气候变化?
人工智能
KeyNG_Jykxg11 分钟前
🥳Elx开源升级:XMarkdown 组件加入、Storybook 预览体验升级
前端·vue.js·人工智能
补三补四14 分钟前
RNN(循环神经网络)
人工智能·rnn·深度学习·神经网络·算法
拓端研究室1 小时前
专题:2025机器人产业深度洞察报告|附136份报告PDF与数据下载
大数据·人工智能·物联网
深圳市快瞳科技有限公司1 小时前
端侧宠物识别+拍摄控制智能化:解决设备识别频次识别率双低问题
人工智能·宠物
智能物联实验室1 小时前
宠物设备如何用AI拦截低质量图片?
人工智能·目标跟踪·宠物
辰尘_星启1 小时前
【机器学习】反向传播如何求梯度(公式推导)
人工智能·深度学习·机器学习·强化学习·梯度下降·反向传播
我.佛.糍.粑2 小时前
Shusen Wang推荐系统学习 --召回 矩阵补充 双塔模型
人工智能·学习·机器学习·矩阵·推荐算法
倔强青铜三2 小时前
苦练Python第20天:Python官方钦定的代码风格指南
人工智能·python·面试
谢尔登2 小时前
office-ai整合excel
人工智能·excel