前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >『数据分析』关于亲和性分析的简单案例讲解

『数据分析』关于亲和性分析的简单案例讲解

作者头像
可以叫我才哥
发布2021-08-05 15:23:23
1.1K0
发布2021-08-05 15:23:23
举报
文章被收录于专栏:可以叫我才哥可以叫我才哥

我们的第84篇原创

作者:才哥


大家好,我是才哥。

今天我们简单介绍一个关于亲和性分析的案例,作为后续关联规则分析的启蒙。

以下案例来自《Python数据挖掘入门与实践(第二版)》第一章1.3亲和性分析的简单示例。

我们先通过本案例了解下关于亲和性的一些概念和工作流程,然后再讨论一些相对更优化的处理方案。

注:该书明确说明为了便于理解,有时更加关注代码和工作流程是否清晰易懂,而不是所采用的方法效率是否最优。

1. 什么是亲和性分析

亲和性分析是一种用于计算样本相似度的数据挖掘方法,这个相似度可以出现在以下几种场景:

  • 网站的用户,拓展服务项目或者定向投放广告;
  • 销售的商品,推荐电影或其他商品(猜你喜欢)。

关于亲和性分析,大家估计都会看到以下这个经典的例子:

在美国的零售业有着这样一个传奇故事,沃尔玛百货将他们的纸尿裤和啤酒并排摆在一起销售,结果纸尿裤和啤酒的销量双双增长!

在今天的案例中,为了简化代码方便理解,我们仅考虑同时购买2件商品的情况,比如以下简单的规则:

用户如果购买了商品X,那么也倾向于购买商品Y

这里我们给出2个用来评价规则的数据指标概念:支持度置信度

支持度 是规则在数据集中出现的次数,即匹配规则的样本数,比如同时购买商品X和Y的交易数;

置信度 是衡量匹配规则的准确度的,比如在购买商品X的交易中同时购买商品Y的比例。

2. 案例详解

本节为书中案例介绍,其使用的工具库如下:

  • numpy
  • collections

2.1. 加载数据集

数据集后台回复 955 领取,有兴趣的同学也可以使用numpy自己构建随机数据组。

代码语言:javascript
复制
import numpy as np

dataset_filename = "affinity_dataset.txt"
X = np.loadtxt(dataset_filename)
n_samples, n_features = X.shape
print(f"这份数据集 有 {n_samples} 行 和 {n_features} 列")
print(X[:5])
代码语言:javascript
复制
这份数据集 有 100 行 和 5 列
[[0. 1. 0. 0. 0.]
 [1. 1. 0. 0. 0.]
 [0. 0. 1. 0. 1.]
 [1. 1. 0. 0. 0.]
 [0. 0. 1. 1. 1.]]

这份数据集比较小,一共100行5列数据。这里我们将每行数据看做是一次交易行为每列代表一种商品数字1代表有购买0代表没有购买

对于这5列,分别代表 面包、牛奶、奶酪、苹果和香蕉。比如第一行[0. 1. 0. 0. 0.]显示首次交易中的商品,消费者只购买了牛奶,而没有购买其它商品。

代码语言:javascript
复制
features = ["面包", "牛奶", "奶酪", "苹果", "香蕉"]

接下来,我们开始研究支持度和置信度的计算。

2.2. 求苹果->香蕉的亲和性

根据概念,置信度需要知道支持度中某商品交易数,这里我们拿香蕉举例,看看其交易数。

计算规则:遍历苹果列数据,值为1则计数+1

代码语言:javascript
复制
num_apple_purchases = 0
for sample in X:
    if sample[3] == 1:  # 第4列
        num_apple_purchases += 1
print(f"含苹果的交易数为:{num_apple_purchases}")
代码语言:javascript
复制
含苹果的交易数为:43

接着,我们计算苹果-香蕉的支持度。

计算规则:如果苹果列为1且香蕉列为1,则计数+1

代码语言:javascript
复制
rule_valid = 0
for sample in X:
    if sample[3] == 1:  # 购买了苹果
        if sample[4] == 1:
            # 同时也购买了香蕉
            rule_valid += 1
        else:
            continue
print(f"同时购买苹果和香蕉的交易数为:{rule_valid}")
代码语言:javascript
复制
同时购买苹果和香蕉的交易数为:27

以上两个数值都计算出来后,我们可以很方便的获取苹果—>香蕉置信度

计算规则:用苹果-香蕉的支持度/含苹果的交易数

代码语言:javascript
复制
support = rule_valid  # 支持度
confidence = rule_valid / num_apple_purchases # 置信度
print(f"苹果-香蕉的支持度为 {support}\n苹果—>香蕉的置信度为 {confidence:.3f}")
# Confidence can be thought of as a percentage using the following:
print(f"苹果—>香蕉的置信度百分比为 {confidence*100:.1f}%.")
代码语言:javascript
复制
苹果-香蕉的支持度为 27
苹果—>香蕉的置信度为 0.628
苹果—>香蕉的置信度百分比为 62.8%

