上一篇文章中介绍了机器学习的简单知识,还有python中进行机器学习实践需要的生态环境,接下来将会通过鸢尾花分类这个例子对机器学习做一个简要的介绍。通过一步一步地实现这个项目来介绍以下内容。

  • 导入和使用python中机器学习的各个方面的类库。
  • 导入数据,并通过描述性分析、可视化等对数据进行分析。
  • 创建六个模型,并从中选择准确度最高的模型。

可以说这并不是一个正式的项目,只是用来做一个简单的展示,用于给初次接触机器学习的读者快速了解机器学习的过程和结果。

机器学习中的Hello World顶目

学习编程时,往往我们的第一句代码就是print(“Hello World”),而接下来的这个数据集,可以说得上是机器学习中的Hello World顶目,入门学习机器学习的过程中最常见的一个数据集。

这个项目是针对鸢尾花(Iris Flower)进行分类的一个项目,数据集是含鸢尾花的三个亚属的分类信息,通过机器学习算法生成一个模型,自动分类新数据到这三个亚属的某一个中。项目中使用的鸢尾花数据集是一个非常容易理解的数据集,这个数据集具有以下特点:

  • 所有的特征数据都是数字,不需要考虑如何导入和处理数据 。
  • 这是一个分类问题,可以很方便地通过有监督学习算法来解决问题。
  • 这是一个多分类问题,也许需要一些特殊的处理。
  • 所有的特征的数值采用相同的单位,不需要进行尺度的转换 。
  • 三个类属的数据完全一样,没有类别不平衡问题。
  • 有着较为明显的区分,机器学习分类效果较为明显。

接下来我们将通过这个例子一步步地来展示一个机器学习项目的简化步骤。我们将按照下面的步骤实现这个项目 :

(1)导入数据。

(2)概述数据。

(3)数据可视化。

(4)评估算法。

(5)实施预测。

在整个项目的过程中,最好尝试自己输入每一行代码,以加深对机器学习项目流程的理解。

2 导入数据

导入项目所需的各种数据处理、数据可视化以及机器学习相关库和鸢尾花(Iris Flower)数据集。

 

2.1 导入类库

 

导入在项目中将要使用的类库和方法 。 代码如下 :

# 导入类库 
from pandas import read_csv
from pandas.plotting import scatter_matrix
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
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.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC

所有类库的导入都不应有错误提示。如果出现了错误提示,那么暂时停下来,先设置一个能够运行的SciPy环境。

 

2.2 导入数据集

 

在本项目中我们使用的是 UCI 机器学习数据仓库中的鸢尾花(Iris Flower)数据集(http://archive.ics.uci.edu/rnl/datasets/Iris),不需要下载,可以通过sklearn模块中datasets导入数据直接使用。在这里将使用Pandas来导入数据和对数据进行描述性统计分析,并利用 Matplotlib实现数据可视化。需要注意的是,在导入数据时,为每个数据特征设定了名称,这有助于后面对数据的展示工作,尤其是通过图表展示数据。 代码如下:

## 导入数据 
import pandas as pd             # 导入pandas库
from sklearn import datasets    # 导入sklearn模块中的datasets,用以导入数据
iris = datasets.load_iris()     # 直接导入数据
dataset = pd.DataFrame(data=iris.data,columns=iris.feature_names)   # 用DataFrame存放数据

3 概述数据

 

在导入数据之后,我们需要先看一下数据,增加对数据的理解,以便选择合适的算法。我们将从以下几个角度来审查数据:

(1)数据的维度。

(2)查看数据自身 。

(3)统计描述所有的数据特征。

(4)数据分类的分布情况。

不要担心这会需要很多代码,每一种审查方法只有一行代码。这些代码非常有效,在以后的项目中也会用到。

 

3.1 数据维度

 

通过查看数据的维度,可以对数据集有一个大概的了解,如数据集中有多少行数据、数据有几个属性等。代码如下 :

#显示数据维度 
print('数据维度: 行 %s,列 %s' % dataset.shape) 

将会得到一个具有 150 行数据, 4 个数据特征属性的结果,执行结果如下:

数据维度: 
行 150,列 4 

3.2 查看数据自身

 

查看数据自身也是一个很好的理解数据的方法,通过查看数据可以直观地看到数据的特征、数据的类型,以及大概的数据分布范围等。代码如下:

# 查看数据的前10行 
print(dataset.head(10)) 

在这里查看前10行记录,执行结果如下:

sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 5.1 3.5 1.4 0.2 
1 4.9 3.0 1.4 0.2 
2 4.7 3.2 1.3 0.2 
3 4.6 3.1 1.5 0.2 
4 5.0 3.6 1.4 0.2 
5 5.4 3.9 1.7 0.4 
6 4.6 3.4 1.4 0.3 
7 5.0 3.4 1.5 0.2 
8 4.4 2.9 1.4 0.2 
9 4.9 3.1 1.5 0.1 

 

3.3 统计描述数据

 

数据特征的统计描述信息包括数据的行数、中位值、最大值、最小值、均值、四分位值等统计数据信息。我们需要通过这些统计的信息来大致了解数据的情况。配合箱线图能够很好了了解数据的分布和数值大小还有异常值情况等,代码如下:

# 统计描述数据信息 
print(dataset.describe()) 

 

执行结果如下:

sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) 
count 150.000000 150.000000 150.000000 150.000000 
mean 5.843333 3.057333 3.758000 1.199333 
std 0.828066 0.435866 1.765298 0.762238 
min 4.300000 2.000000 1.000000 0.100000 
25% 5.100000 2.800000 1.600000 0.300000 
50% 5.800000 3.000000 4.350000 1.300000 
75% 6.400000 3.300000 5.100000 1.800000 
max 7.900000 4.400000 6.900000 2.500000 

 

