感知器与梯度下降

声明:本文由Ronny发表在http://www.cnblogs.com/ronny/p/ann_01.html ,如需转载请注明出处

一、前言

1,什么是神经网络?

人工神经网络(ANN)又称神经网络(NN),它是一种受生物学启发而产生的一种模拟人脑的学习系统。它通过相互连结的结点构成一个复杂的网络结构,每一个结点都具有多个输入和一个输出,并且该结点与其他结点以一个权重因子相连在一起。通俗来说,神经网络是一种学习器,给它一组输入,它会得到一组输出,神经网络里的结点相互连结决定了输入的数据在里面经过怎样的计算。我们可以通过大量的输入,让神经网络调整它自身的连接情况从而总是能够得到我们预期的输出。

2,神经网络能干什么吗?

神经网络对于逼近实数值、离散值或向量值的目标函数提供了一种健壮性很强的方法,现在已经成功应用到很多领域,例如视觉场景分析、手写字符识别、语音识别、人脸识别等。它可以适用在任何实例是“属性-值”Feature→ValueFeature→Value的情况中,需要学习的目标函数是定义在可以用向量描述的实例上,向量由预先定义的特征组成,比如字符识别,那么特征可以是图像中的每个像素亮度值。

现代计算机识别的过程通常都可以描述为这样一个过程:对象 →→特征→→类别,理论上都可以用神经网络来解决。

本篇文章将是人工神经网络这个主题的第一篇文章,主要从最简单的神经网络结构入手,介绍一些基本算法原理。后面会陆续涉及到多层神经网络的原理及其C++实现,同时随着深度学习的提出,卷积神经网络也渐渐走进人们的视野,它在图像识别上表现非常不错,这个主题也将在后面的文章中有全面的介绍。

二、感知器

一个感知器的结构图如下:

稍后我们会知道感知器实际上是神经网络结构中的一个神经元,那么一个感知器就够成了最简单的神经网络系统(虽然还算不上是网络)。感知器是以一组实数向量作为输入,计算这些输入的线性组合,如果结果大于某个阈值就输出1,否则就输出-1。如果我们用公式表达,则假设输入为x1x1到xnxn,那么感知器可以表示为一个函数:

o(x)={1−1 if   w0+x1w1+?+xnwn>0 otherwiseo(x)={1 if   w0+x1w1+?+xnwn>0−1 otherwise

我们把−w0−w0看作是上面提到的阈值,w1w1至wnwn为一组权值。o(x)o(x)就是将输入向量按一组权重进行线性加权求和后做的一个符号函数。

我们可以把感知器看成nn维实例空间(点空间)中的超平面的决策面,平面一侧的所有实例输出1,对另一侧的实例输出-1,这个决策超平面的方程是w? ⋅x? =0w→⋅x→=0。

针对于我们在数据分类的应用时,就是将我们提供的所有样本数据分为2类,对于其中一类样本,感知器总是输出1,而另一类总是输出-1。但是对于任意样本总能找出这个超平面吗,或者是说是找出一组这样的权值向量吗?答案显然是否定的,只有线性可分的空间可以找到超平面,或者说可以找出一组权值。

那么我们怎么利用感知器呢?或者说我们的目标是什么?

我们希望找到一组这样的权值,对于我们输入的每一组向量,总是能够得到一个我们期望的值。但是上面的感知器功能显然不够,它只能得到2个结果,即1和-1。

在实际的模式分类的应用中,样本空间往往并不是线性的,即使是2维数据的集合也可能不是线性可分的,比如下面这张图:

而用这样的感知器结点来构建神经网络显然是不行的,因为线性单元连结在一起得到的仍然是线性单元,我们需要的是一种非线性映射,于是就产生了激活函数这个概念。激活函数是一种非线性函数同时是可微函数(可以求导数),为什么要可微呢,因为我们需要知道权重是怎么影响最终输出的,我们要根据输出来调节那些权重向量,也就是后面讲到的梯度下降法则。

激活函数有很多种,关于激活函数的种类这里不准备介绍太多,只要知道我们选用的是S型激活函数,它将整个一维空间映射到[0,1]或[-1,1]。下面是S型sigmoidsigmoid函数和它的导数:

f(x)=11+e−αx(0<f(x)<1)f(x)=11+e−αx(0<f(x)<1)

f′(x)=αe−αx(1+e−αx)2=αf(x)[1−f(x)]f′(x)=αe−αx(1+e−αx)2=αf(x)[1−f(x)]

经过这样的非线性映射,我们的感知器(现在应该叫SIMGOID单元)就变成了下面这种结构:

上面结构中w0w0我们习惯称它为偏置,相当于我们多了一个x0=1x0=1的输入。

对于上面这种结构,我们可以有如下结论:

1)对于任意一组输入和一个我们预想的在[0,1]之间的输出,我们总可以找到一组w? w→使得。

2)对于很多组这样的输入样本,我们可以通过不断的调整权值,来让它们的输出接近于我们预想的输出。

