机器学习-08 自学笔记 基于sklearn 线性和二次判别分析

tech2022-08-07  142

机器学习-08 自学笔记 基于sklearn 线性和二次判别分析

线性和二次判别分析[LDA 和 QDA 分类器的数学公式](http://www.scikitlearn.com.cn/0.21.3/3/#12)[LDA 的降维数学公式](http://www.scikitlearn.com.cn/0.21.3/3/#123-lda) 代码重现

线性和二次判别分析

机器学习另一个应用是分类问题,就比如说,一个水果店有苹果、香蕉、梨三种水果,现在新上了苹果梨这种水果,那么苹果梨是属于苹果呢,还是梨呢。用机器学习的算法解决这个问题,就是分类问题。 在分类问题中最重要的是分类器,也就是分类算法。通过分类器,可以确定决策平面,就比如水果店问题,会把平面分成苹果、香蕉、梨三个平面,到时候只需要看,苹果梨落在哪个平面里,它就会被分到该类下。 线性判别分析只能学习线性边界, 而二次判别分析则可以学习二次边界,因此它相对而言更加灵活。

LDA 和 QDA 分类器的数学公式

LDA 和 QDA 都是源于简单的概率模型,这些模型对于每一个类别 k k k 的相关分布 P ( X ∣ y = k ) P(X|y=k) P(Xy=k)都可以通过贝叶斯定理所获得。

P ( y = k ∣ X ) = P ( X ∣ y = k ) P ( y = k ) P ( X ) = P ( X ∣ y = k ) P ( y = k ) ∑ l P ( X ∣ y = l ) ⋅ P ( y = l ) P(y=k | X) = \frac{P(X | y=k) P(y=k)}{P(X)} = \frac{P(X | y=k) P(y = k)}{ \sum_{l} P(X | y=l) \cdot P(y=l)} P(y=kX)=P(X)P(Xy=k)P(y=k)=lP(Xy=l)P(y=l)P(Xy=k)P(y=k) 对于线性以及二次判别分析, P(X|y) 被建模成密度多变量高斯分布: p ( X ∣ y = k ) = 1 ( 2 π ) n ∣ Σ k ∣ 1 / 2 exp ⁡ ( − 1 2 ( X − μ k ) t Σ k − 1 ( X − μ k ) ) p(X | y=k) = \frac{1}{(2\pi)^n |\Sigma_k|^{1/2}}\exp\left(-\frac{1}{2} (X-\mu_k)^t \Sigma_k^{-1} (X-\mu_k)\right) p(Xy=k)=(2π)nΣk1/21exp(21(Xμk)tΣk1(Xμk)) 其中的d是特征数量。 为了把该模型作为分类器使用,我们只需要从训练数据中估计出类的先验概率 P ( y = k ) P(y=k) P(y=k) (通过每个类 k k k 的实例的比例得到) 类别均值 μ k \mu_k μk (通过经验样本的类别均值得到)以及协方差矩阵(通过经验样本的类别协方差或者正则化的估计器 estimator 得到)。

在 LDA 中,每个类别k的高斯分布共享相同的协方差矩阵: Σ k = Σ \Sigma_k=\Sigma Σk=Σ。这导致了两者之间的线性决策面,这可以通过比较对数概率比看出来

log ⁡ [ P ( y = k ∣ X ) / P ( y = l ∣ X ) ] \log[P(y=k | X) / P(y=l | X)] log[P(y=kX)/P(y=lX)]

log ⁡ ( P ( y = k ∣ X ) P ( y = l ∣ X ) ) = 0 ⇔ ( μ k − μ l ) Σ − 1 X = 1 2 ( μ k t Σ − 1 μ k − μ l t Σ − 1 μ l ) \log\left(\frac{P(y=k|X)}{P(y=l | X)}\right) = 0 \Leftrightarrow (\mu_k-\mu_l)\Sigma^{-1} X = \frac{1}{2} (\mu_k^t \Sigma^{-1} \mu_k - \mu_l^t \Sigma^{-1} \mu_l) log(P(y=lX)P(y=kX))=0(μkμl)Σ1X=21(μktΣ1μkμltΣ1μl)

在 QDA 中,没有关于高斯协方差矩阵 Σ k \Sigma_k Σk 的假设,因此有了二次决策平面.

LDA 的降维数学公式

过把输入的数据投影到由最大化类之间分离的方向所组成的线性子空间,可以执行有监督降维。 用 K 表示目标类别的总数。 由于在 LDA 中我们假设所有类别都有相同估计的协方差 Σ \Sigma Σ,所以我们可重新调节数据从而让协方差相同。 X ∗ = D − 1 / 2 U t X  with  Σ = U D U t X^* = D^{-1/2}U^t X\text{ with }\Sigma = UDU^t X=D1/2UtX with Σ=UDUt

代码重现

LDA和QDA在特定数据上的对比

from scipy import linalg import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl from matplotlib import colors from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis # ############################################################################# # Colormap cmap = colors.LinearSegmentedColormap( 'red_blue_classes', {'red': [(0, 1, 1), (1, 0.7, 0.7)], 'green': [(0, 0.7, 0.7), (1, 0.7, 0.7)], 'blue': [(0, 0.7, 0.7), (1, 1, 1)]}) plt.cm.register_cmap(cmap=cmap) # ############################################################################# # Generate datasets def dataset_fixed_cov(): '''Generate 2 Gaussians samples with the same covariance matrix''' n, dim = 300, 2 np.random.seed(0) C = np.array([[0., -0.23], [0.83, .23]]) X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C) + np.array([1, 1])] y = np.hstack((np.zeros(n), np.ones(n))) return X, y def dataset_cov(): '''Generate 2 Gaussians samples with different covariance matrices''' n, dim = 300, 2 np.random.seed(0) C = np.array([[0., -1.], [2.5, .7]]) * 2. X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C.T) + np.array([1, 4])] y = np.hstack((np.zeros(n), np.ones(n))) return X, y # ############################################################################# # Plot functions def plot_data(lda, X, y, y_pred, fig_index): splot = plt.subplot(2, 2, fig_index) if fig_index == 1: plt.title('Linear Discriminant Analysis') plt.ylabel('Data with\n fixed covariance') elif fig_index == 2: plt.title('Quadratic Discriminant Analysis') elif fig_index == 3: plt.ylabel('Data with\n varying covariances') tp = (y == y_pred) # True Positive tp0, tp1 = tp[y == 0], tp[y == 1] X0, X1 = X[y == 0], X[y == 1] X0_tp, X0_fp = X0[tp0], X0[~tp0] X1_tp, X1_fp = X1[tp1], X1[~tp1] # class 0: dots plt.scatter(X0_tp[:, 0], X0_tp[:, 1], marker='.', color='red') plt.scatter(X0_fp[:, 0], X0_fp[:, 1], marker='x', s=20, color='#990000') # dark red # class 1: dots plt.scatter(X1_tp[:, 0], X1_tp[:, 1], marker='.', color='blue') plt.scatter(X1_fp[:, 0], X1_fp[:, 1], marker='x', s=20, color='#000099') # dark blue # class 0 and 1 : areas nx, ny = 200, 100 x_min, x_max = plt.xlim() y_min, y_max = plt.ylim() xx, yy = np.meshgrid(np.linspace(x_min, x_max, nx), np.linspace(y_min, y_max, ny)) Z = lda.predict_proba(np.c_[xx.ravel(), yy.ravel()]) Z = Z[:, 1].reshape(xx.shape) plt.pcolormesh(xx, yy, Z, cmap='red_blue_classes', norm=colors.Normalize(0., 1.), zorder=0) plt.contour(xx, yy, Z, [0.5], linewidths=2., colors='white') # means plt.plot(lda.means_[0][0], lda.means_[0][1], '*', color='yellow', markersize=15, markeredgecolor='grey') plt.plot(lda.means_[1][0], lda.means_[1][1], '*', color='yellow', markersize=15, markeredgecolor='grey') return splot def plot_ellipse(splot, mean, cov, color): v, w = linalg.eigh(cov) u = w[0] / linalg.norm(w[0]) angle = np.arctan(u[1] / u[0]) angle = 180 * angle / np.pi # convert to degrees # filled Gaussian at 2 standard deviation ell = mpl.patches.Ellipse(mean, 2 * v[0] ** 0.5, 2 * v[1] ** 0.5, 180 + angle, facecolor=color, edgecolor='black', linewidth=2) ell.set_clip_box(splot.bbox) ell.set_alpha(0.2) splot.add_artist(ell) splot.set_xticks(()) splot.set_yticks(()) def plot_lda_cov(lda, splot): plot_ellipse(splot, lda.means_[0], lda.covariance_, 'red') plot_ellipse(splot, lda.means_[1], lda.covariance_, 'blue') def plot_qda_cov(qda, splot): plot_ellipse(splot, qda.means_[0], qda.covariance_[0], 'red') plot_ellipse(splot, qda.means_[1], qda.covariance_[1], 'blue') plt.figure(figsize=(10, 8), facecolor='white') plt.suptitle('Linear Discriminant Analysis vs Quadratic Discriminant Analysis', y=0.98, fontsize=15) for i, (X, y) in enumerate([dataset_fixed_cov(), dataset_cov()]): # Linear Discriminant Analysis lda = LinearDiscriminantAnalysis(solver="svd", store_covariance=True) y_pred = lda.fit(X, y).predict(X) splot = plot_data(lda, X, y, y_pred, fig_index=2 * i + 1) plot_lda_cov(lda, splot) plt.axis('tight') # Quadratic Discriminant Analysis qda = QuadraticDiscriminantAnalysis(store_covariance=True) y_pred = qda.fit(X, y).predict(X) splot = plot_data(qda, X, y, y_pred, fig_index=2 * i + 2) plot_qda_cov(qda, splot) plt.axis('tight') plt.tight_layout() plt.subplots_adjust(top=0.92) plt.show()

在 Iris 数据集对比 LDA 和 PCA 之间的降维差异 水仙花数据集代表了3种鸢尾花(刚毛鸢尾属、花色鸢尾花和维吉尼亚鸢尾花),具有4种属性:萼片长度、萼片宽度、花瓣长度和花瓣宽度。 应用于该数据的主成分分析(PCA)识别了导致数据中方差最大的属性组合(主成分或特征空间中的方向)。这里我们在两个第一主成分上绘制不同的样本。 线性判别分析(LDA)试图识别导致类间差异最大的属性。特别是,与PCA不同,LDA是一种使用已知类标签的监督方法。

import matplotlib.pyplot as plt from sklearn import datasets from sklearn.decomposition import PCA from sklearn.discriminant_analysis import LinearDiscriminantAnalysis iris = datasets.load_iris() X = iris.data y = iris.target target_names = iris.target_names pca = PCA(n_components=2) X_r = pca.fit(X).transform(X) lda = LinearDiscriminantAnalysis(n_components=2) X_r2 = lda.fit(X, y).transform(X) # Percentage of variance explained for each components print('explained variance ratio (first two components): %s' % str(pca.explained_variance_ratio_)) plt.figure() colors = ['navy', 'turquoise', 'darkorange'] lw = 2 for color, i, target_name in zip(colors, [0, 1, 2], target_names): plt.scatter(X_r[y == i, 0], X_r[y == i, 1], color=color, alpha=.8, lw=lw, label=target_name) plt.legend(loc='best', shadow=False, scatterpoints=1) plt.title('PCA of IRIS dataset') plt.figure() for color, i, target_name in zip(colors, [0, 1, 2], target_names): plt.scatter(X_r2[y == i, 0], X_r2[y == i, 1], alpha=.8, color=color, label=target_name) plt.legend(loc='best', shadow=False, scatterpoints=1) plt.title('LDA of IRIS dataset') plt.show()

最新回复(0)