数据降维-MDS 算法

多维尺度分析(MDS)是一种数据降维方法,它通过距离矩阵将高维数据转换为低维空间表示,保持对象间的相对距离。算法包括距离平方矩阵构建、点积矩阵计算、特征分解等步骤,并可通过Python的sklearn库实现。文章提供了MDS的详细步骤和代码示例。
摘要由CSDN通过智能技术生成

数据降维-MDS 算法

算法概述

MDS的初衷是将图结构中的距离在空间的一种表示

例如,已知几个城市的距离,但是不知道城市的坐标,那么MDS就能通过距离矩阵转换成空间坐标向量来近似描述距离。更重要地是,MDS可以更广泛地应用于任意类型的数据实体相似度或距离描述在低维空间的表示

多维尺度分析MDS的基本思想:

用低维空间 R k R^k Rk ( k < n ) (k<n) (k<n)的n个点去重新标度高维空间 R n R^n Rn的n个实体间的距离或者相似度。将高维空间的n个研究对象简化到低维空间处理,并且保留高维空间中的n个对象的较高的相似度。

算法步骤

  • 输入D
  • D的所有元素取原值的平方,得距离平方矩阵 Δ \Delta Δ
  • 构造单位矩阵 E E E和全1矩阵 U U U
  • 计算点积矩阵 S = − 1 / 2 ( E − U / n ) Δ ( E − U / n ) S=-1/2 (E - U/n)\Delta (E - U/n) S=1/2(EU/n)Δ(EU/n)
  • 对S进行特征分解 S = Q ∑ 2 Q T S = Q\sum^2 Q^T S=Q2QT
  • 选取前k个最大的特征值的根号值 ∑ k \sum k k和正交特征向量 Q k Qk Qk
  • 降维表示 D k = ∑ k Q k T Dk = \sum_k Q^T_k Dk=kQkT

算法证明

M D S MDS MDS 是一种基于距离度量的数据降维方法,要求将高维度数据$X \ \in R^(d \times m) 转化为低维数据 转化为低维数据 转化为低维数据Z \in R^{(d \times m)} $后,样本点间相对位置关系不变。所以将目标函数(也可以理解为相似度):
a i m = ∑ m i n ( ∣ ∣ z i − z j ∣ ∣ − d i j ) 2 aim = \sum_{min} (||z_{i} - z_{j}|| - d_{ij})^2 aim=min(∣∣zizj∣∣dij)2
在上式子中,低维样本 z i z_i zi z j z_j zj之间的欧式距离。 d i j d_{ij} dij表示高维样本 X i X_i Xi X j X_j Xj之间的距离,距离的度量方法任意但需要满足以下三个条件:

  1. d i i = 0 d_{ii} = 0 dii=0
  2. d i j = d j i d_{ij} = d_{ji} dij=dji
  3. d i k + d j k ≥ d i j d_{ik} + d_{jk} \geq d_{ij} dik+djkdij

如何通过上面的目标函数求解出 Z Z Z

直接求解出Z比较困难,转而求 B = Z T Z B = Z^TZ B=ZTZ

Z ∈ R d ′ × m Z \in R^{d' \times m} ZRd×m

B ∈ R m × m B \in R^{m\times m} BRm×m

这里B是一个实对称矩阵,如果能够求得B,那么:
B = U Λ U T = ( Λ 1 2 U T ) T ( Λ 1 2 U T ) = Z T Z B = U \Lambda U^T = (\Lambda^{\frac{1}{2}} U^T)^T (\Lambda^{\frac{1}{2}U^T}) = Z^TZ B=UΛUT=(Λ21UT)T(Λ21UT)=ZTZ
其中 U U U是特征向量, Λ \Lambda Λ是特征值。

在对所求目标进行转化后,并求出以下等式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ta1VG44u-1673537035590)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E5%9B%BE%E7%89%871.png)]

下面我们来对每一步等式做证明:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJVGa3ha-1673537035591)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E5%9B%BE%E7%89%872.png)]

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RnFnnRJD-1673537035593)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E5%9B%BE%E7%89%874.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NAQacDSo-1673537035594)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E5%9B%BE%E7%89%875.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JMduMlAV-1673537035594)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E5%9B%BE%E7%89%876.png)]

证明得到上述的等式后,我们可以根据多项式进行求解B:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uk9gQNyx-1673537038030)(null)]

image-20230112231136146

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ULzWsHbC-1673537035597)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E5%9B%BE%E7%89%877.png)]

到这里已经求得了特征值和特征向量。后面要做的就是对求取的Z做SVD分解,这部分的原理可以参考SVD 理解使用

代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import MDS

def getData():
  data = np.loadtxt("./iris.data", dtype="str", delimiter=",")
  arr = data[:,:-1]
  label = data[:,-1]
  arr = np.float32(arr)
  return arr, label

def cal_distance(vecs, type = 0):
  N, m = vecs.shape
  dist = np.zeros([N, N])
  for i in range(N):
    for j in range(N):
      # 计算汉明距离
      # dist[i, j] = np.sum( np.abs(vecs[i] - vecs[j]))
      # 计算欧式距离
      dist[i, j] = np.sqrt(np.sum( (vecs[i] - vecs[j]) ** 2))
  return dist

def my_mds(D, dims):
  m = len(D)
  D = D ** 2
  t2 = np.sum(D, axis=1, keepdims=True) / m
  t3 = np.sum(D, axis=0, keepdims=True) / m
  t4 = np.sum(D) / m**2
  B =   - (D - t2 - t3 + t4) / 2
  eig_val, eig_vector  = np.linalg.eig(B)
  index_  = np.argsort(-eig_val)[:dims]
  simple_vector = eig_vector[:,index_]
  simple_val = eig_val[index_]
  reduced_vector = simple_vector *  simple_val ** 0.5
  return reduced_vector

def draw(data_2d, labels):
  unque_labs = np.unique(labels)
  unque_labs = unque_labs.tolist()
  colors = [plt.cm.Spectral(each)
    for each in np.linspace(0, 1,len(unque_labs))]
  nodes_color = [colors[unque_labs.index(i)] for i in labels]
  plt.scatter(data_2d[:,0], data_2d[:,1], c=nodes_color)

if __name__ == '__main__':
  arr, label = getData()
  dist = cal_distance(arr)
  data_2d = my_mds(dist, 2)
  draw(data_2d, label)
  plt.show()
  plt.savefig("./欧式距离.png")

其中用到的数据集是:
在这里插入图片描述
运行结果:
请添加图片描述

参考

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值