scikit-learn简介

  • scikit-learn 是一个开源项目,可以免费使用和分发,任何人都可以轻松获取其源代码来查看其背后的原理。
  • scikit-learn 项目正在不断地开发和改进中,它的用户社区非常活跃。
  • scikit-learn 包含许多目前最先进的机器学习算法,每个算法都有详细的文档(http://scikit-learn.org/stable/documentation)。
  • scikit-learn 是一个非常流行的工具,也是最有名的 Python 机器学习库。广泛应用于工业界和学术界。

scikit-learn安装

scikit-learn 依赖于另外两个 Python 包:NumPy 和 SciPy。
若想绘图和进行交互式开发,还应该安装 matplotlib、IPython 和 Jupyter Notebook。

那么,我们也可以使用预先打包的Python 发行版,比如Anaconda

必要的库和工具

scikit-learn 是基于 NumPy(计算基础包之一) 和 SciPy (计算科学函数集合)的。
除了 NumPy 和 SciPy,还会用到 pandas(处理和分析数据 )和 matplotlib(绘图)。
Jupyter Notebook(交互环境),一个基于浏览器的交互编程环境。比较友好
mglearn(scikit-learn专用函数库,快速美化绘图或获取一些有趣的数据)

初认识例子:鸢尾花分类

我们有已知品种的鸢尾花的测量数据,所以这是一个监督学习问题 我们要在多个选项中预测其中一个(鸢尾花的品种),所以这是一个分类问题

1. 数据

我们用scikit-learn 的 datasets 模块中 的鸢尾花(Iris)数据集,调用 load_iris 函数来加载数据

  1. IN:
  2. from sklearn.datasets import load_iris
  3. iris_dataset = load_iris()
  4. # load_iris 返回的 iris 对象是一个 Bunch 对象,与字典非常相似,里面包含键和值

我们可以调用 iris_dataset.keys() 来查看数据集的键

Keys of iris_dataset:

dict_keys([‘target_names’, ‘feature_names’, ‘DESCR’, ‘data’, ‘target’])

  • DESCR 键对应的值是数据集的简要说明
  • target_names 键对应的值是一个字符串数组,里面包含我们要预测的花的品种
  • feature_names 键对应的值是一个字符串列表,对每一个特征进行了说明
  • 数据包含在 target 和 data 字段中。data 里面是花萼长度、花萼宽度、花瓣长度、花瓣宽

度的测量数据,格式为 NumPy 数组 target 数组包含的是测量过的每朵花的品种,也是一个 NumPy 数组

2. 训练数据与测试数据

用于构建机器学习模型的数据,叫作训练数据(training data)或训练集(training set)。
用来评估模型性能的数据,叫作测试数据(test data)、测试集(test set)或留出集(hold-out set)。

scikit-learn 中的 train_test_split 函数可以打乱数据集并进行拆分。

scikit-learn 中的数据通常用大写的 X 表示,而标签用小写的 y 表示。这是受到了数学标准公式 f(x)=y 的启发,其中 x 是函数的输入,y 是输出。用大写的 X 是因为数据是一个二维数组(矩阵),用小写的 y 是因为目标是一个一维数组(向量)。

  1. IN:
  2. from sklearn.model_selection import train_test_split
  3. # 划分训练数据与测试数据
  4. X_train, X_test, y_train, y_test = train_test_split(
  5. iris_dataset['data'], iris_dataset['target'], random_state=0)

3. 观察数据

检查数据的最佳方法之一就是将其可视化。
一种可视化方法是绘制散点图(scatter plot)。数据散点图将一个特征作为 x 轴,另一个特征作为 y 轴,将每一个数据点绘制为图上的一个点。不幸的是,计算机屏幕只有两个维度,所以我们一次只能绘制两个特征(也可能是3 个)。用这种方法难以对多于 3 个特征的数据集作图。解决这个问题的一种方法是绘制散点图矩阵(pair plot),从而可以两两查看所有的特征。如果特征数不多的话,比如我们这里有 4 个,这种方法是很合理的。但是你应该记住,散点图矩阵无法同时显示所有特征之间的关系,所以这种可视化方法可能无法展示数据的某些有趣内容。

  1. IN:
  2. # 利用X_train中的数据创建DataFrame
  3. # 利用iris_dataset.feature_names中的字符串对数据列进行标记
  4. iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)
  5. # 利用DataFrame创建散点图矩阵,按y_train着色
  6. grr = pd.scatter_matrix(iris_dataframe, c=y_train, figsize=(15, 15), marker='o',
  7. hist_kwds={'bins': 20}, s=60, alpha=.8, cmap=mglearn.cm3)

