数据量大的时候大的网络能提高性能。在小的数据集上,我们更应该关注特征的选取、算法实现的细节之类的内容,因为在小的数据集上,各种规模的网络表现差不多。
使用这种方式表达样本在神经网络中是更常见的方式,即,每一列表示一个样本,每一行表示一个特征。
m 样本数量
n 特征数量
L(y,y^)=−ylog(y^)−(1−y)log(1−y^) L ( y , y ^ ) = − y l o g ( y ^ ) − ( 1 − y ) l o g ( 1 − y ^ )
Cost function:
repeat:{ r e p e a t : {
w=w−α∂J(w)∂w w = w − α ∂ J ( w ) ∂ w
b=b−α∂J(b)∂b b = b − α ∂ J ( b ) ∂ b
} }
略
略
略
链式法则
a表示的是 y^ y ^ ,即逻辑回归的预测值。
对于sigmoid函数的求导为:
即 σ(z)′=σ(z)( 1−σ(z) ) σ ( z ) ′ = σ ( z ) ( 1 − σ ( z ) ) 。
Random initialization w1、w2、b R a n d o m i n i t i a l i z a t i o n w 1 、 w 2 、 b
Repeat until convergence: R e p e a t u n t i l c o n v e r g e n c e :
1. J=0, dw1=0, dw2=0, db=0 J = 0 , d w 1 = 0 , d w 2 = 0 , d b = 0
2. For i=1 to m: F o r i = 1 t o m :
3. z(i)=WTX+b z ( i ) = W T X + b
4. a(i)=σ(z(i)) a ( i ) = σ ( z ( i ) )
5. dz(i)=a(i)−y(i) d z ( i ) = a ( i ) − y ( i )
6. J +=−y(i)loga(i)−(1−y(i))log(1−a(i)) J + = − y ( i ) l o g a ( i ) − ( 1 − y ( i ) ) l o g ( 1 − a ( i ) )
7. dw1 +=x(i)1dz(i) d w 1 + = x 1 ( i ) d z ( i )
8. dw2 +=x(i)2dz(i) d w 2 + = x 2 ( i ) d z ( i )
9. db +=dz(i) d b + = d z ( i )
10. end For e n d F o r
11. J=J/m J = J / m
12. dw1=dw1/m d w 1 = d w 1 / m
13. dw2=dw2/m d w 2 = d w 2 / m
14. db=db/m d b = d b / m
15. w1=w1−α dw1 w 1 = w 1 − α d w 1
16. w2=w2−α dw2 w 2 = w 2 − α d w 2
17. b=b−α db b = b − α d b
缺点:
vectorization
矢量化使得运算过程变得更快。
试验中,矢量化比非矢量化快400多倍。
矢量化你的代码
经验法则:无论什么时候,避免显式的使用for循环。
import numpy as np
import time
a = np.random.rand(1000000)
b = np.random.rand(1000000)
tic = time.time()
c = np.dot(a, b)
toc = time.time()
print('Vectorization version :' + str(1000* (toc - tic)) + ' ms')
# Vectorization version :1.0001659393310547 ms
tic = time.time()
for i in range(len(a)):
c = a[i] * b[i]
toc = time.time()
print('NO vectorization version :' + str(1000* (toc - tic)) + ' ms')
# NO vectorization version :424.0000247955322 ms
numpy中很多函数都是直接对矩阵中的元素进行操作。
2.10的矢量化表示:
Random initialization W、b R a n d o m i n i t i a l i z a t i o n W 、 b
Repeat until convergence: R e p e a t u n t i l c o n v e r g e n c e :
1. J=0, dW=np.zeros((n,1)), db=0 J = 0 , d W = n p . z e r o s ( ( n , 1 ) ) , d b = 0
2. For i=1 to m: F o r i = 1 t o m :
3. z(i)=WTX+b z ( i ) = W T X + b
4. a(i)=σ(z(i)) a ( i ) = σ ( z ( i ) )
5. dz(i)=a(i)−y(i) d z ( i ) = a ( i ) − y ( i )
6. J +=−y(i)loga(i)−(1−y(i))log(1−a(i)) J + = − y ( i ) l o g a ( i ) − ( 1 − y ( i ) ) l o g ( 1 − a ( i ) )
7. dW +=x(i)dz(i) d W + = x ( i ) d z ( i )
9. db +=dz(i) d b + = d z ( i )
10. end For e n d F o r
11. J=J/m J = J / m
12. dW=dW/m d W = d W / m
14. db=db/m d b = d b / m
15. W=W−α dW W = W − α d W
17. b=b−α db b = b − α d b
即,W的计算去掉了循环,使用了矩阵。
减少一层循环使得代码变快。
不用for循环
Z=wTX+b Z = w T X + b
A=σ(Z) A = σ ( Z )
再次实现算法:
1. J=0, dw=np.zeros((n,1)), db=0 J = 0 , d w = n p . z e r o s ( ( n , 1 ) ) , d b = 0
3. Z=WTX+b Z = W T X + b
4. A=σ(Z) A = σ ( Z )
5. dZ=A−Y d Z = A − Y
6. dw=1mX(dZ)T d w = 1 m X ( d Z ) T
7. db=1m∑mi=1dz(i)=1m np.sum(dZ) d b = 1 m ∑ i = 1 m d z ( i ) = 1 m n p . s u m ( d Z )
8. W=W−α dW W = W − α d W
9. b=b−α db b = b − α d b
matrixm×n+−×÷(1,n)−−−−−−−−−−−>(m,n) m a t r i x m × n + − × ÷ ( 1 , n ) − − − − − − − − − − − > ( m , n )
matrixm×n+−×÷(m,1)−−−−−−−−−−−>(m,n) m a t r i x m × n + − × ÷ ( m , 1 ) − − − − − − − − − − − > ( m , n )
matrixm×n+−×÷(1,1)−−−−−−−−−−−>(m,n) m a t r i x m × n + − × ÷ ( 1 , 1 ) − − − − − − − − − − − > ( m , n )
因为numpy的灵活性,常常导致出现奇怪的bug。
a = np.random.randn(1, 5)
a = np.random.randn(5, 1)
assert(a.shape == (5, 1))
a = np.reshape((5,1))
通过以上三种手段,彻底杜绝代码中的秩为1的数组。
如果前面代码框的文本后边的代码框有用到,一定要先运行过前边的代码框。
略
略
略
略
略
激活函数:
如果隐藏层只用线性激活函数or不用激活函数:
a[1]=z[1]=w[1]x+b[1] a [ 1 ] = z [ 1 ] = w [ 1 ] x + b [ 1 ]
a[2]=z[2]=w[2]a[1]+b[2] a [ 2 ] = z [ 2 ] = w [ 2 ] a [ 1 ] + b [ 2 ]
即:
a[2]=w[2](w[1]x+b[1])+b[2] a [ 2 ] = w [ 2 ] ( w [ 1 ] x + b [ 1 ] ) + b [ 2 ]
=(w[2]w[1])x+(w[2]b[1]+b[2]) = ( w [ 2 ] w [ 1 ] ) x + ( w [ 2 ] b [ 1 ] + b [ 2 ] )
=w′x+b′ = w ′ x + b ′
那么,仍旧是线性变换。即对输入进行线性组合然后输出。这根本就不需要什么隐藏层。
只有一个地方会用到线性激活函数or不用激活函数,就是回归问题。网络的输出是一个连续值。即 y^∈R y ^ ∈ R ,即使这样,隐藏层依然使用的是诸如tanh、ReLU or leaky ReLU,只有在输出层使用线性激活函数。
前行传播,然后反向传播。
dZ即 ∂L(a,y)∂z ∂ L ( a , y ) ∂ z
输入特征数量: n[0]=nx n [ 0 ] = n x
隐藏单元个数: n[1] n [ 1 ]
输出单元个数: n[2]=1 n [ 2 ] = 1
那么,
X−−>(n[0], m) X − − > ( n [ 0 ] , m )
W[1]、dW[1]−−>(n[1], n[0]) W [ 1 ] 、 d W [ 1 ] − − > ( n [ 1 ] , n [ 0 ] )
b[1] b [ 1 ] 、 db[1]−−>(n[1], 1) d b [ 1 ] − − > ( n [ 1 ] , 1 )
Z[1] Z [ 1 ] 、 dZ[1]−−>(n[1], m) d Z [ 1 ] − − > ( n [ 1 ] , m )
W[2]、dW[2]−−>(n[2], n[1]) W [ 2 ] 、 d W [ 2 ] − − > ( n [ 2 ] , n [ 1 ] )
b[2] b [ 2 ] 、 db[2]−−>(n[2], 1) d b [ 2 ] − − > ( n [ 2 ] , 1 )
Z[2] Z [ 2 ] 、 dZ[2]−−>(n[2], m) d Z [ 2 ] − − > ( n [ 2 ] , m )
dZ[1]=(w[2])TdZ[2]∗g[1] ′(Z[1]) d Z [ 1 ] = ( w [ 2 ] ) T d Z [ 2 ] ∗ g [ 1 ] ′ ( Z [ 1 ] ) 的维度分别为:
(n[1], m) ( n [ 1 ] , m ) = (n[1], n[2]) ( n [ 1 ] , n [ 2 ] ) (n[2], m) ( n [ 2 ] , m ) ∗(n[1], m) ∗ ( n [ 1 ] , m )
dw[1]=1mdZ[1]XT d w [ 1 ] = 1 m d Z [ 1 ] X T 的维度分别为:
(n[1], n[0]) ( n [ 1 ] , n [ 0 ] ) = (n[1], m) ( n [ 1 ] , m ) (m, n[0]) ( m , n [ 0 ] )
db[1]=1mnp.sum(dZ[1], axis=1, keepdims=True) d b [ 1 ] = 1 m 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 ) 的维度分别为: (n[1], 1) ( n [ 1 ] , 1 )
如果不对参数w进行随机初始化,比如全部设置为0,那么,可以证明,所有隐藏层单元都在计算相同的函数,呈对称状态,没有意义。
所以需要对w随机初始化。
一般都将w随机成很小的值。因为如果激活函数是sigmoid或者tanh这样的,小的输入有大的梯度。如果w太大,很可能学习速率很慢。或者隐藏层没有用sigmoid或者tanh,但是是二分类问题,输出层用到了sigmoid,那么也不希望初始参数太大。
b设置成0不影响,但一般也进行随机初始化。
算网络层数时候不算输入层。
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 ] )
z[l] z [ l ] 会被缓存下来到反向传播的时候使用。
一次完整的梯度下降过程:
反向传播到最后不需要计算 da[0] d a [ 0 ]
Back propagation
输入: dA[l] d A [ l ]
输出: dA[l−1] d A [ l − 1 ] 、 dw[l]、db[l] d w [ l ] 、 d b [ l ]
dZ[l]=dA[l]∗g[l] ′(Z[l]) d Z [ l ] = d A [ l ] ∗ g [ l ] ′ ( Z [ l ] )
dw[l]=1mdZ[l](A[l−1])T d w [ l ] = 1 m d Z [ l ] ( A [ l − 1 ] ) T
db[l]=1mnp.sum(dZ[l], axis=1, keepdims=True) d b [ l ] = 1 m 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 )
dA[l−1]=(w[l])TdZ[l] d A [ l − 1 ] = ( w [ l ] ) T d Z [ l ]
超参数:
超参数的选择,就是不断的尝试。
没什么关系。
用神经元类比深度神经网络只是一个粗浅的类比。
一个神经元到底在干什么,没有人能够解释。
人到底是怎么学习的,也还是一个未解之谜。
深度学习是一个强大的工具,能学习到各种灵活、复杂的函数,来实现 x x 到 y y 的映射。
但和人类的学习比起来,不值一提。