一、PyTorch操作

1.1前向传播

  1. 定义:神经网络模型接收输入张量(Tensor),严格按照模型定义的网络层结构、运算逻辑,从输入层到输出层逐层执行正向计算(线性变换、激活函数、卷积等),最终生成预测输出张量的过程。
    通俗一点就是说,按顺序(从输入层到输出层)计算和存储神经网络中每层的结果。在这个过程中,输入数据通过网络中的权重和偏置进行线性变换,然后通过激活函数进行非线性变换,得到每一层的输出。最终,输出层的输出即为神经网络的预测值。
  2. 核心特性
  • 纯计算过程:仅执行数值运算,不更新模型参数;
  • 固定数据流:方向固定为「输入 → 隐藏层 → 输出」;
  • 核心载体:通过继承nn.Module的forward()方法定义计算规则;
  • 双重作用:
    推理阶段:直接输出预测结果;
    训练阶段:生成预测值,为反向传播计算误差提供依据。
  1. 大体流程
  • 第一层是输入层,接受外部数据
  • 数据传入隐藏层,每个神经元都会接受上一个神经元的输入,并计算加权和(加权和通过激活函数进行非线性变换,生成该神经元的输出。)
  • 最后一层是输出层,接收来自隐藏层的输入,并计算最终输出。
  1. 代码示例
import torch.nn as nn
# 导入神经网络模块nn(所有网络层和Module基类都来自这里)
 
class NeuralNetwork(nn.Module):
#定义网络类,继承nn.Module
    def __init__(self):"""搭建网络层"""
    #注意:__init__ 里只定义层的结构,不执行计算,计算全在 forward 里。
        super(NeuralNetwork, self).__init__() #调用父类初始化方法,保证模型功能正常
        self.flatten = nn.Flatten() # 展平层,把二维的图片(28×28)展成一维向量(784=28×28),以便后面的全连接层处理
        self.hidden1 = nn.Linear(784, 128)  #全连接层
        self.hidden2 = nn.Linear(128, 64)   
        self.out = nn.Linear(64, 10)  
        """hidden1:输入 784 维 → 输出 128 维(对应 W^(1));
        hidden2:输入 128 维 → 输出 64 维(第二个隐藏层权重);
        out:输入 64 维 → 输出 10 维(对应 W^(2),10 分类任务的输出);"""
 
    def forward(self, x):
        x = self.flatten(x)
        #展平输入,把二维的图片(28×28)展成一维向量(784=28×28)
        x = self.hidden1(x)   
        #第一次线性变换,对输入的特征进行线性投影   
        x = torch.relu(x)       
        #ReLU激活,引入非线性计算,让网络可以拟合复杂规律
        x = self.hidden2(x)
        #第二次线性变换,进一步提取特征
        x = torch.sigmoid(x)
        #Sigmoid激活,第二次引入非线性计算
        x = self.out(x)      
        #输出层线性变换,得到最终预测输出    
        return x


1.2反向传播与梯度

1.2.1 梯度
  1. 概念
    梯度是标量损失函数 J(θ)J(\theta)J(θ) 关于模型可学习参数 θ\thetaθ(权重矩阵W\boldsymbol{W}W、偏置向量b\boldsymbol{b}b)的一阶偏导数构成的向量,数学表达式为:

∇J(θ)=(∂J∂θ1,∂J∂θ2,…,∂J∂θn)T \nabla J(\theta) = \left( \frac{\partial J}{\partial \theta_1}, \frac{\partial J}{\partial \theta_2}, \dots, \frac{\partial J}{\partial \theta_n} \right)^T J(θ)=(θ1J,θ2J,,θnJ)T

它表征了损失函数在参数空间中变化速率最快的方向与幅值。
通俗来说,梯度设定会影响参数的变化,进而影响误差变化的速率 ,梯度是模型修改参数的唯一依据,告诉整个网络权重怎么调整可以让误差达到最小

1.2.2反向传播(计算梯度)
  1. 概念
    基于链式求导法则,将误差从输出层反向传递到每一层网络,自动计算所有参数的梯度。
    2.代码示例
model = NeuralNetwork()
#创建模型
loss_fn = nn.CrossEntropyLoss()
#初始化损失函数,计算真实标签和预测值之间的误差
optimizer = optim.SGD(model.parameters(), lr=0.01)
#model.parameters():获取模型里所有可学习的权重和偏置;
#lr=0.01:学习率,控制参数更新的步长;
#根据反向传播算出的梯度,自动更新模型参数

