线性与二次判别分析比较

机器学习领域,线性判别分析(LDA)和二次判别分析(QDA)是两种常用的分类算法。它们都基于高斯分布的假设,但对协方差矩阵的处理方式不同。LDA假设所有类别共享相同的协方差矩阵,而QDA允许每个类别有自己的协方差矩阵。本文将通过生成的合成数据集来比较这两种算法的表现,并使用数据可视化来展示它们的决策边界和分类效果。

数据生成

首先,定义了一个函数来生成合成数据。该函数创建了两个以(0, 0)和(1, 1)为中心的数据块,每个数据块被分配到一个特定的类别。数据块的离散程度由协方差矩阵参数控制,这些参数在从高斯分布生成样本时使用。

import numpy as np def make_data(n_samples, n_features, cov_class_1, cov_class_2, seed=0): rng = np.random.RandomState(seed) X = np.concatenate([ rng.randn(n_samples, n_features) @ cov_class_1, rng.randn(n_samples, n_features) @ cov_class_2 + np.array([1, 1]), ]) y = np.concatenate([np.zeros(n_samples), np.ones(n_samples)]) return X, y

生成了三个数据集。第一个数据集的两个类别共享相同的协方差矩阵,且该协方差矩阵是球形的(各向同性)。第二个数据集与第一个类似,但不强制协方差矩阵为球形。最后一个数据集为每个类别提供了一个非球形的协方差矩阵。

绘图函数

下面的代码用于绘制来自估计器的信息,即线性判别分析(LDA)和二次判别分析(QDA)。展示的信息包括:基于估计器的概率估计的决策边界;用圆圈表示正确分类样本的散点图;用叉号表示错误分类样本的散点图;估计器估计的每个类别的均值,用星号标记;以及在2个标准差处用椭圆表示的估计协方差。

import matplotlib as mpl from matplotlib import colors from sklearn.inspection import DecisionBoundaryDisplay def plot_ellipse(mean, cov, color, ax): v, w = np.linalg.eigh(cov) u = w[0] / np.linalg.norm(w[0]) angle = np.arctan(u[1] / u[0]) angle = 180 * angle / np.pi # 转换为度 # 2个标准差处的高斯填充 ell = mpl.patches.Ellipse(mean, 2 * v[0] ** 0.5, 2 * v[1] ** 0.5, angle=180 + angle, facecolor=color, edgecolor="black", linewidth=2) ell.set_clip_box(ax.bbox) ell.set_alpha(0.4) ax.add_artist(ell) def plot_result(estimator, X, y, ax): cmap = colors.ListedColormap(["tab:red", "tab:blue"]) DecisionBoundaryDisplay.from_estimator(estimator, X, response_method="predict_proba", plot_method="pcolormesh", ax=ax, cmap="RdBu", alpha=0.3) DecisionBoundaryDisplay.from_estimator(estimator, X, response_method="predict_proba", plot_method="contour", ax=ax, alpha=1.0, levels=[0.5]) y_pred = estimator.predict(X) X_right, y_right = X[y == y_pred], y[y == y_pred] X_wrong, y_wrong = X[y != y_pred], y[y != y_pred] ax.scatter(X_right[:, 0], X_right[:, 1], c=y_right, s=20, cmap=cmap, alpha=0.5) ax.scatter(X_wrong[:, 0], X_wrong[:, 1], c=y_wrong, s=30, cmap=cmap, alpha=0.9, marker="x") ax.scatter(estimator.means_[:, 0], estimator.means_[:, 1], c="yellow", s=200, marker="*", edgecolor="black") if isinstance(estimator, LinearDiscriminantAnalysis): covariance = [estimator.covariance_] * 2 else: covariance = estimator.covariance_ plot_ellipse(estimator.means_[0], covariance[0], "tab:red", ax) plot_ellipse(estimator.means_[1], covariance[1], "tab:blue", ax) ax.set_box_aspect(1) ax.spines["top"].set_visible(False) ax.spines["bottom"].set_visible(False) ax.spines["left"].set_visible(False) ax.spines["right"].set_visible(False) ax.set(xticks=[], yticks=[])

这些函数将帮助直观地理解LDA和QDA在不同数据集上的表现差异。

LDA与QDA的比较

将在所有三个数据集上比较LDA和QDA两种估计器。首先需要注意的是,在第一和第二个数据集上,LDA和QDA是等价的。实际上,主要的区别在于LDA假设每个类别的协方差矩阵相同,而QDA为每个类别估计一个协方差矩阵。由于在这些情况下,数据生成过程对两个类别有相同的协方差矩阵,QDA估计的两个协方差矩阵几乎相等,因此等同于LDA估计的协方差矩阵。

在第一个数据集中,用于生成数据集的协方差矩阵是球形的,这导致了一个与两个均值之间的垂直平分线对齐的判别边界。在第二个数据集中,判别边界不再通过两个均值的中间。

最后,在第三个数据集中,观察到LDA和QDA之间的真正区别。QDA拟合了两个协方差矩阵,并提供了一个非线性的判别边界,而LDA由于假设两个类别共享一个单一的协方差矩阵,因此拟合不足。

脚本的总运行时间

  • 正态分布、Ledoit-Wolf和OAS线性判别分析用于分类
  • 在真实数据集上进行异常值检测
  • 高斯混合模型选择
  • 鲁棒与经验协方差估计
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485