至此,我们便计算出了苹果-香蕉支持度为27,也就是同时购买苹果和香蕉的交易数为27;而购买苹果的用户中也购买了香蕉的比例为62.8%,这就是置信度。

接着,我们就可以计算全部组合之间的支持度与置信度数据,然后进行对比分析,接着安排相关策略了。

2.3. 亲和性分析

现在我们需要从数据集中计算所有规则(注意:这里的规则我们还是以2个商品为例,不拓展更多组合)。因此需要创建1个字典用于存储匹配的规则,字典的key是X—>Y,值则是支持度;另外一个字典用于存储对应的X—>Y中X出现的次数。

代码语言:javascript
复制
from collections import defaultdict

# 初始化2个字典
valid_rules = defaultdict(int)
num_occurences = defaultdict(int)

# 计算支持度及X->Y中X出现次数
for sample in X:
    for premise in range(n_features):
        if sample[premise] == 0: 
            continue   
        # 记录X—>Y中X出现的次数
        num_occurences[premise] += 1
        for conclusion in range(n_features):
            if premise == conclusion:  # X—>X是无意义的,跳过
                continue
            if sample[conclusion] == 1:
                # X和Y同时出现,则匹配规则的次数+1
                valid_rules[(premise, conclusion)] += 1
            else:
                continue
support = valid_rules
confidence = defaultdict(float)
# 计算置信度
for premise, conclusion in valid_rules.keys():
    confidence[(premise, conclusion)] = valid_rules[(premise, conclusion)] / num_occurences[premise]
    
#输出结果
for premise, conclusion in confidence:
    premise_name = features[premise]
    conclusion_name = features[conclusion]
    print(f"规则: {premise_name}—>{conclusion_name}")
    print(f" - 置信度: {confidence[(premise, conclusion)]*100:.2f}%")
    print(f" - 支持度: {support[(premise, conclusion)]}")
    print('-'*20)

输出结果如下:

代码语言:javascript
复制
规则: 面包—>牛奶
 - 置信度: 46.43%
 - 支持度: 13
--------------------
规则: 牛奶—>面包
 - 置信度: 25.00%
 - 支持度: 13
--------------------
规则: 奶酪—>香蕉
 - 置信度: 51.28%
 - 支持度: 20
--------------------
规则: 香蕉—>奶酪
 - 置信度: 35.09%
 - 支持度: 20
--------------------
规则: 奶酪—>苹果
 - 置信度: 56.41%
 - 支持度: 22
--------------------
规则: 苹果—>奶酪
 - 置信度: 51.16%
 - 支持度: 22
--------------------
规则: 苹果—>香蕉
 - 置信度: 62.79%
 - 支持度: 27
--------------------
规则: 香蕉—>苹果
 - 置信度: 47.37%
 - 支持度: 27
--------------------
规则: 牛奶—>苹果
 - 置信度: 34.62%
 - 支持度: 18
--------------------
规则: 苹果—>牛奶
 - 置信度: 41.86%
 - 支持度: 18
--------------------
规则: 牛奶—>香蕉
 - 置信度: 51.92%
 - 支持度: 27
--------------------
规则: 香蕉—>牛奶
 - 置信度: 47.37%
 - 支持度: 27
--------------------
规则: 面包—>奶酪
 - 置信度: 17.86%
 - 支持度: 5
--------------------
规则: 奶酪—>面包
 - 置信度: 12.82%
 - 支持度: 5
--------------------
规则: 面包—>香蕉
 - 置信度: 57.14%
 - 支持度: 16
--------------------
规则: 香蕉—>面包
 - 置信度: 28.07%
 - 支持度: 16
--------------------
规则: 牛奶—>奶酪
 - 置信度: 21.15%
 - 支持度: 11
--------------------
规则: 奶酪—>牛奶
 - 置信度: 28.21%
 - 支持度: 11
--------------------
规则: 面包—>苹果
 - 置信度: 32.14%
 - 支持度: 9
--------------------
规则: 苹果—>面包
 - 置信度: 20.93%
 - 支持度: 9
--------------------

我们可以输出置信度前5的规则如下:(大家也可以试着输出支持度前5的规则)

代码语言:javascript
复制
def print_rule(premise, conclusion, support, confidence, features):
    premise_name = features[premise]
    conclusion_name = features[conclusion]
    print(f"规则: {premise_name}—>{conclusion_name}")
    print(f" - 置信度: {confidence[(premise, conclusion)]*100:.2f}%")
    print(f" - 支持度: {support[(premise, conclusion)]}")
    print('-'*20)
    
from operator import itemgetter

sorted_support = sorted(support.items(), key=itemgetter(1), reverse=True)
sorted_confidence = sorted(confidence.items(), key=itemgetter(1), reverse=True)
for index in range(5):
    print("Rule #{0}".format(index + 1))
    (premise, conclusion) = sorted_confidence[index][0]
    print_rule(premise, conclusion, support, confidence, features)

输出结果如下:

代码语言:javascript
复制
Rule #1
规则: 苹果—>香蕉
 - 置信度: 62.79%
 - 支持度: 27
--------------------
Rule #2
规则: 面包—>香蕉
 - 置信度: 57.14%
 - 支持度: 16
--------------------
Rule #3
规则: 奶酪—>苹果
 - 置信度: 56.41%
 - 支持度: 22
--------------------
Rule #4
规则: 牛奶—>香蕉
 - 置信度: 51.92%
 - 支持度: 27
--------------------
Rule #5
规则: 奶酪—>香蕉
 - 置信度: 51.28%
 - 支持度: 20
--------------------

当我们得出以上数据后,就可以进行下一步的销售策略调整了,简单的比如 购买苹果可以获得购买香蕉折扣之类的。具体这里不深入讨论,我们放在后续 关联规则分析中做深入介绍。

3. 算法优化

关于亲和性分析,是有一些数据挖掘算法如Apriori算法来处理的,这里也不展开。那么,这里的算法优化其实是指对案例中非常直接的计算方式进行优化,这里用到的是pandas工具以及我们之前介绍过的itertoolsitertools拼装迭代器与生成器》。

主要是计算支持度的逻辑优化,实现的方式有很多种,大家具体查看代码注释吧。

代码语言:javascript
复制
import pandas as pd

# 将数据集转化为Dataframe类型
df = pd.DataFrame(X, columns=features)

# 先引入该内置标准库
import itertools

# 求组合(顺序不同组合不同)
it = itertools.permutations(features,2)
rules = list(it)

for rule in rules:
    num_occurence = df[rule[0]].sum() # X—>Y中X在整个数据集中出现次数
    num_rule = df.query(f"{rule[0]}+{rule[1]}==2").shape[0] # 同时购买X和Y的交易次数(支持度),这里用两数相加=2来验证
#     df.query(f"{rule[0]}*{rule[1]}==1").shape[0] # 用两数相乘=1 验证
#     df[(df[rule[0]]==1) & (df[rule[1]]==1)].shape[0] # 直接用对应值都是1来验证
#     df[df[rule[0]]==1][rule[1]].sum() # 用X—>Y中,X购买情况下Y列求和(毕竟购买为1,不购买为0)
#     df[list(rule)].all(axis = 'columns').sum() # 由于数据为0和1,适用于all()方法进行bool判断,然后sum求和
    confidence = num_rule / num_occurence # 置信度
    
    print(f'规则:{rule[0]}—>{rule[1]}\n- 置信度:{confidence*100:.2f}%\n- 支持度:{num_rule}\n')

输出结果如下:(我们只展示部分)

代码语言:javascript
复制
规则:面包—>牛奶
- 置信度:46.43%
- 支持度:13

规则:面包—>奶酪
- 置信度:17.86%
- 支持度:5

规则:面包—>苹果
- 置信度:32.14%
- 支持度:9

规则:面包—>香蕉
- 置信度:57.14%
- 支持度:16

规则:牛奶—>面包
- 置信度:25.00%
- 支持度:13

为了更方便做后续的操作,我们可以将以上数据转化为DataFrame类型,操作如下:

代码语言:javascript
复制
columns=['规则','置信度','支持度']
data = pd.DataFrame(columns=columns)
for rule in rules:
    num_occurence = df[rule[0]].sum() # X—>Y中X在整个数据集中出现次数
    num_rule = df[df[rule[0]]==1][rule[1]].sum() # 用X—>Y中,X购买情况下Y列求和(毕竟购买为1,不购买为0)
    confidence = num_rule / num_occurence # 置信度
    data = data.append(pd.DataFrame([[f'{rule[0]}—>{rule[1]}',confidence,num_rule]],columns=columns),ignore_index=True)
    
data.nlargest(n=5, columns= '置信度', keep='first')

置信度前5

以上就是本文关于亲和性分析的基础介绍,案例来源《Python数据挖掘入门与实践(第二版)》第一章1.3亲和性分析的简单示例,并没有做太多的展开介绍。

我们后续将会拿实际生活中的具体场景再一次进行更详细的介绍,敬请期待哈。

如果你喜欢本篇介绍,还请点赞、在看给个支持哈!(在看超过10个,咱们分享案例数据集和ipynb笔记

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 可以叫我才哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 什么是亲和性分析
  • 2. 案例详解
    • 2.1. 加载数据集
      • 2.2. 求苹果->香蕉的亲和性
        • 2.3. 亲和性分析
        • 3. 算法优化
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档