3.4 数据分类分布

 

接下来看一下数据在不同分类的分布情况,执行程序后得到的将是每个分类数据量的绝对的数值,看一下各个分类的数据分布是否均衡。代码如下:

# 分类分布情况
target = [x for x in iris.target] 
for item in set(target):  
    print("{} : {}".format(item,target.count(item))) 

这里就是通过前面设定的数据特征名称来查看数据的 。 执行结果如下:

0 : 50 
1 : 50 
2 : 50 

我们可以看到莺尾花的三个亚属的数据各 50 条,分布非常平衡。如果数据的分布不平衡时,可能会影响到模型的准确度。因此,当数据分布不平衡时,需要对数据进行处理,调整数据到相对平衡的状态。调整数据平衡时有以下几种方法。

  • 扩大数据样本: 定向增加类别较少的数据,使其与其他类别达到一定的比列,但数据是非常珍贵的,通常情况下我们建模使用的数据就已经是全部的数据了,也无法再增加数据了。
  • 数据的重新抽样:过抽样 (复制少数类样本)和欠抽样(删除多数类样本)。当数据量很大时可以考虑测试欠抽样,当数据量比较少时可以考虑过抽样。
  • 生成人工样本: 比如SMOTE方法,根据现有的数据,通过某些计算,生成更多的少类别的数据。
  • 异常检测和变化检测: 尝试用不同的观点进行思考,以解决问题。异常检测是对罕见事件的检测。这种思维的转变在于考虑以小类作为异常值类,它可以帮助获得一种新方法来分离和分类样本。

数据可视化

通过对数据集的审查,对数据有了一个基本的了解,接下来将通过图表来进一步查看数据特征的分布情况和数据不同特征之间的相互关系 。

  • 使用单变量图表可以更好地理解每一个特征属性。
  • 多变量图表用于理解不同特征属性之间的关系。 我们可以先看一下前面刚刚提到的分类分布情况,执行代码如下:
  • ## 画图显示 
    import matplotlib.pyplot as plt
    %matplotlib inline # 直方图
    plt.hist(target,[-0.5,0.5,1.5,2.5],rwidth=0.6)
    plt.show()

     

 

“C:\Users\CDA\Desktop\CDA\02 - SEO\01 - 原创\【算法应用】机器学习python应用-简单机器学习项目实践\图片\类别情况.png”

相对于数值而言,数据可视化后就非常直观,我们可以清晰地了解到数据中的标签类别个数以及每种类别间的大致比例情况。

 

4.1 单变量图表

 

单变量图表可以显示每一个单独的特征属性,因为每个特征属性都是数字,因此我们可以通过箱线图来展示属性与中位值的离散速度,了解数据偏向和异常值情况。 代码如下:

 

# 箱线图 
dataset.plot(kind='box', subplots=True, layout=(2,2), sharex=False, sharey=False) 
plt.show()

执行结果:

 

还可以通过直方图来显示每个特征属性的分布状况。 代码如下:

# 直方图 
dataset.hist() 
plt.show()

