MDS降维_机器学习

前言:

     多维标度分析(multidimensional scaling ,MDS)是一组通过直观的空间图(spatial map),

 表示研究对象的感知和偏好的分析方法

     核心思想是降维后,点与点之间的欧式距离不变

目录

  1.     简介
  2.     算法模型
  3.     推导过程
  4.    算法流程
  5.    Code 实例

一 简介

     原始空间数据集为X \in R^{m*k} , 为m个k维度行向量

     X=[x_1,x_2,...x_m]^T

     D 为原始空间中样本点之间的欧式距离矩阵 D \in R^{m*m}

 

     新维度后样本空间为Y

     B=YY^T

    \begin{bmatrix} y_1y_1^T & y_1y_2^T& ... & y_1y_m^T \\ ... & ... & &... \\ ... &... & &... \\ y_my_1^T & y_my_2^T& ... & y_my_m^T \end{bmatrix}

 

    在新的空间中, 样本中心化

   \sum_{i=1}^{m}y_i=0

   得到两个公式:

   \sum_{i}B_{ij}=\sum_{i=1}^{m}y_iy_j^T=y_j^T\sum_{j=1}^my_i=0

 \sum_{j} B_{ij}=\sum_{j}y_iy_j^T=y_i\sum_{j} y_j ^T=0

    

     二 算法模型

        原始空间和新的空间中欧式距离不变

        D_{ij}=||y_i-y_j||^2

      求解目标:

         Y

 

 

    三   推导过程

       D^2_{ij}=(y_i-y_j)(y_i- y_j)^T

          =y_iy_i^T+y_jy_j^T-2y_iy_j^T

         =B_{ii}+B_{jj}-2B_{ij}

      则

      B_{ij}=\frac{1}{2}(B_{ii}+B_{jj}-D^2_{ij})  式0

       

      

    式1: 

     \sum_{i}^{m} D_{ij}^2=\sum_{i}B_{ii} +\sum_{i}B_{jj}-2\sum_{i}B_{ij}

        =tr(B)+mB_{jj}  

     则:

      

 

   式2,同理:

     \sum_{j} D_{ij}^2=tr(B)+mB_{ii}

 

  式3:

   \sum_{i}\sum_j D^2_{ij}=\sum_{i}(trB)+\sum_{i}mB_{ii}

       =mtr(B)+mtr(B)

         =2mtr(B)

 

   

      

把式1,2,3 带入式0,则

  B_{ij}=\frac{1}{2}(\frac{D_i^2+D_j^2}{m}-\frac{1}{m^2}(\sum_{i}\sum_{j}D_{ij}^2)-D_{ij}^2)

 

 因为B 为对称矩阵,可以用一对特征

 B=YY^T = P V P^T

 V 是 特征值

P 是特征向量

YY^T= PV^{1/2} (PV^{1/2})^T

 Y=PV^{1/2}

 

 因为求的是最大值,求n个大于0的特征值对应的特征向量


四  算法流程

     1 计算 矩阵D 

            D_{ij}   为样本 x_i, x_j 欧式距离

       2   计算

           D_i^2,D_j^2 ,\sum_i \sum_j D_{ij}^2

     3 计算矩阵B

     4: 矩阵B特征分解

     5: 排序特征值,取最大的n个

     6  Y=PV^{1/2}


五  算法实现

     

 

        

        

# -*- 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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值