关联分析挖掘算法

场景:假设有100条购买记录,其中60条记录购买了啤酒,40条记录购买了尿布,30条记录既购买了啤酒又购买了尿布。

项集的概念:

一个或多个项(此处是商品)组成的集合。
如:
【啤酒】是一个项集,
【尿布】是一个项集,
【啤酒,尿布】是一个项集。
项集里面的项没有顺序,且不能重复出现。如【啤酒,尿布】和【尿布,啤酒】是同一个项集。
【啤酒,啤酒,尿布】不是一个有效项集,要处理成【啤酒,尿布】才能输入算法。

支持度(support):

项集出现的概率就是此项集的支持度。
【啤酒】支持度:60%
【尿布】支持度:40%
【啤酒,尿布】支持度:30%

关联规则(lift):

关联规则通过对项集进行分析获得,其表示项集内某些项的出现对另一些项出现的影响,寻找有效的关联规则是关联分析挖掘的目的。关联规则可以用以下方式表示
【啤酒->尿布】这条规则表示:一次购买行为中购买啤酒对购买尿布造成的影响。
【尿布->啤酒】这条规则表示:一次购买行为中购买尿布对购买啤酒造成的影响。
注意:上面这两条规则并不相同。

置信度(confidence):

置信度是描述关联规则的指标。
【啤酒->尿布】的置信度=【啤酒,尿布】支持度/【啤酒】支持度=50%(表示了在含有购买啤酒的购买记录中,购买尿布的概率。也就是购买尿布在购买啤酒行为已经发生的条件下的条件概率。)
【尿布->啤酒】的置信度=【尿布,啤酒】支持度/【尿布】支持度=75%

提升度:

用来衡量一些项的出现和另一些项的出现是否存在相互影响。
如:购买记录中啤酒的出现和尿布的出现是否相互影响,就可以看提升度这个指标。
【啤酒->尿布】的提升度和【尿布->啤酒】的提升度是相等的。
提升度等于1说明购买啤酒和购买尿布相互独立没有影响。
提升度小于1说明购买啤酒和购买尿布之间互斥(也就是说买啤酒的时候同时买尿布的可能性小于不买啤酒的时候买尿布的可能性)。
提升度大于1说明购买啤酒和尿布正相关。一般取参考值为3。

提升度的算法:
【啤酒->尿布】提升度=【啤酒->尿布】置信度/【尿布】支持度=【啤酒,尿布】支持度/(【啤酒】支持度*【尿布】支持度)
【尿布->啤酒】提升度=【尿布->啤酒】置信度/【啤酒】支持度=【尿布,啤酒】支持度/(【尿布】支持度*【啤酒】支持度)


weka中还有两个指标,跟提升度差不多:杠杆率(leverage)确信度(conviction)

leverage:

P(A,B)P(A)P(B)P(A,B)-P(A)P(B),为0时A和B独立,越大A和B的关系越密切。

conviction:

P(A)P(!B)/(P(A,!B)+1/K)P(A)P(!B)/(P(A,!B)+1/K) ,(!B表示B没有发生,K表示总条目数量) 也是用来衡量A和B的独立性。


spark中用FPGrowth算法进行关联分析挖掘。此算法是Apriori算法的改良版,只需对原始数据集进行两次扫描处理,构建FP Tree然后就能计算出所有频繁项集。
以下是一个完整的例子:
由于spark中没有提供直接计算提升度的方法,所以自己进行计算

import org.apache.spark.mllib.fpm._

data.cache //RDD[Array[String]],其每一行是一条“购买记录”,每条记录中的项不能重复,否则会报异常。
val numS = data.count
val minSupport = 0.1 //最小支持度
val fpmodel = new FPGrowth().setMinSupport(minSupport).run(data) //FPGrowthModel[String],包含达到最小支持度要求的所有频繁项集和其出现频次 
val freqItemsRDD = fpmodel.freqItemsets //RDD[FPGrowth.FreqItemset[String]]频繁项集集合,每个FPGrowth.FreqItemset[String]描述一个频繁项集,有一个字符串和其频次信息。
freqItemsRDD.cache
freqItemsRDD.count //查看频繁项集数量
freqItemsRDD.foreach(s => println(s.items.mkString("[", ",", "]") + " : " + s.freq)) //查看频繁项集及频次,[啤酒] : 60

val minConfidence = 0.6 //最小置信度
val arules = fpmodel.generateAssociationRules(minConfidence) //RDD[AssociationRules.Rule[String]]关联规则集合,每个AssociationRules.Rule[String]包含规则的条件,结果和置信度。如【尿布->啤酒】尿布为条件,啤酒为结果,置信度为minConfidence-1的浮点数。
arules.count  //查看关联规则数量
arules.foreach(s => println(s.antecedent.mkString("[",",", "]") + " ----> " + s.consequent.mkString("[",",", "]") + " : " + s.confidence)) //查看关联规则及置信度

val minUpdence = 3.0 //最小提升度
val zcd = freqItemsRDD.filter(item => item.items.length == 1).map(item => (item.items.apply(0), item.freq)).collect.toMap.map(s => (s._1, s._2*1.0/numS)) //获取所有单项项集及其支持度的映射Map
val arules_with_updence = for(rule <- arules.collect) yield {  //Array[(AssociationRules.Rule[String], Double)]所有规则和其提升度的二元组数组
	val consequent = rule.consequent.apply(0).toString
	val confidence = rule.confidence
	val tsd = confidence/zcd(consequent)
	(rule , tsd)
}
//arules_with_updence.foreach(s => println(s._1.antecedent.mkString("[",",", "]") + " ----> " + s._1.consequent.mkString("[",",", "]") + " : " + s._1.confidence + " updence: " + s._2)) //输出所有规则和其置信度、提升度信息
val res = arules_with_updence.filter(s => s._2 > minUpdence) //过滤提升度大于最小提升度的规则
res.length  //获取规则的数量
res.foreach(s => println(s._1.antecedent.mkString("[",",", "]") + " ----> " + s._1.consequent.mkString("[",",", "]") + " : " + s._1.confidence + " updence: " + s._2)) //输出规则
posted @ 2018-12-23 00:30  xuejianbest  阅读(293)  评论(0编辑  收藏  举报