简体   繁体   English

如何在Python中创建图像的KNN图形(使用用户定义的距离度量)?

[英]How do I create KNN graph for images in Python (with user-defined distance metric)?

I would like to create a k-nearest neighbors graph for the images in the MNIST digits dataset, with a user-defined distance metric - for simplicity's sake, the Frobenius norm of A - B. 我想为MNIST数字数据集中的图像创建一个k-最近邻图,使用用户定义的距离度量 - 为简单起见,A - B的Frobenius范数。

sklearn.neighbors.kneighbors_graph provides a nice interface, but doesn't allow for matrix-valued data -- eg when I try to make the graph as follows: sklearn.neighbors.kneighbors_graph提供了一个很好的接口,但不允许矩阵值数据 - 例如当我尝试按如下方式制作图形时:

from torchvision.datasets import MNIST
import sklearn

# Define distance metric for matrices
metric_func = lambda X, Y: norm(X - Y, ord='fro')

data = MNIST('sample_data', train=True, transform=None, target_transform=None, download=True)        

adj_matrix = sklearn.neighbors.kneighbors_graph(
        data.data, 
        n_neighbors=5, 
        mode='connectivity',
        metric=metric_func, 
        p=2, 
        metric_params=None, 
        include_self=False, 
        n_jobs=None
    )

I get the error: 我收到错误:

ValueError: Found array with dim 3. Estimator expected <= 2.

I could write my own 'kneighbors_graph()` method but it would probably involve double for loops and lots of inefficiency. 我可以编写自己的'kneighbors_graph()`方法,但它可能涉及双循环和许多低效率。 Is there an efficient way to create this graph in Python? 有没有一种在Python中创建此图的有效方法?

It's quite simple, it expects a 2D (2 dimensional) array as input for X: 这很简单,它期望2D(2维)数组作为X的输入:

https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.kneighbors_graph.html https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.kneighbors_graph.html

Have you provided it one? 你提供了一个吗? Check, what does data.data.shape return? 检查data.data.shape返回什么?

Flatten the images 展平图像

from sklearn import datasets
from sklearn.neighbors import kneighbors_graph

digits = datasets.load_digits()
images = digits.data.reshape(-1, 8, 8)

distances = kneighbors_graph(images.reshape(-1, 64), 5, mode='distance', include_self=True, metric='euclidean')
distances =  distances.todense()

# Test
i = 11
print ("Actual Image: {0}, Nearest 5 Images: {1}".format(
    digits.target[i], digits.target[distances[i].nonzero()[1]]))

Output: Actual Image: 1, Nearest 5 Images: [1 1 1 1] 输出: Actual Image: 1, Nearest 5 Images: [1 1 1 1]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM