鱼书-PH4-类的作用

《深度学习入门(基于 Python 的理论与实现)》中「类(class)」的核心作用

这本书大量用面向对象类封装神经网络、梯度计算、层结构、优化器,把零散函数打包成可复用、易维护、模块化的代码,是全书代码框架的根基。

一、通用层面:Python 类基础作用(书本前置知识点)

  1. 封装:把数据和绑定的方法打包在一起 变量(属性)+ 操作变量的函数(方法)放在同一个类里,不用全局变量乱传参数。 例:神经网络权重W、偏置b是属性;前向传播forward()、反向传播backward()是方法。

  2. 实例化:批量创建独立对象 一个类可以生成多个互不干扰的实例。 比如同一种 Affine 层,可以实例化第一层、第二层,各自保存自己的参数,不会互相覆盖。

  3. 代码复用,减少重复冗余 不用每次写全连接层、激活函数都复制粘贴 forward/backward 代码,定义一次类即可反复调用。

  4. 便于扩展与继承 可以基于基础层类派生出新层,比如给基础激活层新增带 dropout 的子类。

二、本书深度学习代码里类的具体用途(对应书中网络结构)

1. 封装网络层(最核心)

书中所有网络组件全部用类实现:

  • Affine(全连接层):保存权重W、偏置b,实现正向计算与反向求导更新参数
  • ReLUSigmoid:激活函数层,记录中间输入用于反向传播梯度回传
  • SoftmaxWithLoss:softmax 输出 + 交叉熵损失合为一类,同时计算损失与梯度

核心逻辑:每一层只需要实现两个固定接口

python

运行

python 复制代码
forward(x)  # 前向传播,输出下一层输入
backward(dout)  # 接收上游梯度,返回本层梯度、更新参数

类把层内状态(缓存输入、参数) 保存下来,反向传播时直接取用,不用手动存中间变量。

2. 搭建整体神经网络模型

TwoLayerNet(二层神经网络)是典型类:

  • 属性:各层实例、权重参数、超参(学习率、权重衰减系数)
  • 方法:
    • predict():推理预测
    • loss():计算损失值
    • gradient():数值梯度 / 解析梯度
    • update():参数迭代更新

整个网络被封装成一个对象,外部只需调用少量方法就能完成训练,结构清晰。

3. 封装优化器(梯度下降更新策略)

书中 SGD、Momentum、AdaGrad、Adam 全部写成类:

  • 保存优化器自身状态(比如动量累积量、历史梯度平方和)
  • 统一update(params, grads)方法,一键更新网络所有参数 后续更换优化器只需要换一个类实例,主体训练代码完全不用改动。

4. 管理训练过程与参数状态

  • 层在反向传播时需要缓存xW等中间数据,类的实例属性天然用来存储临时变量;
  • 训练时参数不断迭代,每个层实例独占自己的W/b,多网络并行训练不会参数混淆。

三、对比不用类(纯函数写法)的缺点

  1. 所有权重、中间结果要用字典 / 列表手动传递,参数极易混乱;
  2. 前向、反向代码高度重复,新增网络结构要大量复制代码;
  3. 无法单独复用某一层,代码耦合度极高;
  4. 可读性极差,很难区分哪段代码属于网络哪一部分。

四、极简总结(应试 / 笔记版)

  1. 封装:将网络层参数、中间数据、前向 / 反向运算方法绑定为整体;
  2. 模块化:拆分全连接、激活、损失、优化器等独立模块;
  3. 复用性:单类多次实例化,快速搭建多层神经网络;
  4. 规范化:统一 forward/backward 接口,构建链式反向传播计算图;
  5. 易维护扩展:新增网络结构、优化算法只需新增类,不改动原有代码

类定义与 __init__ 构造函数逐行注释

python 复制代码
# 定义Affine全连接层类
class Affine:
    # 构造方法:创建实例时自动执行,初始化层所有属性
    # W:权重矩阵  b:偏置向量,由上层网络传入
    def __init__(self, W, b):
        # 实例属性1:保存本层权重W
        self.W = W
        # 实例属性2:保存本层偏置b
        self.b = b
        
        # 实例属性3:缓存正向传播的输入x,反向求导必须用到
        self.x = None
        # 实例属性4:记录输入原始形状,兼容卷积后多维输入(图片四维数据)
        self.original_x_shape = None
        
        # 实例属性5:权重W的梯度,后续梯度下降更新W使用
        self.dW = None
        # 实例属性6:偏置b的梯度,后续梯度下降更新b使用
        self.db = None

forward 前向传播逐行拆解

python 复制代码
# 前向传播方法:接收输入x,输出本层计算结果out
def forward(self, x):
    # 步骤1:记录输入x最开始的形状(比如卷积输出是(N,C,H,W)四维)
    self.original_x_shape = x.shape
    # 步骤2:将除第一维(批量维度N)外所有维度展平,变成二维矩阵 (N, 特征总数)
    # -1 代表自动计算列数,把单张图片多维数据拉成一维向量
    x = x.reshape(x.shape[0], -1)
    # 步骤3:把展平后的x存入实例变量,反向传播要用
    self.x = x
    # 步骤4:核心仿射运算 X·W + b
    # np.dot矩阵乘法:(N,in) × (in,out) = (N,out),再加偏置b
    out = np.dot(self.x, self.W) + self.b
    # 返回输出给下一层(激活函数/下一个Affine层)
    return out

backward 反向传播逐行拆解(梯度回传核心)

python 复制代码
# 反向传播:dout是上一层传回来的输出梯度 dL/dout
def backward(self, dout):
    # 公式推导:dx = dout · W^T
    # dout(N, out) × W.T(out, in) → dx(N, in)
    dx = np.dot(dout, self.W.T)
    # dW = X^T · dout  权重梯度,本层核心待更新梯度
    self.dW = np.dot(self.x.T, dout)
    # db:偏置梯度,按batch维度求和,axis=0压缩批量维度
    # dout形状(N,out),sum后得到(1,out)即偏置梯度
    self.db = np.sum(dout, axis=0)
    # 把展平后的dx恢复成最开始输入x的原始四维/三维形状
    dx = dx.reshape(*self.original_x_shape)
    # 将dx(dL/dx)传回上一层,继续反向链式求导
    return dx
相关推荐
EQUINOX14 小时前
【论文阅读】| MoCo精读
论文阅读·人工智能·python·深度学习·机器学习
程序喵大人5 小时前
【AI专栏】图解Transformer - 第05章:LLM 推理工程
人工智能·深度学习·llm·transformer
Day(AKA Elin)7 小时前
【Day】MTP(Multi Token Prediction)技术学习
python·深度学习·学习·llama
卡梅德生物科技小能手8 小时前
卡美德生物科普IL25:2型免疫反应的核心调控靶点
经验分享·深度学习·生活
AI人工智能+9 小时前
护照OCR识别技术,依托深度神经网络模型,实现了从像素到语义的端到端智能解析
深度学习·计算机视觉·自然语言处理·ocr·护照ocr识别
手写码匠13 小时前
注意力机制全家桶:从 Multi-Head 到 GQA 再到 Flash Attention 的手写实现
人工智能·深度学习·算法·aigc
大鱼>13 小时前
模型公平性与偏差检测:AI伦理实战指南
人工智能·深度学习·算法·机器学习
大鱼>14 小时前
AI+资产监控:农业设施智能监控系统
人工智能·深度学习·算法·机器学习
qq_263_tohua15 小时前
第110期 FCN 语义分割学习
深度学习·学习