isomap算法 python实现

isomap算法主要流程:

1:构建邻接图G:基于输入空间X中流形G上的的邻近点对i,j之间的欧式距离dx (i,j),选取每个样本点距离最近的K个点(K-Isomap)或在样本点选定半径为常数ε的圆内所有点为该样本点的近邻点,将这些邻近点用边连接,将流形G构建为一个反映邻近关系的带权流通图G;

2:计算所有点对之间的最短路径:通过计算邻接图G上任意两点之间的最短路径逼近流形上的测地距离矩阵DG={dG(i,j)},最短路径的实现以Floyd或者Dijkstra算法为主。

3:构建k维坐标向量:根据图距离矩阵DG={dG(i,j)}使用经典Mds算法在d维空间Y中构造数据的嵌入坐标表示,选择低维空间Y的任意两个嵌入坐标向量yi与yj使得代价函数最小。

下面是python实现的代码:

import numpy as np
import matplotlib.pyplot as plt
import sys

def distancematrix(test):
    leng=len(test)
    resmat=np.zeros([leng,leng],np.float32)
    for i in range(leng):
      for j in range(leng):
          resmat[i,j]=np.linalg.norm(test[i]-test[j])
    return resmat #返回距离矩阵
def mds(test,deg):
    length= len(test)
    re= np.zeros((length, length),np.float32)
    if(deg>length):
        deg=length
    D= distancematrix(test)
    ss = 1.0 /length ** 2 * np.sum(D ** 2)
    for i in range(length):
        for j in range(length):
            re[i, j] = -0.5 * (D[i, j] ** 2 - 1.0 / length * np.dot(D[i, :], D[i, :]) - 1.0 / length * np.dot(D[:, j], D[:, j]) + ss)

    A, V = np.linalg.eig(re)
    list_idx = np.argpartition(A, deg- 1)[-deg:]
    a = np.diag(np.maximum(A[list_idx], 0.0))
    return np.matmul(V[:, list_idx], np.sqrt(a))
# 使用 Dijkstra 算法获取最短路径,并更新距离矩阵
# test: 距离矩阵,大小 m * m
# start:最短路径的起始点,范围 0 到 m-1
def usedijk(test, start):
    count = len(test)
    col= test[start].copy()
    rem = count - 1
    while rem > 0:
        i= np.argpartition(col, 1)[1]
        length = test[start][i]
        for j in range(count):
            if test[start][j] > length + test[i][j]:
                test[start][j] = length + test[i][j]
                test[j][start] = test[start][j]
        rem -= 1
        col[i] = float('inf')

# isomap 算法的具体实现
# test:需要降维的矩阵
# target:目标维度
# k:k 近邻算法中的超参数
# return:降维后的矩阵
def isomap(test, target, k):
    inf = float('inf')
    count = len(test)
    if k >= count:
        raise ValueError('K is too large')
    mat_distance = distancematrix(test)
    knear = np.ones([count, count], np.float32) * inf
    for idx in range(count):
        topk = np.argpartition(mat_distance[idx], k)[:k + 1]
        knear[idx][topk] = mat_distance[idx][topk]
    for idx in range(count):
        usedijk(knear, idx)
    return mds(knear, target)

if __name__ == '__main__':
    print('开始降维.....')
    D =np.array([[1,2,3,4],[2,1,5,6],[3,5,1,7],[4,6,7,1]]) #test data
    outcome= isomap(D, 2, 3)
    sys.stdout.write('降维完成\n')
    print(outcome) 


猜你喜欢

转载自blog.csdn.net/m0_37783096/article/details/79704621