Andrew Ng 深度学习课程——神经网络和深度学习

感谢Andrew Ng的公开课1,这个博客主要是记录公开课的学习过程与理解。

神经网络基础

介绍神经网络的基础,主要是数学表达式,梯度下降法,等的介绍,从简单入手理解神经网络。

逻辑回归

通过介绍逻辑回归(Logistic Regression)理解神经网络问题。假设一个问题有3个参数,分别是 x 1 x_1 x1, x 2 x_2 x2, x 3 x_3 x3,他们共同决定了一个输出 y y y。比如, y y y评价房子是不是值得买,那么 x x x就可能是面积,地段,楼层等参数。有很多房子的参数信息以及房子的评价,这里,我们使用“值得买”,"不值得买"表示两个状态,在数学上,用0,1表示。0-不值得买,1-值得买。那么可以有:
w 1 x 1 + w 2 x 2 + w 3 x 3 + b = y 1 w_1x_1+w_2x_2+w_3x_3+b=y_1 w1x1+w2x2+w3x3+b=y1使用三个 w w w参数和一个 b b b参数与输入的 x x x进行运算得到是不是值得买。那么当有很多个输入参数与是否值得的评价就可以得到方程组:
w 1 x 1 ( 1 ) + w 2 x 2 ( 1 ) + w 3 x 3 ( 1 ) + b = y ( 1 ) w 1 x 1 ( 2 ) + w 2 x 2 ( 2 ) + w 3 x 3 ( 2 ) + b = y ( 2 ) w 1 x 1 ( i ) + w 2 x 2 ( i ) + w 3 x 3 ( i ) + b = y ( i ) . . . . . . w 1 x 1 ( m ) + w 2 x 2 ( m ) + w 3 x 3 ( m ) + b = y ( m ) \begin{array}{l}w_1x_1^{(1)}+w_2x_2^{(1)}+w_3x_3^{(1)}+b=y^{(1)}\\w_1x_1^{(2)}+w_2x_2^{(2)}+w_3x_3^{(2)}+b=y^{(2)}\\w_1x_1^{(i)}+w_2x_2^{(i)}+w_3x_3^{(i)}+b=y^{(i)}\\......\\w_1x_1^{(m)}+w_2x_2^{(m)}+w_3x_3^{(m)}+b=y^{(m)}\end{array} w1x1(1)+w2x2(1)+w3x3(1)+b=y(1)w1x1(2)+w2x2(2)+w3x3(2)+b=y(2)w1x1(i)+w2x2(i)+w3x3(i)+b=y(i)......w1x1(m)+w2x2(m)+w3x3(m)+b=y(m)可以简记为: w T x + b = y \boldsymbol w^T\boldsymbol x+\boldsymbol b=\boldsymbol y wTx+b=y对于每一个 y y y来说,我们希望他是0或1,如果都是0或1并且和实际的是否值得买一一对应,那么参数就适合这个模型。所以我们希望通过 w 1 x 1 ( i ) + w 2 x 2 ( i ) + w 3 x 3 ( i ) + b = y ( i ) w_1x_1^{(i)}+w_2x_2^{(i)}+w_3x_3^{(i)}+b=y^{(i)} w1x1(i)+w2x2(i)+w3x3(i)+b=y(i)计算出来的 y y y的值与实际的 y y y相等或者相近。假设计算的 y y y的结果为 y ^ \widehat y y ,实际的 y y y值就是 y y y。对于单个样本来说,使用方程计算出来的值的范围为整个实数区间,但是我们要求的只有0或1,或者0-1这个范围,所以就有了激活函数的概念,把输出的值映射到0-1的区间中,使用sigmoid函数:
y ( z ) = 1 1 + e − z y(z)=\frac1{1+e^{-z}} y(z)=1+ez1函数的图形可以表示为:
sigmoid函数
实现的python脚本为:

import matplotlib.pyplot as plt
import math

x = [i for i in range(-10, 10)]
y = [1 / (1 + math.exp(-i)) for i in range(-10, 10)]
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('sigmoid')
plt.show()

损失函数

对于上面的方程,可以更加简单表示为: y ^ ( i ) = σ ( w T x ( i ) + b ) \widehat y^{(i)}=\sigma(w^Tx^{(i)}+b) y (i)=σ(wTx(i)+b),其中, σ ( z ( i ) ) = 1 1 + e − z ( i ) \sigma(z^{(i)})=\frac1{1+e^{-z^{(i)}}} σ(z(i))=1+ez(i)1,对于所有的样本 { ( x ( 1 ) , y ( 1 ) ) , ( x ( 2 ) , y ( 2 ) ) , . . . , ( x ( m ) , y ( m ) ) } \{(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)})\} {(x(1),y(1)),(x(2),y(2)),...,(x(m),y(m))},都希望 y ^ ( i ) = y ( i ) \widehat y^{(i)}=y^{(i)} y (i)=y(i)。所以定义损失函数,让损失函数达到最小,就达到了模型的目标。对于计算标签 y ^ ( i ) \widehat y^{(i)} y (i)和实际标签 y ( i ) y^{(i)} y(i),定义单个样本的损失函数为:
L ( y ^ ( i ) , y ( i ) ) = − ( y ( i ) log ⁡    y ^ ( i ) + ( 1 − y ( i ) ) log ⁡ ( 1 − y ^ ( i ) ) ) \mathcal L(\widehat y^{(i)},y^{(i)})=-(y^{(i)}\log\;\widehat y^{(i)}+(1-y^{(i)})\log(1-\widehat y^{(i)})) L(y (i),y(i))=(y(i)logy (i)+(1y(i))log(1y (i))),定义这样的损失函数后,当 y = 1 y=1 y=1时, L ( y ^ ( i ) , y ( i ) ) = − log ⁡    y ^ ( i ) \mathcal L(\widehat y^{(i)},y^{(i)})=-\log\;\widehat y^{(i)} L(y (i),y(i))=logy (i),为了让 L ( y ^ ( i ) , y ( i ) ) \mathcal L(\widehat y^{(i)},y^{(i)}) L(y (i),y(i))最小,就是 log ⁡    y ^ ( i ) \log\;\widehat y^{(i)} logy (i)最大,即 y ^ ( i ) \widehat y^{(i)} y (i)最大, y ^ ( i ) \widehat y^{(i)} y (i)的最大值就是1,所以就是 y ( i ) ≈ y ^ ( i ) y^{(i)} \approx \widehat y^{(i)} y(i)y (i);当 y = 0 y=0 y=0时, L ( y ^ ( i ) , y ( i ) ) = − log ⁡ ( 1 − y ^ ( i ) ) \mathcal L(\widehat y^{(i)},y^{(i)})=-\log(1-\widehat y^{(i)}) L(y (i),y(i))=log(1y (i)),为了让 L ( y ^ ( i ) , y ( i ) ) \mathcal L(\widehat y^{(i)},y^{(i)}) L(y (i),y(i))最小,就是 log ⁡ ( 1 − y ^ ( i ) ) \log(1-\widehat y^{(i)}) log(1y (i))最大, y ^ ( i ) \widehat y^{(i)} y (i)最小,最小就是0,所以这个时候 y ( i ) ≈ y ^ ( i ) y^{(i)} \approx \widehat y^{(i)} y(i)y (i)
这时单个样本的损失表达式,对于 m m m个样本的总体损失函数表达为:
J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) \mathcal J(w,b)=\frac1m\sum_{i=1}^m \mathcal L(\widehat y^{(i)},y^{(i)}) J(w,b)=m1i=1mL(y (i),y(i))

