神经网络
背景
普通的逻辑回归模型,不能有效地处理这么多的特征,这时候我们需要神经网络。
模拟神经元和大脑,通过找出一些近似的或实际的大脑学习算法,然后实现它大脑通过自学掌握如何处理这些不同类型的数据。
在很大的程度上,可以猜想如果我们把几乎任何一种传感器接入到大脑的几乎任何一个部位的话,大脑就会学会处理它。
模型表示
概述
神经网络模型是许多逻辑单元按照不同层级组织起来的网络,每一层的输出变量都是下一层的输入变量。下图为一个3层的神经网络,第一层成为输入层(Input Layer),最后一层称为输出层(Output Layer),中间一层成为隐藏层(Hidden Layers),(有些时候隐藏层不止一层)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNiNx8FesU2cfdGLwczX0xiRGZkRGZ0Xy9GbvNGLwIzXlpXazxSP4cVY6pEWaJXOtFWQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL0IDN0MTN4kTZ1U2M1IDO4czM3QjY4EmZ5EjMiRmMhVzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
参数定义:
Θ为神经网络最重要的参数,有时参数也被叫做权重,其中 Θ ( j ) Θ(j) Θ(j)表示从第j层到第j+1层的运算矩阵,他的维数是以第j+1层的激活单元数量为行数,以第j层的激活单元数加一为列数的矩阵 ( s j + 1 ∗ s j + 1 ) (s_{j+1}*s_j+1) (sj+1∗sj+1)
公式是 Θ ∗ x = z , a = g ( z ) Θ*x=z,a=g(z) Θ∗x=z,a=g(z)
加一是因为我们为每一层都增加一个偏差单位(bias unit),即函数的截距
而在某些资料里参数也被定义为(W, b),其中W表示参数矩阵,b表示偏置项或截距项
递进关系
注意矩阵运算完后,要走一遍激活函数。
与逻辑回归的比较
神经网络和线性回归也很相似,只不过我们把 a 0 , a 1 , a 2 , a 3 a_0,a_1,a_2,a_3 a0,a1,a2,a3看成更高级的特征值,由X和Θ共同决定,这些项会比简单的x多次项更加灵活,更适合于整个模型
实际应用举例:逻辑表示
简单的逻辑运算:与或非
因为由激活函数的存在,如果能让 z = Θ ∗ x z=Θ*x z=Θ∗x为一个较大的正数,则h(z)的值能趋近于1,而如果z为较大的负数,
h(z)的值能趋近于0。赋系数矩阵的方法是列出真值表,然后对着真值表倒推系数
较复杂的逻辑运算:同或(XNOR)
同或运算相较于较为复杂,采用了标准的三层结构,先是分别一个and运算和一个nor运算递进到隐藏层,再在隐藏层里通过or运算递进到输出层(注意偏差单位的引入),这样就得到了一个实现同或运算的神经网络。
按这种方法我们可以逐渐构造出越来越复杂的函数,也能得到更加厉害的特征值。
多类分类
(直接贴大佬的笔记照片了)
代价函数
神经网络的代价函数可以类比正则化后逻辑回归的代价函数
解读:k的值是特征值的个数,就是最后输出层的值个数;
m是样本个数,这一部分只算最后输出层的误差,
后面的Θ是是要计算每一层的Θ矩阵中的每一个值求和
反向传播算法
反向传播算法是神经网络的基础算法,主要是为了计算出代价函数 J ( Θ ) J(Θ) J(Θ)相对于 Θ Θ Θ的偏导数
step 1: 前向传播
从输入层经过多层参数计算至输出层
step 2:反向传播
数学理解和证明较为麻烦,本质上是一系列链式求导法则的应用
我们用 δ i l δ_i^l δil表示 a i l a_i^l ail的误差(第l层第i个单元),我们首先可以算出最后一层(输出层的误差),假如有4层,则最后一层的误差是 δ ( 4 ) = a ( 4 ) − y δ^{(4)}=a^{(4)}-y δ(4)=a(4)−y, 得到了这个之后可以不断向前递推, δ ( 3 ) = ( Θ ( 3 ) ) T ∗ δ ( 4 ) ∗ g ′ ( z ( 3 ) ) δ^{(3)}=(Θ^{(3)})^T* δ^{(4)}* g^{'}(z^{(3)}) δ(3)=(Θ(3))T∗δ(4)∗g′(z(3)),注意这里不会有 δ ( 1 ) δ^{(1)} δ(1)(输入层)
这里 g ( z ) g(z) g(z)函数求导常用,是a*(1-a)
对于误差项的理解是:
矩阵向量化
在实际应用中,我们如果调用更高级的优化算法,如fminuc,MATLAB库里的接口要求我们的参数矩阵和返回的梯度矩阵都表达为一维向量的形式,所以我们在实际的编程过程中,要注意对矩阵的拆解和重组:
详细的讲解过程可以看这里: 反向传播——通俗易懂_chengchaowei的博客
梯度检验
当我们训练的模型非常复杂时,可能会出现一些不为人知的错误,导致梯度出现一定的误差,所以我们可以采用一定的检验手段
具体方法是,在Θ的左边和右边各取一个极小值,观察这两点之间的连线斜率和Θ点导数的值比较
注意偏导的书写形式
随机初始化
当我们初始化所有参数为0时,在逻辑回归时可以,但是在反向传播时,神经网络里使每一项的偏导相同,无法更新,所以我们不能初始化所有参数为同一个值。
一般来说我们会初始化所有参数为正负 ε ε ε之间的随机数
Theta1 = rand(10, 11) * (2*eps) – eps
综合
主要是选择网络结构:层数和每层的单元数
注意隐藏层内每一层的单元数要相同,通常是越多越好
我们真正要决定的是隐藏层的层数和每个中间层的单元数
训练步骤
- 参数的随机初始化
- 利用正向传播方法计算所有的 h Θ ( x ) h_Θ(x) hΘ(x)
- 编写计算代价函数 J J J的代码
- 利用反向传播方法计算所有偏导数
- 利用数值检验方法检验这些偏导数
- 使用优化算法来最小化代价函数