(1)基于关联规则推荐原理详解
关联规则是反映一个事物与其他事物之间的相互依存性和关联性,常用于实体商店或在线电商的推荐系统:通过对顾客的购买记录数据库进行关联规则挖掘,最终目的是发现顾客群体的购买习惯的内在共性,例如购买产品A的同时也连带购买产品B的概率,根据挖掘结果,调整货架的布局陈列、设计促销组合方案,实现销量的提升,最经典的应用案例莫过于《啤酒和尿布》。
关联规则分析中的关键概念包括:支持度(Support)、置信度(Confidence)与提升度(Lift)
我举一个超市购物的例子,下面是几名客户购买的商品列表:
(1.1)支持度(Support)
支持度是个百分比,它指的是某个商品组合出现的次数与总次数之间的比例。在这个例子中,我们能看到“牛奶”出现了4次,那么这5笔订单中“牛奶”的支持度就是4/5=0.8。
同样“牛奶+面包”出现了3次,那么这5笔订单中“牛奶+面包”的支持度就是3/5=0.6
(1.2)置信度(Confidence)
它指的就是当你购买了商品A,会有多大的概率购买商品B,置信度是个条件概念,就是说在A发生的情况下,B发生的概率是多少
置信度(牛奶→啤酒) =2/4=0.5,代表如果你购买了牛奶,有多大的概率会购买啤酒
置信度(啤酒一牛奶)=2/3=0.67,代表如果你购买了啤酒,有多大的概率会购买牛奶
(1.3)提高度
置信度(啤酒→牛奶)=2/3=0.67,代表如果你购买了啤酒,有多大的概率会购买牛奶
提升度(A→B)=置信度(A→B)/支持度(B)
这个公式是用来衡量A出现的情况下,是否会对B出现的概率有所提升。所以提升度有三种可能:
提升度(A→B)> 1:代表有提升;
提升度(A→B)= 1:代表有没有提升,也没有下降;
提升度(A→B)< 1:代表有下降。
(2)关联规则推荐算法-Apriori原理图例数据详解
Apriori的工作原理
首先我们把上面案例中的商品用ID来代表,牛奶、面包、尿布、可乐、啤酒、鸡蛋的商品ID分别设置为1-6,上面的数据表可以变为:
牛奶一1、面包一2、尿布一3、可乐一4、啤酒一5、鸡蛋一6 1
Apriori 算法其实就是查找频繁项集(frequent itemset)的过程,所以首先我们需要定义什么是频繁项集。
频繁项集就是支持度大于等于最小支持度(Min Support)阈值的项集,所以小于最小值支持度的项目就是非频繁项集,而大于等于最小支持度的的项集就是频繁项集。
项集这个概念,英文叫做itemset,它可以是单个的商品,也可以是商品的组合。
我们再来看下这个例子,假设我随机指定最小支持度是50%,也就是0.5。
我们来看下 Apriori 算法是如何运算的:
首先,我们先计算单个商品的支持度,也就是得到K=1项的支持度:
因为最小支持度是0.5,所以你能看到商品4、6是不符合最小支持度的,不属于频繁项集,于是经过筛选商品的频繁项集就变成:
在这个基础上,我们将商品两两组合,得到k=2项的支持度
在这个基础上,我们将商品两两组合,得到k=2项的支持度,并再筛掉小于最小值支持度的商品组合,可以得到:
我们再将商品进行K=3项的商品组合,可以得到:
再筛掉小于最小值支持度的商品组合,可以得到
通过上面这个过程,我们可以得到K=3项的频繁项集{1,2,3},也就是{牛奶、面包、尿布}的组合。
Apriori算法的递归流程:
1、K=1,计算K项集的支持度;
2、筛选掉小于最小支持度的项集;
3、如果项集为空,则对应K-1项集的结果为最终结果。
否则K=K+1,重复1-3步。
(3)关联规则推荐算法-FP-Growth图例数据详解
Apriori的改进算法:FP-Growth算法
Apriori在计算的过程中有以下几个缺点:
可能产生大量的候选集。因为采用排列组合的方式,把可能的项集都组合出来了;
每次计算都需要重新扫描数据集,来计算每个项集的支持度。
所以 Apriori算法会浪费很多计算空间和计算时间,为此人们提出了FP-Growth算法:
创建了一棵FP树来存储频繁项集。在创建前对不满足最小支持度的项进行删除,减少了存储空间。
整个生成过程只遍历数据集2次,大大减少了计算量。
所以在实际工作中,我们常用FP-Growth来做频繁项集的挖掘,下面我给你简述下FP-Growth的原理。
1.创建项头表 (item header table)
创建项头表的作用是为FP构建及频繁项集挖掘提供索引
这一步的流程是先扫描一遍数据集,对于满足最小支持度的单个项(K=1项集)按照支持度从高到低进行排序,这个过程中删除了不满足最小支持度的项。(第一步遍历数据集就删除了不满足最小支持度的项,降低了时间复杂度;同时降序排列可以公用祖先节点-null点)
项头表包括了项目、支持度,以及该项在FP树中的链表。初始的时候链表为空。
2.构建FP树 (item header table)
因为根据参数阈值,第一次扫描就已经剔除了阈值外的数据,对商品用字母表示
A一牛奶;B一面包;C一尿布;D一可乐;E一啤酒;F一鸡蛋 1
(4)关联规则推荐算法-FP-Growth详解与Spark代码开发
FP-Growth代码开发
package com.similarity import org.apache.spark.ml.fpm.FPGrowth import org.apache.spark.sql.SparkSession object FpGrouthTest { def main(args: Array[String]): Unit = { val spark: SparkSession = SparkSession .builder .appName(this.getClass.getName) .master("local[5]") .getOrCreate // 设置日志等级 spark.sparkContext.setLogLevel("WARN") import spark.implicits._ val dataSet = spark.createDataset(Seq( "A B C", "B C E", "A C E", "B A C E", "B A C" )).map(x => x.split(" ")).toDF("items") val fpGrouth = new FPGrowth().setMinSupport(0.5).setMinConfidence(0.5).setItemsCol("items") val fpModel = fpGrouth.fit(dataSet) // 生成频繁详集 fpModel.freqItemsets.show(false) /** * +---------+----+ * |items |freq| * +---------+----+ * |[C] |5 | * |[A] |4 | * |[A, C] |4 | * |[B] |4 | * |[B, A] |3 | * |[B, A, C]|3 | * |[B, C] |4 | * |[E] |3 | * |[E, C] |3 | * +---------+----+ */ fpModel.associationRules.show(false) fpModel.transform(dataSet).show(false) /** * +------------+----------+ * |items |prediction| * +------------+----------+ * |[A, B, C] |[E] | * |[B, C, E] |[A] | * |[A, C, E] |[B] | * |[B, A, C, E]|[] | * |[B, A, C] |[E] | * +------------+----------+ */ } }
FP-Growth验证