文章目录
一、基本前置
神经网络
每一个神经元在一个输入数据后,得到一个新的结果数据。
神经元本身可能就是一个ReLU函数(修正单元,一个数学函数)
神经网络则是将这些神经元连接起来,组成一个更大的网络图,在建立完成网络之后,只需要在源点处输入信息,即可得到结果。
如果能够给到关于x->y足够的数据样本,神经网络会自动计算他们之间的映射函数。
二、神经网络的基本计算原理(二分分类问题为例)
将事物分为两个互不相交的子集,然后对每个子集递归地重复该过程,直到满足某个条件。常用于从不同角度对事物进行分类。
以图片识别为例,二分分类的目的是通过输入一个图片对应的特征向量来判断结果。
假设图片尺寸为
64
×
64
64×64
64×64,RGB通道。
(1)将图片的数据转化为一维的特征列向量
x
x
x,其维度大小
n
x
n_x
nx为
64
×
64
×
3
64×64×3
64×64×3。
(2)我们定义数对
(
x
,
y
)
(x,y)
(x,y),其中
x
x
x为特征向量,
y
y
y为
1
1
1或
0
0
0(是否识别到某个内容)
并用
(
x
(
i
)
,
y
(
i
)
)
(x^{(i)},y^{(i)})
(x(i),y(i))来表示训练集中第
i
i
i个数对。
(3)构造矩阵
X
X
X使得
X
=
[
x
(
0
)
x
(
1
)
.
.
.
x
(
m
)
]
X=\left [ \begin{matrix} x^{(0)} & x^{(1)} & ... & x^{(m)} \\ \end{matrix} \right ]
X=[x(0)x(1)...x(m)]
(
X
X
X表示不唯一,有时候可能会写成转置的形式!)
(4)构造一维矩阵
Y
Y
Y使得
Y
=
[
y
(
0
)
y
(
1
)
.
.
.
y
(
m
)
]
Y=\left [ \begin{matrix} y^{(0)} & y^{(1)} & ... & y^{(m)} \\ \end{matrix} \right ]
Y=[y(0)y(1)...y(m)]
logistic回归
记
y
^
\hat y
y^为识别成功的概率(介于0与1之间),
w
w
w为一个特征向量,
b
b
b为某个实数。
则
y
^
=
σ
(
w
T
x
+
b
)
\hat y=\sigma(w^Tx+b)
y^=σ(wTx+b)(类似线性回归/曲线拟合的方式求出
w
w
w与
b
b
b,此处的
σ
\sigma
σ为sigmoid函数/logistic函数),我们希望
y
^
(
i
)
≈
y
(
i
)
\hat y^{(i)}≈y^{(i)}
y^(i)≈y(i)
其中
σ
(
x
)
=
1
1
+
e
−
x
\sigma(x)=\frac{1}{1+e^{-x}}
σ(x)=1+e−x1(值域是
[
0
,
1
]
[0,1]
[0,1])。
logistic回归损失函数/误差函数(结果与实际值的偏差)
对于单个训练样本,定义Loss函数
L
(
y
^
,
y
)
=
−
(
y
log
y
^
+
(
1
−
y
)
log
(
1
−
y
^
)
)
\mathscr{L}(\hat y,y)=-(y\log\hat y+(1-y)\log(1-\hat y))
L(y^,y)=−(ylogy^+(1−y)log(1−y^))
用来衡量得到的
y
^
\hat y
y^与
y
y
y接近的程度,
L
(
y
^
,
y
)
\mathscr{L}(\hat y,y)
L(y^,y)越小,效果越好。
当
y
=
1
y=1
y=1时,原式为
−
log
y
^
-\log\hat y
−logy^,
y
^
\hat y
y^越大(即越接近1)函数值越小,
当
y
=
0
y=0
y=0时,原式为
−
log
(
1
−
y
^
)
-\log(1-\hat y)
−log(1−y^),
y
^
\hat y
y^越小(即越接近0)函数值越小。
我们定义
m
m
m为隐藏层层数,对于全体训练样本:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
J(w,b)=\frac{1}{m}\sum_{i=1}^{m}\mathscr{L}(\hat y^{(i)},y^{(i)})
J(w,b)=m1∑i=1mL(y^(i),y(i))
因此,我们需要找到合适的
w
w
w与
b
b
b来使得
J
(
w
,
b
)
J(w,b)
J(w,b)尽可能小。
(这里的Loss函数不唯一,根据需要设定,此处的Loss函数是一个凸函数)
为什么选择这个作为Loss函数
当
y
=
1
y=1
y=1时,我们需要让函数为
y
^
\hat y
y^,当
y
=
0
y=0
y=0时则为
1
−
y
^
1-\hat y
1−y^
而
l
o
g
log
log是一个凸的单调函数,便于计算。
而
J
J
J是由最大似然估计得到的函数。
梯度下降法
(类似牛顿迭代法求导数)
令
w
=
w
−
α
∂
J
(
w
,
b
)
∂
w
,
b
=
b
−
α
∂
J
(
w
,
b
)
∂
b
w=w-\alpha\frac{\partial J(w,b)}{\partial w},b=b-\alpha\frac{\partial J(w,b)}{\partial b}
w=w−α∂w∂J(w,b),b=b−α∂b∂J(w,b),不停迭代。
其中
α
\alpha
α代表学习率/梯度下降法的步长。
对于单个训练样本,我们以x的维度为2为例,即
x
=
[
x
1
x
2
]
x=\left [ \begin{matrix} x1 \\ x2\\ \end{matrix} \right ]
x=[x1x2],则
z
=
w
T
x
+
b
=
w
1
x
1
+
w
2
x
2
+
b
z=w^Tx+b=w_1x_1+w_2x_2+b
z=wTx+b=w1x1+w2x2+b
y
^
=
(
1
+
e
−
z
)
−
1
\hat y=(1+e^{-z})^{-1}
y^=(1+e−z)−1
L
(
y
^
,
y
)
=
−
(
y
log
y
^
+
(
1
−
y
)
log
(
1
−
y
^
)
)
\mathscr{L}(\hat y,y)=-(y\log\hat y+(1-y)\log(1-\hat y))
L(y^,y)=−(ylogy^+(1−y)log(1−y^))
以
w
1
w_1
w1为例,
∂
J
(
w
1
,
b
)
∂
w
1
=
∂
L
(
y
^
,
y
)
∂
y
^
∗
∂
y
^
∂
w
1
\frac{\partial J(w_1,b)}{\partial w_1}=\frac{\partial\mathscr{L}(\hat y,y)}{\partial \hat y}*\frac{\partial\hat y}{\partial w_1}
∂w1∂J(w1,b)=∂y^∂L(y^,y)∗∂w1∂y^
=
(
−
y
y
^
+
1
−
y
1
−
y
^
)
∗
(
1
+
e
−
z
)
−
2
∗
e
−
z
∗
x
1
=(-\frac{y}{\hat y}+\frac{1-y}{1-\hat y})*(1+e^{-z})^{-2}*e^{-z}*x_1
=(−y^y+1−y^1−y)∗(1+e−z)−2∗e−z∗x1
=
(
−
y
y
^
+
1
−
y
1
−
y
^
)
∗
(
y
^
)
2
∗
1
−
y
^
y
^
∗
x
1
=(-\frac{y}{\hat y}+\frac{1-y}{1-\hat y})*(\hat y)^{2}*\frac{1-\hat y}{\hat y}*x_1
=(−y^y+1−y^1−y)∗(y^)2∗y^1−y^∗x1
=
(
−
y
y
^
+
1
−
y
1
−
y
^
)
∗
y
^
(
1
−
y
^
)
∗
x
1
=(-\frac{y}{\hat y}+\frac{1-y}{1-\hat y})*\hat y(1-\hat y)*x_1
=(−y^y+1−y^1−y)∗y^(1−y^)∗x1
=
(
−
y
(
1
−
y
^
)
+
y
^
(
1
−
y
)
)
∗
x
1
=(-y(1-\hat y)+\hat y(1-y))*x_1
=(−y(1−y^)+y^(1−y))∗x1
=
(
−
y
+
y
y
^
+
y
^
−
y
^
y
)
∗
x
1
=(-y+y\hat y+\hat y-\hat yy)*x_1
=(−y+yy^+y^−y^y)∗x1
=
(
y
^
−
y
)
∗
x
1
=(\hat y-y)*x_1
=(y^−y)∗x1
将其结果代入,得到
w
1
=
w
1
−
α
∂
J
(
w
1
,
b
)
∂
w
1
w_1=w_1-\alpha\frac{\partial J(w_1,b)}{\partial w_1}
w1=w1−α∂w1∂J(w1,b),其余同理。
对于全体训练样本,把
L
(
y
^
,
y
)
\mathscr{L}(\hat y,y)
L(y^,y)用
J
(
w
,
b
)
J(w,b)
J(w,b)替换即可,计算方法同理。
伪代码
J
=
0
;
d
w
j
=
0
,
b
=
0
;
J=0;dw_j=0,b=0;
J=0;dwj=0,b=0;
f
o
r
i
=
1
t
o
m
for\ i=\ 1\ to\ m
for i= 1 to m
z
(
i
)
=
w
T
x
(
i
)
+
b
\ \ \ z^{(i)}=w^Tx^{(i)}+b
z(i)=wTx(i)+b
a
(
i
)
=
σ
(
z
(
i
)
)
\ \ \ a^{(i)}=\sigma(z^{(i)})
a(i)=σ(z(i))
J
+
=
−
(
y
(
i
)
log
a
(
i
)
+
(
1
−
y
(
i
)
)
log
(
1
−
a
(
i
)
)
)
\ \ \ J+=-(y^{(i)}\log a^{(i)}+(1-y^{(i)})\log(1-a^{(i)}))
J+=−(y(i)loga(i)+(1−y(i))log(1−a(i)))
d
z
(
i
)
=
a
(
i
)
−
y
(
i
)
\ \ \ dz^{(i)}=a^{(i)}-y^{(i)}
dz(i)=a(i)−y(i)
d
w
j
+
=
x
j
(
i
)
∗
d
z
(
i
)
\ \ \ dw_j+=x_{j}^{(i)}*dz^{(i)}
dwj+=xj(i)∗dz(i)
d
b
+
=
d
z
(
i
)
\ \ \ db+=dz^{(i)}
db+=dz(i)
J
/
=
m
;
J/=m;
J/=m;
d
w
j
/
=
m
;
d
b
/
=
m
dw_j/=m;db/=m
dwj/=m;db/=m
w
j
−
=
α
d
w
j
;
b
−
=
α
d
b
w_j-=\alpha dw_j;b-=\alpha db
wj−=αdwj;b−=αdb
向量化方法优化(消去所有的for,加快运算)
直接引用python的矩阵运算,可以快速得出
z
=
w
T
x
+
b
z=w^Tx+b
z=wTx+b等式子的结果。(比正常的循环运算更快,利用SIMD/单控制流多数据流来实现并行处理)
多用numpy内置函数,少用for来提升效率!
numpy很多运算函数适配向量运算!
(1)将
d
w
j
dw_j
dwj定义为一个
n
x
n_x
nx维的向量
d
w
dw
dw,初始置为0,
dw=np.zero(n_x,1) # 初始化
...
dw+=xi*dzi
(2)把 z ( i ) z^{(i)} z(i)与 x ( i ) x^{(i)} x(i)定义为一个 n x n_x nx维的向量,并设置一维向量 B = [ b b . . . b ] B=\left [ \begin{matrix} b & b & ... & b \\ \end{matrix} \right ] B=[bb...b]
Z=np.dot(w.T,x)+b
(在python中,向量与实数相加时会把实数加到向量的每一个数上(广播),因此不用构造一维的B向量)
优化后
J=0;dw=np.zero(n_x);b=0
z=np.dot(w.T,x)+b
A=sigma(z)
dz=A-Y
dw=x*dz.T/m
db=np.sum(dz)/m
w=w-alpha*dw
b=b-alpha*db
一些python广播技巧
面对维度不同的矩阵计算时,会水平/垂直复制自身使得二者维度保持一致。
sum(axis=0)# 列相加形成新矩阵
sum(axis=1)# 行相加形成新矩阵
reshape(x1,x2,x3,...,xn)# 把原矩阵转化为一个n维矩阵
np.random.randn()# 生成随机数
np.random.randn(m,n)# 生成m*n的随机矩阵
shape()# 输出矩阵的维度,格式:x1,x2,...,xn
三、神经网络
一个神经元对应一次操作,以之前的为例,则第一列计算
z
z
z与
a
a
a,第二列计算
y
^
\hat y
y^。
神经网络表示
下图为一个单隐层神经网络。
输入层/第0层:输入的样本(
X
=
A
[
0
]
X=A^{[0]}
X=A[0])
隐藏层:有多个/多层节点,但是不可见,
a
[
i
]
a^{[i]}
a[i]表示第
i
i
i层。
输出层:只有一个节点,表示结果
同理,也可以用矩阵运算来加速来避免for循环!
构造矩阵
X
=
[
x
(
1
)
x
(
2
)
.
.
.
x
(
m
)
]
X=\left [ \begin{matrix} x^{(1)} & x^{(2)}& ... & x^{(m)}\\ \end{matrix} \right ]
X=[x(1)x(2)...x(m)]
一维向量
Z
=
[
z
[
1
]
(
1
)
z
[
1
]
(
2
)
.
.
.
z
[
1
]
(
m
)
]
Z=\left [ \begin{matrix} z^{[1](1)} & z^{[1](2)} & ... & z^{[1](m)}\\ \end{matrix} \right ]
Z=[z[1](1)z[1](2)...z[1](m)]
一维向量
A
=
[
a
[
1
]
(
1
)
a
[
1
]
(
2
)
.
.
.
a
[
1
]
(
m
)
]
A=\left [ \begin{matrix} a^{[1](1)} & a^{[1](2)} & ... & a^{[1](m)}\\ \end{matrix} \right ]
A=[a[1](1)a[1](2)...a[1](m)]
激活函数
事实上,激活函数不一定要是sigmoid函数,如
t
a
n
h
tanh
tanh(双曲正切函数,值域为
[
−
1
,
1
]
[-1,1]
[−1,1])
t
a
n
h
x
=
s
i
n
h
x
c
o
s
h
x
=
e
x
−
e
−
x
2
e
x
+
e
−
x
2
=
e
x
−
e
−
x
e
x
+
e
−
x
tanhx=\frac{sinhx}{coshx}=\frac{\frac{e^{x}-e^{-x}}{2}}{\frac{e^{x}+e^{-x}}{2}}=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}
tanhx=coshxsinhx=2ex+e−x2ex−e−x=ex+e−xex−e−x
(事实上,这是sigmoid函数变换平移过后的版本,通常而言
t
a
n
h
tanh
tanh的效果在大部分情况都比sigmoid函数更好,但在二分分类,即值域在
[
0
,
1
]
[0,1]
[0,1]的问题下,推荐sigmoid函数。且该情况下sigmoid函数往往只在最后一层使用!)
激活函数用
g
g
g表示,不同层的
g
[
i
]
g^{[i]}
g[i]可能不一样!
默认的激活函数:线性修正单元ReLU:
a
=
m
a
x
(
0
,
z
)
a=max(0,z)
a=max(0,z)
带泄漏ReLU(leaky ReLU):负数部分是一个更加缓和的斜率(
[
0
,
1
]
[0,1]
[0,1]之间,下面以0.01为例)。
特殊的激活函数:
a
=
z
a=z
a=z(前后不变)
为什么需要非线性激活函数?
多个线性激活函数的结果也只会是线性函数,神经网络会失去其意义,至多一个位置可以用线性激活函数!
常见激活函数的导数
sigmoid函数:
σ
′
(
z
)
=
(
(
1
+
e
−
z
)
−
1
)
′
=
(
(
1
+
e
−
z
)
−
2
)
∗
e
−
z
=
(
1
σ
(
z
)
−
1
)
∗
σ
2
(
z
)
=
σ
(
z
)
−
σ
2
(
z
)
\sigma '(z)=((1+e^{-z})^{-1})'=((1+e^{-z})^{-2})*e^{-z}=(\frac{1}{\sigma(z)}-1)*\sigma^2(z)=\sigma(z)-\sigma^2(z)
σ′(z)=((1+e−z)−1)′=((1+e−z)−2)∗e−z=(σ(z)1−1)∗σ2(z)=σ(z)−σ2(z)
tanh函数:
g
′
(
z
)
=
(
e
x
−
e
−
x
e
x
+
e
−
x
)
′
=
(
e
x
+
e
−
x
)
2
−
(
e
x
−
e
−
x
)
2
(
e
x
+
e
−
x
)
2
=
4
(
e
x
+
e
−
x
)
2
=
1
−
g
2
(
z
)
g'(z)=(\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}})'=\frac{(e^{x}+e^{-x})^2-(e^{x}-e^{-x})^2}{(e^{x}+e^{-x})^2}=\frac{4}{(e^{x}+e^{-x})^2}=1-g^2(z)
g′(z)=(ex+e−xex−e−x)′=(ex+e−x)2(ex+e−x)2−(ex−e−x)2=(ex+e−x)24=1−g2(z)
(注意到
1
−
g
(
z
)
=
1
−
e
x
−
e
−
x
e
x
+
e
−
x
=
2
e
−
x
e
x
+
e
−
x
1-g(z)=1-\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}=\frac{2e^{-x}}{e^{x}+e^{-x}}
1−g(z)=1−ex+e−xex−e−x=ex+e−x2e−x,同理
1
+
g
(
z
)
=
2
e
x
e
x
+
e
−
x
1+g(z)=\frac{2e^{x}}{e^{x}+e^{-x}}
1+g(z)=ex+e−x2ex,相乘即可。)
ReLU函数:
g
′
(
z
)
=
{
1
,
z
≥
0
0
,
z
<
0
\displaystyle g'(z)= \left\{\begin{array}{l} 1,\ z\geq 0 \\ 0,\ z< 0 \end{array}\right.
g′(z)={1, z≥00, z<0
带泄漏ReLU函数:
g
′
(
z
)
=
{
1
,
z
≥
0
0.01
,
z
<
0
\displaystyle g'(z)= \left\{\begin{array}{l} 1,\ z\geq 0 \\ 0.01,\ z< 0 \end{array}\right.
g′(z)={1, z≥00.01, z<0
(事实上,
z
=
0
z=0
z=0处没有导数定义,但
z
=
0
z=0
z=0处取得的概率很小,因此此处导数是0还是1无关紧要。)
神经网络下的梯度算法
我们假设第一层的激活函数为 g g g,第二层的激活函数为sigmoid函数。
正向传播
第一层:
Z
[
1
]
=
W
[
1
]
X
+
b
[
1
]
Z^{[1]}=W^{[1]}X+b^{[1]}
Z[1]=W[1]X+b[1](矩阵运算)
A
[
1
]
=
g
[
1
]
(
Z
[
1
]
)
A^{[1]}=g^{[1]}(Z^{[1]})
A[1]=g[1](Z[1])
第二层:
Z
[
2
]
=
W
[
2
]
A
[
1
]
+
b
[
2
]
Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]}
Z[2]=W[2]A[1]+b[2](把
X
X
X换成上一次的结果
A
[
1
]
A^{[1]}
A[1])
A
[
2
]
=
g
[
2
]
(
Z
[
2
]
)
=
σ
(
Z
[
2
]
)
A^{[2]}=g^{[2]}(Z^{[2]})=\sigma(Z^{[2]})
A[2]=g[2](Z[2])=σ(Z[2])
反向传播
第二层:
d
Z
[
2
]
=
A
[
2
]
−
Y
dZ^{[2]}=A^{[2]}-Y
dZ[2]=A[2]−Y(
Y
=
[
y
(
0
)
y
(
1
)
.
.
.
y
(
m
)
]
Y=\left [ \begin{matrix} y^{(0)} & y^{(1)} & ... & y^{(m)} \\ \end{matrix} \right ]
Y=[y(0)y(1)...y(m)])
d
W
[
2
]
=
d
Z
[
2
]
∗
(
A
[
1
]
)
T
/
m
dW^[2]=dZ^{[2]}*(A^{[1]})^{T}/m
dW[2]=dZ[2]∗(A[1])T/m(原本的公式内是
X
X
X,但此处为上一层的运算结果
A
[
1
]
A^{[1]}
A[1])
d
b
[
2
]
=
n
p
.
s
u
m
(
d
Z
[
2
]
,
a
x
i
s
=
1
,
k
e
e
p
d
i
m
s
=
t
r
u
e
)
/
m
db^{[2]}=np.sum(dZ^{[2]},axis=1,keepdims=true)/m
db[2]=np.sum(dZ[2],axis=1,keepdims=true)/m(keepdims是防止python输出错误的矩阵形式,确保是一个一维向量)
第一层:
d
Z
[
1
]
=
(
W
[
2
]
)
T
∗
d
Z
[
2
]
∗
g
[
1
]
−
1
(
Z
[
1
]
)
dZ^{[1]}=(W^{[2]})^T*dZ^{[2]}*g^{[1]^{-1}}(Z^{[1]})
dZ[1]=(W[2])T∗dZ[2]∗g[1]−1(Z[1])(g的反函数的导数)
d
W
[
1
]
=
d
Z
[
1
]
∗
X
T
/
m
dW^{[1]}=dZ^{[1]}*X^T/m
dW[1]=dZ[1]∗XT/m
d
b
[
1
]
=
n
p
.
s
u
m
(
d
Z
[
1
]
,
a
x
i
s
=
1
,
k
e
e
p
d
i
m
s
=
t
r
u
e
)
/
m
db^{[1]}=np.sum(dZ^{[1]},axis=1,keepdims=true)/m
db[1]=np.sum(dZ[1],axis=1,keepdims=true)/m
W
[
1
]
=
W
[
1
]
−
α
d
W
[
1
]
;
b
[
1
]
=
b
[
1
]
−
α
d
b
[
1
]
W^{[1]}=W^{[1]}-\alpha dW^{[1]};b^{[1]}=b^{[1]}-\alpha db^{[1]}
W[1]=W[1]−αdW[1];b[1]=b[1]−αdb[1]
随机初始化
如果开始所有
W
,
b
W,b
W,b都为0,则每一层的神经元都在计算相同的激活函数。
往往会使用np.random.randn([
n
x
,
n
x
n_x,n_x
nx,nx])*0.01来作为
W
W
W的初始值,
b
b
b采用全
0
0
0。
(采用0.01这类的小系数是为了能保证梯度下降的学习速度足够快)
四、深层神经网络
许多的复杂函数不能简单的通过少量层数来学习到,因此需要多层实现。
前向传播
对于神经网络中的第
l
l
l层,
Z
[
l
]
=
W
[
i
]
∗
A
[
i
−
1
]
+
b
[
l
]
Z^{[l]}=W^{[i]}*A^{[i-1]}+b^{[l]}
Z[l]=W[i]∗A[i−1]+b[l](b用python广播来处理)
A
[
l
]
=
g
[
l
]
(
Z
[
l
]
)
A^{[l]}=g^{[l]}(Z^{[l]})
A[l]=g[l](Z[l])
反向传播
对于神经网络中的第
l
l
l层,
d
Z
[
l
]
=
d
A
[
l
]
∗
g
[
l
]
′
(
Z
[
l
]
)
dZ^{[l]}=dA^{[l]}*g^{[l]'}(Z^{[l]})
dZ[l]=dA[l]∗g[l]′(Z[l])
d
W
[
l
]
=
d
Z
[
l
]
∗
A
[
l
−
1
]
/
m
dW^{[l]}=dZ^{[l]}*A^{[l-1]}/m
dW[l]=dZ[l]∗A[l−1]/m
d
b
[
l
]
=
n
p
.
s
u
m
(
d
Z
[
l
]
,
a
x
i
s
=
1
,
k
e
e
p
d
i
m
s
=
t
r
u
e
)
/
m
db^{[l]}=np.sum(dZ^{[l]},axis=1,keepdims=true)/m
db[l]=np.sum(dZ[l],axis=1,keepdims=true)/m
d
A
[
l
−
1
]
=
(
W
[
l
]
)
T
∗
d
Z
[
l
]
dA^{[l-1]}=(W^{[l]})^T*dZ^{[l]}
dA[l−1]=(W[l])T∗dZ[l]
核对矩阵的维数
以该图为例,第零层2维(
A
[
0
]
=
n
x
=
2
A^{[0]}=n_x=2
A[0]=nx=2),第一层3维,第二层5维,以此类推。
在单个训练样本中,对于每一个点,都有
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]
A
[
l
]
=
g
[
l
]
(
Z
[
l
]
)
A^{[l]}=g^{[l]}(Z^{[l]})
A[l]=g[l](Z[l])
Z
[
l
]
Z^{[l]}
Z[l]是
n
[
l
]
×
1
n^{[l]}\times1
n[l]×1的向量,故
b
[
l
]
b^{[l]}
b[l]也是
n
[
l
]
×
1
n^{[l]}\times1
n[l]×1的向量。
而
A
[
l
−
1
]
A^{[l-1]}
A[l−1]是
n
[
l
−
1
]
×
1
n^{[l-1]}\times1
n[l−1]×1的向量,因此
W
[
l
]
W^{[l]}
W[l]是
n
[
l
]
×
n
[
l
−
1
]
n^{[l]}\times n^{[l-1]}
n[l]×n[l−1]的矩阵(矩阵相乘法则)。
d
W
[
l
]
dW^{[l]}
dW[l]与
d
b
[
l
]
db^{[l]}
db[l]同理。
对于全体训练样本中,
Z
[
l
]
Z^{[l]}
Z[l]是
n
[
l
]
×
m
n^{[l]}\times m
n[l]×m的向量,故
b
[
l
]
b^{[l]}
b[l]也是
n
[
l
]
×
m
n^{[l]}\times m
n[l]×m的向量。
而
A
[
l
−
1
]
A^{[l-1]}
A[l−1]是
n
[
l
−
1
]
×
m
n^{[l-1]}\times m
n[l−1]×m的向量,因此
W
[
l
]
W^{[l]}
W[l]是
n
[
l
]
×
n
[
l
−
1
]
n^{[l]}\times n^{[l-1]}
n[l]×n[l−1]的矩阵(矩阵相乘法则)。
d
W
[
l
]
dW^{[l]}
dW[l]与
d
b
[
l
]
db^{[l]}
db[l]同理。
为什么要深层表示?
如果用比较浅的神经网络计算同一个函数,则需要的神经元的数目会呈现指数增长。
以人脸识别为例,通常较浅的几层用于探测基本特征信息,如面部边缘等。
在后几层,整合这些简单的特征,实现更复杂的功能,如五官定位等。
超参数(需要事先设定,并控制着参数,得到最终的
W
W
W与
b
b
b):学习率
α
\alpha
α,循环学习迭代次数,隐层数,每一层的单元数,每一层的激活函数等。
五、建立自己的机器学习程序
建立机器学习程序是一个长期的迭代过程,超参数的最佳结果是无法轻易确定的,因此需要不断迭代修改。
训练/验证/测试集
过去常见的方案是:60%训练集,20%验证集,20%测试集。
但在随着数据量越来越大之后,往往后两者的数据比例很小,仅1%(甚至不足1%)。
尽量保证测试集与验证集的数据位于同一分布!
即使没有测试集也可以,因为测试集是为了对最终得到的神经网络做高置信度的无偏评估,保证其准确性,评估的指标也可以根据自己的需要去制定(如通过设置权值来过滤数据等)。
偏差(bias)/方差
拟合要适度,避免过拟合(方差低)与欠拟合(方差高),偏差影响拟合度。
对测试集的错误率与验证集的错误率进行比较,如果二者差距较大,则为“高偏差”。
需要用正则化避免过拟合。
L2正则化(常用)
尽管通过准备更多数据也可以解决高方差的问题,但在很多情况下无法拥有更多的数据,则需要考虑
L2正则化/权重衰减 (常用):
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
2
m
∣
∣
w
∣
∣
2
2
J(w,b)=\frac{1}{m}\sum_{i=1}^{m}\mathscr{L}(\hat y^{(i)},y^{(i)})+\frac{\lambda}{2m}||w||_2^2
J(w,b)=m1∑i=1mL(y^(i),y(i))+2mλ∣∣w∣∣22(L2范数/平方范数:
∣
∣
w
∣
∣
2
2
=
∑
j
=
1
n
x
w
j
2
=
w
T
w
||w||_2^2=\sum_{j=1}^{n_x}w_j^2=w^Tw
∣∣w∣∣22=∑j=1nxwj2=wTw,即L2范数为向量模长)
(通常这个公式内不考虑正则化
b
b
b,若要正则化则再加上
λ
2
m
b
2
\frac{\lambda}{2m}b^2
2mλb2)
L1正则化:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
m
∣
∣
w
∣
∣
1
J(w,b)=\frac{1}{m}\sum_{i=1}^{m}\mathscr{L}(\hat y^{(i)},y^{(i)})+\frac{\lambda}{m}||w||_1
J(w,b)=m1∑i=1mL(y^(i),y(i))+mλ∣∣w∣∣1
(L1范数:
∣
∣
w
∣
∣
1
2
=
∑
j
=
1
n
x
∣
w
j
∣
=
w
T
w
||w||_1^2=\sum_{j=1}^{n_x}|w_j|=w^Tw
∣∣w∣∣12=∑j=1nx∣wj∣=wTw)
(使用L1正则化会让
w
w
w变得更加稀疏,即向量中存在许多的0)
其中,
λ
\lambda
λ是正则化参数,通常由验证集或者交叉验证得出,也是一个超参数。
对于神经网络中,
W
[
l
]
W^{[l]}
W[l]是
n
[
l
]
×
n
[
l
−
1
]
n^{[l]}\times n^{[l-1]}
n[l]×n[l−1]的矩阵,
则弗罗贝尼乌斯范数(Frobenius norm)
∣
∣
W
[
l
]
∣
∣
F
2
=
∑
i
=
1
n
[
l
−
1
]
∑
j
=
1
n
[
l
]
(
∣
W
i
j
[
l
]
∣
)
2
||W^{[l]}||^2_F=\sum_{i=1}^{n^{[l-1]}}\sum_{j=1}^{n^{[l]}}(|W_{ij}^{[l]}|)^2
∣∣W[l]∣∣F2=∑i=1n[l−1]∑j=1n[l](∣Wij[l]∣)2
J
(
w
[
1
]
,
b
[
1
]
,
.
.
.
,
w
[
l
]
,
b
[
l
]
)
=
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
2
m
∑
i
=
1
L
∣
∣
W
[
l
]
∣
∣
F
2
J(w^{[1]},b^{[1]},...,w^{[l]},b^{[l]})=\frac{1}{m}\sum_{i=1}^{m}\mathscr{L}(\hat y^{(i)},y^{(i)})+\frac{\lambda}{2m}\sum_{i=1}^{L}||W^{[l]}||^2_F
J(w[1],b[1],...,w[l],b[l])=m1∑i=1mL(y^(i),y(i))+2mλ∑i=1L∣∣W[l]∣∣F2
在计算梯度下降时,
令
d
W
[
l
]
=
dW^{[l]}=
dW[l]=原本的结果+
λ
m
w
[
l
]
\frac{\lambda}{m}w^{[l]}
mλw[l]
W
[
l
]
=
W
[
l
]
−
α
d
W
[
l
]
W^{[l]}=W^{[l]}-\alpha dW^{[l]}
W[l]=W[l]−αdW[l]
为什么L2正则化可以防止过拟合?
令超参数
λ
\lambda
λ变大,会使得激活函数中的
Z
[
l
]
Z^{[l]}
Z[l]变小,从而的
W
[
l
]
W^{[l]}
W[l]变小,逐渐使得
W
l
W^{l}
Wl内的元素趋向于0。
从而相当于“消除”了某层中几个神经元,让神经网络变得更加“简单”,使得从过拟合的状态到正常或者高偏差的状态(即上图中从右到左)。
上图的激活函数中,
z
z
z趋向于0时,逐渐变为线性变化,而过多的线性变化可以整合成一个线性变化,从而实现“消除”了神经元。
使用正则化的Loss函数是一个单调递减的曲线(梯度下降)
Dropout(随机失活)正则化(计算机视觉中使用较多)
拷贝一份神经网络,将每一层的每一个神经元以某个概率保留或者去除,得到一个精简的神经网络,并重新训练。
反向随机失活
假设有一个
L
L
L层的神经网络。
对于原矩阵A,定义矩阵
D
=
n
p
.
r
a
n
d
o
m
.
r
a
n
d
(
D=np.random.rand(
D=np.random.rand(矩阵A的维度),内部为01矩阵,其中元素为1的概率是keep-prob(超参数,[0,1),keep-prob为1时无变动)。
令A=A*D,消除矩阵D中0对应位置的矩阵A中的元素。,相当于有keep-prob的概率保留A中的元素。
再让A中每个元素除以keep-prob。(为了保证矩阵A的整体期望不变)
(事实上,因为矩阵D每一次可能不一样,所以即使是相同的训练集也可能有不同的结果。)
可以设置一个keep-prob为1的“对照组”(即不使用dropout的结果),和每一次随机不同神经元失活的训练结果进行比对。
将过拟合较为严重的层对应的keep-prob设置较低。
(其实L2正则化和Dropout正则化实现的功能是类似的,都是通过“消去”部分神经元避免过拟合)
Dropout的缺点:Loss函数J不再被明确的定义,在随机移除了一些神经元之后,很难确定梯度下降的性能。(所以其实并不是最优先使用的方法)
其他正则化方式
数据扩增(缓解过拟合)
例如对于图片训练,将图片水平翻转并添加进训练集,或将图片进行一定程度的旋转/裁切等。
对于验证码图片训练,也可以考虑将验证码图片中的数字进行适当的扭曲变化。
(在原有数据上稍作改动,是一种成本较低的数据扩增方式)
Early Stopping/提前停止
除了绘制Loss函数的梯度下降曲线,也绘制测试集的误差,然后选择一个大小适中的弗罗贝尼乌斯范数后,提前停止训练神经网络。
缺点:无法同时做到“优化Loss函数J”与“防止过拟合”
归一化输入(加速神经网络训练)
以
x
=
[
x
1
x
2
]
x=\left [ \begin{matrix} x1 \\ x2\\ \end{matrix} \right ]
x=[x1x2]为例,
第一步:零均值化,令
μ
=
1
m
∑
i
=
1
M
X
(
i
)
,
X
(
i
)
=
X
(
i
)
−
μ
\mu=\frac{1}{m}\sum_{i=1}^{M}X^{(i)},X^{(i)}=X^{(i)}-\mu
μ=m1∑i=1MX(i),X(i)=X(i)−μ(让整体期望变为0)
第二步:归一化方差,令
σ
2
=
1
m
∑
i
=
1
M
(
X
(
i
)
)
2
,
X
(
i
)
=
X
(
i
)
/
σ
2
\sigma^2=\frac{1}{m}\sum_{i=1}^{M}(X^{(i)})^2,X^{(i)}=X^{(i)}/\sigma^2
σ2=m1∑i=1M(X(i))2,X(i)=X(i)/σ2(让整体方差变为1)
在训练数据时,要用相同的
μ
\mu
μ与
σ
2
\sigma^2
σ2来归一化测试集,保证训练的效果更好。
(如果多个测试集的数据区间相差很大,会使训练的效率受到影响)
梯度消失/梯度爆炸
当训练深度神经网络时,Loss函数的梯度下降过快或过慢(导数变得很大或很小)。
以上图的神经网络为例,假设每一层的激活函数
g
(
z
)
=
z
g(z)=z
g(z)=z(线性激活函数),且全体
b
[
l
]
=
0
b^{[l]}=0
b[l]=0(即
z
[
l
]
=
w
T
∗
z
[
l
−
1
]
z^{[l]}=w^T*z^{[l-1]}
z[l]=wT∗z[l−1]),不难得到,最后的
y
=
w
[
l
]
w
[
l
−
1
]
w
[
l
−
2
]
.
.
.
w
[
1
]
x
y=w^{[l]}w^{[l-1]}w^{[l-2]}...w^{[1]}x
y=w[l]w[l−1]w[l−2]...w[1]x。
我们再令以
x
=
[
1.5
0
0
1.5
]
x=\left [ \begin{matrix} 1.5&0 \\ 0&1.5\\ \end{matrix} \right ]
x=[1.5001.5]为例,则
y
^
=
w
[
l
]
∗
[
1.5
0
0
1.5
]
L
−
1
∗
x
\hat y=w^{[l]}*\left [ \begin{matrix} 1.5&0 \\ 0&1.5\\ \end{matrix} \right ]^{L-1}*x
y^=w[l]∗[1.5001.5]L−1∗x。
不难看出,当系数大于1时,随着层数
L
L
L越多,就会呈现指数爆炸增长,同理若小于1时,会指数缩小。
因此,需要通过随机化初始权重来解决。
随机化初始权重
对于单个神经元,我们假定
b
=
0
b=0
b=0,则此时
z
=
w
1
T
x
1
+
w
2
T
x
2
+
.
.
.
+
w
n
T
x
n
z=w_1^Tx1+w_2^Tx2+...+w_n^Tx_n
z=w1Tx1+w2Tx2+...+wnTxn,当
n
n
n越大时,我们期望
w
i
w_i
wi越小,(因为
z
z
z会更小,loss函数也会更小),
因此我们可以令
w
[
l
]
=
n
p
.
r
a
m
d
o
n
.
r
a
n
d
n
(
s
h
a
p
e
)
∗
n
p
.
s
q
r
t
(
1
n
[
l
−
1
]
)
w^{[l]}=np.ramdon.randn(shape)*np.sqrt(\frac{1}{n^{[l-1]}})
w[l]=np.ramdon.randn(shape)∗np.sqrt(n[l−1]1)
(此处的
n
[
l
−
1
]
n^{[l-1]}
n[l−1]指第
l
−
1
l-1
l−1层的神经元数)
(但事实上,当激活函数是ReLU函数时,使用
2
n
[
l
−
1
]
\sqrt{\frac{2}{n^{[l-1]}}}
n[l−1]2的效果更好,当激活函数是
t
a
n
h
tanh
tanh时,
1
n
[
l
−
1
]
\sqrt{\frac{1}{n^{[l-1]}}}
n[l−1]1效果更好,而对于Xavier初始化,则是
2
n
[
l
−
1
]
+
n
[
l
]
\sqrt{\frac{2}{n^{[l-1]}+n^{[l]}}}
n[l−1]+n[l]2)
在反向传播中进行梯度检验(仅用于调试)
双边误差公式:
f
′
(
θ
)
=
l
i
m
ϵ
→
0
f
(
θ
+
ϵ
)
−
f
(
θ
−
ϵ
)
2
ϵ
f'(\theta)=lim_{\epsilon \rightarrow0} \frac{f(\theta+\epsilon)-f(\theta-\epsilon)}{2\epsilon}
f′(θ)=limϵ→02ϵf(θ+ϵ)−f(θ−ϵ)(一种导数定义)
第一步:令大向量
θ
=
[
W
[
1
]
b
[
1
]
.
.
.
W
[
L
]
b
[
L
]
]
\theta=\left [ \begin{matrix} W^{[1]} & b^{[1]} & ... & W^{[L]} & b^{[L]} \\ \end{matrix} \right ]
θ=[W[1]b[1]...W[L]b[L]](其实是一个更大的矩阵)
第二步:计算
d
W
[
1
]
,
d
b
[
1
]
,
.
.
.
,
d
W
[
L
]
,
d
b
[
L
]
dW^{[1]},db^{[1]},...,dW^{[L]},db^{[L]}
dW[1],db[1],...,dW[L],db[L]的值并reshape成
θ
\theta
θ的形状(每一个其实都是一个矩阵,合并后也仍旧是大矩阵)
第三步:循环遍历每一个
d
θ
a
p
p
r
o
x
[
i
]
=
J
(
θ
1
,
θ
2
,
.
.
.
,
θ
i
+
ϵ
,
.
.
.
,
)
−
J
(
θ
1
,
θ
2
,
.
.
.
,
θ
i
−
ϵ
,
.
.
.
,
)
2
ϵ
d\theta_{approx}[i]=\frac{J(\theta_1,\theta_2,...,\theta_i+\epsilon,...,)-J(\theta_1,\theta_2,...,\theta_i-\epsilon,...,)}{2\epsilon}
dθapprox[i]=2ϵJ(θ1,θ2,...,θi+ϵ,...,)−J(θ1,θ2,...,θi−ϵ,...,)(注意:Loss函数需要正则化!但不要使用Dropout,因为会随机消除点,让Loss函数难以计算!)
(用双边误差公式近似的代替
d
θ
i
=
∂
J
∂
θ
i
d\theta_i=\frac{\partial J}{\partial \theta_i}
dθi=∂θi∂J),令
d
θ
a
p
p
r
o
x
=
[
d
θ
a
p
p
r
o
x
[
1
]
.
.
.
d
θ
a
p
p
r
o
x
[
2
L
]
]
d\theta_{approx}=\left [ \begin{matrix} d\theta_{approx}[1] & ... & d\theta_{approx}[2L] \\ \end{matrix} \right ]
dθapprox=[dθapprox[1]...dθapprox[2L]](维度和
θ
\theta
θ相同)
第四步:计算
∣
∣
d
θ
a
p
p
r
o
x
−
d
θ
∣
∣
2
∣
∣
d
θ
a
p
p
r
o
x
∣
∣
2
+
∣
∣
d
θ
∣
∣
2
\frac{||d\theta_{approx}-d\theta||_2}{||d\theta_{approx}||_2+||d\theta||_2}
∣∣dθapprox∣∣2+∣∣dθ∣∣2∣∣dθapprox−dθ∣∣2(此处的
d
θ
d\theta
dθ是实际梯度曲线的导数)
最终计算结果数值在
1
0
−
7
10^{-7}
10−7~
1
0
−
5
10^{-5}
10−5较佳,若大于
1
0
−
3
10^{-3}
10−3(即差距过大)可能需要检验是否有bug,排查哪个
d
θ
a
p
p
r
o
x
[
i
]
d\theta_{approx}[i]
dθapprox[i]与
d
θ
i
d\theta_i
dθi的偏差较大。
六、神经网络优化算法
Mini-Batch 梯度下降法
当训练样本数量很大时,向量化的矩阵运算可能会很慢,因为传统方法下需要处理整个训练集后才可以进行梯度下降。
因此考虑将训练集分为若干个较小的子训练集(Mini-Batch)
X
{
i
}
X^{\{i\}}
X{i},分别对这些子训练集进行和之前相同的向量化训练,Loss函数需要正则化!
在Mini-Batch下,产生的Loss函数可能会有类似“噪音干扰”的梯度下降曲线。
如果Mini-Batch的大小是
m
m
m(即整个训练集),那等价于不使用Mini-Batch,
如果Mini-Batch的大小是1(每个样本一个训练集),则为随机梯度下降法(会失去向量化加速的效果,因为只有一个样本)。
因此,需要挑选合理的Mini-Batch大小!
指数加权平均
用近似但便于计算的曲线拟合代替原来的散点图。
v
t
=
β
v
t
−
1
+
(
1
−
β
)
θ
t
v_t=\beta v_{t-1}+(1-\beta)\theta_t
vt=βvt−1+(1−β)θt(
β
\beta
β为动量,是超参数,常令
β
\beta
β=0.9)
当
β
\beta
β变大时,曲线适应的会更慢,当
β
\beta
β变小时,曲线的噪声会更多。
偏差修正
在估算初期(即
t
t
t比较小的时候)可以使用,令
v
t
=
β
v
t
−
1
+
(
1
−
β
)
θ
t
1
−
β
t
v_t=\frac{\beta v_{t-1}+(1-\beta)\theta_t}{1-\beta^{t}}
vt=1−βtβvt−1+(1−β)θt来消除初期的偏差。
当
t
t
t变大时,
1
−
β
t
→
1
1-\beta^t\rightarrow1
1−βt→1,失去作用。
动量梯度下降法(Momentum)
令
v
d
w
=
β
v
d
w
+
(
1
−
β
)
d
w
v_{dw}=\beta v_{dw}+(1-\beta) dw
vdw=βvdw+(1−β)dw,
v
b
=
β
v
d
b
+
(
1
−
β
)
d
b
v_{b}=\beta v_{db}+(1-\beta)db
vb=βvdb+(1−β)db
w
=
w
−
α
V
d
w
w=w-\alpha V_{dw}
w=w−αVdw
b
=
b
−
α
V
d
b
b=b-\alpha V_{db}
b=b−αVdb
RMSprop
S
d
w
=
β
S
d
w
+
(
1
−
β
)
d
w
2
S_{dw}=\beta S_{dw}+(1-\beta)d_{w^2}
Sdw=βSdw+(1−β)dw2
S
d
b
=
β
S
d
b
+
(
1
−
β
)
d
b
2
S_{db}=\beta S_{db}+(1-\beta)d_{b^2}
Sdb=βSdb+(1−β)db2
w
=
w
−
α
d
w
S
d
w
+
ϵ
w=w-\alpha\frac{dw}{\sqrt{S_{dw}}+\epsilon}
w=w−αSdw+ϵdw
b
=
b
−
α
d
b
S
d
b
+
ϵ
b=b-\alpha\frac{db}{\sqrt{S_{db}}+\epsilon}
b=b−αSdb+ϵdb
(
ϵ
\epsilon
ϵ是为了防止分母为0设置的,通常为1e-8)
Adam(常用,结合了Momentum与RMSprop)
令
v
d
w
=
0
,
S
d
w
=
0
,
V
d
b
=
0
,
S
d
b
=
0
v_{dw}=0,S_{dw}=0,V_{db}=0,S_{db}=0
vdw=0,Sdw=0,Vdb=0,Sdb=0,通常令
β
1
=
0.9
,
β
2
=
0.999
,
ϵ
=
1
e
−
8
\beta_1=0.9,\beta_2=0.999,\epsilon=1e-8
β1=0.9,β2=0.999,ϵ=1e−8
在每一次迭代
t
t
t中,遍历每一个mini-batch,令
v
d
w
=
β
1
v
d
w
+
(
1
−
β
1
)
d
w
v_{dw}=\beta_{1}v_{dw}+(1-\beta_{1})dw
vdw=β1vdw+(1−β1)dw
v
d
b
=
β
1
v
d
b
+
(
1
−
β
1
)
d
b
v_{db}=\beta_{1}v_{db}+(1-\beta_{1})db
vdb=β1vdb+(1−β1)db
S
d
w
=
β
2
S
d
w
+
(
1
−
β
)
d
w
2
S_{dw}=\beta_{2}S_{dw}+(1-\beta)d_{w^2}
Sdw=β2Sdw+(1−β)dw2
S
d
b
=
β
2
S
d
b
+
(
1
−
β
)
d
b
2
S_{db}=\beta_{2}S_{db}+(1-\beta)d_{b^2}
Sdb=β2Sdb+(1−β)db2
(通常
β
1
\beta_1
β1取0.9,
β
2
\beta_2
β2取0.999)
偏差修正:
v
d
w
c
o
r
r
e
c
t
e
d
=
v
d
w
/
(
1
−
β
1
t
)
v^{corrected}_{dw}=v_{dw}/(1-\beta_1^t)
vdwcorrected=vdw/(1−β1t)
v
d
b
c
o
r
r
e
c
t
e
d
=
v
d
b
/
(
1
−
β
1
t
)
v^{corrected}_{db}=v_{db}/(1-\beta_1^t)
vdbcorrected=vdb/(1−β1t)
S
d
w
c
o
r
r
e
c
t
e
d
=
S
d
w
/
(
1
−
β
2
t
)
S^{corrected}_{dw}=S_{dw}/(1-\beta_2^t)
Sdwcorrected=Sdw/(1−β2t)
S
d
b
c
o
r
r
e
c
t
e
d
=
S
d
b
/
(
1
−
β
2
t
)
S^{corrected}_{db}=S_{db}/(1-\beta_2^t)
Sdbcorrected=Sdb/(1−β2t)
w
=
w
−
α
v
d
b
c
o
r
r
e
c
t
e
d
S
d
b
c
o
r
r
e
c
t
e
d
+
ϵ
w=w-\alpha\frac{v^{corrected}_{db}}{\sqrt{S^{corrected}_{db}}+\epsilon}
w=w−αSdbcorrected+ϵvdbcorrected
b
=
b
−
α
v
d
b
c
o
r
r
e
c
t
e
d
S
d
b
c
o
r
r
e
c
t
e
d
+
ϵ
b=b-\alpha\frac{v^{corrected}_{db}}{\sqrt{S^{corrected}_{db}}+\epsilon}
b=b−αSdbcorrected+ϵvdbcorrected
学习率衰减(学习率随着时间降低)
对于每一轮epoch,令
α
=
α
0
1
+
衰减率
∗
e
p
o
c
h
轮次
\alpha=\frac{\alpha_0}{1+衰减率*epoch轮次}
α=1+衰减率∗epoch轮次α0
其中
α
0
\alpha_0
α0为初始学习率,与衰减率一样都是超参数。
也有令
α
=
k
e
p
o
c
h
轮次
∗
a
0
\alpha=k^{epoch轮次}*a_0
α=kepoch轮次∗a0等其他式子
七、微调超参数
调试处理
学习率
α
\alpha
α
动量
β
\beta
β
隐藏层数
mini-batch大小
选择一些随机的点,便于更快的找到合适的超参数。
为超参数选择合适的范围
隐藏层数:区间随机均匀取值
学习率:先取对数划分区间,再随机均匀取值(如以0.001,0.01,0.1作为分界点)
动量:指数加权平均划分区间,再随机均匀取值(如以0.9,0.99,0.999作为分界点)
照看模型(算力不足时采用):每隔一段时间观察训练情况,手动调整学习率。
并行训练(算力充足时采用):同时跑多个,选择参数表现最优秀的。
正则化网络的激活函数/Batch归一化(Batch Norm)
正规化上一个隐藏层的数据,使得其平均值与方差归一,便于后续层的的训练。
(如果由每一层的
w
w
w与
b
b
b组成的集合中方差与平均值差距过大,会增加训练的难度(点过于分散,难以收敛),归一化后可以使数据相对比较“集中”的状态,使得后续层的收敛变得更快。)
对于第
l
l
l层,
μ
=
1
m
∑
i
=
1
M
Z
[
l
]
(
i
)
\mu=\frac{1}{m}\sum_{i=1}^{M}Z^{[l](i)}
μ=m1∑i=1MZ[l](i)
σ
2
=
1
m
∑
i
=
1
M
(
Z
[
l
]
(
i
)
−
μ
)
2
\sigma^2=\frac{1}{m}\sum_{i=1}^{M}(Z^{[l](i)}-\mu)^2
σ2=m1∑i=1M(Z[l](i)−μ)2
Z
n
o
r
m
[
l
]
(
i
)
=
Z
[
l
]
(
i
)
−
μ
σ
2
+
ϵ
Z_{norm}^{[l](i)}=\frac{Z^{[l](i)}-\mu}{\sqrt{\sigma^2+\epsilon}}
Znorm[l](i)=σ2+ϵZ[l](i)−μ(和之前的归一化一样,期望变为0,方差变为1)
Z
~
[
l
]
(
i
)
=
w
Z
n
o
r
m
[
l
]
(
i
)
+
b
\tilde{Z}^{[l](i)}=wZ_{norm}^{[l](i)}+b
Z~[l](i)=wZnorm[l](i)+b
(类似线性ReLU单元,将每一个神经元的数据归一化之后整合,使其平均值与方差变成其他的,特别的,令
w
=
σ
2
+
ϵ
,
b
=
μ
w=\sqrt{\sigma^2+\epsilon},b=\mu
w=σ2+ϵ,b=μ,则
Z
n
o
r
m
[
l
]
(
i
)
=
Z
[
l
]
(
i
)
Z_{norm}^{[l](i)}=Z^{[l](i)}
Znorm[l](i)=Z[l](i),可利用之前的优化算法来不断地更新
w
w
w与
b
b
b)
(对于代码实现,可以直接用batch_normalization来实现)
再mini-batch中使用时,对于
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]而言,归一化时需要先减去平均值再除以标准差,因此不论
b
[
l
]
b^{[l]}
b[l]是多少都会被减掉不参与计算。
因此
Z
~
[
l
]
(
i
)
=
w
Z
n
o
r
m
[
l
]
(
i
)
+
β
[
l
]
\tilde{Z}^{[l](i)}=wZ_{norm}^{[l](i)}+\beta^{[l]}
Z~[l](i)=wZnorm[l](i)+β[l],其中
β
[
l
]
\beta^{[l]}
β[l]为控制参数,去影响转移的条件。
可以将Batch Norm与DropOut一期使用,在数据归一化后,前后层的数据依赖性会略微减弱,因此使用DropOut的影响减小。但使用较大的Mini-batch大小时会减弱正则化效果。
Batch归一化在测试时的使用
在测试神经网络时,需要用指数加权平均/流动平均来估算/追踪 μ \mu μ与 σ 2 \sigma^2 σ2的值。
Softmax回归(logistic回归的一般形式,适用于非二分分类问题)
每一个元素的激活函数的值代表某一类情况发生的概率。
我们假设某一层的神经元个数为
m
l
m_l
ml。
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]
Softmax激活函数:
t
=
e
(
z
[
l
]
)
t=e^{(z^{[l]})}
t=e(z[l])(对向量
z
[
l
]
z^{[l]}
z[l]中每个元素取一次自然指数)
a
[
l
]
=
e
(
z
[
l
]
)
∑
i
=
1
m
l
t
i
a^{[l]}=\frac{e^{(z^{[l]})}}{\sum_{i=1}^{m_l}{t_i}}
a[l]=∑i=1mltie(z[l])(向量中的每个元素都除以向量中元素之和,使其内部的元素之和为1,结果代表着概率。)
(与之前的sigmoid函数与ReLU不同的是,softmax的激活函数是输入一个向量,输出一个向量,而不再是一个数字。)
如何训练Softmax激活函数
Loss函数:
L
(
y
^
,
y
)
=
−
∑
i
=
1
m
[
l
]
y
i
l
o
g
y
i
^
\mathscr{L}(\hat{y},y)=-\sum_{i=1}^{m_{[l]}}{y_ilog\hat{y_i}}
L(y^,y)=−∑i=1m[l]yilogyi^
(由定义可知
y
,
y
^
y,\hat{y}
y,y^∈ [0,1],易知
y
i
y_i
yi越大,
L
(
y
^
,
y
)
\mathscr{L}(\hat{y},y)
L(y^,y)越小。)
J
(
w
[
1
]
,
b
[
1
]
.
.
.
)
=
1
m
∑
i
=
1
m
L
(
y
^
,
y
)
J(w^{[1]},b^{[1]}...)=\frac{1}{m}\sum_{i=1}^{m}\mathscr{L}(\hat{y},y)
J(w[1],b[1]...)=m1∑i=1mL(y^,y)
同之前的计算,为了便利,将所有的
y
y
y与
y
^
\hat{y}
y^的向量合并,分别形成一个大矩阵,即
Y
=
[
y
(
0
)
y
(
1
)
.
.
.
y
(
m
)
]
Y=\left [ \begin{matrix} y^{(0)} & y^{(1)} & ... & y^{(m)} \\ \end{matrix} \right ]
Y=[y(0)y(1)...y(m)]
Y
^
=
[
y
^
(
0
)
y
^
(
1
)
.
.
.
y
^
(
m
)
]
\hat{Y}=\left [ \begin{matrix} \hat{y}^{(0)} & \hat{y}^{(1)} & ... & \hat{y}^{(m)} \\ \end{matrix} \right ]
Y^=[y^(0)y^(1)...y^(m)]
反向传播:
d
z
[
l
]
=
(
y
^
−
y
)
dz^{[l]}=(\hat{y}-y)
dz[l]=(y^−y)(即
∂
J
∂
z
[
l
]
\frac{\partial J}{\partial z^{[l]}}
∂z[l]∂J,计算原理同之前)
八、机器学习策略
正交化
分离各种作用的因素,使得两两尽量互不相关,通过调整这些因素进行微调训练。(类似“控制变量法”,分离互相独立的因素)
单一数字评估指标
当评估性能时是多个指标表现时,有时很难选出最佳的选择,因此要定义单一数字,来综合评估多个指标的综合表现。
(这也是使用F1指数来综合准确率与召回率二者的原因,它是二者的调和平均)
满足与优化指标
当评估性能时是多个指标表现时,可以指定其中一个为优化指标(尽可能优秀),其余的为满足指标(必须达到要求)
人类表现
贝叶斯最优错误率(也就是概念意义上的Optimal):理论情况下机器学习所能达到的最大准确值。
通常而言,人类的理论错误率与贝叶斯最优错误率相似。
可避免偏差:目前错误率与贝叶斯最优错误率的差值
优化策略
比对训练集错误率与开发集错误率之差与人类表现错误率与训练集错误率之差。
若前者差距更大,则说明方差较大,需要考虑正则化。
若后者差距更大,则说明偏差较大,需要考虑构建更大的神经网络/优化算法。
当算法的表现已经超越人类表现错误率之后,优化会变得更加困难。
改善模型表现
减少偏差&方差
减少偏差:
- 训练更大的模型
- 训练更优的算法(momentum、RMSprop、Adam等优化算法)
- 使用RNN/CNN
减少方差:
1.训练更多数据
2.正则化(L2,Dropout等)
3.采用更合适的神经网络与超函数。
九、误差分析
统计不同类型错误的占比与分布
划分一张表格将各种错误类型归类,并以此归纳与总结问题。
清除标注错误的数据
在表格中额外增加“未标注正确”一列,统计其占比来归纳错误。
通常,只要数据集足够大,轻微的标注错误没有太大影响。
如果要修正标注数据,一定要把开发集和测试集的数据都修正。
不仅仅要检查算法判断错误的个例,算法判断正确的个例也需要验证!
搭建系统原型
在系统原型搭建完成后,需要进行偏差/方差测试与上述的错误评估分析,随后开始不停迭代。
在不同分布的数据集上训练
当需要将不同分布的数据集混合起来训练时,开发集和测试集一定要根据系统需要侧重的需求来选择数据集。
(比如需要做文字处理识别时,有做好标注的数据集与随机收集的聊天记录,开发集和测试集就应该要以聊天记录的数据为主。)
迁移学习
在已经训练好的神经网络基础上,进行一定程度的改进来实现其他的需求而无需重新开始训练。如预训练与微调。(比如调整神经网络的最后若干层,根据自己的需要进行调整,前面不涉及变动的层参数就像是被“冻结”/freeze了)
多任务学习
让单个神经网络同时做几件事情,即最后一层的多个神经元分别代表每一种工作的结果。
因此Loss函数得到的结果不再是一个数,而是一个向量。
在某些场合下,让单个神经网络做多件事情比用多个独立的神经网络分别完成性能更好。
- 这些任务可以共用低隐藏层的特征(比如识别一张图中分别有什么物体时,低层次的物体特征是可以共用的。)
- 各个任务的数据量很接近
- 训练的神经网络较大
端到端的深度学习(适用数据量比较大的情况)
直接输入不经过特征处理的原始数据,输出需要的结果,一步到位。
十、计算机视觉(CV)
卷积神经网络/CNN由卷积层、池化层、全连接层组成,卷积层是最核心,但也是最容易构建的层。
通常卷积层和池化层会被合并叫做CNN的“一层”。
边缘检测
假定以下滤波器矩阵都是
f
×
f
f\times f
f×f(
f
f
f通常为奇数),图像矩阵都是
n
×
n
n\times n
n×n的灰度照片(即没有RGB三通道)。以下假定
f
=
3
,
n
=
6
f=3,n=6
f=3,n=6
将图片的原矩阵与过滤器矩阵做卷积运算,得到的矩阵大小是
(
n
−
f
+
1
)
×
(
n
−
f
+
1
)
(n-f+1)\times(n-f+1)
(n−f+1)×(n−f+1)。
(选取与过滤器大小相同的子矩阵
S
S
S与过滤器
F
F
F,则卷积结果
c
i
j
=
∑
∑
S
i
j
∗
F
i
j
c_{ij}=\sum\sum{S_{ij}*F_{ij}}
cij=∑∑Sij∗Fij)
tf.nn.conv2d()
过滤器矩阵中的正数表示亮边,负数表示暗边,0表示交界线。
边缘检测
用
[
1
0
−
1
1
0
−
1
1
0
−
1
]
\left [ \begin{matrix} 1& 0 & -1 \\ 1& 0 & -1 \\ 1& 0 & -1 \\ \end{matrix} \right ]
111000−1−1−1
来检测图像中是否有垂直边缘,卷积结果中数值非0的位置表示垂直边的所在处。同理用
[
1
1
1
0
0
0
−
1
−
1
−
1
]
\left [ \begin{matrix} 1& 1 & 1 \\ 0& 0 & 0 \\ -1& -1& -1 \\ \end{matrix} \right ]
10−110−110−1
检测是否有水平边缘。
Sobel滤波器:
[
1
0
−
1
2
0
−
2
1
0
−
1
]
\left [ \begin{matrix} 1& 0 & -1 \\ 2& 0 & -2 \\ 1& 0 & -1 \\ \end{matrix} \right ]
121000−1−2−1
Scharr滤波器:
[
3
0
−
3
10
0
−
10
3
0
−
3
]
\left [ \begin{matrix} 3& 0 & -3 \\ 10& 0 & -10 \\ 3& 0 & -3 \\ \end{matrix} \right ]
3103000−3−10−3
事实上,过滤器矩阵的系数可以理解为9个超参数,通过反向传播来不断地学习以此找到最佳的系数。
Padding/填充
在卷积运算中,图片矩阵会逐渐变小。且多次卷积会使图片矩阵边界的信息丢失。
考虑在卷积操作前填充图片矩阵,记向外填充的层数为
p
p
p,即原本矩阵变为
(
n
+
2
p
)
×
(
n
+
2
p
)
(n+2p)\times(n+2p)
(n+2p)×(n+2p)。在卷积后变为
(
n
+
2
p
−
f
+
1
)
×
(
n
+
2
p
−
f
+
1
)
(n+2p-f+1)\times(n+2p-f+1)
(n+2p−f+1)×(n+2p−f+1)。
我们假设令
p
=
1
p=1
p=1,则前后卷积后矩阵大小不变。
通常填充的元素可以是0。
(不使用Padding进行卷积被称为Valid卷积,使用Padding且卷积前后输出不变的的被称为Same卷积。此时
2
p
−
f
+
1
=
0
2p-f+1=0
2p−f+1=0,因此
f
f
f通常为奇数。)
卷积步长(Stride)
步长:在遍历每一个子矩阵时,子矩阵间隔的长度,以下简称为
s
s
s。
(如图所示,
s
=
2
s=2
s=2,则第一个子矩阵是
[
2
3
7
6
6
9
3
4
8
]
\left [ \begin{matrix} 2 & 3 & 7 \\ 6 & 6 & 9 \\ 3 & 4 & 8 \\ \end{matrix} \right ]
263364798
,第二个则是
[
7
4
6
9
8
7
8
3
8
]
\left [ \begin{matrix} 7 & 4 & 6 \\ 9 & 8 & 7 \\ 8 & 3 & 8 \\ \end{matrix} \right ]
798483678
)
因此卷积后的图片矩阵大小为
(
⌊
n
+
2
p
−
f
s
⌋
+
1
)
×
(
⌊
n
+
2
p
−
f
s
⌋
+
1
)
(\lfloor\frac{n+2p-f}{s}\rfloor+1)\times(\lfloor\frac{n+2p-f}{s}\rfloor+1)
(⌊sn+2p−f⌋+1)×(⌊sn+2p−f⌋+1)。
(数学意义上的卷积需要先对矩阵作沿着次对角线转置。信号处理时不需要!)
如
[
3
4
5
1
0
2
−
1
9
7
]
\left [ \begin{matrix} 3 & 4 & 5 \\ 1 & 0 & 2\\ -1 & 9 & 7 \\ \end{matrix} \right ]
31−1409527
变为
[
7
2
5
9
0
4
−
1
1
3
]
\left [ \begin{matrix} 7 & 2 & 5 \\ 9 & 0 & 4\\ -1 & 1 & 3 \\ \end{matrix} \right ]
79−1201543
三维卷积
对于RGB图像,有三个颜色通道,因此图像矩阵的层数
n
c
n_c
nc为3,变为了
6
×
6
×
3
6\times6\times3
6×6×3。
过滤器矩阵也变为
3
×
3
×
3
3\times3\times3
3×3×3。
(不论过滤器的维度如何,“层数”必须相同!)
整体与一维卷积类似,每次选出
f
×
f
×
3
f\times f\times 3
f×f×3个数字,分别与图片矩阵相乘后将所有的数字相加得到结果。
滤波器矩阵为
f
×
f
×
n
c
f\times f\times n_c
f×f×nc,图像矩阵为
n
×
n
×
n
−
c
n\times n \times n-c
n×n×n−c。卷积得到的矩阵大小是
(
n
−
f
+
1
)
×
(
n
−
f
+
1
)
×
n
c
(n-f+1)\times(n-f+1)\times n_c
(n−f+1)×(n−f+1)×nc。
多重过滤器(同时检测出多条边缘)
分别对每个过滤器做卷积运算,然后合并成一个多通道的矩阵。
单层卷积网络
把过滤器看做
w
[
l
]
w^{[l]}
w[l],则卷积方程结果为
w
[
l
]
a
[
l
−
1
]
w^{[l]}a^{[l-1]}
w[l]a[l−1],在加上
b
[
l
]
b^{[l]}
b[l](ReLU)
若有10个过滤器,每一个都是
3
×
3
×
3
3\times3\times3
3×3×3的矩阵。则一共有(
10
∗
(
3
∗
3
∗
3
+
1
(
b
[
l
]
)
)
=
280
10*(3*3*3+1(b^{[l]}))=280
10∗(3∗3∗3+1(b[l]))=280个参数)
神经网络的过滤器参数个数与原图片大小无关!(避免过拟合)
一个简单卷积网络示例
第一层:图片矩阵为
39
×
39
×
3
,
f
[
l
]
=
3
,
s
[
l
]
=
1
,
p
[
l
]
=
0
39\times 39\times 3,f^{[l]}=3,s^{[l]}=1,p^{[l]}=0
39×39×3,f[l]=3,s[l]=1,p[l]=0,共10个过滤器,卷积结果为
37
×
37
×
10
37\times37\times10
37×37×10。(
39
−
3
+
1
=
37
39-3+1=37
39−3+1=37)
第二层:图片矩阵为
37
×
37
×
10
,
f
[
l
]
=
5
,
s
[
l
]
=
2
,
p
[
l
]
=
0
37\times 37\times 10,f^{[l]}=5,s^{[l]}=2,p^{[l]}=0
37×37×10,f[l]=5,s[l]=2,p[l]=0,共20个过滤器,卷积结果为
17
×
17
×
20
17\times17\times20
17×17×20。(
⌊
37
−
5
2
⌋
+
1
=
17
\lfloor\frac{37-5}{2}\rfloor+1=17
⌊237−5⌋+1=17)
第二层:图片矩阵为
17
×
17
×
20
,
f
[
l
]
=
5
,
s
[
l
]
=
2
,
p
[
l
]
=
0
17\times 17\times 20,f^{[l]}=5,s^{[l]}=2,p^{[l]}=0
17×17×20,f[l]=5,s[l]=2,p[l]=0,共40个过滤器,卷积结果为
7
×
7
×
40
7\times7\times40
7×7×40。(
⌊
17
−
5
2
⌋
+
1
=
7
\lfloor\frac{17-5}{2}\rfloor+1=7
⌊217−5⌋+1=7)
(可以注意到,每一层的过滤器个数在逐渐变多。)
CNN的池化层
超参数只有过滤器大小 f f f与步长 s s s(最常用 f = 2 / 3 , s = 2 f=2/3,s=2 f=2/3,s=2,一般令 p = 0 p=0 p=0,相当于图像缩小了一倍)
最大池化(最常用)
如图所示,对于一个
n
×
n
n\times n
n×n的矩阵,令
f
=
2
,
s
=
2
f=2,s=2
f=2,s=2,得到一个
⌊
n
−
f
s
⌋
+
1
\lfloor\frac{n-f}{s}\rfloor+1
⌊sn−f⌋+1的矩阵,每个矩阵表示
f
×
f
f\times f
f×f的子矩阵中的最大值,多层数的矩阵同理。
平均池化
基本原理同上,只是将最大值变为了平均值。
CNN的全连接层
同普通的全连接神经网络类似,把前面得到的多通道矩阵转化为一维向量导入到全连接层,通常会有若干个全连接层,最后得到结果。
为什么选择卷积
卷积本身属于一种稀疏连接的方式而非全连接(每次只是子矩阵和过滤器在运算而非整个矩阵),因此可以大大减小开销(参数的个数仅仅由过滤器大小决定而非图片大小)
参数共享:某些特征提取(如边界检测)不仅会对图片的某一部分有用,也可能会对另一部分有用。
(类似地,Loss函数
J
(
w
[
1
]
,
b
[
1
]
.
.
.
)
=
1
m
∑
i
=
1
m
L
(
y
^
,
y
)
J(w^{[1]},b^{[1]}...)=\frac{1}{m}\sum_{i=1}^{m}\mathscr{L}(\hat{y},y)
J(w[1],b[1]...)=m1∑i=1mL(y^,y))
计算机视觉领域下的数据增强(解决数据量不足的问题)
- 图片镜像对称
- 图片随机裁剪(不失去主体信息)
- 色彩转化(调整颜色通道,增加若干失真值来生成新图片,也会使训练的结果更具有健壮性)
可以采用CPU多线程的方式对一个mini-batch内的图片做并行的数据增强处理。
十一、计算机视觉实例探究
经典架构
LeNet-5
将一个卷积层和池化层视为一层,两层神经网络后,再两层全连接层得到结果。
AlexNet(激活函数选择了ReLU)
第一次使用线性激活函数,除了第一次采用Valid卷积,其余都采用Same卷积(即填充保持卷积前后大小不变)
VGG-16(参数很多,但结构上简化的神经网络)
16次卷积层+最大池化操作后全连接16层,全部都是Same卷积,每一次卷积的过滤器次数成倍增加。
残差网络(ResNet)
残差单元:下一层的结果将不止由上一层确定,还与之前层的结果决定。
eg:
a
[
l
+
2
]
=
g
(
z
[
l
+
1
]
+
a
[
l
]
)
a^{[l+2]}=g(z^{[l+1]}+a^{[l]})
a[l+2]=g(z[l+1]+a[l])
与之前层连接的路线被称为“捷径”(shortcut)
残差网络有利于梯度下降与防止梯度消失&梯度爆炸的问题。
采用了Same卷积保证前后尺寸不变。
卷积层+池化层。
Inception网络
网络中的网络/1x1卷积
1x1的过滤器可以令矩阵的每一个数都同乘一个数,前后图片尺寸大小不变。
可以用于压缩通道个数。
Inception网络原理
(提前预输入一些过滤器的大小与池化操作,让系统自己决定在池化时使用什么操作)
先用1x1卷积降低通道数后再做Same卷积。
较为特殊的是,为了保证前后维度一致,在Inception网络模块池化时,需要用到Padding!
将不同卷积的结果进行连接,形成一个巨大通道的矩阵。
Inception网络模块(基本单位)
由
1
×
1
,
3
×
3
,
5
×
5
1\times1,3\times 3,5\times 5
1×1,3×3,5×5的过滤器与带Padding的最大池化层组成。
事实上,除了Inception网络模块,仍然存在少量的全连接层(后面跟着Softmax),用来避免过拟合。
十二、目标定位(检测图片中的物体并定位)
定位某个物体的位置,并输出物体所在位置矩形边界框的四个坐标。
特征点检测:通过定位各种需要的特征点坐标来实现对于需求功能的实现。
检测目标存在
滑动窗口检测算法(计算成本大)
先选定一个特定大小的滑动窗口,并将其置入卷积网络,来判断滑动窗口内是否有目标。若不存在目标,则考虑适当调整滑动窗口的大小。
在卷积网络上的实现
把CNN的全连接层变为全新的卷积层
如图,对于池化后的
5
×
5
×
16
5\times 5 \times 16
5×5×16的矩阵,采用
5
×
5
5\times 5
5×5的过滤器,使其变成
1
×
1
1\times 1
1×1(类似原本全连接层变为一维向量的操作)
Bounding Box/边界框检测
YOLO算法
用网格将图片分割为多个区域,每一个网格对应一个输出向量,标注了是否有目标存在及其边界框坐标。
边界框大小可以超出分割区域。
对于每个分割的单元,设置两个边界框(anchor box),并舍去准确率较低的(
p
c
≤
0.6
p_c\leq 0.6
pc≤0.6),最后执行非极大值抑制。
因为是用卷积实现的,因此有参数共享,可以加快运算时间。
交并比(IoU,计算两个边界框的交集与并集之比)
如果一个区域附近有很多的边界框,则计算其IoU,
若
I
o
U
≥
0.5
IoU\geq0.5
IoU≥0.5则检测正确。
非极大值抑制(避免同一物体被检测多次)
先找到匹配程度 p c p_c pc最高的边界框(采用 p c ≥ 0.6 p_c\geq0.6 pc≥0.6且最大的边界框),将其“高亮”标注,随后非极大值抑制算法就会去除与之IoU很高的边界框,避免重复检测。
Anchor Box(锚定边界,让一个边界框内可以检测出多个物体)
(事实上,当划分的格子颗粒度越小,就越难在一个框内检测出多个物体)
定义若干个Anchor box,让每个边界框的记录矩阵多若干个分量。
候选区域
带区域的卷积神经网络(R-CNN)
不再像滑动窗口那样遍历每一个框,而是用图像分割算法寻找不同的色块作为候选区域进行检测。
分割算法提供的色块不一定准确,需要在此基础上进行检测,找到更加精确的边界框。
十三、人脸识别
人脸识别与活体检测是两个核心的目标。
一次学习(每次新的人脸加入时无需重新学习整个网络)
相似度函数:
d
(
i
m
g
1
,
i
m
g
2
)
=
d(img1,img2)=
d(img1,img2)=两张图片的差异程度,
设置一个阈值
τ
\tau
τ,当
d
(
i
m
g
1
,
i
m
g
2
)
≤
τ
d(img1,img2)\leq \tau
d(img1,img2)≤τ时认为是同一个人。
Siamese 网络
对于一张图片
X
X
X,将CNN的最后一层全连接层的结果作为向量
f
(
X
)
f(X)
f(X)。
令
d
(
X
(
1
)
,
X
(
2
)
)
=
∣
∣
f
(
X
(
1
)
)
−
f
(
X
(
2
)
)
∣
∣
2
2
d(X^{(1)},X^{(2)})=||f(X^{(1)})-f(X^{(2)})||_2^{2}
d(X(1),X(2))=∣∣f(X(1))−f(X(2))∣∣22
(L2范数/平方范数:
∣
∣
w
∣
∣
2
2
=
∑
j
=
1
n
x
w
j
2
=
w
T
w
||w||_2^2=\sum_{j=1}^{n_x}w_j^2=w^Tw
∣∣w∣∣22=∑j=1nxwj2=wTw)
Triplet/三元组Loss
将 锚定图像(A)、正确图像(P)与错误图像(N) 三个作为一个元组。
(A与P是同一个人,A与N不是同一个人)
我们期望
d
(
A
,
P
)
≤
d
(
A
,
N
)
d(A,P)\leq d(A,N)
d(A,P)≤d(A,N),但如果
f
(
X
)
≡
0
f(X)\equiv0
f(X)≡0则式子必定成立,
因此要求
d
(
A
,
P
)
−
d
(
A
,
N
)
+
α
≤
0
d(A,P)-d(A,N)+\alpha\leq0
d(A,P)−d(A,N)+α≤0(
α
\alpha
α也被称为间隔/margin)
Loss函数
L
(
A
,
P
,
N
)
=
m
a
x
(
0
,
d
(
A
,
P
)
−
d
(
A
,
N
)
+
α
)
\mathscr{L}(A,P,N)=max(0,d(A,P)-d(A,N)+\alpha)
L(A,P,N)=max(0,d(A,P)−d(A,N)+α)
(只要
d
(
A
,
P
)
−
d
(
A
,
N
)
+
α
d(A,P)-d(A,N)+\alpha
d(A,P)−d(A,N)+α不大于0,说明三元组符合要求)
J
=
∑
i
=
1
m
L
(
A
(
i
)
,
P
(
i
)
,
N
(
i
)
)
J=\sum_{i=1}^{m}{\mathscr{L}(A^{(i)},P^{(i)},N^{(i)})}
J=∑i=1mL(A(i),P(i),N(i))
(在训练时,要尽量选择
d
(
A
,
P
)
d(A,P)
d(A,P)与
d
(
A
,
N
)
d(A,N)
d(A,N)差距不大的,让神经网络能够区分并放大细微的差别,使得效果更好。)
面部验证&转化为二分分类
定义:如果两张照片是同一个人则输出1,否则为0,则转化为二分分类问题,可以使用sigmoid函数。在最后额外添加一层进行计算。
令
y
^
=
σ
(
∑
k
=
1
w
k
∣
f
(
X
(
k
)
(
1
)
)
−
f
(
X
(
k
)
(
2
)
)
∣
+
b
)
\hat{y}=\sigma(\sum_{k=1}{w_k|f(X^{(1)}_{(k)})-f(X^{(2)}_{(k)})|+b})
y^=σ(∑k=1wk∣f(X(k)(1))−f(X(k)(2))∣+b)(此处的下标
k
k
k表示向量上的第
k
k
k个分量)
或令
y
^
=
σ
(
∑
k
=
1
w
i
(
f
(
X
(
k
)
(
1
)
)
−
f
(
X
(
k
)
(
2
)
)
)
2
f
(
X
(
k
)
(
1
)
)
+
f
(
X
(
k
)
(
2
)
)
+
b
)
\hat{y}=\sigma(\sum_{k=1}{w_i\frac{(f(X^{(1)}_{(k)})-f(X^{(2)}_{(k)}))^2}{f(X^{(1)}_{(k)})+f(X^{(2)}_{(k)})}+b})
y^=σ(∑k=1wif(X(k)(1))+f(X(k)(2))(f(X(k)(1))−f(X(k)(2)))2+b)(
χ
2
\chi^2
χ2相似度)
神经风格迁移
在图像处理中,将图案的色彩风格迁移到其他的图片上,生成新的图片。
Loss函数
对于原图
C
C
C,图片风格
S
S
S,生成图片
G
G
G,
定义Loss函数
J
(
G
)
=
α
J
内容
(
C
,
G
)
+
β
J
风格
(
S
,
G
)
J(G)=\alpha J_{内容}(C,G)+\beta J_{风格}(S,G)
J(G)=αJ内容(C,G)+βJ风格(S,G)
(即内容上的差异与风格上的差异加权总和,其中
α
\alpha
α与
β
\beta
β是超参数)
每次反向传播时用
G
=
G
−
∂
J
(
G
)
∂
G
G=G-\frac{\partial J(G)}{\partial G}
G=G−∂G∂J(G)来更新
G
G
G的像素值。
内容Loss函数
对于某个预训练神经网络的第
l
l
l层,将原图
C
C
C与
G
G
G的整一层的激活函数值作比较,如果值相似,说明图片相似。
J
内容
[
l
]
(
C
,
G
)
=
1
2
∣
∣
a
[
l
]
(
C
)
−
a
[
l
]
(
G
)
∣
∣
2
J_{内容}^{[l]}(C,G)=\frac{1}{2}||a^{[l](C)}-a^{[l](G)}||^2
J内容[l](C,G)=21∣∣a[l](C)−a[l](G)∣∣2(结果是一个向量)
风格Loss函数
定义Gram矩阵/风格矩阵
G
[
l
]
(
S
)
G^{[l](S)}
G[l](S)为一个
n
c
[
l
]
×
n
c
[
l
]
n_c^{[l]}\times n_c^{[l]}
nc[l]×nc[l]大小的矩阵(
n
c
[
l
]
n_c^{[l]}
nc[l]为第
l
l
l层的通道数),使得
a
(
i
,
j
,
k
)
[
l
]
a^{[l]}_{(i,j,k)}
a(i,j,k)[l]代表在神经网络第
l
l
l层中,原矩阵中坐标为
(
i
,
j
,
k
)
(i,j,k)
(i,j,k)的位置。
那么对于通道
k
k
k与
k
′
k'
k′的相关系数
G
k
k
′
[
l
]
=
∑
i
∑
j
a
(
i
,
j
,
k
)
[
l
]
a
(
i
,
j
,
k
′
)
[
l
]
G^{[l]}_{kk'}=\sum_{i}\sum_{j}a^{[l]}_{(i,j,k)}a^{[l]}_{(i,j,k')}
Gkk′[l]=∑i∑ja(i,j,k)[l]a(i,j,k′)[l]
如果两个通道相关,则
G
k
k
′
[
l
]
G^{[l]}_{kk'}
Gkk′[l]越大。
J
风格
[
l
]
(
S
,
G
)
=
∣
∣
G
k
k
′
[
l
]
(
S
)
−
G
k
k
′
[
l
]
(
G
)
∣
∣
F
2
J_{风格}^{[l]}(S,G)=||G^{[l](S)}_{kk'}-G^{[l](G)}_{kk'}||^2_F
J风格[l](S,G)=∣∣Gkk′[l](S)−Gkk′[l](G)∣∣F2(弗罗贝尼乌斯范数,结果是一个矩阵)
(也可以额外定义一些超参数
w
i
w_i
wi使得
J
风格
(
S
,
G
)
=
∑
l
w
l
∗
J
风格
[
l
]
(
S
,
G
)
J_{风格}(S,G)=\sum_{l}{w_l*J_{风格}^{[l]}(S,G)}
J风格(S,G)=∑lwl∗J风格[l](S,G))
将一维数据推广到三维数据
一维与二维的数据要用一维与二维的过滤器来实现卷积操作。
同理三维的也需要用三维过滤器来实现。