来自人工智能贴吧,利_刃。仅供收藏。

关于Matlab的入门教程,参看这个帖子:tieba#baidu#com/p/2945924081




例1:我们都知道,面积=长*宽,假如我们有一组数测量据如下:


matlabpython神经网络 matlab神经网络怎么用_归一化


我们利用这组数据来训练神经网络。(在Matlab中输入以下的代码,按回车即可执行)




p = [2 5; 3 6; 12 2; 1 6; 9 2; 8 12; 4 7; 7 9]'; % 特征数据X1,X2


t = [10 18 24 6 18 96 28 63]; % 样本值


net = 

newff (p, t, 20); % 创建一个BP神经网络 ff=FeedForward


net = 

train (net, p, t); % 用p,t数据来训练这个网络




出现如下的信息,根据蓝线的显示,可以看出最后收敛时,误差已小于10^-20。


matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_02




你也许会问,计算机难道这样就能学会乘法规则吗?不用背乘法口诀表了?先随便选几个数字,试试看:




s = [3 7; 6 9; 4 5; 5 7]'; % 准备一组新的数据用于测试


y = 

sim (net, s) % 模拟一下,看看效果


% 结果是:25.1029 61.5882 29.5848 37.5879




看到了吧,预测结果和实际结果还是有差距的。不过从中也能看出,预测的数据不是瞎蒙的,至少还是有那么一点靠谱。如果训练集中的数据再多一些的话,预测的准确率还会大幅度提高。


matlabpython神经网络 matlab神经网络怎么用_数据_03



你测试的结果也许和我的不同,这是因为初始化的权重参数是随机的,可能会陷入局部最优解,所以有时预测的结果会很不理想。

例2:下面测试一下拟合正弦曲线,这次我们随机生成一些点来做样本。



p = rand(1,50)*7 % 生成1行50个0~7之间的随机数

t = sin(p) % 计算正弦曲线

s = [0:0.1:7]; % 生成0~7的一组数据,间隔0.1,用于模拟测试

plot(p, t, 'x') % 画散点图

matlabpython神经网络 matlab神经网络怎么用_数据_04




net = newff(p, t, 20); % 创建神经网络

net = train(net, p, t); % 开始训练



y = sim(net, s); % 模拟

plot(s, y, 'x') % 画散点图



从图中看出,这次的预测结果显然是不理想的,我们需要设置一些参数来调整。

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_05


下面的设置是一种标准的批量梯度下降法的配置。



% 创建3层神经网络 [隐藏层10个节点->logsig, 输出层1个节点->purelin] traingd代表梯度下降法

net = newff(p, t, 10, {'logsig' 'purelin'}, 'traingd'); % 10不能写成[10 1]



% 设置训练参数

net.trainparam.show = 50; % 显示训练结果(训练50次显示一次)

net.trainparam.epochs = 500; % 总训练次数

net.trainparam.goal = 0.01; % 训练目标:误差<0.01

net.trainParam.lr = 0.01; % 学习率(learning rate)



net = train(net, p, t); % 开始训练



注意:newff的第三个参数10不能写成[10 1],否则就是4层网络,两个隐藏层,分别是10个和1个节点。这个很容易弄错。(输出层的节点数程序会自动根据t的维度自动判断,所以不用指定)

matlabpython神经网络 matlab神经网络怎么用_数据_06




y = sim(net, s); % 模拟

plot(s, y, 'x') % 画散点图



这时的效果显然更差了。

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_07





把精度调高一点看看。训练次数加到9999,误差<0.001;学习率调到0.06,希望能加快点速度。



% 创建2层神经网络 [隐藏层10个节点->logsig, 输出层1个节点->purelin] traingd代表梯度下降法

net = newff(p, t, 10, {'logsig' 'purelin'}, 'traingd');



% 设置训练参数

net.trainparam.show = 50; % 每间隔50次显示一次训练结果

net.trainparam.epochs = 9999; % 总训练次数

net.trainparam.goal = 0.001; % 训练目标:误差<0.001

net.trainParam.lr = 0.06; % 学习率(learning rate)



net = train(net, p, t); % 开始训练



标准的批量梯度下降法的速度确实够慢,这次计算花了一分多钟。

matlabpython神经网络 matlab神经网络怎么用_神经网络_08