x = torch.randn(1, 1, 28, 28)
#模拟手写数字识别的输入数据,对应 MNIST 数据集的单张图片格式。
y = torch.tensor([5])
#输入图片的标准答案,代表这张图片的真实数字是 5,用于和预测值对比计算误差。

for i in range(3):
#让模型进行 3 次完整的学习循环,每循环一次,模型就更新一次参数,预测更准确。
    print(f"=== 第{i+1}次训练 ===")
    
    pred = model(x)
    #前向传播,调用模型自动执行forward()方法,输入图片数据,输出 10 维的预测值。
    loss = loss_fn(pred, y)
    #用损失函数计算预测误差,误差越大说明模型约不准确
    print(f"预测误差:{loss.item():.4f}")
    
    optimizer.zero_grad()
    #清空上一轮训练的梯度:PyTorch 中梯度会自动累加,必须清空上一轮训练的梯度,否则会导致计算错误。
    loss.backward()
    #核心反向传播,基于链式法则,从损失值出发,自动计算所有权重的梯度,并储存在参数中。
    optimizer.step()
    #优化器读取梯度,按照SGD算法更新模型的权重和偏置,模型完成一次学习。
    """SGD随机梯度下降:根据梯度自动修改权重w和偏置b
    新权重 = 旧权重 - 学习率 × 梯度"""
    
1.2.3优化器
  1. 概念
    实现参数更新算法的工具。
    通俗一点,就是一个自动修改权重和偏置的工具(上文代码的SGD)
  2. 底层逻辑
  • 反向传播计算出参数梯度
  • 优化器根据梯度+自身算法,计算更新量
  • 用更新量修改权重再进行下一轮学习
1.2.4归一化
  1. 定义
    归一化是对数据 / 网络特征值进行尺度缩放,把不同大小、不同单位的数值,映射到统一的标准范围内(如 [0,1]、[-1,1]、均值 0 方差 1),消除数值量级差异对模型训练的破坏。(规整数据或特征
  2. 作用
  • 加速模型收敛
  • 训练更稳定,避免过大数据或过小数据导致梯度爆炸或消失
  • 消除量纲影响
  1. 两种不同的归一化
  • 带批归一化 BatchNorm(最主流)
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten() #二维展平成784维向量
        self.hidden1 = nn.Linear(784, 128)
        self.bn1 = nn.BatchNorm1d(128)  # 归一化隐藏层特征
        #第一层隐藏层:BatchNorm1d(128):对 128 维特征做批归一化→ 让数值稳定在标准范围,训练更快、更稳
        self.hidden2 = nn.Linear(128, 64)
        self.bn2 = nn.BatchNorm1d(64)
        #第二层,保证稳定
        self.out = nn.Linear(64, 10)

    def forward(self, x):#前向传播
        x = self.flatten(x) #展平
        x = self.hidden1(x)
        x = self.bn1(x) 
         # 线性层后 → 归一化 → 激活
         
        x = torch.relu(x)
        #引入非线性,使用ReLU激活函数
        x = self.hidden2(x)
        x = self.bn2(x)
        x = torch.sigmoid(x)
        x = self.out(x)
        return x
        
  • 输入数据归一化
x = torch.randn(1, 1, 28, 28)
"""生成一个模拟手写数字图片的随机张量,用来代替真实的 MNIST 数据集图片。
一次输入一张图,灰度图片只有一个通道,高度和宽度均为28像素"""
x = x / 255.0  # 图片像素归一化(0-255 → 0-1)
#输入数据归一化,所有像素值除以255,范围变为0~1
  1. 为什么?
  • 范围缩小后可以让优化器更快找到最优权重
  • 稳定训练
1.2.5 正则化
  1. 定义
    正则化是给损失函数加惩罚项,限制模型权重的大小,降低模型复杂度,解决过拟合(模型死记训练数据,测试数据一塌糊涂)。
  2. 作用
  • 防止过拟合,避免噪声干扰
  • 提升泛化能力,在新数据上也能精确
  • 避免权重过大导致模型过于敏感
  1. 两种正则化
  • L2正则化,权重衰减
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=1e-4)
"""定义优化器:使用 SGD 优化器 + 学习率 0.01 + L2 正则化(权重衰减)
optim:PyTorch 的优化器库
SGD:随机梯度下降算法,用SGD算法更新权重和参数
model.parameters():获取所有可学习的参数
lr=0.01:步长"""
#weight_decay = 权重衰减 (0.0001)防止过拟合
  • Dropout正则化(直接让某些神经元休眠)
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.hidden1 = nn.Linear(784, 128)
        self.dropout1 = nn.Dropout(0.2) 
         # 20%神经元休眠
        self.hidden2 = nn.Linear(128, 64)
        self.dropout2 = nn.Dropout(0.2)
        self.out = nn.Linear(64, 10)

