感知机(matlab实现)

        抓住时间的尾巴,在我还有时间学一点其他东西的时候,尽量做点笔记吧,证明我来过。https://res.wx.qq.com/mpres/htmledition/images/icon/common/emotion_panel/smiley/smiley_22.png

        今天的东西原理很简单,但是要实现起来还是有点小麻烦的,有很多坑,一不小心就会掉下去。通过理解感知机,我们对神经网络也会有更加深刻的认识。因为这就是神经网络的基础。

        先来看看感知机长什么样子:

 

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW011PccKLVMfIGiasI6t3LSGspj2rFDyibhLRwpscR90Ns5bBbNfibckDqg/640?wx_fmt=jpeg

 

        如图所示,它就是一个最最简单的神经网络(虽然只有一个神经元)。我们现在用它来实现逻辑,也就是说当输入为(11)时输出为1,当输入中有0时,输出0 。当然也可以实现逻辑,但是这是重复工作。(注意并非任何逻辑关系都能实现,比如或非,其原因是在直角坐标其中不能将其结果用一条直线分开。)

        来看看它是怎么实现这个逻辑的。

        首先,总共有2个输入x1x0,所以权重也有两个w0,w1,还有阈值θ,后面三者是待确定的。但是通常情况下,将θ视为w3,所以输入就有三个(xiwi为一一对应关系),只是第三个输入恒为-1。最后的结点表达式为:

 

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW0PItK1N50Q3NPdK3PPjuKK7HhMLeqwYMKLVhU5dCia2RzLxwfNA9XO3Q/640?wx_fmt=jpeg

        现在我们的工作是把t带入激活函数中,来判断f(t)。我们选用的激活函数及其图像为:

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW0XZwTlVV9xbm6e28BdNAZdLaZ7AuXA3xLkV2LibhClic1N5qxVS0UdTkw/640?wx_fmt=jpeg

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW0icwLFyfgoQQDckFqFb9lYicmnswRibFjQQiadgvbFZib5xpiafKemDCIDPzw/640?wx_fmt=jpeg

 

        (大家喜欢把它叫做sigmoid函数。)回到上一步,我们现在需要判断的是f(t)是否大于0.5,若 f(t)>=0.5 就把结果视为1,反之视为0

    【注】这种做法仅仅是在设计逻辑函数时的做法。

        那么其判断原理我们现在就弄清楚了,现在来看看怎么训练数据。

        首先需要确定待确定的变量为w1,w2,w3简称wi。在这里,我们希望根据带入wixi后算出的f(t)和数据集中原来的值y(实际值)来作比较,根据其误差大小来改变wi因此,引入公式:

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW0PhnQ5f6UfQZ3HTOo4qs1SRiaH9iahy9mibaF0nTfl7cbyhJNDIJD8QJQQ/640?wx_fmt=jpeg

        其中β称为学习率,在(01)之间。现在可以改变wi了,也就是说可以根据数据集来训练wi了。

        但是别高兴太早,还有很多坑。根据我的经验,总结了有几点:

        1、我们的数据集格式为【110.9】或【100.4】或【010.3】或【11076……你懂我意思吧。

        2、数据集尽量分散,也就是不要【11】一群【10】一群,这样训练来的wi极为不准确(亲测)。

        3、最后输出的时候我们要做一下处理,也就是大于0.5时,我们要让他输出1,小于0.5时,我们要让他输出0 。当然这只是在最后验证结果的时候,

在训练的时候还是要带值的。

下面是我的实现过程:

        我造的数据为160×3的数据集,其中【11】、【10】、【01】、【00】分别占40个。下面是一次训练的结果。

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW0SzK3QQwicZ6nGzKbZQbgfAtPH1EicOIznhxiakodZwscfA90JbaBcb8JQ/640?wx_fmt=jpeg

    可以看到,验证结果全对!!为了验证这种训练的准确度,我又设计了对程序加了一个循环,让它运行1000次!!!其中,分类正确的有919次,也就是说正确率达到了91.9%。要是我的训练集再特殊一点,算法再设计得好一些的话,正确率还会增加。(顺便说下,运行1000次大约花25秒,比较耗时。)

 

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW0cCgkvfXkEUV0iamNdwbXZtQAb4KWuVhz33saZsF3fCJhOoicnnORhibTA/640?wx_fmt=jpeg

