06 深度学习应用——《Python大数据实践(主编:吕欣 杨文川)》读书笔记

本文为《Python大数据实践(主编:吕欣 杨文川)》中“深度学习应用”相关内容的读书笔记。
本文主要围绕深度学习的基本思想、PyTorch 实践基础、常见神经网络结构、典型应用场景以及模型训练中的工程化问题展开。

本文不是对教材内容的简单复述,而是在学习基础上结合个人理解进行重新整理和扩展。


一、对深度学习的整体认识

深度学习是机器学习中的重要分支,它的核心特点是通过多层神经网络自动学习数据中的特征表示。

在传统机器学习中,特征工程往往非常重要。
例如,在图像识别任务中,可能需要人工设计颜色、纹理、边缘、形状等特征;在文本分类任务中,可能需要人工构造词频、关键词、情感词典等特征。

而深度学习的优势在于,它可以直接从原始数据中学习特征。

例如:

  • 在图像任务中,浅层网络可以学习边缘、颜色、纹理;
  • 中间层网络可以学习局部结构;
  • 深层网络可以学习更加抽象的语义信息;
  • 在文本任务中,模型可以学习词语、句子和上下文之间的关系。

因此,我认为深度学习最重要的价值不是“模型层数更深”,而是它能够自动学习复杂数据中的表示方式。


二、深度学习解决了什么问题

深度学习主要适合处理传统方法较难表达的问题。

例如:

  1. 图像识别;
  2. 语音识别;
  3. 自然语言处理;
  4. 视频分析;
  5. 推荐系统;
  6. 时间序列预测;
  7. 图结构数据分析;
  8. 多模态数据理解。

这些任务的共同特点是数据结构复杂,人工特征设计难度较高。

以图像识别为例,一张图片不是简单的数字表格,而是由大量像素组成的空间结构。
如果完全依靠人工提取特征,很难覆盖不同光照、角度、姿态和背景下的变化。

深度学习通过神经网络自动学习特征,使模型能够更好地适应复杂数据。


三、深度学习与传统机器学习的区别

深度学习和传统机器学习并不是完全对立的关系,而是适用于不同场景。

对比维度 传统机器学习 深度学习
特征来源 依赖人工特征工程 自动学习特征
数据需求 中小规模数据也能使用 通常需要较多数据
模型复杂度 相对较低 较高
可解释性 通常较好 通常较弱
计算资源 资源需求较低 通常需要 GPU
适合数据 结构化表格数据 图像、语音、文本、视频等非结构化数据

我的理解是:

传统机器学习更像是在“人设计好的特征”上学习规律;深度学习更像是让模型自己学习“什么特征有用”。

这也是深度学习能够在图像、语音和文本任务中取得突破的重要原因。


四、神经网络的基本结构

神经网络可以看作由多个神经元组成的计算模型。

一个简单的神经元可以表示为:

y=f(w1x1+w2x2+⋯+wnxn+b) y=f(w_1x_1+w_2x_2+\cdots+w_nx_n+b) y=f(w1x1+w2x2++wnxn+b)

其中:

  • xix_ixi 表示输入特征;
  • wiw_iwi 表示权重;
  • bbb 表示偏置;
  • fff 表示激活函数;
  • yyy 表示输出结果。

神经网络通过不断调整权重和偏置,使模型输出逐渐接近真实标签。

从整体流程来看,神经网络训练包括:

  1. 前向传播;
  2. 计算损失;
  3. 反向传播;
  4. 参数更新。

五、前向传播与反向传播

前向传播是指数据从输入层经过隐藏层,最终得到输出结果的过程。

例如,在图像分类任务中,输入是一张图片,输出是每个类别的预测概率。

反向传播则是根据预测结果和真实标签之间的误差,反向计算每个参数对误差的影响,并更新模型参数。

简单来说:

  • 前向传播负责“做预测”;
  • 损失函数负责“判断错多少”;
  • 反向传播负责“找到哪里错了”;
  • 优化器负责“调整参数”。

这四个部分共同构成了深度学习训练的基本闭环。


六、激活函数的作用

如果神经网络中没有激活函数,那么多层线性变换最终仍然等价于一个线性模型。
因此,激活函数的作用是引入非线性能力,使神经网络能够拟合复杂关系。

常见激活函数包括:

激活函数 特点 常见用途
Sigmoid 输出范围在 0 到 1 之间 二分类早期常用
Tanh 输出范围在 -1 到 1 之间 RNN 中较常见
ReLU 计算简单,缓解梯度消失 CNN、MLP 常用
Leaky ReLU 避免部分神经元失活 深层网络
Softmax 输出类别概率分布 多分类任务输出层

其中,ReLU 是目前非常常用的激活函数之一。

import torch
import torch.nn as nn

activation = nn.ReLU()

x = torch.tensor([-1.0, 0.0, 2.0])
y = activation(x)

print(y)

输出结果中,负数会被变为 0,正数保持不变。