4. 构建模型:K近邻算法

k 近邻算法中 k 的含义是,我们可以考虑训练集中与新数据点最近的任意 k 个邻居(比如说,距离最近的 3 个或 5 个邻居),而不是只考虑最近的那一个。然后,我们可以用这些邻居中数量最多的类别做出预测。

k 近邻分类算法是在 neighbors 模块的 KNeighborsClassifier 类中实现的。我们需要将这个类实例化为一个对象,然后才能使用这个模型。这时我们需要设置模型的参数。KNeighborsClassifier 最重要的参数就是邻居的数目。

  1. from sklearn.neighbors import KNeighborsClassifier
  2. knn = KNeighborsClassifier(n_neighbors=1) # 近邻值设置为1

knn 对象对算法进行了封装,既包括用训练数据构建模型的算法,也包括对新数据点进行预测的算法。它还包括算法从训练数据中提取的信息。对于 KNeighborsClassifier 来说,里面只保存了训练集。 想要基于训练集来构建模型,需要调用 knn 对象的 fit 方法,输入参数为 X_train 和 y_train,二者都是 NumPy 数组,前者包含训练数据,后者包含相应的训练标签

  1. IN:
  2. knn.fit(X_train, y_train)
  3. OUT:
  4. KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
  5. metric_params=None, n_jobs=1, n_neighbors=1, p=2,
  6. weights='uniform')

构建模型时用到的参数。几乎所有参数都是默认值,还有一些像 n_neighbors=1,这是我们传入的参数。scikit-learn 中的大多数模型都有很多参数,但多用于速度优化或非常特殊的用途。一般无需关注这个字符串表示中的其他参数。

5. 做出预测

有一朵鸢尾花,花萼长 5cm 宽 2.9cm,花瓣长 1cm 宽 0.2cm。接下来我们预测一下这朵鸢尾花属于哪个品种?

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

注意,我们将这朵花的测量数据转换为二维 NumPy 数组的一行,这是因为 scikit-learn的输入数据必须是二维数组。

我们调用 knn 对象的 predict 方法来进行预测:

  1. IN:
  2. prediction = knn.predict(X_new)
  3. print("Prediction: {}".format(prediction))
  4. print("Predicted target name: {}".format(
  5. iris_dataset['target_names'][prediction]))
  6. OUT:
  7. Prediction: [0]
  8. Predicted target name: ['setosa']

根据我们模型的预测,这朵新的鸢尾花属于类别 0,也就是说它属于 setosa 品种。

6. 评估模型

我们需要用到之前创建的测试集。这些数据没有用于构建模型,但我们知道测试集中每朵鸢尾花的实际品种。
因此,我们可以对测试数据中的每朵鸢尾花进行预测,并将预测结果与标签(已知的品种)进行对比。通过计算精度(accuracy)来衡量模型的优劣,精度就是品种预测正确的花所占的比例。

  1. IN:
  2. y_pred = knn.predict(X_test)
  3. print("Test set predictions:\n {}".format(y_pred))
  4. OUT:
  5. Test set predictions:
  6. [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]
  7. IN:
  8. print("Test set score: {:.2f}".format(np.mean(y_pred == y_test)))
  9. OUT:
  10. Test set score: 0.97

对于这个模型来说,测试集的精度约为 0.97。根据一些数学假设,对于新的鸢尾花,可以认为我们的模型预测结果有 97% 都是正确的。

7. 汇总

如今机器学习的门槛并不是很高,思维是我个人觉得比较重要的,比如上面看似复杂的思路,一个模型的训练、构建、评估其实就几行代码就能解决:

  1. IN
  2. X_train, X_test, y_train, y_test = train_test_split(
  3. iris_dataset['data'], iris_dataset['target'], random_state=0)
  4. knn = KNeighborsClassifier(n_neighbors=1)
  5. knn.fit(X_train, y_train)
  6. print("Test set score: {:.2f}".format(knn.score(X_test, y_test)))
  7. OUT:
  8. Test set score: 0.97