跳至主要内容

Python 机器学习:Scikit-Learn 教程

一份通俗易懂的 scikit-learn 教程,帮助您入门 Python 机器学习。
· 12分钟 阅读

使用 AI 探索

机器学习是人工智能的一个分支,致力于理解并构建方法来模仿人类的学习方式。这些方法通过使用算法与数据来提升在某类任务上的表现,且通常归为以下三种最常见的学习类型之一:

  • 监督学习:学习输入与输出之间关系的一类机器学习。
  • 无监督学习:学习未标注数据集底层结构的一类机器学习。
  • 强化学习:一种机器学习方法,其中软件智能体在环境中学习执行某些操作,以获得最大回报。

Scikit-learn(也称 sklearn)是一款开源、健壮的 Python 机器学习库。它的诞生旨在简化在 Python 中实现机器学习与统计模型的过程。

该库通过一致的接口,让从业者能够快速实现大量监督与无监督的机器学习算法。Sklearn 构建于 SciPy 之上,适用于各种数值数据类型,包括 NumPy 数组、SciPy 稀疏矩阵,以及可转换为数值数组的其他数据类型,如 Pandas DataFrame。

在这篇动手实践的 sklearn 教程中,我们将涵盖机器学习生命周期的多个环节,如数据处理、模型训练与模型评估。

查看这个DataCamp 工作空间以跟进代码。

数据

我们首先要探索的是数据;Scikit-learn 自带一些标准的机器学习数据集,这意味着您无需从外部网站或数据库下载。

sklearn 中可用的玩具数据集示例包括用于分类的鸢尾花数据集和用于回归的糖尿病数据集。在我们的示例中,我们将使用葡萄酒数据集。

让我们将其加载到内存中:

from sklearn.datasets import load_wine

wine_data = load_wine() 

执行上述代码会返回一个类似字典的对象,其中包含数据及其相关的元数据。

我们所需的数据位于 .data 属性中,该属性由 load_wine() 返回。我们可以如下以 wine_data 实例的属性来访问它:

wine_data.data

这将返回一个 N × M 的数组,其中 N 是样本数,M 是特征数。

让我们利用这些信息将数据加载到一个pandas DataFrame 中,它更便于操作与分析。

import pandas as pd
from sklearn.datasets import load_wine

wine_data = load_wine()

# Convert data to pandas dataframe
wine_df = pd.DataFrame(wine_data.data, columns=wine_data.feature_names)

# Add the target label
wine_df["target"] = wine_data.target

# Take a preview
wine_df.head()

wine data

现在,您已准备好进行一些数据探索。

数据探索

Pandas DataFrame 是由列组成的二维带标签数据结构,各列可包含不同类型的数据。理解 DataFrame 的最简单方式,是将其视为三个部分的结合:1)数据,2)索引,3)列。

数据探索不是本文的重点,但它在任何数据项目中都极为重要——您可在我们的Python 探索性数据分析教程中了解更多。我们将进行一次简要探索,以便更好地了解数据集的构成,从而更清楚如何处理数据。

首先,我们将对 pandas DataFrame 调用 info() 方法;这会打印 DataFrame 中葡萄酒数据的简要摘要。

wine_df.info()

"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 14 columns):
 #   Column                        Non-Null Count  Dtype  
---  ------                        --------------  -----  
 0   alcohol                       178 non-null    float64
 1   malic_acid                    178 non-null    float64
 2   ash                           178 non-null    float64
 3   alcalinity_of_ash             178 non-null    float64
 4   magnesium                     178 non-null    float64
 5   total_phenols                 178 non-null    float64
 6   flavanoids                    178 non-null    float64
 7   nonflavanoid_phenols          178 non-null    float64
 8   proanthocyanins               178 non-null    float64
 9   color_intensity               178 non-null    float64
 10  hue                           178 non-null    float64
 11  od280/od315_of_diluted_wines  178 non-null    float64
 12  proline                       178 non-null    float64
 13  target                        178 non-null    int64  
dtypes: float64(13), int64(1)
memory usage: 19.6 KB
"""

执行此单元后,您将了解到:

  • 数据包含 178 个样本
  • 共有 14 列,包括目标列(我们要预测的内容)
  • 无缺失值列;可从“Non-Null Count”列推断得出。
  • 所有特征的数据类型为 float64,而目标标签为 int64。
  • 数据占用 19.6 KB 内存。

我们还可以对 DataFrame 调用 describe() 方法,以获取数据集中每个特征的描述性统计信息。

例如:

wine_df.describe() 

wine data

您还需要了解各特征所包含值的大致类型。最快的方法是使用 head() 方法显示前五行数据,或用 tail() 方法查看最后五行数据。

wine_df.tail()

wine data

运行这段代码后,我们可以看到各特征处于不同的量纲。这在使用基于梯度下降的算法(如逻辑回归)以及基于距离的算法(如支持向量机)时可能带来问题,因为这些算法对数据范围较为敏感。

在常规的机器学习流程中,这一过程会更为详细,但我们将在此直接进入数据处理环节,以回到本教程的重点——Scikit-learn。

您可以在 Python Pandas 教程:新手终极指南中进一步了解 Pandas。

Scikit-learn 示例:数据预处理

我们已经对数据有了相当的了解。到这一步,通常意味着您可以开始着手将数据整理为可供机器学习模型使用的形式。

数据处理是机器学习流程中的关键一步,因为现实世界的数据往往很“脏”。它可能包含:

  • 缺失值,
  • 冗余值
  • 离群点
  • 错误
  • 噪声

在将数据送入机器学习模型之前,您必须先处理好这些问题;否则,模型会将这些错误纳入其逼近函数中——它将“学会”在新样本上犯错。这也正是那句著名机器学习格言“垃圾进,垃圾出”的由来。

另一个原因是机器学习模型通常需要数值型数据。

除特征量纲不一致外,初看之下我们的数据并无太多问题。为解决该问题,让我们使用 sklearn 的 StandardScaler 类对特征进行标准化;这会将各特征标准化为均值为 0、标准差为 1。

代码如下:

from sklearn.preprocessing import StandardScaler

# Split data into features and label 
X = wine_df[wine_data.feature_names].copy()
y = wine_df["target"].copy() 

# Instantiate scaler and fit on features
scaler = StandardScaler()
scaler.fit(X)

# Transform features
X_scaled = scaler.transform(X.values)

# View first instance
print(X_scaled[0])

"""
[ 1.51861254 -0.5622498   0.23205254 -1.16959318  1.91390522  0.80899739
  1.03481896 -0.65956311  1.22488398  0.25171685  0.36217728  1.84791957
  1.01300893]
