挖掘强关联规则的过程:
1.得到最大频繁项目集(这里使用apriori算法)
2.在最大频繁项目集中找强关联规则
工程结构:
(把下面的文件放到自己建的工程中就可以运行了,如果嫌麻烦的话把这些都放到main.cpp中也可以,建议分开放。但是要注意代码中有一个地方用到了自动数据类型auto,要开c++11,否则编译会报错,如果没开的话按照代码注释改一下就可以了。)
codeblock中开c++11:
settings->compiler:
运行结果:
含的文件:
(代码中都有注释,很容易看懂的)
mian.cpp
#include "mining.h"
int main()
{
//freopen("in.txt","r",stdin);
PSet D; //
int min_support,num;
cout<<"输入最小支持度和事务个数:"<<endl;
cin>>min_support>>num;
cout<<"输入所有事务"<<endl;
for(int i=0;i<num;i++)
{
ItemSet tem;
cin>>tem.items;
tem.cnt=1;
D.push_back(tem);
}
//得到频繁项目集
PSet result=apriori(D,min_support);
cout<<endl<<"所有的频繁项目集:"<<endl<<'{';
for(int i=0;i<result.size();i++)
i==result.size()-1?cout<<result[i].items<<'}'<<endl:cout<<result[i].items<<',';
//得到最大频繁项目集
result=get_max(result);
cout<<endl<<"最大频繁项目集:"<<endl<<'{';
for(int i=0;i<result.size();i++)
i==result.size()-1?cout<<result[i].items<<'}'<<endl:cout<<result[i].items<<',';
cout<<endl;
double min_conf;
cout<<"输入最小置信度:";
cin>>min_conf;
//找强关联规则
RuleSet rules=find_rules(D,result,min_conf);
cout<<endl<<"满足条件的所有强关联规则(后面两个分别是置信度和支持度):"<<endl;
for(int i=0;i<rules.size();i++)
cout<<rules[i].f<<"->"<<rules[i].t<<" "<<rules[i].conf<<" "<<rules[i].support<<endl;
return 0;
}
mining.h
#include "base.h"
#include "apriori.h"
#include "gen.h"
base.h
#include <bits/stdc++.h>
using namespace std;
//项集的数据结构
struct ItemSet
{
string items;
int cnt;
bool operator <(ItemSet t)const
{
if(items==t.items)return cnt<t.cnt;
return items<t.items;
}
bool operator ==(ItemSet t)const
{
return items==t.items&&cnt==t.cnt;
}
};
//规则的数据结构
struct Rule
{
string f,t;
double support,conf;
bool operator ==(Rule x)const
{
return f==x.f&&t==x.t&&support;
}
bool operator <(Rule x)const
{
if(f==x.f)
return t<x.t;
else return f<x.f;
}
};
//项目集的数据类型
typedef vector<ItemSet> PSet;
//规则集合
typedef vector<Rule> RuleSet;
//判断a中有多少个项目不属于b,显然当返回值是0的时候a是b的自子集
//gen.h和apriori.h中都会用到
int belong(string a,string b)
{
int ct=0;
for(int i=0;i<a.length();i++)
if(b.find_first_of(a[i])==string::npos)ct++;
return ct;
}
apriori.h
//apriori算法初始时用到,获得L1
PSet get(PSet &D)
{
set<char> se;
PSet ans;
for(int i=0;i<D.size();i++)
{
for(int j=0;j<D[i].items.length();j++)
se.insert(D[i].items[j]);
}
auto it=se.begin();//如果没有开c++11标准的话,把auto改为set<char>::iterator
while(it!=se.end())
{
ItemSet tem;
tem.cnt=0;
tem.items.push_back(*it);
ans.push_back(tem);
it++;
}
return ans;
}
//将b加到a中,用于将apriori中产生的Li加入到最后的结果中
void con(PSet &a,PSet &b)
{
for(int i=0;i<b.size();i++)a.push_back(b[i]);
}
//生成候选集时用到,根据a和b生成一个候选项集
string gen(string a,string b)
{
sort(a.begin(),a.end());
sort(b.begin(),b.end());
for(int i=0;i<a.length();i++)
{
if(b.find_first_of(a[i])==string::npos)
{
b.push_back(a[i]);
sort(b.begin(),b.end());
return b;
}
}
}
//get_candidates中会用到的函数,判断items是否包含非频繁项目集
bool contain_inf(PSet &Li,string items)
{
for(int i=0;i<items.length();i++)
{
string tem=items;
tem.erase(tem.begin()+i);
bool flag=false;
for(int j=0;j<Li.size();j++)
{
if(!belong(tem,Li[j].items))
{
flag=true;break;
}
}
if(!flag)return 1;
}
return 0;
}
//在频繁项目集中求最大频繁项目集
PSet get_max(PSet &L)
{
PSet ans;
for(int i=0;i<L.size();i++)
{
bool flag=false;
for(int j=0;j<L.size();j++)
if(i!=j&&!belong(L[i].items,L[j].items))
{
flag=true;
break;
}
if(!flag)ans.push_back(L[i]);
}
return ans;
}
//apriori算法要用到的函数,根据Li(每个项集都是k项)生成候选项目集Ci(每个项集都是k+1项)
PSet get_candidates(PSet &Li)
{
PSet Ci;
for(int i=0;i<Li.size();i++)
{
for(int j=i+1;j<Li.size();j++)
{
if(i!=j&&belong(Li[i].items,Li[j].items)==1)
{
ItemSet tem;
tem.cnt=0;
tem.items=gen(Li[i].items,Li[j].items);
if(!contain_inf(Li,tem.items))
Ci.push_back(tem);
}
}
}
sort(Ci.begin(),Ci.end());
Ci.erase(unique(Ci.begin(),Ci.end()),Ci.end());
return Ci;
}
//apriori算法主体,求频繁项目集
PSet apriori(PSet &D,int min_support)
{
PSet Ci,Li,L;
Li=get(D);
while(true)
{
con(L,Li);
Ci=get_candidates(Li);
for(int i=0;i<Ci.size();i++)
{
for(int j=0;j<D.size();j++)
if(!belong(Ci[i].items,D[j].items))
Ci[i].cnt++;
}
Li.clear();
for(int i=0;i<Ci.size();i++)
if(Ci[i].cnt>=min_support)
Li.push_back(Ci[i]);
if(Li.size()==0)break;
}
return L;
}
gen.h
//求差集b-a
string inter(string a,string b)
{
int pos;
for(int i=0;i<a.length();i++)
{
pos=b.find_first_of(a[i]);
if(pos!=string::npos)
b.erase(b.begin()+pos);
}
return b;
}
//将b中的规则加到a中
void con_rule(RuleSet &a,RuleSet &b)
{
for(int i=0;i<b.size();i++)a.push_back(b[i]);
}
//求a的支持数(这里只能说是支持度,因为并没有除总事务的个数)
double support(PSet &D,ItemSet a)
{
double conf=0;
for(int i=0;i<D.size();i++)
if(!belong(a.items,D[i].items))conf++;
return conf;
}
RuleSet gen_rules(PSet &D,ItemSet Li,ItemSet Lm,double min_conf)
{
double conf;
RuleSet rules;
for(int i=0;i<Lm.items.length();i++)
{
ItemSet tem=Lm;
tem.items.erase(tem.items.begin()+i);
conf=(double)Li.cnt/support(D,tem);
if(conf>min_conf)
{
Rule rule;
rule.f=tem.items;
rule.t=inter(tem.items,Li.items);
rule.conf=conf;
rules.push_back(rule);
}
if(tem.items.length()>1)
{
RuleSet rules2=gen_rules(D,Li,tem,min_conf);
con_rule(rules,rules2);
}
}
sort(rules.begin(),rules.end());
rules.erase(unique(rules.begin(),rules.end()),rules.end());
return rules;
}
RuleSet find_rules(PSet &D,PSet &L,double min_conf)
{
RuleSet rules;
for(int i=0;i<L.size();i++)
{
RuleSet tem=gen_rules(D,L[i],L[i],min_conf);
con_rule(rules,tem);
}
sort(rules.begin(),rules.end());
rules.erase(unique(rules.begin(),rules.end()),rules.end());
return rules;
}