不知道大家用音乐播放器的时候会不会有听“每日推荐”这个歌单的习惯,当你戴着耳机突然切换到一首从未听过但是非常对味的歌,这种感觉是不是超惊喜呀!
这个看起来很复杂的功能,其实由一个简单易懂的算法就可以实现哟,它就是我们今天的C位——基于关联规则的Apriori算法。
关联规则(association rule),顾名思义就是找到事物之间的关联性,可用来寻找大量变量之间有趣的联系。关联规则学习是无监督的,不需要训练算法,也不需要提前标记数据。基于数据集,就可以简单地运行程序。一个典型的规则可以表述为如下形式:
{轻音乐,古典}
{民谣}
这个规则表达的意思就是:如果爱听轻音乐和古典乐,那么很有可能会爱听民谣。大括号内的事物组合表示它们构成一个集合,被称为项集。关联规则是根据项集的子集研究得到的。
Apriori算法采用一个简单的先验准则来减少关联规则的搜索空间:一个频繁项集的所有子集一定是频繁的,一个不频繁的项集的所有父集一定是不频繁的。基于这条规则,可以有效限制搜索规则的次数。例如,如果集合{轻音乐,古典}是频繁的,当且仅当{轻音乐}和{古典}同时频繁地发生。因此,如果轻音乐或者古典中只要有一个是非频繁的,那么任意一个含有这两项的集合都可以从搜索中删除。
支持度(
):项集在数据中出现的频率,定义公式为:
置信度(
):该规则的预测能力或者准确度的度量,定义公式为:
提升度(
):度量一类事物相对于它的一般选择率,此时被选择的可能性有多大,定义公式为:
通过对这些统计量设置阈值并结合Apriori原则,能够大幅度地限制报告的规则数。
:识别所有满足最小支持度阈值的项集。
:根据满足最小置信度阈值的项集来创建规则。
通过对31位同学的调查,获取了他们"我喜爱“歌单里的部分歌手信息,数据集比较小,仅用于算法练习。若需要进行专业的数据分析,可利用工具爬取大量数据。原始的singer.csv文件部分数据如下所示:
事务性数据是无法直接被利用的,为解决此问题采用了一个称为稀疏矩阵的数据结构,稀疏矩阵的每一行表示一个项集,每一列表示项集中的一个事物。
#安装和加载arules程序包
install.packages("arules")
library(arules)
singer<-read.transactions("singer.csv",sep = ",")
如果想查看singer数据集的一些基本信息,可以使用summary()
函数,从运行结果中可以看出包含3个或4个事物的项集个数居多,出现频率最高的是“五月天”和“周杰伦”。
> summary(singer)
transactions as itemMatrix in sparse format with
35 rows (elements/itemsets/transactions) and
31 columns (items) and a density of 0.1225806
most frequent items:
五月天 周杰伦 王力宏 blackpink 林俊杰 (Other)
15 15 8 7 7 81
element (itemset/transaction) length distribution:
sizes
2 3 4 5 6
2 12 14 5 2
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.0 3.0 4.0 3.8 4.0 6.0
使用inspect()
函数可以查看稀疏矩阵的内容:
> inspect(singer[1:6])
items
[1] {方大同,林俊杰,王力宏,五月天,周杰伦}
[2] {蔡健雅,陈粒,孙燕姿,五月天}
[3] {blackpink,exo,刘瑞琦,温岚,五月天,周杰伦}
[4] {blackpink,BTS,EXO,ITZY,mino,twice}
[5] {陈奕迅,林俊杰,田馥甄,五月天}
[6] {林宥嘉,刘瑞琦,王力宏,五月天,周杰伦}
要想计算每个歌手的支持度(默认按字母顺序排序):
> itemFrequency(singer)
Beyond blackpink BTS exo EXO
0.02857143 0.20000000 0.11428571 0.02857143 0.08571429
ITZY Justin bieber mino twice 八三幺
0.05714286 0.02857143 0.02857143 0.05714286 0.08571429
蔡健雅 曹格 陈粒 陈奕迅 方大同
0.08571429 0.05714286 0.05714286 0.17142857 0.08571429
李宇春 林俊杰 林宥嘉 刘瑞琦 刘若英
0.11428571 0.20000000 0.08571429 0.11428571 0.14285714
刘思鉴 孙燕姿 陶喆 田馥甄 王力宏
0.14285714 0.20000000 0.08571429 0.05714286 0.22857143
温岚 五月天 伍佰 张杰 张艺兴
0.14285714 0.42857143 0.11428571 0.05714286 0.08571429
周杰伦
0.42857143
itemFrequencyPlot(singer,support=0.1)
Freq<-itemFrequency(singer)
Fre<-as.data.frame(Freq)
Fre$word<-row.names(Fre)
Fre$freq<-Freq
Fre<-Fre[,-1]
wordcloud2(Fre,size=0.4)
itemFrequencyPlot(singer,topN=5)
image(singer)
R语言为我们提供了功能强大的apriori()
函数,不需要复杂的代码就可实现探寻功能。虽然运行apriori()
函数很简单,但是需要我们去寻找合适的支持度和置信度参数,参数设置过高可能会发现没有规则或者找到无用的规则。阈值设置过低可能会导致规则的数量过多,使得算法运行时间变长。
#使用apriori的默认参数值:support=0.1,confidence=0.8
>apriori(singer)
set of 2 rules
使用默认参数值只找到两条规则,显然是不够的,需要修改参数值。
>singerrules<-apriori(singer,parameter = list(support=0.06,confidence=0.4,minlen=2))
> singerrules
set of 15 rules
> inspect(singerrules[1:5])
lhs rhs support confidence coverage lift count
[1] {刘瑞琦} => {周杰伦} 0.08571429 0.7500000 0.1142857 1.75 3
[2] {BTS} => {blackpink} 0.08571429 0.7500000 0.1142857 3.75 3
[3] {blackpink} => {BTS} 0.08571429 0.4285714 0.2000000 3.75 3
[4] {温岚} => {周杰伦} 0.08571429 0.6000000 0.1428571 1.40 3
[5] {孙燕姿} => {五月天} 0.08571429 0.4285714 0.2000000 1.00 3
> summary(singerrules)
set of 15 rules
rule length distribution (lhs + rhs):sizes
2 3
12 3
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.0 2.0 2.0 2.2 2.0 3.0
summary of quality measures:
support confidence coverage lift
Min. :0.08571 Min. :0.4286 Min. :0.1143 Min. :1.000
1st Qu.:0.08571 1st Qu.:0.4833 1st Qu.:0.1571 1st Qu.:1.167
Median :0.11429 Median :0.5714 Median :0.2000 Median :1.556
Mean :0.13143 Mean :0.6156 Mean :0.2286 Mean :1.903
3rd Qu.:0.15714 3rd Qu.:0.7083 3rd Qu.:0.2286 3rd Qu.:2.333
Max. :0.22857 Max. :1.0000 Max. :0.4286 Max. :3.750
mining info:
data ntransactions support confidence
singer 35 0.06 0.4
在我们找到的规则集中,有12个规则包含2位歌手,3个规则包含3位歌手。
> inspect(singerrules[1:3])
lhs rhs support confidence coverage lift count
[1] {刘瑞琦} => {周杰伦} 0.08571429 0.7500000 0.1142857 1.75 3
[2] {BTS} => {blackpink} 0.08571429 0.7500000 0.1142857 3.75 3
[3] {blackpink} => {BTS} 0.08571429 0.4285714 0.2000000 3.75 3
第一条规则简单意思就是“如果一个用户喜欢听刘瑞琦的歌,那么她还会听周杰伦的歌。”其支持度大约为0.0857,置信度为0.75,我们可以确定该条规则涵盖了大约8.57%的用户,而且涉及“刘瑞琦”收听的正确率为75%。这条规则也是存在一定合理逻辑的,刘瑞琦就是因为翻唱周杰伦的歌出名,听完翻唱觉得歌不错再去听原唱也是很有可能的。
常受关注的是高支持度、高置信度的规则,但如果大多数或者所有规则都非常接近最小阈值,那我们还需要关注规则的提升度,
,这意味着这两类歌手同时出现在用户喜爱歌单里比只出现一位歌手更常见。因此,一个大的提升度值是一个重要的指标,它表明一个规则是很重要的,反映了事物之间的真实联系。
> inspect(sort(singerrules,by="lift")[1:4])
lhs rhs support confidence coverage
[1] {BTS} => {blackpink} 0.08571429 0.7500000 0.1142857
[2] {blackpink} => {BTS} 0.08571429 0.4285714 0.2000000
[3] {五月天,周杰伦} => {王力宏} 0.11428571 0.5714286 0.2000000
[4] {王力宏} => {周杰伦} 0.22857143 1.0000000 0.2285714
lift count
[1] 3.750000 3
[2] 3.750000 3
[3] 2.500000 4
[4] 2.333333 8
当你需要找到包含“周杰伦”的所有规则时,可以利用subset()
函数:
> sub<-subset(singerrules,items %in% "周杰伦")
> inspect(sub)
lhs rhs support confidence coverage lift
[1] {刘瑞琦} => {周杰伦} 0.08571429 0.7500000 0.1142857 1.750000
[2] {温岚} => {周杰伦} 0.08571429 0.6000000 0.1428571 1.400000
[3] {王力宏} => {周杰伦} 0.22857143 1.0000000 0.2285714 2.333333
[4] {周杰伦} => {王力宏} 0.22857143 0.5333333 0.4285714 2.333333
[5] {周杰伦} => {五月天} 0.20000000 0.4666667 0.4285714 1.088889
[6] {五月天} => {周杰伦} 0.20000000 0.4666667 0.4285714 1.088889
[7] {王力宏,周杰伦} => {五月天} 0.11428571 0.5000000 0.2285714 1.166667
[8] {王力宏,五月天} => {周杰伦} 0.11428571 1.0000000 0.1142857 2.333333
[9] {五月天,周杰伦} => {王力宏} 0.11428571 0.5714286 0.2000000 2.500000
#将关联规则保存到文件
write(singerrules,file = "singerrules.csv",sep=",",quote=T,row.names=F)
生成的表格如下所示:
#将关联规则保存到数据框
> singerframe<-as(singerrules,"data.frame")
> singerframe
rules support confidence coverage lift
1 {刘瑞琦} => {周杰伦} 0.08571429 0.7500000 0.1142857 1.750000
2 {BTS} => {blackpink} 0.08571429 0.7500000 0.1142857 3.750000
3 {blackpink} => {BTS} 0.08571429 0.4285714 0.2000000 3.750000
4 {温岚} => {周杰伦} 0.08571429 0.6000000 0.1428571 1.400000
5 {孙燕姿} => {五月天} 0.08571429 0.4285714 0.2000000 1.000000
6 {陈奕迅} => {五月天} 0.11428571 0.6666667 0.1714286 1.555556
7 {林俊杰} => {五月天} 0.11428571 0.5714286 0.2000000 1.333333
8 {王力宏} => {周杰伦} 0.22857143 1.0000000 0.2285714 2.333333
9 {周杰伦} => {王力宏} 0.22857143 0.5333333 0.4285714 2.333333
10 {王力宏} => {五月天} 0.11428571 0.5000000 0.2285714 1.166667
11 {周杰伦} => {五月天} 0.20000000 0.4666667 0.4285714 1.088889
12 {五月天} => {周杰伦} 0.20000000 0.4666667 0.4285714 1.088889
13 {王力宏,周杰伦} => {五月天} 0.11428571 0.5000000 0.2285714 1.166667
14 {王力宏,五月天} => {周杰伦} 0.11428571 1.0000000 0.1142857 2.333333
15 {五月天,周杰伦} => {王力宏} 0.11428571 0.5714286 0.2000000 2.500000
看完文章是不是发现Apriori算法很好理解呢,通过设置兴趣度的最小阈值就可以去搜寻事物之间的关联模式,一个典型的应用实例就是“购物篮分析”,赶紧动动小手去实践一下吧~需要数据可在公众号后台回复命令关联规则数据
即可。