二、CNN框架

2.1 卷积计算

  1. 用一个小矩阵(卷积核/滤波器),在大矩阵上滑动相乘再相加,提取特征
  2. 一些概念
  • 卷积核大小
  • 步幅,步幅越大结果越小
  • 填充,让卷积前后尺寸不变

2.1 ResNet(解决网络越深效果越差)

  1. 加入跳连接
    输入 → 层1 → 层2 → 相加 → 输出
    ↑ ↓
    └──────────────── ──┘
    叫做 Residual Block 残差块
import torch
import torch.nn as nn

# 定义 最简单的残差块
class SimpleResidualBlock(nn.Module):
    def __init__(self, channels):
        super().__init__()
        # 残差块里的 2 层卷积(CNN核心)
        self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.relu = nn.ReLU()  # 激活函数

    # 前向计算(关键!跳连就在这里)
    def forward(self, x):
        # 第一步:x 经过两层卷积
        out = self.relu(self.conv1(x))
        out = self.conv2(out)
        
        # 🔥 核心:跳连接!直接把 原始x + 卷积结果out
        out = out + x  
        
        # 最后激活
        out = self.relu(out)
        return out

三、Transformer

3.1 整体Transformer架构

  1. 基于自注意力机制的序列建模架构,彻底替代了传统 RNN/CNN,是现在大语言模型、视觉模型的核心基石。
  2. 核心结构
  • 编码器:输入序列编码为带全局上下文的特征向量
  • 解码器:生成目标序列
  • 位置编码:给序列增添位置信息
  • 自注意力:计算序列中每个元素与所有元素的关联权重,实现全局依赖建模

3.2 图像Transformer(ViT/Swin Transformer)

3.2.1 ViT(把图像当成序列处理)
  1. 流程
  • 图像分块,图像分割成小块,每个小块再展成一维向量,再线性投影为固定维度的Token
  • 添加位置编码+分类Token
  • 输入到Transformer编码器,建立起所有小块之间的全局关系
  • 分类后输出
  1. 一些缺陷
  • 计算复杂度随图像尺寸爆炸式增长
  • 依赖大规模预训练,在小数据集上表现不好
  • 适合图像分类,不适合目标检测这种密集预测任务
3.2.2 Swin Transformer
  1. Swin Transformer 是 ViT 的改进版,解决了 ViT 计算效率低、不适合高分辨率的问题,是现在视觉任务的通用 backbone。
  2. 核心创新
  • 窗口自注意力:把图像分为固定大小的局部小窗口,只在窗口内做自注意力,计算复杂度随图像尺寸线性增长,高分辨率下内存占用更少
  • 移位窗口:交叉使用常规和偏移窗口,弥补窗口自注意力的局限
  • 生成多尺度特征
3.2.3 DETR
  1. DETR(DEtection TRansformer)是首个将 Transformer 用于目标检测的端到端模型,彻底颠覆了传统 CNN 检测范式。
  2. 核心架构:
  • CNN主干网:提取图像2D特征图
  • 编码器:特征展平为序列,加位置编码,用自注意力机制建立全局关系
  • 解码器:一组可学习的对象查询,从编码器中提取目标信息
  • 检测头:直接预测每个查询对应的目标类别

四、半监督

4.1 强增强与弱增强

  1. 弱增强:只做自然轻微的改动,如左右上下翻转,随机小范围裁剪,进行标准化、归一化操作或是轻微模糊处理,图像基本不变,用来生成可靠的伪标签
  2. 强增强:大幅度的改,如大角度的旋转、更改颜色或亮度、强模糊等操作,虽然物体类别没有变化,但是图片对模型来说会有很大噪声干扰,让模型学习语义特征而非颜色等简单特征
import torch
import torchvision.transforms as transforms
from PIL import Image
import numpy as np


# 通用配置(图片尺寸、标准化)
IMAGE_SIZE = 224  # 通用图片大小
NORMALIZE = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
# 图像标准化(所有CNN/Transformer都用这个)

