数据挖掘Apriori算法C++实现Word格式文档下载.docx
《数据挖掘Apriori算法C++实现Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《数据挖掘Apriori算法C++实现Word格式文档下载.docx(22页珍藏版)》请在冰豆网上搜索。
//统计候选频繁k-项集的计数
(8)}
(9)Lk={c∈Ck|c.count≥min_sup}//满足最小支持度的k-项集即为频繁k-项集
(10)}
(11)returnL=∪kLk;
//合并频繁k-项集(k>
0)
2、算法流程
①首先单趟扫描数据集,计算各个一项集的支持度,根据给定的最小支持度闵值,得到一项频繁集L1。
②然后通过连接运算,得到二项候选集,对每个候选集再次扫描数据集,得出每个候选集的支持度,再与最小支持度比较。
得到二项频繁集L2。
③如此进行下去,直到不能连接产生新的候选集为止。
④对于找到的所有频繁集,用规则提取算法进行关联规则的提取。
3、算法的不足:
(1)数据库重复扫描的次数太多。
在由CK寻找LK的过程中,CK中的每一项都需要扫描事务数据库进行验证,以决定其是否加入Lk,存在的频繁K-项集越大,重复扫描的次数就越多。
这一过程耗时太大,增加了系统1/0开销,处理效率低[10],不利于实际应用。
(2)产生的候选集可能过于庞大。
如果一个频繁1-项集包含100个项,那么频繁2-项集就有C2
100个,为找到元素个数为100的频繁项集,如{b1,b2,…,b100},那么就要扫描数据库100次,产生的候选项集总个数为:
举例:
对于一个这样庞大的项集,计算机难以存储和计算,挖掘效率低下。
二、算法的改进1
1、改进方法:
性质1:
频繁项集的所有非空子集都必须是频繁的。
(Apriori性质,记为性质1)
性质2:
若频繁K-项集Lk中各个项可以做链接产生Lk+1
,则Lk中每个元素在Lk中出现的次数应大于或等于K,若小于K,则删除该项在Lk中所有的事务集[11]。
(Apriori性质的推论,记为性质2)
改进的方法:
在连接之后得到的候选频繁k项,直接进行最小支持度判断,并进行剪枝,从而直接得到频繁k项集,避免候选项集可能过大的问题;
2、算法的流程
①首先单趟扫描数据集,计算各个一项集的支持度,根据给定的最小支持度阈值,得到一项频繁集L1。
②然后通过连接运算,对于每个连接的到项直接进行最小支持度判断,如果大于最小支持度的加入频繁二项集,如果小于则舍弃,循环直到连接完毕;
③如此进行下去,直到不能连接产生新的频繁项集为止。
3、代码实现的描述(详细描述文末附上):
使用C++,构造了一个Apriori类:
classApriori
{
public:
//初始化,输入数据源,得到原始数据集、频繁1项集
voidinit(stringfileName);
//连接频繁k项集、并且直接剪枝,得到频繁k+1项集,加入到容器item_list
voidapri_gen();
;
//连接频繁k项集、并且直接剪枝,得到频繁k+1项集,加入到频繁项集集合frequentvec中
floatcalculateSup(vector<
string>
judge_item);
//求候选项的支持度
vector<
mergeItem(vector<
vect1,vector<
vect2,intround);
//判断两个项是否可以合并成一个新的项集做为新的候选项,能则合并,不能的返回空容器
voidshowItem();
//输出频繁项集
private:
set<
>
datavec;
//原始数据集
inttrancount;
//原始数据项数量
vector<
pair<
float>
frequentvec;
//频繁项集的集合
doubleminsup;
//设置最小支持度和最小置信度
doubleminconf;
};
运行结果:
效果对比:
数据集大小:
9835
数据元素多少:
170
置信度:
0.05
原始:
频繁1项集28
候选2项集2^28
频繁2项集3
改进后:
算法的改进2
第一次扫描数据库时,对于数据库中的数据,利用各项元素的数字编号来替换各数据元素的名称;
即将数据元素的名称字符传用数字来替换,从而减少在求各候选项的支持度时的资源消耗;
代码中的改进之处,
string类型的元素转为对应的int代号:
储存频繁项集的容器由vector<
变为vector<
int>
;
然后对代码进行相应的调整,使得代码正常运行;
代码的描述:
//判断两个项是否可以合并成一个新的项集做为新的候选项,能则合并,不能的返回空容器
dataNumVec;
//原始数据集转换出来的、数据项用代号来表示的数据
map<
string,int>
reflection;
//原始数据中各个不同的元素的代号映射,数据元素从1开始编号
//原始数据项数量
//频繁项集集合,储存各项以及其支持度
改进后14.496;
14.549;
14.577
改进前20.165;
20.463;
20.383
效率提升28.1%
附:
改进1的代码(改进2与改进1代码几乎相同,不同之处在于储存频繁项的数据类型,代码略)
#include<
iostream>
fstream>
vector>
map>
cmath>
algorithm>
iomanip>
set>
utility>
time.h>
usingnamespacestd;
/*最大数据集数量,置信度阈值,*/
//判断候选项,是否为频繁项
//判断两个项集是否可以合并(要求只有一项不同)成一个新的项集(做为候选集)
//频繁项集de集合
voidApriori:
:
init(stringfileName)
//std:
cout<
<
"
调用init"
endl;
minsup=0.05;
minconf=0.5;
trancount=0;
ifstreamfile(fileName);
//打开数据文件
if(!
file)//检查文件是否打开成功
{
std:
Failtoopendatafile!
}
else
stringtemp;
set<
item;
//项集的临时set
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.insert(temp.substr(begin,end-begin));
//将每一个项插入item中
begin=end+1;
}
item.insert(temp.substr(begin));
//一个事务中的最后一项
datavec.push_back(item);
//将一个事务中的所有项当成一个整体插入另一个大的vector中
item.clear();
//清空item
//c