MATLAB实现BP算法对iris数据集进行分类

实验内容

用BP算法训练单隐层前馈神经网络,实现对lris数据分类;数据划分:训练和测试数据划分参考网站上论文中的划分。

  • 程序画出BP算法迭代过程中训练准确性曲线
  • 列表给出10次独立实验平均错误率和标准差要求
  • 讨论BP算法中学习系数的变化对训练错误率的影响,画出曲线
  • 在权值更新公式总加入动量项重复以上实验

实验数据集

本实验以Fisher的Iris数据集作为神经网络程序的测试数据集。Iris数据集能够在http:/larchive.ics.uci.edu/ml/datasets/Iris找到。这里简要介绍一下Iris数据集:

有一批Iris花,已知这批Iris花可分为3个品种,现须要对其进行分类。不同品种的Iris花的花萼长度、花萼宽度、花瓣长度、花瓣宽度会有差异。我们现有一批已知品种的Iris花的花萼长度、花萼宽度、花瓣长度、花瓣宽度的数据。

神经网络的实现

数据预处理

在训练神经网络前一般须要对数据进行预处理,一种重要的预处理手段是归一化处理。以下简要介绍归一化处理的原理与方法。

原理

  • 什么是归一化?

数据归一化,就是将数据映射到[0,1]或[-1,1]区间或更小的区间,比方(0.1,0.9) 。

  • 为什么要归一化处理?
  • 输入数据的单位不一样,有些数据的范围可能特别大,导致的结果是神经网络收敛慢、训练时间长。
  •  数据范围大的输入在模式分类中的作用可能会偏大,而数据范围小的输入作用就可能会偏小。
  • 因为神经网络输出层的激活函数的值域是有限制的,因此须要将网络训练的目标数据映射到激活函数的值域。比如神经网络的输出层若採用S形激活函数,因为S形函数的值域限制在(0,1),也就是说神经网络的输出仅仅能限制在(0,1),所以训练数据的输出就要归一化到[0,1]区间。
  •  S形激活函数在(0,1)区间以外区域非常平缓,区分度太小。比如S形函数f(X)在參数a=1时,f(100)与f(5)仅仅相差0.0067。
  • 归一化算法

一种简单而高速的归一化算法是线性转换算法。线性转换算法常见有两种形式:

y = ( x – min )/( max – min )

  当中min为x的最小值,max为x的最大值,输入向量为x,归一化后的输出向量为y 。上式将数据归一化到 [ 0 , 1 ]区间,当激活函数採用S形函数时(值域为(0,1))时这条式子适用。

y = 2 * ( x – min ) / ( max – min ) – 1

       这条公式将数据归一化到 [ -1 , 1 ] 区间。当激活函数採用双极S形函数(值域为(-1,1))时这条式子适用。

MATLAB数据归一化处理函数

Matlab中归一化处理数据能够採用premnmx , postmnmx , tramnmx 这3个函数。

  •  premnmx

语法:[pn,minp,maxp,tn,mint,maxt] = premnmx(p,t)

參数:

pn: p矩阵按行归一化后的矩阵

minp,maxp:p矩阵每一行的最小值,最大值

tn:t矩阵按行归一化后的矩阵

mint,maxt:t矩阵每一行的最小值,最大值

作用:将矩阵p,t归一化到[-1,1] ,主要用于归一化处理训练数据集。

  •  tramnmx

语法:[pn] = tramnmx(p,minp,maxp)

參数:

minp,maxp:premnmx函数计算的矩阵的最小,最大值

pn:归一化后的矩阵

作用:主要用于归一化处理待分类的输入数据。

  •  postmnmx

语法: [p,t] = postmnmx(pn,minp,maxp,tn,mint,maxt)

參数:

minp,maxp:premnmx函数计算的p矩阵每行的最小值,最大值

mint,maxt:premnmx函数计算的t矩阵每行的最小值,最大值

