Python实现的图相似度评分算法

24

我正在寻找一个Python实现的算法,它执行以下任务:

给定两个可能包含循环的有向图及其根节点,生成两个图相似度的分数。

(类似Python中difflib对两个序列所执行的方式)

希望这样的实现已经存在。否则,我将尝试自己实现算法。在这种情况下,哪种算法更简单易懂?

算法的工作方式对我来说并不重要,但它的复杂性很重要。 另外,只要可以用这个数据结构表示我描述的图形,使用不同数据结构的算法也是可以接受的。

我强调,有实现会更好。

编辑:
似乎同构算法与此无关。建议使用图编辑距离更加切合要求,这将缩小我的搜索范围,只需一个能够执行图编辑距离将图缩减为树然后执行树编辑距离的解决方案。
节点本身由几行汇编代码组成。


1
“相似性”对我来说有点模糊。有没有我不知道的适用于有向图的相似性的普遍含义? - John La Rooy
你是否查看过各种Python图形库,以查看它们是否已经实现了某些功能? - Martijn Pieters
@gnibbler 谢谢您的回复。我所说的相似性是指以下内容:如果两个图形之间存在双射(同构),则它们是相等的。如果它们的编辑距离较低,则它们是相似的。如果它们都有一个最大公共子图,那么它们在某种程度上是相似的,依此类推... [链接] (http://lees-web.mit.edu/lees/presentations/LauraZager.pdf) - YaronK
@YaronK 除非它们被标记,否则每两个非空图形都有一个最大公共子图。 - Qnan
1
@MartijnPieters 我已经考虑了NetworkX和igraph。它们都允许检查同构性,无论是否存在,但它们都不允许量化相似性。 - YaronK
4个回答

16

另一种方法是使用称为特征向量相似度的方法。基本上,您需要计算每个图的邻接矩阵的拉普拉斯特征值。对于每个图,找到最小的k,使得k个最大特征值的总和至少占所有特征值总和的90%。如果两个图的k值不同,则选用较小的值。然后,相似性指标是两个图之间最大的k个特征值之间平方差的总和。这将产生一个在[0,∞)范围内的相似度度量,数值越接近零表示越相似。

例如,如果使用networkx

def select_k(spectrum, minimum_energy = 0.9):
    running_total = 0.0
    total = sum(spectrum)
    if total == 0.0:
        return len(spectrum)
    for i in range(len(spectrum)):
        running_total += spectrum[i]
        if running_total / total >= minimum_energy:
            return i + 1
    return len(spectrum)

laplacian1 = nx.spectrum.laplacian_spectrum(graph1)
laplacian2 = nx.spectrum.laplacian_spectrum(graph2)

k1 = select_k(laplacian1)
k2 = select_k(laplacian2)
k = min(k1, k2)

similarity = sum((laplacian1[:k] - laplacian2[:k])**2)

1
这看起来非常有趣,@ESultanik,你有这种方法的参考论文吗?谢谢! - Lucien S.
1
@Rodolphe 这是一份学生报告,但它作为一个相对不错的介绍/调查。 - ESultanik
你能想到一种规范化相似性方法的方式,以便它可以检测近似子图吗?例如,如果G1有100个节点和200条边,而G2只有5个节点和7条边,您需要通过节点和边数的差异函数来调整相似度阈值。 - Andrew
你好@ESultanik!我对这个非常感兴趣,并尝试在R中实现它。请参见pastebin链接:http://pastebin.com/W320mYBx。如果running_total/total >=0.9,为什么要返回i+1?为什么要加一?对于我的代码,有时会得到NA,有时会得到1.286。我不明白为什么它不会每次给我相同的答案?这是使用R编程语言中的igraph - 因此需要require(igraph)。 - lrthistlethwaite
1
是的,@ESultanik!!! 谢谢你提醒我你的实现是用Python完成的!你太棒了 - 谢谢!! - lrthistlethwaite
显示剩余4条评论

4
我们最终采用的算法是描述在:"化合物匹配的启发式算法"中。
我们使用NetworkX来表示图形并查找最大团。
编辑:
基本上,您创建一个新图形,每个节点(v)代表从图A(a)到图B(b)的节点可能配对。
如果在您的应用程序中,两个节点(a,b)相似或不相似,则从对应于不相似配对(a,b)的新图中删除节点(v)。 如果它们不矛盾,则连接两个节点与一个边缘。例如,配对(a,b)和(a,c)互相矛盾(请参阅文章以获取正式定义)。 然后,在新图中查找具有最大节点数量的团。
如果在您的应用程序中,两个节点的相似性不是二进制的,则在范围内为新节点分配权重(例如(0,1))。 可以根据启发式方法删除相似度等级低于预定义阈值的新节点。 然后,在新图中查找具有最大权重的团(分配权重的节点的总和)。
无论哪种方式,您都可以通过生成相似度等级来完成:团的大小/总权重除以原始图形的属性函数(A和B的大小/权重的最大/最小/平均值)。
一个好的特性是,您可以从找到的团中推断出相似性的“来源”-“更强”的配对。
进一步澄清: 约束取决于应用程序。我们使用该方法来比较函数控制流图的成对。通常,该方法找到第一个图形中某些节点与第二个图形中某些节点的匹配(子图到子图)。关联图中的每个节点都表示第一个图形中单个节点与第二个图形中单个节点的可能匹配。由于最终选择了一个团体(节点的子集),因此边缘意味着两个匹配不互相矛盾。要应用于不同的应用程序,请询问可能配对的标准是什么(或者我创建了哪些节点),以及选择一个配对如何影响选择另一个配对(或者如何连接边缘节点)。

1
太棒了,我正在寻找这样的算法。你介意分享一下吗? - Lucien S.
我很难理解为什么(a,b)和(a,c)相互矛盾。为什么a不能与多个节点配对?我尝试用R转录上面的算法,但我卡在了矛盾阶段。@YaronK能帮忙吗?这是一个pastebin链接:http://pastebin.com/ua5XrTG0 - lrthistlethwaite
如果节点“a”与节点“b”匹配,并且“b”是不同于“c”的节点,则“a”不能与“c”匹配。一个节点只能与另一个图中的单个节点匹配。 - YaronK
这是你方法的先决条件,不是吗 - 因为它适用于化学结构?实际上,我想在蛋白质相互作用图中使用这个算法,在这种情况下,允许蛋白质A与B和C都发生相互作用,等等。这有意义吗?那么,对于PPI来说,这个算法仍然有用吗?我不确定。 - lrthistlethwaite
@areyoujokingme 我已经编辑了答案并尝试回答你的问题。我希望这样可以澄清事情。 - YaronK

4
这是一个旧问题,但我想分享我的方法。我有一个CVRP(容量车辆路径问题)任务。我的启发式算法生成了几个不同的图表来寻找解决方案。 为了避免陷入局部最优解,我使用了一个放松和修复的过程。
在这一点上,我必须过滤掉太相似的解决方案。由于大多数启发式方法使用局部搜索过程中邻域的系统变化来提供解决方案,因此对我而言,Levenshtein距离非常适合。Levenshtein算法的复杂度为O(n*m),其中n和m是两个字符串的长度。因此,通过对图形节点和路线进行字符串表示,我能够找出相似之处。编辑操作可以被认为是邻域操作,因此它可以被认为是搜索空间距离(而不是解决方案空间距离)。
一个更好/更通用的方法是使用牺牲一些速度的Needleman-Wunsch算法。 Needleman-Wunsch是一种混合相似度测量,它概括了Levenshtein距离,并考虑了两个字符串之间的全局对齐。具体而言,它通过为每个输入字符串之间的对齐分配分数来计算,并选择最佳对齐的分数,即最大分数。两个字符串之间的对齐是它们字符之间的一组对应关系,允许存在空位。
例如:
import py_stringmatching as sm
nw = sm.NeedlemanWunsch(gap_cost=0.5, sim_func=lambda s1, s2: (0.0 if s1 == s2 else 1.0))
print('\nNeedleman-Wunsch: ', nw.get_raw_score('045601230', '062401530'))

在这个例子中,你可以使用自定义的Levenshtein算法。
快速实现Levenshtein算法存在于Git中(使用Cython、Numpy等)。 一个好用的库是py_stringmatching,其中包含以下相似性算法列表:
- Affine Gap - Bag Distance - Cosine - Dice - Editex - Generalized Jaccard - Hamming Distance - Jaccard - Jaro - Jaro Winkler - Levenshtein - Monge Elkan - Needleman Wunsch - Overlap Coefficient - Partial Ratio - Partial Token Sort - Ratio - Smith-Waterman - Soft TF/IDF - Soundex - TF/IDF - Token Sort - Tversky Index

如果我们使用这种方法,首先要将图形转换为字符串,对吗?像[node1[node2,node3[node4,node5]]]这样的格式? - agenis
是的,正确的,你需要有一个字符串表示。 - Panos Kalatzantonakis
1
Networkx有一些有用的函数。https://networkx.github.io/documentation/latest/reference/convert.html - Panos Kalatzantonakis
这与您的问题有关吗?https://stackoverflow.com/q/54253477/266068 - Panos Kalatzantonakis
1
发布一个问题并提供详细信息,我会尽力帮助。 - Panos Kalatzantonakis
显示剩余2条评论

1

我认为你定义相似性的方式不是很标准,因此可能更容易找到同构检查、图编辑距离和最大公共子图的实现,然后自己组合。

然而,需要理解计算这样的相似度量可能是昂贵的,因此如果有很多图形,您可能需要先进行某种筛选。

igraph 例如可以检查同构。

编辑:实际上,您可能只需要编辑距离,因为MCS的存在通常是无关紧要的,正如我上面指出的那样,如果编辑距离为0,则两个图形将是同构的。


谢谢您的回复。关于图形编辑距离或最大公共子图,您是否熟悉任何Python实现算法来尝试解决这些问题(最好不要太昂贵)? - YaronK
@YaronK 任何精确的图形编辑距离算法都会很昂贵,即非多项式,因为该问题至少与图同构问题一样困难。http://en.wikipedia.org/wiki/Graph_isomorphism_problem。我不知道是否有这样的算法实现,但很想看到一个。 - Qnan
@YaronK 看起来文献中描述了许多高效的近似解决方案,适用于某些类型的图形。你所看的是哪些呢? - Qnan
@YaronK 这意味着节点带有语句和/或函数名称标签,对吗? - Qnan
每个节点实际上是一些连续的汇编指令。这有帮助吗? - YaronK
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接