ML-分类-1_鸢尾花分类

源码部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#------iris.py------
import sklearn.datasets as sk_datasets
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import mglearn
import matplotlib.pyplot as plt
plt.show()
iris_dataset = load_iris()
print("Keys of iris_dataset:\n{}".format(iris_dataset.keys()))
print("Target names:{}".format(iris_dataset['target_names']))
print("Feature names:\n{}".format(iris_dataset["feature_names"]))
print("data:\n{}".format(iris_dataset['data']))
print("target:{}".format(iris_dataset['target']))
print("frame:{}".format(iris_dataset["frame"]))
print("DESCR:{}".format(iris_dataset["DESCR"][:50] + "\n..."))
#dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])
iris = sk_datasets.load_iris()
iris_X = iris.data
iris_Y = iris.target



#from sklearn.datasets import load_iris
#print(load_iris().DESCR)

#from sklearn import preprocessing

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
iris_dataset['data'], iris_dataset['target'],random_state=0)
print("X_train shape:{}".format(X_train.shape))
print("Y_train shape:{}".format(y_train.shape))
print("X_test shape:{}".format(X_test.shape))
print("Y_test shape:{}".format(y_test.shape))

iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)
grr = pd.plotting.scatter_matrix(iris_dataframe, c=y_train, figsize=(15,15),marker='o',
hist_kwds={'bins': 20}, s=60, alpha=.8, cmap=mglearn.cm3)

#plt.show()

# KNN
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train,y_train)

X_new = np.array([[5,2.9,1,0.2]])
print("X_new.shape:{}".format(X_new.shape))

prediction = knn.predict(X_new)
print("prediction:{}".format(prediction))
print("Predicted target name;{}".format(iris_dataset['target_names'][prediction]))

y_pred = knn.predict(X_test)
print("Test set predictions: \n {}".format(y_pred))
int("Test set Score:{:.2f}".format(np.mean(y_pred == y_test)))
print("Test set Score:{:.2f}".format(knn.score(X_test,y_test)))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
------output------
Iris plants dataset
-----------
...
X_train shape:(112, 4)
Y_train shape:(112,)
X_test shape:(38, 4)
Y_test shape:(38,)
X_new.shape:(1, 4)
prediction:[0]
Predicted target name;['setosa']
Test set predictions:
[2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
2]
Test set Score:0.97
Test set Score:0.97

代码精解

1.初识数据集

数据集信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# iris 鸢尾花数据集, 是机器学习与统计学中一个经典的数据集
# 调用该数据集,需要从scikit-learn库中引入该模块
from sklearn.datasets import load_iris
iris_dataset = load_iris()

#load_iris()返回的iris对象是一个Bunch类,与字典非常相似,里面包含键与值:
print("Keys of iris_dataset:{}".format(iris_dataset.keys()))
#返回如下:
##dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])

#可以对每个键值逐个访问、查看
print("Target names:{}".format(iris_dataset['target_names']))
print("Feature names:\n{}".format(iris_dataset["feature_names"]))
print("data:\n{}".format(iris_dataset['data']))
print("target:{}".format(iris_dataset['target']))
print("frame:{}".format(iris_dataset["frame"]))
print("DESCR:{}".format(iris_dataset["DESCR"][:50] + "\n..."))

数据包含在target和data字段中。

data里是花萼长度、花萼宽度、花瓣长度、花瓣宽度 的测量数据,格式是Numpy数组。

data数组的每一行都对应一朵花,列代表每一朵花的四个测量数据。

机器学习中的个体叫作==样本==

其属性叫作==特征==

data数组的形状(shape)是 样本数x特征数 , 这是sklearn中的约定

1
2
3
4
5
6
7
8
9
10
11
12
13
------output------
[5.1 3.5 1.4 0.2]
[4.9 3. 1.4 0.2]
[4.7 3.2 1.3 0.2]
[4.6 3.1 1.5 0.2]
[5. 3.6 1.4 0.2]
[5.4 3.9 1.7 0.4]
[4.6 3.4 1.4 0.3]
[5. 3.4 1.5 0.2]
[4.4 2.9 1.4 0.2]
[4.9 3.1 1.5 0.1]
[5.4 3.7 1.5 0.2]
[4.8 3.4 1.6 0.2]

2.训练与测试

我们想要利用已有数据集构建一个机器学习模型,此前需要知道训练的模型是否有效。

然而,我们不能将用于构建(训练)模型的数据用于评估模型,因为模型会一直记住整个训练集,所以对于训练集中的任何数据点总会预测正确的标签。