在输出的图表中,我们看到 separ- length 和 separ-width 这两个特征比较符合高斯分布。执行结果如图 3-2 所示 。

 

 

4.2 多变量图表

 

通过多变量图表可以查看不同特征属性之间的关系。我们通过散点矩阵图来查看每个属性之间的影响关系。

# 散点矩阵图 
import seaborn as sns                   # 导入画图库-seaborn 
plt.figure(figsize=(15.0, 10.0))
sns.pairplot(dataset, diag_kind = 'kde', 
             plot_kws = {'alpha': 0.6, 's': 80, 'edgecolor': 'k'},
             size =3)
# 保存图片
plt.savefig('scatter_matrix.jpg', dpi=100, bbox_inches='tight')

执行结果如下所示,对角线上的四副图是四个特征的分布情况,其意义和前面的直方图内容的意义是一致的,很明显看出 separ- length 和 separ-width 这两个特征是单峰的,比较符合高斯分布;而 petal length 和 petal width是双峰的。除了对角线外的其他图则是散点图的形式,它们表示的是不同特征间的相关性,从图中我们可以看出 petal length 和 petal width这两个特征间有着明显的线性相关性。如果是回归模型中,出现多重共线性的特征是需要进行处理的,但我们目前只是简单的展示一下分类机器学习的大致流程,所以就没必须做处理了。

 

5 数据处理

一般在机器学习的项目中,数据清洗、数据处理就占去了整个项目的80%的工作量,所以这是机器学习项目中非常重要的一个环节,但在本项目中,iris的数据已经是非常完善的,不需要再进行过多的数据处理过程。如此我们只需要简单处理一下原数据,使其更适合在某些有特殊要求的算法上使用。

 

5.1 数据标准化

 

不同的算法对数据也有不同的要求,比如KNN算法,因为一般是基于欧式距离进行计算,所以也要求数据必须要做标准化,否则建模过程中大小不一的特征的实际权重也会不同,数值较大的特征将会覆盖掉数值较小的特征。为了解决这中影响,我们可以将数据标准化,执行代码如下:

# 标准化处理
from sklearn import preprocessing
#建立StandardScaler对象 
std = preprocessing.StandardScaler()
data_std = std.fit_transform(dataset)

 

5.2 分离出评估数据集

 

模型被创建后需要知道创建的模型是否足够好。在选择算法的过程中会采用统计学方法来评估算法模型。但是,我们更想知道算法模型对真实数据的准确度如何,这就是保留一部分数据来评估算法模型的主要原因。下面将按照70%的训练数据集,30%的评估数据集来分离数据。代码如下:

# 分离数据集 
## 原数据 
X_train, X_validation, Y_train, Y_validation = train_test_split(dataset, target, test_size=0.3, random_state=12) 
## 标准化数据 
X_train_std, X_validation_std, Y_train, Y_validation = train_test_split(data_std, target, test_size=0.3, random_state=12) 

现在就分离出了 X_train 和 Y_train 或者标准化后的X_train_std和Y_train用来训练算法创建模型, x_validation(X_validation_std)和Y_validation 在后面会用来验证评估模型。

6 评估算法

通过不同的算法来创建模型,并评估它们的准确度,以便找到最合适的算法。将按照下面的步骤进行操作:

(1)采用 10 折交叉验证来评估算法模型 。

(2)生成几个常用的分类模型来预测新数据 。

(3)选择最优模型

 

6.1 评估模式

 

在这里将通过 10 折交叉验证来分离训练数据集,并评估算法模型的准确度。10 折交叉验证是随机地将数据分成 10 份,9 份用来训练模型,1 份用来评估算法。后面我们会使用相同的数据对每一种算法进行训练和评估 , 并从中选择最好的模型。

 

6.2 创建模型

 

对任何问题来说,不能仅通过对数据进行审查,就判断出哪个算法最有效。通过前面的图表,发现有些数据特征符合线性分布,所有可以期待算法会得到比较好的结果 。

接下来评估六种不同的算法:

  • 线性回归(LR)。
  • 神经网络(ANN)
  • K 近邻(KNN)。
  • 分类与回归树(CART)。
  • 贝叶斯分类器(NB)。
  • 支持向量机(SVM)。

这个算法列表中包含了线性算法(LR)和非线性算法(ANN、KNN 、CART、NB和SVM)。在每次对算法进行评估前都会重新设置随机数的种子,以确保每次对算法的评估都使用相同的数据集,保证算法评估的准确性。接下来就创建并评估这六种算法模型。代码如下:

