关联规则挖掘之算法实现
2014-10-17 18:19
274 查看
一: A Priori的基础实现
算法:Apriori 输入:D -事务数据库;min_sup -最小支持度计数阈值 输出:L - D中的频繁项集 方法: L1=find_frequent_1-itemsets(D); //找出所有频繁1项集 For(k=2;Lk-1!=null;k++){ Ck=apriori_gen(Lk-1); //产生候选,并剪枝 For each事务t in D{ //扫描D进行候选计数 Ct =subset(Ck,t); //得到t的子集 For each候选c属于Ct c.count++; } Lk={c属于Ck | c.count>=min_sup} } Return L=所有的频繁集; Procedure apriori_gen(Lk-1:frequent(k-1)-itemsets) For each项集l1属于Lk-1 For each项集l2属于Lk-1 If((l1[1]=l2[1])&&( l1[2]=l2[2])&&…….. && (l1[k-2]=l2[k-2])&&(l1[k-1]<l2[k-1])) then{ c=l1连接l2 //连接步:产生候选 if has_infrequent_subset(c,Lk-1) then delete c; //剪枝步:删除非频繁候选 else add c to Ck;} Return Ck; Procedure has_infrequent_sub(c:candidate k-itemset; Lk-1:frequent(k-1)-itemsets) For each(k-1)-subset s of c If s不属于Lk-1 then Return true; Return false; |
定理:如果项目集X是频繁集,那么它的非空子集都是频繁集。
根据定理,已知一个k-频繁集的项集X,X的所有k-1阶子集都肯定是频繁集,也就肯定可以找到两个k-1频繁集的项集,它们只有一项不同,且连接后等于X。这证明了通过连接k-1频繁集产生的k-候选集覆盖了k-频繁集。同时,如果k-候选集中的项集Y,包含有某个k-1阶子集不属于k-1频繁集,那么Y就不可能是频繁集,应该从候选集中裁剪掉。Apriori算法就是利用了频繁集的这个性质。
step1: join, 连接k-1频繁集产生的k-候选集覆盖了k-频繁集。
step2: prune, 如果k-候选集中的项集Y,包含有某个k-1阶子集不属于k-1频繁集,那么Y就不可能是频繁集,应该从候选集中裁剪掉。
/*construct C3...................................................*/ vector<Node3> c3; vector<Node3> l3; vector<Node2>::iterator ite31=l2.begin();//iter 31,32 for(;ite31!=l2.end();ite31++) { vector<Node2>::iterator ite32=l2.begin(); for(;ite32!=l2.end();ite32++) { if(ite31->index_j == ite32->index_i) //step1:找到两个k-1频繁集的项集,它们只有一项不同,且连接后等于X { vector<Node2>::iterator ite33=l2.begin(); for(;ite33!=l2.end();ite33++) { /*step2:如果k-候选集中的项集Y,包含有某个k-1阶子集不属于k-1频繁集,那么Y就不可能是频繁集,应该从候选集中裁剪掉*/ if(ite33->index_i == ite31->index_i && ite33->index_j ==ite32->index_j) { Node3 n3(ite31->index_i,ite31->index_j,ite32->index_j,0); c3.push_back(n3); } } } } }
如果不同的k-候选集的最小支持度是相同的,那么并不需要上述中的第二步的prune操作。因为在接下来的扫描D的步骤中是可以裁减掉他的不满足条件的子集的。 如ab+bc=abc, 已知ab和bc已经是k-1介子集,那么如果abc达到了2次的最小支持度,可以成为频繁项集,那么一定会有ac也达到至少2次的支持度。只是如果随着k的增加,最小支持度减少,就必须在k-1介子集中去修剪。
如下是A Priori算法的实现。计算到了L3。
<pre name="code" class="cpp"><pre name="code" class="cpp">/* 这个程序是数据挖掘中的Apriori算法 Apriori算法的描述 Apriori算法的第一步是简单统计所有含一个元素的项集出现的频率,来决定最大的一维项目集. 在第k步,分两个阶段,首先用一函数sc_candidate(候选),通过第(k-1)步中生成的最大项目集Lk-1来生成侯选项目集Ck. 然后搜索数据库计算侯选项目集Ck的支持度. 为了更快速地计算Ck中项目的支持度, 文中使用函数count_support计算支持度. Apriori算法描述如下 (1) C1={candidate1-itemsets}; (2) L1={c∈C1|c.count≥minsupport}; (3) For(k=2,Lk-1≠Φ,k++) //直到不能再生成最大项目集为止 (4) Ck=sc_candidate(Lk-1); //生成含k个元素的侯选项目集 (5) for all transactions t∈D //办理处理 (6) Ct=count_support(Ck,t); //包含在事务t中的侯选项目集 (7) for all candidates c∈Ct (8) c.count=c.count+1; (9) next (10) Lk={c∈Ck|c.count≥minsupport}; (11) next (12) resultset=resultset∪Lk*/ #include <stdio.h> #include<string.h> #include <iostream> #include <vector> #include <algorithm> #define D 9 /*D数事务的个数*/ #define MinSupCount 2 /*最小事务支持度数*/ #define ItemN 5 using namespace std; int hash1(char c) { return (int)c-(int)'a'; } class Node1 { public: int index_i; int count; Node1() { index_i=-1; count=0; } Node1(int i, int c):index_i(i),count(c) { } }; class Node2 { public: int index_i; int index_j; int count; Node2() { index_i=-1; index_j=-1; count = 0; } Node2(int i, int j, int c):index_i(i),index_j(j),count(c) { } }; class Node3 { public: int index_i; int index_j; int index_k; int count; Node3() { index_i=-1; index_j=-1; index_k=-1; count =0; } Node3(int i, int j, int k, int c):index_i(i),index_j(j),index_k(k), count(c) { } }; void printNode3(vector<Node3>& n3) { vector<Node3>::iterator ite = n3.begin(); for(;ite!=n3.end();ite++) { cout<<(char)(ite->index_i+'a')<<(char)(ite->index_j+'a')<<(char)(ite->index_k+'a')<<":"<<ite->count<<"\t"; } cout<<endl; } void printNode2(vector<Node2>& n2) { vector<Node2>::iterator ite = n2.begin(); for(;ite!=n2.end();ite++) { cout<<(char)(ite->index_i+'a')<<(char)(ite->index_j+'a')<<":"<<ite->count<<"\t"; } cout<<endl; } void printNode1(vector<Node1>& n1) { vector<Node1>::iterator ite = n1.begin(); for(;ite!=n1.end();ite++) { cout<<(char)(ite->index_i+'a')<<":"<<ite->count<<"\t"; } cout<<endl; } void main() { /*这里的a,b,c,d,e 分别代表着书上数据挖掘那章的I1,I2,I3,I4,I5 */ char a[10][10]={ {'a','b','e'}, {'b','d'}, {'b','c'}, {'a','b','d'}, {'a','c'}, {'b','c'}, {'a','c'}, {'a','b','c','e'}, {'a','b','c'} }; //total is D /*c1, hash the first time to b*/ //at first. hash the value vector<Node1> l1; int b[10]={0}; int ItemNumber=0; for(int i=0;i<D;i++) { for(int j=0;a[i][j]!='\0';j++) { int item = hash1(a[i][j]); if(b[item]==0) { b[item]++; ItemNumber++; } else { b[item]++; } } } /*L1........................................................*/ for(int i=0;i<ItemNumber;i++) { if(b[i]>=MinSupCount) { Node1 n1(i,b[i]); l1.push_back(n1); } } cout<<"print L1................................................"<<endl; printNode1(l1); /*construct c2...........................................................*/ vector<Node2> c2; vector<Node2>l2; vector<Node1>::iterator ite21=l1.begin(); //ite21,22 for(;ite21!=l1.end();ite21++) { vector<Node1>::iterator ite22=l1.begin(); for(;ite22!=l1.end();ite22++) { if(ite22->index_i > ite21->index_i) { Node2 n2(ite21->index_i,ite22->index_i,0); c2.push_back(n2); } } } /*count C2.........................................................................*/ for(int k=0;k<D;k++) { for(int i=0;a[k][i]!='\0';i++) { int h1 = hash1(a[k][i]); for(int j=i+1;a[k][j]!='\0';j++) { int h2=hash1(a[k][j]); vector<Node2>::iterator ite=c2.begin(); for(;ite!=c2.end();ite++) { if(ite->index_i ==h1 && ite->index_j == h2) ite->count++; } } } } /*prune C2 to L2.......................................................*/ l2.clear(); vector<Node2>::iterator ite2=c2.begin(); //ite2 for(;ite2!=c2.end();ite2++) { if(ite2->count>=MinSupCount) { l2.push_back(*ite2); } } cout<<"print L2............................................"<<endl; printNode2(l2); /*construct C3...................................................*/ vector<Node3> c3; vector<Node3> l3; vector<Node2>::iterator ite31=l2.begin();//iter 31,32 for(;ite31!=l2.end();ite31++) { vector<Node2>::iterator ite32=l2.begin(); for(;ite32!=l2.end();ite32++) { if(ite31->index_j == ite32->index_i) { Node3 n3(ite31->index_i,ite31->index_j,ite32->index_j,0); c3.push_back(n3); } } } /*countC3.................................................*/ for(int out=0;out<D;out++) { for(int i=0;a[out][i]!='\0';i++) { int h1 = hash1(a[out][i]); for(int j=i+1;a[out][j]!='\0';j++) { int h2=hash1(a[out][j]); for(int k=j+1;a[out][k]!='\0';k++) { int h3=hash1(a[out][k]); vector<Node3>::iterator ite=c3.begin(); for(;ite!=c3.end();ite++) { if(ite->index_i ==h1 && ite->index_j == h2 && ite->index_k==h3) ite->count++; } } } } } /*prune C3 to l3....................................*/ l3.clear(); vector<Node3>::iterator ite3=c3.begin(); //ite3 for(;ite3!=c3.end();ite3++) { if(ite3->count>=MinSupCount) { l3.push_back(*ite3); } } cout<<"print L3..........................."<<endl; printNode3(l3); system("pause"); }
下面是代码的结果:
相关文章推荐
- 数据挖掘之关联规则挖掘之SETM算法实现
- 数据挖掘之关联规则挖掘之Apriori算法实现
- 应用Aprion算法实现web与数据库关联规则做挖掘
- openminer中挖掘关联规则的算法实现概述
- 关联规则挖掘算法之Apriori算法的原理解析及代码实现
- 数据挖掘:Apriori 关联规则分析算法原理分析与代码实现
- 关联规则挖掘之Apriori算法实现超市购物
- 基于.NET实现数据挖掘--关联规则分析算法
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文档分类器的JAVA实现(下)
- aprioriTid关联规则挖掘的算法
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(下)
- 关于数据挖掘关联规则的Oracle实现
- 数据挖掘—决策树ID3分类算法的C++实现
- 数据挖掘算法-Apriori Algorithm(关联规则)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(上)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文档分类器的JAVA实现(上)
- 挖掘关联规则之Apriori算法详解
- 序列模式挖掘算法实现
- 关于数据挖掘关联规则的Oracle实现