Функция кодирования Isomap (& MDS), использующая только numpy и scipy in python - PullRequest
1 голос
/ 25 апреля 2020

Я закодировал функцию Isomap, начиная с вычисления матрицы евлидовых расстояний (используя scipy.spatial.distance.cdist), затем на основе метода K-ближайших соседей и алгоритма Дейкстры (для определения кратчайшего пути). Я вычислил полное расстояние Матрица по всем путям, наконец, я сделал вычисления карты, следуя сокращению размерности. НО, я хочу использовать epsilon вместо K-ближайших соседей, как показано ниже:

Y = isomap (X, epsilon, d)

• X - матрица n × m, которая соответствует до n точек с m атрибутами.

• epsilon - анонимная функция матрицы расстояний, используемая для нахождения параметров окрестности. (Граф окрестностей должен быть сформирован путем исключения ребер, ширина которых больше эпсилона полного графа расстояний.)

• d - это параметр, который обозначает выходной размер.

• Y - это матрица n × d, которая обозначает вложение, являющееся результатом isomap.

СПАСИБО заранее

import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist


def distance_Matrix(X):
    return cdist(X,X,'euclidean')

def Dijkstra(h):
    q = h.copy()
    for i in range(ndata):
        for j in range(ndata):
            k = np.argmin(q[i,:])
            while not(np.isinf(q[i,k])):
                q[i,k] = np.inf
                for l in neighbours[k,:]:
                    possible = h[i,l] + h[l,k]
                    if possible < h[i,k]:
                        h[i,k] = possible
                k = np.argmin(q[i,:])
    return h

def MDS(D,newdim=2):  

    n = D.shape[0]
    # Torgerson formula
    I = np.eye(n)
    J = np.ones(D.shape)
    J = I-(1/n)*J
    B = (-1/2)*np.dot(np.dot(J,D),np.dot(D,J))  # B = -(1/2).JD²J

    # 
    eigenval, eigenvec = np.linalg.eig(B)
    indices = np.argsort(eigenval)[::-1]   
    eigenval = eigenval[indices]
    eigenvec = eigenvec[:, indices]

    # dimension reduction
    K = eigenvec[:, :newdim]
    L = np.diag(eigenval[:newdim])  
    # result
    Y = K @ L **(1/2)    
    return np.real(Y)

def isomap(data,newdim=2,K=12):

    ndata = np.shape(data)[0]
    ndim = np.shape(data)[1]

    d = distance_Matrix(X)

    # replace begin 
    # K-nearest neighbours
    indices = d.argsort()
    #notneighbours = indices[:,K+1:]
    neighbours = indices[:,:K+1]
    # replace end

    h = np.ones((ndata,ndata),dtype=float)*np.inf
    for i in range(ndata):
        h[i,neighbours[i,:]] = d[i,neighbours[i,:]]
    h = Dijkstra(h)
    return MDS(h,newdim)
...