七、损失函数的作用

损失函数用于衡量模型预测值和真实值之间的差距。

不同任务需要选择不同的损失函数。

任务类型 常用损失函数
回归任务 MSELoss、L1Loss
二分类任务 BCELoss、BCEWithLogitsLoss
多分类任务 CrossEntropyLoss
图像分割 Dice Loss、CrossEntropyLoss
目标检测 分类损失 + 边界框回归损失

例如,多分类任务中常使用交叉熵损失:

import torch.nn as nn

criterion = nn.CrossEntropyLoss()

回归任务中常使用均方误差损失:

criterion = nn.MSELoss()

我的理解是:

损失函数决定了模型“努力优化的方向”。

如果损失函数选择不合适,模型即使训练很久,也可能无法得到理想结果。


八、优化器的作用

优化器负责根据梯度更新模型参数。

常见优化器包括:

优化器 特点
SGD 基础优化方法,稳定但可能收敛慢
Momentum 在 SGD 基础上加入动量
RMSProp 适合处理非平稳目标
Adam 自适应学习率,使用广泛
AdamW 在 Adam 基础上改进权重衰减

在实际深度学习任务中,Adam 和 AdamW 使用较多。

import torch.optim as optim

optimizer = optim.Adam(model.parameters(), lr=0.001)

优化器并不是越复杂越好。
有些任务中,SGD 配合合适的学习率调度也能取得非常好的效果。


九、PyTorch 的基本认识

PyTorch 是深度学习中常用的框架之一。

它的特点包括:

  1. 代码风格接近 Python;
  2. 支持动态计算图;
  3. 调试相对方便;
  4. 支持 GPU 加速;
  5. 社区资源丰富;
  6. 适合研究和工程实践。

PyTorch 中最基础的数据结构是张量 Tensor。
张量可以理解为多维数组,是神经网络中数据和参数的基本表示方式。


十、PyTorch 张量操作

创建张量:

import torch

x = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)

print(x)

矩阵乘法:

y = torch.matmul(x, x.T)

print(y)

移动到 GPU:

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

x = x.to(device)

张量是 PyTorch 的基础。
神经网络中的输入、权重、梯度和输出,本质上都可以看作张量。


十一、自动求导机制

PyTorch 的一个重要能力是自动求导。

只要设置 requires_grad=True,PyTorch 就可以追踪张量计算过程,并自动计算梯度。

import torch

x = torch.tensor(2.0, requires_grad=True)

y = x ** 2 + 3 * x + 1

y.backward()

print(x.grad)

这段代码会自动计算:

y=x2+3x+1 y=x^2+3x+1 y=x2+3x+1

xxx 的导数:

dydx=2x+3 \frac{dy}{dx}=2x+3 dxdy=2x+3

x=2x=2x=2 时,梯度为 7。

自动求导是神经网络反向传播的基础。


十二、构建一个简单神经网络

在 PyTorch 中,通常通过继承 nn.Module 构建模型。

import torch
import torch.nn as nn

class SimpleNet(nn.Module):
    def __init__(self):
        super().__init__()

        self.net = nn.Sequential(
            nn.Linear(10, 32),
            nn.ReLU(),
            nn.Linear(32, 2)
        )

    def forward(self, x):
        return self.net(x)

这个模型包含:

  1. 一个输入层;
  2. 一个隐藏层;
  3. 一个 ReLU 激活函数;
  4. 一个输出层。

虽然结构简单,但已经体现了神经网络的基本组成方式。


十三、模型训练的基本流程

一个完整的 PyTorch 训练流程通常包括:

  1. 准备数据;
  2. 构建模型;
  3. 定义损失函数;
  4. 定义优化器;
  5. 前向传播;
  6. 计算损失;
  7. 反向传播;
  8. 更新参数;
  9. 验证模型效果。

示例代码:

for epoch in range(num_epochs):
    model.train()

    for x_batch, y_batch in train_loader:
        x_batch = x_batch.to(device)
        y_batch = y_batch.to(device)

        outputs = model(x_batch)

        loss = criterion(outputs, y_batch)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    print("Epoch:", epoch, "Loss:", loss.item())

需要注意的是,optimizer.zero_grad() 很重要。
如果不清空梯度,PyTorch 会默认累积梯度,导致参数更新错误。


十四、全连接神经网络 MLP

MLP 是最基础的神经网络结构,也叫多层感知机。

它主要由多个全连接层组成,适合处理结构化特征或已经向量化的数据。

例如,手写数字识别中,可以将 28×28 的图像展平成 784 维向量,然后输入 MLP。

import torch.nn as nn

class MLP(nn.Module):
    def __init__(self):
        super().__init__()

        self.model = nn.Sequential(
            nn.Linear(784, 256),
            nn.ReLU(),
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )

    def forward(self, x):
        x = x.view(x.size(0), -1)
        return self.model(x)

MLP 的优点是结构简单,容易理解。
缺点是难以保留图像中的空间结构信息。

