用于分类的线性判别分析

Machine LearningMachine LearningBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

本实验将向你介绍线性判别分析(LDA)及其在分类中的应用。我们将使用 Python 中流行的机器学习库 scikit-learn 来实现 LDA。我们还将探讨协方差的 Ledoit-Wolf 和 Oracle 收缩近似(OAS)估计器如何改进分类。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup(["Advanced Data Analysis and Dimensionality Reduction"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/discriminant_analysis("Discriminant Analysis") sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup -.-> sklearn/covariance("Covariance Estimators") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/discriminant_analysis -.-> lab-49194{{"用于分类的线性判别分析"}} sklearn/covariance -.-> lab-49194{{"用于分类的线性判别分析"}} sklearn/datasets -.-> lab-49194{{"用于分类的线性判别分析"}} ml/sklearn -.-> lab-49194{{"用于分类的线性判别分析"}} end

生成随机数据

首先,我们需要生成具有判别性特征和噪声特征的随机数据。我们将使用 scikit-learn 的make_blobs函数来生成具有一个判别性特征的两个数据簇。然后,我们将向其他特征添加随机噪声。

import numpy as np
from sklearn.datasets import make_blobs

def generate_data(n_samples, n_features):
    """生成具有噪声特征的随机类似斑点的数据。

    这将返回一个形状为`(n_samples, n_features)`的输入数据数组
    和一个包含 `n_samples` 个目标标签的数组。

    只有一个特征包含判别性信息,其他特征
    只包含噪声。
    """
    X, y = make_blobs(n_samples=n_samples, n_features=1, centers=[[-2], [2]])

    ## 添加非判别性特征
    if n_features > 1:
        X = np.hstack([X, np.random.randn(n_samples, n_features - 1)])
    return X, y

实现线性判别分析(LDA)

接下来,我们将使用 scikit-learn 的LinearDiscriminantAnalysis类来实现 LDA。我们将创建三个分类器:

  • 无收缩的 LDA
  • 具有 Ledoit-Wolf 收缩的 LDA
  • 具有 OAS 收缩的 LDA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.covariance import OAS

clf1 = LinearDiscriminantAnalysis(solver="lsqr", shrinkage=None)
clf2 = LinearDiscriminantAnalysis(solver="lsqr", shrinkage="auto")
oa = OAS(store_precision=False, assume_centered=False)
clf3 = LinearDiscriminantAnalysis(solver="lsqr", covariance_estimator=oa)

训练和测试分类器

我们将训练和测试每个分类器,以观察它们在生成的数据上的表现。我们将多次重复此过程,以获得平均准确率得分。

n_train = 20  ## 训练样本数
n_test = 200  ## 测试样本数
n_averages = 50  ## 重复分类的次数
n_features_max = 75  ## 最大特征数
step = 4  ## 计算的步长

acc_clf1, acc_clf2, acc_clf3 = [], [], []
n_features_range = range(1, n_features_max + 1, step)

for n_features in n_features_range:
    score_clf1, score_clf2, score_clf3 = 0, 0, 0
    for _ in range(n_averages):
        X, y = generate_data(n_train, n_features)

        clf1.fit(X, y)
        clf2.fit(X, y)
        clf3.fit(X, y)

        X, y = generate_data(n_test, n_features)
        score_clf1 += clf1.score(X, y)
        score_clf2 += clf2.score(X, y)
        score_clf3 += clf3.score(X, y)

    acc_clf1.append(score_clf1 / n_averages)
    acc_clf2.append(score_clf2 / n_averages)
    acc_clf3.append(score_clf3 / n_averages)

可视化结果

最后,我们将绘制每个分类器的分类准确率与特征数量的函数关系图。我们将使用 matplotlib 来创建该图。

import matplotlib.pyplot as plt

features_samples_ratio = np.array(n_features_range) / n_train

plt.plot(
    features_samples_ratio,
    acc_clf1,
    linewidth=2,
    label="LDA",
    color="gold",
    linestyle="solid",
)
plt.plot(
    features_samples_ratio,
    acc_clf2,
    linewidth=2,
    label="LDA with Ledoit Wolf",
    color="navy",
    linestyle="dashed",
)
plt.plot(
    features_samples_ratio,
    acc_clf3,
    linewidth=2,
    label="LDA with OAS",
    color="red",
    linestyle="dotted",
)

plt.xlabel("n_features / n_samples")
plt.ylabel("Classification accuracy")

plt.legend(loc="lower left")
plt.ylim((0.65, 1.0))
plt.suptitle(
    "LDA (线性判别分析) 与\n"
    + "带 Ledoit Wolf 的 LDA 与\n"
    + "带 OAS 的 LDA (1 个判别性特征)"
)
plt.show()

总结

在本实验中,我们学习了如何使用 scikit-learn 实现线性判别分析(LDA)。我们探讨了协方差的 Ledoit-Wolf 和 Oracle 收缩近似(OAS)估计器如何提高分类准确率。我们还生成了具有判别性特征的随机数据,并在这些数据上测试了我们的分类器。最后,我们将分类准确率可视化为特征数量的函数。