GSP序列模式分析算法

参考资料:http://blog.csdn.net/zone_programming/article/details/42032309

更多数据挖掘代码:https://github.com/linyiqun/DataMiningAlgorithm

介绍

GSP算法是序列模式挖掘算法的一种,他是一种类Apriori的一种,整个过程与Apriori算法比较类似,不过在细节上会略有不同,在下面的描述中,将会有所描述。GSP在原有的频繁模式定义的概念下,增加了3个的概念。

1、加入时间约束min_gap,max_gap,要求原来的连续变为只要满足在规定的min_gap到max_gap之间即可。

2、加入time_windows_size,只要在windows_size内的item,都可以被认为是同一ItemSet。

3、加入分类标准。

以上3点新的中的第一条特征将会在后面的算法中着重展现。

算法原理

1、根据所输入的序列,找出所有的单项集,即1频繁模式,这里会经过最小支持度阈值的判断。

2、根据1频繁模式进行连接运算,产生2频繁模式,这里会有进行最小阈值的判断。

3、根据2频繁模式连接产生3频繁模式,会经过最小支持度判断和剪枝操作,剪枝操作的原理在于判断他的所有子集是否也全是频繁模式。

4、3频繁模式不断的挖掘知道不能够产生出候选集为止。

连接操作的原理

2个序列,全部变为item列表的形式,如果a序列去掉第1个元素后,b序列去掉最后1个序列,2个序列的item完全一致,则代表可以连接,由b的最后一个元素加入到a中,至于是以独立项集的身份加入还是加入到a中最后1个项集中取决于b中的最后一个元素所属项集是否为单项项集。

时间约束计算

这个是用在支持度计数使用的,GSP算法的支持度计算不是那么简单,比如序列判断<2, <3, 4>>是否在序列<(1,5), 2 , <3, 4>, 2>,这就不能仅仅判断序列中是否只包含2,<3, 4>就行了,还要满足时间间隔约束,这就要把2,和<3,4>的所有出现时间都找出来,然后再里面找出一条满足时间约束的路径就算包含。时间的定义是从左往右起1.2,3...继续,以1个项集为单位,所有2的时间有2个分别为t=2和t=4,然后同理,因为<3,4>在序列中只有1次,所以时间为t=3,所以问题就变为了下面一个数组的问题

2 4

3

从时间数组的上往下,通过对多个时间的组合,找出1条满足时间约束的方案,这里的方案只有2-3,4-3,然后判断时间间隔,如果存在这样的方式,则代表此序列支持所给定序列,支持度值加1,这个算法在程序的实现中是比较复杂的。

算法的代码实现

测试数据输入(格式:事务ID item数 item1 item2.....):

  1. 1215
  2. 112
  3. 113
  4. 114
  5. 211
  6. 213
  7. 214
  8. 2235
  9. 311
  10. 312
  11. 313
  12. 314
  13. 315
  14. 411
  15. 413
  16. 415
  17. 514
  18. 515
最后组成的序列为:

<(1,5) 2 3 4>

<1 3 4 (3,5)>

<1 2 3 4 5>

<1 3 5>

<4 5>

也就是说同一序列都是同事务的。下面是关键的类

