ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Python 机器学习降维实战:PCA、LDA 与核 PCA 的完整实现指南(python-machine-learning-book 第 5 章)

Python 机器学习降维实战:PCA、LDA 与核 PCA 的完整实现指南(python-machine-learning-book 第 5 章) 机器学习教程【免费下载链接】python-machine-learning-bookThe Python Machine Learning (1st edition) book code repository and info resource项目地址https://gitcode.com/gh_mirrors/py/python-machine-learning-book点击查看免费下载本指南以python-machine-learning-book仓库第 5 章《Compressing Data via Dimensionality Reduction通过降维压缩数据》为骨架系统讲解三类降维技术的原理、手工实现与 scikit-learn 调用方式无监督的主成分分析PCA、有监督的线性判别分析LDA以及用于非线性映射的核主成分分析核 PCA / Kernel PCA。读完本文你将能够独立复现特征分解求主成分、构造类内/类间散布矩阵求解线性判别式以及从零实现 RBF 核 PCA 并投影新样本的完整流程并能在 Wine 数据集与合成数据半月形、同心圆上完成可运行的实战验证。一、章节概览一条完整的降维技术路线本章的原版目录见 code/ch05/README.md规划了如下内容主线无监督降维主成分分析PCA总方差与解释方差Total and explained variance特征变换Feature transformationscikit-learn 中的 PCA有监督数据压缩线性判别分析LDA计算散布矩阵Computing the scatter matrices为新的特征子空间选择线性判别式Selecting linear discriminants将样本投影到新特征空间Projecting samples onto the new feature spacescikit-learn 中的 LDA使用核 PCA 进行非线性映射kernel PCA核函数与核技巧Kernel functions and the kernel trick用 Python 实现核 PCA例 1分离半月形数据half-moon shapes例 2分离同心圆数据concentric circles投影新数据点Projecting new data pointsscikit-learn 中的核 PCA小结仓库为本章提供了三种可执行载体内容完全同源、可互相印证载体路径说明交互式 Notebookcode/ch05/ch05.ipynb112 个 cell57 个 Markdown 55 个代码 cell含图文讲解与逐步输出纯脚本code/optional-py-scripts/ch05.py与 Notebook 等价的顺序执行脚本适合命令行直接运行本地数据集code/datasets/wine/wine.dataWine 数据集的仓库本地副本避免在线下载失败运行前可先通过 code/check_environment.ipynb 检查环境依赖包括numpy、pandas、scipy、matplotlib与scikit-learn。从源码结构看ch05.py 还针对 scikit-learn 0.18 的 API 变更做了兼容处理低于 0.18 时从sklearn.grid_search与sklearn.lda导入否则从sklearn.model_selection与sklearn.discriminant_analysis导入——说明该章节代码适用于 0.18 及以上的 scikit-learn 版本。二、无监督降维主成分分析PCA2.1 核心思想沿最大方差方向投影PCA 是无监督的线性变换它寻找一组相互正交的轴主成分使得数据沿这些轴投影后方差最大。几何上可以理解为把数据点云的主伸展方向协方差椭圆的长轴方向找出来再丢弃方差贡献小的方向从而用更少的维度保留最多的信息。本章用 Wine 数据集第 4、5 章共用规格见 code/datasets/wine/README.md演示完整流程该数据集包含178 个样本、13 个特征、3 个类别三个类别样本数分别为 59、71、48特征包括 Alcohol、Malic acid、Ash、Alcalinity of ash、Magnesium、Total phenols、Flavanoids、Nonflavanoid phenols、Proanthocyanins、Color intensity、Hue、OD280/OD315 of diluted wines、Proline。2.2 数据准备划分训练集与标准化首先读取数据并划分 70% 训练集 / 30% 测试集随后用StandardScaler标准化这是 PCA 前的关键一步避免量纲较大的特征主导方差。注意源码中的用法是训练集fit_transform、测试集仅transform见 ch05.py避免数据泄漏Notebook 中作者还专门备注过一处笔误误将测试集写成fit_transform提示了正确的做法import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler df_wine pd.read_csv(https://archive.ics.uci.edu/ml/ machine-learning-databases/wine/wine.data, headerNone) df_wine.columns [Class label, Alcohol, Malic acid, Ash, Alcalinity of ash, Magnesium, Total phenols, Flavanoids, Nonflavanoid phenols, Proanthocyanins, Color intensity, Hue, OD280/OD315 of diluted wines, Proline] X, y df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values X_train, X_test, y_train, y_test \ train_test_split(X, y, test_size0.3, random_state0) sc StandardScaler() X_train_std sc.fit_transform(X_train) X_test_std sc.transform(X_test)若在线地址不可用Notebook 中明确指出可以在仓库本地副本 code/datasets/wine/wine.data 找到该数据集相对 Notebook 的路径写作./../datasets/wine/wine.data。2.3 协方差矩阵的特征分解PCA 的第一步是构造标准化数据的协方差矩阵并对其进行特征分解见 ch05.pyimport numpy as np cov_mat np.cov(X_train_std.T) eigen_vals, eigen_vecs np.linalg.eig(cov_mat) print(\nEigenvalues \n%s % eigen_vals)特征值衡量对应特征向量主成分方向上解释的方差大小。Notebook 中作者特别备注此处使用numpy.linalg.eig分解的是对称的协方差矩阵而对称矩阵更稳妥的做法是用numpy.linalg.eigh专为对称/厄米矩阵设计返回排序后的特征值。这一细节在后面手工实现核 PCA 时会被再次用到——届时由于核矩阵必然对称源码直接选用scipy.linalg.eigh。2.4 总方差与解释方差解释方差比explained variance ratio指单个特征值占总特征值之和的比例$\text{var_exp}i \lambda_i / \sum{j1}^{d} \lambda_j$。累积解释方差则用np.cumsum计算。源码ch05.py同时绘制柱状图单个主成分解释方差与阶梯线累积解释方差tot sum(eigen_vals) var_exp [(i / tot) for i in sorted(eigen_vals, reverseTrue)] cum_var_exp np.cumsum(var_exp) plt.bar(range(1, 14), var_exp, alpha0.5, aligncenter, labelindividual explained variance) plt.step(range(1, 14), cum_var_exp, wheremid, labelcumulative explained variance) plt.ylabel(Explained variance ratio) plt.xlabel(Principal components) plt.legend(locbest) plt.show()上图是运行结果前两个主成分即解释了 Wine 数据绝大部分方差后续主成分贡献迅速衰减——这正是用少量主成分压缩数据的直观证据。2.5 特征变换构造投影矩阵 W选定前 k 个特征向量后将其按列堆叠成投影矩阵 $W \in \mathbb{R}^{d \times k}$新特征 $X X_{std} \cdot W$。源码实现ch05.py将特征值绝对值, 特征向量组成元组并按特征值降序排序取前两个特征向量构造 Weigen_pairs [(np.abs(eigen_vals[i]), eigen_vecs[:, i]) for i in range(len(eigen_vals))] eigen_pairs.sort(reverseTrue) w np.hstack((eigen_pairs[0][1][:, np.newaxis], eigen_pairs[1][1][:, np.newaxis])) X_train_pca X_train_std.dot(w)两个实战要点符号翻转Notebook 明确提示不同 NumPy/LAPACK 版本下特征向量的符号可能整体翻转得到的 W 与书中截图相反但这不影响降维与分类效果只是坐标轴镜像点积验证源码打印了X_train_std[0].dot(w)确认单样本投影结果与矩阵乘法一致便于逐元素核对。2.6 scikit-learn 中的 PCA手工实现有助于理解原理实际工程可直接使用sklearn.decomposition.PCA见 ch05.pyfrom sklearn.decomposition import PCA pca PCA() X_train_pca pca.fit_transform(X_train_std) print(Variance explained ratio:\n, pca.explained_variance_ratio_) pca PCA(n_components2) X_train_pca pca.fit_transform(X_train_std) X_test_pca pca.transform(X_test_std)关键参数与属性n_components保留的主成分数。设为None默认时保留全部主成分可通过explained_variance_ratio_观察累积解释方差后人工决定截断点explained_variance_ratio_每个主成分的解释方差比是选择维度的核心依据fit_transform/transform训练集用前者拟合并变换测试集用后者仅变换与手工流程一致。降维后的训练集与测试集均可在 PC1–PC2 平面绘制散点图并接入LogisticRegression训练分类器用plot_decision_regions绘制决策边界——三类样本在二维主成分空间中已基本可分验证了压缩后仍保留判别信息。三、有监督数据压缩线性判别分析LDA3.1 与 PCA 的本质区别PCA 不关心类别标签只最大化整体方差LDA 则有监督目标是最大化类间距离、最小化类内距离找到最能区分类别的方向线性判别式Linear Discriminants。PCA 寻找的是描述数据的轴LDA 寻找的是区分类别的轴。3.2 计算散布矩阵LDA 的核心是两类散布矩阵见 ch05.py各类均值向量对 3 个类别分别计算 13 维均值向量类内散布矩阵 $S_W$先对每个类别计算各样本与其类均值之差的向量外积之和再对类别求和d 13 # number of features S_W np.zeros((d, d)) for label, mv in zip(range(1, 4), mean_vecs): class_scatter np.zeros((d, d)) for row in X_train_std[y_train label]: row, mv row.reshape(d, 1), mv.reshape(d, 1) class_scatter (row - mv).dot((row - mv).T) S_W class_scatter用协方差矩阵修正由于三个类别样本数不均衡59 / 71 / 48直接累加外积会放大样本数多的类别的贡献。源码随即展示更合理的做法——用各类别的协方差矩阵$\text{cov}(X_{train,label}^T)$ 求和替代 $S_W$本质是按样本数做了归一化见 ch05.py类间散布矩阵 $S_B$以总体均值为基准用每类样本数 ×类均值 − 总体均值外积求和mean_overall np.mean(X_train_std, axis0) d 13 S_B np.zeros((d, d)) for i, mean_vec in enumerate(mean_vecs): n X_train[y_train i 1, :].shape[0] S_B n * (mean_vec - mean_overall).dot((mean_vec - mean_overall).T)3.3 求解广义特征值问题$S_W^{-1}S_B$对矩阵 $S_W^{-1}S_B$ 做特征分解得到的特征值越大对应判别方向上的类别可区分性越强见 ch05.pyeigen_vals, eigen_vecs np.linalg.eig(np.linalg.inv(S_W).dot(S_B)) eigen_pairs sorted(eigen_pairs, keylambda k: k[0], reverseTrue)与 PCA 的方差图类似源码绘制了可区分性discriminability柱状图与累积曲线LDA 的判别子空间最多只有 c − 1 2 个非零判别式c 为类别数前两个判别式即承载了全部可区分性。3.4 投影样本与新特征空间取前两个判别向量堆叠成 W投影 $X X_{std} \cdot W$见 ch05.py。源码在绘图时对坐标取了相反数乘以 −1并在 Notebook 中说明这只是可视化方向调整不影响判别结果。投影后的三类样本在 LD1–LD2 平面上被清晰地分到不同区域。3.5 scikit-learn 中的 LDA实际使用中直接调用sklearn.discriminant_analysis.LinearDiscriminantAnalysis见 ch05.pyfrom sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA lda LDA(n_components2) X_train_lda lda.fit_transform(X_train_std, y_train) lr LogisticRegression() lr lr.fit(X_train_lda, y_train) X_test_lda lda.transform(X_test_std)注意 LDA 与 PCA 的关键差异fit_transform需要同时传入X_train_std与y_train监督信息训练好的lr分类器在训练集与测试集的 LD 平面上绘制的决策边界几乎一致说明 LDA 压缩出的二维空间对未见数据同样具有良好的泛化判别能力。四、核 PCA处理非线性映射4.1 为什么需要核技巧PCA 与 LDA 都是线性变换当数据本身呈非线性结构如半月形、同心圆时线性投影无法有效分离类别。核 PCA 的思路是先用核函数把样本隐式映射到高维特征空间在该空间中执行标准 PCA从而让原本线性不可分的数据变得线性可分同时不必显式计算高维坐标——这就是核技巧kernel trick。常用的核函数包括 RBF高斯核 $k(x, x) \exp(-\gamma |x - x|^2)$ 等。4.2 从零实现 RBF 核 PCA仓库源码提供了完整的rbf_kernel_pca实现见 ch05.py步骤清晰可复现from scipy.spatial.distance import pdist, squareform from scipy import exp from scipy.linalg import eigh def rbf_kernel_pca(X, gamma, n_components): # 1) 计算两两样本的平方欧氏距离 sq_dists pdist(X, sqeuclidean) mat_sq_dists squareform(sq_dists) # 2) 计算对称核矩阵 KRBF 核 K exp(-gamma * mat_sq_dists) # 3) 对核矩阵中心化 N K.shape[0] one_n np.ones((N, N)) / N K K - one_n.dot(K) - K.dot(one_n) one_n.dot(K).dot(one_n) # 4) 特征分解eigh 针对对称矩阵并返回有序特征值 eigvals, eigvecs eigh(K) # 5) 取前 k 个特征向量作为投影结果 X_pc np.column_stack((eigvecs[:, -i] for i in range(1, n_components 1))) return X_pc实现要点pdist(X, sqeuclidean)计算两两平方欧氏距离squareform还原为对称矩阵核矩阵必须中心化centering否则结果不是真正的主成分——公式 $K K - 1_N K - K 1_N 1_N K 1_N$ 是核 PCA 正确性的关键此处特意选用scipy.linalg.eigh而非eig核矩阵对称eigh返回升序特征值取末尾 k 个eigvecs[:, -i]即对应最大的 k 个特征值与 2.3 节的备注呼应。4.3 例 1分离半月形数据用sklearn.datasets.make_moons(n_samples100, random_state123)生成半月形数据。对比可见源码见 ch05.py线性 PCA 将两类样本投影到 PC1 后完全重叠无法分离调用rbf_kernel_pca(X, gamma15, n_components2)后两类样本在 PC1 轴上被明显分开且右子图展示的一维投影PC1 值分布呈现出清晰的两段分离——非线性结构被成功拉直。gamma15是 RBF 核的调节参数gamma 越大核的局部影响范围越小决策边界越复杂实际使用时通常需要通过交叉验证调优。4.4 例 2分离同心圆数据make_circles(n_samples1000, random_state123, noise0.1, factor0.2)生成内外两层同心圆。同样的对比结论成立见 ch05.py线性 PCA 投影后两类在 PC1 上几乎完全混叠而核 PCA 将内圈与外圈样本沿 PC1 分离成两个清晰的区间。这一类线性方法彻底失效的数据形态正是核 PCA 的典型应用场景。4.5 投影新数据点project_x与线性 PCA 不同核 PCA 的特征向量是训练样本的线性组合以核函数形式出现无法像 PCA 那样用简单的 W 矩阵直接变换新样本。源码给出了针对 RBF 核的投影函数project_x见 ch05.pydef rbf_kernel_pca(X, gamma, n_components): # ... 与 4.2 相同但额外返回 alphas np.column_stack((eigvecs[:, -i] for i in range(1, n_components 1))) lambdas [eigvals[-i] for i in range(1, n_components 1)] return alphas, lambdas def project_x(x_new, X, gamma, alphas, lambdas): pair_dist np.array([np.sum((x_new - row)**2) for row in X]) k np.exp(-gamma * pair_dist) return k.dot(alphas / lambdas)project_x的数学依据是新样本的核 PCA 坐标 新样本与所有训练样本的核向量 $k$ 点乘特征向量 / 特征值。源码以X[25]为新样本验证了流程alphas[25]原始投影与project_x重投影remapped point在图上的位置吻合说明该函数可正确把未见样本映射进已训练好的核 PCA 子空间——这是把核 PCA 用于真实预测流水线如分类器推理的必要环节。4.6 scikit-learn 中的核 PCA工程实践直接使用sklearn.decomposition.KernelPCA见 ch05.pyfrom sklearn.decomposition import KernelPCA scikit_kpca KernelPCA(n_components2, kernelrbf, gamma15) X_skernpca scikit_kpca.fit_transform(X)KernelPCA支持linear、poly、rbf、sigmoid等多种核gamma为 RBF/多项式等核的参数其降维结果与手工实现基本一致符号方向可能不同但结构相同可作为生产环境的首选实现。五、三种方法如何选型结合仓库的 FAQ 文档 docs/faq/dimensionality-reduction.md 可以形成清晰的选型原则PCA无监督不利用标签寻找正交的最大方差轴适合数据可视化、去相关、压缩与无标签场景LDA有监督利用标签最大化类别可分性适合线性可分程度较高的分类任务前置压缩FAQ 同时提醒虽然直觉上分类任务 LDA 优于 PCA但实证并不总是如此需要按数据验证核 PCA非线性能分离同心圆这类线性不可分数据但并非万能——例如它无法展开瑞士卷Swiss Roll流形此时应改用局部线性嵌入LLE等流形学习方法相关对比可见 docs/faq/large-num-features.md 与 docs/faq/lda-vs-pca.md。即没有恒优的降维方法选择取决于数据形态与任务目标线性 vs 非线性、有监督 vs 无监督。六、运行与验证方式Notebook 方式启动 Jupyter 打开 code/ch05/ch05.ipynb逐 cell 执行即可看到每步输出与图表脚本方式直接运行python code/optional-py-scripts/ch05.py脚本按章节打印分隔标题并依次执行全部代码段数据源默认从 UCI 在线地址读取 Wine 数据离线时改用 code/datasets/wine/wine.data可运行性验证仓库在 code/ch01/tests/test_notebooks.py 中提供了基于nbconvert --execute的 Notebook 执行测试模式可用于验证 Notebook 端到端可运行该测试文件当前仅挂接附录 G 的 TensorFlow Notebook可作为扩展本章验证的参考写法。小结本章以降维压缩数据为统一主题给出了从原理到实现再到工程调用的完整闭环PCA 用无监督的方差最大化压缩数据并可视化LDA 引入类别标签、通过 $S_W^{-1}S_B$ 的广义特征分解最大化类别可分性核 PCA 借助核技巧把非线性结构映射到可线性分离的高维空间并提供了新样本投影的完整数学方案。仓库中 code/optional-py-scripts/ch05.py 与 code/ch05/ch05.ipynb 的全部代码均可直接复现是理解并落地这三类降维技术的可靠参照。赞分享机器学习教程【免费下载链接】python-machine-learning-bookThe Python Machine Learning (1st edition) book code repository and info resource项目地址https://gitcode.com/gh_mirrors/py/python-machine-learning-book点击查看免费下载相关推荐5分钟上手Dochub前端开发者必备的离线文档解决方案5分钟上手Dochub前端开发者必备的离线文档解决方案 Dochub 是一款专为开发者设计的离线文档搜索工具让你在没有网络连接的情况下也能快速查阅前端开发相后端开发工具CANN/Ascend C调试打印APIPrinta nameZH CN_TOPIC_0000002330927402 /a 产品支持情况a namesection1550532418人工智能深度学习算子库CANNAscendp5play快速入门从零到一的完整游戏制作教程p5play快速入门从零到一的完整游戏制作教程 p5play是一款基于p5.js和Box2D物理引擎的JavaScript游戏开发框架它让游戏开发变得简单直上一篇CANN opbase 数据类型转换指南ToOpDataType 将 aclDataType 映射为 op::DataType下一篇Obsidian界面优化实战指南从基础到高级的视觉与交互解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表