# 1. 弱增强(Weak Augmentation)
weak_aug = transforms.Compose([
    transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),
    transforms.RandomHorizontalFlip(p=0.5),  # 随机左右翻转(50%概率)
    transforms.RandomCrop(IMAGE_SIZE, padding=4),  # 小范围随机裁剪
    transforms.ToTensor(),
    NORMALIZE
])


# 2. 强增强(Strong Augmentation)
strong_aug = transforms.Compose([
    transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),
    # RandAugment:随机组合14种增强(旋转、颜色、扭曲、锐化...)
    transforms.RandAugment(num_ops=3, magnitude=10),  # 3种操作,强度10(最大)
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.RandomCrop(IMAGE_SIZE, padding=4),
    transforms.ToTensor(),
    # CutOut:随机挖掉一块(强增强标配)
    transforms.RandomErasing(p=1.0, scale=(0.1, 0.3)),
    NORMALIZE
])

4.2 检测架构细分

4.2.1 双阶段检测器
  1. 流程
  • 区域提议:先找出可能存在物体的很多个候选框
  • 分类回归:判断每一个候选框的物体,并调整位置
  1. 代表性算法: Faster R-CNN(最经典) R-FCN、Mask R-CNN
  2. 优缺点:
  • 精确度高,但是速度较慢
  • 小物体以及复杂场景表现好,但是结构复杂
fasterrcnn_resnet50_fpn()
#先生成候选框,再分类回归
4.2.2 单阶段检测器
  1. 流程:
  • 直接在特征图上进行预测
  1. 代表性算法:YOLO (v1~v8) SSD RetinaNet
  2. 优缺点:
  • 速度快,结构简单,适合实时监测
  • 精度稍低,对小物体检测较弱
retinanet_resnet50_fpn()

4.3 损失函数

4.3.1 分类损失
  1. 如果模型认错类别,就惩罚
  2. 交叉熵损失:衡量模型预测与真实答案差多少
cls_loss = nn.CrossEntropyLoss()
#内部集成**Softmax归一化 + 交叉熵计算**
4.3.2 定位损失
  1. 如果定位框不准,就会惩罚
box_loss = nn.SmoothL1Loss()
4.3.3 匈牙利损失,DTER专用
  1. 因为DTER摒弃了锚框、候选框等直接预测固定数量的目标集合,要通过匈牙利算法完成集合匹配
  2. 构建代价矩阵
    定义预测框与真实框之间的匹配代价,由分类代价+定位代价组成:

Ci,j=−Pi(j)+Lbox(bi,b^j) \mathcal{C}_{i,j} = -\mathcal{P}_i(j) + \mathcal{L}_{box}(b_i, \hat{b}_j) Ci,j=Pi(j)+Lbox(bi,b^j)

  • Pi(j)\mathcal{P}_i(j)Pi(j):第iii个预测框对第jjj个真实框的分类概率
  • Lbox\mathcal{L}_{box}Lbox:边界框定位损失(SmoothL1/GIoU),位置误差

  1. 匈牙利最优匹配
    利用匈牙利算法求解代价矩阵,得到唯一、最小总代价的一对一匹配关系,保证每个真实框仅匹配一个预测框,每个预测框仅匹配一个真实框。

  2. 计算最终损失
    仅对匹配成功的预测-真实对计算损失,未匹配的预测框判定为背景,无监督损失。

  3. 数学表达
    LHungarian=1Ngt∑(i,j)∈M[Lcls(pi,cj)+λ⋅Lbox(bi,b^j)] \mathcal{L}_{Hungarian} = \frac{1}{N_{gt}} \sum_{(i,j) \in \mathcal{M}} \left[ \mathcal{L}_{cls}(p_i, c_j) + \lambda \cdot \mathcal{L}_{box}(b_i, \hat{b}_j) \right] LHungarian=Ngt1(i,j)M[Lcls(pi,cj)+λLbox(bi,b^j)]

  • M\mathcal{M}M:匈牙利算法得到的最优匹配集合
  • NgtN_{gt}Ngt:真实目标数量
  • λ\lambdaλ:定位损失权重系数
  • Lcls\mathcal{L}_{cls}Lcls:交叉熵分类损失
  • Lbox\mathcal{L}_{box}Lbox:SmoothL1 定位损失