# 算法审查
models = {}
models['LR'] = LogisticRegression()
models['ANN'] = MLPClassifier()
models['KNN'] = KNeighborsClassifier()
models['CART'] = DecisionTreeClassifier()
models['NB'] = GaussianNB()
models['SVM'] = SVC()

# 评估算法
results = [] for key in models:
kfold = KFold(n_splits=10, random_state=seed)
cv_results = cross_val_score(models[key], X_train, Y_train, cv=kfold, scoring='accuracy')
results.append(cv_results) 
print('原数据:%s: %f (%f)' %(key, cv_results.mean(), cv_results.std()))

results = [] for key in models:
kfold = KFold(n_splits=10, random_state=seed)
cv_results = cross_val_score(models[key], X_train_std, Y_train, cv=kfold, scoring='accuracy')
results.append(cv_results) 
print('标准化数据:%s: %f (%f)' %(key, cv_results.mean(), cv_results.std()))

6.3 选择最优模型

 

现在已经有了六种模型,并且评估了它们的精确度。接下来就需要比较这六种模型,并选出准确度最高的算法。执行上面的代码,结果如下 :

原数据:LR: 0.933636 (0.062463)
原数据:ANN: 0.972727 (0.041660)
原数据:KNN: 0.972727 (0.041660)
原数据:CART: 0.914545 (0.066953)
原数据:NB: 0.933636 (0.062463)
原数据:SVM: 0.963636 (0.060302)

标准化数据:LR: 0.887273 (0.069734)
标准化数据:ANN: 0.942727 (0.064801)
标准化数据:KNN: 0.942727 (0.046895)
标准化数据:CART: 0.914545 (0.066953)
标准化数据:NB: 0.933636 (0.062463)
标准化数据:SVM: 0.951818 (0.065813)

通过上面的结果,可以看出实际上用原数据进行建模的结果反而更好,说明这份数据不需要再更变动了。然后6种算法中神经网络和KNN算法的准确率最高,这种情况下怎么办,该如何确定哪个才是更好的。接下来创建一个箱线图,通过图表来比较算法的评估结果。 代码如下 :

# 箱线图比较算法 
fig = plt.figure() 
fig.suptitle('Algorithm Comparison') 
ax = fig.add_subplot(111) 
plt.boxplot(results) 
ax.set_xticklabels(models.keys()) 
plt.show() 

执行结果:

 

我们可以看出,虽然总体的平均准确率和标准差是一样的,但是ANN算法的中值相对KNN的更高,说明ANN算法的相对来说会更好一点。

7 实施预测

评估的结果显示,神经网络(ANN) 是准确度最高的算法。现在使用预留的评估数据集来验证这个算法模型。这将会对生成的算法模型的准确度有一个更加直观的认识。现在使用全部训练集的数据生成神经网络(ANN)的算法模型,并用预留的评估数据集给出一个算法模型的报告。 代码如下:

#使用评估数据集评估算法 
ann = MLPClassifier() 
ann.fit(X=X_train, y=Y_train) 
predictions = ann.predict(X_validation) 
print("准确率:",accuracy_score(Y_validation, predictions)) 
print(confusion_matrix(Y_validation, predictions)) 
print(classification_report(Y_validation, predictions)) 

 

执行程序后,看到算法模型的准确度是0.98。通过混淆矩阵看到只有一个数据预测错误。最后还提供了一个包含精确率(precision)、召回率(recall)、Fl 值(Fl-score)等数据的报告。结果如下:

准确率: 0.9777777777777777 
[[20 0 0] 
 [ 0 13 1] 
 [ 0 0 11]] 
precision recall f1-score support 
0 1.00 1.00 1.00 20 
1 1.00 0.93 0.96 14 
2 0.92 1.00 0.96 11 
accuracy 0.98 45 
macro avg 0.97 0.98 0.97 45 
weighted avg 0.98 0.98 0.98 45 

 

8 总结

 

到这里已经完成了第一个机器学习项目。这个项目包含从数据导入到生成模型,以及通过模型对数据进行分类的全部过程。通过这个项目我们熟悉了机器学习项目中的各个步骤。接下来将介绍在本文中用到的对数据进行处理分析的技巧和算法,以及改进算法的实践。

 

回复“资讯”,获取更多最新人工智能前沿动态!