我们首先从一个简单而经典的例子开始学习——鸢尾花的识别。很多机器学习算法都采用这个例子进行测试,而且从中可以看到多种编程语言的实现。在这里我们也将完成第一个解决机器学习问题的Python程序。
一个事物之所以被归结为哪个类别,关键在于它和其他的事物有所区别,这个区别就是事物的特征,比如,一个人的身高、体重可以在一定程度上反映出他的体型,加上骨密度、体脂率、水分含量、代谢情况,可以反映出他的健康程度。这些指标就是事物的特征。人工智能的一个重要任务就是能够根据事物的特征对它们进行分类。同样,在鸢尾花种类的识别问题中,也需要提取特征。
鸢尾花识别问题描述
鸢尾花(Iris tectorum Maxim)又名蓝蝴蝶、紫蝴蝶、扁竹花等,属百合目。下图分别是自然界中的鸢尾花以及梵高和莫奈笔下的鸢尾花。
鸢尾花
世界上的鸢尾花大约有300种,如何利用计算机对所发现的鸢尾花进行自动分类?下面我们先选择3种鸢尾花(山鸢尾、弗吉尼亚鸢尾、变色鸢尾)进行观察。
不同品种的鸢尾花
如果要对这些鸢尾花进行分类,首先观察以上3类鸢尾花的不同。我们可以发现,它们花萼和花瓣的形状有所不同,有的偏瘦长,有点偏短宽。因此,1936年英国的统计学家和生物学家费希尔测量了鸢尾花花萼和花瓣的长度和宽度,创建了一个包含这3类鸢尾花的数据集,目前这个数据集包含150组数据,每种鸢尾花各有50组数据,鸢尾花分类已成为机器学习分类问题的标准入门内容之一。表7-1给出了其中5组数据。
表7-1 5组鸢尾花数据
从表7-1中我们可以看到鸢尾花的属性是数值型数据,简单易懂,便于计算机处理,并且在一个数量级上。鸢尾花分类问题是一个多分类问题,并且在数据集中已知输出,因此可以采用监督学习算法。
模型与学习算法的一些讨论
当给定了许多已知品种的鸢尾花数据之后,我们能够利用这些数据做什么?小P有些疑问,并和同学们一起进行了探讨。
小P问一问
问题1:如果现在给我们一株新的鸢尾花,我们如何让机器(计算机)识别出这是哪个品种?
同学甲:我可以对比现有鸢尾花品种与这一株新的鸢尾花花萼和花瓣的数值,对比结果哪个接近就是该品种。
同学乙:同一品种的花也有一定差异,该和哪个进行比较呢?
同学丙:如果可以建立花萼和花瓣测量值与鸢尾花品种之间的关系,就像刮大风意味着体感温度降低,是不是机器就可以进行自动判断了?
问题2:如何建立花萼和花瓣测量值与鸢尾花品种之间的关系?
同学甲:可以用函数来表示。
同学乙:采用什么函数呢?
我们把花萼和花瓣测量值与鸢尾花品种之间的这种关系称为模型。本书不会深入探讨具体模型的原理,读者能够初步使用函数建立模型这个概念就可以了,这在后面的语音和图像识别中同样适用。
对于计算机模型,每个模型都可以看成一个函数y=f(x,w),当给定某一个x时,就会输出一个y,不同的x会得到不同的y,模型的关键就是建立合适的f以及参数w,使得对一个x,能够得到符合预期的y。
简化模型
在这个问题中,数据集既包含鸢尾花的特征,也包含鸢尾花的种类标签,此时就可以将足够多的具有代表性的样本数据送到模型中。
现在的问题是,如何进行参数的设计或者说参数的确定,这就是学习算法要解决的问题。这里先给出一种简单的调节方法,以帮助读者理解什么是学习算法。假定目前模型中只有一个参数w,输入为x,标签为t,在当前输入下,模型的输出为y,如果y和t不一样,存在一定误差,我们就开始调节w,如果此时增加w使得这个误差加大,则我们朝w减小的方向进行调节,直到这个误差达到我们可以接受的范围。这是一种典型的监督学习算法,也就是我们知道标准是什么,模型参数的调整朝着使误差减少的方向进行,就可以达到一定的效果。这种调节参数的方法类似于我们下山,每一步都朝着山坡下降的方向就可以从山顶下来,但也有可能中间会遇到需要上坡的时候,因此这类方法也有较大的局限性,但是它确实是一种非常简单且易于操作的方法。
小P说一说
模型是真实世界的一种模拟。
给定一个输入,得到与真实世界相似的结果,这个模型不错!
模型一开始是个小婴儿,需要学习。
拿来一块儿水果糖,你说“水果糖”,它说“糖糖”,你会不断纠正它,直到它说对为止,这就是监督学习。
在不断的训练之下,模型小M终于从小婴儿长大了,成了一名小学生。
小P和小M
小M:我的能力超强,输出结果正确率达到90%,我很棒!
小P:别急别急,我给你做个测试(在训练集之外找到10组数据)。
小M:没问题,让我来预测一下(秒算给出结果)。
小P:小M,正确率只有70%。
小M:???
小P:新给的数据和原数据相似但不同,你的举一反三能力(泛化能力)还不强啊!
小M:这可怎么办?我已经很努力了!
小P:方向不对,努力白费。我们在原有训练方法上加一个步骤,不同的模型和学习算法训练之后效果并不同,我们用一些新数据作检验,对训练数据和新数据预测能力都好的就留下来。
小M:好,让我再来试一试,见多识广,百炼成钢。
在模型训练过程中,往往还需要引入校验数据(与训练数据同分布,但不是相同的数据),用来选择更好的参数或者模型。这类似于我们平时的学习过程,通过书本和练习册的练习题训练我们可以掌握相应的知识点,而单元测验题目可以检测我们的学习效果。这两部分的题目一般源于相同的知识点,而它们的具体题目内容可能不同。
训练集和校验集的数据源于同一个数据集合,即它们是同属于一个范围的数据,比如在数字的手写体识别中,有多个数字0~9的不同手写体,训练集中一般会包含0~9,而校验集中也会包含或部分包含0~9。如果训练集的数据只包含0~5,训练效果可能不够好。
即使训练集都包含0~9,不同模型的训练效果也各不相同。这如同有的同学擅长做小数运算,有的擅长做分数运算,有的擅长做几何图形运算。每个模型的结构都不同,就如同每个人的大脑结构都不同,故所擅长的领域就各不相同。训练模型的过程就是让模型尽可能地对训练数据具有较好的拟合能力,然而仅评估训练效果是不够的,需要用新的数据进行检测,这就是校验集的作用。训练就是构建一种模式,对计算机模型来说,实际上就是构建一个复杂的函数,找到一组合适的参数,让输入(手写体数字的图像或其特征值)经过函数的运算之后可以得到正确的输出(手写体数字的类别)。
在训练集中已知事物类别的问题被称为分类问题,此时相当于标准答案已知,训练的目的就是让模型的输出尽可能地接近标准答案。而另一类问题是不知道类别的答案,就像在大街上看到很多人,我们并不知道他们应该属于哪一类,这时可以通过他们内在特征的相似性,例如身高、肤色、头发长短,给他们划分到不同类别,或者根据共同的爱好(如下棋、唱歌、运动等)进行划分,划分为运动达人、围棋爱好者等。这种对事物类别的确定称为聚类。
还有一些问题,它们的输出不是类别,而是一个连续值,比如某一地区的房屋价格、某一地区的未来温度预报。进行预测时,往往要找到影响这些输出的因素,例如地区的位置,周边学校、医院,交通,周围人群组成等。这类问题称为预测。
无论是分类还是预测问题,如果训练数据中已知输入和输出,就可以采用有导师(监督)学习算法,如果是聚类问题,则采用无监督学习算法,对于含有缺失数据的训练问题,可以采用半监督学习算法。
基于数据的模型的目的是找到数据输入与输出之间的联系,或者输入数据之间的联系,对于前者,由于输出已知,模型参数的调节(学习算法)可以采用监督学习算法,对于不知道输出的问题,则可以采用无监督学习算法。学习算法就是找到一种规则来调节参数,使得模型在给定输入的时候能够得到理想的输出结果。
在鸢尾花识别这个问题中,由于数据集中的标签已知,因此可以采用监督学习算法。
鸢尾花识别问题Python程序的流程和准备
1.解决问题的通用步骤
在用Python解决分类等机器学习问题时,有一些通用的步骤,包括:
① 定义问题;
② 准备数据;
③ 评价算法;
④ 改进结果;
⑤ 展示结果。
2.程序准备
在Python中,需要安装的模块包有Scipy、numpy、matplotlib、pandas和sklearn。可以在cmd窗口采用pip install完成。
3.鸢尾花识别问题Python编程的步骤
● 下载数据集。
● 对数据集进行统计分析。
● 可视化数据集。
● 评价算法。
● 做出预测。
鸢尾花识别问题的Python程序
这个程序大致分为准备阶段、数据导入阶段、数据分析和可视化阶段、建立模型阶段、训练模型阶段、选择模型阶段、预测阶段。该程序参考https://machinelearningmastery.com/machine-learning-in-python-step-by-step/。
下面我们分别进行说明。
1.准备与数据导入
-----------------------part 1准备工作-----------------------
#导入相应的库,包括相关数据统计库、画图库、机器学习库,如果没有安装,可以采用pip install 进行安装
import pandas
from pandas.plotting import scatter_matrix
import matplotlib.pyplot as plt
from sklearn import model_selection
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
pandas.set option('display.max_column',10)
----------------part 2下载数据或导入数据-------------------
url="https://archive.ics.uci.edu/ml/machinelearning-databases/iris/iris.data"
names=['sepal-length','sepal-width','petallength','petal-width','class']
dataset=pandas.read_csv(url,names=names)(www.xing528.com)
也可以下载之后再进行导入,从https://archive.ics.uci.edu/ml/machinelearning-databases/iris/iris.data处下载数据文件,存入硬盘,在导入数据时将url换成相应的磁盘路径即可。
以上完成了最基本的工作,下面将对数据进行分析和可视化。
2.数据分析和可视化
一般在获得数据之后,需要观察数据的分布情况,包括数据的维度、数据的范围、所有指标的统计情况、每种类别的数据量,这样可以建立全面的对数据的认识。
数据可视化
-----------------------part 3数据分析-----------------------
print(dataset.shape)#采用shape函数观察数据的维度
(150,5)表示这个数据集有150行、5列。
print(dataset.head(20))#采用head()函数获得前20行的数据
print(dataset.describe())#采用describe()函数对每项指标进行统计
下面我们看一看每一类包含的数据量,采用groupby()函数,参数是需要统计的属性,例如第五列(class)。
可以看出每一类别都包含了50组数据。
----------------------part 4数据可视化----------------------
#对于单变量,可以采用箱形图更好地展示数据的分布情况,例如最大值、最小值、中位数、异常值等
# box and whisker plots
dataset.plot(kind='box',subplots=True,layout=(2,2),sharex=False,sharey=False)
plt.show()
还可以使用柱状图(histograms)进行展示。
dataset.hist()
plt.show()
可以看出,sepal的长度和宽度符合一定的高斯分布。
也可以观察不同变量之间是否具有相关性。
scatter_matrix(dataset)
plt.show()
如果散点在一条直线附近,可以认为它们存在较强的相关性,例如下图中圆圈标注的位置。
3.建立模型、训练模型、选择模型与预测
人工智能的一个重要工作是建立模型,模型最基本的工作方式就是给定输入,能够得到正确的输出结果。建立模型的方法有很多,在人工智能领域,建立模型的方式是基于数据模型建立的,这也是机器学习的重要内容。基于数据的模型建立需要确定训练数据,选择模型的类型,通过学习算法确定模型的参数。同时,一般在建立或选择模型时还需要有一个校验集。
下面我们给出一个较为完整的建立模型的流程。
● 确定训练集和测试集。
● 用n-fold交叉验证来对模型的性能进行测试,这里选n为10,即10个子集,每个子集均做一次测试集,其余的作为训练集。交叉验证重复10次,每次都选择一个子集作为测试集,并将10次的平均交叉验证识别正确率作为结果。
● 建立m(这里m=5)个模型并进行预测。
● 选择最好的模型。
---------------------part 5数据集准备---------------------
#划分数据集,确定训练集和测试集
array=dataset.values
X=array[:,0:4]
Y=array[:,4]
test_size=0.20
seed=7
X_train,X_test,Y_train,Y_test=model_selection.train_test_split(X,Y,test_size=test_size,random_state=seed)#所有数据中的20%作为测试集
--------------------part 6建立模型并比较--------------------
#确定测试标准
seed=7
scoring='accuracy'#使用精确度作为评价标准
#这里测试6个模型的效果,最后选择效果最好的模型来进行预测,其中有两个线性模型(Logistic Regression,LR;Linear Discriminant Analysis,LDA)、4个非线性模型(K-Nearest Neighbors,K NN;Classification and Regression Trees,CART;Gaussian Naive Bayes,GNB;Support Vector Machines,SVM)
#将6个模型的名称存入models变量中
models=[]
models.append(('LR',LogisticRegression()))
models.append(('LDA',LinearDiscriminantAnalysis()))
models.append(('KNN',KNeighborsClassifier()))
models.append(('CART',DecisionTreeClassifier()))
models.append(('NB',GaussianNB()))
models.append(('SVM',SVC()))
#采用循环程序依次测试模型的性能,采用10-fold进行校验评分
results=[]
names=[]
for name,model in models:
kfold=model_selection.KFold(n_splits=10,random_state=seed)
cv_results=model_selection.cross_val_score(model,X_train,Y_train,cv=kfold,scoring=scoring)
results.append(cv_results)
names.append(name)
msg="%s:%f(%f)"%(name,cv_results.mean(),cv_results.std())
print(msg)
从结果可以看出,通过10次实验结果的评估,KNN的效果比较好。
#画图比较各种算法
fig=plt.figure()
fig.suptitle('Algorithm Comparison')
ax=fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.show()
-------------------part 7在测试集上做出预测-------------------
#在测试集上做出预测,采用knn模型
knn=KNeighborsClassifier()
knn.fit(X_train,Y_train)#训练knn
predictions=knn.predict(X_test)#输入X_test,得到输出
print(accuracy_score(Y_test,predictions))#精确度
print(confusion_matrix(Y_test,predictions))
print(classification_report(Y_test,predictions))
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。