Apriori算法及其代码

Apriori算法是一个容易理解,逻辑简单,代码容易编写的一个大数据频繁项集查找的算法。

设最小支持度计数为3  即个数要大于等于3的才是频繁项

如图1--原始数据库                  计数得到图2--每个东西的个数            则得到图3的频繁一项

                      
                                    

图1                                                图2                                                  图3

由频繁一项集两两配对得到候选项集合{A,B},{A,E},{B,E}

扫面原始数据库,即图1

{A,B}2个,{A,E}3个,{B,E}1个,所以得到频繁二项集{A,E}。由于此时二项集只剩下一个了,所以无法产生三项集,故程序结束。

看如下图所示程序流程图:

图5(图片来源于网络,仅供学习参考)

C++代码:完整说明以及大数据测试数据可以从这里下载http://download.csdn.net/download/my_acm/8042909

本程序为了简单编程使用直接把原始数据读入内存中,所以不能处理非常大的数据,而正真的apriori算法处理超大规模数据时会一遍一遍的从数据库中读取数据。这也是为什么apriori算法效率不高的原因之一。

/*
    function: apriori算法查找频繁集
    authour:
    date:
    Code::Blocks 12.11下运行通过
*/
#include<vector>
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<map>
using namespace std;

#define maxn 100000
#define maxItem 90
#define suport 0.01     //最小支持度
struct Item{
    vector <int> num;
};
typedef vector <int> i_list;

class Apriori{
public:
    int suport_num;        //最小支持度计数
    int num_max;           //单行最大数量
    int num_sol;           //交易条数
    int num_fre;           //频繁项种类的数量
    Item item[maxn];       //初始交易信息
    vector <i_list> fre_item[maxn];   //保存所有频繁项信息,fre_item[i]表示频繁i项信息
    map <int,int> list_item;         //标记某一个项目序号的总数
public:
    void init(){
        num_fre=0;
        num_max=0;
        suport_num=0;
        num_sol=0;
    }
    void input(){                        //输入,初始化交易信息
        char str[3000];
        int t=0;
        while(gets(str)){     //按行逐个读入数据
            char *f;
            f=strtok(str," ");
            while(f){
                int x;
                x=atoi(f);
                list_item[x]++;      //商品计数
                item[t].num.push_back(x);
                f=strtok(NULL," ");
            }
            if(item[t].num.size()>num_max)
                    num_max=item[t].num.size();
            t++;
        }
        num_sol=t;

        for(int i=0;i<num_sol;i++){
            sort(item[i].num.begin(),item[i].num.end());      //交易项目序号从小到大排列
        }
        suport_num=ceil(suport*num_sol);         //最小支持度计数
        cout<<"数据总行数: "<<num_sol<<" 最小支持度"<<suport<<" 最小支持度计数: "<<suport_num<<endl;
//        for(int i=0;i<num_sol;i++){
//            int len=item[i].num.size();
//            for(int j=0;j<len;j++){
//                printf("%d ",item[i].num[j]);
//            }
//            printf("\n");
//        }
    }
    void output(){                  //输出频繁项集
        if(!fre_item[1].size()){
            printf("no frequent item!\n");
            return ;
        }
        for(int k=1;k<=num_fre;k++){
            printf("%d frequent item is:\n",k);
            for(int i=0;i<fre_item[k].size();i++){
                for(int j=0;j<fre_item[k][i].size();j++){
                    printf("%d ",fre_item[k][i][j]);
                }
                printf("\n");
            }
            printf("\n");
        }
    }
    void LCS(i_list &tmp,i_list &t1,i_list &t2){//匹配最长公共子序列
        int len=t1.size();
        int sucess=1;
        for(int i=0;i<len-1;i++){
            if(t1[i]!=t2[i]){
                sucess=0;
                break;
            }
        }
        if(t1[len-1]==t2[len-1])
            sucess=0;
        if(sucess){
            tmp=t1;
            tmp.push_back(t2[len-1]);
        }
    }
    int judge(i_list tmp){              //判断tmp是否是频繁项
        int len=tmp.size();
        int sum=0;
        int sucess=1;
        for(int i=0;i<num_sol;i++){         //遍历所有原始数据
            sucess=1;
            if(item[i].num.size()<len)
                continue;
            for(int k=0;k<len;k++){
                int j;
                int tlen=item[i].num.size();
                for(j=0;j<tlen;j++){
                    if(tmp[k]==item[i].num[j])
                        break;
                }
                if(j>=tlen){
                    sucess=0;
                    break;
                }
            }
            if(sucess)
                sum++;
        }
        if(sum>=suport_num)            //大于等于最小支持度则是频繁项
            return 1;
        return 0;                //不是频繁项
    }
    void find_fre_item(){          //找出所有频繁项
        for(map <int,int>::iterator it=list_item.begin();it!=list_item.end();it++){   //找出所有的频繁一项
            if(it->second>=suport_num){
                i_list tmp;
                tmp.push_back(it->first);
                fre_item[1].push_back(tmp);
            }
        }
        list_item.clear();       //释放lisg_item
        if(0==fre_item[1].size())
            return ;
        if(1==fre_item[1].size()){
            num_fre=1;
            return ;
        }

        int len=num_max;
        for(int k=2;k<=len;k++){                   //找出所有二项以后的频繁项集
            //枚举k-1项的所有单项的数据,进行LCS匹配,得到k频繁项
            if(fre_item[k-1].size()>=2)
            for(int i=0;i<fre_item[k-1].size();i++){
                for(int j=i+1;j<fre_item[k-1].size();j++){

                    i_list tmp; tmp.clear();

                    LCS(tmp,fre_item[k-1][i],fre_item[k-1][j]);
                    if(!tmp.size())
                        continue;
                    if(judge(tmp)){
                        fre_item[k].push_back(tmp);
                        num_fre=k;
                    }
                }
            }
        }
    }
    void calculate_fre_item(){   //频繁项计算
        init();
        input();
        find_fre_item();
        output();
    }
}sol;
int main(){
    freopen("retail.dat","r",stdin);
    freopen("result.txt","w",stdout);
    sol.calculate_fre_item();
    return 0;
}
时间: 2024-08-24 09:59:31

