Apriori算法(矩阵)
来源:互联网 发布:python一般用什么界面 编辑:程序博客网 时间:2024/06/06 06:29
陈老师Apriori算法整理(缺点:1.通用性不强,只解决3项集的问题未做推广2.算法程序为加上优化,封装、连接等操作3.置信度的计算不全,缺1->2 2->1等情况)
说明:支持度范围大于0小于1,因为分母是一样的,所以用支持度计数代表支持度
传统Apriori算法候选项集多(主要是二项集),且需要频繁扫描数据库。效率较低。现提出一种优化算法。通过一次扫描数据库生成上三角矩阵,通过此上三角矩阵直接生成频繁1项集、频繁2项集及候选3项集,避免了Apriori算法产生过多的候选2项集的问题,同时减少了频繁2项集自连接后进行剪枝的步骤;在第二次扫描数据库时,他只将数据库中对计算支持度产生作用且项数不小于3的项集形成链表,进而提高算法的执行效率。
具体步骤如下:
步骤一:扫描数据库,构造2项集的支持度矩阵M。
步骤二:根据最小支持度技术,遍历矩阵得到L1、L2与C3.
步骤一具体操作方法如下:在矩阵中,以集合I的项作为矩阵相应的行标和列标,矩阵中的某一元素Mij表示二项集{Ii,Ij}在事务数据库中出现的次数。扫描过程为:如果扫描到一条事务中包含有{Ii,Ij}二项集,则在矩阵中对应Mij位置的元素计数值加1,在扫描过程中依次对单项进行计数,将技术结果贴入主对角线对应的位置。
步骤二具体操作方法如下:读取矩阵M的主对角线数据并与支持度进行比较即可得到L1,遍历矩阵M的上三角数据并与支持度进行比较即可得到L2.从上到下逐行读取读取矩阵M的数据,首先找出第i行(i=1,2…,m)中不小于最小支持度计数的元素Mij;其次定位到第j行,如果Mij的值不小于最小支持度计数,那么寻找第j行中不小于最小支持度计数的元素Mij;最后再顺着第k列定位回到第i行,如果Mij的值也不小于最小支持度计数,那么则可以生成候选三项集{Ii,Ij,Ik}。根据上述步骤可知,只需扫描一次数据库就可以形成矩阵M,通过对矩阵遍历即可得到L1,L2和C3,避免了Apriori算法中产生大量候选2项集且不能剪枝的问题,也省略了L2自连接后的剪枝步骤。
然后根据以下两条性质确定最终的频繁3项集:
性质1:如果事务数据库中某事务的长度小于k,则由Lk-1生成Lk时,扫描该事务是对计算Ck中项集的计数不产生作用;
性质2:如果某项Ix属于I,但Ix不出现在Ck中,则在计算Lk时扫描Ix也是对计算候选项集的支持度不起作用。
根据以上两条性质,结合遍历矩阵找到的C3,寻找L3。
3.2举例说明
举例说明:最小支持度为2(>=2)
事务数据库D中的数据如下表所示:
ID
Product
1
L1
2
L2
3
L3
4
L4
5
L5
Trade_ID
Product_list(真正数据库中用商品的ID号也就是纯数字组成)
T001
L1,L2,L5
T002
L2,L4
T003
L2,L3
T004
L1,L2,L4
T005
L1,L3
T006
L2,L3
T007
L1,L3
T008
L1,L2,L3,L5
T009
L1,L2,L3
扫描数据库形成2项集支持度上三角矩阵M:
上三角矩阵M
扫描矩阵M并与最小支持度进行比较得L1,L2,C3
频繁1项集L1
项集
支持度计数
{L1}
6
{L2}
7
{L3}
6
{L4}
2
{L5}
2
频繁2项集L2
项集
支持度计数
{L1,L2}
4
{L1,L3}
4
{L1,L5}
2
{L2,L3}
4
{L2,L4}
2
{L2,L5}
2
生成候选3项集C3:步骤如下:首先找出第1行中不小于最小支持度计数的元素M12({L1,L2})=4>2(对应步骤二中的i=1,j=2);然后到第2行中找出不小于最小支持度计数的元素M23({L2,L3})=4>2(对应步骤二中的k=3);然后顺着第3列定位回第1行的元素M13({L1,L3})=4>2。则把{L1,L2,L3}放入候选3项集。然后依次对每一行进行上述操作,直至全部完成(严格按照步骤完成一行再进行下一行)。
最终生成候选3项集C3
项集
{L1,L2,L3}
{L1,L2,L5}
然后遍历数据库中所选商品种类大于等于3个的订单,确定候选3项集中的每一项的支持度并与最小支持度进行比较获得频繁3项集L3
频繁3项集L3
项集
支持度
{L1,L2,L3}
2
{L1,L2,L5}
2
最后计算每一项互推的可信度(置信度)
通过读取频繁3项集和频繁1、2项集的支持度进行计算置信度
L1=>L2,L3 2/6=33.3%
L2=>L1,L3 2/7=28.6%
L3=>L1,L3 2/6=33.3%
L1,L2=>L3 2/4=50%
L1,L3=>L2 2/4=50%
L2,L3=>L1 2/4=50%
根据最小置信度40%最终确定关联关系为: L1,L2=>L3.L1,L3=>L2.L2,L3=>L1
小结:1.支持度计数过于麻烦,可以使用连接,然后用count进行计数。这样这样更加优化。
2.可以把下面的代码封装成函数进行运行
程序代码:
--------------------建表------------------------(1)产品名和产品名称对应表,产品ID用数字表示 CREATE TABLE PRODUCT_ID ("P_ID" NUMBER, "PRODUCT" VARCHAR2(20 BYTE) );(2)购物单号和所购物品ID对应表CREATE TABLE TRADE_LIST ("TRADE_ID" NUMBER, "PRODUCT" NUMBER );(3)候选3项集表 CREATE TABLE APRIORIC3 ("SET1" NUMBER, "SET2" NUMBER, "SET3" NUMBER, "SUPPORTCOUNT" NUMBER, "C_ID" NUMBER );(4)频繁1项集表 CREATE TABLE APRIORISET1 ("SET1" NUMBER, "SUPPORTCOUNT" NUMBER );(5)频繁2项集表 CREATE TABLE APRIORISET2 ("SET1" NUMBER, "SET2" NUMBER, "SUPPORTCOUNT" NUMBER );(6)频繁3项集表 CREATE TABLE APRIORISET3 ("SET1" NUMBER, "SET2" NUMBER, "SET3" NUMBER, "SUPPORTCOUNT" NUMBER );(7)置信度表 (共有4个位置,L1,L2=>L3则表中S4的位置为null. L1=>L2,L3则表中S2的位置为null。OP代表推到符号=>)CREATE TABLE CONFIDENCE ("S1" VARCHAR2(10 BYTE), "S2" VARCHAR2(10 BYTE), "OP" VARCHAR2(10 BYTE), "S3" VARCHAR2(10 BYTE), "S4" VARCHAR2(10 BYTE), "CONFIDENCELEVEL" NUMBER );
--------------------------(1)-------------------------------------生成频繁1项集频繁2项集和候选3项集----------------------在建表和插入数据之后更改代码中的支持度直接运行即可----------------------DECLARE SUPPORT NUMBER;--支持度 TYPE T_NUM_TAB IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; TYPE T_NUM_VAR IS TABLE OF T_NUM_TAB INDEX BY BINARY_INTEGER; M T_NUM_VAR;--二维数组(矩阵) TRADE_NO NUMBER;--每一次的交易号 X NUMBER; Y NUMBER; P_NO NUMBER;--产品的总数量 NUM NUMBER;--表中的辅助变量 CURSOR TRADE_CURSOR IS SELECT DISTINCT(TRADE_ID) FROM TRADE_LIST ORDER BY TRADE_ID; CURSOR X_CURSOR IS SELECT PRODUCT FROM TRADE_LIST WHERE TRADE_ID=TRADE_NO ORDER BY PRODUCT; CURSOR Y_CURSOR IS SELECT PRODUCT FROM TRADE_LIST WHERE TRADE_ID=TRADE_NO ORDER BY PRODUCT;BEGIN SUPPORT:=7; NUM:=1; /*矩阵初始化为全0*/ SELECT COUNT(P_ID) INTO P_NO FROM PRODUCT_ID; FOR I IN 1..P_NO LOOP FOR J IN 1..P_NO LOOP M(I)(J):=0; END LOOP; END LOOP; /*初始化矩阵结束*/ OPEN TRADE_CURSOR; LOOP FETCH TRADE_CURSOR INTO TRADE_NO; EXIT WHEN TRADE_CURSOR%NOTFOUND; /* DBMS_OUTPUT.PUT_LINE('Trade Number:'||TRADE_NO); SELECT COUNT(PRODUCT) INTO LIST_COUNT FROM TRADE_LIST WHERE TRADE_ID=TRADE_NO; DBMS_OUTPUT.PUT_LINE('COUNT:'||LIST_COUNT); */ /*X的游标开始*/ OPEN X_CURSOR; LOOP FETCH X_CURSOR INTO X; EXIT WHEN X_CURSOR%NOTFOUND; -- DBMS_OUTPUT.PUT_LINE('TRADE_NO:'||TRADE_NO||'PRODUCT:'||X); /*Y的游标开始*/ OPEN Y_CURSOR; LOOP FETCH Y_CURSOR INTO Y; EXIT WHEN Y_CURSOR%NOTFOUND; IF X<=Y THEN M(X)(Y):=M(X)(Y)+1; END IF; END LOOP; CLOSE Y_CURSOR; /*Y的游标结束*/ END LOOP; CLOSE X_CURSOR; /*X的游标结束*/ END LOOP; CLOSE TRADE_CURSOR; /*循环输出开始*/ /* FOR I IN 1..M.COUNT LOOP FOR J IN 1..M(I).COUNT LOOP DBMS_OUTPUT.PUT_LINE(M(I)(J)); END LOOP; END LOOP; */ /*循环输出结束*/ /*生成频繁1项集*/ DELETE FROM AprioriSet1; FOR I IN 1..P_NO LOOP IF M(I)(I)>=SUPPORT THEN INSERT INTO AprioriSet1 VALUES(I,M(I)(I)); END IF; END LOOP; /*生成频繁1项集结束*/ /*生成频繁2项集*/ DELETE FROM AprioriSet2; FOR I IN 1..P_NO LOOP FOR J IN I+1..P_NO LOOP IF M(I)(J)>=SUPPORT THEN INSERT INTO AprioriSet2 VALUES(I,J,M(I)(J)); END IF; END LOOP; END LOOP; /*生成频繁2项集结束*/ /*生成候选3项集*/ DELETE FROM APRIORIC3; FOR I IN 1..P_NO LOOP FOR J IN I+1..P_NO LOOP IF M(I)(J)>=SUPPORT THEN FOR K IN J+1..P_NO LOOP IF M(J)(K)>=SUPPORT AND M(I)(K)>=SUPPORT THEN INSERT INTO APRIORIC3(SET1,SET2,SET3,SUPPORTCOUNT,C_ID) VALUES(I,J,K,0,NUM); NUM:=NUM+1; END IF; END LOOP; END IF; END LOOP; END LOOP; /*生成候选3项集结束*/END;
----------------------------(2)--------------------------------------------------------由候选3项集生成频繁3项集---------------------------------------------修改支持度即可-----------------------------------DECLARE T_ID NUMBER;----选择购物种类大于等于3的交易号P_ID NUMBER;A1 NUMBER;--A1,A2,A3复制0,1,用于逻辑处理判断A2 NUMBER;A3 NUMBER;SUPPORT NUMBER;--支持度CURSOR T_CURSOR IS SELECT DISTINCT(TRADE_ID) FROM TRADE_LIST GROUP BY TRADE_ID HAVING COUNT(PRODUCT)>=3;CURSOR P_CURSOR IS SELECT PRODUCT FROM TRADE_LIST WHERE TRADE_ID=T_ID;CURSOR C_CURSOR IS SELECT * FROM APRIORIC3;C3 C_CURSOR%ROWTYPE;--利用游标从候选3项集中选出来的一行BEGIN SUPPORT:=7; A1:=0; A2:=0; A3:=0; UPDATE APRIORIC3 SET SUPPORTCOUNT=0; OPEN C_CURSOR; LOOP FETCH C_CURSOR INTO C3; EXIT WHEN C_CURSOR%NOTFOUND; OPEN T_CURSOR; LOOP FETCH T_CURSOR INTO T_ID; EXIT WHEN T_CURSOR%NOTFOUND; OPEN P_CURSOR; LOOP FETCH P_CURSOR INTO P_ID; EXIT WHEN P_CURSOR%NOTFOUND; /*对每一条大于3项的记录都对候选3项集中的所有数据进行检索*/ DBMS_OUTPUT.PUT_LINE('L'||P_ID); IF P_ID=C3.SET1 THEN A1:=1; DBMS_OUTPUT.PUT_LINE('SET1-L'||P_ID); END IF; IF P_ID=C3.SET2 THEN A2:=1; DBMS_OUTPUT.PUT_LINE('SET2-L'||P_ID);END IF; IF P_ID=C3.SET3 THEN A3:=1; DBMS_OUTPUT.PUT_LINE('SET3-L'||P_ID);END IF; IF A1=1 AND A2=1 AND A3=1 THEN UPDATE APRIORIC3 SET SUPPORTCOUNT=SUPPORTCOUNT+1 WHERE C_ID=C3.C_ID; A1:=0; A2:=0; A3:=0; DBMS_OUTPUT.PUT_LINE('UPDATE'); END IF; END LOOP; CLOSE P_CURSOR; A1:=0; A2:=0; A3:=0; END LOOP; CLOSE T_CURSOR; END LOOP; CLOSE C_CURSOR; /*生成频繁3项集*/ DELETE FROM AprioriSet3; OPEN C_CURSOR; LOOP FETCH C_CURSOR INTO C3; EXIT WHEN C_CURSOR%NOTFOUND; IF C3.SUPPORTCOUNT>=SUPPORT THEN INSERT INTO APRIORISET3 VALUES(C3.SET1,C3.SET2,C3.SET3,C3.SUPPORTCOUNT); END IF; END LOOP; CLOSE C_CURSOR; /*生成频繁3项集结束*/END;
---------------------------------------------------------------------------------(3)--------------------------------------------------置信度计算-------------------------DECLARE NUM1 NUMBER; NUM2 NUMBER; NUM3 NUMBER; LEVEL1 NUMBER; LEVEL2 NUMBER; LEVEL3 NUMBER; CURSOR CONFIDENCE_CURSOR IS SELECT * FROM APRIORISET3; L3 CONFIDENCE_CURSOR%ROWTYPE; CONFIDENCE_LEVEL NUMBER; --给定置信度BEGIN DELETE FROM CONFIDENCE; CONFIDENCE_LEVEL:=0.8; OPEN CONFIDENCE_CURSOR; LOOP FETCH CONFIDENCE_CURSOR INTO L3; EXIT WHEN CONFIDENCE_CURSOR%NOTFOUND; /*一项推二项开始L1=>L2,L3*/ SELECT SUPPORTCOUNT INTO NUM1 FROM APRIORISET1 WHERE SET1=L3.SET1; SELECT SUPPORTCOUNT INTO NUM2 FROM APRIORISET1 WHERE SET1=L3.SET2; SELECT SUPPORTCOUNT INTO NUM3 FROM APRIORISET1 WHERE SET1=L3.SET3; LEVEL1:=L3.SUPPORTCOUNT/NUM1; LEVEL2:=L3.SUPPORTCOUNT/NUM2; LEVEL3:=L3.SUPPORTCOUNT/NUM3; IF LEVEL1>=CONFIDENCE_LEVEL THEN INSERT INTO CONFIDENCE(S1,S2,OP,S3,S4,CONFIDENCELEVEL) VALUES('L'||L3.SET1,'','=>','L'||L3.SET2,'L'||L3.SET3,LEVEL1); END IF; IF LEVEL2>=CONFIDENCE_LEVEL THEN INSERT INTO CONFIDENCE(S1,S2,OP,S3,S4,CONFIDENCELEVEL) VALUES('L'||L3.SET2,'','=>','L'||L3.SET1,'L'||L3.SET3,LEVEL2); END IF; IF LEVEL3>=CONFIDENCE_LEVEL THEN INSERT INTO CONFIDENCE(S1,S2,OP,S3,S4,CONFIDENCELEVEL) VALUES('L'||L3.SET3,'','=>','L'||L3.SET1,'L'||L3.SET2,LEVEL3); END IF; /*一项推二项结束L1=>L2,L3*/ /*二项推一项开始L1,L2=>L3*/ SELECT SUPPORTCOUNT INTO NUM1 FROM APRIORISET2 WHERE SET1=L3.SET1 AND SET2=L3.SET2; SELECT SUPPORTCOUNT INTO NUM2 FROM APRIORISET2 WHERE SET1=L3.SET1 AND SET2=L3.SET3; SELECT SUPPORTCOUNT INTO NUM3 FROM APRIORISET2 WHERE SET1=L3.SET2 AND SET2=L3.SET3; LEVEL1:=L3.SUPPORTCOUNT/NUM1; LEVEL2:=L3.SUPPORTCOUNT/NUM2; LEVEL3:=L3.SUPPORTCOUNT/NUM3; IF LEVEL1>=CONFIDENCE_LEVEL THEN INSERT INTO CONFIDENCE(S1,S2,OP,S3,S4,CONFIDENCELEVEL) VALUES('L'||L3.SET1,'L'||L3.SET2,'=>','L'||L3.SET3,'',LEVEL1); END IF; IF LEVEL2>=CONFIDENCE_LEVEL THEN INSERT INTO CONFIDENCE(S1,S2,OP,S3,S4,CONFIDENCELEVEL) VALUES('L'||L3.SET1,'L'||L3.SET3,'=>','L'||L3.SET2,'',LEVEL2); END IF; IF LEVEL3>=CONFIDENCE_LEVEL THEN INSERT INTO CONFIDENCE(S1,S2,OP,S3,S4,CONFIDENCELEVEL) VALUES('L'||L3.SET2,'L'||L3.SET3,'=>','L'||L3.SET1,'',LEVEL3); END IF; /*二项推一项结束L1,L2=>L3*/ END LOOP; CLOSE CONFIDENCE_CURSOR;END;
- Apriori算法(矩阵)
- Apriori算法 (先验算法)
- Apriori算法(关联算法)
- Apriori算法实现(java)
- Apriori算法学习(一)
- Apriori算法笔记(二)
- Apriori算法
- Apriori算法
- Apriori算法
- apriori 算法
- Apriori算法
- Apriori算法
- Apriori算法
- Apriori算法
- Apriori算法
- Apriori算法
- Apriori算法
- Apriori算法
- 黑马程序员_java语法基础【1】(关键字,标识符,注释,常量与变量,运算符)
- Vijos P1016北京2008的挂钟
- Windows学习笔记6——窗口与消息<四>
- js实现复制到剪贴板功能,兼容所有浏览器
- mysql与Hibernate的整合
- Apriori算法(矩阵)
- 项目变更一定要有书面的确认
- C语言实现线性存储之连续存储
- 图片等比例缩放居中放置
- Visual formatting model(图)
- Haar特征与积分图
- Java String.split()用法小结
- 油田合并
- poj 1966 Cable TV Network 点连通度