下面我们该考虑,如何求得这样的一组权值向量。

三、反向传播算法

我们需要在向量空间中搜索最合适的权值向量,但是我们不能盲目的搜索,需要有一定的规则指导我们的搜索,那么梯度下降就是很有用的方法。首先我们来定义输出误差,即对于任意一组权值向量,那它得到的输出和我们预想的输出之间的误差值。

定义误差的方法很多,不同的误差计算方法可以得到不同的权值更新法则,这里我们先用这样的定义:

E(w? )=12∑d∈D(td−od)2E(w→)=12∑d∈D(td−od)2

上面公式中DD代表了所有的输入实例,或者说是样本,dd代表了一个样本实例,odod表示感知器的输出,tdtd代表我们预想的输出。

这样,我们的目标就明确了,就是想找到一组权值让这个误差的值最小,显然我们用误差对权值求导将是一个很好的选择,导数的意义是提供了一个方向,沿着这个方向改变权值,将会让总的误差变大,更形象的叫它为梯度。

∇E(wi)=∂E∂w=12∂∑d∈D(td−od)2∂wi=12∑d∈D∂(td−od)2∂wi∇E(wi)=∂E∂w=12∂∑d∈D(td−od)2∂wi=12∑d∈D∂(td−od)2∂wi

既然梯度确定了E最陡峭的上升的方向,那么梯度下降的训练法则是:

wi→←wi→+Δwi→,其中Δwi→=−η∂E∂wiwi→←wi→+Δwi→,其中Δwi→=−η∂E∂wi

梯度下降是一种重要最优化算法,但在应用它的时候通常会有两个问题:

1)有时收敛过程可能非常慢;

2)如果误差曲面上有多个局极小值,那么不能保证这个过程会找到全局最小值。

为了解决上面的问题,实际中我们应用的是梯度下降的一种变体被称为随机梯度下降。上面公式中的误差是针对于所有训练样本而得到的,而随机梯度下降的思想是根据每个单独的训练样本来更新权值,这样我们上面的梯度公式就变成了:

∂E∂wi=12∂(t−o)2∂wi=−(t−o)∂o∂wi∂E∂wi=12∂(t−o)2∂wi=−(t−o)∂o∂wi

经过推导后,我们就可以得到最终的权值更新的公式:

wi=wi+Δwiδ=(t−o)o(1−o)Δwi=ηδxiwi=wi+Δwiδ=(t−o)o(1−o)Δwi=ηδxi

有了上面权重的更新公式后,我们就可以通过输入大量的实例样本,来根据我们预期的结果不断地调整权值,从而最终得到一组权值使得我们的SIGMOID能够对一个新的样本输入得到正确的或无限接近的结果。

四、实例说明

上面我们已经介绍了经过基本的感知器,我们构造了一种SIGMOID单元,可以对“输入向量-值”这种模式的数据进行目标函数的逼近,但是这毕竟只是单个神经元,它逼近不了太复杂的映射关系,我们需要构造一个多层的神经网络结构来解决更一般的学习与分类问题。

下面我们通过一个简单的逼近实例来说明单个SIMGOID单元的工作原理。

首先,我们假设我们的输入是一个4维的向量x=[x1,x2,x3,x4]x=[x1,x2,x3,x4],其中xixi的值为0或者1。为了简单其见,我们只设计了下面4种样本。

x1=[1,0,0,0]x2=[0,1,0,0]x3=[0,0,1,0]x4=[0,0,0,1]x1=[1,0,0,0]x2=[0,1,0,0]x3=[0,0,1,0]x4=[0,0,0,1]