梯度下降

梯度下降就是使用函数值在该点的梯度作为变化的方向的方法,让函数值逐步达到极值点。使用的梯度下降法的表达为:
w : = w − α d J d w b : = b − α d J d w \begin{array}{l}w:=w-\alpha\frac{dJ}{dw}\\\\b:=b-\alpha\frac{dJ}{dw}\end{array} w:=wαdwdJb:=bαdwdJ其中, α \alpha α表示学习率, d J d w \frac{dJ}{dw} dwdJ表示的就是梯度。这样就能让函数值慢慢达到一个极值点(可能时局部的极值点)。
但是如何计算这个梯度,然后带回到表达式中,不断迭代优化参数呢?答案是通过链式求导法则进行求导。现在有的表达式有:
z = w T x + b y ^ = a = σ ( z ) L ( a , y ) = − ( y log ⁡    a + ( 1 − y ) log ⁡ ( 1 − a ) ) \begin{array}{l}z=w^Tx+b\\\widehat y=a=\sigma(z)\\ \mathcal L(a,y)=-(y\log\;a+(1-y)\log(1-a))\end{array} z=wTx+by =a=σ(z)L(a,y)=(yloga+(1y)log(1a))为了书写方便,就令 y ^ = a \widehat y=a y =a了。现在要求的就是 d J d w \frac{dJ}{dw} dwdJ d J d b \frac{dJ}{db} dbdJ了。不妨,先假设只有2个参数,即:
z = w 1 x 1 + w 2 x 2 + b y ^ = a = σ ( z ) L ( a , y ) = − ( y log ⁡    a + ( 1 − y ) log ⁡ ( 1 − a ) ) \begin{array}{l}z=w_1x_1+w_2x_2+b\\\widehat y=a=\sigma(z)\\L(a,y)=-(y\log\;a+(1-y)\log(1-a))\end{array} z=w1x1+w2x2+by =a=σ(z)L(a,y)=(yloga+(1y)log(1a))根据链式求导法则有: ∂ L ∂ w 1 = ∂ L ∂ a ⋅ ∂ a ∂ z ⋅ ∂ z ∂ w 1 \frac{\partial L}{\partial w_1}=\frac{\displaystyle\partial L}{\displaystyle\partial a}\cdot\frac{\displaystyle\partial a}{\displaystyle\partial z}\cdot\frac{\displaystyle\partial z}{\displaystyle\partial w_1} w1L=aLzaw1z其中:
∂ L ∂ a = ∂ [ − ( y log ⁡ a + ( 1 − y ) log ⁡ ( 1 − a ) ) ] ∂ a = ∂ − y log ⁡ a ∂ a + ∂ − ( 1 − y ) log ⁡ ( 1 − a ) ) ∂ a = − y a + − ( 1 − y ) × ( − 1 ) 1 − a = 1 − y 1 − a − y a ∂ a ∂ z = ∂ ( 1 1 + e − z ) ∂ z = ( − 1 ) × e − z × ( − 1 ) ( 1 + e − z ) 2 = 1 1 + e − z × e − z 1 + e − z = 1 1 + e − z × ( 1 − 1 1 + e − z ) = a ( 1 − a ) \frac{\displaystyle\partial L}{\displaystyle\partial a}=\frac{\displaystyle\partial\lbrack-(y\log a+(1-y)\log(1-a))\rbrack}{\partial a}=\frac{\partial-y\log a}{\partial a}+\frac{\partial-(1-y)\log(1-a))}{\partial a}=\frac{-y}a+\frac{-(1-y)\times(-1)}{1-a}=\frac{1-y}{1-a}-\frac ya \\\frac{\displaystyle\partial a}{\displaystyle\partial z}=\frac{\partial({\displaystyle\frac1{1+e^{-z}}})}{\partial z}=\frac{(-1)\times e^{-z}\times(-1)}{(1+e^{-z})^2}=\frac{\displaystyle1}{\displaystyle1+e^{-z}}\times\frac{\displaystyle e^{-z}}{\displaystyle1+e^{-z}}=\frac{\displaystyle1}{\displaystyle1+e^{-z}}\times(1-\frac{\displaystyle1}{\displaystyle1+e^{-z}})=a(1-a) aL=a[(yloga+(1y)log(1a))]=ayloga+a(1y)log(1a))=ay+1a(1y)×(1)=1a1yayza=z(1+ez1)=(1+ez)2(1)×ez×(1)=1+ez1×1+ezez=1+ez1×(11+ez1)=a(1a)所以:
∂ L ∂ w 1 = ( 1 − y 1 − a − y a ) a ( 1 − a ) ∂ z ∂ w 1 = ( a − y ) x 1 ∂ L ∂ w 2 = ( 1 − y 1 − a − y a ) a ( 1 − a ) ∂ z ∂ w 2 = ( a − y ) x 2 ∂ L ∂ b = ( 1 − y 1 − a − y a ) a ( 1 − a ) ∂ z ∂ b = a − y \frac{\displaystyle\partial L}{\displaystyle\partial w_1}=(\frac{1-y}{1-a}-\frac ya)a(1-a)\frac{\partial z}{\partial w_1}=(a-y)x_1\\\frac{\displaystyle\partial L}{\displaystyle\partial w_2}=(\frac{1-y}{1-a}-\frac ya)a(1-a)\frac{\partial z}{\partial w_2}=(a-y)x_2\\\frac{\displaystyle\partial L}{\displaystyle\partial b}=(\frac{1-y}{1-a}-\frac ya)a(1-a)\frac{\partial z}{\partial b}=a-y w1L=(1a1yay)a(1a)w1z=(ay)x1w2L=(1a1yay)a(1a)w2z=(ay)x2bL=(1a1yay)a(1a)bz=ay同样当有 m m m个样本的时候,梯度表示为: ∂ J ∂ w n = 1 m ∑ i = 1 m ∂ L ∂ w n , i \frac{\partial J}{\partial w_n}=\frac1m\sum_{i=1}^m\frac{\partial L}{\partial w_{n,i}} wnJ=m1i=1mwn,iL这样,使用梯度下降的伪代码为:

