Apriori算法中频繁项目集生成算法C语言实现

来源:互联网 发布:婚庆域名 编辑:程序博客网 时间:2024/05/18 01:05

          数据挖掘是从大量数据中分析推断出数据规律的一种技术,它具有广泛的应用前景,比如社交网络中好友推荐,购物网站中的商品推荐等等。数据挖掘至提出到现在,已经产生了多种数据挖掘算法。其中Apriori 是一种最有影响的挖掘布尔关联规则频繁项集的算法。本文使用C语言实现来一个单一最小支持度的Apriori算法。

         行文开始之前先简单介绍一下相关概念。设I={i1,i2,i3……im}是一个项目(Item)集合T={t1,t2,……,tm}是一个事物集合,每个事物t是一个项目集合,且t属于I,一条关联规则定义如下:X->Y,其中X、Y都属于I且X与Y的交集是空集。集合T中所有包含X的事物的数目称之为X的支持计数(X.count),一个规则的支持度:sup=(XUY.count)/n,n是T中事物的个数。置信度:conf=(XUY.count)/X.count。支持度决定了规则在T中出现的频度,置信度指出了规则的可预测度。minsup与minconf是用户指定的满足条件的一个最小阀值。一个频繁项目集是指一个支持度高于minsup的项集。如何高效的从中找到满足条件的规则,是数据挖掘中一个基础问题。如果从I中找出所有可能的规则,然后再从规则中去找,这会随着I的基数增加而成指数规模增加,显然不具有使用的价值。Apriori算法通过一定的剪枝优化策略使得计算大大缩小。

         Apriori算法大致分为两步:1生成所有的频繁项目集,2从频繁项目集中生成所有的可信关联规则(指它的置信度高于minconf)。Apriori算法基于演绎原理生成所有的频繁项目集:如歌一个频繁项目集满足最小支持度要求,那么它的所有非空子集都满足最小支持度要求。位了简化处理,Apriori算法假定所有项目集中的项目都采用字典顺序排列。它采用逐级搜索的思想:先产生频繁一项集,然后根据频繁一项集产生频繁而项集,依次类推,产生频繁K项集。现给定生成频繁K项集的Apriori算法的伪代码描述:

Algorith Apriori(T)

      C1<--init-pass(T) ;对事物进行第一轮搜索

     F1<--{f|f属于C1,f.count>=minsup};

     for(k=2;Fk-1 nut null;k++) do

        Ck<--candidate-gen(Fk-1);//候选K项集生成函数,分为两步:合并、减枝

       for each transzction t is one of T do

            for each candidate c is one of Ck do

                   if c is contained in t then

                          c.count++;

             endfor

         endfor

       Fk<--{c is one of Ck | c.count/n>=minsup}

   end for

 return

算法在根据频繁k-1项集生成频繁K项集过程中要计算频繁K项集中每个元素的支持度,并计算K项集中每个k-1项子集是否在Fk-1中,上述两条任何一条不满足,则删去这个K项集中的元素。candidate-gen与init-pass相关的伪代码就不详细给出了,同时我们在init-pass中实现频繁一项集生成。具体代码如下(不给出测试main函数):

//对事物进行第一次扫描,生成频繁一项集,并返回一项集中个数int init_pass(char *item,char tran[len_t][len],int len,char res_item[len_t][len],float min_sup){float t_sup;int number=0;for(int i=0;i<len;i++){int count=0;for(int j=0;j<len_t;j++){for(int k=0;k<len;k++)if(item[i]==tran[j][k]){count++;break;}break;}t_sup=count*1.0/len;if(t_sup>=min_sup)res_item[number++][0]=item[i];}return number-1;}//生成候选K项集,返回k项集中事物的个数int candidate_gen(char ktran[len][k],char kktran[len][k+1]){char temp[k],temp1[k],ktemp[k+1];int number=0;for(int i=0;i<len;i++){strcpy(temp,ktran[i]);bool flag;for(j=i+1;j<len;j++){strcpy(temp1,ktran[i]);for(int m=0;m<k;m++){if((m<k-1 && temp[m]==temp1[m])||m==k-1){continue;flag=true;}else  {flag=false;break;}}if(flag){if(temp[k-1]>temp1[k-1]){strcpy(ktemp,temp1);ktemp[k]=temp[k-1];}else{strcpy(ktemp,temp);ktemp[k]=temp1[k-1]}break;}}flag=judge(kemp,ktran[len][k]);if(flag==true)strcpy(kktran[number++],ktemp);}return number-1;}//判断子集是否在k项集中bool judge(char *srcstr,char desstr[len][k]){char temp[k];int count=0;for(int i=0;i<k-1;i++){for(int j=0;j<i;j++)temp[j]=srcstr[j];for(int j=i+1;j<k+1;j++)temp[j]=srcstr[j];for(int p=0;p<len;p++)if(strcmp(temp,desstr[i])==0){count++;break;}}if(count==k-1)return true;return false;}//apriori算法int apriori(char item[len],char tran[length][len],char res_tran[length][len],float min_sup){char ttran[length][len];int number,count,t_num;for(int i=0;i<length;i++)for(int j=0;j<len;j++)ttran[i][j]='0';number=init_pass(item,tran[length][len],len,ttran[length][len],min_sup);for(int i=0i<length;i++)res_tran[i][0]=ttran[i][0];for(int k=2;number!=0;k++){t_num=number;number=candidate_gen(res_item[number][k-1],ttran[number][k]);if(k==2)continue;else{count=0;for(int i=0;i<number;i++){char temp[k];strcpy(temp,ttran[i]);bool t_flag=false;for(int j=0;j<length;j++){//求出候选K项集中每个事物的支持计数int t_k=0;for(int n=0;n<k;n++){bool m_flag=falsefor(int g=t_k;g<len;g++){if(temp[k]==tran[j][g]){m_flag=true;t_k=g;break;}}if(m_flag==true && n==k-1)t_flag=true;}if(t_flag==true)count++;flag = false;}if(count/length > min_sup)strcpy(res_item[i],temp);count=0;}}}return t_num;}
相关的测试main函数可以自己书写。根据频繁k项集生成关联规则相对简单,只需要计算最小置信度即可从频繁K项集中找到所有的满足条件的关联规则。