阅读的文章:
https://zhuanlan.zhihu.com/p/78166580
https://zhuanlan.zhihu.com/p/79412570
解析:
1、现象:
啤酒与尿不湿的故事 => 两个看似不相干的东西放一起,销量双双增加。
2、目的:
找出物品之间的关联规则,将两个商品放在一起,双双提升销量。
3、做法:
这些是一个超市里面的一部分购买商品记录:
3.1、关联分析涉及的几个概念
- 支持度:support,也即物品的流行程度
支持度 = (包含物品A的记录数量) / (总的记录数量) 得到了物品A的支持度
=(同时包含物品A、B的记录数量) / (总的记录数量) 得到了物品(A,B)的支持度
具体来讲牛奶的支持度为:牛奶在5次交易中出现的次数 / 交易的总次数,即3/5,注意我们也可以统计两个物品同时出现的支持度比如(牛奶和鸡蛋)的支持度为:牛奶与鸡蛋一起出现的订单次数 / 交易总次数,即2/5
- 置信度:confidence,也即买了A就会买B的可能性
置信度(A -> B)= (同时包含物品A和B的记录数) / (包含A的记录数)
具体来讲:(鸡蛋,牛奶)一起购买的次数是2,(鸡蛋)的购买次数是4次,那么confidence(鸡蛋 -> 牛奶) = 2 / 4
- 提升度:lift,也即当卖了一个物品时另一个物品的销售率会增加多少
提升度(A -> B) =置信度(A -> B)/ (支持度A)
具体来讲:支持度(鸡蛋 -> 牛奶) = 置信度(鸡蛋 -> 牛奶) / 支持度(鸡蛋) = (2/4)/(4/5) = 0.625 ,支持度小于1表示鸡蛋卖的越多牛奶卖的越少。如果支持度等于1则表示卖鸡蛋和卖牛奶没有关联。如果支持度大于1则表示卖鸡蛋有助于卖更多牛奶。
3.2、方法步骤概括
- A、从记录中找出同时出现的物品集合(称作 频繁集项)
- B、从A得到的频繁集的基础上,使用关联规则算法找出其中物品的关联结果
4、使用Apriori算法得到关联规则(或者说进行关联分析)
4.1、算法使用背景
已知支持度计算公式 -> 遍历所有组合 -> 计算其支持度 -> 筛选出大于最小支持度(阈值)的组合 -> 从中筛选出频繁项 -> 计算提升度 -> 找到关联规则
问题在于:遍历所有组合计算量太大。
4.2、Apriori算法的用处
使用思想:如果一个项集是 非频繁项集,那么它的所有超集也是非频繁项集。
具体:假设(AB)为非频繁集,那么虚线框内的它的超集都是非频繁集。这样的话,很多的组合都被去掉了,也就是不用遍历所有的组合了。
4.3、Apriori算法流程
要使用Apriori算法,我们需要提供两个参数,数据集和最小支持度。我们从前面已经知道了Apriori会遍历所有的物品组合,怎么遍历呢?答案就是递归。先遍历1个物品组合的情况,剔除掉支持度低于最小支持度的数据项,然后用剩下的物品进行组合。遍历2个物品组合的情况,再剔除不满足条件的组合。不断递归下去,直到不再有物品可以组合。
4.4、Apriori实战
4.4.1、用到的库是mlxtend,及参数介绍
def apriori(df, min_support=0.5,
use_colnames=False,
max_len=None)
参数如下:
df:这个不用说,就是我们的数据集。
min_support:给定的最小支持度。
use_colnames:默认False,则返回的物品组合用编号显示,为True的话直接显示物品名称。
max_len:最大物品组合数,默认是None,不做限制。如果只需要计算两个物品组合的话,便将这个值设置为2。
4.4.2、使用Apriori算法找到频繁项集
import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori
#设置数据集
dataset = [['牛奶','洋葱','肉豆蔻','芸豆','鸡蛋','酸奶'],
['莳萝','洋葱','肉豆蔻','芸豆','鸡蛋','酸奶'],
['牛奶','苹果','芸豆','鸡蛋'],
['牛奶','独角兽','玉米','芸豆','酸奶'],
['玉米','洋葱','洋葱','芸豆','冰淇淋','鸡蛋']]
te = TransactionEncoder()
#进行 one-hot 编码
te_ary = te.fit(records).transform(records)
df = pd.DataFrame(te_ary, columns=te.columns_)
#利用 Apriori 找出频繁项集
freq = apriori(df, min_support=0.05, use_colnames=True)
首先,需要先将商品进行one-hot编码,编码后用boolean值表示。所谓ont-hot编码呢,直观来说就是有多少个状态就有多少比特,而且只有一个比特为1,其他全为0的一种码制。比如冰淇淋只存在最后一共交易单中,其他交易中都没出现。那冰淇淋就可以用[0,0,0,0,1]来表示。
编码后的数据如下:
冰淇淋 洋葱 牛奶 独角兽 玉米 肉豆蔻 芸豆 苹果 莳萝 酸奶 鸡蛋
0 False True True False False True True False False True True
1 False True False False False True True False True True True
2 False False True False False False True True False False True
3 False False True True True False True False False True False
4 True True False False True False True False False False True
我们设定的最小支持度是0.6,那么只有支持度大于0.6的物品集合才是频繁项集,最终结果如下:
support itemsets
0 0.6 (洋葱)
1 0.6 (牛奶)
2 1.0 (芸豆)
3 0.6 (酸奶)
4 0.8 (鸡蛋)
5 0.6 (芸豆, 洋葱)
6 0.6 (洋葱, 鸡蛋)
7 0.6 (牛奶, 芸豆)
8 0.6 (酸奶, 芸豆)
9 0.8 (芸豆, 鸡蛋)
10 0.6 (芸豆, 洋葱, 鸡蛋)
5、在利用Apriori得到频繁项集后如何得到关联规则
5.1、关联规则 指的就是 置信度和提升度
难点:
在计算置信度时,需要获得物品和其它物品的关联,这种关联由于物品繁多所以关联结果太多。
解决思路:
如果一个关联结果的置信度低,那么它的所有超集的置信度也低。
5.2、具体实例:
使用mlxtend库,计算关联规则的api:
association_rules(df, metric="confidence",
min_threshold=0.8,
support_only=False):
参数介绍:
- df:这个不用说,就是 Apriori 计算后的频繁项集。
- metric:可选值['support','confidence','lift','leverage','conviction']。
里面比较常用的就是置信度和支持度。这个参数和下面的min_threshold参数配合使用。
- min_threshold:参数类型是浮点型,根据 metric 不同可选值有不同的范围,
metric = 'support' => 取值范围 [0,1]
metric = 'confidence' => 取值范围 [0,1]
metric = 'lift' => 取值范围 [0, inf]
support_only:默认是 False。仅计算有支持度的项集,若缺失支持度则用 NaNs 填充。
完整的从原始数据得到关联规则的代码:
import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori
#设置数据集
dataset = [['牛奶','洋葱','肉豆蔻','芸豆','鸡蛋','酸奶'],
['莳萝','洋葱','肉豆蔻','芸豆','鸡蛋','酸奶'],
['牛奶','苹果','芸豆','鸡蛋'],
['牛奶','独角兽','玉米','芸豆','酸奶'],
['玉米','洋葱','洋葱','芸豆','冰淇淋','鸡蛋']]
te = TransactionEncoder()
#进行 one-hot 编码
te_ary = te.fit(records).transform(records)
df = pd.DataFrame(te_ary, columns=te.columns_)
#利用 Apriori 找出频繁项集
freq = apriori(df, min_support=0.05, use_colnames=True)
#导入关联规则包
from mlxtend.frequent_patterns import association_rules
#计算关联规则
result = association_rules(freq, metric="confidence", min_threshold=0.6)
这里我们根据置信度来计算,找出置信度大于0.6的关联规则。
计算结果如下:
我们可以发现,除了置信度(confidence),提升度(lift)外,还有两个指标,leverage和conviction。这两个用得比较少,和置信度,提升度也有些类似,就不展开说了。
要找出最大的置信度,用
result.sort_values(by = 'confidence',ascending=False,axis=1)
上面例子中我们可以发现,{洋葱 -> 鸡蛋,芸豆} 的置信度是 1.00 ,而它们的提升度是 1.25 。这说明买了洋葱的人很可能会再购买 1.25 份的 {鸡蛋,芸豆} 。所以可以让它们放到一起出售。