y = sim(net, s); % 模拟

plot(s, y, 'x') % 画散点图



效果比上次稍好一点。不过这条曲线显得坑坑洼洼的很难看,这是一种过拟合(Overfitting)现象,与之相反的是欠拟合(Underfitting)。

matlabpython神经网络 matlab神经网络怎么用_数据_09

先来解决速度问题,把traingd改为trainlm即可。trainlm使用LM算法,是介于牛顿法和梯度下降法之间的一种非线性优化方法,不但会加快训练速度,还会减小陷入局部最小值的可能性,是Matlab的默认值。




net = newff(p, t, 10, {'logsig' 'purelin'}, 'trainlm');

... 后面的代码不变

matlabpython神经网络 matlab神经网络怎么用_神经网络_10



这个速度比较惊叹了,1秒钟之内完成,只做了6轮计算,效果也好了一些。不过,LM算法也有弱点,它占用的内存非常大,所以没把其它算法给淘汰掉。

matlabpython神经网络 matlab神经网络怎么用_归一化_11

 



下面解决过拟合问题,把隐藏层的节点数目设少一点就行了。



net = newff(p, t, 3, {'logsig' 'purelin'}, 'trainlm');

... 后面的代码不变



这回终于达到满意的效果了。(有时会出现局部最优解,可以多试几次)

matlabpython神经网络 matlab神经网络怎么用_归一化_12

如果节点数目太少,会出现欠拟合的情况。

matlabpython神经网络 matlab神经网络怎么用_神经网络_13





关于隐藏层的节点个数,一般是要凭感觉去调的。如果训练集的维数比较多,调节起来比较耗时间,这时可以根据经验公式上下浮动地去调整。

下面给出几个经验公式供参考:

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_14

如果把输出层改为logsig激活会是什么样子呢?



net = newff(p, t, 3, {'logsig' 'logsig'}); % 创建神经网络

net = train(net, p, t); % 开始训练

y = sim(net, s); % 模拟

plot(s, y, 'x') % 画散点图


可以看出,-1~0范围之间的点都变为0了。使用logsig输出时要想得到完整数值范围的效果,必须先对数据进行归一化才行。




matlabpython神经网络 matlab神经网络怎么用_数据_15

 



归一化(Normalization),也叫标准化,就是把一堆数字按比例缩放到0~1或-1~1的范围。

虽然用Purelin输出可以不必归一化,但归一化能在一定程度上加快收敛速度,因此被许多教程定为训练前的必须步骤。



公式为:归一值 = (当前值x-最小值min)/(最大值max-最小值min)

如果限定了范围,公式为:y = (ymax-ymin)*(x-xmin)/(xmax-xmin) + ymin;

0.1~0.9的范围:(0.9-0.1)*(x-min)/(max-min)*(0.9-0.1)+0.1

把5, 2, 6, 3这四个数归一化:

matlabpython神经网络 matlab神经网络怎么用_数据_16

 



Matlab的归一化命令为:mapminmax

注:网上的不少教程里用premnmx命令来归一化,要注意Matlab版本R2007b和R2008b,premnmx在处理单列数据时有bug,Matlab已给出了警告,R2009a版才修正。因此推荐使用mapminmax。mapminmax的输入输出值和premnmx是行列颠倒的,使用时要注意代码中是否添加转置符号。



a = [5, 2, 6, 3];



b = mapminmax(a, 0, 1) % 归一化到0~1之间

% b = 0.7500 0 1.0000 0.2500



c = mapminmax(a) % 归一化到-1~1之间

% c = 0.5000 -1.0000 1.0000 -0.5000


反归一化(Denormalization)就是按归一化时的比例还原数值。



a = [5, 2, 6, 3];

[c,PS] = mapminmax(a); % PS记录归一化时的比例

mapminmax('reverse', c, PS) % 利用PS反归一化

% ans = 5 2 6 3


神经网络的归一化(0~1范围)代码:



p = rand(1,50)*7; % 特征数据

t = sin(p); % 样本值

s = [0:0.1:7]; % 测试数据



[pn, ps] = mapminmax(p, 0, 1); % 特征数据归一化

[tn, ts] = mapminmax(t, 0, 1); % 样本值归一化

sn = mapminmax('apply', s, ps); % 测试数据,按ps比例缩放