作用:将矩阵pn,tn映射回归一化处理前的范围。postmnmx函数主要用于将神经网络的输出结果映射回归一化前的数据范围。

使用Matlab实现神经网络

使用Matlab建立前馈神经网络主要会使用到以下3个函数:

  • newff :前馈网络创建函数
  • train:训练一个神经网络
  • sim :使用网络进行仿真

 以下简要介绍这3个函数的使用方法。

  • newff函数
    • newff函数语法

       newff函数參数列表有非常多的可选參数,详细能够參考Matlab的帮助文档,这里介绍newff函数的一种简单的形式。

语法:net = newff ( A, B, {C} ,‘trainFun’)

參数:

A:一个n×2的矩阵,第i行元素为输入信号xi的最小值和最大值;

B:一个k维行向量,其元素为网络中各层节点数;

C:一个k维字符串行向量,每一分量为相应层神经元的激活函数;

trainFun :为学习规则採用的训练算法。

  • 经常使用的激活函数

  经常使用的激活函数有:

  a) 线性函数 (Linear transfer function)

f(x) = x

  该函数的字符串为’purelin’。

b) 对数S形转移函数( Logarithmic sigmoid transfer function )

    该函数的字符串为’logsig’。

c) 双曲正切S形函数 (Hyperbolic tangent sigmoid transfer function )

  也就是上面所提到的双极S形函数。

  该函数的字符串为’ tansig’。

  Matlab的安装文件夹下的toolbox\nnet\nnet\nntransfer子文件夹中有全部激活函数的定义说明。

  • 常见的训练函数

    常见的训练函数有:

traingd :梯度下降BP训练函数(Gradient descent backpropagation)

traingdx :梯度下降自适应学习率训练函数

  • 网络配置參数

一些重要的网络配置參数例如以下:

net.trainparam.goal  :神经网络训练的目标误差

net.trainparam.show   : 显示中间结果的周期

net.trainparam.epochs  :最大迭代次数

net.trainParam.lr    : 学习率

  •  train函数

    网络训练学习函数。

语法:[ net, tr, Y1, E ]  = train( net, X, Y )

參数:

X:网络实际输入

Y:网络应有输出

tr:训练跟踪信息

Y1:网络实际输出

E:误差矩阵

  •  sim函数

语法:Y=sim(net,X)

參数:

net:网络

X:输入给网络的K×N矩阵,当中K为网络输入个数,N为数据样本数

Y:输出矩阵Q×N,当中Q为网络输出个数。

实验过程

将数据集加载到工作区

load iris.dat;

数据预处理

  • 将原始iris数据集随机抽取118行作为训练数据集。再在这118行之外抽取32行(即剩余的32行)作为测试数据集。然后分别保存在trainData1.txt和testData1.txt中。

A1=randsample(150,118,false) ;

trainData1=iris(A1,:);

A2=randsample(150,32,false) ;

testData1=iris(A2,:);

save(‘trainData1.txt’,‘trainData1’,’-ascii’),

save(‘testData1.txt’,‘testData1’,’-ascii’),

  • 将训练数据每行相同格式的数据按语法读取150次,然后得到每列。

f1 f2 f3 f4是四个特征值,class是类别。

[f1,f2,f3,f4,class] = textread(‘trainData1.txt’ , ‘%f%f%f%f%f’,150);

  • 特征值归一化

把输入的4个属性矩阵归一化到[-1,1],并保存到input矩阵中。

即下式为归一化公式:

[input,minI,maxI] = premnmx( [f1 , f2 , f3 , f4 ]’)

  • 构造输出矩阵

s = length( class) ; %得到类别矩阵长度:118

Output =zeros(s,3); %生成s行3列的全零阵:预先分配内存空间大小效率更高

for i = 1 : s

output( i , class( i ) ) = 1 ;

End

output矩阵即为输出矩阵

例第一个样本即第一行:0 1 0 则表示属于第二类,而第二个样本即第二行: 1 0 0 则表示它属于第一类。