因此,在图像任务中,CNN 通常比 MLP 更合适。


十五、卷积神经网络 CNN

CNN 是图像任务中非常重要的神经网络结构。

它的核心思想包括:

  1. 局部感受野;
  2. 权值共享;
  3. 池化降采样;
  4. 多层特征提取。

卷积层可以提取图像局部区域的特征,例如边缘、角点和纹理。
随着网络加深,模型可以提取更加抽象的语义特征。

CNN 的优势在于,它能够保留图像空间结构,同时减少参数数量。


十六、CNN 简单示例

import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self):
        super().__init__()

        self.features = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Conv2d(16, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )

        self.classifier = nn.Sequential(
            nn.Linear(32 * 7 * 7, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        return self.classifier(x)

这个模型可以用于简单的灰度图像分类任务。

其中:

  • Conv2d 用于卷积特征提取;
  • ReLU 用于引入非线性;
  • MaxPool2d 用于降低特征图尺寸;
  • Linear 用于最终分类。

十七、CNN 的应用场景

CNN 常见应用包括:

  1. 图像分类;
  2. 目标检测;
  3. 图像分割;
  4. 人脸识别;
  5. 医学影像分析;
  6. 遥感影像识别;
  7. 缺陷检测。

CNN 适合图像任务,是因为图像具有明显的空间局部性。
相邻像素之间通常存在联系,而 CNN 可以利用这种局部结构。

我的理解是:

CNN 并不是简单地“看整张图”,而是先看局部,再逐渐组合成整体理解。


十八、循环神经网络 RNN

RNN 主要用于处理序列数据。

序列数据的特点是前后之间存在顺序关系,例如:

  1. 文本;
  2. 语音;
  3. 时间序列;
  4. 股票价格;
  5. 传感器数据。

RNN 的核心思想是引入隐藏状态,用来保存历史信息。

其基本形式可以表示为:

ht=tanh⁡(Wxt+Uht−1+b) h_t=\tanh(Wx_t+Uh_{t-1}+b) ht=tanh(Wxt+Uht1+b)

其中:

  • xtx_txt 表示当前时刻输入;
  • ht−1h_{t-1}ht1 表示上一时刻隐藏状态;
  • hth_tht 表示当前隐藏状态。

RNN 的问题是,当序列较长时,容易出现梯度消失或梯度爆炸,导致模型难以学习长期依赖关系。


十九、LSTM 与 GRU

为了解决普通 RNN 难以捕捉长期依赖的问题,出现了 LSTM 和 GRU。

LSTM 通过门控机制控制信息的保留和遗忘。
它包含输入门、遗忘门、输出门等结构。

GRU 是 LSTM 的简化版本,参数更少,训练速度通常更快。

二者都适合处理序列任务,例如:

  • 文本分类;
  • 机器翻译;
  • 语音识别;
  • 时间序列预测;
  • 股票趋势预测。

简单来说:

RNN 适合短序列,LSTM 和 GRU 更适合长序列。


二十、LSTM 示例代码

import torch.nn as nn

class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()

        self.lstm = nn.LSTM(
            input_size=input_size,
            hidden_size=hidden_size,
            num_layers=2,
            batch_first=True
        )

        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        output, (h_n, c_n) = self.lstm(x)

        last_output = output[:, -1, :]

        return self.fc(last_output)

在时间序列预测中,输入通常是一个时间窗口。
例如,用过去 30 天的数据预测第 31 天的数值。


二十一、Transformer 的基本认识

Transformer 是自然语言处理领域的重要模型结构,也逐渐扩展到图像、语音、多模态等领域。

Transformer 的核心机制是注意力机制,尤其是自注意力机制。

自注意力机制可以让模型在处理一个词时,同时关注句子中的其他词。

例如,对于句子:

我把苹果放进书包,因为它很重。

模型需要判断“它”指的是苹果还是书包。
注意力机制可以帮助模型建立词与词之间的联系。


二十二、Transformer 的优势

与 RNN 相比,Transformer 有几个明显优势:

  1. 更容易并行计算;
  2. 更擅长捕捉长距离依赖;
  3. 可以处理复杂上下文关系;
  4. 适合大规模预训练;
  5. 能够扩展到多模态任务。

Transformer 的出现推动了 BERT、GPT、T5、ViT 等模型的发展。

我的理解是:

RNN 是按顺序读句子,Transformer 是同时观察句子中各部分之间的关系。

这也是 Transformer 在 NLP 中表现突出的重要原因。


二十三、注意力机制的直观理解

注意力机制可以理解为模型在处理信息时的“重点选择”。

在图像中,模型可能更关注目标所在区域;
在文本中,模型可能更关注与当前词语相关的上下文;
在时间序列中,模型可能更关注关键时间点。

注意力机制的价值在于,它不是平均对待所有输入,而是学习哪些信息更重要。

这使模型具有更强的表达能力。


二十四、图神经网络 GNN

图神经网络用于处理图结构数据。

图结构由节点和边组成。
例如:

  • 社交网络中,用户是节点,好友关系是边;
  • 论文引用网络中,论文是节点,引用关系是边;
  • 交通网络中,路口是节点,道路是边;
  • 分子结构中,原子是节点,化学键是边。

传统神经网络擅长处理规则数据,例如图像和序列。
但图结构是不规则的,因此需要专门的图神经网络。


二十五、GNN 的基本思想

GNN 的核心思想是信息传播。

每个节点不仅使用自身特征,还会聚合邻居节点的信息。

可以简单理解为:

一个节点的表示,不只由自己决定,也由它周围的节点共同决定。

例如,在论文分类任务中,一篇论文的类别不仅与自身文本有关,也可能与它引用了哪些论文、被哪些论文引用有关。

常见 GNN 模型包括:

  1. GCN;
  2. GAT;
  3. GraphSAGE;
  4. GIN。

其中,GAT 引入注意力机制,可以为不同邻居分配不同重要性。


二十六、深度学习应用一:图像分类

图像分类是深度学习最典型的应用之一。

任务目标是让模型判断一张图片属于哪个类别。

例如:

  • 猫狗分类;
  • 手写数字识别;
  • 遥感地物分类;
  • 医学影像病灶识别;
  • 工业产品缺陷识别。

图像分类的一般流程包括:

  1. 收集图像数据;
  2. 标注类别标签;
  3. 图像尺寸统一;
  4. 数据增强;
  5. 构建 CNN 或使用预训练模型;
  6. 训练模型;
  7. 评估准确率;
  8. 分析错误样本。

二十七、图像分类中的数据增强

数据增强是提升图像模型泛化能力的重要方法。

常见方法包括:

  1. 随机裁剪;
  2. 水平翻转;
  3. 颜色扰动;
  4. 随机旋转;
  5. 尺度缩放;
  6. 添加噪声。

PyTorch 示例:

from torchvision import transforms

transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(10),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

数据增强的作用不是简单增加图片数量,而是让模型见到更多变化情况,从而减少过拟合。


二十八、迁移学习的价值

在图像任务中,如果数据量不大,从零训练深度模型通常效果不好。

此时可以使用迁移学习。

迁移学习的思想是:

利用在大规模数据集上训练好的模型,再针对自己的任务进行微调。

例如,可以使用 ResNet、VGG、EfficientNet 等预训练模型。

import torchvision.models as models
import torch.nn as nn

model = models.resnet18(weights="DEFAULT")

num_features = model.fc.in_features

model.fc = nn.Linear(num_features, 5)

这里将 ResNet 的最后分类层替换为适合自己任务的类别数量。

迁移学习的优势是:

  1. 减少训练时间;
  2. 降低数据需求;
  3. 提升模型效果;
  4. 适合中小规模数据集。

二十九、深度学习应用二:目标检测与实例分割

图像分类只需要判断图片属于哪一类。
但在很多场景中,我们还需要知道目标在哪里。

这就需要目标检测。

目标检测不仅要判断类别,还要输出目标位置。
例如,在监控图像中检测行人,需要输出行人的类别和边界框。

实例分割则进一步要求模型识别出目标的精确轮廓。

常见模型包括:

  1. Faster R-CNN;
  2. Mask R-CNN;
  3. YOLO;
  4. SSD;
  5. DETR。

三十、目标检测的实践难点

目标检测比图像分类更复杂,主要难点包括:

  1. 图像中目标数量不固定;
  2. 目标大小差异较大;
  3. 目标可能发生遮挡;
  4. 背景干扰较多;
  5. 标注成本较高;
  6. 实时检测对速度要求高。

例如,在行人检测中,一个人可能只露出半个身体,也可能被其他物体遮挡。
这就要求模型不仅能识别完整目标,也能识别局部可见目标。

在工程应用中,目标检测模型需要在准确率和推理速度之间平衡。


三十一、深度学习应用三:时间序列预测

时间序列预测是深度学习的重要应用方向之一。

常见任务包括:

  1. 股票价格预测;
  2. 电力负荷预测;
  3. 交通流量预测;
  4. 气象数据预测;
  5. 设备状态预测;
  6. 用户行为趋势预测。

时间序列数据具有明显的时间依赖性。
当前状态往往与过去一段时间有关。

LSTM、GRU、Temporal CNN 和 Transformer 都可以用于时间序列建模。


三十二、时间序列预测的注意事项

时间序列预测不能像普通数据一样随机打乱。

因为时间顺序本身包含重要信息。

在划分训练集和测试集时,应按照时间顺序划分:

前 70% 时间段:训练集
中间 15% 时间段:验证集
后 15% 时间段:测试集

如果随机划分,可能会出现未来信息泄露,导致模型评估结果虚高。

这是时间序列建模中非常容易忽视的问题。


三十三、时间窗口构造示例

使用过去若干天数据预测下一天,可以构造滑动窗口。

import numpy as np

def build_windows(data, window_size):
    X = []
    y = []

    for i in range(window_size, len(data)):
        X.append(data[i-window_size:i])
        y.append(data[i])

    return np.array(X), np.array(y)

例如,使用过去 30 天预测第 31 天:

X, y = build_windows(data, window_size=30)

这种方式把时间序列问题转化为了监督学习问题。


三十四、深度学习应用四:自然语言处理

自然语言处理主要研究如何让计算机理解和生成文本。

常见任务包括:

  1. 文本分类;
  2. 情感分析;
  3. 机器翻译;
  4. 文本摘要;
  5. 命名实体识别;
  6. 问答系统;
  7. 文本生成。

早期 NLP 方法依赖词袋模型、TF-IDF、Word2Vec 等技术。
现在,BERT、GPT 等预训练语言模型成为主流方法。


三十五、情感分析任务理解

情感分析是文本分类中的典型任务。

例如,判断一句评论是正面还是负面:

这家酒店位置很好,服务也很热情。

可以判断为正面。

房间很吵,卫生也不好。

可以判断为负面。

情感分析看似简单,但实际存在很多难点:

  1. 反讽表达;
  2. 否定词;
  3. 语境依赖;
  4. 行业词汇;
  5. 多情感混合;
  6. 短文本信息不足。

例如:

这服务真是太“贴心”了。

如果结合上下文,可能实际表达的是不满。


三十六、BERT 微调基本流程

BERT 是一种基于 Transformer 的预训练语言模型。
在具体任务中,可以在预训练模型基础上进行微调。

基本流程包括:

  1. 加载分词器;
  2. 对文本进行编码;
  3. 加载预训练模型;
  4. 添加分类层;
  5. 在任务数据上训练;
  6. 评估模型效果。

示例代码:

from transformers import BertTokenizer, BertForSequenceClassification

tokenizer = BertTokenizer.from_pretrained("bert-base-chinese")

model = BertForSequenceClassification.from_pretrained(
    "bert-base-chinese",
    num_labels=2
)

文本编码:

encoded = tokenizer(
    texts,
    padding=True,
    truncation=True,
    max_length=128,
    return_tensors="pt"
)

BERT 的优势在于能够结合上下文理解词语含义。
这比传统词袋模型更适合复杂文本理解任务。


三十七、深度学习应用五:机器翻译

机器翻译是自然语言处理中的重要任务。

早期机器翻译依赖规则和统计方法。
后来,RNN、LSTM 和 Seq2Seq 模型推动了神经机器翻译的发展。
现在,Transformer 成为机器翻译中的核心结构。

机器翻译的难点包括:

  1. 词序差异;
  2. 一词多义;
  3. 长句依赖;
  4. 文化语境;
  5. 低资源语言;
  6. 专业术语翻译。

例如,中文和英文的语序差异较大,直接逐词翻译往往效果不好。

Transformer 通过注意力机制,可以更好地建立源语言和目标语言之间的对应关系。


三十八、深度学习应用六:图结构数据分析

图结构数据在现实中非常常见。

例如:

  1. 社交网络;
  2. 推荐系统;
  3. 交通网络;
  4. 知识图谱;
  5. 分子结构;
  6. 论文引用网络。

在图结构任务中,模型不仅要考虑节点自身特征,还要考虑节点之间的连接关系。

常见任务包括:

  1. 节点分类;
  2. 边预测;
  3. 图分类;
  4. 社区发现;
  5. 链路预测。

图神经网络的价值在于,它能把结构信息和特征信息结合起来。


三十九、图注意力网络 GAT 的理解

GAT 在 GNN 中引入注意力机制。

它不是简单平均邻居信息,而是学习不同邻居的重要程度。

例如,在论文引用网络中,一篇论文可能引用很多论文,但并不是每篇引用论文对当前论文分类都同等重要。
GAT 可以自动学习哪些邻居节点更关键。

这种思想与人类判断类似:

不同关系的重要性不同,模型应该学会区分。


四十、深度学习应用七:风格迁移

风格迁移是一种有趣的深度学习应用。

它的目标是将一张图片的内容和另一张图片的风格结合起来。

例如:

  • 内容图像是一张城市照片;
  • 风格图像是一幅油画;
  • 生成图像保留城市结构,同时具有油画风格。

风格迁移通常会使用预训练 CNN 提取图像特征。

其中:

  • 内容损失用于保留原图结构;
  • 风格损失用于学习风格图像的纹理和色彩;
  • 总损失用于平衡内容和风格。

四十一、Gram 矩阵的直观理解

在风格迁移中,Gram 矩阵常用于表示风格信息。

它可以衡量不同特征通道之间的相关性。

简单来说:

内容关注“图中有什么”,风格关注“它看起来像什么”。

示例代码:

import torch

def gram_matrix(feature):
    batch, channels, height, width = feature.size()

    feature = feature.view(batch * channels, height * width)

    gram = torch.mm(feature, feature.t())

    return gram / (batch * channels * height * width)

通过比较生成图像和风格图像的 Gram 矩阵,可以让生成图像逐渐接近目标风格。


四十二、深度学习训练中的过拟合问题

过拟合是深度学习中常见问题。

表现为:

  • 训练集效果很好;
  • 验证集或测试集效果较差。

原因可能包括:

  1. 模型过于复杂;
  2. 数据量太少;
  3. 数据噪声较大;
  4. 训练轮数过多;
  5. 数据增强不足;
  6. 正则化不足。

解决方法包括:

  1. 增加数据;
  2. 数据增强;
  3. Dropout;
  4. L2 正则化;
  5. Early Stopping;
  6. 降低模型复杂度;
  7. 使用预训练模型;
  8. 交叉验证。

四十三、Dropout 的作用

Dropout 是防止过拟合的常用方法。

它在训练过程中随机丢弃部分神经元,使模型不能过度依赖某些特定节点。

import torch.nn as nn

layer = nn.Dropout(p=0.5)

在训练时,Dropout 会随机让部分神经元输出为 0。
在测试时,Dropout 不再随机丢弃神经元。

我的理解是:

Dropout 相当于让模型不要只依赖少数“熟人”,而是学会从更多特征中做判断。


四十四、Batch Normalization 的作用

Batch Normalization 用于稳定神经网络训练过程。

它可以对中间层输出进行标准化,使数据分布更加稳定。

优点包括:

  1. 加快训练速度;
  2. 缓解梯度消失;
  3. 使模型对初始化不那么敏感;
  4. 具有一定正则化效果。

示例:

import torch.nn as nn

bn = nn.BatchNorm2d(32)

在 CNN 中,BatchNorm 常放在卷积层之后、激活函数之前或之后。


四十五、学习率调度

学习率是深度学习训练中非常重要的超参数。

学习率太大,模型可能震荡甚至无法收敛。
学习率太小,模型训练速度很慢,也可能陷入局部最优。

常见学习率策略包括:

  1. 固定学习率;
  2. 分段衰减;
  3. 指数衰减;
  4. 余弦退火;
  5. 学习率预热。

PyTorch 示例:

scheduler = torch.optim.lr_scheduler.StepLR(
    optimizer,
    step_size=10,
    gamma=0.1
)

在每轮训练后更新学习率:

scheduler.step()

学习率调度的作用是让模型在训练初期快速学习,在训练后期稳定收敛。


四十六、早停机制 Early Stopping

Early Stopping 是防止过拟合的常用方法。

它的思想是:

如果验证集效果连续多轮没有提升,就提前停止训练。

这样可以避免模型在训练集上继续过度拟合。

简单逻辑如下:

best_loss = float("inf")
patience = 5
counter = 0

for epoch in range(num_epochs):
    val_loss = evaluate(model, val_loader)

    if val_loss < best_loss:
        best_loss = val_loss
        counter = 0
        torch.save(model.state_dict(), "best_model.pth")
    else:
        counter += 1

    if counter >= patience:
        print("Early stopping")
        break

早停机制在数据量有限时非常实用。


四十七、模型评估指标

不同任务需要不同的评估指标。

分类任务常用:

  1. Accuracy;
  2. Precision;
  3. Recall;
  4. F1-score;
  5. AUC。

回归任务常用:

  1. MAE;
  2. MSE;
  3. RMSE;
  4. R²。

目标检测常用:

  1. IoU;
  2. mAP;
  3. Precision;
  4. Recall。

机器翻译常用:

  1. BLEU;
  2. ROUGE;
  3. METEOR。

不能只看一个指标。
例如,在类别不平衡任务中,Accuracy 可能很高,但模型可能只是倾向预测多数类。


四十八、深度学习中的数据质量问题

深度学习虽然强大,但对数据质量非常敏感。

常见数据问题包括:

  1. 标签错误;
  2. 样本数量不足;
  3. 类别不平衡;
  4. 数据分布偏移;
  5. 重复数据过多;
  6. 训练集与测试集差异过大;
  7. 数据泄露。

例如,在图像分类中,如果训练集背景与类别高度绑定,模型可能学到的是背景,而不是目标本身。

比如,所有猫图片都在室内,所有狗图片都在户外,模型可能实际上是在区分室内和户外。

因此,深度学习不是只要把数据丢进模型就可以,还需要认真检查数据。


四十九、深度学习工程实践流程

我认为,一个完整的深度学习项目可以按照以下流程进行:

  1. 明确任务目标;
  2. 收集数据;
  3. 检查数据质量;
  4. 划分训练集、验证集和测试集;
  5. 进行数据预处理;
  6. 构建基线模型;
  7. 选择合适网络结构;
  8. 设置损失函数和优化器;
  9. 训练模型;
  10. 观察训练曲线;
  11. 调整超参数;
  12. 分析错误样本;
  13. 保存最优模型;
  14. 部署模型;
  15. 持续监控模型效果。

其中,错误样本分析非常重要。
它可以帮助我们判断模型到底错在哪里。


五十、训练曲线的分析

训练过程中,通常需要观察训练集和验证集的损失曲线。

如果训练损失下降,验证损失也下降,说明模型正常学习。

如果训练损失下降,但验证损失上升,说明可能过拟合。

如果训练损失和验证损失都很高,说明模型可能欠拟合。

如果损失曲线剧烈震荡,可能是学习率过大。

因此,训练曲线是判断模型状态的重要依据。


五十一、模型部署与压缩

深度学习模型训练完成后,还需要考虑部署问题。

部署时常见挑战包括:

  1. 模型体积太大;
  2. 推理速度太慢;
  3. 设备算力有限;
  4. 显存或内存不足;
  5. 不同框架兼容问题;
  6. 线上数据分布变化。

常见优化方法包括:

  1. 模型剪枝;
  2. 模型量化;
  3. 知识蒸馏;
  4. ONNX 转换;
  5. TensorRT 加速;
  6. 使用轻量化模型。

例如,移动端部署时,可能更适合 MobileNet、ShuffleNet 等轻量模型。


五十二、可解释性问题

深度学习模型经常被认为是“黑箱”。

模型虽然能给出预测结果,但不一定容易解释为什么这样预测。

在一些高风险场景中,可解释性非常重要。
例如:

  1. 医疗诊断;
  2. 金融风控;
  3. 自动驾驶;
  4. 法律辅助;
  5. 安全监控。

常见可解释方法包括:

  1. Grad-CAM;
  2. LIME;
  3. SHAP;
  4. Attention 可视化;
  5. 特征重要性分析。

可解释性可以帮助研究者发现模型是否真的学到了合理特征。


五十三、深度学习的局限性

深度学习虽然强大,但并不是万能方法。

它存在以下局限:

  1. 需要大量数据;
  2. 训练成本较高;
  3. 模型解释性较弱;
  4. 对数据分布变化敏感;
  5. 容易受到对抗样本影响;
  6. 调参成本较高;
  7. 小数据场景下不一定优于传统方法。

因此,在实际应用中,不能盲目使用深度学习。

如果任务是结构化表格数据,并且样本量不大,随机森林、XGBoost、LightGBM 等传统机器学习模型可能更加合适。


五十四、不同任务的模型选择建议

任务类型 可选模型 说明
图像分类 CNN、ResNet、ViT 数据少时建议迁移学习
目标检测 YOLO、Faster R-CNN、Mask R-CNN 需要关注速度和精度
文本分类 BERT、TextCNN、Transformer 中文任务可使用中文预训练模型
时间序列预测 LSTM、GRU、Transformer 注意时间顺序划分
图结构任务 GCN、GAT、GraphSAGE 适合社交网络和知识图谱
回归预测 MLP、LSTM、GBDT 需根据数据类型选择
多模态任务 CLIP、跨模态 Transformer 适合图文结合任务

模型选择不能只看模型是否先进,而要结合数据规模、任务类型、计算资源和部署要求。


五十五、深度学习学习路线

结合本章内容,我认为学习深度学习可以按照以下顺序:

  1. Python 基础;
  2. NumPy 和 Pandas;
  3. 机器学习基础;
  4. 神经网络基本原理;
  5. PyTorch 张量和自动求导;
  6. MLP;
  7. CNN;
  8. RNN、LSTM、GRU;
  9. Transformer;
  10. GNN;
  11. 模型训练技巧;
  12. 项目实践;
  13. 模型部署与优化。

学习深度学习不能只看理论,也不能只跑代码。

比较好的方式是:

理解原理 + 阅读代码 + 跑通案例 + 修改实验 + 总结错误。


五十六、本章学习总结

通过本章学习,我认识到深度学习是一种以神经网络为基础的表示学习方法。

它最大的优势是能够从数据中自动提取特征,特别适合处理图像、文本、语音、视频和图结构等复杂数据。

PyTorch 为深度学习实践提供了方便的工具。
通过张量、自动求导、神经网络模块、损失函数和优化器,可以较为清晰地完成模型构建与训练。

不同神经网络结构适合不同任务:

  • MLP 适合基础向量数据;
  • CNN 适合图像和空间结构数据;
  • RNN、LSTM、GRU 适合序列数据;
  • Transformer 适合文本和长距离依赖任务;
  • GNN 适合图结构数据。

同时,深度学习实践并不只是搭建模型。
数据质量、损失函数、优化器、学习率、正则化、评估指标、过拟合控制和模型部署都非常重要。

本章给我的启发是:深度学习不是“越深越好”,也不是“模型越复杂越好”,而是要根据任务特点选择合适的方法。


五十七、个人理解

我认为,深度学习真正重要的地方不只是算法本身,而是它改变了我们处理数据的方式。

传统方法更依赖人工经验,需要人先设计特征,再交给模型学习。
深度学习则尝试让模型自己从数据中学习有效表示。

这种变化使得模型能够处理更加复杂的数据,例如图片、语音、文本和图结构。

但是,深度学习也不是万能的。

如果数据量不足、标签质量差、训练集和测试集分布不一致,那么再复杂的模型也可能得不到可靠结果。

因此,我认为深度学习项目中最重要的不是直接追求高准确率,而是建立完整的建模思维:

  1. 先理解任务;
  2. 再理解数据;
  3. 再选择模型;
  4. 再优化训练过程;
  5. 最后分析错误原因。

其中,错误分析非常关键。
它能帮助我们判断模型失败是因为数据问题、模型问题、参数问题,还是任务本身存在困难。

我的总结是:

深度学习的本质不是堆叠网络层数,而是通过数据、模型和优化方法共同学习有效表示。

只有理解这一点,才能真正把深度学习应用到实际问题中。


五十八、参考代码汇总

1. 创建张量

import torch

x = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)

print(x)

2. 自动求导

import torch

x = torch.tensor(2.0, requires_grad=True)

y = x ** 2 + 3 * x + 1

y.backward()

print(x.grad)

3. 简单 MLP 模型

import torch.nn as nn

class MLP(nn.Module):
    def __init__(self):
        super().__init__()

        self.model = nn.Sequential(
            nn.Linear(784, 256),
            nn.ReLU(),
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )

    def forward(self, x):
        x = x.view(x.size(0), -1)
        return self.model(x)

4. 简单 CNN 模型

import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self):
        super().__init__()

        self.features = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Conv2d(16, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )

        self.classifier = nn.Sequential(
            nn.Linear(32 * 7 * 7, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        return self.classifier(x)

5. LSTM 模型

import torch.nn as nn

class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()

        self.lstm = nn.LSTM(
            input_size=input_size,
            hidden_size=hidden_size,
            num_layers=2,
            batch_first=True
        )

        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        output, _ = self.lstm(x)

        last_output = output[:, -1, :]

        return self.fc(last_output)

6. 数据增强

from torchvision import transforms

transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(10),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

7. 加载预训练模型

import torchvision.models as models
import torch.nn as nn

model = models.resnet18(weights="DEFAULT")

num_features = model.fc.in_features

model.fc = nn.Linear(num_features, 5)

8. 定义损失函数

import torch.nn as nn

criterion = nn.CrossEntropyLoss()

9. 定义优化器

import torch.optim as optim

optimizer = optim.Adam(model.parameters(), lr=0.001)

10. 模型训练循环

for epoch in range(num_epochs):
    model.train()

    for x_batch, y_batch in train_loader:
        x_batch = x_batch.to(device)
        y_batch = y_batch.to(device)

        outputs = model(x_batch)

        loss = criterion(outputs, y_batch)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    print("Epoch:", epoch, "Loss:", loss.item())

11. 学习率调度

scheduler = torch.optim.lr_scheduler.StepLR(
    optimizer,
    step_size=10,
    gamma=0.1
)

for epoch in range(num_epochs):
    train_one_epoch()

    scheduler.step()

12. Early Stopping 示例

best_loss = float("inf")
patience = 5
counter = 0

for epoch in range(num_epochs):
    val_loss = evaluate(model, val_loader)

    if val_loss < best_loss:
        best_loss = val_loss
        counter = 0
        torch.save(model.state_dict(), "best_model.pth")
    else:
        counter += 1

    if counter >= patience:
        print("Early stopping")
        break

13. BERT 文本分类模型

from transformers import BertTokenizer, BertForSequenceClassification

tokenizer = BertTokenizer.from_pretrained("bert-base-chinese")

model = BertForSequenceClassification.from_pretrained(
    "bert-base-chinese",
    num_labels=2
)

14. BERT 文本编码

encoded = tokenizer(
    texts,
    padding=True,
    truncation=True,
    max_length=128,
    return_tensors="pt"
)

15. Gram 矩阵

import torch

def gram_matrix(feature):
    batch, channels, height, width = feature.size()

    feature = feature.view(batch * channels, height * width)

    gram = torch.mm(feature, feature.t())

    return gram / (batch * channels * height * width)

16. 模型保存

torch.save(model.state_dict(), "model.pth")

17. 模型加载

model.load_state_dict(torch.load("model.pth"))

model.eval()

五十九、结语

深度学习应用范围非常广,从图像分类、目标检测,到自然语言处理、时间序列预测和图神经网络,都可以看到深度学习的作用。

但在实际学习和使用中,不能只关注模型名称,也不能只追求复杂网络结构。
更重要的是理解数据特点、任务目标、训练过程和模型评估方法。

深度学习真正的价值,不只是提高预测准确率,而是为复杂数据提供了一种自动表示学习的方法。

这也是本章对我最大的启发。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