别再只盯着PCA了!用Python手写LDA降维,实战区分鸢尾花数据集
别再只盯着PCA了用Python手写LDA降维实战区分鸢尾花数据集当数据科学家面对高维数据时降维技术就像一把瑞士军刀。虽然主成分分析(PCA)几乎成了降维的代名词但在分类任务中线性判别分析(LDA)往往能带来意想不到的效果提升。本文将带您从零实现LDA算法并在经典的鸢尾花数据集上展示其与PCA的本质区别。1. 为什么需要LDA理解降维的本质差异PCA和LDA虽然都是线性降维技术但它们的数学目标截然不同。PCA寻找的是数据方差最大的方向而LDA则寻找能够最好区分不同类别的投影方向。关键区别对比特性PCALDA监督性无监督有监督优化目标最大化总体方差最大化类间方差/类内方差适用场景通用降维分类任务预处理保留信息全局结构判别信息在实际项目中我发现当数据标签可用时LDA通常能带来更好的分类效果。特别是在鸢尾花数据集这样类别区分明显的场景下LDA的优势尤为突出。2. LDA数学原理深度解析LDA的核心思想可以概括为找到一个投影方向使得同类样本的投影点尽可能接近不同类样本的投影点尽可能远离。这通过优化以下目标函数实现$$ J(w) \frac{w^T S_b w}{w^T S_w w} $$其中$S_b$是类间散布矩阵$S_w$是类内散布矩阵计算步骤详解计算每个类别的均值向量mean_vectors [] for cl in range(3): # 鸢尾花有3个类别 mean_vectors.append(np.mean(X[ycl], axis0))计算类内散布矩阵$S_w$S_w np.zeros((4,4)) # 鸢尾花有4个特征 for cl,mv in zip(range(3), mean_vectors): class_sc_mat np.zeros((4,4)) for row in X[y cl]: row, mv row.reshape(4,1), mv.reshape(4,1) class_sc_mat (row-mv).dot((row-mv).T) S_w class_sc_mat计算类间散布矩阵$S_b$overall_mean np.mean(X, axis0) S_b np.zeros((4,4)) for i,mean_vec in enumerate(mean_vectors): n X[yi,:].shape[0] mean_vec mean_vec.reshape(4,1) overall_mean overall_mean.reshape(4,1) S_b n * (mean_vec - overall_mean).dot((mean_vec - overall_mean).T)3. Python实现LDA全流程现在我们将上述数学原理转化为完整的Python实现。使用scikit-learn加载鸢尾花数据集from sklearn.datasets import load_iris import numpy as np iris load_iris() X iris.data y iris.target特征标准化重要但常被忽视的步骤from sklearn.preprocessing import StandardScaler scaler StandardScaler() X scaler.fit_transform(X)计算特征值和特征向量eig_vals, eig_vecs np.linalg.eig(np.linalg.inv(S_w).dot(S_b)) # 按特征值大小排序 eig_pairs [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))] eig_pairs sorted(eig_pairs, keylambda k: k[0], reverseTrue)选择前2个最大的特征值对应的特征向量降维到2维W np.hstack((eig_pairs[0][1].reshape(4,1), eig_pairs[1][1].reshape(4,1))) X_lda X.dot(W)4. 可视化对比LDA vs PCA让我们将LDA的结果与PCA进行直观对比import matplotlib.pyplot as plt from sklearn.decomposition import PCA # PCA降维 pca PCA(n_components2) X_pca pca.fit_transform(X) # 绘制结果 fig, (ax1, ax2) plt.subplots(1, 2, figsize(12,5)) for label, marker, color in zip(range(3), (^, s, o), (blue, red, green)): ax1.scatter(xX_lda[ylabel, 0], yX_lda[ylabel, 1], markermarker, colorcolor, labeliris.target_names[label]) ax2.scatter(xX_pca[ylabel, 0], yX_pca[ylabel, 1], markermarker, colorcolor, labeliris.target_names[label]) ax1.set_title(LDA投影) ax2.set_title(PCA投影) plt.legend() plt.show()注意在实际项目中LDA最多能将数据降到类别数-1的维度。对于鸢尾花的3个类别最大维度是2。从可视化结果可以明显看出LDA投影后的类别分离度远高于PCA。这正是因为LDA利用了标签信息有针对性地寻找最佳判别方向。5. 进阶技巧与常见陷阱技巧1处理小样本问题当特征维度高于样本数时$S_w$可能不可逆。解决方案是# 加入正则化项 S_w 0.001 * np.eye(S_w.shape[0])技巧2LDA作为分类器LDA不仅可以降维还可以直接用于分类from sklearn.discriminant_analysis import LinearDiscriminantAnalysis lda_clf LinearDiscriminantAnalysis() lda_clf.fit(X, y)常见陷阱忘记特征标准化会导致某些特征主导结果类别不平衡会影响LDA性能非线性可分数据需要核LDA等扩展方法在金融风控项目中我曾用LDA处理过客户信用评分数据。与PCA相比LDA降维后的特征使模型AUC提升了约8%这充分证明了在分类任务中选择合适降维方法的重要性。