J = 0;dw1 = 0;dw2 = 0;db = 0;  % 初始化
for i =1 to m:
	z(i) = wTx(i)+b; 
	a(i) = sigmoid(z(i)); % 计算估计的标签
	J += -(y(i)log(a(i))+(1-y(i))log(1-a(i))); %损失函数
	dw1 += (a(i)-y(i))*x1(i);  % 计算梯度
	dw2 += (a(i)-y(i))*x2(i);
	db += (a(i)-y(i));
end
J /= m;
dw1 / = m;
dw2 / = m;
db /= m;
w1 = w1 - alpha * dw1;  % 使用梯度下降更新参数
w2 = w2 - alpha * dw2;
b = b - alpha * b;

通过以上过程,就使用所有的参数更新了一次参数,经过多次参数更新就优化了模型。在上面的代码中,使用 d w 1 = ∂ J / ∂ w 1 , d w 2 = ∂ J / ∂ w 2 , d b = ∂ J / ∂ b d w_1=\partial J / \partial w_1,d w_2=\partial J / \partial w_2,d b=\partial J / \partial b dw1=J/w1,dw2=J/w2,db=J/b,如果有更多的参数,用这样的方法更新他们就好了。

向量化

使用for循环的效率比较低,使用向量化的计算有助于大大提高计算效率。看一个例子:

import numpy as np
import datetime

a = np.random.rand(1000000)
b = np.random.rand(1000000)
tic = datetime.datetime.now()
c = np.dot(a, b)  # 使用np.dot向量化计算
toc = datetime.datetime.now()
print(c)
print('向量化的Time Cost:', toc - tic)
tic = datetime.datetime.now()
c = 0
for i in range(1000000):
    c += a[i] * b[i]  # 使用for循环计算
toc = datetime.datetime.now()
print(c)
print('非向量化的Time Cost:', toc - tic)

结果为:

249934.26780889684
向量化的Time Cost: 0:00:00.000936
249934.26780889346
非向量化的Time Cost: 0:00:00.304249

使用向量化的操作,提高了大概300倍的效率。在numpy中常见的向量化操作函数还有np.abs,np.log,np.exp,np.maxium等。
那么使用向量化的操作对逻辑回归进行优化:

J = 0;dw = np.zeros((n,1));db = 0;  % 初始化
for i =1 to m:
	z(i) = wTx(i)+b; 
	a(i) = sigmoid(z(i)); % 计算估计的标签
	J += -(y(i)log(a(i))+(1-y(i))log(1-a(i))); %损失函数
	dw += (a(i)-y(i))*x(i);  % 计算梯度
	db += (a(i)-y(i));
end
J /= m;
dw /= m;
db /= m;
w = w - alpha * dw;  % 使用梯度下降更新参数
b = b - alpha * b;