Sequence.java:

  1. packageDataMining_GSP;
  2. importjava.util.ArrayList;
  3. /**
  4. *序列,每个序列内部包含多组ItemSet项集
  5. *
  6. *@authorlyq
  7. *
  8. */
  9. publicclassSequenceimplementsComparable<Sequence>,Cloneable{
  10. //序列所属事务ID
  11. privateinttrsanctionID;
  12. //项集列表
  13. privateArrayList<ItemSet>itemSetList;
  14. publicSequence(inttrsanctionID){
  15. this.trsanctionID=trsanctionID;
  16. this.itemSetList=newArrayList<>();
  17. }
  18. publicSequence(){
  19. this.itemSetList=newArrayList<>();
  20. }
  21. publicintgetTrsanctionID(){
  22. returntrsanctionID;
  23. }
  24. publicvoidsetTrsanctionID(inttrsanctionID){
  25. this.trsanctionID=trsanctionID;
  26. }
  27. publicArrayList<ItemSet>getItemSetList(){
  28. returnitemSetList;
  29. }
  30. publicvoidsetItemSetList(ArrayList<ItemSet>itemSetList){
  31. this.itemSetList=itemSetList;
  32. }
  33. /**
  34. *取出序列中第一个项集的第一个元素
  35. *
  36. *@return
  37. */
  38. publicIntegergetFirstItemSetNum(){
  39. returnthis.getItemSetList().get(0).getItems().get(0);
  40. }
  41. /**
  42. *获取序列中最后一个项集
  43. *
  44. *@return
  45. */
  46. publicItemSetgetLastItemSet(){
  47. returngetItemSetList().get(getItemSetList().size()-1);
  48. }
  49. /**
  50. *获取序列中最后一个项集的最后一个一个元素
  51. *
  52. *@return
  53. */
  54. publicIntegergetLastItemSetNum(){
  55. ItemSetlastItemSet=getItemSetList().get(getItemSetList().size()-1);
  56. intlastItemNum=lastItemSet.getItems().get(
  57. lastItemSet.getItems().size()-1);
  58. returnlastItemNum;
  59. }
  60. /**
  61. *判断序列中最后一个项集是否为单一的值
  62. *
  63. *@return
  64. */
  65. publicbooleanisLastItemSetSingleNum(){
  66. ItemSetlastItemSet=getItemSetList().get(getItemSetList().size()-1);
  67. intsize=lastItemSet.getItems().size();
  68. returnsize==1?true:false;
  69. }
  70. @Override
  71. publicintcompareTo(Sequenceo){
  72. //TODOAuto-generatedmethodstub
  73. returnthis.getFirstItemSetNum().compareTo(o.getFirstItemSetNum());
  74. }
  75. @Override
  76. protectedObjectclone()throwsCloneNotSupportedException{
  77. //TODOAuto-generatedmethodstub
  78. returnsuper.clone();
  79. }
  80. /**
  81. *拷贝一份一模一样的序列
  82. */
  83. publicSequencecopySeqence(){
  84. SequencecopySeq=newSequence();
  85. for(ItemSetitemSet:this.itemSetList){
  86. copySeq.getItemSetList().add(newItemSet(itemSet.copyItems()));
  87. }
  88. returncopySeq;
  89. }
  90. /**
  91. *比较2个序列是否相等,需要判断内部的每个项集是否完全一致
  92. *
  93. *@paramseq
  94. *比较的序列对象
  95. *@return
  96. */
  97. publicbooleancompareIsSame(Sequenceseq){
  98. booleanresult=true;
  99. ArrayList<ItemSet>itemSetList2=seq.getItemSetList();
  100. ItemSettempItemSet1;
  101. ItemSettempItemSet2;
  102. if(itemSetList2.size()!=this.itemSetList.size()){
  103. returnfalse;
  104. }
  105. for(inti=0;i<itemSetList2.size();i++){
  106. tempItemSet1=this.itemSetList.get(i);
  107. tempItemSet2=itemSetList2.get(i);
  108. if(!tempItemSet1.compareIsSame(tempItemSet2)){
  109. //只要不相等,直接退出函数
  110. result=false;
  111. break;
  112. }
  113. }
  114. returnresult;
  115. }
  116. /**
  117. *生成此序列的所有子序列
  118. *
  119. *@return
  120. */
  121. publicArrayList<Sequence>createChildSeqs(){
  122. ArrayList<Sequence>childSeqs=newArrayList<>();
  123. ArrayList<Integer>tempItems;
  124. SequencetempSeq=null;
  125. ItemSettempItemSet;
  126. for(inti=0;i<this.itemSetList.size();i++){
  127. tempItemSet=itemSetList.get(i);
  128. if(tempItemSet.getItems().size()==1){
  129. tempSeq=this.copySeqence();
  130. //如果只有项集中只有1个元素,则直接移除
  131. tempSeq.itemSetList.remove(i);
  132. childSeqs.add(tempSeq);
  133. }else{
  134. tempItems=tempItemSet.getItems();
  135. for(intj=0;j<tempItems.size();j++){
  136. tempSeq=this.copySeqence();
  137. //在拷贝的序列中移除一个数字
  138. tempSeq.getItemSetList().get(i).getItems().remove(j);
  139. childSeqs.add(tempSeq);
  140. }
  141. }
  142. }
  143. returnchildSeqs;
  144. }
  145. }
