关联规则挖掘之算法实现

一: A Priori的基础实现

算法:Apriori

输入:D -事务数据库;min_sup -最小支持度计数阈值

输出:L - D中的频繁项集

方法:

L1=find_frequent_1-itemsets(D); //找出所有频繁1项集

For(k=2;Lk-1!=null;k++){

Ck=apriori_gen(Lk-1); //产生候选,并剪枝

For each事务t in D{ //扫描D进行候选计数

Ct =subset(Ck,t); //得到t的子集

For each候选c属于Ct

c.count++;

}

Lk={c属于Ck | c.count>=min_sup}

}

Return L=所有的频繁集;

Procedure apriori_gen(Lk-1:frequent(k-1)-itemsets)

For each项集l1属于Lk-1

For each项集l2属于Lk-1

If((l1[1]=l2[1])&&( l1[2]=l2[2])&&……..

&& (l1[k-2]=l2[k-2])&&(l1[k-1]<l2[k-1])) then{

c=l1连接l2 //连接步:产生候选

if has_infrequent_subset(c,Lk-1) then

delete c; //剪枝步:删除非频繁候选

else add c to Ck;}

Return Ck;

Procedure has_infrequent_sub(c:candidate k-itemset; Lk-1:frequent(k-1)-itemsets)

For each(k-1)-subset s of c

If s不属于Lk-1 then

Return true;

Return false;


    首先来看一个频繁集的性质。
   定理:如果项目集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, int c):index_i(i),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 j, int k, int c):index_i(i),index_j(j),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'},   
		{'b','c'},   
		{'a','b','d'},   
		{'a','c'},   
		{'b','c'},   
		{'a','c'},   
		{'a','b','c','e'},   
		{'a','b','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]!='\0';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]!='\0';i++)
		{
			int h1 = hash1(a[k][i]);
			for(int j=i+1;a[k][j]!='\0';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,ite31->index_j,ite32->index_j,0);
				c3.push_back(n3);
			}

		}
	}
	/*countC3.................................................*/
	for(int out=0;out<D;out++)
	{
		for(int i=0;a[out][i]!='\0';i++)
		{
			int h1 = hash1(a[out][i]);
			for(int j=i+1;a[out][j]!='\0';j++)
			{
				int h2=hash1(a[out][j]);
				for(int k=j+1;a[out][k]!='\0';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");
}


 
 
 
 下面是代码的结果: 
 


 

你可能感兴趣的:(a,a,C++实现,Priori,priori改进)