關聯規則挖掘最經典的例子就是購物籃分析。也就是根據顧客購買行爲模式,分析出商品與商品之間的聯繫。比如買了炸雞,和可能接下來去買啤酒。這對於商品的佈局,庫存安排以及商業推銷都有很大幫助。
而我項目中也用到了關聯規則算法,第一個是挖掘店鋪和店鋪之間的關係,第二個是挖掘店鋪內商品與商品之間的關係。(這點我覺得分析意義不大,因爲店鋪內其實數據不大,種類也不是很多,挖掘的意義不大,但是領導有安排,咱就得做。不過對於超市來說還是非常有意義的。)
挖掘計算出來最終得到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就是核心代碼了,計算支持度,置信度,提升度。計算的公式前面也給大家了,套進去就行了,每一項的說明我在代碼裏也都註釋了。