https://mmbiz.qpic.cn/mmbiz_jpg/89ddjNLOqwfZKzLHnK9NXkq7vaCYdkW0icAtWIsnncuzhRYSpwlyVSunLRwRyB9QQSgSpFA3czzWKnclzy7SBiag/640?wx_fmt=jpeg

 

 

附件一(单次训练):

f = inline('1/(1+exp(-x))','x');  %sigmoid函数表达式

theta = 0.5;   %学习率

shuju = ones(160,3);%下面几句有关shuju的都是在生成数据集

shuju(41:80,2) = 0;

shuju(81:120,1) = 0;

shuju(121:160,1:2) = 0;

shuju(1:40,3) = rand(40,1)*0.5+0.5;

shuju(41:end,3) = rand(120,1)*0.5;

randindex = randperm(size(shuju,1));%这两句是打乱数据集的顺序

shuju=shuju(randindex,:)

 

y=shuju(1:end,3);%构造xi

x = shuju;

x(1:end,3) = -1;

w = rand(3,1);%生成初始wi

for i=1:160  %训练

    t = x(i,:)*w; 

    loss = theta*(y(i)-f(t));

    for j =1:3

        w(j) = w(j)+x(i,j)*loss

    end

    

end

disp('验证') %下面全是验证

disp('带入x=[1,1]')

x1=[1,1,-1];

t = x1*w;

if f(t)>=0.5

    disp('1')

else

    disp('0')

end

 

disp('带入x=[0,1]')

x1=[0,1,-1];

t = x1*w;

if f(t)>=0.5

    disp('1')

else

    disp('0')

end

disp('带入x=[0,0]')

x1=[0,0,-1];

t = x1*w;

if f(t)>=0.5

    disp('1')

else

    disp('0')

end

 

disp('带入x=[0,1]')

x1=[0,1,-1];

t = x1*w;

if f(t)>=0.5

    disp('1')

else

    disp('0')

end

 

 

 

附件二(运行1000次):

f = inline('1/(1+exp(-x))','x');  %sigmoid函数表达式

sum = 0;

for k=1:1000

theta = 0.5;   %学习率

shuju = ones(160,3);%下面几句有关shuju的都是在生成数据集

shuju(41:80,2) = 0;

shuju(81:120,1) = 0;

shuju(121:160,1:2) = 0;

shuju(1:40,3) = rand(40,1)*0.5+0.5;

shuju(41:end,3) = rand(120,1)*0.5;

randindex = randperm(size(shuju,1));%这两句是打乱数据集的顺序

shuju=shuju(randindex,:);

 

y=shuju(1:end,3);%构造xi

x = shuju;

x(1:end,3) = -1;

w = rand(3,1);%生成初始wi

for i=1:160  %训练

    t = x(i,:)*w; 

    loss = theta*(y(i)-f(t));

    for j =1:3

        w(j) = w(j)+x(i,j)*loss;

    end

    

end

a = 0;%标记

 

x1=[1,1,-1];

t = x1*w;

if f(t)>=0.5

    a=a+1;

end

 

 

x1=[0,1,-1];

t = x1*w;

if f(t)<0.5

    a=a+1;

end

 

x1=[0,0,-1];

t = x1*w;

if f(t)<0.5

    a=a+1;

end

 

 

x1=[0,1,-1];

t = x1*w;

if f(t)<0.5

    a=a+1;

end

 

if a==4

    sum=sum+1;

end

 

sum

end

 

disp('1000次中正确的次数')

sum

disp('正确率为:')

sum/1000

 

 

 

 

 

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值