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就是核心代碼了,計算支持度,置信度,提升度。計算的公式前面也給大家了,套進去就行了,每一項的說明我在代碼裏也都註釋了。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章