对于这4类样本,我们希望它们得到4种不同的结果以说明它们属于哪一种,也就是我们的目标输出是一个标号,像下面这样:

x1→1x2→2x3→3x4→4x1→1x2→2x3→3x4→4

上面的样本只是4种,我们可以让每一种样本重复来构建大量的样本实例。比如实际采集到的样本可能会有所浮动,比如与x1x1同类的样本可能采集到的数据是这样的x=[0.993,0.002,0.0012,−0.019]x=[0.993,0.002,0.0012,−0.019],所以我们可以用很小的随机数来模拟大量的样本输入。

因为我们的SIMGOID单元输出值只可能是[0,1][0,1],所以我们可以将我们的类别标号归一化为[1,2,3,4]/4[1,2,3,4]/4,下面我们用C++来模拟这一过程。

1,样本获取:

 1 void SampleNN::getSamplesData()
 2 {
 3     const int iterations = 15000; // 15000个样本
 4     for (int i = 0; i < iterations; i++)
 5     {
 6         int index = i % 4;
 7         vector<double> dvect(4, 0);
 8         dvect[index] = 1;
 9         for (size_t i = 0; i != dvect.size(); i++)
10         {
11             dvect[i] += (5e-3*rand() / RAND_MAX - 2.5e-3);
12         }
13         inputData.push_back(dvect);
14     }
15 }

2,用[0,0.05]之间的随机值初始化权重。

1 void SampleNN::intialWgt()
2 {
3     // 4个连结和一个偏置w0
4     for (int i = 0; i != 5; i++)
5     {
6         weight.push_back(0.05*rand()/RAND_MAX);
7     }
8 }

3,向前计算

1 void SampleNN::cmtForward(const vector<double>& inVect)
2 {
3     double dsum = weight[4];//先把偏置加上
4     for (size_t i = 0; i != inVect.size(); i++)
5     {
6         dsum += (inVect[i] * weight[i]);
7     }
8     actual_output = 1 / (1 + exp(-1*dsum));
9 }

4,更新权重

 1 void SampleNN::updataWgt(const vector<double>& inVect,const double true_output)
 2 {
 3     double learnRate = 0.05; // 权重更新参数
 4     for (size_t i = 0; i != weight.size() - 1; i++)
 5     {
 6         weight[i] += (learnRate*(true_output - actual_output)*actual_output*(1 - actual_output)*inVect[i]);
 7     }
 8     // w0单独计算
 9     weight[4] += (learnRate*(true_output - actual_output)*actual_output*(1 - actual_output)*1);
10 }

下面是经过15000次迭代后得到的结果:

从上面结果可以看出,输出的值基本收敛于0.25、0.5、0.75与0.96,说明已经可以用来分类的了。

五、结束语

经过上面的讨论,单个神经元的功能及其原理应该可以清楚的了解,那么下一步,我们将用这些单个的神经元(SIGMOID单元)相互连结组成一个网状结构形成神经网络,并用来做更一些有意义的识别,这些内容将在下一篇文章中详细描述。

时间: 2024-10-24 07:26:14

感知器与梯度下降的相关文章

机器学习 —— 基础整理(六):线性判别函数——感知器、松弛算法、Ho-Kashyap算法

本文简单整理了以下内容: (一)线性判别函数与广义线性判别函数 (二)感知器 (三)松弛算法 (四)Ho-Kashyap算法 (一)线性判别函数与广义线性判别函数 一.线性判别函数 这篇总结继续关注分类问题.假设判别函数(Discriminant function)的参数形式已知,用训练的方法直接根据样本估计判别函数的参数.线性判别函数的形式为: $$g(\textbf x)=\textbf w^{\top}\textbf x+w_0$$ $\textbf x\in \mathbb R^d$ 是

机器学习推导笔记1--机器学习的任务、步骤、线性回归、误差、梯度下降

前段时间放假在家的时候,总算是看完了斯坦福的机器学习公开课(Andrew NG)的监督学习,这项计划持续了将近一个学期.无监督学习和强化学习部分暂时还不太想看,目前来说监督学习与我现在的情况更契合一些.看完监督学习部分,对机器学习的了解又深了一些,加上之前帮师兄做实验,从工程角度和理论角度共同推进,感觉还是挺好的. 为了巩固学习成果,在刷题之余,准备写一系列笔记,自己推导一遍机器学习里比较重要的几个算法,并附上自己的理解.我一直认为能讲出来的东西,才是自己的.写笔记有助于我自己理清思路,当然也希

随机梯度下降分类器和回归器

随机梯度下降分类器并不是一个独立的算法,而是一系列利用随机梯度下降求解参数的算法的集合. SGDClassifier(分类): from sklearn.linear_model import SGDClassifier clf = SGDClassifier(loss="hinge", penalty="l2") loss function(损失函数): 可以通过 loss 参数来设置.SGDClassifier 支持以下的 loss functions(损失函数

Stanford大学机器学习公开课(三):局部加权回归、最小二乘的概率解释、逻辑回归、感知器算法

(一)局部加权回归 通常情况下的线性拟合不能很好地预测所有的值,因为它容易导致欠拟合(under fitting).如下图的左图.而多项式拟合能拟合所有数据,但是在预测新样本的时候又会变得很糟糕,因为它导致数据的 过拟合(overfitting),不符合数据真实的模型.如下图的右图. 下面来讲一种非参数学习方法——局部加权回归(LWR).为什么局部加权回归叫做非参数学习方法呢?首先,参数学习方法是这样一种方法:在训练完成所有数据后得到一系列训练参数,然后根据训练参数来预测新样本的值,这时不再依赖

人工神经网络之感知器算法

感知器作为人工神经网络中最基本的单元,有多个输入和一个输出组成.虽然我们的目的是学习很多神经单元互连的网络,但是我们还是需要先对单个的神经单元进行研究. 感知器算法的主要流程: 首先得到n个输入,再将每个输入值加权,然后判断感知器输入的加权和最否达到某一阀值v,若达到,则通过sign函数输出1,否则输出-1. 为了统一表达式,我们将上面的阀值v设为-w0,新增变量x0=1,这样就可以使用w0x0+w1x1+w2x2+…+wnxn>0来代替上面的w1x1+w2x2+…+wnxn>v.于是有: 从

感知器、逻辑回归和SVM的求解

这篇文章将介绍感知器.逻辑回归的求解和SVM的部分求解,包含部分的证明.本文章涉及的一些基础知识,已经在<梯度下降.牛顿法和拉格朗日对偶性>中指出,而这里要解决的问题,来自<从感知器到SVM> .<从线性回归到逻辑回归>两篇文章. 感知器: 前面的文章已经讲到,感知器的目标函数如下: $min \ L(w,b)$ 其中,$L(w,b)=-\sum_{i=1}^{n}[y_i*(w*x_i+b)]$ 对于上面这种无约束的最优化问题,一般采用的是梯度下降的办法,但是,考虑到

统计学习方法(感知器)

感知机 假设:输入空间是 x?Rn 输出空间是 y={+1,-1} 由如下2.1函数进行分类称之为感知器 其中,w为权值向量,b为偏置 sign(.)是符号函数,记为如下所示: 感知机是一种线性分类模型,属于判别模型. 感知机模型的假设空间是定义在特征空间中的 所有线性分类模型(linear classification model)或 线性分类器(linear classifier) 即函数集合{f|f(x) = wx +b} 求感知机模型2.1,即求得模型参数w,b. 感知机预测,通过学习得

模式识别:感知器的实现

在之前的模式识别研究中,判别函数J(.)的参数是已知的,即假设概率密度函数的参数形式已知.本节不考虑概率密度函数的确切形式,使用非参数化的方法来求解判别函数.由于线性判别函数具有许多优良的特性,因此这里我们只考虑以下形式的判别函数:它们或者是x的各个分量的线性函数,或者是关于以x为自变量的某些函数的线性函数.在设计感知器之前,需要明确以下几个基本概念: 一.判别函数:是指由x的各个分量的线性组合而成的函数: 若样本有c类,则存在c个判别函数,本节只讨论两类样本的分类情况.要求实现以下判定规则:

感知器算法--python实现

写在前面: 参考: 1  <统计学习方法>第二章感知机[感知机的概念.误分类的判断]   http://pan.baidu.com/s/1hrTscza 2   点到面的距离 3   梯度下降 4   NumPy-快速处理数据    属性shape:表示几行几列:   dot(a,b) 计算数组.矩阵的乘积 感知器算法: Python实现: #coding:utf-8 import numpy as np class Perceptron(object): def __init__(self)