• 2025年8月29日 星期五

3.10训练参数设置

8 月 27, 2025

三个训练神经网络的建议

(1)一般情况下,在训练集上的目标函数的平均值(cost)会随着训练的深入而不断减小,如果这个指标有增大情况,停下来。
有两种情况:

  • 采用的模型不够复杂,以致于不能在训练集上完全拟合;
  • 已经训练很好了。

(2)分出一些验证集Validation Set,训练本质目标是在验证集上获取最大识别率。因此训练一段时间后,必须在验证集上测试识别率,保存使验证集上识别率最大的模型参数作为最后的结果。

(3)注意调整学习率Learning Rate,如果刚训练几步损失函数就增加,一般来说是学习率太高;反之如果每次cost变化很小,说明学习率太低。


一点人生的经验:

(1)目标函数可以加入正则项

Minimize E(ω,b)=L(ω,b)+λ/2 ||ω||2

L(ω,b)为原来的目标函数,λ/2 ||ω||2为正则项。λ为权值衰减系数

参考前向传播nn_forward.m

if strcmp(nn.objective_function,'MSE')
            nn.cost(s) = 0.5 / m * sum(sum((nn.a{k} - batch_y).^2)) + 0.5 * nn.weight_decay * cost2;
        elseif strcmp(nn.objective_function,'Cross Entropy')
            nn.cost(s) = -0.5*sum(sum(batch_y.*log(nn.a{k})))/m + 0.5 * nn.weight_decay * cost2;

后向传播nn_backpropagation.m

nn.W_grad{nn.depth-1} = nn.theta{nn.depth}*nn.a{nn.depth-1}'/m + nn.weight_decay*nn.W{nn.depth-1};
nn.b_grad{nn.depth-1} = sum(nn.theta{nn.depth},2)/m;

(2)训练数据归一化

newX=[X-mean(X)]/ std(X)

(3)参数ω和b的初始化

一种比较简单有效的方法:

(ω,b)初始化从区间(-1/sqrt(d),1/sqrt(d))均匀随机取值,其中d为(ω,b)所在层的神经元个数。

可以证明如果X服从均值0方差1的正态分布,且各个维度无关,而(ω,b)是区间(-1/sqrt(d),1/sqrt(d))的均匀分布,则ωTX+b是均值0,方差为1/3的正态分布

nn_create.m

nn.W{k} = 2*rand(height, width)/sqrt(width)-1/sqrt(width);%rand产生伪随机数矩阵,即W权重矩阵初始化
nn.b{k} = 2*rand(height, 1)/sqrt(width)-1/sqrt(width);%b阈值的初始化

避免一开始梯度趋近于0的现象。

(4)BATCH NORMALIZATION

论文:Batch normalization accelerating deep network training by reducing internal covariate shift(2015)

在这可以看:


基本思想:既然我们希望每一层获得的值都在0附近,从而避免梯度消失现象,那么我们为什么不直接把每一层的值做基于均值和方差的归一化呢?

(5)参数的更新策略

ADAGRAD的方法

if strcmp(nn.optimization_method,'AdaGrad')
nn.rW{k}= nn.rW{k}+nn.W_grad{k}.^2;nn.rb{k}= nn.rb{k}+nn.b_grad{k}.^2;
nn.W{k}=nn.W{k}-nn.learning_rate*nn.W_grad{k}./(sqrt(nn.rW{k})+0.001);
nn.b{k}=nn.b{k}-nn.learning_rate*nn.b_qrad{k}./(sqrt(nn.rb{k})+0.001);

解决梯度随机性的问题:引入Momentum

同时结合:Adam-解决梯度绝对值分量不平衡和梯度方向随机性的问题,也引入了逐渐降低梯度搜索步长的机制。

📝 算法步骤解释

  1. Require
    • Step size (ϵ,学习率),推荐默认值 0.001。
    • Exponential decay rates (ρ1,ρ2​):分别控制一阶、二阶动量的衰减速率。推荐默认值 ρ1=0.9,ρ2=0.999。
    • Small constant δ:数值稳定常数,防止分母为零,默认 10−8
    • Initial parameters θ:模型初始参数。

  1. Initialize
    • 一阶动量变量 s=0(存放梯度的指数加权平均,类似 Momentum)。
    • 二阶动量变量 r=0(存放梯度平方的指数加权平均,类似 RMSProp)。
    • 时间步 t=0。
  2. 循环过程 (直到满足停止条件,例如迭代次数用完或收敛)
    • Step A. 采样一个 minibatch
      • 从训练集取出一个小批量样本 {x(1),…,x(m)} 和对应标签。
    • Step B. 计算梯度
g=1mθi=1mL(f(x(i);θ),y(i))

即小批量平均梯度。

Step C. 时间步递增

t←t+1

Step D. 更新一阶动量(偏置的)

s←ρ1s+(1−ρ1)g

——这是梯度的指数滑动平均(类似 Momentum)。

Step E. 更新二阶动量(偏置的)

r←ρ2r+(1−ρ2)(g⊙g)

——这里 ⊙表示逐元素乘法。即对梯度平方取指数滑动平均(类似 RMSProp)。

Step F. 偏差修正
由于初始化 s=0,r=0,前期会有向零偏移,需要修正:

s^=s1ρ1t,r^=r1ρ2t

Step G. 计算更新量

Δθ=ϵs^r^+δ

Step H. 更新参数

θ←θ+Δθ


🔑 总结

  • sss:梯度的一阶动量(方向 + 平滑)。
  • rrr:梯度的二阶动量(幅度 + 自适应缩放)。
  • 偏差修正:解决初期 (s,r≈0)的估计偏差问题。
  • 更新公式:学习率会根据梯度历史动态调整,每个参数有自己独立的学习率。

