早期的感知机
Summary
在这里总结了一下早期的感知机的工作机制,并用数学的方式写出它的算法,最后用python来实现这种感知机。虽然其中的算法很粗糙,但是这种算法在本质上和最陡梯度下降(gradient descent)和随机梯度下降法(stochastic gradient descent)是一样的。我自己很喜欢这种朴素但只管的思想,所以才在这里总结了一下。而不是把GD或SGD等方法的数学推导放在这里。还是觉得思想是最重要的。
问题的提出
不同的植物有不同形状的花朵,如Fig 0所示,花的形状可以用两个参数来度量,一是长轴,一是短轴。现在我们要问的是,假设一人给我们一朵花的长轴和短轴的数据,我们是否可以判断这朵花属于哪一类?

早期的感知机
早期的感知机希望了解人脑的工作机制。人的神经元接收到信号,然后就输出一个信号。比如,我们看到一个人,我们的大脑会抽取到各种特征,然后做出判断说,这是一个人。因此,神经元的工作机制,或者说学习机制,是通过对特征的加工,然后得到一个结论。在上边的例子中,花有四个特征,分别是:花瓣(petal)的长轴和短轴,花萼(sepal)的长轴和短轴。那么怎样对这四个特征进行加工,以使得我们可以判断这朵花是属于哪一种类型呢?
早期的感知机对特征的加工方式分为两步。第一步:给定特征x1,x2,x3,,,,,,我们分别给这些特征一个系数w1,w2,w3......,得到input=w1*x1+w2*x2+............。第二步:将input传给一个映射或函数f,得到output=f(input)。在这里,函数f必须事先给定,w1,w2,w3....是需要我们在学习过程中不断优化的参数。
数学形式
我们用向量(矩阵)的形式来描述特征,系数等等。
特征和系数分别写成向量的形式:

由此可以得到输入信号是:

有了input,我们需要将这个input喂给我们的神经元f,神经元然后吐出一个output。那么早期神经元f的形式是什么呢?下图就是早期用的f,非常简单,当输入大于某个值后,神经元吐出1,否则吐出-1. 这和人的大脑很相似,因为人的电脑并不是一接收信号就发出响应,而是当接收到的信号强度达到一定值后,神经元才会被激活。

让神经元学习吧
假设我们拿到一组特征x=(x1,x2,x3.....),并且已经知道它属于-1(在这里,我们必须将类别进行数字化,比如蔷薇花对应1,牡丹花对应-1,因为只有这样数字化以后,我们才可以更容易用数学的形式来表示现实世界)。在这里,我们让神经元在input>=0的时候吐出1,否则吐出-1(你可以设置成其它值,比如当Input>1的时候,神经元吐出1,等等)。那么我们应该改动我们的参数向量w呢?以使得我们的神经元吐出正确的值?
在上一节中,我们知道,第i个特征对应的系数是wi,那我们应该怎样改进wi呢?方法如下:

这个公式稍稍有些复杂,而且也没有告诉我们它是怎么来的。不用担心,暂时不要问这个公式是怎么来的,权当这个公式是我们瞎猜出来的。让我们从直观上来理解一下这个公式。假设我们的神经元吐出的值和实际值一样,那么这个时候就不需要改动我们的参数。从公式中我们可以看到,

也就是说,我们的方法是正确的,不用去改进我们的参数。
如果预测错了呢?假设实际值是1,但是神经元f吐出了-1,这个时候我们该怎么办呢?还记得我们的神经元f吧?当input>=0的时候,我们的神经元吐出1,这个时候神经元吐出了-1,说明我们的神经元的input<0,所以这个时候需要增加我们的input的值。现在反观Fig 4给的公式,我们可以得到系数改变后,input中第i个特征的值变成了:

在我们的例子中,

于是Fig 6变成了:

由此看到,这是个非负数,所以我们的input是增加的。这是个正确的改动w参数的方式。也说明Fig 4中给出的改动w的方案是可行的。
编程实现
Fig 9.中的代码是在Jupyter中实现的。定义了三个函数,fit,net_input和predict. 在这里最重要的是fit函数,因为在这个函数里实现了参数的参数的改进。

实例
现在我们利用 鸢尾花卉数据集 (Iris dataset)来做一个训练。
下边的命令用来从数据库中读取数据:
import pandas as pd
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)
然后我们用df.head()来查看数据的格式:

比如第一行的数据是:5.1 3.5 1.4 0.2 Iris-setosa,表示某花片长是5.1cm,宽是3.5cm,花萼长是:1.4cm,宽是0.2cm,该花名是:Iris-setosa.
然后我们取该数据库的前100个数据,前50个数据属于Iris-setosa,后50个数据属于 Iris-versicolor. 首先,我们需要将最后一列数据变成数字,在这里我们将Iris-setosa设置为-1,吧Iris-versicolor设置为1.用如下的命令:
y=df.iloc[0:100,4].values. #这个命令取得前100个数据的第4个特征,也就是花的种类。
y=np.where(y=='Iris-setosa',-1,1) #where语句是一个if then的判断语句,如果y=='Iris-setosa',则值为-1,否则为1.
然后是选取特征:X=df.iloc[0:100,[0,2]].values #这个命令选取前100个数据点的第0,1个特征,也就是花片的长度和宽度。在这里我们不用花萼的数据。
用下边的命令来观察一下我们的数据的分布状况。

得到的输出如下:

数据准备好了,下一步就是训练,模型的训练的命令:ppn = Perceptron(eta=0.1, n_iter=10) ppn.fit(X,y). 对,就是这两个命令. 然后我们来看一下收敛的情况.

从图中可以看到在进行到第6轮iteration的时候,我们的分类器就可以预测准全部的数据点。
最后,我们来看一下decision boundaries,命令如下:

这段代码先是生成一系列的格点,然后预测每个格点所属的类,最终我们得到如下的图:
