gpt4 book ai didi

python - 按相似关系过滤图像列表

转载 作者:行者123 更新时间:2023-12-05 08:51:29 25 4
gpt4 key购买 nike

我有一个图像名称列表和它们的(阈值)相似度矩阵。相似关系是自反和对称的,但不一定是传递性的,即如果 image_iimage_jimage_k 相似,则不需要意味着 image_jimage_k 是相似的。

例如:

images = ['image_0', 'image_1', 'image_2', 'image_3', 'image_4']

sm = np.array([[1, 1, 1, 0, 1],
[1, 1, 0, 0, 1],
[1, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[1, 1, 0, 0, 1]])

相似度矩阵 sm 解释如下:如果 sm[i, j] == 1 那么 image_iimage_j 相似,否则不相似。这里我们看到 image_0 类似于 image_1image_2,但是 image_1image_2 不相似(这只是非传递性的一个例子)。

我想保留最大数量的唯一图像(根据给定的 sm 矩阵,它们都是成对不相似的)。对于此示例,它将是 [image_2, image_3, image_4][image_1, image_2, image_3](通常有多个这样的子集,但我不介意哪个保持它们的最大长度)。我正在寻找一种有效的方法来执行此操作,因为我有数千张图像。

编辑:我原来的解决方案如下

np.array(images)[np.tril(sm).sum(0) == 1]

但是,不能保证它会返回一个最大长度子集。考虑以下示例:

sm = np.array([[1, 1, 0, 0, 0],
[1, 1, 0, 0, 0],
[0, 0, 1, 1, 0],
[0, 0, 1, 1, 1],
[0, 0, 0, 1, 1]])

此解决方案将返回 ['image_1', 'image_4'],而所需的结果是 ['image_0', 'image_2', 'image_4']['image_1', 'image_2', 'image_4']

更新:请参阅我的回答,其中使用图论更详细地解释了问题。我仍然愿意接受建议,因为我还没有找到一种合理快速的方法来获得数千张图像列表的结果。

最佳答案

经过进一步研究,我发现这就是图论中所谓的最大独立集问题,不幸的是NP-hard。

independent set图 G 的 S 是 G 的顶点的子集,因此 S 中的顶点不相邻。在我们的例子中,我们正在寻找最大独立集 (MIS),即具有尽可能多的顶点的独立集。

有几个用于处理图形和网络的库,例如 igraphNetworkX,它们具有查找最大独立集的函数。我最终使用了 igraph。

对于我的问题,我们可以将图像视为图 G 的顶点,将“相似性矩阵”视为邻接矩阵:

images = ['image_0', 'image_1', 'image_2', 'image_3', 'image_4']

sm = np.array([[1, 1, 1, 0, 1],
[1, 1, 0, 0, 1],
[1, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[1, 1, 0, 0, 1]])

# Adjacency matrix
adj = sm.copy()
np.fill_diagonal(adj, 0)

# Create the graph
import igraph
g = igraph.Graph.Adjacency(adj.tolist(), mode='UNDIRECTED')

enter image description here


# Find the maximum independent sets
g.largest_independent_vertex_sets()
[(1, 2, 3), (2, 3, 4)]

enter image description here


enter image description here


不幸的是,这对于成千上万的图像(顶点)来说太慢了。所以我仍然愿意接受有关更快方法的建议(也许不是找到所有的 MIS,而是找到一个)。

注意:@Sergey(更新#1)和@marke 提出的解决方案并不总是返回 MIS——它们是贪婪的近似算法,删除了一个最大度的顶点,直到没有边缘剩余。为了证明这一点,请考虑以下示例:

sm = np.array([[1, 1, 0, 0, 0, 1],
[1, 1, 0, 1, 0, 0],
[0, 0, 1, 1, 1, 0],
[0, 1, 1, 1, 0, 0],
[0, 0, 1, 0, 1, 1],
[1, 0, 0, 0, 1, 1]])

两种解决方案都返回 [3, 5],但对于此示例,最大独立集为两个,[(0, 3, 4), (1, 2, 5)] ,正如 igraph 正确找到的那样。要了解为什么这些解决方案无法找到 MIS,下面是一个 gif,它显示了每次迭代时如何删除顶点和边(这是返回第一次出现的 np.argmax 的“副作用”对于多次出现的最大值):

enter image description here

Sergey 的解决方案(更新#2)似乎可行,但它比 igraph 的 largest_independent_vertex_sets() 慢得多。对于速度比较,您可以使用以下随机生成的长度为 100 的相似度矩阵:

a = np.random.randint(2, size=(100, 100))

# create a symmetric similarity matrix
sm = np.tril(a) + np.tril(a, -1).T
np.fill_diagonal(sm, 1)

# create adjacency matrix for igraph
adj = sm.copy()
np.fill_diagonal(adj, 0)

更新:事实证明,虽然我有数千个图像-顶点,但边的数量相对较少(即我有一个稀疏图),所以使用 igraph 查找 MIS 是可以接受的速度方面。或者,作为折衷方案,可以使用贪婪近似算法来查找大型独立集(如果足够幸运,也可以使用 MIS)。下面是一个看起来相当快的算法:

def independent_set(adj):
'''
Given adjacency matrix, returns an independent set
of size >= np.sum(1/(1 + adj.sum(0)))
'''
adj = np.array(adj, dtype=bool).astype(np.uint8)
np.fill_diagonal(adj, 1) # for the purposes of algorithm

indep_set = set(range(len(adj)))
# Loop until no edges remain
while adj.sum(0).max() > 1:
degrees = adj.sum(0)
# Randomly pick a vertex v of max degree
v = random.choice(np.where(degrees == degrees.max())[0])
# "Remove" the vertex v and the edges to its neigbours
adj[v, :], adj[:, v] = 0, 0
# Update the maximal independent set
indep_set.difference_update({v})
return indep_set

或者更好的是,我们可以获得一个最大独立集:

def maximal_independent_set(adj):  
adj = np.array(adj, dtype=bool).astype(np.uint8)
degrees = adj.sum(0)
V = set(range(len(adj))) # vertices of the graph
mis = set() # maximal independent set
while V:
# Randomly pick a vertex of min degree
v = random.choice(np.where(degrees == degrees.min())[0])
# Add it to the mis and remove it and its neighbours from V
mis.add(v)
Nv_c = set(np.nonzero(adj[v])[0]).union({v}) # closed neighbourhood of v
V.difference_update(Nv_c)
degrees[list(Nv_c)] = len(adj) + 1
return mis

关于python - 按相似关系过滤图像列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59907662/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com