感知机(matlab实现)

        抓住时间的尾巴,在我还有时间学一点其他东西的时候,尽量做点笔记吧,证明我来过。感知机(matlab实现)

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

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

 

感知机(matlab实现)

 

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

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

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

 

感知机(matlab实现)

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

感知机(matlab实现)

感知机(matlab实现)

 

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

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

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

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

感知机(matlab实现)

        其中β称为学习率,在(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个。下面是一次训练的结果。

感知机(matlab实现)

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

 

感知机(matlab实现)

感知机(matlab实现)

 

 

附件一(单次训练):

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