一.神经网络复杂度
空间复杂度:用神经网络层数和待优化参数个数表示,计算神经网络层数时,只统计具有运算能力的层,所以不要输入层,只要隐藏层和输出层。总参数=总w+总b
时间复杂度:神经网络中乘加运算的次数(即多少根线)
二.学习率
表示参数更新的幅度
实际应用中,学习率设置多少合适呢?
比如采用指数衰减学习率
可以先用较大的学习率,快速得到较优解,然后逐步减小学习率,使模型在训练后期稳定
import tensorflow as tf
w = tf.Variable(tf.constant(5, dtype=tf.float32))
epoch = 40
LR_BASE = 0.2 # 最初学习率
LR_DECAY = 0.99 # 学习率衰减率
LR_STEP = 1 # 喂入多少轮BATCH_SIZE后,更新一次学习率
for epoch in range(epoch): # for epoch 定义顶层循环,表示对数据集循环epoch次,此例数据集数据仅有1个w,初始化时候constant赋值为5,循环100次迭代。
lr = LR_BASE * LR_DECAY ** (epoch / LR_STEP)
with tf.GradientTape() as tape: # with结构到grads框起了梯度的计算过程。
loss = tf.square(w + 1)
grads = tape.gradient(loss, w) # .gradient函数告知谁对谁求导
w.assign_sub(lr * grads) # .assign_sub 对变量做自减 即:w -= lr*grads 即 w = w - lr*grads
if(epoch % 2 == 1):
print("After %s epoch,w is %f,loss is %f,lr is %f" % (epoch, w.numpy(), loss, lr))
结果如下:
After 1 epoch,w is 1.174400,loss is 12.959999,lr is 0.198000
After 3 epoch,w is -0.191126,loss is 1.747547,lr is 0.194060
After 5 epoch,w is -0.691392,loss is 0.248077,lr is 0.190198
After 7 epoch,w is -0.879339,loss is 0.037014,lr is 0.186413
After 9 epoch,w is -0.951691,loss is 0.005795,lr is 0.182703
After 11 epoch,w is -0.980209,loss is 0.000951,lr is 0.179068
After 13 epoch,w is -0.991710,loss is 0.000163,lr is 0.175504
After 15 epoch,w is -0.996452,loss is 0.000029,lr is 0.172012
After 17 epoch,w is -0.998449,loss is 0.000005,lr is 0.168589
After 19 epoch,w is -0.999308,loss is 0.000001,lr is 0.165234
After 21 epoch,w is -0.999685,loss is 0.000000,lr is 0.161946
After 23 epoch,w is -0.999854,loss is 0.000000,lr is 0.158723
After 25 epoch,w is -0.999931,loss is 0.000000,lr is 0.155564
After 27 epoch,w is -0.999967,loss is 0.000000,lr is 0.152469
After 29 epoch,w is -0.999984,loss is 0.000000,lr is 0.149434
After 31 epoch,w is -0.999992,loss is 0.000000,lr is 0.146461
After 33 epoch,w is -0.999996,loss is 0.000000,lr is 0.143546
After 35 epoch,w is -0.999998,loss is 0.000000,lr is 0.140690
After 37 epoch,w is -0.999999,loss is 0.000000,lr is 0.137890
After 39 epoch,w is -0.999999,loss is 0.000000,lr is 0.135146
三.激活函数
对于线性函数,即使有多层神经元首尾相接,构成深层神经网络,依旧是线性组合,模型的表达能力不够
非线性的激活函数的加入,大大提升模型的表达力
优秀的激活函数具有如下特点:
1.非线性:只有激活函数非线性时,才不会被单层网络替代,使多层网络有了意义
2.可微性:优化器大多依据梯度下降更新参数,不可微就没法更新参数了
3.单调性:激活函数是单调的才能保证单层网络的损失函数是凸函数,更容易收敛
4.近似恒等性:最好是近似恒等,f(x)约等于x,激活函数的输出值约等于激活函数的输入值,当参数初始化为随机小值时,神经网络更稳定
激活函数输出值的范围:
1.激活函数输出为有限值时,权重对特征的影响会更显著,基于梯度的优化方法更稳定
2.激活函数输出为无限值时,参数的初始值对模型的影响非常大,建议调小学习率
常用激活函数:
1.Sigmoid函数
缺点:
(1)易造成梯度消失,导数输出0~0.25之间的小数,链式求导需要多层导数连续相乘
(2)输出非0均值,收敛慢
(3)幂运算复杂,训练时间长
2.Tanh函数
特点:
(1)输出的是0均值
(2)易造成梯度消失
(3)幂运算训练复杂
3.Relu函数
优点:
(1)解决梯度消失问题(在正区间)
(2)使用时只需判断是否大于0,计算速度快
(3)训练参数时的收敛速度远快于sigmoid和tanh
缺点:
(1)输出非0均值,收敛慢
(2)存在Dead Relu问题:送入激活函数的输入特征是负数时,激活函数输出是0,激活函数输出是0,反向传播得到的梯度是0,导致参数无法更新,造成神经元死亡
4.Leaky Relu函数
为解决Relu负区间为0,引起神经元死亡问题而设计的
理论上来说,Leaky Relu 比Relu好,但在实际使用中,选择Relu的更多
选取激活函数的建议:
四.损失函数
预测值y与已知答案y_的差距
1.均方误差
2.自定义损失函数
3.交叉熵损失
4.softmax与交叉熵结合
分类问题时,通常先用softmax函数让输出结果符合概率分布,再求交叉熵损失函数
下面函数可同时计算softmax和交叉熵
tf.nn.softmax_cross_entropy_with_logits(y_, y)
五.缓解过拟合
欠拟合:模型不能有效拟合数据集,是对现有数据集学习的不够彻底
过拟合:模型对当前数据拟合的太好了,但是对从未见过的新数据却难以做出正确的判断,模型缺少泛化能力
欠拟合解决方法:
1.增加输入特征项
2.增加网络参数
3.减少正则化参数
过拟合解决方法:
1.数据集清洗
2.增大数据集
3.采用正则化
4.增大正则化参数
正则化缓解过拟合
正则化就是在损失函数中引入模型复杂度指标,给每个参数w加上权重,抑制训练数据集中的噪声(一般只对参数w使用,不对偏置b使用)
L1正则化与L2正则化:
正则化的选择:
L1正则化大概率会使很多参数变为0,因此该方法可通过稀疏参数,减少参数的数量,降低模型复杂度
L2正则化会使参数接近0但是不为0,因此可以减少参数数值,可以有效缓解数据集中因噪声引起的过拟合
看一下L2正则化计算loss(w)的过程
六.优化器
引导神经网络更新参数的工具
一阶动量:与梯度相关的函数
二阶动量:与梯度平方相关的函数
不同的优化器实质上只是定义了不同的一阶动量和二阶动量公式
1.SGD
2.SGDM
3.Adagrad
4.RMSProp
5.Adam