Apriori算法及其代码的相关文章

机器学习(八)—Apriori算法

摘要:本文对Apriori算法进行了简单介绍,并通过Python进行实现,进而结合UCI数据库中的肋形蘑菇数据集对算法进行验证. “啤酒与尿布”的例子相信很多人都听说过吧,故事是这样的:在一家超市中,人们发现了一个特别有趣的现象,尿布与啤酒这两种风马牛不相及的商品居然摆在一起.但这一奇怪的举措居然使尿布和啤酒的销量大幅增加了.这可不是一个笑话,而是一直被商家所津津乐道的发生在美国沃尔玛连锁超市的真实案例.原来,美国的妇女通常在家照顾孩子,所以她们经常会嘱咐丈夫在下班回家的路上为孩子买尿布,而丈夫

Apriori算法--关联规则挖掘

我的数据挖掘算法代码:https://github.com/linyiqun/DataMiningAlgorithm 介绍 Apriori算法是一个经典的数据挖掘算法,Apriori的单词的意思是"先验的",说明这个算法是具有先验性质的,就是说要通过上一次的结果推导出下一次的结果,这个如何体现将会在下面的分析中会慢慢的体现出来.Apriori算法的用处是挖掘频繁项集的,频繁项集粗俗的理解就是找出经常出现的组合,然后根据这些组合最终推出我们的关联规则. Apriori算法原理 Aprio

Apriori算法关联分析与pyhon实现

算法中核心性质:频繁项集的所有非空子集也必须是频繁的.逆反命题 也成立:如果一个项集是非频繁的,那么所有它的超集也是非频繁. 一.Apriori算法简介:  Apriori算法是一种挖掘关联规则的频繁项集算法,其核心思想是通过候选集生成和情节的向下封闭检测两个阶段来挖掘频繁项集. Apriori(先验的,推测的)算法应用广泛,可用于消费市场价格分析,猜测顾客的消费习惯:网络安全领域中的入侵检测技术:可用在用于高校管理中,根据挖掘规则可以有效地辅助学校管理部门有针对性的开展贫困助学工作:也可用在移