这里还是有for i =1 to m这一层显示的循环。在上面的表达式中 x ( i ) = [ x 1 ( i ) , x 2 ( i ) , x 3 ( i ) ] T x^{(i)} = [x_1^{(i)},x_2^{(i)},x_3^{(i)}]^T x(i)=[x1(i),x2(i),x3(i)]T为一个列向量 ( 3 × 1 ) (3 \times 1) (3×1),那么如果横向堆叠为一个矩阵的话,就可以没有显示的for循环了。
x = [ x 1 ( 1 ) x 1 ( 2 ) x 1 ( 3 ) x 1 ( 4 ) x 2 ( 1 ) x 2 ( 2 ) x 2 ( 3 ) x 2 ( 4 ) x 3 ( 1 ) x 3 ( 2 ) x 3 ( 3 ) x 3 ( 4 ) ] \boldsymbol x=\begin{bmatrix}x_1^{(1)}&x_1^{(2)}&x_1^{(3)}&x_1^{(4)}\\x_2^{(1)}&x_2^{(2)}&x_2^{(3)}&x_2^{(4)}\\x_3^{(1)}&x_3^{(2)}&x_3^{(3)}&x_3^{(4)}\end{bmatrix} x=x1(1)x2(1)x3(1)x1(2)x2(2)x3(2)x1(3)x2(3)x3(3)x1(4)x2(4)x3(4) x ∈ R 3 × 4 \boldsymbol x\in\mathbb{R}^{3\times4} xR3×4,一个样本有3个特征点,一共有4个样本的话,所有的数据点就可以表达为上式。那么 w = [ w 1 , w 2 , w 3 ] \boldsymbol w=[w_1,w_2,w_3] w=[w1,w2,w3]的话, b = [ b , b , b , b ] \boldsymbol b = [b,b,b,b] b=[b,b,b,b],就有 z = w x + b \boldsymbol z=\boldsymbol w \boldsymbol x + \boldsymbol b z=wx+b就是所有的样本的计算值。来看 w \boldsymbol w w 1 × 3 1\times3 1×3维的, x \boldsymbol x x 3 × 4 3\times4 3×4维,乘积的结果为 1 × 4 1\times4 1×4,加上 1 × 4 1\times4 1×4维的 b \boldsymbol b b后就是 1 × 4 1\times4 1×4维的 z \boldsymbol z z。表达为python代码为z = np.dot(w,x)+b,因为这里的 w w w是行向量,由于部分写法是把 w w w写为列向量,所以可能会有z = np.dot(w.T,x)+b的写法,结果一样的。
m m m个样本时候,有实际标签 Y = [ y ( 1 ) , y ( 2 ) , . . . , y ( m ) ] Y=[y^{(1)},y^{(2)},...,y^{(m)}] Y=[y(1),y(2),...,y(m)],计算标签 A = [ a ( 1 ) , a ( 2 ) , . . . , a ( m ) ] A=[a^{(1)},a^{(2)},...,a^{(m)}] A=[a(1),a(2),...,a(m)],由于 d z ( i ) = ∂ J / ∂ z ( i ) = a ( i ) − y ( i ) dz^{(i)} = \partial J / \partial z^{(i)}=a^{(i)}-y^{(i)} dz(i)=J/z(i)=a(i)y(i),所以有 d Z = [ d z ( 1 ) , d z ( 2 ) , . . . , d z ( m ) ] = [ a ( 1 ) − y ( 1 ) , a ( 2 ) − y ( 2 ) , . . . , a ( m ) − y ( m ) ] = A − Y dZ=[dz^{(1)},dz^{(2)},...,dz^{(m)}]=[a^{(1)}-y^{(1)},a^{(2)}-y^{(2)},...,a^{(m)}-y^{(m)}]=A-Y dZ=[dz(1),dz(2),...,dz(m)]=[a(1)y(1),a(2)y(2),...,a(m)y(m)]=AY
m m m个样本的 w w w的梯度可以表示为:
∂ J ∂ w = 1 m ∑ i = 1 m ∂ L ∂ w = 1 m ∑ i = 1 m ( a ( i ) − y ( i ) ) x ( i ) = 1 m d Z x ∂ J ∂ b = 1 m ∑ i = 1 m ∂ L ∂ b = 1 m ∑ i = 1 m ( a ( i ) − y ( i ) ) = 1 m d Z \frac{\partial J}{\partial w}=\frac1m\sum_{i=1}^m\frac{\partial L}{\partial w}=\frac1m\sum_{i=1}^m(a^{(i)}-y^{(i)})\boldsymbol x^{(i)}=\frac1m dZ\boldsymbol x\\ \frac{\partial J}{\partial b}=\frac1m\sum_{i=1}^m\frac{\partial L}{\partial b}=\frac1m\sum_{i=1}^m(a^{(i)}-y^{(i)})=\frac1m dZ wJ=m1i=1mwL=m1i=1m(a(i)y(i))x(i)=m1dZxbJ=m1i=1mbL=m1i=1m(a(i)y(i))=m1dZ使用python代码表示即为:

dw = np.dot(X,dZ.T) / m
db = np.sum(dZ) / m

实现逻辑回归一次循环的整体代码为:

Z = np.dot(w.T,x) + b
A = sigmoid(Z)
dw = np.dot(X,(A-Y).T) / m
db = np.sum(A-Y) / m
w = w - alpha * dw;  % 使用梯度下降更新参数
b = b - alpha * b;
补充:广播

python numpy中使用矩阵进行操作时候,并不需要矩阵的维度是一致的,如果第一个矩阵为 m × n m \times n m×n维的,第二个是 1 × n 1 \times n 1×n维的,就会把第二个填充为 m × n m \times n m×n维的再进行相应操作,哪怕第二个矩阵是 1 × 1 1 \times 1 1×1维的,也就是一个数,也会按照行列补齐后进行运算,这就是广播机制。
m a t r i x m × n + − × ÷ m a t r i x ( 1 , n ) − − > m a t r i x ( m , n ) m a t r i x m × n + − × ÷ m a t r i x ( 1 , n ) − − > m a t r i x ( m , n )      m a t r i x m × n + − × ÷ m a t r i x ( m , 1 ) − − > m a t r i x ( m , n ) m a t r i x m × n + − × ÷ m a t r i x ( m , 1 ) − − > m a t r i x ( m , n )      m a t r i x m × n + − × ÷ m a t r i x ( 1 , 1 ) − − > m a t r i x ( m , n ) \begin{array}{l}matrix_{m\times n}+-\times\div matrix_{(1,n)}-->matrix_{(m,n)}\\matrix_{m\times n}+-\times\div matrix_{(1,n)}-->matrix_{(m,n)\;\;}\\matrix_{m\times n}+-\times\div matrix_{(m,1)}-->matrix_{(m,n)}\\matrix_{m\times n}+-\times\div matrix_{(m,1)}-->matrix_{(m,n)}\;\;\\matrix_{m\times n}+-\times\div matrix_{(1,1)}-->matrix_{(m,n)}\end{array} matrixm×n+×÷matrix(1,n)>matrix(m,n)matrixm×n+×÷matrix(1,n)>matrix(m,n)matrixm×n+×÷matrix(m,1)>matrix(m,n)matrixm×n+×÷matrix(m,1)>matrix(m,n)matrixm×n+×÷matrix(1,1)>matrix(m,n)

代码实现

第二周 神经网络基础-1逻辑回归.rar

浅层神经网络