ItemSet.java:

  1. packageDataMining_GSP;
  2. importjava.util.ArrayList;
  3. /**
  4. *序列中的子项集
  5. *
  6. *@authorlyq
  7. *
  8. */
  9. publicclassItemSet{
  10. /**
  11. *项集中保存的是数字项数组
  12. */
  13. privateArrayList<Integer>items;
  14. publicItemSet(String[]itemStr){
  15. items=newArrayList<>();
  16. for(Strings:itemStr){
  17. items.add(Integer.parseInt(s));
  18. }
  19. }
  20. publicItemSet(int[]itemNum){
  21. items=newArrayList<>();
  22. for(intnum:itemNum){
  23. items.add(num);
  24. }
  25. }
  26. publicItemSet(ArrayList<Integer>itemNum){
  27. this.items=itemNum;
  28. }
  29. publicArrayList<Integer>getItems(){
  30. returnitems;
  31. }
  32. publicvoidsetItems(ArrayList<Integer>items){
  33. this.items=items;
  34. }
  35. /**
  36. *判断2个项集是否相等
  37. *
  38. *@paramitemSet
  39. *比较对象
  40. *@return
  41. */
  42. publicbooleancompareIsSame(ItemSetitemSet){
  43. booleanresult=true;
  44. if(this.items.size()!=itemSet.items.size()){
  45. returnfalse;
  46. }
  47. for(inti=0;i<itemSet.items.size();i++){
  48. if(this.items.get(i)!=itemSet.items.get(i)){
  49. //只要有值不相等,直接算作不相等
  50. result=false;
  51. break;
  52. }
  53. }
  54. returnresult;
  55. }
  56. /**
  57. *拷贝项集中同样的数据一份
  58. *
  59. *@return
  60. */
  61. publicArrayList<Integer>copyItems(){
  62. ArrayList<Integer>copyItems=newArrayList<>();
  63. for(intnum:this.items){
  64. copyItems.add(num);
  65. }
  66. returncopyItems;
  67. }
  68. }
