这个系列主要记述了笔者学习 Andrew NG 在coursera上的Deep Learning系列课程的笔记与代码实现。
前两篇文章传送门:Andrew NG 深度学习课程笔记(一)、AndrewNG深度学习课程笔记(二)。每篇笔记的内容大致包括一周的课程内容,网易上有课程视频,但没有作业,想要完成对应编程练习和证书还是需要到coursera上学习。如果你也在coursera上学习了Andrew的课程,在做后面编程作业时有困难的话,可以私信我,因为他有申明不能把自己的代码公开出来,所以这里,我不方便把我的代码放出来。
这次的内容是浅层神经网络,还是通过逻辑回归应用来介绍神经网络是如何运作的。因为其中涉及了不少python编程的内容,所以我会先介绍一下这里面运用到的python numpy的一些基本计算,然后再以逻辑回归为例介绍神经网络的构建。
numpy中常用的矩阵、向量运算
用python写机器学习算法的过程中,numpy几乎是一个必不可少的库,关于numpy详细的介绍可以去google上搜一下官网,这里,我只介绍一下我在学习这门课里,Andrew经常用到的两个运算,np.sum和np.dot。
np.sum
这个函数我想介绍的主要是他的两个数,axis 和keepdims。
axis指的是用什么维度来进行求和运算,对于二维的矩阵,axis=0表示按列相加,axis=1表示按行相加,如下图:
对于多维的情况,有一个不是很简单,但是很好理解的方法是:你的输入矩阵的shape是(2,2,4),那么当axis=0时,就是在第一个维度上进行求和,最后得到的结果的shape就是去掉第一个dimension后的shape,也就是(2,4)。具体的计算方法则是,对于c[i,j,k],假设输出矩阵为s[j,k],第一个维度求和那么就是s[j,k]=∑i(c[i,j,k]);如果axis=1,那么输出shape就是去掉第二个dim,也就是(2,4),计算是 s[i,k]=sumj(c[i,j,k]);如果axis=2,那么输出shape就是去掉第三个dim,也就是(2,2),计算是 s[i,j]=sumk(c[i,j,k])。
在数据处理里面经常会碰到高维数据,通过二维矩阵去想它的计算方法就很难了,这个时候只要按axis对应的维度求和,其他维度的位置和形状不变,最后把shape去掉对应维度就能理解了。
keepdims就比较简单了,就是为了避免矩阵的shape变成(4,)这种情况,因为如果出现这种缺省情况的出现,后面的计算就都跟着出错了。
np.dot
这个运算其实很简单,就是向量相乘。重点是要区别于python里的“*”运算,np.dot是真正意义上的矩阵相乘,同线性代数里的矩阵乘法定义。
当两个向量直接用运算符“*”进行相乘时,其实是和np.multipy一样的,被称作element-wise间的运算,就是对应元素相乘。这个运算在后面的程序中也会用到。
神经网络构建
在构建一个神经网络之前,可能很多同学之前就听说过梯度下降法,听说过正向传播,反向传播这些术语,其实这些听起来好像很复杂,其实过程非常简单,总结起来,就是下面这几个步骤:
1. 定义神经网络的结构(包括输入层,隐藏层等)
2. 初始化模型参数
3. 循环以下步骤:
3.1 通过正向传播计算loss
3.2 通过反向传播计算出要更新的梯度(gradients)
3.3 更新模型参数
3.4 迭代第3步
在前一篇博客里,我们把逻辑回归表示成y^=wx+b的形式,这里的w和b就是输入的参数,也就是每次迭代之后要调整的值。之前我们的梯度下降法概况起来就是,将逻辑回归表示成y^=wx+b,因为这个函数是个线性函数,我们期望的y取值是0到1之间(因为是二分类问题),所以这里用了一个sigmoid激活函数,把y取值映射到了0到1之前,之后再计算损失函数。计算损失函数的过程就是正向传播。计算出了损失函数的值,就需要再利用反向传播计算梯度,也就是下一次迭代中,我们需要如何调整输入的w和b这两个参数。这个调整的过程也就是学习的过程。因为我们希望损失函数的取值越小越好,所以这里用了求导数的操作来计算梯度,取了损失函数取值下降最快的方向来更新我们的输入参数。
以上是之前就介绍过的,如果在多一层神经网络呢?其实过程是基本相同的。第一层的输入就是整个网络的输入,也就是input layer, 计算出来的输出,就是下一层的输入,只不过每一层可以选用不同的激活函数。
(上述过程在编程的时候,如果理解不透彻的话,很容易就把其中矩阵的维度搞错了,这里提示一个矩阵维度推导小技巧: W[1]表示第一层中的参数W, 假设W.shape是(4,3),则表示当前层一共有4个神经元,输入到当前层的特征数是3。)
比较常用的激活函数有ReLU和tanh。tanh函数和sigmoid比较相似,但在大多数情况下,tanh会优于sigmoid, 因为tanh的输出更加接近于0,使得神经网络的下一层数据更加集中。
可能有同学会问,为什么激活函数不能用线性函数? 因为使用线性模型的隐藏层和没用使用是一样的。但在输出层里,有些特定的情况下,是会使用线性模型的,比如压缩相关的一些处理。
(关于激活函数的选择,后面的课程好像会有更多的内容)
编程练习
这次的编程练习,是要把下图中红色和蓝色的点做分类。
因为数据集是非线性的,练习中有用传统机器学习中的逻辑回归来尝试完成,但效果很差,但使用两一个两层的神经网络却达到了比较好的效果,还是很有意思的。
版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明出处:来自陈晖的博客浅层神经网络——Andrew NG 深度学习课程笔记(三)!