数据挖掘 Apriori算法

来源:互联网 发布:全国建筑业统计软件 编辑:程序博客网 时间:2024/05/02 00:34

Apriori算法


Apriori算法是一个挖掘关联规则的算法,是Agrawal等设计的一个基本算法,这是一个采用两阶段挖掘的思想,并且基于多次扫描事务数据库来执行的。Apriori算法的设计可以分解为两步骤来执行挖掘:

1、从事务数据库(D)中挖掘出所有频繁项集。

支持度大于最小支持度minSup的项集(Itemset)称为频集(Frequent Itemset)。

首先需要挖掘出频繁1-项集;

然后,继续采用递推的方式来挖掘频繁k-项集(k>1),具体做法是:

在挖掘出候选频繁k-项集(Ck)之后,根据最小置信度minSup来筛选,得到频繁k-项集。

最后合并全部的频繁k-项集(k>0)。

挖掘频繁项集的算法描述如下:

(1) L1 = find_frequent_1-itemsets(D); // 挖掘频繁1-项集,比较容易
(2) for (k=2;Lk-1 ≠Φ ;k++) {
(3)         Ck = apriori_gen(Lk-1 ,min_sup); // 调用apriori_gen方法生成候选频繁k-项集
(4)          for each transaction t ∈ D {    // 扫描事务数据库D
(5)                  Ct = subset(Ck,t);
(6)                  for each candidate c ∈ Ct
(7)                         c.count++; //   统计候选频繁k-项集的计数
(8)           }
(9)           Lk ={c ∈ Ck|c.count≥min_sup} // 满足最小支持度的k-项集即为频繁k-项集
(10) }
(11) return L= ∪ k Lk; // 合并频繁k-项集(k>0)

2、基于第1步挖掘到的频繁项集,继续挖掘出全部的频繁关联规则。

置信度大于给定最小置信度minConf的关联规则称为频繁关联规则(Frequent Association Rule)。在这一步,首先需要从频繁项集入手,首先挖掘出全部的关联规则(或者称候选关联规则),然后根据minConf来得到频繁关联规则。

挖掘频繁关联规则的算法描述如下:

(1) 初始状态 : L = ∪ k Lk; AR = Φ; // L是频繁项集集合,AR是频繁关联规则集合
(2) for all λk (λk是L的元素,是一个k-频繁项集,大小为n){
(3)           for all αk (αk是λk 的非空真子集){
(4)                   if(αk → βm的置信度>= minConf) { // 这里,m + k = n,其中αk → βm是一个关联规则
(5)                          AR = AR ∪ (αk → βm);
(6)                   }
(7)           }
(8)    }
(9) return AR;


源代码如下:

#include <iostream>#include <algorithm>using namespace std;#define MIN_SUP 0.6#define MAX_ITEM 26#define MOST_ITEM 10struct Transaction      //事务结构体{int TID;int num;char item[MOST_ITEM];}*trans;struct KN         //为方便指针指向切换,利用结构体指针{char KN_item[MOST_ITEM][MOST_ITEM];}*pKN,*qKN,*tKN;int trans_num;       //事务数int MIN;         //绝对支持度,最小支持度计数bool apriori_gen(char c1[],char c2[],char tk[],int curk) //由curk项频繁集生成curk+1项{int i,j,tk_num;i=j=0;tk_num=0;while(i<curk && j<curk){if(c1[i]==c2[j]){tk[tk_num]=c1[i];i++;j++;}else if(c1[i]<c2[j]){tk[tk_num]=c1[i];i++;}else {tk[tk_num]=c2[j];j++;}tk_num++;}if(i>=curk){while(j<curk) {tk[tk_num]=c2[j];j++;tk_num++;}}else{while(i<curk){tk[tk_num]=c1[i];i++;tk_num++;}}tk[tk_num]='\0';if(tk_num==curk+1)return true;else return false;}bool hasChecked(KN *p,int n,char tk[],int curK)  //判断是否已在频繁集中{int i;for(i=0;i<n;i++){if(strcmp(p->KN_item[i],tk)==0)return true;}return false;}bool isFrequent(char c[],int n)  //判断一个n项集是否为频繁的{int i,j,pos;int times=0;for(i=0;i<trans_num;i++){if(n>trans[i].num)continue;j=0;pos=0;while(j<n && pos<trans[i].num){if(c[j]==trans[i].item[pos]){j++;pos++;}else if(c[j]<trans[i].item[pos]){break;}else pos++;}if(j==n)times++;}return (times>=MIN);}int main(){freopen("in.txt","r",stdin);cin>>trans_num;trans=(Transaction *)malloc(sizeof(Transaction)*trans_num);MIN = trans_num * MIN_SUP;  int allItem[MAX_ITEM]={0};int i,j;char tmp;for(i=0;i<trans_num;i++){cin>>trans[i].TID>>trans[i].num;for(j=0;j<trans[i].num;j++){cin>>tmp;trans[i].item[j]=tmp-'A';allItem[trans[i].item[j]]++;}sort(trans[i].item,trans[i].item+trans[i].num);}pKN=new KN;qKN=new KN;memset(pKN,0,sizeof(pKN));memset(qKN,0,sizeof(qKN));cout<<" K=1 时的 频繁项集为:";j=0;for(i=0;i<MAX_ITEM;i++){if(allItem[i]>=MIN){pKN->KN_item[j][0]=i;cout<<char(pKN->KN_item[j][0]+'A')<<" , ";j++;}}cout<<endl<<endl;int KN_num=j;if(KN_num<2)return 0;char tk[MOST_ITEM];int curK=1;int curNum;while(1){curNum=0;for(i=0;i<KN_num-1;i++){for(j=i+1;j<KN_num;j++){if(!apriori_gen(pKN->KN_item[i],pKN->KN_item[j],tk,curK))continue;if(hasChecked(qKN,curNum,tk,curK+1))continue;if(isFrequent(tk,curK+1)){strcpy(qKN->KN_item[curNum],tk);curNum++;}}}KN_num=curNum;curK++;if(KN_num>0)cout<<"K="<<curK<<"时的 频繁项集为:"<<endl;for(i=0;i<KN_num;i++){cout<<" <";for(j=0;j<curK-1;j++){cout<<char(qKN->KN_item[i][j]+'A')<<",";}cout<<char(qKN->KN_item[i][j]+'A')<<"> ";}cout<<endl<<endl;if(KN_num<2)break;tKN=pKN;pKN=qKN;qKN=tKN;}return 0;}





原创粉丝点击