数据挖掘中的模式发现(二)Apriori算法

基本概念 对于A→B 支持度(support): P(A∩B),既有A又有B的概率 置信度(Confidence Strength): conf(A→B)=sup(A∪B)sup(A)=P(B|A) 即,在A发生的事件中同时发生B的概率 例如购物篮分析:牛奶?面包 例子:[支持度:3%,置信度:40%] 支持度3%:意味着3%顾客同时购买牛奶和面包 置信度40%:意味着购买牛奶的顾客40%也购买面包 候选集(Candidate itemset): 通过向下合并得出的项集. 定义为C[k]. 频繁

Apriori 算法 理论

关联规则的基本模型-规则 关联规则的基本模型-置信度 关联规则的基本模型-支持度 关联规则基本概念 频繁项集举例 关联规则举例 Apriori的步骤 Apriori的重要性质 Apriori算法实例-产生频繁项集 Apriori算法实例-产生关联规则 Apriori算法思想总结 Apriori算法代码 由L(k-1)生成候选集Ck 从频繁项集中挖掘关联规则 由频繁项集产生关联规则--频繁项集性质 由频繁项集产生关联规则

玩转大数据:深入浅出大数据挖掘技术(Apriori算法、Tanagra工具、决策树)

一.本课程是怎么样的一门课程(全面介绍) 1.1.课程的背景 “大数据”作为时下最火热的IT行业的词汇,随之而来的数据仓库.数据分析.数据挖掘等等围绕大数据的商业价值的利用逐渐成为行业人士争相追捧的利润焦点. “大数据” 其实离我们的生活并不遥远,大到微博的海量用户信息,小到一个小区超市的月销售清单,都蕴含着大量潜在的商业价值. 正是由于数据量的快速增长,并且已经远远超过了人们的数据分析能力.因此,科学.商用等领域都迫切需要智能化.自动化的数据分析工具.在这样的背景下,数据挖掘技术应用而生,使得

利用Hbase的coprocessor实现增量式Apriori算法

Apriori在数据挖掘中是经典的频繁项集挖掘算法,其主要思想就是如果某个项集不频繁,则任何包含此项集的项集一定不频繁.而今天要实现的增量式的Apriori算法,有点像分布式的Apriori,因为我们可以把已挖掘的事务集和新增的事务集看作两个互相独立的数据集,挖掘新增的事务集,获取所有新增频繁集,然后与已有的频繁集做并集,对于两边都同时频繁的项集肯定全局频繁,而只有一边频繁的项集则需要统计其在两边的频繁计数,这样完成后就能获得所有的全局频繁集,并不需要重新挖掘已有的事务集,效率必然提高. 至于H

Apriori算法思想和其python实现

第十一章 使用Apriori算法进行关联分析 一.导语 "啤酒和尿布"问题属于经典的关联分析.在零售业,医药业等我们经常需要是要关联分析.我们之所以要使用关联分析,其目的是为了从大量的数据中找到一些有趣的关系.这些有趣的关系将对我们的工作和生活提供指导作用. 二.关联分析的基本概念 所谓的关联分析就是从海量的数据中找到一些有趣的关系.关联分析它有两个目标,一个是发现频繁项集,另一个是发现关联规则. 关联分析常用到的四个概念是:频繁项集,关联规则,置信度,支持度.频繁项集指的是频繁同时出

Apriori算法的介绍

前言: 数据挖掘中的关联分析可以分成频繁项集的挖掘和关联规则的生成两个步骤,而Apriori算法是找频繁项集最常用到的一种算法. 关于关联分析和频繁项集请见:什么是关联分析? 中言: 我们还是利用购物篮的例子来讲述Apriori算法的思路. 购物篮信息如下: TID Items 001 Cola, Egg, Ham 002 Cola, Diaper, Beer 003 Cola, Diaper, Beer, Ham 004 Diaper, Beer TID代表交易流水号,Items代表一次交易的