而 0 0 1则表示属于第三类。

创建神经网络

net = newff(minmax(input),[10 3] , { ‘logsig’ ‘logsig’ } , ‘traingdx’ ); minmax(input):设定输入特征的范围—获取4个输入信号(存储在f1 f2 f3 f4中)的最大值和最小值;

{ ‘logsig’ ‘logsig’ }:隐层和输出层的传递函数–这里隐层和输出层传递函数都为logsig(S形传输函数)

‘traingdx’:表示学习规则采用的学习方法,即学习训练函数为traingdx(梯度下降)

设置训练参数

net.trainparam.show = 50 ;% 显示中间结果的周期

net.trainparam.epochs = 500 ;%最大迭代次数(学习次数)

net.trainparam.goal = 0.01;%神经网络训练的目标误差

net.trainParam.lr = 0.01 ;%学习速率

开始训练

将原先创建的神经网络以input为输入,output为目标函数的基础上训练epochs次即500次。

net = train( net, input , output’ ) ;

这里训练就结束了,以下开始测试。

开始测试

  • 读取测试数据

[t1, t2, t3, t4, c] = textread(‘testData1.txt’ , ‘%f%f%f%f%f’,150);

  • 测试数据归一化

[testInput,minI,maxI] = premnmx( [t1 , t2 , t3 , t4 ]’) ;

  • 仿真

Y = sim( net , testInput ) ; %其中net为训练后得到的网络

Y是最终得到的输出结果,在该样本中,哪一类的值更大,则将该样本分给哪一类。

比如说第一列:就是第一个样本:(2.9182e-05,0.322,0.9606)中0.9606更大,那么将第一个样本分到第三类;再举例说第32列,即第32个样本:(0.0028,0.9408,0.0628)中0.9408更大,那么将第32个样本分给第二类。

统计识别正确率

[s1,s2] = size(Y) ; %返回矩阵的行-s1,列-s2

hitNum = 0 ;

for i = 1 : s2

[m,Index]= max(Y(:,i)); % m返回的是Y矩阵第i列中最大的数(归为类)

if(Index ==c(i)) % index返回的是Y矩阵第i列中最大的数下标

hitNum =hitNum + 1 ;

end

end

sprintf(‘识别率是 %3.3f%%’,100 * hitNum / s2 )

最终命令窗口得到识别的正确率如上:基本稳定在100.000%

实验结果及分析

改变输出层的传递函数

  • 左图输出层为s型传递函数即logsig ,右图为线性传递函数即purelin
  • Performance:性能-用mse评估,进度条右边是设定的均方误差,即通过参数net.trainparam.goal设定。
  • Gradient:梯度-当梯度值达到了1.00e-05时,则停止训练
  • Validation check:泛化能力检查-若连续6次训练误差不降反升(误差不再减小,不会再有更好的效果了),则停止训练。
  • 训练集性能

从纵坐标就可以知道,它通过均方差开衡量网络的性能。由图可看到随着迭代次数的增大,均方误差越来越小,性能越好。

总结:改变输出层传递函数对训练周期、训练性能有一定影响,本例中左图迭代到206次收敛,均方误差0.0099642;而右图迭代到492次才收敛,均方误差0.091497,超过了目标误差0.0815328;所以输出层为s型传递函数要优于线性传递函数。

改变隐层的传递函数

  • 左图隐层为s型传递函数即logsig ,右图隐层为双曲正切S型传递函数即tansig
  • 训练集性能

总结:改变隐层传递函数对训练的性能、训练周期都有影响,本例中左图迭代到206次收敛,均方误差0.0099642;而右图迭代到500次收敛,均方误差0.015068;所以隐层传递函数使用双曲正切s型传递函数要比S型传递函数更好一些。

改变学习率

  • 左图学习率为0.01 ,右图为0.05
  • 训练集性能

