引言
分类 - 简介
Section titled “分类 - 简介”什么是分类?
Section titled “什么是分类?”分类 (Classification) 是监督机器学习 (supervised machine learning) 中的一项基本任务。它涉及根据输入数据点 (data point) 的特征 (features),预测其属于某个特定的类别 (category) 或类标签 (class label)。可以将其想象成将物体放入预定义的容器 (bin)。输出结果是一个离散的类别,例如电子邮件的“垃圾邮件” (Spam) 或“非垃圾邮件” (Not Spam),图像的“猫” (Cat) 或“狗” (Dog),或贷款申请的“批准” (Approved) 或“拒绝” (Rejected)。
数学上,分类旨在学习一个映射函数 (f),该函数接收输入变量 (X) 并预测离散的输出变量 (Y)。由于是监督学习,算法从一个数据集中学习,其中训练 (training) 期间提供了输入特征 (X) 和正确的类标签 (Y)。
一个常见例子是电子邮件垃圾邮件检测。算法从标记为“垃圾邮件”或“非垃圾邮件”的电子邮件中学习。目标是构建一个模型,能够准确分类新的、未见过的电子邮件。如果只有两个可能的类别,就像这个例子一样,称为二分类 (binary classification)。如果类别多于两个(例如,将新闻文章分类为“体育”、“政治”、“技术”),则称为多分类 (multi-class classification)。
为了构建分类器 (classifier),我们首先在一个标记数据集(训练数据 training data)上训练它。模型学习将特征与特定类别关联起来的模式。训练完成后,我们在模型之前未见过的一个单独数据集(测试数据 testing data)上评估其性能,以了解其泛化能力 (generalizes)。
分类中的学习器类型
Section titled “分类中的学习器类型”分类算法可以根据其学习方式大致分为以下几类:
懒惰学习器 (Lazy Learners)
Section titled “懒惰学习器 (Lazy Learners)”顾名思义,懒惰学习器在训练阶段不构建通用模型。它们只存储整个训练数据集。当需要对新的数据点进行分类时,它们会将其与存储的数据点进行比较以进行预测。这意味着训练速度快,但预测速度可能较慢,尤其对于大型数据集。例子包括 K 近邻 (K-Nearest Neighbors, KNN) 和基于案例推理 (Case-Based Reasoning)。
急切学习器 (Eager Learners)
Section titled “急切学习器 (Eager Learners)”急切学习器在接收到任何测试数据之前,就基于训练数据构建一个分类模型。它们构建发现的模式的泛化表示。训练需要更长时间,但预测新实例通常快得多。大多数常见的分类算法都属于此类,例如决策树 (Decision Trees)、朴素贝叶斯 (Naïve Bayes)、支持向量机 (Support Vector Machines, SVM)、逻辑回归 (Logistic Regression) 和人工神经网络 (Artificial Neural Networks, ANN)。
使用 Scikit-learn 在 Python 中构建分类器
Section titled “使用 Scikit-learn 在 Python 中构建分类器”Scikit-learn 是用于机器学习的首选 Python 库。让我们逐步构建一个简单的分类器。
步骤 1:导入必要的库
Section titled “步骤 1:导入必要的库”我们需要用于数据处理 (Pandas)、数值运算 (NumPy)、数据分割、分类器本身以及评估指标 (Scikit-learn) 的库。
import pandas as pdimport numpy as npfrom sklearn.model_selection import train_test_splitfrom sklearn.naive_bayes import GaussianNBfrom sklearn.metrics import accuracy_score, classification_report, confusion_matrixfrom sklearn.datasets import load_breast_cancerfrom sklearn.preprocessing import StandardScaler步骤 2:加载和准备数据集
Section titled “步骤 2:加载和准备数据集”我们将使用 Breast Cancer Wisconsin Diagnostic Database 数据集,这是一个经典的二分类数据集,可在 Scikit-learn 中获取。将数据加载到 Pandas DataFrame 中以便于操作是一个好习惯。
# 加载数据集cancer = load_breast_cancer()
# 创建一个 Pandas DataFrame# 特征在 cancer.data 中,目标在 cancer.target 中df = pd.DataFrame(data=np.c_[cancer['data'], cancer['target']], columns=np.append(cancer['feature_names'], ['target']))
# 显示基本信息和前几行print('数据集形状:', df.shape)print('\n前 5 行:\n', df.head())
# 分离特征 (X) 和目标 (y)X = df[cancer.feature_names]y = df['target']
# 打印类别标签(0:恶性,1:良性)print('\n目标名称:', cancer.target_names)print('类别分布:\n', y.value_counts())输出解释:代码加载数据集,创建一个表格 (DataFrame),其中每行是一个样本,列代表测量值(特征)和最终诊断(目标)。它显示了表格的大小、前几个示例、目标值 (0 和 1) 的含义,以及属于每个类别的样本数量。
步骤 3:将数据分割为训练集和测试集
Section titled “步骤 3:将数据分割为训练集和测试集”我们需要分割数据,一部分用于训练模型,另一部分用于测试其在未见数据上的性能。这有助于估计模型在新数据上的表现。我们使用 train_test_split。设置 random_state 可确保每次运行代码时分割结果相同,从而使结果可重现。按 y 进行分层 (stratifying) 可确保训练集和测试集中的类别比例相同。
# 分割数据:80% 用于训练,20% 用于测试X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42, stratify=y)
print('\n训练集形状:', X_train.shape)print('测试集形状:', X_test.shape)步骤 3.5:特征缩放(可选但推荐)
Section titled “步骤 3.5:特征缩放(可选但推荐)”当特征处于相似的尺度时,许多算法表现更好。虽然朴素贝叶斯并非严格对缩放敏感,但这是一个好习惯,尤其对于 SVM 或逻辑回归等算法。我们将使用 StandardScaler 对数据进行缩放,它通过去除均值并缩放到单位方差来标准化特征。
scaler = StandardScaler()X_train_scaled = scaler.fit_transform(X_train)X_test_scaled = scaler.transform(X_test)
# 注意:我们仅在训练数据上拟合缩放器,然后对训练和测试数据进行转换。# 这可以防止测试集的数据泄露到训练过程中。步骤 4:训练分类模型
Section titled “步骤 4:训练分类模型”我们将使用高斯朴素贝叶斯 (Gaussian Naïve Bayes, GaussianNB) 分类器,这是一种简单且通常有效的算法,基于贝叶斯定理 (Bayes’ theorem),并假设特征服从正态分布(高斯分布)。
# 初始化高斯朴素贝叶斯分类器gnb = GaussianNB()
# 使用缩放后的训练数据训练模型model = gnb.fit(X_train_scaled, y_train)
print('\n模型训练完成。')步骤 5:进行预测
Section titled “步骤 5:进行预测”现在我们使用训练好的模型对缩放后的测试数据进行类别标签预测。
# 对缩放后的测试集进行预测y_pred = model.predict(X_test_scaled)
# 显示前几个预测值与实际标签的对比print('\n前 10 个预测值:', y_pred[:10])print('前 10 个实际标签:', y_test.values[:10])步骤 6:评估模型
Section titled “步骤 6:评估模型”我们的模型表现如何?我们使用各种指标来评估其预测结果与真实标签 (y_test) 的对比。
# 计算准确率accuracy = accuracy_score(y_test, y_pred)print(f'\n模型准确率: {accuracy:.4f}')
# 生成混淆矩阵print('\n混淆矩阵:')cm = confusion_matrix(y_test, y_pred)print(cm)# 注意:在 Scikit-learn 的二分类混淆矩阵中:# 左上角:真阴性 (TN)# 右上角:假阳性 (FP)# 左下角:假阴性 (FN)# 右下角:真阳性 (TP)# 假设类别 1 ('benign' 良性) 是阳性类别
# 生成详细的分类报告print('\n分类报告:')report = classification_report(y_test, y_pred, target_names=cancer.target_names)print(report)准确率 (Accuracy) 告诉我们总预测中正确预测的百分比。混淆矩阵 (Confusion matrix) 详细列出了每个类别的正确和错误预测。分类报告 (Classification report) 提供了每个类别的精确率 (Precision)、召回率 (Recall) 和 F1 分数 (F1-score),这些指标通常比准确率更能提供信息,尤其对于类别不平衡的数据集。
为了更鲁棒的评估,特别是在数据集较小的情况下,考虑使用交叉验证 (Cross-Validation)。请参阅 Scikit-learn 文档:https://scikit-learn.org/stable/modules/cross_validation.html
理解分类评估指标
Section titled “理解分类评估指标”选择正确的评估指标至关重要。仅仅构建模型是不够的;我们需要知道它的有效性如何。指标的选择取决于问题本身以及不同类型错误带来的后果。
混淆矩阵 (Confusion Matrix)
Section titled “混淆矩阵 (Confusion Matrix)”混淆矩阵提供了一个表格,总结了分类模型的性能。对于二分类器,其形式如下:
预测为阴性 | 预测为阳性
-----------------|------------------
真实为阴性 | 真阴性 (TN) | 假阳性 (FP - 第一类错误 Type I Error)
真实为阳性 | 假阴性 (FN - 第二类错误 Type II Error) | 真阳性 (TP)
- 真阳性 (True Positives, TP): 正确预测为阳性的实例(例如,实际是良性 benign,被正确识别为良性)。
- 真阴性 (True Negatives, TN): 正确预测为阴性的实例(例如,实际是恶性 malignant,被正确识别为恶性)。
- 假阳性 (False Positives, FP): 错误预测为阳性的实例(例如,实际是恶性,被错误识别为良性 - “误报 False Alarm”)。
- 假阴性 (False Negatives, FN): 错误预测为阴性的实例(例如,实际是良性,被错误识别为恶性 - “漏报 Miss”)。
请参考上面代码示例中 Scikit-learn confusion_matrix 的输出,查看计算出的值。
准确率 (Accuracy)
Section titled “准确率 (Accuracy)”总预测中正确预测的比例。公式:Accuracy = (TP + TN) / (TP + TN + FP + FN)。虽然直观,但准确率在类别不平衡 (imbalanced datasets) 的数据集上可能产生误导(其中一个类别远比其他类别频繁)。
使用 accuracy_score(y_test, y_pred) 计算。
精确率 (Precision)
Section titled “精确率 (Precision)”在所有被预测为阳性的实例中,实际是阳性的比例是多少?高精确率意味着更少的假阳性。公式:Precision = TP / (TP + FP)。当假阳性的成本很高时(例如,将非垃圾邮件标记为垃圾邮件)非常有用。
请查看 classification_report 输出中的 ‘precision’ 列。
召回率 (Recall)(灵敏度 Sensitivity 或 真阳性率 True Positive Rate)
Section titled “召回率 (Recall)(灵敏度 Sensitivity 或 真阳性率 True Positive Rate)”在所有实际是阳性的实例中,模型正确识别的比例是多少?高召回率意味着更少的假阴性。公式:Recall = TP / (TP + FN)。当假阴性的成本很高时(例如,未能检测出恶性肿瘤)至关重要。
请查看 classification_report 输出中的 ‘recall’ 列。
F1 分数 (F1-Score)
Section titled “F1 分数 (F1-Score)”精确率和召回率的调和平均值 (harmonic mean)。它提供了一个兼顾这两个指标的单一分数。公式:F1 = 2 * (Precision * Recall) / (Precision + Recall)。在类别不平衡的数据集上,它通常比准确率是一个更好的衡量标准。
请查看 classification_report 输出中的 ‘f1-score’ 列。
特异度 (Specificity)(真阴性率 True Negative Rate)
Section titled “特异度 (Specificity)(真阴性率 True Negative Rate)”在所有实际是阴性的实例中,模型正确识别的比例是多少?公式:Specificity = TN / (TN + FP)。它是召回率对于阴性类别的对应指标。虽然默认的 classification_report 不总是显示它,但可以从混淆矩阵计算得出。高特异度意味着模型善于识别真阴性。
从 confusion_matrix 的值计算得出:TN / (TN + FP)。
常见的分类算法
Section titled “常见的分类算法”除了朴素贝叶斯之外,其他流行且强大的分类算法包括:
- 逻辑回归 (Logistic Regression): 一种适用于二分类任务的线性模型。
- 支持向量机 (Support Vector Machine, SVM): 找到最优超平面来分隔类别,在高维空间中有效。
- 决策树 (Decision Tree): 一种树状结构,内部节点测试特征,叶节点代表类别标签。
- 随机森林 (Random Forest): 一种集成方法,使用多个决策树来提高鲁棒性和准确性。
- K 近邻 (K-Nearest Neighbors, KNN): 一种懒惰学习器,根据其最近邻居的多数类别进行分类。
- 梯度提升机 (Gradient Boosting Machines)(例如,XGBoost, LightGBM): 强大的集成方法,按顺序构建模型,纠正先前模型的错误。
我们将在后续章节中更详细地探讨其中的一些算法。
分类模型被用于无数的实际应用中:
- 医学诊断: 根据患者症状和检查结果识别疾病(例如,癌症检测)。
- 垃圾邮件过滤: 将电子邮件分类为垃圾邮件或非垃圾邮件。
- 情感分析: 确定文本中表达的情感(积极、消极、中立)。
- 图像识别: 对图像进行分类(例如,识别物体,人脸识别)。
- 欺诈检测: 识别欺诈性交易或活动。
- 客户流失预测: 预测客户是否可能停止使用某项服务。
- 文档分类: 将文档分配到预定义的类别(例如,按主题分类新闻文章)。