用Python手把手实现MDS降维:从水果口味数据到可视化分析

张开发
2026/6/19 8:22:30 15 分钟阅读
用Python手把手实现MDS降维:从水果口味数据到可视化分析
用Python手把手实现MDS降维从水果口味数据到可视化分析在数据分析领域高维数据的可视化一直是个挑战。当我们面对超过三维的数据时如何直观地理解数据点之间的关系多维尺度变换(MDS)提供了一种优雅的解决方案。本文将带你用Python从零开始实现MDS算法通过一个水果口味评分的实际案例完整展示从数据预处理到可视化分析的全过程。1. MDS算法原理与准备工作MDS(Multidimensional Scaling)是一种基于距离保持的降维技术其核心思想是将高维空间中的数据点映射到低维空间(通常是2D或3D)同时尽可能保持原始数据点之间的距离关系。这种技术特别适用于需要可视化高维数据关系的场景。要理解MDS我们需要掌握几个关键概念距离矩阵描述数据点之间距离的对称矩阵中心化矩阵用于将数据点中心化处理的特殊矩阵内积矩阵反映数据点之间内积关系的矩阵特征分解获取数据主要变化方向的关键步骤在开始编码前我们需要准备以下Python库import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.metrics import pairwise_distances from sklearn.preprocessing import StandardScaler2. 数据准备与预处理我们使用一个水果口味评分数据集作为案例包含五种水果在三个维度的评分水果甜度酸度多汁度苹果645香蕉813橙子576葡萄734菠萝468首先我们将数据加载为DataFrame并进行标准化处理# 创建数据集 fruits [苹果, 香蕉, 橙子, 葡萄, 菠萝] data np.array([ [6, 4, 5], # 苹果 [8, 1, 3], # 香蕉 [5, 7, 6], # 橙子 [7, 3, 4], # 葡萄 [4, 6, 8] # 菠萝 ]) # 标准化数据 scaler StandardScaler() scaled_data scaler.fit_transform(data)提示数据标准化是重要步骤可以消除不同维度间量纲的影响使各维度对距离计算的贡献均衡。3. 距离矩阵计算与中心化MDS的核心输入是距离矩阵。我们首先计算标准化后数据的欧氏距离矩阵# 计算欧氏距离矩阵 distance_matrix pairwise_distances(scaled_data, metriceuclidean) print(距离矩阵:\n, np.round(distance_matrix, 2))得到的距离矩阵如下[[0. 1.72 1.8 1.15 1.73] [1.72 0. 2.83 1.15 2.83] [1.8 2.83 0. 2.16 1.15] [1.15 1.15 2.16 0. 2.16] [1.73 2.83 1.15 2.16 0. ]]接下来是中心化处理这是MDS算法的关键步骤之一n distance_matrix.shape[0] I np.eye(n) L np.ones((n, n)) H I - (1/n) * L # 中心化距离矩阵 B -0.5 * H (distance_matrix ** 2) H4. 特征分解与降维坐标计算通过特征分解我们可以找到数据的主要变化方向# 计算特征值和特征向量 eigenvalues, eigenvectors np.linalg.eigh(B) # 按特征值大小降序排列 idx np.argsort(eigenvalues)[::-1] eigenvalues eigenvalues[idx] eigenvectors eigenvectors[:, idx] # 选择前两个最大的特征值和对应的特征向量 top2_eigenvalues eigenvalues[:2] top2_eigenvectors eigenvectors[:, :2] # 计算降维后的坐标 coordinates top2_eigenvectors np.diag(np.sqrt(top2_eigenvalues))得到的二维坐标如下苹果: [-0.38, -0.62] 香蕉: [ 1.34, 0.70] 橙子: [-1.03, 0.39] 葡萄: [ 0.75, -0.59] 菠萝: [ 0.31, 1.11]5. 结果可视化与分析最后我们将降维结果可视化直观展示水果之间的口味关系plt.figure(figsize(10, 8)) plt.scatter(coordinates[:, 0], coordinates[:, 1], colorred, s100) # 添加水果标签 for i, fruit in enumerate(fruits): plt.annotate(fruit, (coordinates[i, 0], coordinates[i, 1]), textcoordsoffset points, xytext(0,10), hacenter) plt.xlabel(第一主成分) plt.ylabel(第二主成分) plt.title(水果口味MDS降维可视化) plt.grid(True) plt.show()从可视化结果中我们可以得出一些有趣的观察香蕉在甜度维度得分最高在图中明显与其他水果分离橙子和菠萝在酸度和多汁度上得分较高在图中位置相近苹果和葡萄位于中间位置口味相对均衡第一主成分可能主要反映甜度与酸度的平衡第二主成分可能主要反映多汁程度6. MDS算法实现完整代码以下是完整的Python实现代码封装成了一个可复用的函数def mds_manual(X, n_components2, metriceuclidean): 手动实现MDS算法 参数: X: 原始数据矩阵 (n_samples, n_features) n_components: 降维后的维度 metric: 距离度量方法 返回: coordinates: 降维后的坐标 (n_samples, n_components) # 计算距离矩阵 distance_matrix pairwise_distances(X, metricmetric) # 中心化处理 n distance_matrix.shape[0] H np.eye(n) - (1/n) * np.ones((n, n)) B -0.5 * H (distance_matrix ** 2) H # 特征分解 eigenvalues, eigenvectors np.linalg.eigh(B) # 排序并选择前n_components个特征 idx np.argsort(eigenvalues)[::-1][:n_components] eigenvalues eigenvalues[idx] eigenvectors eigenvectors[:, idx] # 计算坐标 coordinates eigenvectors np.diag(np.sqrt(eigenvalues)) return coordinates # 使用示例 coordinates mds_manual(scaled_data) print(降维坐标:\n, np.round(coordinates, 2))7. MDS与其他降维技术的比较MDS与其他常见降维方法相比有其独特优势方法优点缺点适用场景MDS保持全局距离关系解释性强计算复杂度高(O(n^3))距离保持可视化PCA计算效率高保持最大方差只考虑线性关系线性数据降维t-SNE擅长保持局部结构可视化效果好参数敏感难以解释高维数据可视化UMAP计算效率高保持局部和全局结构较新方法理论理解仍在发展大规模数据降维在实际项目中选择哪种降维方法取决于具体需求如果目标是可视化全局距离关系MDS是很好的选择如果数据量很大(10000样本)考虑使用UMAP或PCA如果关注局部邻域结构t-SNE可能更合适8. 实战技巧与常见问题在实现MDS时有几个实用技巧和常见陷阱需要注意距离度量的选择欧氏距离适用于连续数值数据余弦相似度适用于文本或高维稀疏数据预计算距离可以直接使用领域特定的距离度量数值稳定性问题确保距离矩阵是对称的检查特征值是否为实数(由于浮点运算误差可能出现微小虚部)处理负特征值(经典MDS要求所有特征值为非负)# 处理可能出现的复数问题 eigenvalues np.real(eigenvalues) eigenvectors np.real(eigenvectors) # 处理负特征值(设置最小为0) eigenvalues[eigenvalues 0] 0可视化增强技巧添加颜色编码表示额外维度使用不同形状标记不同类别添加置信椭圆显示数据分布交互式可视化(使用plotly等库)# 增强版可视化示例 import matplotlib.patches as patches plt.figure(figsize(12, 8)) colors [red, green, blue, purple, orange] markers [o, s, ^, D, v] for i, (fruit, color, marker) in enumerate(zip(fruits, colors, markers)): plt.scatter(coordinates[i, 0], coordinates[i, 1], ccolor, markermarker, s150, labelfruit) # 添加置信椭圆 ell patches.Ellipse((coordinates[i, 0], coordinates[i, 1]), width0.3, height0.2, angle0, alpha0.1, colorcolor) plt.gca().add_patch(ell) plt.legend() plt.title(增强版水果口味MDS可视化) plt.grid(True)9. 扩展应用与进阶方向掌握了基础MDS后可以探索以下几个进阶方向1. 非度量MDS(Non-metric MDS)适用于序数尺度数据仅保持距离的单调关系而非数值关系在心理学、市场调研中应用广泛2. 加权MDS为不同维度分配不同权重反映领域知识或专家意见实现特定分析目标3. 大规模数据MDS使用随机采样或分块处理近似算法如Landmark MDSGPU加速实现4. 与其他技术的结合MDS 聚类分析先降维后聚类MDS 分类器降维后构建分类模型MDS 异常检测在低维空间识别异常点# 结合KMeans聚类的示例 from sklearn.cluster import KMeans # 在MDS降维结果上进行聚类 kmeans KMeans(n_clusters2, random_state42) clusters kmeans.fit_predict(coordinates) # 可视化聚类结果 plt.scatter(coordinates[:, 0], coordinates[:, 1], cclusters, cmapviridis) for i, fruit in enumerate(fruits): plt.annotate(fruit, (coordinates[i, 0], coordinates[i, 1])) plt.title(MDS降维后聚类结果)

更多文章