Adam 的更新可以理解为:
👉 用 Momentum 决定方向,再 用 RMSProp 决定步长大小

Python代码示例(一阶动量用 s,二阶动量用 r,含偏差修正;并给了一个最小化二次函数的小示例):

import numpy as np

class Adam:
    """
    Adam 优化器(Algorithm 8.7)
    s: 一阶动量(biased)
    r: 二阶动量(biased)
    """
    def __init__(self, shape, lr=1e-3, rho1=0.9, rho2=0.999, eps=1e-8):
        self.lr   = lr        # ε (step size)
        self.rho1 = rho1      # ρ1
        self.rho2 = rho2      # ρ2
        self.eps  = eps       # δ
        self.s    = np.zeros(shape)  # 初始化一阶动量 s=0
        self.r    = np.zeros(shape)  # 初始化二阶动量 r=0
        self.t    = 0                  # 初始化时间步 t=0

    def step(self, theta, g):
        """
        单次更新:
        theta: 参数
        g:     当前梯度(对 minibatch 的平均梯度)
        return: 更新后的参数
        """
        # t ← t + 1
        self.t += 1

        # Update biased first moment estimate: s ← ρ1 s + (1-ρ1) g
        self.s = self.rho1 * self.s + (1.0 - self.rho1) * g

        # Update biased second moment estimate: r ← ρ2 r + (1-ρ2) (g ⊙ g)
        self.r = self.rho2 * self.r + (1.0 - self.rho2) * (g * g)

        # Correct bias:
        # ŝ = s / (1 - ρ1^t),   r̂ = r / (1 - ρ2^t)
        s_hat = self.s / (1.0 - self.rho1 ** self.t)
        r_hat = self.r / (1.0 - self.rho2 ** self.t)

        # Compute update: Δθ = -ε * ŝ / (sqrt(r̂) + δ)
        delta_theta = - self.lr * s_hat / (np.sqrt(r_hat) + self.eps)

        # Apply update: θ ← θ + Δθ
        theta = theta + delta_theta
        return theta

# ================= 示例:最小化 f(θ)=∑ θ_i^2 =================
# 真梯度:∇f(θ)=2θ
np.random.seed(0)
theta = np.random.randn(3) * 5.0        # 初始参数
opt   = Adam(shape=theta.shape, lr=1e-2) # 用默认 ρ1=0.9, ρ2=0.999, δ=1e-8

for k in range(1, 501):
    g = 2.0 * theta                      # 计算梯度 (小批量平均梯度在真实任务里替换这里)
    theta = opt.step(theta, g)           # 按图中流程更新
    if k % 100 == 0:
        fval = (theta**2).sum()
        print(f"iter {k:3d}  f(theta)={fval:.6f}  theta={theta}")

# 输出会看到 f(θ) 单调下降,θ 收敛到 0 附近

输出:

iter 100  f(theta)=78.124320  theta=[7.84011204 1.09919008 3.93048901]
iter 200  f(theta)=57.552498  theta=[6.91704488 0.49699096 3.07570938]
iter 300  f(theta)=42.152403  theta=[6.0541767  0.17936161 2.33819949]
iter 400  f(theta)=30.556370  theta=[5.25288565 0.05091135 1.72074696]
iter 500  f(theta)=21.872385  theta=[4.51437396 0.01130478 1.22175496]

📊 结果逐行解释

输出是每 100 次迭代打印一次:

Iter 100

f(theta)=78.124320  
theta=[7.84011204 1.09919008 3.93048901]
  • 初始 θ 很大(一开始是 np.random.randn(3)*5 随机出来的)。
  • 经过 100 步更新后,参数值比初始小了一些,但还比较大。目标函数 f(θ) 还在 78 左右。

Iter 200

f(theta)=57.552498  
theta=[6.91704488 0.49699096 3.07570938]
  • θ 的数值进一步下降了(尤其是第二个分量从 ~1.1 → 0.49)。
  • 函数值 f(θ) 从 78 降到了 57,说明 Adam 在往 0 的方向走。

Iter 300

f(theta)=42.152403  
theta=[6.0541767  0.17936161 2.33819949]
  • 继续下降,f 值变成 ~42。
  • 第二个分量(0.179)几乎快收敛到 0 了。

Iter 400

f(theta)=30.556370  
theta=[5.25288565 0.05091135 1.72074696]
  • 三个分量继续减小,函数值也继续下降。
  • 可以看出来参数在逐步往 0 收缩。

Iter 500

f(theta)=21.872385  
theta=[4.51437396 0.01130478 1.22175496]
  • 此时 f 值还在下降(21),但下降速度变慢了。
  • 第二个参数已经基本到 0(0.01),其他两个参数也明显比最开始小了很多。

🔑 总结

  1. 趋势:函数值从 78 → 57 → 42 → 30 → 21,说明优化器 Adam 确实在不断让目标函数下降。
  2. 参数收敛:θ 在逐步往 0 收敛(最终最优解)。
  3. 下降速度:一开始下降快,后面越来越慢,这是正常的,因为越靠近最优点,梯度越小。
  4. 未到 0:500 步还没完全到 0,是因为学习率比较小(lr=0.01),如果继续迭代或适当调大学习率,θ 会更快逼近 0。

画图验证Adam 能不断减小损失函数,并逐渐收敛到最优解的python代码请到第2页查看👇

Avatar photo

李星海

简介: 2025-今 浙江农林大学 | 2022-今 广州白蓝碗蛋科技有限公司 | 2022-2024 广州商学院 | 2019-2022 广东工贸职业技术学院 | 服务宗旨:心始至客,行亦致远。