Skip to content

sklearn笔记(1):K近邻算法进行鸢尾花分类

前言

注: 阅读书籍《Introduction to Machine Learning with Python》过程中形成的笔记

scikit-learn(sklearn) 库是一个非常流行的Python机器学习库,使用之前安装依赖:

$ pip install numpy scipy matplotlib ipython pandas scikit-learn

书中通过一个使用 K近邻算法 进行鸢尾花分类的例子,来说明机器学习中的一些概念和这个库的使用方式,使用IPython交互工具:

# $ ./venv/bin/ipython

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sklearn as sk

from IPython.display import display

# %matplotlib inline
# %matplotlib notebook
%matplotlib osx # 省去每次plt.show()

鸢尾花(Iris)数据集

In [1]: from sklearn.datasets import load_iris

In [2]: iris_dataset = load_iris()

In [4]: iris_dataset.keys()
Out[4]: dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 
                   'feature_names', 'filename', 'data_module'])

In [5]: iris_dataset.filename
Out[5]: 'iris.csv'

In [8]: iris_dataset.target_names
Out[8]: array(['setosa', 'versicolor', 'virginica'], dtype='<U10')

In [13]: iris_dataset.feature_names
Out[13]:
['sepal length (cm)',
 'sepal width (cm)',
 'petal length (cm)',
 'petal width (cm)']

In [14]: iris_dataset.target
Out[14]:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

In [24]: iris_dataset.data[:10]
Out[24]:
array([[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]])

In [27]: type(iris_dataset.data)
Out[27]: numpy.ndarray

In [28]: iris_dataset.data.shape
Out[28]: (150, 4)

Iris数据集是 sklearn 库自带的一个经典数据集,大概150行数据,可以看到它其实是读取自文件iris.csv,它的各个key含义:

  • data: 数据集具体的数据,是一个numpy数组,其 形状(shape) 是样本(sample)数乘以特征数,这里是150行*4个特征
  • feature_names: 数据中每一条数据的各个 特证(feature),即列的名字
  • target: 数据中每一条数据对应的分类结果,即 类别(class),比如0,1,2
  • target_names: 分类(classification) 结果的值对应的含义或 标签(label),比如setosa, versicolor, virginica

训练集与测试集的拆分

这里要进行的是一个监督学习,因为是根据数据集中的每一个输入都有一个对应的标准结果输出,让算法根据这些标准答案来进行训练,从而学到一种分类的能力,对将来新的数据进行分类判断。

将这个数据集分成两部分,一部分叫 训练数据(training data)或训练集(training set),另一部分叫 测试集(test data)或测试集(test set)

在库中自带一个函数train_test_split可以自动将数据集按照75%和25%的bili拆分,默认是这个比例。

In [29]: from sklearn.model_selection import train_test_split

In [30]: X_train, X_test, y_train, y_test = train_test_split(iris_dataset.data, iris_dataset.target, random_state=0)

In [36]: X_train.shape, X_test.shape
Out[36]: ((112, 4), (38, 4))

In [37]: y_train.shape, y_test.shape
Out[37]: ((112,), (38,))

In [38]: 112/150.0
Out[38]: 0.7466666666666667
  • 拆分时参数 random_state=0 是提供给随机数生成器的种子,同样的种子总能得到同样的拆分结果。
  • 默认比例是75%和25%

观察数据

通过绘制散点图(scatter plot)或矩阵散点图(scatter matrix plot)来大致看看数据集里面的数据是否可以根据特征进行分类:

In [39]: import pandas as pd

In [40]: iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)

In [26]: type(iris_dataframe)
Out[26]: pandas.core.frame.DataFrame

In [25]: grr = pd.plotting.scatter_matrix(iris_dataframe, c=y_train, figsize=(15,15), marker='o', 
                                         hist_kwds={'bins': 20}, s=60, alpha=.8, cmap="rainbow")

In [35]: import matplotlib.pyplot as plt

In [39]: plt.show()

# %matplotlib inline
# %matplotlib notebook
In [20]: %matplotlib tk
Warning: Cannot change to a different GUI toolkit: tk. Using osx instead

In [18]: %matplotlib osx # 自动显示图片

通过绘制的图像可以看到数据是可以有明显的分类的。

建立模型: K近邻算法

这个算法会根据邻近的N个数据所属的分类标签来决定新数据的分类:

In [27]: from sklearn.neighbors import KNeighborsClassifier

In [28]: knn = KNeighborsClassifier(n_neighbors=1) # 只看邻近距离是1的元素

In [29]: knn.fit(X_train, y_train)
Out[29]: KNeighborsClassifier(n_neighbors=1)

In [31]: type(knn)
Out[31]: sklearn.neighbors._classification.KNeighborsClassifier

通过读取训练集数据和训练集结果,完成了模型的学习过程。

评估模型

因为已经有测试集的结果y_test了,评估模型的精确度就是对比下预测准确的百分比:

In [34]: knn.score(X_test, y_test)
Out[34]: 0.9736842105263158

In [32]: y_pred = knn.predict(X_test)

In [33]: y_pred
Out[33]:
array([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])

In [35]: np.mean(y_pred == y_test)
Out[35]: 0.9736842105263158       

这个模型的精确度是97%。

使用模型预测

In [36]: X_new = np.array([[5, 2.9, 1, 0.2]])

In [37]: X_new.shape
Out[37]: (1, 4)

In [38]: knn.predict(X_new)
Out[38]: array([0])

In [39]: iris_dataset.target_names[knn.predict(X_new)]
Out[39]: array(['setosa'], dtype='<U10')

提供一条数据,模型根据4个特征算出它最接近的分类是0,即setosa。

总结:监督学习模型常用接口

sklearn 库中,监督学习模型常用的接口有:

  • fit: 训练模型
  • predict: 预测结果
  • score: 评估精确度

资源