(五)等度量映射(Isomap)

一、问题

低维流形嵌入到高维空间之后,直接再高维空间中计算直线距离具有误导性,因为高维空间中的直线距离在低维嵌入流形上是不可达的。低维嵌入流形上两点间的距离是“测地线”距离,是两点之间的本真距离。直接在高维空间中计算直线距离是不恰当的。
区别

二、解决

如何计算测地线距离呢?流形在局部上与欧氏空间同胚,对于每个点基于欧氏距离找出其近邻点,建立一个近邻连接图(1指定近邻点的个数,k近邻图;2指定距离的阈值, ϵ \epsilon ϵ近邻图),即解决近邻连接图上最短路径的问题(使用Dijkstra或者Floyd算法求最短路径)。由此得到距离矩阵,接下来使用MDS方法来获得样本点在低维空间中的坐标。MDS原理及python实现

三、算法描述

输入:样本集 D = ( x ( 1 ) , x ( 2 ) , . . . x ( n ) ) T ; D=(x_{(1)},x_{(2)},...x_{(n)})^T; D=(x(1),x(2),...x(n))T;
    \qquad \,\,\, 近邻参数 k k k;
    \qquad \,\,\, 低维空间维数 d ′ d^{'} d
输出:样本集 D D D在低维空间中的投影 Z = ( z ( 1 ) , z ( 2 ) , . . . z ( n ) ) T ; Z=(z_{(1)},z_{(2)},...z_{(n)})^T; Z=(z(1),z(2),...z(n))T;
过程:
for i = 1 , 2 , . . n i=1,2,..n i=1,2,..n do
\qquad 确定 x ( i ) T x_{(i)}^T x(i)T k k k近邻, x ( i ) T x_{(i)}^T x(i)T k k k近邻之间的距离设置为欧氏距离,与其他点之间的距离设置为无穷大;
end for
调用最短路径算法计算任意两样本点之间的距离,得到距离矩阵,作为MDS算法的输入;
return      \,\,\,\, MDS算法的输出

四、python实现

# coding:utf-8
import numpy as np
from sklearn.datasets import make_s_curve
import matplotlib.pyplot as plt
from sklearn.manifold import Isomap
from mpl_toolkits.mplot3d import Axes3D

def floyd(D,n_neighbors=15):    #k近邻
    Max = np.max(D)*1000
    n1,n2 = D.shape
    k = n_neighbors
    D1 = np.ones((n1,n1))*Max
    D_arg = np.argsort(D,axis=1) #返回从小到大的索引值,每一列进行排序
    print(D_arg)
    for i in range(n1):
        D1[i,D_arg[i,0:k+1]] = D[i,D_arg[i,0:k+1]]  #找出与i最近的k个数
    for k in range(n1):
        for i in range(n1):
            for j in range(n1):
                if D1[i,k]+D1[k,j]<D1[i,j]:
                    D1[i,j] = D1[i,k]+D1[k,j]  #需再次理解 
    return D1

def cal_pairwise_dist(x):          #任意两点之间距离的平方
    '''计算pairwise 距离, x是matrix
    (a-b)^2 = a^2 + b^2 - 2*a*b
    '''
    sum_x = np.sum(np.square(x), 1)   #square计算各元素平方      1 按行相加  0按列相加
    dist = np.add(np.add(-2 * np.dot(x, x.T), sum_x).T, sum_x)
    #返回任意两个点之间距离的平方
    return dist

def my_mds(dist, n_dims):    #距离矩阵分解,得到降维之后的数据
    # dist (n_samples, n_samples)
    dist = dist**2
    n = dist.shape[0]
    T1 = np.ones((n,n))*np.sum(dist)/n**2
    T2 = np.sum(dist, axis = 1)/n
    T3 = np.sum(dist, axis = 0)/n

    B = -(T1 - T2 - T3 + dist)/2

    eig_val, eig_vector = np.linalg.eig(B)
    index_ = np.argsort(-eig_val)[:n_dims]
    picked_eig_val = eig_val[index_].real
    picked_eig_vector = eig_vector[:, index_]

    return picked_eig_vector*picked_eig_val**(0.5)

def my_Isomap(data,n=2,n_neighbors=30):
    D = cal_pairwise_dist(data)
    D[D < 0] = 0
    D = D**0.5       #距离矩阵
    D_floyd=floyd(D, n_neighbors)     #k近邻之后得到的距离矩阵
    data_n = my_mds(D_floyd, n_dims=n)
    return data_n

def scatter_3d(X, y):
    fig = plt.figure(figsize=(6, 5))
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=y, cmap=plt.cm.hot)
    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()

if __name__ == '__main__':
    X, Y = make_s_curve(n_samples = 500,
                           noise = 0.1,
                           random_state = 42)  #生成S型曲线数据集

    data_1 = my_Isomap(X, 2, 10)    

    data_2 = Isomap(n_neighbors = 10, n_components = 2).fit_transform(X)

    plt.figure(figsize=(8,4))
    plt.subplot(121)
    plt.title("my_Isomap")
    plt.scatter(data_1[:, 0], data_1[:, 1], c = Y)

    plt.subplot(122)
    plt.title("sklearn_Isomap")
    plt.scatter(data_2[:, 0], data_2[:, 1], c = Y)
    plt.savefig("Isomap1.png")
    plt.show()
    
    
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值