深度学习符号字典:http://www.ai-start.com/dl2017/html/notation.html
文章目录
第一章节:最简单的神经网络
该神经网络的输入x是房屋的面积,输出y是房屋的价格,中间的神经元根据输入x做线性运算,取一个不小于0的值作为输出y。这样,神经网络就实现了预测房价的功能。
ReLU函数(rectified linear unit),全称是“修正线性单元”,修正指的是取不小于0的值。
监督式学习和非监督式学习的本质区别在于是否已知训练样本的输出y。
输入数据的类型一般有两种:Structured Data和Unstructured Data。
逻辑回归问题一般用来解决二分类(Binary Classification)问题。二分类就是输出y只有(0,1)连个离散值。输出1为对象存在,输出0则表示对象不存在。
逻辑回归Logistic Regression
使用逻辑回归解决二分类问题时,预测值
表示为1的概率,取值在[0,1]之间,这是与二分类模型不同的地方。逻辑回归中,通常使用线性模型,引入参数w和b,逻辑回归的线性预测输出可以写成:
上式的线性输出区间是整个实数范围,而逻辑回归要求的输出在[0,1]之间,所以我们还需要对上式的线性输出函数进行处理,处理方法是引入Sigmoid函数,把输出限定在[0,1]之间。Sigmoid函数的表达式和曲线为:
这样,逻辑回归的输出表示为:
这里一般会习惯性的令z=w^T+b
逻辑回归代价函数
由于w和b是未知参数,通过反复训练优化才能得到,所以需要定义一个包含w和b的cost function,通过优化cost function,使其取值最小,得到相应的w和b。一般用平方错误(squared error)来衡量,但是平方错误衡量的损失函数一般是非凸的的,在使用梯度下降算法时,容易得到局部的最小值,但在逻辑回归中的优化目标是全局最优化,所以应当选择为凸的损失函数,构建为:
上式对应的loss function针对的是单个样本,而对于m个样本,cost function是m个样本的loss function的平均值,表达式为:
梯度下降法
对于m个样本,cost function函数J(w,b)是凸函数,梯度下降法的求取方法是选取一组w,b,然后在每次迭代的过程中分别沿w和b的梯度的反方向前进一步,不断改进w和b的值,直到(w,b)达到最小。w和b的表达式为:
其中 α为学习因子,表示梯度下降的步进长度, α 越大,w和b的变化率就越大
推导导数:
已知:
z
=
w
T
x
+
b
z=w^{T} x+b
z=wTx+b
y ^ = a = σ ( z ) = 1 1 + e − z \hat{y}=a=\sigma(z)=\frac{1}{1+e^{-z}} y^=a=σ(z)=1+e−z1
L ( a , y ) = − ( y log ( a ) + ( 1 − y ) log ( 1 − a ) ) \mathcal{L}(a, y)=-(y \log (a)+(1-y) \log (1-a)) L(a,y)=−(ylog(a)+(1−y)log(1−a))
那么:
d L ( a , y ) d a = − y / a + ( 1 − y ) / ( 1 − a ) \frac{d L(a, y)}{d a}=-y / a+(1-y) /(1-a) dadL(a,y)=−y/a+(1−y)/(1−a)
d a d z = a ⋅ ( 1 − a ) \frac{d a}{d z}=a \cdot(1-a) dzda=a⋅(1−a)(其中 d d z g ( z ) = 1 1 + e − z ( 1 − 1 1 + e − z ) = g ( z ) ( 1 − g ( z ) ) \frac{d}{d z} g(z)=\frac{1}{1+e^{-z}}\left(1-\frac{1}{1+e^{-z}}\right)=g(z)(1-g(z)) dzdg(z)=1+e−z1(1−1+e−z1)=g(z)(1−g(z)))
d z = d L ( a , y ) d z = d L d z = ( d L d a ) ⋅ ( d a d z ) = ( − y a + ( 1 − y ) ( 1 − a ) ) ⋅ a ( 1 − a ) = a − y d z=\frac{d L(a, y)}{d z}=\frac{d L}{d z}=\left(\frac{d L}{d a}\right) \cdot\left(\frac{d a}{d z}\right)=\left(-\frac{y}{a}+\frac{(1-y)}{(1-a)}\right) \cdot a(1-a)=a-y dz=dzdL(a,y)=dzdL=(dadL)⋅(dzda)=(−ay+(1−a)(1−y))⋅a(1−a)=a−y
∂ L ∂ w 1 = x 1 ⋅ d z \frac{\partial L}{\partial w_{1}}=x_{1} \cdot d z ∂w1∂L=x1⋅dz
d b = d z d b=d z db=dz
浅层神经网络
规定:使用符号[m]表示第m层网络中节点相关的数,这些节点的集合被称为第m层网络。与之前用来表示第i个的训练样本的(i)相区分
输入层是第0层,不算入总的层数。所以上图的神经网络为2层
对应到公式就是:
对于反向传播:
对于第一层隐藏层而言,
W
W
W是一个4x3的矩阵,而
b
b
b是一个4x1的向量,第一个数字4源自于我们有四个结点或隐藏层单元,然后数字3源自于这里有三个输入特征。相似的输出层也有一些与之关联的
W
W
W[2]参数以及
b
b
b[2]。从维数上来看,它们的规模分别是1x4以及1x1。1x4是因为隐藏层有四个隐藏层单元而输出层只有一个单元。
激活函数
快速概括一下不同激活函数的过程和结论。
sigmoid激活函数:
g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z}} g(z)=1+e−z1
d d z g ( z ) = 1 1 + e − z ( 1 − 1 1 + e − z ) = g ( z ) ( 1 − g ( z ) ) \frac{d}{d z} g(z)=\frac{1}{1+e^{-z}}\left(1-\frac{1}{1+e^{-z}}\right)=g(z)(1-g(z)) dzdg(z)=1+e−z1(1−1+e−z1)=g(z)(1−g(z))
除了输出层是一个二分类问题基本不会用它。
tanh激活函数:
g ( z ) = tanh ( z ) = e z − e − z e z + e − z g(z)=\tanh (z)=\frac{e^{z}-e^{-z}}{e^{z}+e^{-z}} g(z)=tanh(z)=ez+e−zez−e−z
d d z g ( z ) = 1 − ( tanh ( z ) ) 2 \frac{d}{d z} g(z)=1-(\tanh (z))^{2} dzdg(z)=1−(tanh(z))2
tanh是非常优秀的,几乎适合所有场合。
ReLu激活函数:最常用的默认函数,如果不确定用哪个激活函数,就使用ReLu或者Leaky ReLu
神经网络的梯度下降
propagation : ( 1 ) z [ 1 ] = W [ 1 ] x + b [ 1 ] :(1) z^{[1]}=W^{[1]} x+b^{[1]} :(1)z[1]=W[1]x+b[1] (2) a [ 1 ] = σ ( z [ 1 ] ) a^{[1]}=\sigma\left(z^{[1]}\right) a[1]=σ(z[1]) (3) z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]}=W^{[2]} a^{[1]}+b^{[2]} z[2]=W[2]a[1]+b[2] (4) a [ 2 ] = g [ 2 ] ( z [ z ] ) = σ ( z [ 2 ] ) a^{[2]}=g^{[2]}\left(z^{[z]}\right)=\sigma\left(z^{[2]}\right) a[2]=g[2](z[z])=σ(z[2])
back propagation:
d
z
[
2
]
=
A
[
2
]
−
Y
,
Y
=
[
y
[
1
]
y
[
2
]
⋯
y
[
m
]
]
d z^{[2]}=A^{[2]}-Y, Y=\left[\begin{array}{llll}y^{[1]} & y^{[2]} & \cdots & y^{[m]}\end{array}\right]
dz[2]=A[2]−Y,Y=[y[1]y[2]⋯y[m]]
d
W
[
2
]
=
1
m
d
z
[
2
]
A
[
1
]
T
d W^{[2]}=\frac{1}{m} d z^{[2]} A^{[1] T}
dW[2]=m1dz[2]A[1]T
d
b
[
2
]
=
1
m
n
p
.
sum
(
d
z
[
2
]
,
axis
=
1
,
keepdims
=
True
)
\mathrm{d} b^{[2]}=\frac{1}{m} n p . \operatorname{sum}\left(d z^{[2]}, \text {axis}=1, \text {keepdims}=\text {True}\right)
db[2]=m1np.sum(dz[2],axis=1,keepdims=True)
d
z
[
1
]
=
W
[
2
]
T
d
z
[
2
]
⏟
(
n
[
1
]
,
m
)
∗
g
[
1
]
⏟
activation function of hidden layer
∗
(
z
[
1
]
)
⏟
(
n
[
1
]
,
m
)
d z^{[1]}=\underbrace{W^{[2] T} \mathrm{d} z^{[2]}}_{\left(n^{[1]}, m\right)} * \underbrace{g^{[1]}}_{\text {activation function of hidden layer}} * \underbrace{\left(z^{[1]}\right)}_{\left(n^{[1]}, m\right)}
dz[1]=(n[1],m)
W[2]Tdz[2]∗activation function of hidden layer
g[1]∗(n[1],m)
(z[1])
d W [ 1 ] = 1 m d z [ 1 ] x T d W^{[1]}=\frac{1}{m} d z^{[1]} x^{T} dW[1]=m1dz[1]xT
d b [ 1 ] ⏟ ( n 11 , 1 ) = 1 m n p . sum ( d z [ 1 ] , axis = 1 , keepdims = True ) \underbrace{d b^{[1]}}_{\left(n^{11}, 1\right)}=\frac{1}{m} n p . \operatorname{sum}\left(d z^{[1]}, \text {axis}=1, \text {keepdims}=\text {True}\right) (n11,1) db[1]=m1np.sum(dz[1],axis=1,keepdims=True)
这里np.sum是python的numpy命令,axis=1表示水平相加求和,keepdims是防止python输出那些古怪的秩数
训练参数需要做梯度下降,在训练神经网络的时候,随机初始化参数很重要,而不是初始化成全零
随机初始化
对于一个神经网络,如果你把权重或者参数都初始化为0,那么梯度下降将不会起作用。
搭建神经网络块
神经网络的一步训练包含了,从a
[
0
]
^{[0]}
[0] 开始, 也就是
x
x
x 然后经过一系列正向传播计算得到
y
^
,
\hat{y},
y^, 之后再用输出值计算这 个 (第二行最后方块),再实现反向传播。现在你就有所有的导数项了,W也会在每一层被更新为
W
=
W
−
α
d
W
,
b
W=W-\alpha d W, \quad b
W=W−αdW,b 也一样,
b
=
b
−
α
d
b
,
\quad b=b-\alpha d b,
b=b−αdb, 反向传播就都计算完毕, 我们有所有的导数值,那么这是神经网络一 个梯度下降循环。
继续下去之前再补充一个细节,概念上会非常有帮助,那就是把反向函数计算出来的z值缓存下来。当你做编程练习中你缓存了 z , z, z, 还有W和b对吧? 从实现角度上看, 我认为是一个很方便的方法, 可以将参数复制到你在计算反 向传播时所需要的地方。
第二章节:偏差,方差
第一个例子中:训练集误差为1%,验证集误差为16%。我们可能过度拟合了训练集,这种情况称 为“高方差”。
第二个例子中:训练集误差为15%,验证集误差为16%。算法并没有在训练集得到很好的训练,就是数据欠拟合,算法偏差较高。而验证集结果合理,低方差。
第三个例子中:训练集误差15%,偏差较高。验证集错误高达30%,高方差。
第四个例子中:低方差,低偏差
通过查看训练集误差,我们可以判断数据拟合情况,判断是否有偏差问题。从训练集到验证集的过程中,我们可以判断方差是否过高。
偏差高:选择新的网络,比如含有更多隐藏层或者隐藏单元的网络,或者花费更多时间来训练,或者尝试更先进的算法。
方差高:采用更多的数据,正则化
正则化
λ
2
m
\frac{\lambda}{2 m}
2mλ 乘以
w
w
w 范数的平方,
w
w
w欧 几 里 德 范 数 的 平 方 等 于
w
j
w_{j}
wj (
j
j
j 值从1到
n
x
n_{x}
nx ) 平方的和, 也可表示为
w
T
w
,
w^{T} w,
wTw, 也就是向量参数
w
w
w的欧几里德范数(2范数)的平方,此方法称为L2正则化。因为这里用了欧几里德法线, 被称为向量参数w的 L2范数。
λ
\lambda
λ是正则化参数,我们通常使用验证集或交叉验证集来配置这个参数,要考虑训练集之间的权衡,把参数设置为较小值,这样可以避免过拟合,所以λ是另外一个需要调整的超级参数.
在Python编程语言中, λ \lambda λ是一个保留字段,编写代码时,我写成lambd,以免与Python中的保留字段冲突
神经网络含有一个成本函数, 该函数包含
W
[
1
]
,
b
[
1
]
W^{[1]}, \quad b^{[1]}
W[1],b[1] 到
W
[
l
]
,
b
[
l
]
W^{[l]}, \quad b^{[l]}
W[l],b[l] 所有参数, 字母
L
L
L 是神经网络所含的层数, 因此成 本函数等于m个训练样本损失函数的总和乘以
1
m
,
\frac{1}{m},
m1, 正则项为
λ
2
m
∑
1
L
∣
W
[
l
]
∣
2
,
\frac{\lambda}{2 m} \sum_{1}^{L}\left|W^{[l]}\right|^{2},
2mλ∑1L∣∣W[l]∣∣2, 我们称 ||
W
[
l
]
∣
∣
2
W^{[l]}||^{2}
W[l]∣∣2 为范数平方, 这个矩阵范数||
W
[
l
]
∥
2
(
W^{[l]} \|^{2}(
W[l]∥2( 即平方范数
)
,
),
), 被定义为矩阵中所有元素的平方求和,
我们看下求和公式的具体参数, 第一个求和符号其值
i
i
i从1到
n
[
l
−
1
]
,
n^{[l-1]},
n[l−1], 第二个其J值从1到
n
[
l
]
,
n^{[l]},
n[l], 因为W是一个
n
[
l
]
×
n
[
l
−
1
]
n^{[l]} \times n^{[l-1]}
n[l]×n[l−1] 的多维矩阵,
n
[
l
]
n^{[l]}
n[l] 表示
l
l
l 层单元的数量,
n
[
l
−
1
]
n^{[l-1]}
n[l−1] 表示第
l
−
1
l-1
l−1 层隐藏单元的数量。
如何使用该范数实现梯度下降:
我们要做的就是给dW加上这一项
λ
m
\frac{\lambda}{m}
mλ
W
[
l
]
W^{[l]}
W[l] 然后计算这个更新项, 使用新定义的
d
W
[
l
]
,
d W^{[l]},
dW[l], 它的定义含有相关参数代价函数导数和, 以及最后添加的额外正则项, 这也是L2正则化有时被称为“权重衰减"的原因。
我们用d
W
[
l
]
W^{[l]}
W[l] 的定义替换此处的
d
W
[
l
]
,
d W^{[l]},
dW[l], 可以看到,
W
[
l
]
W^{[l]}
W[l] 的定义被更新为
W
[
l
]
W^{[l]}
W[l] 减去学习率
a
a
a 乘以backprop 再加上
λ
m
W
[
l
]
\frac{\lambda}{m} W^{[l]}
mλW[l]
该正则项说明, 不论
W
[
l
]
W^{[l]}
W[l]是什么, 我们都试图让它变得更小, 实际上, 相当于我们给矩阵W乘以(
1
−
a
λ
m
1-a \frac{\lambda}{m}
1−amλ )倍的权 重, 矩阵W减去
α
λ
m
\alpha \frac{\lambda}{m}
αmλ 倍的它, 也就是用这个系数
(
1
−
a
λ
m
)
\left(1-a \frac{\lambda}{m}\right)
(1−amλ) 乘以矩阵
W
,
W,
W, 该系数小于1,因此L2范数正则化也被称 为“权重衰减"
dropout 正则化
除了正则化,还有一个非常实用的正则化方法——“Dropout(随机失活)”
dropout会遍历网络的每一层,并设置消除神经网络中节点的概率。假设网络中的每一层,每个节点都以抛硬币的方式设置概率,每个节点得以保留和消除的概率都是0.5,设置完节点概率,我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,然后用backprop方法进行训练
为了预防矩阵的过拟合,对于权重矩阵较大的层,keep-prob值应该相对较低。对于其它层,过拟合的程度可能没那么严重,它们的keep-prob值可能高一些。有点像在处理L2正则化的正则化参数
λ
\lambda
λ,我们尝试对某些层施行更多正则化
目前实施dropout最常用的方法就是Inverted dropout
dropout一大缺点就是代价函数不再被明确定义,每次迭代,都会随机移除一些节点,定义明确的代价函数每次迭代后都会下降,因为我们所优化的代价函数实际上并没有明确定义,或者说在某种程度上很难计算,所以我们失去了调试工具来绘制这样的图片。我通常会关闭dropout函数,将keep-prob的值设为1,运行代码,确保J函数单调递减。然后打开dropout函数。
训练的时候dropout的作用就是通过引入噪声,防止模型过拟合。所以其实测试的时候是不能关闭dropout的(关闭的话训练的模型和测试的模型就不同了)。
但是多次采样会带来较大的计算开销。这时我们假设平均参数(关闭dropout)得到的模型的预测值近似等于上面说的多次采样的平均值。所以这个时候就有了训练开dropout,预测时关闭的做法
其他正则化方法
一.数据扩增
水平翻转,裁剪,扭曲。
二.early stopping
运行梯度下降时,我们可以绘制训练误差,或只绘制代价函数J的优化过程,在训练集上用0-1记录分类误差次数。呈单调下降趋势。
还可以绘制验证集误差,它可以是验证集上的分类误差,或验证集上的代价函数,逻辑损失和对数损失等,你会发现,验证集误差通常会先呈下降趋势,然后在某个节点处开始上升。
early stopping代表提早停止训练神经网络。可以获得一个较低的验证机误差和训练误差,以及一个
w
w
w值中等大小的弗罗贝尼乌斯范数
early stopping的主要缺点就是你不能独立地处理这两个问题,因为提早停止梯度下降,也就是停止了优化代价函数
Early stopping的优点是,只运行一次梯度下降,你可以找出
w
w
w的较小值,中间值和较大值,而无需尝试
L
2
L2
L2正则化超级参数的很多值。
归一化(正则化)输入
训练神经网络,其中一个加速训练的方法就是归一化输入。假设一个训练集有两个特征,输入特征为2维,归一化需要两个步骤:
1.零均值
2.归一化方差;
目的就是让代价函数更快的优化
神经网络的权重初始化
针对深度神经网络的梯度消失和爆炸问题,我们需要设置权重矩阵。
优化算法
Mini-batch 梯度下降
当深度学习的训练集样本数非常大时,可以将训练集分割为小的子集训练,这些子集被称为mini-batch。
我们使用
{
t
}
^{\{t\}}
{t}来表示mini-batch的序数。
把mini-batch大小设为m可以得到batch梯度下降法。
把mini-batch大小为1,就有了新的算法,叫做随机梯度下降法。
在实践中最好选择不大不小的mini-batch尺寸,你会发现两个好处,一方面,你得到了大量向量化,比你一次性处理多个样本快得多。另一方面,你不需要等待整个训练集被处理完就可以开始进行后续工作。
一般少于2000个样本,比较适合batch梯度下降法。样本数目较大时,一般的mini-batch大小为64~512,取2的n次方
指数加权平均数
关键方程:
v
t
=
β
v
t
−
1
+
(
1
−
β
)
θ
t
v_{t}=\beta v_{t-1}+(1-\beta) \theta_{t}
vt=βvt−1+(1−β)θt
在计算时可视
v
t
v_{t}
vt 大概是
1
(
1
−
β
)
\frac{1}{(1-\beta)}
(1−β)1 的每日温度
β
\beta
β=0.9的时候,得到的结果是红线,如果它更接近于1,比如0.98,结果就是绿线,如果
β
\beta
β小一点,如果是0.5,结果就是黄线。
计算移动平均数的时候, 初始化
v
0
=
0
,
v
1
=
0.98
v
0
+
0.02
θ
1
,
v_{0}=0, \quad v_{1}=0.98 v_{0}+0.02 \theta_{1},
v0=0,v1=0.98v0+0.02θ1, 但是
v
0
=
0
,
v_{0}=0,
v0=0, 所以这部分没有了 (
0.98
v
0
0.98 v_{0}
0.98v0 ) , 所以
v
1
=
0.02
θ
1
v_{1}=0.02 \theta_{1}
v1=0.02θ1, 所以如果一天温度是40华氏度, 那么
v
1
=
0.02
θ
1
=
0.02
×
40
=
8
,
v_{1}=0.02 \theta_{1}=0.02 \times 40=8,
v1=0.02θ1=0.02×40=8, 因 此得到的值会小很多,所以第一天温度的估测不准。
v
2
=
0.98
v
1
+
0.02
θ
2
,
v_{2}=0.98 v_{1}+0.02 \theta_{2},
v2=0.98v1+0.02θ2, 如果代入
v
1
,
v_{1},
v1, 然后相乘,所以
v
2
=
0.98
×
0.02
θ
1
+
0.02
θ
2
=
0.0196
θ
1
+
0.02
θ
2
,
v_{2}=0.98 \times 0.02 \theta_{1}+0.02 \theta_{2}=0.0196 \theta_{1}+0.02 \theta_{2},
v2=0.98×0.02θ1+0.02θ2=0.0196θ1+0.02θ2, 假设
θ
1
\theta_{1}
θ1 和
θ
2
\theta_{2}
θ2 都是正数,
\quad
计算后
v
2
v_{2}
v2 要远小于
θ
1
\theta_{1}
θ1 和
θ
2
\theta_{2}
θ2
所以v_不能很好估测出这一年前两天的温度。。
有个办法可以修改这一估测,让估测变得更好,更准确,特别是在估测初期,也就是不用v
t
,
_{t},
t, 而是用
v
t
1
−
β
t
,
\frac{v_{t}}{1-\beta^{t}},
1−βtvt, t就是现在的天数。举个具体例子,
\quad
当
t
=
2
t=2
t=2 时,
1
−
β
t
=
1
−
0.9
8
2
=
0.0396
,
1-\beta^{t}=1-0.98^{2}=0.0396,
1−βt=1−0.982=0.0396, 因此对第二天温 度的估测变成了
v
2
0.0396
=
0.0196
θ
1
+
0.02
θ
2
0.0396
,
\frac{v_{2}}{0.0396}=\frac{0.0196 \theta_{1}+0.02 \theta_{2}}{0.0396},
0.0396v2=0.03960.0196θ1+0.02θ2, 也就是
θ
1
\theta_{1}
θ1 和
θ
2
\theta_{2}
θ2 的加权平均数, 并去除了偏差。
动量梯度下降法
还有一种算法叫做Momentum,或者叫做动量梯度下降法,运行速度几乎总是快于标准的梯度下降算法,基本的想法就是计算梯度的指数加权平均数,并利用该梯度更新你的权重
相比较与梯度下降方法,在纵轴上,你希望学习慢一点,因为你不想要这些摆动,但是在横轴上,你希望加快学习,你希望快速从左向右移,移向最小值,移向红点。
你要做的是计算
v
d
W
=
β
v
d
W
+
(
1
−
β
)
d
W
v_{d W}=\beta v_{d W}+(1-\beta) d W
vdW=βvdW+(1−β)dW, 这跟我们之前的计算相似, 也就是
v
=
β
v
+
(
1
β
)
θ
t
,
d
W
v=\beta v+(1\beta) \theta_{t}, \quad d W
v=βv+(1β)θt,dW 的移动平均数, 接着同样地计算
v
d
b
,
v
d
b
=
β
v
d
b
+
(
1
−
β
)
d
b
,
v_{d b}, \quad v_{d b}=\beta v_{d b}+(1-\beta) d b,
vdb,vdb=βvdb+(1−β)db, 然后重新赋值权重,
W
:
=
W
−
a
v
d
W
,
W:=W-a v_{d W},
W:=W−avdW, 同样
b
:
=
b
−
a
v
d
b
,
b:=b-a v_{d b},
b:=b−avdb, 这样就可以减缓梯度下降的幅度。
在上几个导数中,你会发现这些纵轴上的摆动平均值接近于零,所以在纵轴方向,你希望放慢一点,平均过程中,正负数相互抵消,所以平均值接近于零。但在横轴方向,所有的微分都指向横轴方向,因此横轴方向的平均值仍然较大,因此用算法几次迭代后,你发现动量梯度下降法,最终纵轴方向的摆动变小了,横轴方向运动更快
RMSprop
全称是root mean square prop算法,它也可以加速梯度下降.
在第t次迭代中,该算法会照常计算当下mini-batch的微分
d
W
,
d
b
,
d W, d b,
dW,db, 所以我会保留这个指数加权平均 我们用到新符号
S
d
W
,
S_{d W},
SdW, 而不是
v
d
W
,
v_{d W},
vdW, 因此
S
d
W
=
β
S
d
W
+
(
1
−
β
)
d
W
2
,
S_{d W}=\beta S_{d W}+(1-\beta) d W^{2},
SdW=βSdW+(1−β)dW2, 澄清一下,这个平方的操 作是针对这一整个符号的, 这样做能够保留微分平方的加权平均数, 同样
S
d
b
=
β
S
d
b
+
(
1
−
β
)
d
b
2
S_{d b}=\beta S_{d b}+(1-\beta) d b^{2}
Sdb=βSdb+(1−β)db2 再说一次,平方是针对整个符号的操作。
接着RMSprop会这样更新参数值,
W
:
=
W
−
a
d
W
S
d
W
,
b
:
=
b
−
α
d
b
S
d
b
,
W:=W-a \frac{d W}{\sqrt{S_{d W}}}, \quad b:=b-\alpha \frac{d b}{\sqrt{S_{d b}}},
W:=W−aSdWdW,b:=b−αSdbdb, 我们来理解一下其原理。记得在横轴方向或者在例子中的W方向,我们希望学习速度快,而在垂直方向,也就是例子中的b方向, 我们希望减缓纵轴上的摆动, 所以有了
S
d
W
S_{d W}
SdW 和
S
d
b
S_{d b}
Sdb, 我们希望
S
d
W
S_{d W}
SdW 会相对较小,所以我们要除以一个较小的数, 而希望
S
d
b
S_{d b}
Sdb 又较大, 所以这里我们要除以较大的数字, 这样就可以减缓纵轴上的变化。
Adam 优化算法
Adam优化算法基本上就是将Momentum和RMSprop结合在一起。
使用Adam算法, 首先你要初始化,
v
d
W
=
0
,
S
d
W
=
0
,
v
d
b
=
0
,
S
d
b
=
0
,
v_{d W}=0, S_{d W}=0, v_{d b}=0, S_{d b}=0,
vdW=0,SdW=0,vdb=0,Sdb=0, 在第t次迭代中, 你要计算微分, 用当前的mini-batch计算dW,db。接下来计算Momentum指数加权平均数, 所以
v
d
W
=
β
1
v
d
W
+
(
1
−
β
1
)
d
W
v_{d W}=\beta_{1} v_{d W}+\left(1-\beta_{1}\right) d W \quad
vdW=β1vdW+(1−β1)dW (使用
β
1
,
\beta_{1},
β1, 这样就不会跟超参数
β
2
\beta_{2}
β2 混淆, 因为后面RMSprop要用到
β
2
\beta_{2}
β2 ) 使用Momentum时我们肯定会用这个公式, 但现在不叫它
β
,
\beta,
β, 而叫它 $\beta_{1} $ 同样
v
d
b
=
β
1
v
d
b
+
(
1
−
β
1
)
d
b
v_{d b}=\beta_{1} v_{d b}+\left(1-\beta_{1}\right) d b_{}
vdb=β1vdb+(1−β1)db。
接着你用RMSprop进行更新, 即用不同的超参数
β
2
,
S
d
W
=
β
2
S
d
W
+
(
1
−
β
2
)
(
d
W
)
2
,
\beta_{2}, \quad S_{d W}=\beta_{2} S_{d W}+\left(1-\beta_{2}\right)(d W)^{2},
β2,SdW=β2SdW+(1−β2)(dW)2, 再说一次, 这里是对整 个微分
d
W
d W
dW 进行平方处理,
S
d
b
=
β
2
S
d
b
+
(
1
−
β
2
)
(
d
b
)
2
S_{d b}=\beta_{2} S_{d b}+\left(1-\beta_{2}\right)(d b)^{2}
Sdb=β2Sdb+(1−β2)(db)2。
相当于Momentum更新了超参数
β
1
,
\beta_{1}, \quad
β1, RMSprop更新了超参数 $\beta_{2} $ 一般使用Adam算法的时候, 要计算偏差修 正,
v
d
W
corrected
,
v_{d W}^{\text {corrected }},
vdWcorrected , 修正也就是在偏差修正之后,
v
d
W
corrected
=
v
d
W
1
−
β
1
t
v_{d W}^{\text {corrected }}=\frac{v_{d W}}{1-\beta_{1}^{t}}
vdWcorrected =1−β1tvdW
同样
v
d
b
corrected
=
v
d
b
1
−
β
1
t
v_{d b}^{\text {corrected }}=\frac{v_{d b}}{1-\beta_{1}^{t}}
vdbcorrected =1−β1tvdb
S
S
S 也使用偏差修正,
,
,
, 也就是
S
d
W
corrected
=
S
d
W
1
−
β
2
β
,
S
d
b
corrected
=
S
d
b
1
−
β
2
′
S_{d W}^{\text {corrected }}=\frac{S_{d W}}{1-\beta_{2}^{\beta}}, \quad S_{d b}^{\text {corrected }}=\frac{S_{d b}}{1-\beta_{2}^{\prime}}
SdWcorrected =1−β2βSdW,Sdbcorrected =1−β2′Sdb
最后更新权重, 所以W更新后是
W
:
=
W
−
a
v
d
W
corrected
S
d
W
corrected
+
ε
W:=W-\frac{a v_{d W}^{\text {corrected }}}{\sqrt{S_{d W}^{\text {corrected }}+\varepsilon}}
W:=W−SdWcorrected +εavdWcorrected (如果你只是用Momentum, 使用
v
d
W
v_{d W}
vdW 或者修正后的
v
d
W
,
v_{d W},
vdW, 但现在我们加入了RMSprop的部分,所以我们要除以修正后
S
d
W
S_{d W}
SdW 的平 方根加上
ε
)
\varepsilon)
ε) 。
根据类似的公式更新b值,
b
:
=
b
−
α
v
d
t
correted
S
d
b
corrected
+
ε
b:=b-\frac{\alpha v_{\mathrm{dt}}^{\text {correted }}}{\sqrt{S_{\mathrm{db}}^{\text {corrected }}}+\varepsilon}
b:=b−Sdbcorrected +εαvdtcorreted
第四章节:卷积神经网络
边缘检测
最常检测的图片边缘有两种:垂直边缘和水平边缘。图片的边缘检测可以通过使用相应的滤波器来实现。以垂直边缘为例:
在卷积过程中,是可以同时进行垂直和水平等方向的检测,只需要在网络中加入相应的滤波器即可,有几个滤波器便有几个通道的输出。
Padding
按上述方法对图片卷积,如果原始尺寸为n*n,滤波器尺寸为f*f,则卷积后得到的图片尺寸为(n-f+1)*(n-f+1)。这样会导致两个问题:卷积后输出图片尺寸变小和原始图片的边缘信息丢失。为了解决这两个问题,使用Padding方法,扩展原始图片的尺寸,扩展的区域全部补零,补零的目的是为了不影响原始图片的数据。假设扩展的尺寸为p,则原始图片的尺寸为(n+2p)*(n+2p),卷积后的输出图片尺寸为(n+2p-f+1)*(n+2p-f+1),为了保证图片尺寸不变,只需要保证
若没有Padding操作,p=0,称之为“Valid convolution”;有Padding操作,称之为“Same convolution”。
卷积步长
在上述卷积过程中,我们都默认卷积的步长为1,即滤波器在原图片中的水平方向和垂直方向每次步进的长度为1,。而实际应用中,卷积的步长是可以改变的,记为s。此时输出图片的尺寸就变为
其中表示向下取整。
池化层
在卷积神经网络中应用池化层的目的是减小尺寸,提高运算速度,同时还能减小噪声影响。相比于卷积层,池化层的做法比卷积层更简单,仅在滤波器算子滑动区域内取最大值,即max pooling最大池化。如下图所示:
最大池化的好处在于只保留了区域内的最大值,降低噪声影响,提高了模型的健壮性。同时,由于最大池化只需要考虑滤波器尺寸f和滤波器步进长度s两个超参数,计算量会小很多.最大池化的输出结果为\left\lfloor\frac{n_{H}+2p-f}{s}+1\right\rfloor \times\left\lfloor\frac{n_{w}+2p-f}{s}+1\right\rfloor \times n_{c}$。你可以使用池化层减少
n
H
,
n
W
n_{H},n_{W}
nH,nW,但是不能减少
n
C
n_{C}
nC。
另一种池化方法为average pooling,即平均池化,也就是计算区域内的平均值。在实际应用中,max pooling更为常见。
全连接层
全连接的意思为输出层的神经元和输入层的每个神经元都连接。全连接层的作用是将二维的图像特征转换为一维向量,方便交给分类器和逻辑回归使用。
目标定位
如果你正在构建汽车自动驾驶系统,那么对象可能包括以下几类:行人、汽车、摩托车和背景,这意味着图片中不含有前三种对象,也就是说图片中没有行人、汽车和摩托车,输出结果会是背景对象,这四个分类就是softmax函数可能输出的结果。
这就是标准的分类过程,如果你还想定位图片中汽车的位置,该怎么做呢?我们可以让神经网络多输出几个单元,输出一个边界框。具体说就是让神经网络再多输出4个数字,标记为
b
x
,
b
y
,
b
h
和
b
w
b_x,b_y,b_h和b_w
bx,by,bh和bw,这四个数字是被检测对象的边界框的参数化表示。
目标标签的定义如下:
它是一个向量,第一个组件
p
c
p_{c}
pc 表示是否含有对象,如果对象属于前三类(行人、汽车、摩托车),则
p
c
=
1
,
p_{c}=1,
pc=1, 如果 是背景,则图片中没有要检测的对象,则
p
c
=
0
p_{c}=0
pc=0 。我们可以这样理解
p
c
,
p_{c},
pc, 它表示被检测对象属于某一分类的概率, 背景分类除外。
如果检测到对象,就输出被检测对象的边界框参数
b
x
、
b
y
、
b
h
b_{x} 、 b_{y} 、 b_{h}
bx、by、bh 和
b
w
b_{w}
bw 。最后,如果存在某个对象,那么
p
c
=
1
,
p_{c}=1,
pc=1, 同 时输出c_、c_和c
3
,
_{3},
3, 表示该对象属于1-3类中的哪一类,是行人,汽车还是摩托车。鉴于我们所要处理的问题, 我 们假设图片中只含有一个对象,所以针对这个分类定位问题,图片最多只会出现其中一个对象。
神经网络的损失函数定义为:
L
(
y
^
,
y
)
=
(
y
1
^
−
y
1
)
2
+
(
y
2
^
−
y
2
)
2
+
…
(
y
8
^
−
y
8
)
2
,
L(\hat{y}, y)=\left(\hat{y_{1}}-y_{1}\right)^{2}+\left(\hat{y_{2}}-y_{2}\right)^{2}+\ldots\left(\hat{y_{8}}-y_{8}\right)^{2},
L(y^,y)=(y1^−y1)2+(y2^−y2)2+…(y8^−y8)2, 损失值等于每个元素相应差值的平方和。
如果图片中存在定位对象, 那么
y
1
=
1
,
y_{1}=1,
y1=1, 所以
y
1
=
p
c
,
y_{1}=p_{c},
y1=pc, 同样地,如果图片中存在定位对象,
p
c
=
1
,
p_{c}=1,
pc=1, 损失值就是 不同元素的平方和。
另一种情况是,
y
1
=
0
,
y_{1}=0,
y1=0, 也就是
p
c
=
0
,
p_{c}=0,
pc=0, 损失值是
(
y
^
1
−
y
1
)
2
,
\left(\hat{y}_{1}-y_{1}\right)^{2},
(y^1−y1)2, 因为对于这种情况, 我们不用考虑其它元素, 只需 要关注神经网络输出p_的准确度。
目标检测
假如你想构建一个汽车检测算法,步骤是,首先创建一个标签训练集,也就是x和y表示适当剪切的汽车图片样本。出于我们对这个训练集的期望,你一开始可以使用适当剪切的图片,就是整张图片几乎都被汽车占据,你可以照张照片,然后剪切,剪掉汽车以外的部分,使汽车居于中间位置,并基本占据整张图片。有了这个标签训练集,你就可以开始训练卷积网络了,输入这些适当剪切过的图片(编号6),卷积网络输出y,0或1表示图片中有汽车或没有汽车。训练完这个卷积网络,就可以用它来实现滑动窗口目标检测.
假设这是一张测试图片,首先选定一个特定大小的窗口,比如图片下方这个窗口,将这个红色小方块输入卷积神经网络,卷积网络开始进行预测,即判断红色方框内有没有汽车。
滑动窗口目标检测算法接下来会继续处理第二个图像,即红色方框稍向右滑动之后的区域,并输入给卷积网络,因此输入给卷积网络的只有红色方框内的区域,再次运行卷积网络,然后处理第三个图像,依次重复操作,直到这个窗口滑过图像的每一个角落。为了滑动得更快,我这里选用的步幅比较大,思路是以固定步幅移动窗口,遍历图像的每个区域,把这些剪切后的小图像输入卷积网络,对每个位置按0或1进行分类,这就是所谓的图像滑动窗口操作。
重复上述操作,选择一个更大的窗口,截取更大的区域,并输入给卷积神经网络处理.如果你这样做,不论汽车在图片的什么位置,总有一个窗口可以检测到它。
滑动窗口目标检测算法也有很明显的缺点,就是计算成本,因为你在图片中剪切出太多小方块,卷积网络要一个个地处理。如果你选用的步幅很大,显然会减少输入卷积网络的窗口个数,但是粗糙间隔尺寸可能会影响性能。反之,如果采用小粒度或小步幅,传递给卷积网络的小窗口会特别多,这意味着超高的计算成本。
滑动窗口的卷积实现
为了构建滑动窗口的卷积应用,首先要知道如何把神经网络的全连接层转化成卷积层.
假设对象检测算法输入一个14×14×3的图像,在这里过滤器大小为5×5,数量是16,14×14×3的图像在过滤器处理之后映射为10×10×16。然后通过参数为2×2的最大池化操作,图像减小到5×5×16。然后添加一个连接400个单元的全连接层,接着再添加一个全连接层,最后通过softmax单元输出y。为了跟下图区分开,我先做一点改动,用4个数字来表示y,它们分别对应softmax单元所输出的4个分类出现的概率。这4个分类可以是行人、汽车、摩托车和背景或其它对象。
现在我要演示的就是如何把这些全连接层转化为卷积层,画一个这样的卷积网络,它的前几层和之前的一样,而对于下一层,也就是这个全连接层,我们可以用5×5的过滤器来实现,数量是400个(编号1所示),输入图像大小为5×5×16,用5×5的过滤器对它进行卷积操作,过滤器实际上是5×5×16,因为在卷积过程中,过滤器会遍历这16个通道,所以这两处的通道数量必须保持一致,输出结果为1×1。假设应用400个这样的5×5×16过滤器,输出维度就是1×1×400,我们不再把它看作一个含有400个节点的集合,而是一个1×1×400的输出层。从数学角度看,它和全连接层是一样的,因为这400个节点中每个节点都有一个5×5×16维度的过滤器,所以每个值都是上一层这些5×5×16激活值经过某个任意线性函数的输出结果。
我们再添加另外一个卷积层(编号2所示),这里用的是1×1卷积,假设有400个1×1的过滤器,在这400个过滤器的作用下,下一层的维度是1×1×400,它其实就是上个网络中的这一全连接层。最后经由1×1过滤器的处理,得到一个softmax激活值,通过卷积网络,我们最终得到这个1×1×4的输出层,而不是这4个数字(编号3所示)。
以上就是用卷积层代替全连接层的过程,结果这几个单元集变成了1×1×400和1×1×4的维度。
假设输入给卷积网络的图片大小是14×14×3,测试集图片是16×16×3,现在给这个输入图片加上黄色条块,在最初的滑动窗口算法中,你会把这片蓝色区域输入卷积网络(红色笔标记)生成0或1分类。接着滑动窗口,步幅为2个像素,向右滑动2个像素,将这个绿框区域输入给卷积网络,运行整个卷积网络,得到另外一个标签0或1。继续将这个橘色区域输入给卷积网络,卷积后得到另一个标签,最后对右下方的紫色区域进行最后一次卷积操作。我们在这个16×16×3的小图像上滑动窗口,卷积网络运行了4次,于是输出了了4个标签。
结果发现,这4次卷积操作中很多计算都是重复的。所以执行滑动窗口的卷积时使得卷积网络在这4次前向传播过程中共享很多计算,尤其是在这一步操作中(编号1),卷积网络运行同样的参数,使得相同的5×5×16过滤器进行卷积操作,得到12×12×16的输出层。然后执行同样的最大池化(编号2),输出结果6×6×16。照旧应用400个5×5的过滤器(编号3),得到一个2×2×400的输出层,现在输出层为2×2×400,而不是1×1×400。应用1×1过滤器(编号4)得到另一个2×2×400的输出层。再做一次全连接的操作(编号5),最终得到2×2×4的输出层,而不是1×1×4。最终,在输出层这4个子方块中,蓝色的是图像左上部分14×14的输出(红色箭头标识),右上角方块是图像右上部分(绿色箭头标识)的对应输出,左下角方块是输入层左下角(橘色箭头标识),也就是这个14×14区域经过卷积网络处理后的结果,同样,右下角这个方块是卷积网络处理输入层右下角14×14区域(紫色箭头标识)的结果。
所以该卷积操作的原理是我们不需要把输入图像分割成四个子集,分别执行前向传播,而是把它们作为一张图片输入给卷积网络进行计算,其中的公共区域可以共享很多计算。不过这种算法仍然存在一个缺点,就是边界框的位置可能不够准确。
Bounding Box预测
交并比
在对象检测任务中,你希望能够同时定位对象,所以如果实际边界框是这样的,你的算法给出这个紫色的边界框,那么这个结果是好还是坏?所以交并比(loU)函数做的是计算两个边界框交集和并集之比。
非极大值抑制
Anchor Boxes
anchor box的思路是,预先定义两个不同形状的anchor box,或者anchor box形状,你要做的是把预测结果和这两个anchor box关联起来。一般来说,你可能会用更多的anchor box,可能要5个甚至更多
现在每个对象都和之前一样分配到同一个格子中,分配到对象中点所在的格子中,以及分配到和对象形状交并比最高的anchor box中。所以这里有两个anchor box,你就取这个对象,如果你的对象形状是这样的(编号1,红色框),你就看看这两个anchor box,anchor box 1形状是这样(编号2,紫色框),anchor box 2形状是这样(编号3,紫色框),然后你观察哪一个anchor box和实际边界框(编号1,红色框)的交并比更高,不管选的是哪一个,这个对象不只分配到一个格子,而是分配到一对,即(grid cell,anchor box)对,这就是对象在目标标签中的编码方式。所以现在输出y就是3×3×16,上一张幻灯片中你们看到 现在是16维的,或者你也可以看成是3×3×2×8,因为现在这里有2个anchor box,而y是8维的。 y维度是8,因为我们有3个对象类别,如果你有更多对象,那么 y的维度会更高。
参考文章:https://zhuanlan.zhihu.com/p/36029364
http://www.ai-start.com/dl2017/html/lesson1-week1.html