Apriori

APRIORI

  Apriori算法是一种最有影响的挖掘布尔关联规则频繁项集的算法。其核心是基于两阶段频集思想的递推算法。该关联规则在分类上属于单维、单层、布尔关联规则。在这里,所有支持度大于最小支持度的项集称为频繁项集,简称频集。
  该算法的基本思想是:首先找出所有的频集,这些项集出现的频繁性至少和预定义的最小支持度一样。然后由频集产生强关联规则,这些规则必须满足最小支持度和最小可信度。然后使用第1步找到的频集产生期望的规则,产生只包含集合的项的所有规则,其中每一条规则的右部只有一项,这里采用的是中规则的定义。一旦这些规则被生成,那么只有那些大于用户给定的最小可信度的规则才被留下来。为了生成所有频集,使用了递推的方法。
  可能产生大量的候选集,以及可能需要重复扫描数据库,是Apriori算法的两大缺点。
***
核心算法分析
1、相关概念

 项目(item):定义为在事务中呈现的一个东西

 关联规则:项目之间的关系

 事务:一次活动

Item出现频度:表示一个item在所有的事务活动中呈现的次数

支持度:就是针对每一个item,在所有事务中出现大事务比率。

S=出现该项目事务的总数/事务总数

显然,如果计算出一个频繁项集是 很消耗时间的。设计到的算法有apriori算法

 

2、 apriori 算法过程个人理解:

 
扫描所有事务(或者遍历事务集合),计算出频繁集L1(频繁集合Lk表示集合内的每个项k个元素组成,比如L2={ {a,b},{c,d} });然后采用apriorigen算法计算出候选集合C2(候选集合Ck表示集合内的每个项k个元素组成。注意在产生候选集合时候,可判定每个项内的元素组成的项集是否在Lk-1内,若不在,则抛弃该项目,显然支持度不满足,这样可提高效率);产生候选集合C2后遍历一遍事务集合,计算每个项的支持度,并根据支持度阀值筛选出频繁集合L2,依此类推,直到Lk为空集合。

 
上述特点分析:

<!--[if !supportLists]-->1、  <!--[endif]-->每个频繁集合Lk的产生都根据候选集合Ck,通过遍历事务集合,也就是LkCk的子集合。

<!--[if !supportLists]-->2、  <!--[endif]-->每个候选集合Ck的产生都根据频繁集合Lk-1apriorigen算法合并Lk-1

<!--[if !supportLists]-->3、  <!--[endif]-->apriorigen算法.

nsert into Ck

Select p[1], p[2],……,p[k-1]q[k-1]

From Lk-1 p Lk-1 q

Where p[1] = q[1],……,p[k-2] = q[k-2]

              p[k-1] < q[k-1]

Ck中的每一个项是对两个只有一个项不同的属于Lk-1的频集做一个(k-2)-连接来产生的(如果不清楚连接,可以单独分析集合合并问题)。注意为了提高效率,可以同时判断组合后新的项元素组成的项(由k-1个元素组成)否属如Lk-1集合的项,如不是则抛弃。

 

 

3、apriorigen算法举例

 本算法主要是集合构造。如下
集合合并:

C1={A,B,C,D}

C2={AB,AC,AD,BC,BD,CD}

C3={ABAC,ABAD,ABBC,ABBD,ABCD

ACAD,ACBC, ACBD, ACCD

,ADBC, ADBD, ADCD

BCBD, BCCD

BDCD

}

合并相同元素(且忽略次序)后====C3={ABC,ABD,ACD BCD}

经过程序测试,对于26个字母,110元的组合,产生10970271个记录项,消耗时间大约12分(CPU intel P 2.93),计算相当消耗时间。所以候选集合尽量不用,可采用FP-tree算法



5、apriorigen相应的实现代码:

// apr-gen.cpp : 定义控制台应用程序的入口点。
//单独测试集合合并的情况,验证apriori-gen算法功能
//结果:没有考虑频繁集合的过滤情况,单纯的集合合并过于消耗CPU和内存
//

#include "stdafx.h"
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;
#define MAX_SIZE 30


//判断两个项的组合情况,根据前1-k个元素进行比较
//最后把合并的结果存放到sOut内
int get_condition(const char* s1,const char* s2,char *sOut)
{
    int n = strlen(s1)-1;
    int nRet = strncmp(s1,s2,n);
    if(nRet!=0)
        return -1;
    if(*(s1+n) < *(s2+n))
    {
        memmove(sOut,s1,n);
        *(sOut+n)=*(s1+n);
        *(sOut+n+1)=*(s2+n);
        return 0;
    }
    else
        return -1;
}
//nElemNum表示一个项的最大元素个数
//vec 初始数组。如A,B,C,D,
//产生1--nElemNum个集合中的所有项
//注意:此种算法过于消耗CPU和内存
int main_process(vector<string> &vec,int nElemNum)
{
    int nTotalNum =0;
    char szTemp[1024];
    int nEndPos ,nBegPos;
    string str;
    int i,k,m;
       
    nTotalNum =0;
    for(i=0;i<MAX_SIZE;i++)
    {
        for(k=i+1;k < MAX_SIZE; k++)
        {
            str = vec[i]+vec[k];
            //cout<<str<<endl;
            vec.push_back(str);
            nTotalNum++;
           
        }
    }
    for(m =1;m<nElemNum-1;m++)
    {
        nEndPos =vec.size();
        nBegPos= nEndPos -nTotalNum;
        nTotalNum =0;
        memset(szTemp,0,sizeof(szTemp));
        for(i=nBegPos;i<nEndPos;i++)
        {
            for(k=i+1;k < nEndPos; k++)
            {
               
                if(get_condition(vec[i].c_str(),vec[k].c_str(),szTemp) < 0)
                    //continue;      //按照有序增长,后面不需要在比较
                    break;
                //str = vec[i]+vec[k];
                str = szTemp;
                //cout<<str<<endl;
                vec.push_back(str);
                nTotalNum++;
                memset(szTemp,0,sizeof(szTemp));
           
            }
        }
    }
    return 0;

}

int _tmain(int argc, _TCHAR* argv[])
{
    //ofstream myfile("c://1.txt",ios::out|ios::trunc,0);
    ofstream myfile("d://1.txt");
    int nTotalNum =0;
    char szTemp[1024];
    vector<string>  vec;
   
    char ch[] ="A";
    string str=ch;
    int i,k;
   
    for(i=0;i<MAX_SIZE;i++)
    {
        nTotalNum++;
        str=ch;
        vec.push_back(str);
        ch[0]++;
    }

    main_process(vec,5);
    for(i=0;i<vec.size();i++)
    //    cout<<vec[i]<<endl;
        myfile<<vec[i]<<endl;
//    cout<<"Num="<<vec.size()<<endl;
myfile<<"Num="<<vec.size()<<endl;
    return 0;
}
***

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值