Apriori算法实验报告文档格式.docx
《Apriori算法实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《Apriori算法实验报告文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
string>
>
datavec;
//原始数据项集
candidatevec;
//候选项集
frequentvec;
//频繁项集
ofstreamoutFile;
intround=1;
//生成项集轮次
longtrancount=0;
//原始事务总数
//判断某个工程在某一个事务中是否存在,存在那么值为1,反之为0
string,bool>
>
bitmap;
Apriori算法的第一步是简单统计所有含一个元素的项集出现的频率,来决定频繁1项集。
在第k步,分两个阶段:
1,用函数genCanItemsetK,通过第(k-1)步中生成的频繁(k-1)项集来生成侯选k项集;
2.计算侯选k项集的支持度,并找出频繁k项集。
Apriori算法描述如下
getOriData();
//获取原始数据集,并统计事务个数
genCanItemset1();
//产生输出候选1项集
genFreItemset1();
//产生频繁项集
if(!
frequentvec.empty())//根据频繁1项集,执行程序
{
do
{
genCanItemsetK();
//生成并输出候选k项集
genFreItemsetK();
//计算并输出频繁k项集
}while(!
frequentvec.empty());
//频繁项集不为空,那么循环继续
}
其中,产生候选k项集函数genCanItemsetK中涉及两个重要函数,项集合并函数mergeItem和剪枝函数cutNotCanItemsetK。
3、函数方法说明
//获取原始数据集,并统计事务个数
voidgetOriData();
//合并生成新的候选项集
mergeItem(vector<
vect1,vector<
vect2,intround);
//判断项集item是否已经存在候选项集集合items中,存在那么返回1
intisExist(vector<
item,vector<
items);
//产生并输出候选1项集
voidgenCanItemset1();
//产生并输出频繁1项集
voidgenFreItemset1();
//产生并输出候选k-项集〔k>
=2〕
voidgenCanItemsetK();
//产生并输出频繁k-项集〔k>
voidgenFreItemsetK();
//剪枝:
剪去合并后项集中含有非频繁项集中的项
voidcutNotCanItemsetK(vector<
&
item);
五、实验截图
1.程序运行界面
2.输出文件截图1
3.输出文件截图1
六、实验总结
做完这个实验,有如下收获:
1.同一数据集,最小支持度越小,那么产生的频繁项集维数越高,程序运行时间越长;
2.更加深刻理解了:
频繁子集的任何子集一定是频繁的,子集频繁父亲一定频繁;
3.Apriori也存在缺点:
第一在每一步产生侯选工程集时循环产生的组合过多,没有排除不应该参与组合的元素;
第二,每次计算项集的支持度时,开销会随着数据的增多而成几何级增长。
七、附
1.程序源码main.cpp
#include<
iostream>
fstream>
vector>
map>
algorithm>
iomanip>
usingnamespacestd;
intmain()
{
getOriData();
cout<
<
"
请输入结果文件名:
"
;
//pause
stringfName;
cin>
fName;
请输入最小支持度:
minsup;
outFile.open(fName,ios:
:
trunc);
outFile<
最小支持度为minsup="
<
minsup<
endl;
genCanItemset1();
genFreItemset1();
frequentvec.empty())//判断频繁1项集是否为空,为空那么退出
outFile.close();
\n结果已保存到"
fName<
文件!
\n"
system("
pause"
);
return0;
}
voidgetOriData()
intflag;
数据集文件:
\n1.dataA.txt\n2.dataB.txt\n请输入〔1选择dataA,其他选择2〕\n"
flag;
stringfilename;
if(flag==1)
filename="
dataA.txt"
//翻开数据文件
else
dataB.txt"
ifstreamfile(filename);
file)//检查文件是否翻开成功
{
cout<
Failtoopendatafile!
endl;
system("
exit(0);
stringtemp;
vector<
item;
//项集的临时vector
原始数据集:
intbegin,end;
while(getline(file,temp))//一行一行读入数据
trancount++;
begin=0;
temp.erase(0,temp.find_first_not_of("
\r\t\n"
));
//去除字符串首部的空格
temp.erase(temp.find_last_not_of("
\r\t\n"
)+1);
//去除字符串尾部的空格
while((end=temp.find('
'
begin))!
=string:
npos)//每一个事务中的项是以空格为分隔符的
{
item.push_back(temp.substr(begin,end-begin));
//将每一个项插入item中
begin=end+1;
}
item.push_back(temp.substr(begin));
//一个事务中的最后一项
datavec.push_back(item);
//将一个事务中的所有项当成一个整体插入另一个大的vector中
item.clear();
//清空item
cout<
temp<
}
file.close();
voidgenCanItemset1()
map<
item_map;
for(intix=0;
ix!
=datavec.size();
++ix)
for(intiy=0;
iy!
=datavec[ix].size();
++iy)
items_count[datavec[ix].at(iy)]++;
//该项集的计数加1
item_map[datavec[ix].at(iy)]=true;
//表示该工程在该事务中存在,值为1,否那么默认为0
bitmap.push_back(item_map);
item_map.clear();
//这里一定要清空一下
const_iteratormap_it=items_count.begin();
候选1项集:
while(map_it!
=items_count.end())//输出候选1项集
outFile<
{"
map_it->
first<
}"
map_it++;
voidgenFreItemset1()
outFile<
频繁1项集:
vector<
//项集的临时vector
=items_count.end())//频繁1项集
if(((float)map_it->
second/(float)trancount)>
minsup||fabs(((float)map_it->
second/(float)trancount)-minsup)<
1.0e-7)//支持度大于0.2
outFile.setf(ios:
fixed);
outFile<
支持度:
setprecision
(2)<
(float)map_it->
second/(float)trancount<
item.push_back(map_it->
first);
frequentvec.push_back(item);
//插入频繁1项集的vector中
voidgenCanItemsetK()
//生成下一轮的候选项集
intst=frequentvec.size();
candidatevec.clear();
//去除上一轮的候选项集
for(intst1=0;
st1<
st;
st1++)
for(intst2=st1+1;
st2<
st2++)
item=mergeItem(frequentvec[st1],frequentvec[st2],round);
//调用函数合并生成下一轮的候选项集
if(!
item.empty()&
&
!
isExist(item,candidatevec))//假设经过判断处理后返回的vector不为空且还不存在该项集,那么作为候选项集参加候选vector中
cutNotCanItemsetK(item);
round++;
候选"
round<
项集:
=candidatevec.size();
++ix)//输出候选项集
outFile<
=candidatevec[ix].size();
outFile<
candidatevec[ix].at(iy);
if(candidatevec.empty())//候选项集为空
项集为空!
//产生并输出频繁k-项集(k>
=2)
voidgenFreItemsetK()
//标记某个项集在某条事务中是否出现,出现为1,不出现为0,如:
{I1I2}
intcount;
//统计某个想集在整个交易的事务集中出现的次数
stringtempstr;
//临时string,用于串接各个项成一个字符串:
如:
I1I2I3串接为"
I1I2I3"
intmark;
//为防止执行多余的字符串串接工作
frequentvec.clear();
//去除上一轮的频繁项集
for(intsx=0;
sx!
++sx)//构造下一轮的频繁项集
mark=1;
count=0;
for(intsy=0;
sy!
=bitmap.size();
++sy)
flag=1;
//初始化为1,表出现
for(intsz=0;
sz!
=candidatevec[sx].size();
++sz)
if(bitmap[sy][candidatevec[sx].at(sz)]==false)//存在某一个子项不存在,那么没出现项集
{
flag=0;
}
if(mark==1)//只串接一次,如I1I2否那么为10个I1I2的串接
tempstr+=candidatevec[sx].at(sz);
//串接字符串
if(flag)//flag仍然为1,表示该项集在该条事务中出现了,计数加1
count++;
mark++;
if(((float)count/(float)trancount)>
minsup||fabs(((float)count/(float)trancount)-minsup)<
frequentvec.push_back(candidatevec[sx]);
//插入频繁项集
items_count[tempstr]=count;
//对应该项集的计数值
/////////假设此时生成的tempstr为I1I2I3,为便于后面的求置信度的计算,这里需要产生I2I1I3,I1I3I2等组合,并
//在items_count中给它们赋予和I1I2I3相同的值
sort(candidatevec[sx].begin(),candidatevec[sx].end());
//排序
stringtempstr2;
while(next_permutation(candidatevec[sx].begin(),candidatevec[sx].end()))//取下一排列组合
for(inttempst=0;
tempst!
tempst++)//拼接出该字符串组合
tempstr2+=candidatevec[sx][tempst];
items_count[tempstr2]=count;
tempstr2.erase();
}
tempstr.erase();
frequentvec.empty())//频繁项集不为空
频繁"
for(intsx=0;
=frequentvec.size();
++sx)//输出频繁项集
=frequentvec[sx].size();
outFile<
frequentvec[sx].at(sz);
tempstr+=frequentvec[sx].at(sz);
(float)items_count[tempstr]/(float)trancount<
tempstr.erase();
没有"
-频繁项集,Apriori算法结束!
//两个项集合并(要求只有一项不同)成一个新的项集〔做为候选集〕
vect2,intround)
intcount=0;
//统计两个vector中相同的项的数目
vect;
tempMap;
//辅助判断两个vector中重复的项
for(unsignedintst=0;
st<
vect1.size();
st++)
tempMap[vect1[st]]++;
vect.push_back(vect1[st]);
vect2.size();
tempMap[vect2[st]]++;
if(tempMap[vect2[st]]==2)//表示这两项相同
count++;
else
vect.push_back(vect2[st]);
if((count+1)!
=round)//要求两个工程集只有一个工程不相同,其他都相同,如:
I1I2I4和I1I2I3
vect.clear();
returnvect;
item)
////////实现剪枝//////////////////////////
tempvec;
boolfound=false;
//是否包含有非频繁的子集,为1表示含有,有的话进行剪枝,如假设I1I4为非频繁项集,那么I1I2I4要剪枝掉
stringteststr;
inttestint;
tempvec=item;
sort(tempvec.begin(),tempvec.end());
while(next_permutation(tempvec.begin(),tempvec.end()))//遍历所有的组合I1I2I4,要变成I1I4I2或其他如I2I1I4才能判断它包含I1I4这个非频繁项集
for(inttempst=0;
=tempvec.size();
tempstr+=tempvec[tempst];
for(map<
const_iteratortempit=items_count.begin