鱼书-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
相关推荐
遥感知识服务27 分钟前
从局部阈值、双极化到暗地表剔除:NASA OPERA DSWx-S1全球动态水体算法拆解
大数据·人工智能·深度学习·神经网络·算法·机器学习
jeffsonfu1 小时前
循环神经网络(RNN)详解:处理序列数据的自然选择
人工智能·深度学习
Web3&Basketball3 小时前
vLLM部署开源大模型实战:显存、命令与成本核算
人工智能·深度学习·大模型·ai技术·vllm
lancyu3 小时前
关于多轮对话机器人的上下文Token优化和解决方案
人工智能·python·深度学习·机器学习·chatgpt·机器人·prompt
xier_ran3 小时前
【infra之路】GPU 执行与存储层次全景关系图
人工智能·深度学习·cuda
老郑聊AI业财智造4 小时前
Transformer 技术架构与源码分析
人工智能·python·深度学习·语言模型·架构·transformer·软件工程
147API8 小时前
蒸馏训练效果差,怎样判断问题是不是出在数据
人工智能·深度学习·机器学习
txg6669 小时前
可控扩散驱动模糊测试:CtrlFuzz 如何在“流形空间”中精准探索神经网络漏洞
人工智能·深度学习·神经网络
Yoyo Chen18011 小时前
DeepSeek发布多模态模型deepseek-v4-flash-vision-exp:视觉能力正式接入Agent工作流
人工智能·深度学习·microsoft
Rocky Ding*11 小时前
【三年面试五年模拟】2026-08-18_哔哩哔哩AI应用岗Agent开发一面面经全解析(含完整答案)
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·ai agent