关联规则挖掘之算法实现
一: A Priori的基础实现
? ? 首先来看一个频繁集的性质。
? ?定理:如果项目集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,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 k,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'},'c'},{'a','c','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]!=' ';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]!=' ';i++) { int h1 = hash1(a[k][i]); for(int j=i+1;a[k][j]!=' ';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,0); c3.push_back(n3); } } } /*countC3.................................................*/ for(int out=0;out<D;out++) { for(int i=0;a[out][i]!=' ';i++) { int h1 = hash1(a[out][i]); for(int j=i+1;a[out][j]!=' ';j++) { int h2=hash1(a[out][j]); for(int k=j+1;a[out][k]!=' ';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"); } 下面是代码的结果: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |