gSpan简介
gSpan是一种频繁子图挖掘技术,是基于深度优先遍历的。这里的深度优先是指的在子图扩展时采用的策略。
论文:gSpan: Graph-Based Substructure Pattern Mining
Technical Report :gspan: Graph-based substructure pattern
mining.
原有方法存在的不足
产生大量的候选。gspan不产生候选,
子图同构是NP-hard问题
gspan的
gspan只考虑了连通的子图。
对于大图,可以先对图进行划分,在进行gspan。
在label较少或无label时,会导致候选集过多。
gSpan
输入:图流 ,标签图
输出
算法可以分为两部分,第一部分相当于预处理,第二部分是进行递归挖掘。下图为论文中的算法流程。第一部分的预处理是指的第1到第5步,剩下的是第二部分。
第一部分 预处理
gspan输入的是一个图,图中的边和节点是有标签的。
首先是对图进行剪枝(对应算法流程中的1-2)。对节点和边根据频率进行排序,根据预先设定的阈值,移除频率较低的节点和边。得到一个新的图G。频率高低是根据边上的标签来进行统计的。
重新标记(对应算法流程中的3)。对上述的图G进行重新标记,标记的规则是按照频率高低来的,即频率越高,标记的标签对应的字母序越低。此外,还需要保存原始标签和新标签之间的映射关系。在后序的描述中,标签都是指的新标签。
获得边集合(对应算法流程中的4-5)。将频率较高的边组成一个集合E。这里可以认为是将图G中的所有边组成一个集合E。并按照字母序对集合E中的边进行排序,也就是按照边的频率进行排序。字母序越低,频率越高,对应的边排序越靠前 。
我们是要获得图中频率的子图,而边也是一种特殊的子图。集合E中的边可以认为是最简单的频繁子图。之后的频繁子图挖掘都是基于这些频繁的边来进行递归挖掘的。
第二部分 递归挖掘
这是gspan中最难以理解的一部分,首先给出这部分的一个整体框架。
核心想法:先扩展,扩展后满足要求,则继续进行扩展。
# 假设给定一个频繁子图A
def f(A) #递归挖掘函数 对子图A进行递归挖掘
判断 子图A是否满足 最小DFS编码
若满足 对A进行最右路扩展,得到B
判断 子图B是否满足支持度 # 这里就是判断子图是否是频繁的
若满足 则 递归调用f对B进行递归挖掘
在频繁子图挖掘过程中,支持度是需要满足向下覆盖的,即频繁子图C的所有子图都是频繁子图。
上面的伪代码是从一个频繁子图开始的,首先假设了一个频繁子图,然后在该图的基础上进行递归扩展。那么如何得到最初假设的频繁子图呢?这就用到了第一部分中得到的频繁边集合E。
第二部分递归扩展,可以认为是,对于集合E中的每一条边,进行上述的递归扩展。
遍历集合E 对于其中的每一条边e
f(e)
在递归挖掘中中,涉及到两个判断,一个是判断当前子图是否满足最小DFS编码;另一是判断子图是否满足支持度。
DFS编码判断
DFS编码这里的作用是对子图进行标号。
一个子图,可能有多种生成方式。这里的生成方式是指,从一条边进行递归扩展得到该子图。
为了避免对同一个子图进行多次扩展,就使用DFS编码对子图进行编码,使得每个子图只扩展一次。对于不满足最小DFS编码的子图K,则停止对其的扩展,并返回到扩展K之前的状态。
这里只需要明白DFS编码的作用,即唯一标识一个子图,避免对同一个子图重复进行扩展。更详细的DFS编码在后面进行阐述。
这里使用了“扩展”这个词,为了避免歧义进行下解释,停止扩展 对应流程中可以认为是 停止了递归挖掘,但挖掘首先需要进行扩展,这里说停止扩展更准确一些。
支持度判断
gspan算法是去找图中频繁的子图,如何衡量一个子图是否频繁,就是通过支持度来判断的。
如果子图满足支持度,那么认为该子图是频繁的,是我们想要的一个结果,那么就在该子图的基础上继续进行扩展。这也就是递归扩展的递归所在,gspan是基于深度优先遍历,也是根据这里来的。
深度优先遍历是说,沿着一条路,一直走,直到不能走为止。这里扩展也是,如果当前子图是频繁的,那么就在该子图的基础上继续进行扩展,直到不能扩展。但这里扩展的规则并不是按照深度优先遍历的顺序,只是采用了深度优先遍历的思想,扩展方式是基于最右路扩展的,后面会进行阐述。
如果子图不满足支持度,那么当前的子图就不是我们要的子图,那么也是停止当前的扩展,回到前一阶段。
解释到这里,应该对算法的整个流程有了个大概的认识,再简单的描述一下。首先得到一个频繁的边的集合,然后对于集合中的每一条边,进行递归扩展。扩展的过程分为三步,首先判断是否满足最小的DFS编码;如果满足则进行最右路扩展;对于扩展后的新的子图判断其是否满足支持度,如果满足,则基于新的子图继续进行递归扩展。
下面解释其中的一些概念,包括:DFS编码、支持度、最右路扩展等。
概念解释
论文中主要解释的是DFS编码,以及对应的扩展方式,即最右路扩展。
DFS编码
图是无向的,只是遍历顺序是有向的
对于给定的图,以及某次深度优先遍历,可以得到唯一的深度优先遍历树T,将节点按照比遍历的顺序进行标号,则树T中的边应该都是从标号小的节点到标号大的节点,这种边成为前向边,边上标号是从大到小的是后向边,后向边不是树T中的边。
两条边的比较是通过三个规则来比较,如下图。但结合深度优先遍历来解释,则先遍历的边大于后遍历的边。
图上的一次深度优先遍历,会访问所有的节点,但不会访问所有的边,只会遍历T上的边。最后的DFS编码也是指的树T上的边,而不是图中所有的边。
DFS编码是指的树T上的边,按照遍历的顺序进行排序,得到的边序列。
不同的遍历只会影响节点的id,不影响节点的label和边的label。
前项边的起点一定是最右路上的终点,终点是最右路上的某个点;后向边的起点是最右路上的任意一个节点
支持度
单个图的支持度
多个图的支持度
最右路扩展
为什么是最右路?
最右路扩展是根据深度优先遍历而来的,保证了当图满足父子关系时(即子图与超图),对应的编码也满足包含关系,即子图对应的编码是超图的一部分。