(tensorflow笔记)神经网络中的一些关键概念(学习率、激活函数、损失函数、欠拟合和过拟合、正则化和优化器)

1.神经网络复杂度

神经网络的复杂度,多用神经网络的层数和神经网络中待优化参数的个数表示。以下图为例说明
在这里插入图片描述

空间复杂度

神经网络的层数=隐藏层的层数+1个输出层
统计神经网络的层数时,只统计具有运算能力的层,输入层仅把数据传输过来,没有运算,不算到神经网络的层数中。输入层和输出层之间的所有层都叫做隐藏层。上图有2层神经网络
总参数=总w + 总b
(第一层)3×4+4 + (第二层)4×2+2 = 26

时间复杂度

神经网络中乘加运算的次数表示。有几条权重线,就有几次乘加运算
(第一层)3×4 + (第二层)4×2 = 20

2.学习率策略

参数更新公式如下,公式中的lr即为学习率,表示参数每次更新的幅度。
在这里插入图片描述
当学习率设置过小时,更新过慢,当学习率设置过大时,不收敛,那么学习率设置多少合适

指数衰减学习率

可以先用较大的学习率,快速得到较优解,然后逐步减小学习率,使模型在训练后期稳定
在这里插入图片描述
可使用此公式实现指数衰减学习率,根据当前迭代次数,动态改变学习率的值。指数型学习率衰减法是最常用的衰减方法,在大量模型中都广泛使用.此公式中,绿色的文字为超参数,当前轮数一般为epoch或者是当前迭代的batch数global_step表示
TensorFlow API: tf.keras.optimizers.schedules.ExponentialDecay
在这里插入图片描述

分段常数衰减

TensorFlow API: tf.optimizers.schedules.PiecewiseConstantDecay
在这里插入图片描述
分段常数衰减可以让调试人员针对不同任务设置不同的学习率,进行精细调参,在任意步长后下降任意数值的learning rate,要求调试人员对模型和数据集有深刻认识,一般用的不多。

3.激活函数

激活函数是用来加入非线性因素的,因为线性模型的表达能力不够。引入非线性激活函数,可使深层神经网络的表达能力更加强大
优秀的激活函数应满足:

  1. 非线性:激活函数非线性时,多层神经网络可逼近所有函数
  2. 可微性:优化器大多使用梯度下降来更新参数
  3. 单调性:当激活函数是单调的,能保证单层网络的损失函数是凸函数
  4. 近似恒等性:f(x)约等于x。当参数初始化为随机小值时,神经网络更稳定

简单看下凸函数,比如这就是一个凸函数的图像,像一个大碗一样
在这里插入图片描述
与刚才的图有些相反,这是非凸函数,因为它是非凸的并且有很多不同的局部最小值
在这里插入图片描述
激活函数输出值的范围:
激活函数输出为有限值时,基于梯度的优化方法更稳定
激活函数输出为无限值时,建议调小学习率

sigmoid

在这里插入图片描述
可以看到,sigmoid函数将输入值变换到0-1之间的值输出,若输入值是非常大的负数,则输出为0;若输入值是非常大的正数,则输出值为1,相当于对输入进行归一化。
现在sigmoid函数用的很少,主要的原因是,深层神经网络更新参数时,需要从输出层到输入层,逐层进行链式求导,而sigmoid函数的导数输出是0-0.25之间的小数,链式求导需要多层导数连续相乘,会出现多个0-0.25之间的小数连续相乘,结果将趋于0,产生梯度消失,使得参数无法继续更新
我们希望输入每层神经网络的特征是以0为均值的小数值,但是过sigmoid激活函数后的数据都是正数,会使收敛变慢。而且sigmoid函数存在幂运算,计算复杂度大,计算时间长

TensorFlow API: tf.math.sigmoid

优点:

  1. 输出映射在(0,1)之间,单调连续,输出范围有限,优化稳定,可用作输出层;
  2. 求导容易

缺点:

  1. 易造成梯度消失;
  2. 输出非0均值,收敛慢;
  3. 幂运算复杂,训练时间长。

sigmoid函数可应用在训练过程中。然而,当处理分类问题作为输出时,sigmoid却无能为力。简单地说,sigmoid函数只能处理两个类,不适用于多分类问题。而softmax可以有效解决这个问题,并且softmax函数大都运用在神经网路中的最后一层网络中,使得值得区间在(0,1)之间,而不是二分类的。

tanh

在这里插入图片描述
在这里插入图片描述
从函数图像看,tanh函数的输出为0均值了,但是依旧存在梯度消失和幂运算问题
TensorFlow API: tf.math.tanh

优点:

  1. 比sigmoid函数收敛速度更快。
  2. 相比sigmoid函数,其输出以0为中心

缺点:

  1. 易造成梯度消失;
  2. 幂运算复杂,训练时间长。

ReLU

在这里插入图片描述
在这里插入图片描述
relu函数非常符合好的激活函数应该具有近似恒等性这一要求,
TensorFlow API: tf.nn.relu