我们要设计方法来评估模型的==泛化==能力。换句话说就是在新数据上能否正确预测。

通常的做法是将收集好的带标签数据分为两部分,一部分用于构建机器学习模型,叫作==训练数据或训练集==,其余的数据用来评估模型性能,叫作==测试数据或测试集或留出集==.

scikit-learn中的train_test_split函数可以打乱数据集并进行拆分。这个函数将75%的行数据及其对应标签作为训练集,剩下的25%作为测试集。

1
2
3
4
5
6
7
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
iris_dataset['data'], iris_dataset['target'],random_state=0)
print("X_train shape:{}".format(X_train.shape))
print("Y_train shape:{}".format(y_train.shape))
print("X_test shape:{}".format(X_test.shape))
print("Y_test shape:{}".format(y_test.shape))
1
2
3
4
5
------output------
X_train shape:(112, 4)
Y_train shape:(112,)
X_test shape:(38, 4)
Y_test shape:(38,)

3.观察数据

在进行模型的构建、训练前,通常最好检查一下数据,看用机器学习能否轻松完成任务,或者需要的信息有没有被包含在数据中。

此外检查数据也可以发现异常值和特殊值。

检查数据的最好方法之一就是将其可视化。

  • 绘制散点图
    • 一个特征作为x,另一个特征作为y,绘制散点图
    • 缺点:难以对多于3个特征的数据集作图
  • 绘制散点图矩阵
    • 可以两两查看所有的特征

为了绘制散点图矩阵,我们首先将Numpy数组转换成pandas DataFrame。pandas有一个绘制散点图矩阵的函数scatter_matrix()。矩阵对角线是每个特征的直方图。

1
2
3
4
iris_dataframe = pd.DataFrame(X_train,columns=iris_dataset.feature_names)
grr = pd.plotting.scatter_matrix(iris_dataframe, c=y_train, figsize=(15,15),marker='o',hist_kwds={'bins': 20}, s=60, alpha=.8, cmap=mglearn.cm3)

plt.show()

从图中可以看出,利用花瓣和花萼的测量数据基本可以将三个类别区分开。这说明我们的数据集较为完善,可以用来训练机器学习模型。

4.构建模型 - KNN分类器

scikit-learn中有许多可用的分类算法,本文档使用的是==k近邻分类器==。构建此模型只需要保存训练集即可。要对一个新的数据点进行观测,算法会在训练集中寻找与这个新数据点距离最近的数据点,然后将这个点的标签赋值给新的数据点。

k近邻算法中k的含义是,我们可以考虑训练集中与新数据点最近的任意k个邻居(比如最近的3个或5个邻居),而不是只考虑最近的那一个。

然后我们可以用这些邻居中数量最多的类别作出预测。

scikit-learn中所有的机器学习模型都在各自的类中实现,这些类被称为Estimator类。k近邻分类算法是在neighbors模块的KNeighborsClassifier类中实现的。我们需要将这个类实例化为一个对象,然后才能使用这个模型。

1
2
3
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train,y_train)

==具体KNN的编写实现后续会跟进研究==

5.作出预测

现在可以用我们构建出来的机器学习模型来对新数据进行预测了。

1
2
3
4
5
6
7
X_new = np.array([[5,2.9,1,0.2]])
print("X_new.shape:{}".format(X_new.shape))

prediction = knn.predict(X_new)
print("prediction:{}".format(prediction))
print("Predicted target name;{}".format(iris_dataset['target_names'][prediction]))

1
2
3
------output------
prediction:[0]
Predicted target name;['setosa']

6.评估模型

我们可以对测试数据中的每朵鸢尾花进行预测,并将预测结果与标签(已知的品种)进行对比。我们可以通过计算精度来衡量模型的优劣,精度就是品种预测正确的花所占的比例。

此外,还可以使用knn对象的score方法来计算测试集的精度。

1
2
3
4
y_pred = knn.predict(X_test)
print("Test set predictions: \n {}".format(y_pred))
int("Test set Score:{:.2f}".format(np.mean(y_pred == y_test)))
print("Test set Score:{:.2f}".format(knn.score(X_test,y_test)))
1
2
3
4
5
6
------output------
Test set predictions:
[2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0 2]
Test set Score:0.97
Test set Score:0.97

小结

本文针对机器学习中监督式学习的其中一个分支——分类问题进行了一次实例分析。

对于鸢尾花分类问题,我们采取的步骤是:

  1. 审查数据集
  2. 训练与测试
  3. 构建模型 -- 分类器
  4. 作出预测
  5. 评估模型

这是机器学习的一套标准流程,也是日后构造机器学习模型会反复套用的结构。