4.4 评价指标

  1. (以 IoU 阈值 0.5 为例)
  • TP (True Positive):真阳性,预测正确的目标,预测框与真实框 IoU ≥ 0.5,且类别预测正确
  • FP (False Positive) 假阳性 误检 / 虚警 预测框与真实框 IoU < 0.5,或类别预测错误,或重复检测
  • FN (False Negative) 假阴性 漏检 真实框没有被任何预测框匹配到(没检测出来)
  1. Precision / Recall(精确率 / 召回率)
  • 精确率 (Precision)
    公式:
    Precision=TPTP+FP \text{Precision} = \frac{TP}{TP + FP} Precision=TP+FPTP

  • 通俗解释:模型预测的所有目标中,真正是目标的比例

  • 核心意义:衡量模型「不瞎检」的能力,值越高,误检越少

  • 例子:模型预测了 10 个框,其中 8 个是真目标 → Precision=80%\text{Precision}=80\%Precision=80%


  • 召回率 (Recall)
    公式:
    Recall=TPTP+FN \text{Recall} = \frac{TP}{TP + FN} Recall=TP+FNTP

  • 通俗解释:图里所有真实目标中,被模型检测出来的比例

  • 核心意义:衡量模型「不漏检」的能力,值越高,漏检越少

  • 例子:图里有 10 个真实目标,模型检测出 8 个 → Recall=80%\text{Recall}=80\%Recall=80%

  1. AP /mAP(平均精度 / 均值平均精度)
  • AP@0.5 (Average Precision @ IoU=0.5)在 IoU 阈值为 0.5 时,Precision-Recall 曲线下的面积
  • AP@0.5:0.95 在 IoU 阈值从 0.5 到 0.95(步长 0.05)的 10 个阈值下,AP 的平均值,比AP更严格,要求模型检测到且检测的准
  • mAP:所有类别 AP 的平均值,模型在所有类别上的平均检测性能,最核心综合指标
  1. AR:模型召回目标的能力,与AP对应,就是模型能把多少真实目标检测出来的能力
  2. FPS:每秒处理的图片帧数,直接决定模型能否应用于实时场景
  3. IoU 是预测框与真实框的交并比,阈值越高,要求框得越准

4.5 经典半监督方法

4.5.1伪标签
  1. 基础伪标签:模型对无标签图像生成高置信度的预测标签,将其作为人工标注的真实标签使用,把无标签数据转化为有监督数据参与训练。(自我迭代学习)
  2. 高置信度筛选
  • 设定固定置信度阈值 ,仅保留置信度大于 阈值 的伪标签,过滤低质量、噪声标签。
  • 可以大幅度降低伪标签噪声,保证伪标签的准确性
  1. 动态阈值,根据模型训练情况及难度自动调整阈值
  • 初期:阈值较高,训练出准确的伪标签
  • 后期:阈值降低,使用更多伪标签训练
  • 较难类:阈值较高
  • 可以平衡伪标签数量与质量
  1. 框过滤策略:对预测框进行多维度过滤,仅保留高质量框作为伪标签。
  • 置信度过滤:框得分 > 阈值
  • IoU 过滤:去除重复框(NMS)
  • 尺寸过滤:去除过小 / 过大无效框
  • 位置过滤:去除边界不合理框
  • 类别一致性过滤:类别预测稳定
4.5.2 一致性正则化
  1. 一致性正则化:对同一张无标签图像施加不同的语义不变扰动(数据增强、噪声、Dropout),约束模型的输出预测保持一致,利用数据的不变性正则化模型训练。
  • 计算一致性损失,强制让强增强和弱增强的预测输出约相等
  • 注意:扰动必须是语义不变的(强弱增强、高斯噪声等)

4.6 EMA操作

  1. 定义:指数移动平均,对模型权重进行滑动平均更新,生成一组更平滑、泛化性更强的影子权重,用于推理和伪标签生成。
  2. θema=τ⋅θema+(1−τ)⋅θmodel \theta_{\text{ema}} = \tau \cdot \theta_{\text{ema}} + (1 - \tau) \cdot \theta_{\text{model}} θema=τθema+(1τ)θmodel
  • θema\theta_{\text{ema}}θema:EMA 平滑权重
  • θmodel\theta_{\text{model}}θmodel:当前模型权重
  • τ\tauτ:衰减率(通常 0.999 / 0.995 / 0.99)
  1. 作用:
  • 提升模型稳定性
  • 生成高质量伪标签
  • 减少噪声,提高半监督训练效果
Logo

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

更多推荐