Spark FPGrowth关联规则算法

关联规则挖掘最经典的例子就是购物篮分析。也就是根据顾客购买行为模式,分析出商品与商品之间的联系。比如买了炸鸡,和可能接下来去买啤酒。这对于商品的布局,库存安排以及商业推销都有很大帮助。

而我项目中也用到了关联规则算法,第一个是挖掘店铺和店铺之间的关系,第二个是挖掘店铺内商品与商品之间的关系。(这点我觉得分析意义不大,因为店铺内其实数据不大,种类也不是很多,挖掘的意义不大,但是领导有安排,咱就得做。不过对于超市来说还是非常有意义的。)

 

挖掘计算出来最终得到3个指标,还是以啤酒和尿布来解释,我看过网上很多对这三个概念的解释,很多人提升度基本上都解释错了。而且也只说明了支持度怎么计算,置信度,提升度根本就没有计算,也没有代码参考。

 

这里假如1000个消费者购买了商品,购买了尿布的人有800个,购买了啤酒的人有400个,同时购买了尿布和啤酒的人有200个。

这里要说明下,买啤酒>买尿布和买尿布>买啤酒是两种不同的情况,但是它们的支持度和提升度是一样的,置信度不一样。

支持度:同时购买了尿布和啤酒的人占比。200/1000=20%

置信度:

              购买了尿布后购买啤酒的人占比。200/800=25%

              购买了啤酒后购买尿布的人占比。200/400=50%

提升度:购买了尿布后购买啤酒的人占比(置信度)/购买啤酒的人占比 = 25%/40%=62.5%

               购买了啤酒后购买尿布的人占比(置信度)/购买尿布的人占比 = 50%/80%=62.5%

至于我刚才说的结论为什么是这样,大家可以利用下面的公式推导一下。

支持度 假设存在关联规则A⇒B,此规则支持度为: support(A⇒B)=count(A⋃B)/|T|=P(A⋃B)
置信度 假设存在关联规则A⇒B,此规则置信度为: confidence(A⇒B)=P(A⋃B)/P(A)=support(A⇒B)/support(A)
提升度 假设存在关联规则A⇒B,此规则提升度为: Lift(A⇒B)=confidence(A⇒B)/support(B)

 

说完基本概念(对fpgrwoth不知道是什么的先查查其他资料),这里再说下spark实现的fpgrowth做了什么。

spark提供的fpgrowth计算出了频繁项集,然后提供了一个generateAssociationRules方法,但是这个方法最后返回的rdd只有前后项以及置信度,真是想不通,为啥功能只做了一半,没有返回支持度和提升度。所以我们只能自己实现了。

 

自己实现的代码:

//计算出频繁项集
val model = new FPGrowth().
      setMinSupport(minSupport).
      setNumPartitions(numPartition).
      run(data)

//计算出总量
val count = data.count()

//注解1
val modelFilter: RDD[FPGrowth.FreqItemset[String]] = model.freqItemsets.filter(_.items.length <= 2)

modelFilter.cache()

//注解2
val candidates = modelFilter.flatMap { itemset =>
   val items = itemset.items
   items.flatMap { item =>
   items.partition(_ == item) match {
        case (consequent, antecedent) if !antecedent.isEmpty =>
            Some((antecedent.toSeq.head, (consequent.toSeq.head, itemset.freq)))
        case _ => None
     }
   }
}

//注解3
val singleItmes: RDD[(String, Long)] = modelFilter.filter(_.items.length == 1).map( x =>(x.items.head,x.freq))

//注解4,计算出支持度,置信度,提升度
val result = candidates.join(singleItmes).map(x => (x._2._1._1,(x._1,x._2._1._2,x._2._2))).join(singleItmes)
      //前项,后项,前项频繁值/总数=支持度,前后项频繁值/前项频繁值=置信度,前后项频繁值/前项频繁值/后项频繁值*总数=提升度
      .map(x => (x._2._1._1,x._1,x._2._1._2.toDouble/ count,x._2._1._2.toDouble /x._2._1._3.toDouble,x._2._1._2.toDouble /x._2._1._3.toDouble/x._2._2.toDouble * count))
      .filter(_._4 >= minConfidence)
      .map(x => (x._1, x._2, f"${x._3}%.5f", f"${x._4}%.5f",  f"${x._5}%.5f"))

modelFilter.unpersist()
result

代码说明:

这段代码的注解2是来自源码的AssociationRules.scala,主要是过滤掉前后项为空的数据。

注解1和注解3的代码都是我自己加的,大家可以自行选择是否需要。主要功能是频繁项集太多太多了。比如买了AB,可能买C的情况,买了ABD,可能买C的情况。而我添加的这段代码就是过滤出来A>B,A>C,也就是说我只考虑单项对单项的情况,不考虑复杂项的情况。

注解4就是核心代码了,计算支持度,置信度,提升度。计算的公式前面也给大家了,套进去就行了,每一项的说明我在代码里也都注释了。 

 

你可能感兴趣的:(机器学习,Spark,机器学习,spark,mllib,FPGrowth,关联规则算法)