优点:

  1. 解决了梯度消失问题(在正区间);
  2. 只需判断输入是否大于0,计算速度快;
  3. 收敛速度远快于sigmoid和tanh,因为sigmoid和tanh涉及很多expensive的操作;
  4. 提供了神经网络的稀疏表达能力。

缺点:

  1. 输出非0均值,收敛慢;
  2. Dead ReLU问题:某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。即送入激活函数的特征是负数时,激活函数输出是0,反向传播得到的梯度是0,导致参数无法更新,造成神经元死亡

其实,导致神经元死亡的根本原因是送入神经元的负数特征过多导致的,我们可以改进随机初始化,避免过多的负数特征送入relu函数,可以通过设置更小的学习率,减少参数分布的巨大变化,避免训练中产生过多负数特征进入relu函数

Leaky ReLU

在这里插入图片描述
Leaky ReLU是为解决relu负区间为0,引起神经元死亡问题而设计的,Leaky ReLU的负区间引入了一个固定的斜率a,使得Leaky ReLU的负区间不再恒等于0
理论上来讲,Leaky ReLU有ReLU的所有优点,外加不会有Dead ReLU问题,但是在实际操作当中,并没有完全证明Leaky ReLU总是好于ReLU。实际使用中,大部分仍然选用relu
TensorFlow API: tf.nn.leaky_relu

建议

  1. 首选ReLU激活函数;
  2. 学习率设置较小值;
  3. 输入特征标准化,即让输入特征满足以0为均值,1为标准差的正态分布;
  4. 初始化问题:初始参数中心化,即让随机生成的参数满足以0为均值,以在这里插入图片描述
    为标准差的正态分布。

4.损失函数

损失函数:预测值(y)与已知答案(y_)的差距。神经网络的优化目标,就是找到某套参数,使得计算出来的结果y与已知答案y_无限接近,也即它们的差距loss值最小
神经网络模型的效果及优化的目标是通过损失函数来定义的。回归和分类是监督学习中的两个大
类。主流的loss有三种计算方法,均方误差、交叉熵和自定义。下面用一个预测酸奶日销量的例子,来理解损失函数

均方误差损失函数

均方误差(Mean Square Error)是回归问题最常用的损失函数。回归问题解决的是对具体数值的预测,比如房价预测、销量预测等。这些问题需要预测的不是一个事先定义好的类别,而是一个任意实数。均方误差定义如下:
在这里插入图片描述
TensorFlow API: tf.keras.losses.MSE

预测酸奶日销量y, x1、 x2是影响日销量的因素。
建模前,应预先采集的数据有:每日x1、 x2和销量y_(即已知答案,知道了销量,就可以建议产量了,这里假定,最佳的情况:产量=销量)
拟造数据集X,Y_: y_ = x1 + x2 噪声: -0.05 ~ +0.05 拟合可以预测销量的函数
构建一个一层的神经网络,将这套构建的数据集喂入其中

import tensorflow as tf
import numpy as np

SEED = 23455

rdm = np.random.RandomState(seed=SEED)  # 生成[0,1)之间的随机数
x = rdm.rand(32, 2) #此即x1和x2
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x]  # 生成噪声[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)
x = tf.cast(x, dtype=tf.float32)

w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1))
b1 = tf.Variable(tf.random.normal([1], stddev=1, seed=1))

epoch = 30000
lr = 0.003

for epoch in range(epoch):
    with tf.GradientTape() as tape: #用with结构计算前向传播结构y和loss
        y = tf.matmul(x, w1) + b1
        loss_mse = tf.reduce_mean(tf.square(y_ - y))

    grads = tape.gradient(loss_mse, [w1,b1])
    w1.assign_sub(lr * grads[0])
    b1.assign_sub(lr * grads[1])

    if epoch % 2000 == 0:
        print("After %d training steps,w1 and b1 are " % (epoch))
        print(w1.numpy())
        print(b1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())
print("Final b1 is: ", b1.numpy())


Final w1 is:  [[0.9900439]
 			   [0.983632 ]]
Final b1 is:  [0.01385183]

运行代码可以看到,随着迭代轮次的上升,w1的两个元素值不断趋近于1,而偏置项b1不断趋近于0,这符合我们制造数据集的公式y=x1+x2,说明神经网络拟合正确

交叉熵损失函数

交叉熵(Cross Entropy)表征两个概率分布之间的距离,交叉熵越小说明二者分布越接近,是分类问题中使用较广泛的损失函数
在这里插入图片描述
其中y_代表数据的真实值,y代表神经网络的预测值。对于多分类问题,神经网络的输出一般不是概率分布,因此需要引入softmax层,使得输出服从概率分布。TensorFlow中可计算交叉熵损失函数的API有
TensorFlow API: tf.keras.losses.categorical_crossentropy

loss_ce1 = tf.losses.categorical_crossentropy([1, 0], [0.6, 0.4])
loss_ce2 = tf.losses.categorical_crossentropy([1, 0], [0.8, 0.2])
print("loss_ce1:", loss_ce1)
print
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值