GSPTool.java(算法工具类):

  1. packageDataMining_GSP;
  2. importjava.io.BufferedReader;
  3. importjava.io.File;
  4. importjava.io.FileReader;
  5. importjava.io.IOException;
  6. importjava.util.ArrayList;
  7. importjava.util.Collections;
  8. importjava.util.HashMap;
  9. importjava.util.Map;
  10. /**
  11. *GSP序列模式分析算法
  12. *
  13. *@authorlyq
  14. *
  15. */
  16. publicclassGSPTool{
  17. //测试数据文件地址
  18. privateStringfilePath;
  19. //最小支持度阈值
  20. privateintminSupportCount;
  21. //时间最小间隔
  22. privateintmin_gap;
  23. //时间最大间隔
  24. privateintmax_gap;
  25. //原始数据序列
  26. privateArrayList<Sequence>totalSequences;
  27. //GSP算法中产生的所有的频繁项集序列
  28. privateArrayList<Sequence>totalFrequencySeqs;
  29. //序列项数字对时间的映射图容器
  30. privateArrayList<ArrayList<HashMap<Integer,Integer>>>itemNum2Time;
  31. publicGSPTool(StringfilePath,intminSupportCount,intmin_gap,
  32. intmax_gap){
  33. this.filePath=filePath;
  34. this.minSupportCount=minSupportCount;
  35. this.min_gap=min_gap;
  36. this.max_gap=max_gap;
  37. totalFrequencySeqs=newArrayList<>();
  38. readDataFile();
  39. }
  40. /**
  41. *从文件中读取数据
  42. */
  43. privatevoidreadDataFile(){
  44. Filefile=newFile(filePath);
  45. ArrayList<String[]>dataArray=newArrayList<String[]>();
  46. try{
  47. BufferedReaderin=newBufferedReader(newFileReader(file));
  48. Stringstr;
  49. String[]tempArray;
  50. while((str=in.readLine())!=null){
  51. tempArray=str.split("");
  52. dataArray.add(tempArray);
  53. }
  54. in.close();
  55. }catch(IOExceptione){
  56. e.getStackTrace();
  57. }
  58. HashMap<Integer,Sequence>mapSeq=newHashMap<>();
  59. Sequenceseq;
  60. ItemSetitemSet;
  61. inttID;
  62. String[]itemStr;
  63. for(String[]str:dataArray){
  64. tID=Integer.parseInt(str[0]);
  65. itemStr=newString[Integer.parseInt(str[1])];
  66. System.arraycopy(str,2,itemStr,0,itemStr.length);
  67. itemSet=newItemSet(itemStr);
  68. if(mapSeq.containsKey(tID)){
  69. seq=mapSeq.get(tID);
  70. }else{
  71. seq=newSequence(tID);
  72. }
  73. seq.getItemSetList().add(itemSet);
  74. mapSeq.put(tID,seq);
  75. }
  76. //将序列图加入到序列List中
  77. totalSequences=newArrayList<>();
  78. for(Map.Entryentry:mapSeq.entrySet()){
  79. totalSequences.add((Sequence)entry.getValue());
  80. }
  81. }
  82. /**
  83. *生成1频繁项集
  84. *
  85. *@return
  86. */
  87. privateArrayList<Sequence>generateOneFrequencyItem(){
  88. intcount=0;
  89. intcurrentTransanctionID=0;
  90. SequencetempSeq;
  91. ItemSettempItemSet;
  92. HashMap<Integer,Integer>itemNumMap=newHashMap<>();
  93. ArrayList<Sequence>seqList=newArrayList<>();
  94. for(Sequenceseq:totalSequences){
  95. for(ItemSetitemSet:seq.getItemSetList()){
  96. for(intnum:itemSet.getItems()){
  97. //如果没有此种类型项,则进行添加操作
  98. if(!itemNumMap.containsKey(num)){
  99. itemNumMap.put(num,1);
  100. }
  101. }
  102. }
  103. }
  104. booleanisContain=false;
  105. intnumber=0;
  106. for(Map.Entryentry:itemNumMap.entrySet()){
  107. count=0;
  108. number=(int)entry.getKey();
  109. for(Sequenceseq:totalSequences){
  110. isContain=false;
  111. for(ItemSetitemSet:seq.getItemSetList()){
  112. for(intnum:itemSet.getItems()){
  113. if(num==number){
  114. isContain=true;
  115. break;
  116. }
  117. }
  118. if(isContain){
  119. break;
  120. }
  121. }
  122. if(isContain){
  123. count++;
  124. }
  125. }
  126. itemNumMap.put(number,count);
  127. }
  128. for(Map.Entryentry:itemNumMap.entrySet()){
  129. count=(int)entry.getValue();
  130. if(count>=minSupportCount){
  131. tempSeq=newSequence();
  132. tempItemSet=newItemSet(newint[]{(int)entry.getKey()});
  133. tempSeq.getItemSetList().add(tempItemSet);
  134. seqList.add(tempSeq);
  135. }
  136. }
  137. //将序列升序排列
  138. Collections.sort(seqList);
  139. //将频繁1项集加入总频繁项集列表中
  140. totalFrequencySeqs.addAll(seqList);
  141. returnseqList;
  142. }
  143. /**
  144. *通过1频繁项集连接产生2频繁项集
  145. *
  146. *@paramoneSeq
  147. *1频繁项集序列
  148. *@return
  149. */
  150. privateArrayList<Sequence>generateTwoFrequencyItem(
  151. ArrayList<Sequence>oneSeq){
  152. SequencetempSeq;
  153. ArrayList<Sequence>resultSeq=newArrayList<>();
  154. ItemSettempItemSet;
  155. intnum1;
  156. intnum2;
  157. //假如将<a>,<b>2个1频繁项集做连接组合,可以分为<aa>,<ab>,<ba>,<bb>4个序列模式
  158. //注意此时的每个序列中包含2个独立项集
  159. for(inti=0;i<oneSeq.size();i++){
  160. num1=oneSeq.get(i).getFirstItemSetNum();
  161. for(intj=0;j<oneSeq.size();j++){
  162. num2=oneSeq.get(j).getFirstItemSetNum();
  163. tempSeq=newSequence();
  164. tempItemSet=newItemSet(newint[]{num1});
  165. tempSeq.getItemSetList().add(tempItemSet);
  166. tempItemSet=newItemSet(newint[]{num2});
  167. tempSeq.getItemSetList().add(tempItemSet);
  168. if(countSupport(tempSeq)>=minSupportCount){
  169. resultSeq.add(tempSeq);
  170. }
  171. }
  172. }
  173. //上面连接还有1种情况是每个序列中只包含有一个项集的情况,此时a,b的划分则是<(a,a)><(a,b)><(b,b)>
  174. for(inti=0;i<oneSeq.size();i++){
  175. num1=oneSeq.get(i).getFirstItemSetNum();
  176. for(intj=i;j<oneSeq.size();j++){
  177. num2=oneSeq.get(j).getFirstItemSetNum();
  178. tempSeq=newSequence();
  179. tempItemSet=newItemSet(newint[]{num1,num2});
  180. tempSeq.getItemSetList().add(tempItemSet);
  181. if(countSupport(tempSeq)>=minSupportCount){
  182. resultSeq.add(tempSeq);
  183. }
  184. }
  185. }
  186. //同样将2频繁项集加入到总频繁项集中
  187. totalFrequencySeqs.addAll(resultSeq);
  188. returnresultSeq;
  189. }
  190. /**
  191. *根据上次的频繁集连接产生新的侯选集
  192. *
  193. *@paramseqList
  194. *上次产生的候选集
  195. *@return
  196. */
  197. privateArrayList<Sequence>generateCandidateItem(
  198. ArrayList<Sequence>seqList){
  199. SequencetempSeq;
  200. ArrayList<Integer>tempNumArray;
  201. ArrayList<Sequence>resultSeq=newArrayList<>();
  202. //序列数字项列表
  203. ArrayList<ArrayList<Integer>>seqNums=newArrayList<>();
  204. for(inti=0;i<seqList.size();i++){
  205. tempNumArray=newArrayList<>();
  206. tempSeq=seqList.get(i);
  207. for(ItemSetitemSet:tempSeq.getItemSetList()){
  208. tempNumArray.addAll(itemSet.copyItems());
  209. }
  210. seqNums.add(tempNumArray);
  211. }
  212. ArrayList<Integer>array1;
  213. ArrayList<Integer>array2;
  214. //序列i,j的拷贝
  215. Sequenceseqi=null;
  216. Sequenceseqj=null;
  217. //判断是否能够连接,默认能连接
  218. booleancanConnect=true;
  219. //进行连接运算,包括自己与自己连接
  220. for(inti=0;i<seqNums.size();i++){
  221. for(intj=0;j<seqNums.size();j++){
  222. array1=(ArrayList<Integer>)seqNums.get(i).clone();
  223. array2=(ArrayList<Integer>)seqNums.get(j).clone();
  224. //将第一个数字组去掉第一个,第二个数字组去掉最后一个,如果剩下的部分相等,则可以连接
  225. array1.remove(0);
  226. array2.remove(array2.size()-1);
  227. canConnect=true;
  228. for(intk=0;k<array1.size();k++){
  229. if(array1.get(k)!=array2.get(k)){
  230. canConnect=false;
  231. break;
  232. }
  233. }
  234. if(canConnect){
  235. seqi=seqList.get(i).copySeqence();
  236. seqj=seqList.get(j).copySeqence();
  237. intlastItemNum=seqj.getLastItemSetNum();
  238. if(seqj.isLastItemSetSingleNum()){
  239. //如果j序列的最后项集为单一值,则最后一个数字以独立项集加入i序列
  240. ItemSetitemSet=newItemSet(newint[]{lastItemNum});
  241. seqi.getItemSetList().add(itemSet);
  242. }else{
  243. //如果j序列的最后项集为非单一值,则最后一个数字加入i序列最后一个项集中
  244. ItemSetitemSet=seqi.getLastItemSet();
  245. itemSet.getItems().add(lastItemNum);
  246. }
  247. //判断是否超过最小支持度阈值
  248. if(isChildSeqContained(seqi)
  249. &&countSupport(seqi)>=minSupportCount){
  250. resultSeq.add(seqi);
  251. }
  252. }
  253. }
  254. }
  255. totalFrequencySeqs.addAll(resultSeq);
  256. returnresultSeq;
  257. }
  258. /**
  259. *判断此序列的所有子序列是否也是频繁序列
  260. *
  261. *@paramseq
  262. *待比较序列
  263. *@return
  264. */
  265. privatebooleanisChildSeqContained(Sequenceseq){
  266. booleanisContained=false;
  267. ArrayList<Sequence>childSeqs;
  268. childSeqs=seq.createChildSeqs();
  269. for(SequencetempSeq:childSeqs){
  270. isContained=false;
  271. for(SequencefrequencySeq:totalFrequencySeqs){
  272. if(tempSeq.compareIsSame(frequencySeq)){
  273. isContained=true;
  274. break;
  275. }
  276. }
  277. if(!isContained){
  278. break;
  279. }
  280. }
  281. returnisContained;
  282. }
  283. /**
  284. *候选集判断支持度的值
  285. *
  286. *@paramseq
  287. *待判断序列
  288. *@return
  289. */
  290. privateintcountSupport(Sequenceseq){
  291. intcount=0;
  292. intmatchNum=0;
  293. SequencetempSeq;
  294. ItemSettempItemSet;
  295. HashMap<Integer,Integer>timeMap;
  296. ArrayList<ItemSet>itemSetList;
  297. ArrayList<ArrayList<Integer>>numArray=newArrayList<>();
  298. //每项集对应的时间链表
  299. ArrayList<ArrayList<Integer>>timeArray=newArrayList<>();
  300. for(ItemSetitemSet:seq.getItemSetList()){
  301. numArray.add(itemSet.getItems());
  302. }
  303. for(inti=0;i<totalSequences.size();i++){
  304. timeArray=newArrayList<>();
  305. for(ints=0;s<numArray.size();s++){
  306. ArrayList<Integer>childNum=numArray.get(s);
  307. ArrayList<Integer>localTime=newArrayList<>();
  308. tempSeq=totalSequences.get(i);
  309. itemSetList=tempSeq.getItemSetList();
  310. for(intj=0;j<itemSetList.size();j++){
  311. tempItemSet=itemSetList.get(j);
  312. matchNum=0;
  313. intt=0;
  314. if(tempItemSet.getItems().size()==childNum.size()){
  315. timeMap=itemNum2Time.get(i).get(j);
  316. //只有当项集长度匹配时才匹配
  317. for(intk=0;k<childNum.size();k++){
  318. if(timeMap.containsKey(childNum.get(k))){
  319. matchNum++;
  320. t=timeMap.get(childNum.get(k));
  321. }
  322. }
  323. //如果完全匹配,则记录时间
  324. if(matchNum==childNum.size()){
  325. localTime.add(t);
  326. }
  327. }
  328. }
  329. if(localTime.size()>0){
  330. timeArray.add(localTime);
  331. }
  332. }
  333. //判断时间是否满足时间最大最小约束,如果满足,则此条事务包含候选事务
  334. if(timeArray.size()==numArray.size()
  335. &&judgeTimeInGap(timeArray)){
  336. count++;
  337. }
  338. }
  339. returncount;
  340. }
  341. /**
  342. *判断事务是否满足时间约束
  343. *
  344. *@paramtimeArray
  345. *时间数组,每行代表各项集的在事务中的发生时间链表
  346. *@return
  347. */
  348. privatebooleanjudgeTimeInGap(ArrayList<ArrayList<Integer>>timeArray){
  349. booleanresult=false;
  350. intpreTime=0;
  351. ArrayList<Integer>firstTimes=timeArray.get(0);
  352. timeArray.remove(0);
  353. if(timeArray.size()==0){
  354. returnfalse;
  355. }
  356. for(inti=0;i<firstTimes.size();i++){
  357. preTime=firstTimes.get(i);
  358. if(dfsJudgeTime(preTime,timeArray)){
  359. result=true;
  360. break;
  361. }
  362. }
  363. returnresult;
  364. }
  365. /**
  366. *深度优先遍历时间,判断是否有符合条件的时间间隔
  367. *
  368. *@parampreTime
  369. *@paramtimeArray
  370. *@return
  371. */
  372. privatebooleandfsJudgeTime(intpreTime,
  373. ArrayList<ArrayList<Integer>>timeArray){
  374. booleanresult=false;
  375. ArrayList<ArrayList<Integer>>timeArrayClone=(ArrayList<ArrayList<Integer>>)timeArray
  376. .clone();
  377. ArrayList<Integer>firstItemItem=timeArrayClone.get(0);
  378. for(inti=0;i<firstItemItem.size();i++){
  379. if(firstItemItem.get(i)-preTime>=min_gap
  380. &&firstItemItem.get(i)-preTime<=max_gap){
  381. //如果此2项间隔时间满足时间约束,则继续往下递归
  382. preTime=firstItemItem.get(i);
  383. timeArrayClone.remove(0);
  384. if(timeArrayClone.size()==0){
  385. returntrue;
  386. }else{
  387. result=dfsJudgeTime(preTime,timeArrayClone);
  388. if(result){
  389. returntrue;
  390. }
  391. }
  392. }
  393. }
  394. returnresult;
  395. }
  396. /**
  397. *初始化序列项到时间的序列图,为了后面的时间约束计算
  398. */
  399. privatevoidinitItemNumToTimeMap(){
  400. Sequenceseq;
  401. itemNum2Time=newArrayList<>();
  402. HashMap<Integer,Integer>tempMap;
  403. ArrayList<HashMap<Integer,Integer>>tempMapList;
  404. for(inti=0;i<totalSequences.size();i++){
  405. seq=totalSequences.get(i);
  406. tempMapList=newArrayList<>();
  407. for(intj=0;j<seq.getItemSetList().size();j++){
  408. ItemSetitemSet=seq.getItemSetList().get(j);
  409. tempMap=newHashMap<>();
  410. for(intitemNum:itemSet.getItems()){
  411. tempMap.put(itemNum,j+1);
  412. }
  413. tempMapList.add(tempMap);
  414. }
  415. itemNum2Time.add(tempMapList);
  416. }
  417. }
  418. /**
  419. *进行GSP算法计算
  420. */
  421. publicvoidgspCalculate(){
  422. ArrayList<Sequence>oneSeq;
  423. ArrayList<Sequence>twoSeq;
  424. ArrayList<Sequence>candidateSeq;
  425. initItemNumToTimeMap();
  426. oneSeq=generateOneFrequencyItem();
  427. twoSeq=generateTwoFrequencyItem(oneSeq);
  428. candidateSeq=twoSeq;
  429. //不断连接生产候选集,直到没有产生出侯选集
  430. for(;;){
  431. candidateSeq=generateCandidateItem(candidateSeq);
  432. if(candidateSeq.size()==0){
  433. break;
  434. }
  435. }
  436. outputSeqence(totalFrequencySeqs);
  437. }
  438. /**
  439. *输出序列列表信息
  440. *
  441. *@paramoutputSeqList
  442. *待输出序列列表
  443. */
  444. privatevoidoutputSeqence(ArrayList<Sequence>outputSeqList){
  445. for(Sequenceseq:outputSeqList){
  446. System.out.print("<");
  447. for(ItemSetitemSet:seq.getItemSetList()){
  448. System.out.print("(");
  449. for(intnum:itemSet.getItems()){
  450. System.out.print(num+",");
  451. }
  452. System.out.print("),");
  453. }
  454. System.out.println(">");
  455. }
  456. }
  457. }