"""

接下来进入模型训练。

Scikit-learn 示例:模型训练

在机器学习模型进行预测之前,必须先在一组数据上进行训练,以学习一个逼近函数。

但我们如何判断模型在未见数据上的表现是否良好?除非进行测试,否则无从得知。

在将模型部署到会影响他人的环境之前,测试模型的一种方法是将训练数据划分为训练集与测试集,并使用测试集来评估模型学到了什么;这被称为离线评估。

划分训练集与测试集的方法有多种,但 scikit-learn 提供了一个内置函数可替我们完成该操作,名为 train_test_split()。

我们将使用此函数按 70%/30% 的比例划分数据:70% 用于训练模型,30% 用于评估模型对未见样本的泛化能力。

from sklearn.model_selection import train_test_split

# Split data into train and test
X_train_scaled, X_test_scaled, y_train, y_test = train_test_split(X_scaled,
                                                                  y,
                                                             train_size=.7,
                                                           random_state=25)

# Check the splits are correct
print(f"Train size: {round(len(X_train_scaled) / len(X) * 100)}% \n\
Test size: {round(len(X_test_scaled) / len(X) * 100)}%")

"""
Train size: 70% 
Test size: 30%

现在让我们来构建一些模型。

构建模型

得益于 sklearn,构建机器学习模型非常简单。

我们将构建三个模型来预测葡萄酒的类别:

  1. 逻辑回归
  2. 支持向量机
  3. 决策树分类器
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier

# Instnatiating the models 
logistic_regression = LogisticRegression()
svm = SVC()
tree = DecisionTreeClassifier()

# Training the models 
logistic_regression.fit(X_train_scaled, y_train)
svm.fit(X_train_scaled, y_train)
tree.fit(X_train_scaled, y_train)

# Making predictions with each model
log_reg_preds = logistic_regression.predict(X_test_scaled)
svm_preds = svm.predict(X_test_scaled)
tree_preds = tree.predict(X_test_scaled)

下一步是评估模型在未见样本上的泛化能力。

Scikit-learn 示例:模型评估

进行模型评估是为了测试模型在未见样本上的泛化表现。Scikit-learn 提供了多种分类与回归指标,用于评估已训练模型的性能。

在我们的用例中,我们将使用 classification_report()(来自 metrics 模块)来生成一份文本报告,展示主要的分类评估指标,如 precision、recall、f1_score、accuracy 等。

代码如下:

from sklearn.metrics import classification_report

# Store model predictions in a dictionary
# this makes it easier to iterate through each model
# and print the results. 
model_preds = {
    "Logistic Regression": log_reg_preds,
    "Support Vector Machine": svm_preds,
    "Decision Tree": tree_preds
}

for model, preds in model_preds.items():
    print(f"{model} Results:\n{classification_report(y_test, preds)}", sep="\n\n")

"""
Logistic Regression Results:
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        17
           1       1.00      0.92      0.96        25
           2       0.86      1.00      0.92        12

    accuracy                           0.96        54
   macro avg       0.95      0.97      0.96        54
weighted avg       0.97      0.96      0.96        54

Support Vector Machine Results:
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        17
           1       1.00      1.00      1.00        25
           2       1.00      1.00      1.00        12

    accuracy                           1.00        54
   macro avg       1.00      1.00      1.00        54
weighted avg       1.00      1.00      1.00        54

Decision Tree Results:
              precision    recall  f1-score   support

           0       0.94      0.94      0.94        17
           1       0.96      0.88      0.92        25
           2       0.86      1.00      0.92        12

    accuracy                           0.93        54
   macro avg       0.92      0.94      0.93        54
weighted avg       0.93      0.93      0.93        54
"""

初步看来,支持向量机似乎是最佳模型。在典型流程中,这会激发对模型的好奇心——它真的如结果所示那么出色,还是我们某处出了错?您应当主动进一步了解您的模型及其所学内容,因为这将帮助您更好地洞察模型的优劣势。

掌握这些信息对相关方也极具价值,因为这能帮助他们找到方案来弥补模型的不足之处。

结语

scikit-learn 库由多个模块组成,使得实现机器学习模型变得容易。这些模块从用于准备数据进入机器学习模型的预处理工具,到用于在数据中发现模式的模型,再到用于评估模型表现的度量指标,一应俱全。

在本教程中,我们只是浅尝辄止地展示了 sklearn 的能力。若想更深入地了解该库能做什么,我们提供了多种资源助您启程。以下是几个起点:

主题