在神经网络基础中的逻辑回归可以看成是只有一层的神经网络。那么先构造一个只有2层的浅层神经网络为:
浅层网络
输入层 x x x,隐藏层L1,输出层L2。先规定表达式的写法,输入层 x = a [ 0 ] x=a^{[0]} x=a[0],隐藏层输出为 a [ 1 ] a^{[1]} a[1],有计算 z [ 1 ] = w [ 1 ] T x + b [ 1 ] z^{[1]}=w^{[1]T}x+b^{[1]} z[1]=w[1]Tx+b[1] a [ 1 ] = s i g m o i d ( z [ 1 ] ) a^{[1]}=sigmoid(z^{[1]}) a[1]=sigmoid(z[1]),隐藏层的输出 a [ 1 ] a^{[1]} a[1]作为输出层的输入,有计算 z [ 2 ] = w [ 2 ] T a [ 1 ] + b [ 2 ] z^{[2]}=w^{[2]T}a^{[1]}+b^{[2]} z[2]=w[2]Ta[1]+b[2] a [ 2 ] = s i g m o i d ( z [ 2 ] ) a^{[2]}=sigmoid(z^{[2]}) a[2]=sigmoid(z[2]),输出层最终输出为 a [ 2 ] a^{[2]} a[2]。参数 x [ m ] x^{[m]} x[m]的上标 [ m ] [m] [m]代表为第 m m m层。而 a n [ m ] a^{[m]}_n an[m]的下标表示第 n n n个节点, a n [ m ] a^{[m]}_n an[m]就表示了第 m m m层的第 n n n个节点的输出。为了表示区分,现在假设每个样本有3个特征,隐藏层有4个节点。每个节点都可以表示为一个逻辑回归,就有:
z 1 [ 1 ] = w 1 [ 1 ] T x + b 1 [ 1 ] , a 1 [ 1 ] = σ ( z 1 [ 1 ] ) z 2 [ 1 ] = w 2 [ 1 ] T x + b 2 [ 1 ] , a 2 [ 1 ] = σ ( z 2 [ 1 ] ) z 3 [ 1 ] = w 3 [ 1 ] T x + b 3 [ 1 ] , a 3 [ 1 ] = σ ( z 3 [ 1 ] ) z 4 [ 1 ] = w 4 [ 1 ] T x + b 4 [ 1 ] , a 4 [ 1 ] = σ ( z 4 [ 1 ] ) z^{[1]}_1=w^{[1]T}_1x+b^{[1]}_1,a^{[1]}_1=\sigma(z^{[1]}_1)\\ z^{[1]}_2=w^{[1]T}_2x+b^{[1]}_2,a^{[1]}_2=\sigma(z^{[1]}_2)\\ z^{[1]}_3=w^{[1]T}_3x+b^{[1]}_3,a^{[1]}_3=\sigma(z^{[1]}_3)\\ z^{[1]}_4=w^{[1]T}_4x+b^{[1]}_4,a^{[1]}_4=\sigma(z^{[1]}_4) z1[1]=w1[1]Tx+b1[1],a1[1]=σ(z1[1])z2[1]=w2[1]Tx+b2[1],a2[1]=σ(z2[1])z3[1]=w3[1]Tx+b3[1],a3[1]=σ(z3[1])z4[1]=w4[1]Tx+b4[1],a4[1]=σ(z4[1])这里 w n [ 1 ] w^{[1]}_n wn[1]是一个列向量,维度为 3 × 1 3 \times 1 3×1 w n [ 1 ] T w^{[1]T}_n wn[1]T就是维度为 1 × 3 1 \times 3 1×3的行向量,把4个的 w n [ 1 ] T w^{[1]T}_n wn[1]T向下堆叠,就是 4 × 3 4 \times 3 4×3维的 W [ 1 ] \boldsymbol W^{[1]} W[1]矩阵。输入层为 x = [ x 1 , x 2 , x 3 ] T \boldsymbol x = [x_1,x_2,x_3]^T x=[x1,x2,x3]T的列向量,维度为 3 × 1 3 \times 1 3×1,偏置项 b [ 1 ] = [ b 1 [ 1 ] , b 2 [ 1 ] , b 3 [ 1 ] , b 4 [ 1 ] ] T \boldsymbol b^{[1]}=[b^{[1]}_1,b^{[1]}_2,b^{[1]}_3,b^{[1]}_4]^T b[1]=[b1[1],b2[1],b3[1],b4[1]]T 4 × 1 4 \times 1 4×1列向量,所以就有:
Z [ 1 ] = W [ 1 ] x + b [ 1 ] a [ 1 ] = σ ( Z [ 1 ] ) \boldsymbol Z^{[1]} = \boldsymbol W^{[1]} \boldsymbol x + \boldsymbol b^{[1]}\\ \boldsymbol a^{[1]} = \sigma(\boldsymbol Z^{[1]}) Z[1]=W[1]x+b[1]a[1]=σ(Z[1])同理,由于隐藏层的输出就是输出层的输入,所以只需要把输出层的输入 x \boldsymbol x x替换为 A [ 1 ] \boldsymbol A^{[1]} A[1]即可,就有2层的神经网络的表示为:
z [ 1 ] = W [ 1 ] x + b [ 1 ] a [ 1 ] = σ ( z [ 1 ] ) z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] a [ 2 ] = σ ( z [ 2 ] ) \boldsymbol z^{[1]} = \boldsymbol W^{[1]} \boldsymbol x + \boldsymbol b^{[1]}\\ \boldsymbol a^{[1]} = \sigma(\boldsymbol z^{[1]})\\ \boldsymbol z^{[2]} = \boldsymbol W^{[2]} \boldsymbol a^{[1]} + \boldsymbol b^{[2]}\\ \boldsymbol a^{[2]} = \sigma(\boldsymbol z^{[2]}) z[1]=W[1]x+b[1]a[1]=σ(z[1])z[2]=W[2]a[1]+b[2]a[2]=σ(z[2])在上式中,输入 x = [ x 1 , x 2 , x 3 ] T \boldsymbol x = [x_1,x_2,x_3]^T x=[x1,x2,x3]T是一个样本,有 m m m个样本的话,就把输入横向堆叠为维度为 3 × m 3 \times m 3×m的矩阵,与 4 × 3 4 \times 3 4×3维的 W [ 1 ] \boldsymbol W^{[1]} W[1]的乘积为 4 × m 4 \times m 4×m维的,加上 4 × 1 4 \times 1 4×1列向量的偏置项 b [ 1 ] = [ b 1 [ 1 ] , b 2 [ 1 ] , b 3 [ 1 ] , b 4 [ 1 ] ] T \boldsymbol b^{[1]}=[b^{[1]}_1,b^{[1]}_2,b^{[1]}_3,b^{[1]}_4]^T b[1]=[b1[1],b2[1],b3[1],b4[1]]T得到的是 4 × m 4 \times m 4×m维的 Z \boldsymbol Z Z,以及 4 × m 4 \times m 4×m A = σ ( Z ) \boldsymbol A = \sigma( \boldsymbol Z) A=σ(Z)。多个样本的表示方法为: Z [ 1 ] = W [ 1 ] x + b [ 1 ] A [ 1 ] = σ ( Z [ 1 ] ) Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] A [ 2 ] = σ ( Z [ 2 ] ) \boldsymbol Z^{[1]} = \boldsymbol W^{[1]} \boldsymbol x + \boldsymbol b^{[1]}\\ \boldsymbol A^{[1]} = \sigma(\boldsymbol Z^{[1]})\\ \boldsymbol Z^{[2]} = \boldsymbol W^{[2]} \boldsymbol A^{[1]} + \boldsymbol b^{[2]}\\ \boldsymbol A^{[2]} = \sigma(\boldsymbol Z^{[2]}) Z[1]=W[1]x+b[1]A[1]=σ(Z[1])Z[2]=W[2]A[1]+b[2]A[2]=σ(Z[2])

