AI嵌入式系统:算法优化与实现
上QQ阅读APP看书,第一时间看更新

3.2 感知器

3.2.1 原理概述

感知器可以看作极简的线性前馈型神经网络,它通过对输入数据x(列向量)的线性运算实现物体分类。具体来说,感知器计算输入向量x各个元素的加权和,并和给定门限比较来确定x对应的数据类别。对于二分类器,通过下面的公式计算函数f(x),并根据f(x)的值大于0或者小于0来决定x的类别:

其中w是加权重系数构成的(列)向量,b是给定门限。符号<*,*>代表两个向量的内积,即

比如我们用机器根据重量和体积区分西瓜和苹果这两类水果,把输入写成向量,其中分别代表重量和体积数值。用坐标系下的点表示向量x,如图3-1所示。

可以看到对于西瓜,其重量和体积数值较大,对应的点在右上角,而对于苹果,根据其重量和体积,对应的点大多落在图的左下角,于是可以用图3-2中所示的直线将其分离。

图3-1 西瓜和苹果两类水果特征数据在特征空间的位置示意图

图3-2 通过分类边界线分割特征平面,西瓜和苹果两类水果特征数据在分类边界两侧

假设图中直线对应的方程是

分类器就是相对应的方程

对照式(3-5)得到,b=-10。对于某种水果的重量和体积数据,我们计算,如果它大于0则分类为西瓜,小于0则分类为苹果。分类器的设计其实就是寻找合适的分界线,使得不同类型的数据对应的特征分别在直线的两侧。

前面给出的算法用于二分类器设计,当需要分类数据有多个类别时,使用“一对所有”(One-Versus-All,OVA)的方法设计分类器。下面通过一个例子说明它的分类原理。

假设需要分类的数据有3种类别,分别记作,于是我们训练3个分类器,对其中的分类器,通过训练使得当数据的确属于类别A时,,对于其他类别的数据,。同样对于,我们希望当数据的确属于类别B时,,对于其他类别的数据;对,训练分类器使得当数据的确属于类别C时,,对于其他类别的数据。对于未知类别的输入数据,我们分别计算,根据这三个值中最大的那一个作为数据x的分类结果,比如时,将x分为类别B。

感知器执行的主要运算是向量乘法,即式(3-6)中的向量内积运算,向量内积进一步可以看成一系列乘加运算。在第6章将介绍对这一运算的优化。

3.2.2 模型训练和推理

下面给出基于Python的Scikit-Learn软件包库构建和训练线性感知器分类器,它使用和之前一样的鸢尾花分类数据。代码的总体结构和之前类似,如代码清单3-1所示。

代码清单3-1 感知器模型训练例程


from sklearn.model_selection import train_test_split
from sklearn.linear_model import Perceptron
from sklearn import datasets

# 加载数据集
iris = datasets.load_iris()

# 数据拆分为训练集和测试集
x_train, x_test, y_train, y_test = \
    train_test_split(iris.data, iris.target, 
                     test_size = 0.3,  # 数据划分比例,test数据占30%
                     random_state = 1, # 随机数"种子"
                     stratify = iris.target )# 划分数据中类别比例
# 构建感知机分类器
model =  Perceptron()

# 利用训练数据集训练分类器
model.fit(x_train, y_train)

上述代码中使用API train_test_split将原始训练数据分为两部分,x_train/y_train和x_test/y_test。其中x_train和x_test来自原始数据中的iris.data,即鸢尾花特征测量数据,而y_train和y_test是对应的鸢尾花分类的标准答案。上面的代码中Perceptron用于构建感知器分类器对象,而model.fit函数用于训练,得到感知器的参数。训练完成后通过下面的API调用计算数据分类:


y_pred = model.predict(x_test)

其中x_test是存放测试数据的矩阵,每一行对应一朵花的4个测量数据,y_pred是分类器分类结果,它的每个元素和x_test行对应。

如果需要提取训练结果中每个分类器的参数,即式(3-5)中的权重系数w和偏置b,可以分别从model.coef_和model.intercept_得到,代码如下,我们可以用这两个数据手动计算y_pred。


b=model.intercept_
W=model.coef_
f=x_test.dot(W.T)+b
y_pred=np.argmax(f,axis=1)