MLP(多层神经网络)介绍
写在前面的
接触神经网络(ANN)的时间很长了,以前也只是学了学原理,做过一个BPN的练习,没有系统的总结过,最近看Torch的源码,对MLP有了更多的了解,写写自己学到的东西吧,算是做了一次总结!
ANN的特点
(1) 高度的并行性
人工神经网络是由许多相同的简单处理单元并联组合而成,虽然每个单元的功能简单,但大量简单单元的并行活动,使其对信息的处理能力与效果惊人。
(2) 高度的非线性全局作用
神经网络系统是由大量简单神经元构成的,每个神经元接受大量其他神经元的输入,通过非线性输入、输出关系,产生输出影响其它神经元。网络就是这样互相制约相互影响,实现从输入状态空间到输出状态空间非线性映射的。网络的演化遵从全局性作用原则,从输入状态演化到终态而输出。从全局观点来看,网络整体性能不是网络局部性能的简单迭加,而表现某种集体性行为;而电脑遵从串行式局域性操作原则,每一步计算与上一步计算紧密相关,并对下一步产生影响,问题是通过算法逐步进行处理的。
(3) 良好的容错性与联想记忆功能
人工神经网络通过自身的网络结构能够实现对信息的记忆,而所记忆的信息是存储在神经元之间的权值中。从单个权值中看不出所储存的信息内容,因而是分布式的存储方式。这使得网络具有良好的容错性,并能进行聚类分析、特征提取、缺损模式复原等模式信息处理工作。
十分强的自适应、自学习功能人工神经网络可以通过训练和学习来获得网络的权值与结构,呈现出很强的自学习能力和对环境的自适应能力。
ANN分类
BPN(Back Propagation Net)
在这里我介绍一下反向传播网络BPN---带动量项的误差反传。反向传播神经网络是对非线性可微分函数进行权值训练的多层网络,是前向神经网络的一种。BP网络主要用于:
1)函数逼近与预测分析:用输入矢量和相应的输出矢量训练一个网络,逼近一个函数或预测未知信息;
2)模式识别:用一个特定的输出矢量将它与输入矢量联系起来;
3)分类:把输入矢量以所定义的合适方式进行分类;
4)数据压缩:减少输出矢量维数以便于传输与存储。
比如,一个三层BPN结构如下:
由输入层、隐含层和输出层三层组成。其中每一层的单元与与之相邻层的所有单元连接,同一层的单元之间没有连接。当一对学习样本提供给网络后,神经元的激活值从输入层经各中间层向输出层传播,在输出层的各神经元获得网络的输入响应。接下来,按照减少目标输出与实际误差的方向,从输出层经过各中间层逐层修正各连接权值,最后回到输入层。
感知器(Perception)类型
linear----线性感知器
tanh----双曲正切函数
sigmoid----双曲函数
softmax----1/(e(net) * e(wi*xi- shift))
log-softmax---- log(1/(e(net) * e(wi*xi)))
exp----指数函数
softplus----log(1+ e(wi*xi))
梯度下降
Delta学习方法
增量梯度下降
MLP的缺陷
1.网络的隐含节点个数选取问题至今仍是一个 世界难题(Google, Elsevier, CNKI);
2.停止阈值、学习率、动量常数需要采用”trial-and-error”法,极其耗时(动手实验);
3.学习速度慢;
4.容易陷入局部极值,学习不够充分。
应用举例
- static void Main(string[] args)
- {
- int row = 2;//训练样例的数目
- int n_in = 2;//输入值的个数
- int n_out = 1;//输出值的个数
- int n_hidden = 1;//隐含层单元个个数
- double eta = 0.3;//学习速率
- double alfa = 0.9;//动量项
- int [,] t_ex = new int[row,n_in + n_out];//训练样例
- //赋初值 训练样例
- t_ex[0, 0] = 1;
- t_ex[0, 1] = 0;
- t_ex[0, 2] = 1;
- t_ex[1, 0] = 0;
- t_ex[1, 1] = 1;
- t_ex[1, 2] = 0;
- double[] Delta_Out = new double[n_out];//输出单元误差
- double[] Delta_Hidden = new double[n_hidden];//隐藏单元误差
- double[] O_Out = new double[n_out];//输出单元的输出
- double[] O_Hidden = new double[n_hidden];//隐含单元的输出
- double[,] W_Out = new double[n_out,n_hidden + 1];//输出单元的权值
- double[,] W_Hidden = new double[n_hidden,n_in + 1];//隐含单元的权值
- double[,] Delta_W_Out = new double[n_out,n_hidden + 1];//输出单元的权值差
- double[,] Delta_W_Hidden = new double[n_hidden,n_in + 1];//隐含单元的权值差
- //初始化所有网络权值为0.1
- for (int i = 0; i < n_out;i++ )
- {
- for (int j = 0;j < n_hidden + 1;j++)
- {
- W_Out[i,j] = 0.1;
- Delta_W_Out[i,j] = 0;
- }
- }
- for (int i = 0; i < n_hidden; i++)
- {
- for (int j = 0; j < n_in + 1;j++ )
- {
- W_Hidden[i,j] = 0.1;
- Delta_W_Hidden[i,j] = 0;
- }
- }
- //迭代进行训练
- bool over = true;
- int itera_time = 0;//迭代次数
- while (over)
- {
- //进行训练
- for (int i = 0; i < row;i++ )
- {
- //计算隐含层单元的输出
- double net = 0;
- for (int j = 0; j < n_hidden; j++)
- {
- net = W_Hidden[j, 0];
- //计算输出值
- for (int r = 1; r < n_in + 1; r++)
- {
- net += W_Hidden[j, r] * t_ex[i, r - 1];
- }
- O_Hidden[j] = 1.0 / (1 + Math.Exp(-net));
- }
- //计算输出层单元的输出
- for (int j = 0; j < n_out;j++ )
- {
- net = W_Out[j,0];
- for (int r = 1; r < n_hidden + 1;r++ )
- {
- net += W_Out[j,r] * O_Hidden[r - 1];
- }
- O_Out[j] = 1.0 / (1 + Math.Exp(-net));
- }
- //计算输出层单元的误差项
- for (int j = 0; j < n_out;j++ )
- {
- Delta_Out[j] = O_Out[j] * (1 - O_Out[j]) * (t_ex[i,n_in + j] - O_Out[j]);
- }
- //计算隐含层单元的误差项
- for (int j = 0;j < n_hidden;j++)
- {
- double sum_weight = 0;
- for (int k = 0;k < n_out;k++)
- {
- for (int h = 0;h < n_hidden + 1;h++)
- {
- sum_weight += Delta_Out[k] * W_Out[k,h];
- }
- }
- Delta_Hidden[j] = O_Hidden[j] * (1 - O_Hidden[j]) * sum_weight;
- }
- //更新每个网络单元的权值
- //更新输出层的权值
- for (int j = 0;j < n_out;j++)
- {
- Delta_W_Out[j, 0] = eta * Delta_Out[j] + alfa * Delta_W_Out[j, 0];
- W_Out[j, 0] = W_Out[j, 0] + Delta_W_Out[j, 0];
- for (int k = 1; k < n_hidden + 1;k++ )
- {
- Delta_W_Out[j, k] = eta * Delta_Out[j] * O_Hidden[k - 1] + alfa * Delta_W_Out[j, k];
- W_Out[j, k] = W_Out[j, k] + Delta_W_Out[j, k];
- }
- }
- //更新隐含层的权值
- for (int j = 0; j < n_hidden; j++)
- {
- Delta_W_Hidden[j, 0] = eta * Delta_Hidden[j] + alfa * Delta_W_Hidden[j, 0];
- W_Hidden[j, 0] = W_Hidden[j, 0] + Delta_W_Hidden[j, 0];
- for (int k = 1; k < n_in + 1;k++ )
- {
- Delta_W_Hidden[j, k] = eta * Delta_Hidden[j] * t_ex[i, k - 1] + alfa * Delta_W_Hidden[j, k];
- W_Hidden[j, k] = W_Hidden[j, k] + Delta_W_Hidden[j, k];
- }
- }
- }
- //训练1000次结束循环
- itera_time++;
- if (itera_time == 1000)over = false;
- }
- //输出训练后的权值
- Console.WriteLine("输出层权值:");
- for (int i = 0; i < n_out; i++)
- {
- for (int j = 0; j < n_hidden + 1;j++ )
- {
- Console.WriteLine(W_Out[i,j]);
- }
- }
- Console.WriteLine("隐含层权值:");
- for (int i = 0; i < n_hidden; i++)
- {
- for (int j = 0; j < n_in + 1;j++ )
- {
- Console.WriteLine(W_Hidden[i,j]);
- }
- }
- }
- }
原文:http://blog.csdn.net/cxf7394373/article/details/6061372