前言:
多维标度分析(multidimensional scaling ,MDS)是一组通过直观的空间图(spatial map),
表示研究对象的感知和偏好的分析方法
核心思想是降维后,点与点之间的欧式距离不变
目录
- 简介
- 算法模型
- 推导过程
- 算法流程
- Code 实例
一 简介
原始空间数据集为 , 为m个k维度行向量
D 为原始空间中样本点之间的欧式距离矩阵
新维度后样本空间为Y
在新的空间中, 样本中心化
得到两个公式:
二 算法模型
原始空间和新的空间中欧式距离不变
求解目标:
三 推导过程
则
式0
式1:
则:
式2,同理:
式3:
把式1,2,3 带入式0,则
因为B 为对称矩阵,可以用一对特征
V 是 特征值
P 是特征向量
因为求的是最大值,求n个大于0的特征值对应的特征向量
四 算法流程
1 计算 矩阵D
为样本 欧式距离
2 计算
3 计算矩阵B
4: 矩阵B特征分解
5: 排序特征值,取最大的n个
6
五 算法实现
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 16 13:25:15 2019
@author: chengxf2
"""
import numpy as np
from sklearn.datasets import load_iris
from sklearn.manifold import MDS
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.ticker import NullFormatter
class MyMDS:
"""
直接用skelean 的库函数实现
Args
n_components: 新的样本维度
return
None
"""
def SklearnMDS(self,n_components):
fun = MDS(n_components)
ReduceData =fun.fit_transform(self.data)
plt.scatter(ReduceData[:,0],ReduceData[:,1],c=self.color)
plt.title('Using sklearn MDS')
"""
加载数据集
Args
None
return
dataList
"""
def LoadData(self):
iris = load_iris()
self.color = iris.target
self.data = iris.data
self.m, self.n = np.shape(self.data)
fig = plt.figure(figsize=(6, 5))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(self.data[:, 0], self.data[:, 1], self.data[:, 2], c=self.color, cmap= plt.cm.cool)
ax.view_init(10, -70)
ax.set_xlabel("$x_1$", fontsize=18)
ax.set_ylabel("$x_2$", fontsize=18)
ax.set_zlabel("$x_3$", fontsize=18)
plt.show()
# self.SklearnMDS(2)
"""
降维
Args
n_components 降维后的新维度,特征值个数
"""
def Train(self,n_components):
m = self.m
B = np.zeros((self.m, self.m))
D = np.zeros((self.m, self.m))
DI = np.zeros(m)
DJ = np.zeros(m)
print("\n 计算欧氏距离矩阵 \n",m)
for i in range(self.m):
x = self.data[i]
xi_j =x-self.data
dist = np.sum(np.square(xi_j),axis=1) ##行方向求和
D[i]= dist.reshape(1,m)
print("\n 计算DI \n")
for j in range(self.m):
DI[j] =np.mean(D[j,:])
DJ[j] = np.mean(D[:,j])
D_IJ = np.mean(D) ##相当于除以sum(D)/m*m
for i in range(self.m):
for j in range(self.m):
#print("DI ",DI[i])
#print("DJ ",DJ[j])
#print("DIJ ",D[i,j])
B[i,j]=(DI[i]+DJ[j]-D[i,j]-D_IJ)/2.0
V,P = np.linalg.eig(B) ##特征值,特征向量
#print("v: ",V)
indexList = np.argsort(-V)[:n_components] ##默认升序排序,这里按照降序排,取最大的几个
i = 0
newX =np.zeros((self.m, n_components)) #降维后的数组
for index in indexList:
lamb = np.sqrt(V[index]).real ##取实部
p = P[:,index].real## 对应的特征向量
newP= p*lamb
newX[:,i]= newP
i=i+1
Tip ="my MDS"
plt.title(Tip, fontsize=14)
plt.scatter(newX[:, 0], newX[:, 1], c=self.color, cmap= plt.cm.cool)
plt.xlabel("$z_1$", fontsize=18)
plt.ylabel("$z_2$", fontsize=18)
plt.grid(True)
def __init__(self):
self.m = 0 #样本的个数
self.n = 0 ##样本的维度
self.newDim = 2 ##样本新维度
self.LoadData()
self.Train(2)
#Test()
mds = MyMDS()
参考文档
西瓜书 第十章
https://www.jianshu.com/p/6efc8283952b