1.序列挖掘的概念
在Apriori算法进行频繁集关联分析时,数据集D中的每一条记录是无序的,即比如:
购买物品 |
豆浆机、面包、牛奶 |
黄豆、面包、牛奶 |
这个数据集可以最终得到(面包,牛奶)的频繁集,并且可以得到面包->牛奶和牛奶->面包的关联规则。
它在乎的是每一条记录中频繁同时出现的某些项,而不在乎每一条记录的时间,也不在乎记录的顺序。所以得不到:用户在第一天购买了豆浆机,所以他第二天可能会购买一些黄豆,这样的结论。
而为了对含有时间的数据集进行挖掘,就有了序列挖掘理论的诞生。
序列挖掘,假定有一个数据集D,它含有n个序列Sequence,Sequence由多个事件组成,Sequence中的多个事件是时间有序的。可以认为事件号(eventid)更大的事件在eventid小的事件之后发生。
如果有一个序列S,它是数据集D的序列的子序列,那么它的支持度的计算方式为:
support(s) = s在n个序列中出现的次数
如果spport(s)>min_support,则我们可以把它称为频繁序列,或者序列模式。序列模式是很有用的,比如如果我们得到了<豆浆机,黄豆>这样的序列模式(尖括号表示它里面的元素是有序的,前一个在后一个之前发生),那么我们就可以认为,如果一个用户购买了豆浆机,则他之后极有可能购买黄豆。
序列模式挖掘就是发现序列模式的过程。
2.GSP算法
如果对Apriori算法还有印象的话,应该依旧记得,Apriori算法就两个步骤。1.进行自连接 2.进行剪枝
GSP算法其实就是一个类Apriori算法,它也就两个步骤:1.进行自连接 2.进行剪枝
序列如何进行自连接呢?有这样一个定义,即对于序列S1和S2,如果序列S1去掉第一项,与序列2去掉最后一项得到的序列相同,那么序列1和序列2就是可以连接的。把序列2的最后一项加入到序列1中,得到一个新的连接,即可以作为序列1和序列2连接的结果。
GSP算法的剪枝条件与Apriori算法的剪枝条件相同:1.如果序列的支持度小于最小支持度,那么就会被剪掉 2.如果序列是频繁序列,则它的所有子序列必定是频繁序列;所以如果一个序列存在不是频繁序列的子序列的话,也会被剪掉。
我们可以用一个例子推导一下,明白GSP算法究竟是怎样一回事:
我们假定数据集D有三组序列,分别为(假定min_support=2):
SID | EID | 项 |
1 | 1 | I1,I2 |
1 | 2 | I3 |
1 | 3 | I4 |
SID | EID | 项 |
2 | 1 | I2 |
2 | 2 | I3 |
SID | EID | 项 |
3 | 1 | I2 |
3 | 2 | I4 |
我们首先得到的候选序列为(接下来的表述中,尖括号<>表示里面的项有序,而圆括号()表示里面的项是出现在一个event中):
<I1>,<I2>,<I3>,<I4>
可以得到它们的支持度分别为:
<I1>:1
<I2>:3
<I3>:2
<I4>:2
进行剪枝,可以得到的序列模式为:
<I2>:3
<I3>:2
<I4>:2
然后再用前一步得到的序列模式,进行自连接,我们可以得到候选序列:
<I2,I2>:0
<I2,I3>:2
<I2,I4>:2
<I3,I2>:0
<I3,I3>:0
<I3,I4>:1
<I4,I2>:0
<I4,I3>:0
<I4,I4>:0
(I2,I3):0
(I2,I4):0
(I3,I4):0
进行剪枝,得到的序列模式为:
<I2,I3>:2
<I2,I4>:2
由于<I2,I3>去掉第一项得到<I3>,与<I2,I4>去掉最后一项得到<I2>,序列并不相同。所以它们是不能进行连接的,此时算法终止。最终得到的序列模式即为:
<I2,I3>,<I2,I4>
即如果用户购买了I2,则很有可能再购买I3;如果用户购买了I2,则很有可能再购买I4。
GSP算法很直白,但是也有缺点,就是每次计算序列的支持度时,都需要全表扫描数据集D。我们简单估计一下,假设数据集D的里面含有m个不同的项。假设第一步得到的单个序列候选集无需进行剪枝,那么由那个单个序列集合再进行自连接时,得到的序列个数为:m*m+m(m-1)/2个。(m*m个为有序的序列,m(m-1)/2为同时出现在某一个event的序列个数),那么此时需要进行的数据集D的扫描次数=(m*m+m(m-1)/2)*数据集D的记录数。一次候选集剪枝的全数据集D的扫描次数都非常之大。
针对上面的问题,就有了SPADE算法的提出。
3.SPADE算法
SPADE算法在GSP算法的基础上,提出了ID_LIST的概念,来规避多次对数据集D进行全表扫描的问题。ID_LIST是一个(SID,EID)组成的集合。
我们用上面一个例子来推导一下,了解SPADE算法是如何做的。
第一轮的候选序列<I1>,<I2>,<I3>,<I4>,我们得到它们的ID_LIST:
I1
SID | EID |
1 | 1 |
SID | EID |
1 | 1 |
2 | 1 |
3 | 1 |
SID | EID |
1 | 2 |
2 | 2 |
SID | EID |
1 | 3 |
3 | 2 |
<I1>:1
<I2>:3
<I3>:2
<I4>:2
进行剪枝,可以得到的序列模式为:
<I2>:3
<I3>:2
<I4>:2
然后,我们再根据序列模式自连接得到本轮的候选集,以及候选集对应的ID_LIST(此时的ID_LIST可以由上一轮的ID_LIST得到),因为候选集包括:<I2,I2>:0
<I2,I3>:2
<I2,I4>:2
<I3,I2>:0
<I3,I3>:0
<I3,I4>:1
<I4,I2>:0
<I4,I3>:0
<I4,I4>:0
(I2,I3):0
(I2,I4):0
(I3,I4):0
数目比较多,我们就针对其中的<I2,I3>的ID_LIST进行举例子;I2的ID_LIST含有3项(1,1),(2,1),(3,1),而I3的ID_LIST有两项,(1,2),(2,2),那么我们可以知道,序列号相同,且I3在I2之后出现的有两项,即可以得到<I2,I3>的ID_LIST:
SID | EID | EID |
1 | 1 | 2 |
2 | 1 | 2 |
<I2,I3>:2
<I2,I4>:2
由于<I2,I3>去掉第一项得到<I3>,与<I2,I4>去掉最后一项得到<I2>,序列并不相同。所以它们是不能进行连接的,此时算法终止。最终得到的序列模式即为:
<I2,I3>,<I2,I4>
其实可以看到,SPADE与GSP算法大体相同,只不过由于它多了一个ID_LIST记录,使得每一次的ID_LIST根据上一次的ID_LIST得到(从而得到支持度),而ID_LIST的规模是随着剪枝的不断进行,而规模逐渐缩小的。所以也就解决了GSP算法多次扫描数据集D问题。由于时间仓促,所以以上算法只给出了解释和推导,而没有给出算法源码。以后抽空给出。