net = newff(pn, tn, [5 1], {'logsig' 'logsig'}); % 创建神经网络

net = train(net, pn, tn); % 开始训练



yn = sim(net, sn); % 模拟

y = mapminmax('reverse', yn, ts); % 按ps的比例还原

plot(s, y, 'x') % 画散点图


matlabpython神经网络 matlab神经网络怎么用_神经网络_17


神经网络工具箱还有一个UI图形操作界面,执行nntool就可以打开。我觉得不如写代码方便,所以不怎么用。我提供一个相关的教程链接,有兴趣的可以看一下:matlab神经网络工具箱创建神经网络 - http://blog.新浪.com.cn/s/blog_8684880b0100vxtv.html (新浪替换成sina)

matlabpython神经网络 matlab神经网络怎么用_数据_18

关于Sigmoid的由来,中文的网站上很少有提及的。下面简单讲一下,希望能给大家拓展一下思路。


PS: 这里的公式我都给出了求解过程,但如今这个年头,用手工解题的人越来越少了,一般的方程用软件来解就行了。
例如解Sigmoid微分方程,可以用Matlab去解:



dsolve('Dx=x*(1-x)')
% ans = 1/(1+exp(-t)*C1) 



如果想得到求解的步骤或更详细的信息,推荐使用Wolfram:http://www.wolframalpha.com在Wolfram的搜索框输入 x'=x(1-x) 即可。

logsig



Sigmoid函数(S形函数,Logistic Function)是受统计学模型的启发而产生的激活函数。

基于生物学的神经元激活函数是这样的:

matlabpython神经网络 matlab神经网络怎么用_数据_19


matlabpython神经网络 matlab神经网络怎么用_数据_20





参看:http://eprints.pascal-network.org/archive/00008596/01/glorot11a.pdf


实践证明了基于统计学的Sigmoid函数激活效果要比基于生物学的模型好,而且计算起来很方便,所以说不能以机器和人的相似度为标准来判断AI算法的好坏。

Sigmoid函数原先是个描述人口增长的数学模型,1838提出,给出的是导数形式(概率密度)。人口增长规律:起初阶段大致是指数增长;然后逐渐开始变得饱和,增长变慢;达到成熟时几乎停止增长;整个过程形如一条S型曲线。

matlabpython神经网络 matlab神经网络怎么用_神经网络_21

导数的形式知道了,那么它的原函数是什么样子呢?已知导数求原函数,用统计学的话来讲,即根据概率密度函数(PDF)求累积分布函数(CDF),不定积分(Indefinite Integral)就是专门用来做这个的工具。

根据不定积分的知识可知,由于常数项是可变的,所以存在无数个原函数的可能。让我们先用图解法看一下:既然导数是函数曲线的斜率,那么可以把一定数值范围内的斜率,都画成一根根的短斜线,组成斜率场(Slope Fields, Direction Fields),然后根据这些斜线的走势,画出积分曲线。

Matlab可以用quiver命令来画斜率场。

matlabpython神经网络 matlab神经网络怎么用_神经网络_22




从上图中可以看出,在y轴的0~1之间是个分水岭,0和1处的方向趋于水平。下面放大0~1的范围看看是什么样子的。


看到了吧,我们要的Logistic Sigmoid就在这里呢。

matlabpython神经网络 matlab神经网络怎么用_神经网络_23



下面给出符号求解的过程:

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_24

tansig



双曲正切函数(双极S形函数, tanh, Hyperbolic Tangent),读tanch,18世纪就已经出现了。它的定义是:tanh(x)=sinh(x)/cosh(x),可以由著名的欧拉公式(Euler's formula)推导出来。

用tanh作激活函数,收敛比较快,效果比Logistic函数还要好。

欧拉公式:

matlabpython神经网络 matlab神经网络怎么用_归一化_25

 i是虚数(Imaginary Number)单位,它的定义是:

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_26

 (即i^2 = -1)

题外话:根据上面的公式变换,可以得出史上最美的数学公式:

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_27

 ,数学中最神秘的5个符号e、i、π、1和0,全包含在里面了。



matlabpython神经网络 matlab神经网络怎么用_归一化_28


matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_29





求tanh的导数:

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_30





logsig和tansig的关系:

matlabpython神经网络 matlab神经网络怎么用_matlabpython神经网络_31