调用类Client.java:

  1. packageDataMining_GSP;
  2. /**
  3. *GSP序列模式分析算法
  4. *@authorlyq
  5. *
  6. */
  7. publicclassClient{
  8. publicstaticvoidmain(String[]args){
  9. StringfilePath="C:\\Users\\lyq\\Desktop\\icon\\testInput.txt";
  10. //最小支持度阈值
  11. intminSupportCount=2;
  12. //时间最小间隔
  13. intmin_gap=1;
  14. //施加最大间隔
  15. intmax_gap=5;
  16. GSPTooltool=newGSPTool(filePath,minSupportCount,min_gap,max_gap);
  17. tool.gspCalculate();
  18. }
  19. }
算法的输出(挖掘出的所有频繁模式):

  1. <(1,),>
  2. <(2,),>
  3. <(3,),>
  4. <(4,),>
  5. <(5,),>
  6. <(1,),(3,),>
  7. <(1,),(4,),>
  8. <(1,),(5,),>
  9. <(2,),(3,),>
  10. <(2,),(4,),>
  11. <(3,),(4,),>
  12. <(3,),(5,),>
  13. <(4,),(5,),>
  14. <(1,),(3,),(4,),>
  15. <(1,),(3,),(5,),>
  16. <(2,),(3,),(4,),>

算法实现的难点

1、算法花费了几天的时间,难点首先在于对算法原理本身的理解,网上对于此算法的资料特别少,而且不同的人所表达的意思 都有少许的不同,讲的也不是很详细,于是就通过阅读别人的代码理解GSP算法的原理,我的代码实现也是参考了参考资料的C语言的实现。

2、在实现时间约束的支持度计数统计的时候,调试了一段时间,做时间统计容易出错,因为层级实在太多容易搞晕。

3、还有1个是Sequence和ItemSet的拷贝时的引用问题,在产生新的序列时一定要深拷贝1个否则导致同一引用会把原数据给改掉的。

GSP算法和Apriori算法的比较

我是都实现过了GSP算法和Apriori算法的,后者是被称为关联规则挖掘算法,偏向于挖掘关联规则的,2个算法在连接的操作上有不一样的地方,还有在数据的构成方式上,Apriori的数据会简单一点,都是单项单项构成的,而且在做支持度统计的时候只需判断存在与否即可。不需要考虑时间约束。Apriori算法给定K项集,连接到K-1项集算法就停止了,而GSP算法是直到不能够产生候选集为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值