激活函数

在逻辑回归中使用了sigmoid函数作为激活函数,但是由于当sigmoid函数的输入绝对值比较大时候,函数值变化比较小,但是我们的目标就是让函数值趋近于1或者0,这时候的输入值肯定较大,所以函数值的变化量就变小了,这就是梯度消失问题。除非在处理二分类问题,否则一般较少使用 σ \sigma σ激活函数。
除了使用 g ( z ) = σ ( z ) g(z)=\sigma (z) g(z)=σ(z)函数意外,还有常见的激活函数为tanh函数(也不是常用的):
g ( z ) = e z − e − z e z + e − z g(z) =\frac{e^z - e^{-z}}{e^z + e^{-z}} g(z)=ez+ezezez常用的为ReLu函数,即为修正线性函数: g ( z ) = m a x ( 0 , z ) g(z) = max(0,z) g(z)=max(0,z),在输入大于0时候,就是输入,在输入小于零时候为0。或者泄露ReLu函数 g ( z ) = m a x ( 0.01 z , z ) g(z) = max(0.01z,z) g(z)=max(0.01z,z)
那为什么要使用激活函数,而不是直接使用 z = w x + b z=wx+b z=wx+b的z作为这一层的输出?
假设就使用 z = w x + b z=wx+b z=wx+b作为计算,那么 z [ 1 ] = w [ 1 ] x + b [ 1 ] z^{[1]} = w^{[1]}x+b^{[1]} z[1]=w[1]x+b[1] z [ 1 ] z^{[1]} z[1]作为了第二层的输入,有 z [ 2 ] = w [ 2 ] z [ 1 ] + b [ 2 ] z^{[2]} = w^{[2]}z^{[1]}+b^{[2]} z[2]=w[2]z[1]+b[2],所以: z [ 2 ] = w [ 2 ] z [ 1 ] + b [ 2 ] = w [ 2 ] ( w [ 1 ] x + b [ 1 ] ) + b [ 2 ] = w [ 2 ] w [ 1 ] x + w [ 2 ] b [ 1 ] + b [ 2 ] = w ′ x + b ′ z^{[2]} = w^{[2]}z^{[1]}+b^{[2]}=w^{[2]}(w^{[1]}x+b^{[1]})+b^{[2]}=w^{[2]}w^{[1]}x+w^{[2]}b^{[1]}+b^{[2]}=w'x+b' z[2]=w[2]z[1]+b[2]=w[2](w[1]x+b[1])+b[2]=w[2]w[1]x+w[2]b[1]+b[2]=wx+b,其实就是一层,并没有体现出多层结果出来。
计算一下激活函数的导数, a = σ ( x ) a=\sigma (x) a=σ(x)的导数 σ ′ ( x ) = a ( 1 − a ) \sigma '(x)=a(1-a) σ(x)=a(1a) a = t a n h ( x ) a=tanh (x) a=tanh(x)的导数为 t a n h ′ ( x ) = 1 − a 2 tanh ' (x)=1-a^2 tanh(x)=1a2,都可以使用求导公式比较方便获得。对于ReLU函数,在0点是不可导的,可以直接对0点的导数值进行赋值。 g ′ ( z ) = { 1 , if z > 0 0 , if z <= 0 g'(z)= \begin{cases} 1, &\text{if z > 0}\\ 0, & \text{if z <= 0} \end{cases} g(z)={1,0,if z > 0if z <= 0

浅层网络梯度下降法的推导

在一个两层的神经网络中反向传播计算就是相当于把逻辑回归中的反向传播计算两遍。在下图中,需要不断优化迭代的参数有 W [ 1 ] , W [ 2 ] , b [ 1 ] , b [ 2 ] W^{[1]},W^{[2]},b^{[1]},b^{[2]} W[1],W[2],b[1],b[2],使得 J ( W [ 1 ] , W [ 2 ] , b [ 1 ] , b [ 2 ] ) J(W^{[1]},W^{[2]},b^{[1]},b^{[2]}) J(W[1],W[2],b[1],b[2])最小,而 J ( W [ 1 ] , W [ 2 ] , b [ 1 ] , b [ 2 ] ) = 1 m ∑ i = 1 m L ( y ^ , y ) J(W^{[1]},W^{[2]},b^{[1]},b^{[2]})=\frac1m\sum_{i=1}^mL(\widehat y,y) J(W[1],W[2],b[1],b[2])=m1i=1mL(y ,y)二层网络计算图
在逻辑回归中已经计算获得了
∂ J ∂ w = 1 m ∑ i = 1 m ∂ L ∂ w = 1 m ∑ i = 1 m ( a ( i ) − y ( i ) ) x ( i ) = 1 m d Z x ∂ J ∂ b = 1 m ∑ i = 1 m ∂ L ∂ b = 1 m ∑ i = 1 m ( a ( i ) − y ( i ) ) = 1 m d Z \frac{\partial J}{\partial w}=\frac1m\sum_{i=1}^m\frac{\partial L}{\partial w}=\frac1m\sum_{i=1}^m(a^{(i)}-y^{(i)})\boldsymbol x^{(i)}=\frac1m dZ\boldsymbol x\\ \frac{\partial J}{\partial b}=\frac1m\sum_{i=1}^m\frac{\partial L}{\partial b}=\frac1m\sum_{i=1}^m(a^{(i)}-y^{(i)})=\frac1m dZ wJ=m1i=1mwL=m1i=1m(a(i)y(i))x(i)=m1dZxbJ=m1i=1mbL=m1i=1m(a(i)y(i))=m1dZ也就可以直接得到了(这里默认了 a [ 2 ] a^{[2]} a[2]层的激活函数为sigmoid函数): d W [ 2 ] = ∂ J ∂ W [ 2 ] = 1 m ∑ i = 1 m ∂ L ∂ W [ 2 ] = 1 m ∑ i = 1 m ( a [ 2 ] ( i ) − y ( i ) ) a [ 1 ] ( i ) = 1 m ( A [ 2 ] − Y ) A [ 1 ] T ∂ J ∂ b [ 2 ] = 1 m ∑ i = 1 m ∂ L ∂ b [ 2 ] = 1 m ∑ i = 1 m ( a [ 2 ] ( i ) − y ( i ) ) = 1 m ( A [ 2 ] − Y ) ( 水 平 相 加 求 和 ) dW^{[2]}=\frac{\partial J}{\partial W^{[2]}}=\frac1m\sum_{i=1}^m\frac{\partial L}{\partial W^{[2]}}=\frac1m\sum_{i=1}^m(a^{[2](i)}-y^{(i)})\boldsymbol a^{[1](i)}=\frac1m (\boldsymbol A^{[2]} - \boldsymbol Y) \boldsymbol A^{[1]T}\\ \frac{\partial J}{\partial b^{[2]}}=\frac1m\sum_{i=1}^m\frac{\partial L}{\partial b^{[2]}}=\frac1m\sum_{i=1}^m(a^{[2](i)}-y^{(i)})=\frac1m (\boldsymbol A^{[2]}-\boldsymbol Y)(水平相加求和) dW[2]=W[2]J=m1i=1mW[2]L=m1i=1m(a[2](i)y(i))a[1](i)=m1(A[2]Y)A[1]Tb[2]J=m1i=1mb[2]L=m1i=1m(a[2](i)y(i))=m1(A[2]Y)()同时在逻辑回归中, d z = ∂ L ∂ z = ∂ L ∂ a ⋅ ∂ a ∂ z = a − y dz =\frac{\partial L}{\partial z}=\frac{\partial L}{\partial a}\cdot \frac{\partial a}{\partial z}=a-y dz=zL=aLza=ay所以, d z [ 2 ] = ∂ L / ∂ z [ 2 ] = a [ 2 ] − y dz^{[2]}= \partial L / \partial z^{[2]}=a^{[2]}- y dz[2]=L/z[2]=a[2]y,同样的,根据链式求导法则: d z [ 1 ] = ∂ L ∂ z [ 2 ] ⋅ ∂ z [ 2 ] ∂ a [ 1 ] ⋅ ∂ a [ 1 ] ∂ z [ 1 ] = d z [ 2 ] W [ 2 ] g ′ [ 1 ] ( z [ 1 ] ) dz^{[1]}=\frac{\partial L}{\partial z^{[2]}}\cdot \frac{\partial z^{[2]}}{\partial a^{[1]}}\cdot \frac{\partial a^{[1]}}{\partial z^{[1]}}=dz^{[2]} W^{[2]}g'^{[1]}(z^{[1]}) dz[1]=z[2]La[1]z[2]z[1]a[1]=dz[2]W[2]g[1](z[1])这是一个样本,当有多个样本时候,可以表示为( ∗ * 表示每个对应元素相乘) d Z [ 1 ] = W [ 2 ] T d Z [ 2 ] ∗ g ′ [ 1 ] ( z [ 1 ] ) dZ^{[1]}=W^{[2]T}dZ^{[2]} * g'^{[1]}(z^{[1]}) dZ[1]=W[2]TdZ[2]g[1](z[1])所以 d W [ 1 ] = ∂ J ∂ W [ 1 ] = 1 m d Z [ 1 ] X T d b [ 1 ] = ∂ J ∂ b [ 1 ] = 1 m d Z [ 1 ] ( 水 平 相 加 求 和 ) dW^{[1]}=\frac{\partial J}{\partial W^{[1]}}=\frac1mdZ^{[1]}X^T\\db^{[1]}=\frac{\partial J}{\partial b^{[1]}}=\frac1m dZ^{[1]}(水平相加求和) dW[1]=W[1]J=m1dZ[1]XTdb[1]=b[1]J=m1dZ[1]()

代码实现

第三周浅层神经网络

深度神经网络

通过浅层神经网络已经了解了包含1个隐藏层的神经网络是怎样的结构以及如何向前向后传播,深度神经网络就是在浅层神经网络的基础上继续添加隐藏层获得的深度的结构,即为多隐藏层的逻辑回归。例如下图的结构即为包含了4个隐藏层的5层神经网络结构:
在这里插入图片描述
按照浅层神经网络的符号定义,输入 a [ 0 ] = x = [ x 1 , x 2 ] T a^{[0]}=x=[x_1,x_2]^T a[0]=x=[x1,x2]T 2 × 1 2 \times 1 2×1的列向量,输出(即 a [ 1 ] a^{[1]} a[1])为 3 × 1 3 \times 1 3×1的,所以 W [ 1 ] W^{[1]} W[1] 3 × 2 3 \times 2 3×2 维的, b [ 1 ] b^{[1]} b[1] 3 × 1 3 \times 1 3×1维。同理, W [ 2 ] W^{[2]} W[2] 5 × 3 5 \times 3 5×3 维的, b [ 2 ] b^{[2]} b[2] 5 × 1 5 \times 1 5×1维… W [ l ] W^{[l]} W[l] n l × n l − 1 n_l \times n_{l-1} nl×nl1 维的, b [ 2 ] b^{[2]} b[2] n l × 1 n_l \times 1 nl×1维。 n l n_l nl表示当前层的节点个数。这是一个样本的情况,当有 m m m个样本时候(输入为列向量向后堆叠), W [ l ] W^{[l]} W[l] n l × n l − 1 n_l \times n_{l-1} nl×nl1 维的, b [ 2 ] b^{[2]} b[2] n l × m n_l \times m nl×m维。

**Shape of W** **Shape of b** **Activation** **Shape of Activation**
**Layer 1** $(n^{[1]},12288)$ $(n^{[1]},1)$ $Z^{[1]} = W^{[1]} X + b^{[1]} $ $(n^{[1]},209)$
**Layer 2** $(n^{[2]}, n^{[1]})$ $(n^{[2]},1)$ $Z^{[2]} = W^{[2]} A^{[1]} + b^{[2]}$ $(n^{[2]}, 209)$
$\vdots$ $\vdots$ $\vdots$ $\vdots$ $\vdots$
**Layer L-1** $(n^{[L-1]}, n^{[L-2]})$ $(n^{[L-1]}, 1)$ $Z^{[L-1]} = W^{[L-1]} A^{[L-2]} + b^{[L-1]}$ $(n^{[L-1]}, 209)$
**Layer L** $(n^{[L]}, n^{[L-1]})$ $(n^{[L]}, 1)$ $Z^{[L]} = W^{[L]} A^{[L-1]} + b^{[L]}$ $(n^{[L]}, 209)$
计算流程

对于其中一层来讲,假设为 l l l层,向前传播时,输入为 a [ l − 1 ] a^{[l-1]} a[l1],输出为 z [ l ] = W [ l ] a [ l − 1 ] + b [ l ] z^{[l]}=W^{[l]}a^{[l-1]}+b^{[l]} z[l]=W[l]a[l1]+b[l] a [ l ] = g [ l ] ( z [ l ] ) a^{[l]}=g^{[l]}(z^{[l]}) a[l]=g[l](z[l]) g [ l ] g^{[l]} g[l]为第 l l l层的激活函数,为了简化后续计算,将 z [ l ] z^{[l]} z[l]缓存下来。向后传播时候,输入为 d a [ l ] da^{[l]} da[l],输出为 d a [ l − 1 ] da^{[l-1]} da[l1],同时计算 d W [ l ] dW^{[l]} dW[l] d b [ l ] db^{[l]} db[l]用于更新参数值。
在这里插入图片描述
在第 l l l层的向前计算中使用的公式为: z [ l ] = W [ l ] a [ l − 1 ] + b [ l ] a [ l ] = g [ l ] ( z [ l ] ) z^{[l]}=W^{[l]}a^{[l−1]}+b^{[l]}\\a^{[l]}=g^{[l]}(z^{[l]}) z[l]=W[l]a[l1]+b[l]a[l]=g[l](z[l])根据链式求导公式,有 d z [ l ] = d a [ l ] ∗ g [ l ] ′ ( z [ l ] ) d W [ l ] = d z [ l ] a [ l − 1 ] d b [ l ] = d z [ l ] d a [ l − 1 ] = W [ l ] T d z [ l ] dz^{[l]}=da^{[l]}*g^{[l]'}(z^{[l]})\\ dW^{[l]}=dz^{[l]}a^{[l-1]}\\ db^{[l]}=dz^{[l]}\\ da^{[l-1]}=W^{[l]T}dz^{[l]} dz[l]=da[l]g[l](z[l])dW[l]=dz[l]a[l1]db[l]=dz[l]da[l1]=W[l]Tdz[l]向量化表示为: d Z [ l ] = d A [ l ] ∗ g [ l ] ′ ( Z [ l ] ) d W [ l ] = 1 m d Z [ l ] A [ l − 1 ] T d b [ l ] = 1 m n p . s u m ( d Z [ l ] , a x i s = 1 ) d A [ l − 1 ] = W [ l ] T d A [ l ] d Z [ l − 1 ] = d W [ l ] T d Z [ l ] g [ l ] ′ ( Z [ l − 1 ] ) dZ^{[l]}=dA^{[l]}*g^{[l]'}(Z^{[l]})\\ dW^{[l]}=\frac1mdZ^{[l]}A^{[l-1]T}\\ db^{[l]}=\frac1m np.sum(dZ^{[l]},axis=1)\\ dA^{[l-1]}= W^{[l]T}dA^{[l]}\\ dZ^{[l-1]}=dW^{[l]T}dZ^{[l]}g^{[l]'}(Z^{[l-1]}) dZ[l]=dA[l]g[l](Z[l])dW[l]=m1dZ[l]A[l1]Tdb[l]=m1np.sum(dZ[l],axis=1)dA[l1]=W[l]TdA[l]dZ[l1]=dW[l]TdZ[l]g[l](Z[l1])


  1. 网易公开课,神经网络和深度学习,https://mooc.study.163.com/smartSpec/detail/1001319001.htm ↩︎

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值