总结:学习速率的选取大了可能导致系统不稳定,小了会导致训练周期过长、收敛慢,达不到要求的误差。一般通过观察误差下降曲线来判断。同时,由于网络规模大小的不同,学习率选择应当针对其进行调整。

总结

我在实验中通过调整隐含层节点数,选择不通过的激活函数,设定不同的学习率,

  1. 隐含层节点个数

  隐含层节点的个数对于识别率的影响并不大,可是节点个数过多会添加运算量,使得训练较慢。

  • 激活函数的选择

       激活函数不管对于识别率或收敛速度都有显著的影响。在逼近高次曲线时,S形函数精度比线性函数要高得多,但计算量也要大得多。

  • 学习率的选择

       学习率影响着网络收敛的速度,以及网络是否能收敛。学习率设置偏小能够保证网络收敛,可是收敛较慢。相反,学习率设置偏大则有可能使网络训练不收敛,影响识别效果。

源代码

%读取训练数据
clear
clc
load iris.dat;

%随机提取完数据并保存之后,要注释掉以下这6行代码
%因为每次训练都必须是同样的训练集和测试集,不能每训练一次随机提取一次。
%A1=randsample(150,118,false) ;
%trainData1=iris(A1,:);
%A2=randsample(150,32,false) ;
%testData1=iris(A2,:);
%save('trainData1.txt','trainData1','-ascii'),
%save('testData1.txt','testData1','-ascii'),

%f1 f2 f3 f4是四个特征值
[f1,f2,f3,f4,class] = textread('trainData1.txt' , '%f%f%f%f%f',150);
%特征值归一化
[input,minI,maxI] = premnmx( [f1 , f2 , f3 , f4 ]')  ;
%构造输出矩阵
s = length( class) ;
output = zeros( s , 3  ) ;
for i = 1 : s 
   output( i , class( i )  ) = 1 ;
end
%创建神经网络
net = newff( minmax(input) , [10 3] , { 'tansig' 'tansig' } , 'traingdx' ) ; 
%{
    minmax(input):获取4个输入信号(存储在f1 f2 f3 f4中)的最大值和最小值;
    [10,3]:表示使用2层网络,第一层网络节点数为10,第二层网络节点数为3;
    { 'logsig' 'purelin' }:
        表示每一层相应神经元的**函数;
        即:第一层神经元的**函数为logsig(对数S形转移函数),第二层为purelin(线性函数)
    'traingdx':表示学习规则采用的学习方法为traingdx(梯度下降自适应学习率训练函数)
%}
%设置训练參数
net.trainparam.show = 50 ;% 显示中间结果的周期
net.trainparam.epochs = 500 ;%最大迭代次数(学习次数)
net.trainparam.goal = 0.01;%神经网络训练的目标误差
net.trainParam.lr = 0.05 ;%学习速率(Learning rate)
%开始训练
%其中input为训练集的输入信号,对应output为训练集的输出结果
net = train( net, input , output' ) ;

%================================训练完成====================================%
%% 读取测试数据并归一化
%=============================接下来进行测试=================================%
%读取测试数据
[t1, t2, t3, t4, c] = textread('testData1.txt' , '%f%f%f%f%f',150);
%測试数据归一化
[testInput,minI,maxI] = premnmx( [t1 , t2 , t3 , t4 ]')  ;
%仿真
%其中net为训练后得到的网络,返回的Y为
Y = sim( net , testInput ) ;
%统计识别正确率
[s1 , s2] = size( Y ) ;
hitNum = 0 ;
for i = 1 : s2
    [m , Index] = max( Y( : ,  i ) ) ;
    if( Index  == c(i)   ) 
       hitNum = hitNum + 1 ; 
   end
end
sprintf('识别率是 %3.3f%%',100 * hitNum / s2 )

数据集

iris.data


文章标题:MATLAB实现BP算法对iris数据集进行分类
文章作者:世间难得逍遥
文章链接:https://www.abyss.website/classify/algorithm/bp/

许可协议: CC BY 4.0 转载请保留原文链接及作者。


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