本文基于
coursera 斯坦福吴恩达机器学习课程
谢绝任何形式的转载
这周是讲一下神经网络的基础概念。
第一部分 非线性假设
之前的线性回归和逻辑回归都属于线性假设的范围。他们能解决的问题是有限的,在自变量非常多的情况下(比如图像处理、图像识别问题),拿线性假设建模(尤其是多项式模型)是不切实际且昂贵的。
例如,对一个50*50像素点的图片,我们就有2500像素,普通线性模型自变量就有2500个。对于RGB呈像,那么就会有7500个自变量。
第二部分 神经和大脑
神经网络的起源就是在模仿大脑,在80-90年代神经网络的使用非常广泛,90年代后期逐渐减少,近年又复苏了起来。
根据高中生物我们知道,胚胎干细胞理论上可以发育成任何细胞,神经元记不太清了。有研究表明,一块脑组织理论上是可以被培育成具有独立功能的区域的,可以用于听觉、嗅觉等独立功能。只要给它不同的刺激,它就会相应产生特殊的功能(输出)。
下图是一个神经元的示意图。因为我高中生物基本忘光了,所以可能说的不太准确,意会意会。一定量的树突接收外界刺激,经过轴突深入神经内部,由轴突的神经节点一个个处理,最后被运送到神经轴突终端。
词汇表
Dendrite: 树突
Axon:轴突
neuron: 神经
brain: 大脑
terminal:终端
——摘自coursera吴恩达机器学习
神经网络是由若干个神经元组成的,如下图所示。刺激由上面的神经元经过内部节点传输处理,到达下一个神经元进行更深度的处理。这就是人类神经网络的运作方式,机器学习的神经网络是仿照人类神经构成的。
——摘自coursera吴恩达机器学习
第三部分 神经网络模型表达式
下面我们来看一下神经网络的运作(下图)。这是最简单的神经网络。
x1, x2, x3是三个给出的刺激,他们顺着树突(三个箭头)进入神经元(黑色圆圈),在每一个节点处,都有一个激励函数activation function来对信号进行处理(通常为sigmoid 函数)。神经元处理过后再通过轴突(右边的水平箭头)做出反应(hθ(x))。
有时候我们也会添加一个x0,这里的x0和逻辑回归、线性回归的x0同,被称为bias unit(偏置单位)。x0是不必须画出的。
在神经网络里,参数θ不再被称为“参数”,而是叫做权重weights,可以理解为不同的刺激对神经的影响不同,但是其实它们本质是一样的。
sigmoid(逻辑)激励函数
sigmoid是常用的一类激励函数,常用g(z)表示(通常情况下,z = θX)。其曲线如下图所示。在[-∞,-4]处,其函数值无限接近于0;在[4, +∞]处,其函数值无限接近于1. 这是未来会使用到的重要性质。
下面我们再来看一个复杂一点的例子. 因为微信编辑功能有限,所以图中的【a上标2下标0】我就写作a(2,0)了,其它同。
x0和a(2,0)都被称为偏置单元,值恒为1.
首先我们来看“层(layer)”的概念:
自变量x所在的第一层被称为输入层(input layer),输出h的最后一层第三层被称为输出层(output layer)。
其中间的第二层被称为隐藏层(hidden layer)。因为它没有输入也没有输出,只是在内部进行处理。从监督学习的概念上,我们可以看到的过程被称为输入或输出,神经网络中这种既没有认为输入也没有最终输出的层都被称为隐藏层。
其次我们来确定几个术语:
(1)a(i,j)代表着第i层(隐藏层)的第j个激励单元 activation (hidden units),例如a(2,1)就是第二层的第一个激励(这里我们隐去了a(2,0),这些叫法都是灵活的,不重要)。
(2)θ则被称为从第i层映射到第i+1层的权重矩阵。每两层之间都会有一个θ矩阵。θ(i,j)表示从i到i+1层映射的第j个权重。θ(i)则表示两层之间的权重矩阵。
(3)这整个三层,3/3/1节点分布的架构被称为神经网络架构(neural network architecture)。
在sigmoid逻辑激励函数下,激励a和最终的h的表达式如下:
——摘自coursera吴恩达机器学习
方便起见,也可以写成a(2,1) = g(z(2,1))的形式。
上图中的theta(1)表示第一层到第二层之间3*4的权重矩阵。对于两层节点数不一样多的情况,θ的维度为【下一层的节点数*(这一层节点数+1)】.
接下来我们要学习一个重要概念:前向传播 Forward Propagation. 依然用上面的例子,从第一层开始,我们计算出第二层每个a的值,然后再应用第二层的a计算出第三层的h.这样从第一层依次计算得出h的方式就是forwar propagation. 非常简单易懂。
在实际代码中,我们需要向量化这个过程,所以就需要x0和a(2,0)的存在了,要记得他们的值恒为1.
看了这么多,那么为什么神经网络能够帮我们解决非线性问题呢?我们把上图拆分来看:
只看第二层和第三层,我们会发现它其实就是一个逻辑回归。三个变量a1,a2,a3作为输入,通过sigmoid逻辑函数得出h。
但是这里的逻辑回归输入a比之前我们看到的更高级,因为它是x1,x2,x3(和x0)每一个变量作用在每一个隐藏单元a上得到的。拆分出来如下图所示。这还仅仅是三个变量和一层隐藏层,可以想象神经网络是非常灵活和强大的。
第四部分 神经网络的简单应用
这一部分用一个例子来讲一讲神经网络内部的运算是怎么进行的。
我们想对下图左边的红叉(y=1)和蓝圈(y=0)进行分类,自变量为01二项分布,问题可以简化为下图右边坐标图所示。表达式如图所示,是一个XNOR的逻辑运算。
XNOR 同或门
表示除了或之外所有运算结果均为0的逻辑运算。
那么我们需要神经网络来做一个异或门的表达。
首先我们学习一下最简单的逻辑运算之一与门的神经网络表达。如下图所示,我们有两个自变量x1,x2和偏置单位x0,θ值如下图所示。
我们使用sigmoid来计算输出:
回忆上文,sigmoid函数为:
所以我们有:
可以看出只有在x1 AND x2时,逻辑运算结果为1,所以这是一个与门的神经网络架构。同理我们可以得到或门和【(NOT X1)AND(NOT X2)】的两个神经网络架构。把这三个架构组合在一起,就是我们想要的同或门的架构:
——摘自coursera吴恩达机器学习
顺便复习一下,这里的θ(1)是一个2*3的矩阵~
第五部分 多类别分类
多类别分类问题指的是输出结果不止两种的分类问题。例如将一堆个位数字按照0-9十种分类。多类别分类我们依然使用逻辑回归中提到的one-vs-all mehtod.
这里我们用一个现成的例子理解(如下图所示)。想要将行人、汽车。摩托车和卡车分类,我们构建了如下的神经网络。不同于上面的神经网络架构,这次我们给它4个输出,每个输出分别对应0或1. 我们规定如果h = ^T, 那么输入就是一个行人;h = ^T, 输入就为一辆车;... 也是很好理解的。
第四周编程作业笔记(matlab)
这一周的作业是分别用逻辑回归和神经网络的one-to-all method对5000组有着400个自变量的像素数据进行分类,识别0-9这10个数字。下图为抽取的100组数据组成的100个数字,大概就长这样,识别它们是几。
第一部分 逻辑回归
我们需要写的是正则化后的cost function和梯度下降算法,紫色为我的代码:
文件名:lrCostFunction.m
初始化变量先:
m = length(y); % number of training examples
J = 0;//cost function值
grad = zeros(size(theta)); //梯度下降得到的参数
//根据公式,这里θ0不应该被正则化:
temp = theta;
temp(1) = 0;
//计算sigmoid结果:注意这里带入的是整个参数含θ0
H = sigmoid(X*theta);
//根据公式计算cost function:注意这里x0没有被正则化
J = ((-y)'*log(H)-(1-y)'*log(1-H))/m+lambda/(2*m)*sum(temp.^2);
//计算正则化梯度下降得到的theta:
grad = X'*(H-y)/m+lambda/m*temp;
然后我们需要补全one-vs-all method来计算出所有的theta值。输出结果有10种可能,所以theta有10行,变量有400个,加上x0,theta有(400+1)列:
文件名:oneVsAll.m
还是变量声明先:
m = size(X, 1);
n = size(X, 2);
% You need to return the following variables correctly
all_theta = zeros(num_labels, n + 1);
% Add ones to the X data matrix
X = [ones(m, 1) X];
//fmincg()指从theta初始值initial_theta开始,使用lrCostFunction()函数寻求局部最优解,选项为迭代50次。
//y==i表示给y中所有和i相等的值赋值为1,其余全部为0.
//这个地方我卡了很久,matlab的下标是从1开始,我一直想着0为基,i从0开始,bug卡了很久。然后又死活想不通y==10怎么可以出结果,数字明明是0-9,但是y==i-1又过不去。后来又突然想起来做过的题显示one-vs-all method中,改变theta排列顺序并不会影响预测结果,这里循环第1-9次的theta是和i一一对应的。第一次循环对应的是数字1,第二次是数字2,。。。到第10次循环的theta,y = 10,是数字0的theta的结果。
options = optimset('GradObj','on','MaxIter',50);
for i = 1:num_labels,
initial_theta = zeros(n+1,1);
[all_theta(i,:)]=fmincg(@(t)(lrCostFunction(t,X,(y==i),lambda)),initial_theta,options);
end;
在这之后,写一个预测函数来进行预测:
文件名:predictOneVsAll.m
% Useful value
m = size(X, 1);
num_labels = size(Theta2, 1);
% You need to return the following variables correctly
p = zeros(size(X, 1), 1);
X = [ones(m, 1) X];
% ====================== YOUR CODE HERE ======================
A = zeros(size(X,1),num_labels);//创建一个存放结果的矩阵
A = X*all_theta';//计算所有的预测值
[value,p] = max(A,[],2);//在5000个实例中,寻找出每一个实例的预测最大值value,返回这个最大值所在的位置。这里再一次证明了oneVsAll.m里面的y=10是数字0的参数。这里的不再是h=表示数字0,而是h=。当计算出来的这个预测的结果最佳,返回的就是这个实例中的最大值value的位置10.
第二部分 神经网络
这里的神经网络还很简单,网络架构都是给好的,权重也是填充好的,我只需要完成预测就可以:
文件:predict.m
m = size(X, 1);
num_labels = size(Theta2, 1);
% You need to return the following variables correctly
p = zeros(size(X, 1), 1);
//这里基本和上面的一样,就是逻辑回归改成了神经网络的计算。
X = [ones(m,1) X];
a2 = sigmoid(X*Theta1');//算第二层的a
a2 = [ones(size(a2,1),1) a2];//给第二层加一个a0
[unused,p] = max(a2*Theta2',[],2);//算最后一层并且返回最大值的位置
最后展示一个运行结果,可以说非常好玩了:
领取专属 10元无门槛券
私享最新 技术干货