Table of contents
2 神经网络优化
2.1 常用函数
-
在每个元素上执行条件语句,为真则返回A,为假则返回B:
tf.where(条件语句,真返回A,假返回B)1 2 3 4a = tf.constant([1, 2, 3, 1, 1]) b = tf.constant([0, 1, 3, 4, 5]) c = tf.where(tf.greater(a,b), a, b) # 若a>b, 返回a对应位置的元素,否则返回b对应位置的元素 print(c) # tf.Tensor([1 2 3 4 5], shape=(5,), dtype=int32) -
返回一个 [0,1) 之间的随机数:
np.random.RandomState.rand(维度)维度为空时返回标量1 2 3 4 5rdm = np.random.RandomState(seed=1) # 设置随机种子每次生成的随机数相同 a = rdm.rand() b = rdm.rand(2,3) print(a) # 0.4170220047 print(b) # [[7.20324493e-01 1.14374817e-04 3.02332573e-01] [1.46755891e-01 9.23385948e-02 1.86260211e-01]] -
将两个数组按垂直方向叠加
np.vstack(数组1,数组2)1 2 3 4a = np.array([1, 2, 3]) # shape=(3,) b = np.array([4, 5, 6]) c = np.vstack((a,b)) print(c) # [[1 2 3] [4 5 6]] shape=(2,3) -
生成网格坐标
np.mgrid[起始值:结束值:步长,起始值:结束值:步长,...]生成若干维度的等差数组,不包括结束值x.ravel()将多维数组x变为一维数组,“把变量拉直”np.c_[数组1,数组2,...]数组对应位置元素配对1 2 3 4 5 6 7import numpy as np x, y = np.mgrid[1:3:1, 2:4:0.5] # x坐标+1递增,y坐标+0.5递增 grid = np.c_[x.ravel(), y.ravel()] # 两个(8,) array配对 print(x) # [[1. 1. 1. 1.] [2. 2. 2. 2.]] shape=(2,4) print(y) # [[2. 2.5 3. 3.5] [2. 2.5 3. 3.5]] print(grid) # [[1. 2.] [1. 2.5] [1. 3.] [1. 3.5] [2. 2.] [2. 2.5] [2. 3.] [2. 3.5]] shape=(8,2)
神经网络复杂度
多用网络层数和网络参数的个数表示:
空间复杂度:层数=隐藏层的层数+1个输出层;总参数=总w+总b
时间复杂度:乘加运算次数(多少次wx+b)
2.2 指数衰减学习率
先用较大的学习率,快速得到较优解,然后逐步减小学习率,使模型在训练后期稳定
指数衰减学习率 = 初始学习率 x 学习率衰减率 ^ (当前epoch(或batch) / 多少epoch(或batch)衰减一次)
|
|
2.3 激活函数
sigmoid 函数 作用:把无限变有限,把无穷归一,引入非线性,全域可导(导数在0-0.25之间);缺点:应用链式法则容易造成梯度消失;输入特征最好使均值为0的小数,但经过sigmoid后变为正数,导致收敛慢;其中有幂运算,计算时间长
tf.math.tanh(x) 激活后的输出的均值是0,导数在0-1之间,仍易造成梯度消失,两次幂运算,计算时间 更长
tf.nn.relu(x) f(x)=max(x,0) 优点:导数不是0就是1,在正区间内解决了梯度消失问题;只需判断输入是否大于0,计算速度快;收敛速度远快于sigmoid 和 tanh。缺点:输出不是以0为均值,收敛慢;Dead Relu问题,当输入特征是负数时,激活函数输出为0,反向传播时,梯度为0,导致相应的参数无法更新。可以改进随机初始化,避免过多的负数特征输入Relu函数;可以通过减小学习率,减小参数分布的巨大变化,避免训练中产生过多的负数特征
tf.nn.leaky_relu(x) f(x) = max(ax, x) 是为了解决Relu在负区间的导数为0 引起神经元死亡问题而设计的,它在负区间引入了固定的斜率a。理论上来讲,Leaky Relu 有 Relu 的所有优点,外加不会有 Dead Relu问题,但是在实际操作中,并没有完全证明 Leaky Relu 总好于Relu
对于初学者的建议:
- 首选relu激活函数
- 学习率设置较小值
- 输入特征标准化,即让输入特征满足以0为均值,以1为标准差的正态分布
- 初始参数中心化,即让随机生成的参数满足以0为均值,根号下当前层输入特征个数分之2 为标准差的正态分布。
2.4 损失函数
预测值y 与 已知答案 y_ 的差距
NN优化目标:loss最小,主流三种计算方法:mse,交叉熵,自定义
loss_mse = tf.reduce_mean(tf.square(y_ - y))
|
|
。。。。
2.6 优化器
参数更新:下一时刻的参数 等于 当前时刻的参数 减去 η (梯度下降)。η等于学习率乘上(一阶动量除以根号下二阶动量)。
SGD中无动量,一阶动量等于loss对参数的偏导数,二阶动量=1,所以 η 是沿梯度方向改变的步长。
单层网络 w*x+b 应用 SGD:
|
|
SGDM 在SGD基础上增加了一阶动量,一阶动量等于上一时刻的一阶动量与当前时刻的梯度共同作用:mₜ = β⋅mₜ₋₁ + (1-β)⋅gₜ , β是接近1的系数(经验值0.9),所以上一时刻的动量占主导;二阶动量=1。 一阶动量是“指数滑动平均值”?过去一段时间的平均值?
|
|
Adagrad 在SGD 基础上增加了二阶动量,可以对模型中的每个参数分配自适应学习率了。一阶动量与SGD设置相同,等于loss的梯度,二阶动量是从开始时刻到现在,梯度平方的累计和 $V_t = \sum_{τ=1}^t g_τ^2$
|
|
RMSProp 在SGD基础上增加了二阶动量,一阶动量仍等于当前时刻loss的梯度,二阶动量 $V_t = β⋅V_{t-1} + (1-β)⋅g_t^2$
|
|
Adam 同时结合了SGDM的一阶动量和RMSProp的二阶动量,并分别增加修正系数:mₜ = β₁⋅mₜ₋₁ + (1-β₁)⋅gₜ ,$\hat{m_t} = \frac{m_t}{1-β_1^t}$ ,Vₜ = β₂⋅Vₜ₋₁ + (1-β₂)⋅gₜ²,$\hat{V_t}=\frac{V_t}{1-β_2^t}$ , t 是从开始到现在经历的所有batch数
|
|
不同优化器训练速度不同