本文是吴恩达深度学习第二课:改善深层网络的笔记。这次内容包括深度学习的实用技巧、提高算法运行效率、超参数调优。 第二课有以下三个部分,本文是第二部分。 神经网络中有很多超参数,那要如何找到一套好点的参数设置呢。 那如果想调试一些参数值,要怎么做呢。 而在深度学习中,我们常用下面的做法。就是随机取点,比如也取25个点。 举个例子,假设超参数一是学习率,超参数二是Adam算法中的 这种情况下,学习率的取值很重要,而 如果在网络中取点, 因为有25个样本值,但是只尝试了5个 而随机取值,可以尝试25个独立的 上面只是两个超参数,如果有三个的话,就会是一个立方体。 如果有更多的参数就无法画出来了。 这种从粗到细的搜索经常使用。 但超参数的搜索内容不止这些,下面我来介绍如何为超参数选择合适的范围。 上面我们已经知道了可以随机取值提升搜索效率,但是这里的随机取值并不是在有效值范围内的随机均匀取值,而是选择合适的范围,用来探究这些超参数哪个重要。 或者我们要选择神经网络的层数 假设我们将学习率最小值设为0.0001,最大值为1。 这样看上去不对,此时考虑标尺搜索超参数的方式更合理。 在python中可以这么做: 最后另一个棘手的例子是给指数加权平均值的 假设我们认为 解决这个问题的最好方法是改成考虑 你也许已经找到了一组好的超参数设置,并继续发展算法。但在几个月的过程中,你可以观察到你的数据逐渐发生改变,或许只是数据中心更新了服务器。 正因为有这些原因,可能原来的超参数设定不再好用,所以建议每隔几个月至少重新评估一次设定的超参数。 关于如何搜索超参数的问题,有两种主要的流派。 这种情况通常是你机器的资源不够好,计算能力不强,不能再同一时间试验大量模型时才采取的办法。 而另一种方法则显得财大气粗了一点,就是同时试验多种模型。 一般第一种方法叫做熊猫方式,因为熊猫的孩子比较少,一次通常只有一个,会花费很多精力抚养熊猫宝宝。 而第二种方式就像鱼子酱一样,一次会产生上亿个鱼卵。 所以这两种方法取决于你的计算机资源。 在深度学习兴起后,最重要的一个思想之一就是批归一化(Batch Normalization),批归一化会使参数搜索问题变得很容易,使神经网络对超参数的选择更加稳定,超参数的范围也可以更庞大,工作效果也很好。重要的是会使我们很容易的训练深层网络。 当训练一个模型,比如逻辑回归时,我们知道归一化输入特征可以加速学习过程。 那更深层的网络呢,不仅有输入特征,每层还有激活值。 在逻辑回归中,我们看到如果归一化输入特征 现在的问题是,我们能否归一化每层的输出值 下面看如何实现批归一化。 假设你有一些隐藏单元值,从 已知这些值,先要计算平均值,然后计算方差。 这样就把这些 因此要计算 这 这里 如果 那么 通过给 所以现在用 我们从这小节学到的是,批归一化的作用是它适用的归一化过程不只是输入层,同样适用于神经网络中的深层隐藏神经元。 不过训练输入和这些隐藏单元值的一个区别是,我们不想隐藏单元值必须是均值0方差1的标准正态分布,以便利用激活函数的非线性部分。 所以批归一化的真正作用是使隐藏单元值的均值和方差归一化,使它们有固定的均值和方差。 在实践中,BN通常和mini-batch一起使用。 变成由 因为这是隐藏单元的数量,要与 下面总结一下如何用BN来应用梯度下降法。 我们知道对输入特征进行归一化可以加速学习,而BN做的和输入特征归一化类似的事情。 BN有用的第二个原因是它可以使权重比你的网络更加深。 下面以一个例子说明。 训练集的数据分布和预测集的数据分布不一致的问题就叫做“covariate shift”问题(或者可以想成输入值改变的问题就是covariate shift)。 如果你已经学习了 还是以一个例子说明下,考虑下面这个神经网络: 我们先遮住左边部分,从该层来看,它得到了4个输入值,用 该层的工作是找到一种方式,使这些值映射到 因此也就有了covariate shift问题,所以BN的作用是减少这些输入值改变的程度。 这在一定程度上限制了上一层的参数更新能影响数据分布的程度,因此说BN减少了输入值改变的问题。 也可以这样想,BN减弱了前层参数的作用与后层参数的作用之间的联系,它使得网络每层可以自己学习,稍微独立于其他层,这有助于加速整个网络的学习。 BN还有一个作用是有一点正则化效果。 因为正则化效果比较小,所以还是可以和dropout一起使用。 因为BN一次只能处理一个mini-batch数据,它在mini-batch上计算均值和方差。因为测试时没有mini-batch样本,所以需要做一些不同的东西以确保预测有意义。 BN将你的数据以mini-batch的形式逐一处理,但在测试时,你可能需要对每个样本逐一处理。 典型的做法是用一个指数加权平均来估算 我们之前的例子都是二分类问题,今天我们来了解下多分类问题。 有一种逻辑回归的一般形式叫Softmax回归,能预测多个类别的概率。 假设现在不是要识别是否为猫,而是要识别猫(类1)、狗(类2)和鸡(类3),如果不属于任何一类,则分为其他(类0)。 我们用 因此我们可以构建一个神经网络,它的输出层有4个单元。我们想要输出单元的值告诉我们属于这4种类型中每一种的概率有多大。 这里的 要做到这一点通常要使用Softmax层。 它的做法是这样的,首先要计算临时变量 然后计算 下面以一个例子说明, 从决策边界可以直觉的感受到,这些决策边界都是线性的。 当然,深度网络会有更多的层和神经元,因为用的激活函数都是非线性的,我们就可以学习到更复杂的非线性决策边界。 本小节我们来看下如何训练一个使用了Softmax层的模型。 接下来我们看下如何训练带有softmax输出层的神经网络。 先来看下损失函数的定义,下面是真实标签 那么如果用损失函数来表示这种差别呢,对应了两个向量的差别第一个想到的应该就是交叉熵了吧。损失函数的定义如下: 上面是单个样本的损失函数,那整个训练集的成本函数 最后说一下代码实现细节,因为 所以向量化实现的话,对于 下面介绍一下深度学习框架,从这次课程开始就可以不用自己实现深度神经网络了。 这里一下选择框架的标准: (本小节介绍的是TensorFlow1,这还是博主第一次学习TensorFlow1)。 假设现在有一个简单损失函数 基本上用tf只要实现前向传播,它能弄明白如何做反向传播和梯度计算。 tf还重载了运行符,这样上面的代码可以简写。 上面我们最小化的是固定参数的损失函数。 如果你想要最小化的函数是训练集函数又该怎么办呢,如果把训练数据加入TensorFlow程序呢 现在 这三行代码在tf里面是符合表达习惯的, 有些程序员习惯上面这么写。 这段代码文章目录
引言
参数调优处理
比如上面的这些参数,如果要按重要程度来排序的话,红框里面的学习率是最重要的;其次是橙框框出的那些参数;再其次是紫框框出的那些;最后是没有框出的那些。
之前常见的做法是在网格中取样本点,比如上面有两个参数,每个样本点代表两个参数的值。然后尝试这25个点,看哪个选择效果最好。
然后从中选出效果最好的点,这样做的原因是对于你要解决的问题而言,通常都不知道哪个超参数最重要。就像上面看到的一样,一些参数比其他参数更重要。
ε。
ε则相对无关紧要。
用规整网格的方法试了5个学习率取值,你会发现无论
ε取什么,结果基本上都是一样的(在同一个学习率
α下)。
α取值。
α值。
当给超参数取值时,一个惯例是采用由粗到细的策略。
假设有两个参数,并且你发现红线画出的那个取值效果较好,它附近的几个点也不错。接下来要做的是,放到这块小的区域,然后在里面更加密集地取值。
也就是在上面蓝色方格中取更多的点,再搜索哪个点效果最好。为超参数选择合适的范围
假设想知道网络的单元数多少合适,通常要预先设定一个范围,比如50到100,此时可以看到上面从50到100的数轴,我们可以随机在上面取点(这里要取整数),这是一个搜索特定超参数的很直观的方式。
L,或许可以定位2到4中的某个值。
上面都是取整数的例子,那如果取一些小数呢,比如学习率
α的取值。
如果还是用类似前面的方法的话,即从0.0001到1中随机取值,可能90%的结果落到了0.1到1之间。(相当于按0.1将1分成了10份,取到0~0.1的概率只有10%)。
即依次取0.0001、0.001、0.01、0.1、1。然后以幂次-4到0之间随机取值(要有小数),取到的值作为
10的幂次,就可以得到我们想要的随机值。
上面
σ取值[-4,0]之间的随机数,然后取
10σ就可以得到我们想要的
α。>>> r = -4 * np.random.rand() >>> r -2.8480000821641887 >>> 10 ** r 0.001419057253217574
β取值。
β的取值是0.9到0.999之间的某个值。
1−β的取值,也就是0.1到0.001之间。这样就和我们上面考虑
α的问题一样。
一旦我们得到了一个比较不错的值,我们还可以应用由粗到细的方法,在附近更加密集的随机取值。超参数训练的实践:Pandas VS Caviar
一种是你像照顾婴儿一样照顾一个模型
可能第一天收敛效果不错,然后第二天你增大了学习率,然后过了几天,你发现学习率太大了,又把学习率改为之前的设置。可以说每天都花时间照顾此模型。
一般设定了一些超参数,然后让它自己运行,可能经过几周后得到这样的曲线;同时你可能有不同的模型,第二个模型可能会生成紫色曲线:
显然紫色曲线对应的模型更好一点,甚至同时试验了多种模型:
用这种方式可以同时试验许多不同的参数设定,到最后只要选择效果最好的那个即可。
归一化网络的激活函数
如果你想训练这些参数,比如
W[3],b[3],那若能归一化
a[2]岂不是美滋滋。
x1,x2,x3,会帮助我们更有效的训练
w,b。
a。严格来说是归一化
z值。
z(1)到
z(m),这些来自隐藏层
l,精确的写法应该是
z[l](i),这里为了方便简化了
l符号。
接着归一化每个
z(i)值。
同样防止分母为零,加上了一个很小的值。
z值归一化为均值为0方差为1的值,但是我们不想让隐藏单元总是含有均值0方差1分布的值,也许有不同的分布更有意义。
z∼(i)
z∼(i)=γznorm(i)+β
γ和
β是模型的学习参数,不是超参数。
γ和
β的作用是可以随意设置
z∼的平均值。
γ=σ2+ε,而
β=μ,
z∼(i)=z(i)
γ和
β赋其他值,就可以使你构造含其他平均值和方差的隐藏单元值。
z∼(i)取代
z(i)来参与神经网络的后续计算。将Batch Norm拟合进神经网络
假设我们有一个这样的神经网络,对于上面这些记号应该很熟悉了吧。那我们要如何加入Batch Norm(简称BN)呢,
如果没有Batch Norm,下一步就是代入激活函数得到激活值了,但是我们今天要在这一步加入Batch Norm。
如上节所说的,我们加入BN,通过参数
β[1],γ[1] 计算得到
z∼[1]。然后再代入激活函数,得到
a[1]=g[1](z∼[1])。这样就计算完第一层的结果。
BN发生在
Z和
a的计算过程之间。接下来通过这个
a[1]来计算
z[2],和第一层一样,我们对
z[2]进行BN。
这里要强调的是BN发生在计算
z和
a之间的。
这里我们(每个隐藏层)引入了两个参数
γ,β,所有现在网络的参数是:
这些参数都可以通过模型自己学习的,
更新的公式和参数
W,b一样,同时也可以应用Adam或RMSprop。
这里要指出的是
在应用BN时,我们要先将
z[l]归一化,结果为均值0方差1的分布,然后再通过
β和
γ进行缩放。 这意味着,无论
b[l]的值是多少,都会将均值设成0的过程中被减掉,因此在这里增加的任何常数的数值都不会发生改变,因为它们会被均值减法所抵消。 也就是使用BN,可以消除
b[l]这个参数,或者说将它设为零即可。
z[l]的式子中可以直接去掉
b:
β[l]控制转移或偏置条件。
下面来看下这些参数的维度,
z[l]的维度是
(n[l],1),
β[l]和
γ[l]的维度也是
(n[l],1)。
z[l]的维度匹配才能对其进行转换。Batch Norm为什么奏效
比如我们有一个网络,假设已经在所有黑猫的图像上训练了数据集,如果现在要把这个网络应用于其他颜色的猫
此时可能你的模型适用的不会很好。
如果黑猫图像中的训练集是上图左边那样分布的,而其他颜色猫训练集分布是右边那样的,那么无法期待在左边训练好的模型能同样在右边也表现的很好。
x到
y的映射,此时若
x的分布改变了,那么你可能需要重新训练你的模型。
我们从第三个隐藏来看看学习过程,假设已经学习了参数
W[3],b[3]。从该层来看的话,它从上一层得到一些输入值,接下来它要做些事情希望使输出值
y^更接近于真实值
y。
a[2]来表示,但这些值也可能是输入特征值。
y^。也许现在做得不错。
现在把遮罩打开,这个网络还有参数
W[2],b[2]和
W[1],b[1]。如果这些参数发生改变,那么第三层得到的输入也会发生改变。
如果绘制出来的话(这里取两个输入来绘制),BN说的是,
z1[2],z2[2]的值可以改变,
但是无论怎么变化,它们的均值和方差是一样的,由
γ[2]和
β[2]决定均值和方差具体是多少。
测试时的Batch Norm
上面是在训练时用到的BN式子,在训练是都是应用于mini-batch的。但在测试时需要用其他方式来得到
μ,σ2。
μ,σ2,这个指数加权平均涵盖了所有mini-batch。
假设在
l层得到很多小批次的均值,对这些均值做指数加权平均就得到了这一隐藏层的
μ估计,同样地也可以对小批次的
σ2进行估计。
最后在测试时,对应于下面这个等式
只要用估计的
μ,σ2来计算即可,
z值是计算出来的,
γ,β直接用训练时学到的。多分类问题-Softmax 回归
C表示类别的总数,这里有4种。
y^会是一个
(4,1)维度的向量,并且因为输出的是概率,这4个概率加起来应该等于1。
在计算出最后一层的
Z[L]后,要应用Softmax激活函数。
t=ez[L],它的维度这个例子中也是
(4,1)。
a[L]为向量
t的归一化,使得
a[L]中元素和为1,它的维度这个例子中也是
(4,1)。
这里取指数
e的目的是使得所有的值都为正数,满足了概率为正的定义,同时让每个值除以总和,这样所得的值加起来就为
1。然后可以根据值的大小得出属于哪个类别的概率最大。
这里是类别0的值最大,也就是属于类别0的概率最大。最后用紫线框出来的四个值就是
y^的输出。
这里的激活函数是Softmax函数。
上面是Softmax的三个例子,这里输入为
x1,x2,把它们直接接入Softmax层,这里这里有3个类别,就会得到3个输出。上面相当于是一个没有隐藏层的神经网络。训练一个Softmax分类器
先来回顾下上小节的内容,上面是Softmax函数的计算过程,最后由输入值5变成了0.842。这里的softmax说的是和hardmax对应的, hardmax是
hardmax会把最大元素的位置上放1,其他放0。这种比较适用于手写数字识别的one-hot向量。
y和输出标签
y^。
从上面的例子看到,这个结果不太好。因为这实际上是一只猫,但是只给了猫20%的概率。
这个例子中只有
y2=1,其他都是
0,因此上面的项可以简化为:
因此
要最小化损失函数,就变成要最小化
−logy^2,即最大化
y^2,由softmax的公式可以值,最大也不会超过
1。
J要如何计算呢
就是对每个样本的损失函数值取个平均即可。
C=4,
y和
y^都是一个
(4,1)向量
m个样本,
Y写成:
Y^也这样表示:
最后看一下有softmax输出层时如何实现梯度下降法。
我们上面讲了前向传播,那反向传播呢
关键是
dz的表达式。
求
dz表达式可参考:吴恩达深度学习——神经网络基础深度学习框架
如今又这么的深度学习框架(教程录制的时候可能还没有PyTorch和TensorFlow2)
TensorFlow
J需要最小化,
我们来看怎样利用TensorFlow将其最小化。# 定义参数w w = tf.Variable(0,dtype=tf.float32) # 定义损失函数 cost = tf.add(tf.add(w**2,tf.multiply(-10.,w)),25)# w^2 - 10w + 25 # 学习算法 用0.01的学习率来最小化损失函数 train = tf.train.GradientDescentOptimizer(0.01).minimize(cost) init = tf.global_variables_initializer() session = tf.Session() session.run(init) print(session.run(w)) # 初始为0 session.run(train) print(session.run(w)) # 运行一次梯度下降后,得到的w是0.099999994
下面我们运行梯度下降1000次迭代。for i in range(1000): session.run(train) print(session.run(w))
运行1000次梯度下降后,得到的w
变成了4.9999,此时已经很接近最优值了。#cost = tf.add(tf.add(w**2,tf.multiply(-10.,w)),25)# w^2 - 10w + 25 cost = w**2 - 10*w +25
# 定义参数w w = tf.Variable(0,dtype=tf.float32) # 把x定义成一个3x1的矩阵 x = tf.placeholder(tf.float32,[3,1]) # 定义损失函数 #cost = tf.add(tf.add(w**2,tf.multiply(-10.,w)),25)# w^2 - 10w + 25 # cost = w**2 - 10*w +25 cost = x[0][0]*w**2 + x[1][0]*w + x[2][0]
x
变成了控制这个二次函数系数的数据,这个placeholder
说的是后面会为x
提供值。# 模拟x的数据 cofficients = np.array([[1.],[-10.],[25.]]) # 定义参数w w = tf.Variable(0,dtype=tf.float32) # 把x定义成一个3x1的矩阵 x = tf.placeholder(tf.float32,[3,1]) # 定义损失函数 #cost = tf.add(tf.add(w**2,tf.multiply(-10.,w)),25)# w^2 - 10w + 25 # cost = w**2 - 10*w +25 cost = x[0][0]*w**2 + x[1][0]*w + x[2][0] # 学习算法 用0.01的学习率来最小化损失函数 train = tf.train.GradientDescentOptimizer(0.01).minimize(cost) init = tf.global_variables_initializer() session = tf.Session() session.run(init) print(session.run(w)) # 初始为0 session.run(train,feed_dict={x:cofficients}) print(session.run(w)) for i in range(1000): session.run(train,feed_dict={x:cofficients}) print(session.run(w))
session = tf.Session() session.run(init) print(session.run(w)) # 初始为0
with tf.Session() as sessioin: session.run(init) print(session.run(w)) # 初始为0
cost = x[0][0]*w**2 + x[1][0]*w + x[2][0]
的作用是让tf建立计算图
参考
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算