这里可能用很多错误内容,不建议阅读,我最近在看Residual Neural Network,以前对NN都不太了解。只是写一下加强印象。
NN学习笔记(Neural Network)
NN的框框
图1 不同的NN模型图示(标准神经网络,卷积神经网络,循环神经网络)
标准的NN一般用于做预测,CNN一般用于图像识别,RNN一般用于处理一维数据(时序数据)。
符号表示
对于一个训练样本来说,他可能是一张 64 × 64 64\times 64 64×64,RGB通道的图片,那么令样本 x x x为这个图片展开后的数组,大小为 n x = 12288 n_x=12288 nx=12288。对应的,有一个标签 y y y,可能用来表示这张图片里面是否有一只猫, y ∈ { 0 , 1 } y\in\{0,1\} y∈{0,1}。记这样的 ( x , y ) (x,y) (x,y)为一个带标签的样本。
如果说我们有 m m m个训练样本,记为 m = m t r a i n m=m_{train} m=mtrain, m t e s t m_{test} mtest个测试样本。分别为: ( x ( 1 ) , y ( 1 ) ) , ( x ( 2 ) , y ( 2 ) ) , ⋯ , ( x ( m ) , y ( m ) ) (x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),\cdots,(x^{(m)},y^{(m)}) (x(1),y(1)),(x(2),y(2)),⋯,(x(m),y(m))。
那可以用一个矩阵来表示他:
X
=
[
x
(
1
)
,
x
(
2
)
,
…
,
x
(
m
)
]
∈
R
n
x
×
m
,
Y
=
[
y
(
1
)
,
y
(
2
)
,
…
,
y
(
m
)
]
∈
R
1
×
m
X=\left[x^{(1)}, x^{(2)}, \ldots, x^{(m)}\right] \in \mathbb{R}^{n_{x} \times m}, Y=\left[y^{(1)}, y^{(2)}, \ldots, y^{(m)}\right] \in \mathbb{R}^{1 \times m}
X=[x(1),x(2),…,x(m)]∈Rnx×m,Y=[y(1),y(2),…,y(m)]∈R1×m
逻辑回归
给定一个 x x x,想要得到的结果是 y ^ = P r [ y = 1 ∣ x ] \hat{y}=Pr[y=1|x] y^=Pr[y=1∣x],即样本 x x x满足条件的概率。
x ∈ R n x x\in \R^{n_x} x∈Rnx,模型是 w ∈ R n x , b ∈ R w\in \R^{n_x},b\in \R w∈Rnx,b∈R。
在线性回归里面是: y ^ = w T x + b \hat{y}=w^Tx +b y^=wTx+b,但这样得到的结果是不在 [ 0 , 1 ] [0,1] [0,1]区间内的。
所以在逻辑回归中: y ^ = σ ( w T x + b ) \hat{y}=\sigma(w^Tx+b) y^=σ(wTx+b),其中sigmoid函数 σ ( z ) = 1 1 + e − z , z = w T x + b \sigma(z)=\frac{1}{1+e^{-z}},z=w^Tx+b σ(z)=1+e−z1,z=wTx+b。
损失函数
逻辑回归中, z ( i ) = w T x ( i ) + b z^{(i)}=w^{T}x^{(i)}+b z(i)=wTx(i)+b, y ^ ( i ) = σ ( z ( i ) ) 1 ≤ i ≤ m \hat{y}^{(i)}=\sigma(z^{(i)})_{1\le i \le m} y^(i)=σ(z(i))1≤i≤m,目标是使 y ^ ( i ) ≈ y ( i ) \hat{y}^{(i)}\approx y^{(i)} y^(i)≈y(i)。
损失函数(loss function)的一种定义方法是 L ( y ^ , y ) = 1 2 ( y ^ − y ) 2 \mathcal{L}(\hat{y},y)=\frac{1}{2}(\hat{y}-y)^2 L(y^,y)=21(y^−y)2,但在逻辑回归中一般不这么做,
在逻辑回归中用到的损失函数是: ℓ ( y ^ , y ) = − ( y log y ^ + ( 1 − y ) log ( 1 − y ^ ) ) \ell(\hat{y},y)=-\left(y\log \hat{y} + (1-y) \log (1-\hat{y})\right) ℓ(y^,y)=−(ylogy^+(1−y)log(1−y^))。
定义成本函数(cost function)为:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
ℓ
(
y
^
(
i
)
,
y
(
i
)
)
=
−
1
m
(
y
(
i
)
log
y
^
(
i
)
+
(
1
−
y
(
i
)
)
log
(
1
−
y
^
(
i
)
)
)
J(w,b)=\frac{1}{m}\sum_{i=1}^{m}\ell(\hat{y}^{(i)},y^{(i)})=-\frac{1}{m}\left(y^{(i)}\log \hat{y}^{(i)} + (1-y^{(i)}) \log (1-\hat{y}^{(i)})\right)
J(w,b)=m1i=1∑mℓ(y^(i),y(i))=−m1(y(i)logy^(i)+(1−y(i))log(1−y^(i)))
为什么损失函数是这个:
注意到:
If
y
=
1
:
p
(
y
∣
x
)
=
y
^
If
y
=
0
:
p
(
y
∣
x
)
=
1
−
y
^
\begin{aligned} \text{If}\quad y=1&:\quad p(y|x)=\hat{y}\\ \text{If}\quad y=0&:\quad p(y|x)=1-\hat{y} \end{aligned}
Ify=1Ify=0:p(y∣x)=y^:p(y∣x)=1−y^
结合上面两个式子,可以得到
p
(
y
∣
x
)
=
y
^
y
(
1
−
y
^
)
1
−
y
p(y|x)=\hat{y}^y(1-\hat{y})^{1-y}
p(y∣x)=y^y(1−y^)1−y。
我们的目标是让 p ( y ∣ x ) p(y|x) p(y∣x)尽可能大,注意 log \log log是一个递增函数,就相当于让 − log ( p ( y ∣ x ) ) -\log(p(y|x)) −log(p(y∣x))尽可能小。也就得到了 L ( y ^ , y ) \mathcal{L}(\hat{y},y) L(y^,y)这个式子。
梯度下降
目标是找到一组
(
w
,
b
)
(w,b)
(w,b)使得
J
(
w
,
b
)
J(w,b)
J(w,b)最小,因此可以每次进行更新:
w
:
=
w
−
α
∂
J
(
w
,
b
)
∂
w
d
:
=
d
−
α
∂
J
(
w
,
b
)
∂
b
w:=w-\alpha \frac{\partial J(w,b)}{\partial w}\\ d:=d-\alpha\frac{\partial J(w,b)}{\partial b}
w:=w−α∂w∂J(w,b)d:=d−α∂b∂J(w,b)
其中
α
\alpha
α是学习率,后面是对
w
,
b
w,b
w,b分别求偏导。(偏导就是对有一个以上变量的函数中的某个变量求导的意思)
算法:
For i in [ 1 , m ] : z ( i ) = w T x ( i ) + b a ( i ) = σ ( z ( i ) ) J = + − [ y ( i ) log a ( i ) + ( 1 − y ( i ) ) log ( 1 − a ( i ) ) ] d z ( i ) = a ( i ) − y ( i ) For j in n x : d w j = + x j ( i ) d z ( i ) d b = + d z ( i ) J / = m , d w / = m , d b / = m \begin{aligned} &\text{For }i\text{ in }[1,m]:\\ &\quad z^{(i)}=w^Tx^{(i)}+b\\ &\quad a^{(i)}=\sigma(z^{(i)})\\ &\quad J\stackrel{+}=-\left[y^{(i)}\log a^{(i)}+(1-y^{(i)})\log(1-a^{(i)})\right]\\ &\quad \mathbf{d}z^{(i)}=a^{(i)}-y^{(i)}\\ &\quad \text{For }j\text{ in }n_x:\\ &\quad\quad \mathbf{d}w_j \stackrel{+}= x_j^{(i)}dz^{(i)}\\ &\quad\quad \mathbf{d}b \stackrel{+}= dz^{(i)}\\ &J/=m,\mathbf{d}w/=m,\mathbf{d}b/=m \end{aligned} For i in [1,m]:z(i)=wTx(i)+ba(i)=σ(z(i))J=+−[y(i)loga(i)+(1−y(i))log(1−a(i))]dz(i)=a(i)−y(i)For j in nx:dwj=+xj(i)dz(i)db=+dz(i)J/=m,dw/=m,db/=m
对 j ∈ [ 1 , n x ] j\in[1,n_x] j∈[1,nx]计算 w j = w j − α d w j w_j=w_j-\alpha \mathbf{d}w_j wj=wj−αdwj, b = b − α d b b=b-\alpha \mathbf{d}b b=b−αdb。
向量化(numpy)加速
可以取消上面 For i in [ 1 , m ] : \text{For }i\text{ in }[1,m]: For i in [1,m]:的循环,通过 X = [ x ( 1 ) , . . . , x ( m ) ] , Z = n p . d o t ( w . T , X ) + b , A = σ ( Z ) X=[x^{(1)},...,x^{(m)}],Z=np.dot(w.T,X)+b,A=\sigma(Z) X=[x(1),...,x(m)],Z=np.dot(w.T,X)+b,A=σ(Z),
非向量版本:
向量化版本:
def gradient():
Z=np.dot(w.T,X)+b
A=sigmoid(Z)
J= - (y*np.log(A) + (1-y)*np.log(1-A))/m
dZ = A-y
dw = X*dZ.T/m
db = np.sum(dZ)/m
return dw,db
def train():
iterations = 1000
lr = 0.01
for i in range(iterations):
dw,db = gradient()
w = w-lr*dw
b = b-lr*db
return w,b
残差神经网络
Residual Block
在通常情况下,一个深度神经网络中,记不同的激活层为 a [ l ] , a [ l + 1 ] , a [ l + 2 ] a^{[l]},a^{[l+1]},a^{[l+2]} a[l],a[l+1],a[l+2]。
变化方式为 a [ l ] ⟶ L i n e a r z [ l + 1 ] ⟶ R e L U a [ l + 1 ] ⟶ L i n e a r z [ l + 2 ] ⟶ R e L U a [ l + 2 ] a^{[l]} \stackrel{{\sf Linear}}\longrightarrow z^{[l+1]} \stackrel{\sf ReLU}\longrightarrow a^{[l+1]}\stackrel{{\sf Linear}}\longrightarrow z^{[l+2]}\stackrel{\sf ReLU}\longrightarrow a^{[l+2]} a[l]⟶Linearz[l+1]⟶ReLUa[l+1]⟶Linearz[l+2]⟶ReLUa[l+2]。
其中 L i n e a r : z [ l + 1 ] = W [ l + 1 ] a [ l ] + b [ l + 1 ] , R e L U : a l + 1 = g ( z [ l + 1 ] ) , g ( x ) = m a x ( 0 , x ) {\sf Linear}: z^{[l+1]}=W^{[l+1]}a^{[l]}+b^{[l+1]},{\sf ReLU}: a^{l+1}=g(z^{[l+1]}),g(x)=max(0,x) Linear:z[l+1]=W[l+1]a[l]+b[l+1],ReLU:al+1=g(z[l+1]),g(x)=max(0,x)。
Residual Block就是在执行下一个ReLU之前,将输入变为 z [ l + 1 ] ⊕ a [ l ] z^{[l+1]}\oplus a^{[l]} z[l+1]⊕a[l],或者说可以跳跃两个链接,得到 z [ l + 2 ] ⊕ a [ l ] z^{[l+2]}\oplus a^{[l]} z[l+2]⊕a[l]。
为什么Residue Network可以做的更深呢?
考虑在一个原本的Big NN后面加上一个Residue Block。
如果说这个模型本来就已经训练的不错了,加上最后一个Residue Block也只是做了一个恒等映射,式子为:
a
[
l
+
2
]
=
g
(
z
[
l
+
2
]
+
a
[
l
]
)
Note that
a
[
l
]
≥
0
because it is a output of
R
e
L
U
=
g
(
W
[
l
+
2
]
a
[
l
+
1
]
+
b
[
l
+
2
]
+
a
[
l
]
)
Then set
W
[
l
+
2
]
,
b
[
l
+
2
]
to be 0 to get an identity function
=
a
[
l
]
\begin{aligned} a^{[l+2]}&=g(z^{[l+2]} + a^{[l]}) &&\text{Note that }a^{[l]}\ge 0\text{ because it is a output of }{\sf ReLU}\\ &=g(W^{[l+2]}a^{[l+1]} + b^{[l+2]} +a^{[l]})&&\text{Then set }W^{[l+2]},b^{[l+2]}\text{ to be 0 to get an identity function}\\ &=a^{[l]} \end{aligned}
a[l+2]=g(z[l+2]+a[l])=g(W[l+2]a[l+1]+b[l+2]+a[l])=a[l]Note that a[l]≥0 because it is a output of ReLUThen set W[l+2],b[l+2] to be 0 to get an identity function
Residue Block做恒等映射是非常free的。所以增加层数最起码不会负面影响网络的性能。
总结来说的话,只要把 W , b W,b W,b设置为0,至少不会影响网络的准确程度,而是否设置为0需要看反向传播,让网络自己来决定这里 W , b W,b W,b到底取多少。而普通的神经网络要实现恒等映射是比较复杂的。这就是残差网络的优势所在。
如果 z [ l + 2 ] 和 a [ l ] z^{[l+2]}和a^{[l]} z[l+2]和a[l]的维数不等怎么办
其实很简单就是加上一个 W s Ws Ws,比如 z [ l + 2 ] z^{[l+2]} z[l+2]是256维的,而 a [ l ] a^{[l]} a[l]只有128维,那就可以令 W s ∈ R 256 × 128 Ws\in\R^{256\times 128} Ws∈R256×128, z [ l + 2 ] + W s ⋅ a [ l ] z^{[l+2]}+Ws\cdot a^{[l]} z[l+2]+Ws⋅a[l]