好几天之前看,没有及时做笔记,现在重新整理都有点不知道怎么说顺了

第二周 神经网路基础

2.1 二分类

给定一个X,输出y 是0类还是1类。吴恩达以识别猫为例子,判断是不是猫。一张彩色图片,有三个通道,每个通道都存储著不同的像素点。把像素点堆叠成一个列向量x。

2.2 logistic 回归

用逻辑回归方法去分类是不是猫。

输入一张图片,由特征向量x来表示,输出 	ilde{y}=P(y=1|x), 0<=y<=1

输出采用激活函数,sigmoid,如果z趋于无穷大,输出为1;如果z趋于无穷小,则输出0。

逻辑回归方程的损失函数:

损失函数并没有采用最小二乘法,而是变换成了log形式: Loss(	ilde{y},y)=-(ylog	ilde{y}+(1-y)log(1-	ilde{y}))

这里的y为真实值 ,	ilde{y} 为输出值

J(w,b)这个式子中表示,将所有的样本相加求平均。通过这个式子,可以把w和b求出来。

2.3 梯度下降法

梯度下降法是解目标函数J的一种方法,在下图这个曲面中找到w,b,使得J最小。代价函数J必须为凸函数,如果是非凸的,波浪线那样,就会有很多局部最小值。

计算式子: w:=w-alphafrac{dJ(w,b)}{d(w)} b:=b-alphafrac{dJ(w,b)}{db}

2.4 计算图

计算图形式:

计算求导:

2.5 逻辑回归中的梯度下降法

首先表示成计算图的形式,通过这个图和链式法则就能很容易的求出梯度。

其中a是逻辑回归的输出,y是样本的标签值。

frac{dL(a,y)}{dw}=frac{dL(a,y)}{da}	imesfrac{da}{dz}	imesfrac{dz}{dw}

dz=frac{dL(a,y)}{dz}=frac{dL}{dz}=frac{dL}{da}*frac{da}{dz}=a-y

dw=x*dz db=dz

m个样本:w和b变化对代价函数L的影响

下图是关於单个样本实例的梯度下降法中参数更新一次的步骤:

2.6 m个样本的梯度下降

之前讨论了梯度下降在逻辑回归的一个训练样本上,现在讨论应用在m个训练样本上。

注意损失函数 J=(w,b) 的定义:

J(w,b)=frac{1}{m}sum_{i=1}^{m}{L(a^{(i)},y^{(i)})}

//代码流程
J=0;dw1=0;dw2=0;db=0;
for i=1 to m:
z(i)=wx(i)+b;
a(i)=sigmoid(z(i));
J+=-[y(i)loga(i)+(1-y(i)log(1-a(i))]
dz(i)=a(i)-y(i)
dw1+=x1(i)dz(i)
dw2+=x2(i)dz(i)
db+=dz(i)
J/=m
dw1/=m
dw2/=m
db/=m
w=w-alpha*dw
b=b-alpha*db

这里只有两个特证,n=2。实际上,这段代码,有两个for循环,第一个for循环是遍历所有的m样本,第二个循环是遍历所有的特征,从dw1,dw2到dwn。

当特征很多和样本很多的时候,for循环的效率很低。所以运用到了向量化。


2.7 向量化

向量化是我觉得非常很棒的一个trick!!!!!

使用向量化可以代替for循环。

例1:在逻辑回归中,你需要计算 z=w^{T}x+b,w,x 都是列向量。

如果有很多特征,那么w和x就会是一个非常大的向量: win R^{n_{x}},xin R^{n_{x}}

非向量化实现方式:

z=0
for i in range(n_x)
z+=w[i]*x[i]
z+=b

向量化实现方式:

import numpy
z=np.dot(w,x)+b

例2:计算向量u=AV

同时,numpy里有很多内置的函数,例如np.log,np.abs()

使用向量化去简化逻辑回归的梯度下降上的代码:

直接定义dw为一个向量dw=np.zeros((n_x,1))

逻辑回归的向量化计算:

能处理整个数据集,不会用一个明确的for循环。

逻辑回归的前向传播过程是:

假设你有m个样本,首先对第一个样本先计算。 z^{(1)}=w^{(T)}x^{(1)}+b ,然后计算激活函数 a^{(1)}=sigma(z^{(1)}) ,依次类推。

用一下代码即可实现:

Z=np.dot(w.T,X)+b


向量化 logistic 回归的梯度输出

在这之前,我们已经去掉了一个for循环,但仍有for循环遍历训练集。

向量化:

利用了5个公式完成了前向和后向传播,还实现了对所有训练样本的预测和求导。不过,下面只是展示了利用一次梯度下降的过程,如果是多次迭代梯度下降,还需要在外层加一个for循环。这里还用到了python中的broadcasing技术。这里就不展开讲了


找bug的小trick

在编写神经网路的时候,经常会发生一些维度错误。

例如定义 a=np.random.randn(5) a.shape=(5, ) 容易发现维度错误

应该定义成:a=np.random.randn(5,1) a.shape=(5,1)

不要吝啬使用a=a.reshape((5,1))

或如果不确定一个向量的维度的时候,可以使用断言语句。assert(a.shape==(5,1))

推荐阅读:

相关文章