调试处理
关于训练深度最难的事情之一就是你要处理的参数的数量
来感受一下目前所能涉及的最复杂的神经网络有多少个超参数:
m i n i − b a t c h , β 1 , β 2 , ε , 神 经 网 络 层 数 , 每 层 隐 藏 单 元 数 , α mini-batch,\beta_1,\beta_2,\varepsilon,神经网络层数,每层隐藏单元数,\alpha mini−batch,β1,β2,ε,神经网络层数,每层隐藏单元数,α,还有可能进行学习率衰减
上面这些参数,哪些比较重要:
α
\alpha
α无疑最重要
其次:
β
隐
藏
单
元
数
m
i
n
i
−
b
a
t
c
h
s
i
z
e
\beta 隐藏单元数 mini-batch size
β隐藏单元数mini−batchsize
其次:
layers
learning rate decay
当用Adam时,一般不调试 β 1 , β 2 , ε \beta_1,\beta_2,\varepsilon β1,β2,ε默认其设置为 β 1 = 0.9 , β 2 = 0.999 , ε = 1 0 − 8 \beta_1=0.9,\beta_2=0.999,\varepsilon=10^{-8} β1=0.9,β2=0.999,ε=10−8
在参数过多
的时候尝试使用随机法
去生成,而不是去进行网格搜索,这可以让你探究更多超参数
的潜在
值
还有另一个
,在给超参数取值时,由粗糙到精细
发现了效果最好
的那个点,然后在其附近
的更小一些的区域,进行随机取值
,直到找到满意的超参点为止
为超参数选择合适的范围
随机取值可以提升搜索效率
随机取值去选择合适的标尺以探究这些超参数
假设在搜索超参数
α
\alpha
α时,其值疑似在0.0001-1之间,若随机均匀取值,则大部分分布在0.1到1之间了,用对数尺度
更合理
所以在以上假设情况就可以这样做:
r = np.random.rand()
a = pow(a,r)
指数加权平均的超参 β \beta β,假设\beta在0.9-0.999之间,(1-\beta)就在0.001-0.1之间了,就可以用上面的方法了。
为什么会有以上的现象呢?因为 β \beta β趋近于1的时候,所得结果的灵敏度会变化。
超参数调试实践
超参数是需要周期性的进行更新的。
搜索超参数的两种不同方式有:
-
每个时间周期观察学习效果,调整超参,这通常是因为没有足够的计算资源采取的措施。
-
另一种方法是同时试验多种模型,然后让它们自己运行,经过一天甚至多天,你会获得以下的学习曲线:
紫色的看起来更好看一些,绿色的下面一条也不错。
最后选择工作效果最好的那一个。
以上就是熊猫方式和鱼子酱方式。
如果拥有足够的计算资源,那么绝对采用鱼子酱方式。
归一化网络的激活函数
batch归一化会让你的参数搜索问题变得更容易,使神经网络对超参数的选择更加稳定。
当训练一个模型的时候,比如logistic回归,归一化会让油条变成一个碗。
那么更深的模型呢?为什么不归一化 α [ 2 ] \alpha^{[2]} α[2],比如在训练 w [ 3 ] , b [ 3 ] w^{[3]},b^{[3]} w[3],b[3]的情况下。
所以我们是否归一化
α
\alpha
α值呢?
这是有一些争论的,但这个课里推荐归一化Z
添加了一个 ε \varepsilon ε的情况,避免分母为0
现在已经将这些z值标准化了,化为含有平均值0和标准单位方差,所以z的每一个分量都含有平均值0和方差1,但不想如此,隐藏单元不同会有意义,所以要做的就是:
z
~
(
i
)
=
γ
z
n
o
r
m
(
i
)
+
β
\widetilde{z}^{(i)}=\gamma z^{(i)}_{norm}+\beta
z
(i)=γznorm(i)+β
当使用momentum或者Adam时,会更新 γ , β \gamma,\beta γ,β,它们的作用是合理设定后,会规范化过程,若设置为 γ = δ 2 + ε , β = μ \gamma = \sqrt{\delta^2+\varepsilon},\beta=\mu γ=δ2+ε,β=μ,那么它就是 z n o r m ( i ) z^{(i)}_{norm} znorm(i),但我们一般会设定为其他的值。
由它们两个控制,均值和方差可以是其他的任何值。
将batch norm 拟合进神经网络
以上可以在单一层进行batch归一化,接下来在深度网络训练中拟合。
一个圆圈内相当于两步
计算:
-
z
-
a = g(z)
-
z = w T + b z = w^T + b z=wT+b
-
z = z − μ δ 2 + ε z = \frac{z-\mu}{\sqrt{\delta^2 + \varepsilon}} z=δ2+εz−μ
-
z ~ ( i ) = γ [ 1 ] z n o r m ( i ) + β [ 1 ] \widetilde{z}^{(i)}=\gamma^{[1]} z^{(i)}_{norm}+\beta^{[1]} z (i)=γ[1]znorm(i)+β[1]
-
a [ 1 ] = g [ 1 ] ( z ~ ( i ) ) a^{[1]}=g^{[1]}(\widetilde{z}^{(i)}) a[1]=g[1](z (i))
接下来就要用 a [ 1 ] 值 计 算 z [ 2 ] a^{[1]}值计算z^{[2]} a[1]值计算z[2],同上面的过程。
所以可见:batch归一化是发生在计算z和a之间的。
更新
β
\beta
β(batch归一化的\beta):
梯度下降法
Momentum或者是Adam
在实践当中,batch归一化通常和mini-batch一起使用。
b
[
l
]
b^{[l]}
b[l]可
以消除
因为:
z
~
[
l
]
]
=
γ
[
l
]
z
n
o
r
m
[
l
]
]
+
β
[
l
]
\widetilde{z}^{[l]]}=\gamma^{[l]} z^{[l]]}_{norm}+\beta^{[l]}
z
[l]]=γ[l]znorm[l]]+β[l]
z
[
l
]
=
W
[
l
]
T
X
+
b
[
l
]
z^{[l]} = W^{[l]T}X+b^{[l]}
z[l]=W[l]TX+b[l]
z
[
l
]
−
μ
δ
2
+
ε
\frac{z^{[l]}-\mu}{\sqrt{\delta^2 + \varepsilon}}
δ2+εz[l]−μ
μ
=
1
m
∑
i
=
1
m
(
z
[
l
]
i
m
b
[
l
]
)
\mu=\frac{1}{m}\sum_{i=1}^m (z^{[l]i} mb^{[l]})
μ=m1∑i=1m(z[l]imb[l])
从下到上代入,最后 b [ l ] b^{[l]} b[l]被消除。
最后:
β
[
l
]
,
γ
[
l
]
\beta^{[l]},\gamma^{[l]}
β[l],γ[l]的维度是:(n^{[l]},1)
最后,你更新这些参数:?[?] = ?[?] − αd?[?],和以前一样,?[?] = ?[?] − ???[?],对于?也是如此?[?] = ?[?] − ???[?]。
Batch norm 为什么奏效
Batch归一化有效的另一个原因是,它可以使权重
比网络更滞后
或者说更深层,比如:第10层的权重更能经受得住变化。
假设已经在左所有黑猫的图像上训练了数据集,那么如果现在把这一网络应用于有色猫,它的表现就不会很好。
就比如说,你在右面训练一个网络,表现已经很好了,那么你不能期待它在右面的表现也很好。
所以想改变数据分布。
有个名字是:“Convariate shift”,试想一个如上图的神经网络,从第三层来看的话,此网络已经学会了 w [ 3 ] , b [ 3 ] , 从 第 三 隐 藏 层 的 角 度 来 看 , w^{[3]},b^{[3]},从第三隐藏层的角度来看, w[3],b[3],从第三隐藏层的角度来看,它从前层取得一些纸,接着如何使输出值 y ^ \hat{y} y^更接近于 y y y呢?
如上图,先遮住左边的部分,第三层得到了一些值:
a
1
[
2
]
,
a
2
[
2
]
,
a
3
[
2
]
,
a
4
[
2
]
a^{[2]}_1,a^{[2]}_2,a^{[2]}_3,a^{[2]}_4
a1[2],a2[2],a3[2],a4[2],学习了后面的w和b,然后映射到
y
^
\hat{y}
y^
如上图,把前面漏出来,还有前面部分相应的w和b,那么就有一种情况,前面的w和b改变了,那么
a
[
2
]
a^{[2]}
a[2]就改变了,那么第三层的输入也就变了,所以就有了“Convariate shift"的问题,Batch归一化的作用就是减少
这些隐藏值分布变化的数量
Batch归一化下, z 1 [ 2 ] , z 2 [ 2 ] z^{[2]}_1,z^{[2]}_2 z1[2],z2[2]可以改变,但它的分布一定是在由 β [ 2 ] , γ [ 2 ] \beta^{[2]},\gamma^{[2]} β[2],γ[2]所决定的一个范围内。
也就减少了输入值改变的问题。
Batch归一化还有轻微的正则化作用
。
因为在mini-batch的情况下,它计算的是一个划分部分的均值和方差,所以有一些小的噪声。那么后部单元就不会过分依赖于任何一个单元。
但不要把batch当做是正则化。
##测试Batch norm
Batch归一化将数据以mini-batch的形式逐一处理,但在测试时,可能需要对每个样本逐一处理。
在l层,假设我们有mini-batch: X { 1 } , X { 2 } , . . . X^{\{1\}},X^{\{2\}},... X{1},X{2},...,那么当训练第一个mini-batch和这一层的 μ \mu μ( μ [ l ] → μ [ l ] { 1 } \mu^{[l]}\rightarrow{\mu^{[l]\{1\}}} μ[l]→μ[l]{1})
第二个mini-batch同理就是: μ \mu μ( μ [ l ] → μ [ l ] { 2 } \mu^{[l]}\rightarrow{\mu^{[l]\{2\}}} μ[l]→μ[l]{2})
以此类推,然后对所有的 μ \mu μ进行指数加权平均(移动平均值)
最后在测试时,只需要用z值来计算 z n o r m ( i ) z^{(i)}_{norm} znorm(i),用 μ , δ 2 \mu,\delta^2 μ,δ2的指数加权平均(在训练过程中所得到的 μ , δ 2 \mu,\delta^2 μ,δ2的指数加权平均值)
Softmax回归
如果有多种可能的类型的话:logistic回归的一般形式,就是softmax回归
在这个例子中,将建立一个神经网络,其输出层有4个,或者说C个输出单元,想要输出层单元的数字显示出这4种类型中每个的概率有多大
最后的输出 y ^ \hat{y} y^在这里也就是一个 4 × 1 4\times{1} 4×1维的向量。向量中的四个值加在一起应该为1。
z
[
l
]
z^{[l]}
z[l]是最后一层的z变量:
z
[
L
]
=
W
[
L
]
a
[
L
−
1
]
+
b
[
L
]
z^{[L]}=W^{[L]}a^{[L-1]}+b^{[L]}
z[L]=W[L]a[L−1]+b[L],计算出z之后,需要应用softmax激活函数
,这个激活函数对于softmax层而言有一些不同:
Activation Function:
t
=
e
(
z
l
)
t = e^{(z^{l})}
t=e(zl) 对所有元素求幂
KaTeX parse error: Expected '}', got 'EOF' at end of input: …sum_{j=1}^4 t_i
t,a,z都是一个KaTeX parse error: Expected 'EOF', got '}' at position 11: 4\times{1}}̲维矩阵。
与Relu和tanh等激活函数不同,这里的softmax接收的是一个向量
假设有一个没有隐藏层的神经网络,就是计算 z [ 1 ] = W [ 1 ] X + b [ 1 ] z^{[1]}=W^{[1]}X+b^{[1]} z[1]=W[1]X+b[1],而输出 a [ 1 ] a^{[1]} a[1]
一个C=3个输出分类的softmax层能够产生以上的决策边界。
若网络层数更深呢?就可以产生许多非线性的决策边界来区分更多种类了。
训练一个softmax分类器
C=2,实际上将简化成logistic回归
用怎么样的损失函数来训练softmax神经网络
L ( y ^ , y ) = − ∑ j = 1 4 y j l o g y ^ j L(\hat{y},y)=-\sum_{j=1}^4 y_jlog\hat{y}_j L(y^,y)=−∑j=14yjlogy^j
J ( W l , b l , . . . ) = 1 m ∑ i = 1 m L ( y ( i ) ^ , y ( i ) ) J(W^{l},b^{l},...)=\frac{1}{m}\sum_{i=1}^m L(\hat{y^{(i)}},y^{(i)}) J(Wl,bl,...)=m1∑i=1mL(y(i)^,y(i))
Tensorflow
- TensorFlow重载了常见的运算,可以直接用数学符号书写
- 使用梯度下降
train = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost_function)
- 打开一个TensorFlow会话
session = tf.Session()
- 全局的初始化
init = tf.global_variables_initializer()
- 之后会赋值的变量,这是把训练数据导入代价函数比较好用的方法
x = tf.placeholder(tf.float32,[3,1])#之后会赋值的变量
- 把训练数据喂给x
session.run(train,feed_dict={x:cofficients})