【亲和性分析】第一个项目:分析两种商品的关系

完整代码在最下面

什么是亲和性分析?

亲和性分析(affinity analysis)是一种用于计算样本(对象)相似度的数据挖掘方法。

说人话就是:寻找样本中内含的关系。

举个例子,它可用于推荐商品。

如果当用户购买了A,那么也倾向于购买B

那么我们就可以把A和B放在一起,以此增加销量。

开始:分析两件商品被同时购买的关系。

    • 使用NumPy加载数据集

数据集,用我所学的《Python数据挖掘入门与实战(第2版)》一书中提供的数据集。

以下是资源网址。

Learning-Data-Mining-with-Python-Second-Edition/Chapter01 at master · PacktPublishing/Learning-Data-Mining-with-Python-Second-Edition · GitHub

数据集文件↓

数据集预览↓

可以看到,这是一个二维数组,

每行代表一次交易,

每列代表每种商品,0和1代表是否被购买。(0代表否,1代表是,这里不考虑购买数量)

在该样本中,我们称商品为特征值

我们可以假设

第一列是bread

第二列是milk

第三列是cheese

第四列是apples

第五列是bananas

这些bread什么的,都是特征值,它们代表样本的五个特征

它们对应的列的索引值分别是0、1、2、3、4

因此,我们可以让索引值充当商品的编号。


小知识:数组的维度

举例子,假如有一个数组array,我们要获取其中的某个元素。

如果要写array[0],那就是一维数组;

如果要写array[0][0],那就是二维数组。


代码

import numpy as np

data = "affinity_dataset.txt"

x = np.loadtxt(data)
# np.loadtxt方法可以返回一个np的数组对象
n_samples, n_features = x.shape
# shape属性会返回包含两个元素的元组
# 两元素是:样本数(行数),特征值的数量(列数)

# 把五种特征值转换成对应单词
features = ["bread", "milk", "cheese", "apples", "bananas"]

接下来涉及到的概念

如果你已经知晓这些概念,请直接跳到第二点 。

规则

本次项目中,

规则:顾客如果购买了商品A,那么也倾向于购买商品B

前提↑ 结论↑

规则可拆分为前提结论

前提:购买了商品A

结论:倾向于购买商品B

那么,商品A是什么,商品B又是什么?

要找出这样的规则

评价规则的两种方法

比较两个东西:支持度(support)置信度(confidence)

支持度:某个项集出现的频率

置信度:规则的可信程度

计算规则支持度的方法:{匹配规则的情况次数} / {样本总数}

计算规则的置信度的方法:支持度{前提,结论}/支持度{前提})

因为计算支持度要除以样本总数,

所以,我们可以简化为

某规则的置信度 = {匹配该规则的次数} / {满足这个规则的前提的次数}

目标

计算各个规则的支持度和置信度。

理清每一对商品之间的关系。

2.计算支持度和置信度

首先,我们要导入collections库的defaultdict方法,定义两个字典变量。

(至于为什么要用defaultdict来定义字典,是为了更好处理找不到对应的键的情况。

collections是个标准库,非常好用,具体用法不赘述)

定义变量

from collections import defaultdict

valid_rules = defaultdict(int)
# 记录匹配规则的样本数

num_occurences = defaultdict(int)
# 记录所有特征值(商品)的被购买次数

遍历数据集,开始统计

for sample in x:    # 遍历数据集
    for premise in range(n_features):


        if sample[premise] == 0:
            continue
# 如果不满足前提,则直接跳过,
        num_occurences[premise] += 1
# 满足,则记录下来,对应商品被购买的次数+1
        for conclusion in range(n_features):

            if premise == conclusion:

                continue
# 前提购买的商品和结果购买的商品一样的话,统计没有意义

            if sample[conclusion] == 1:
                valid_rules[(premise, conclusion)] += 1
# 如果结果也满足,匹配该规则的数量+1
            else:
                invalid_rules[(premise,conclusion)] += 1
# 如果只满足前提,不满足结果,则不匹配该规则次数+1

最终得到的valid_rules包含了所有规则和对应成功匹配次数的键值对。

计算支持度

根据前文公式

某规则的支持度 = {匹配该规则的情况次数} / {样本总数}

可以直接从valid_rules中取出{成功匹配规则的次数},除以 总样本数

support = defaultdict(float)
# 关联规则与对应支持度
for premise_conclusion in valid_rules.keys():
 
    support[premise_conclusion] = valid_rules[premise_conclusion] / n_samples

计算置信度

根据前文的简化公式:

某规则的置信度 = {匹配该规则的次数} / {满足这个规则的前提的次数}

我们可以直接将从valid_rules中取出的{成功匹配规则的次数},除以 从num_occurences中取出的{满足前提次数},得到对应的置信度。

confidence = defaultdict(float)
# 关联规则与对应置信度
for premise, conclusion in valid_rules.keys():
    rule = (premise, conclusion)

    confidence[rule] = valid_rules[rule] / num_occurences[premise]
# 计算置信度,让  满足前提和结果的数量  除以  只满足前提的数量

定义一个可以输出对应规则的支持度和置信度的函数。

我们可以传入开头说过的商品编号来查看其支持度和置信度。

代码:输出特定结果

def print_rule(premise: int, conclusion: int, support, confidence, features):
    premise_name = features[premise]
    conclusion_name = features[conclusion]
    # 根据所给的数据集中的商品编号,取出对应名称。

    print("Rule: If a person buys {0} they will also buy {1}".format(premise_name, conclusion_name))
    
    print("Confidence:{0:.3f}".format(
        confidence[(premise, conclusion)]
        )
    )
    print("Support:{0}".format(
        support[(premise, conclusion)]
        )
    )
    print("")

代码:输出所有结果

from operator import itemgetter
# 这个库用来选取items函数形成的对象中的元素

for index in range(len(sorted_confidence)):
    this_confidence = sorted_confidence[index]

    features1 = features[this_confidence[0][0]]
    features2 = features[this_confidence[0][1]]

    features1_index = features.index(features1)
    features2_index = features.index(features2)

    this_support = support[features1_index, features2_index]

    print("premise:{0:^10} |   conclusion:{1:^10} |   Confidence is {2:^10.3f} |    Support is {3:^10}".format(features1, features2,  this_confidence[1], this_support))

测试!

我们来查看以编号1为前提和以编号3为结论的商品

print_rule(1, 3, support, confidence, features)

效果展示

输出特定结果:

输出所有结果:

看起来不错!当然你也可以修改得更好。

完整代码

import numpy as np
from collections import defaultdict
from operator import itemgetter



data = "affinity_dataset.txt"
x = np.loadtxt(data)
features = ["bread", "milk", "cheese", "apples", "bananas"]


n_samples, n_features = x.shape

valid_rules = defaultdict(int)
invalid_rules = defaultdict(int)
num_occurences = defaultdict(int)


for sample in x:
    for premise in range(n_features):

        if sample[premise] == 0:
            continue

        num_occurences[premise] += 1

        for conclusion in range(n_features):

            if premise == conclusion:
                continue

            if sample[conclusion] == 1:
                valid_rules[(premise, conclusion)] += 1

            else:
                invalid_rules[(premise,conclusion)] += 1


confidence = defaultdict(float)

for premise, conclusion in valid_rules.keys():
    rule = (premise, conclusion)
    confidence[rule] = valid_rules[rule] / num_occurences[premise]

support = defaultdict(float)
for premise_conclusion in valid_rules.keys():

    support[premise_conclusion] = valid_rules[premise_conclusion] / n_samples


def print_rule(premise: int, conclusion: int, support, confidence, features):
    premise_name = features[premise]
    conclusion_name = features[conclusion]

    print("Rule: If a person buys {0} they will also buy {1}".format(premise_name, conclusion_name))

    print("Confidence:{0:.3f}".format(
        confidence[(premise, conclusion)]
        )
    )
    print("Support:{0}".format(
        support[(premise, conclusion)]
        )
    )
    print("")


print_rule(1, 3, support, confidence, features)


sorted_confidence = sorted(confidence.items(), key=itemgetter(1), reverse=True)

for index in range(len(sorted_confidence)):
    this_confidence = sorted_confidence[index]

    features1 = features[this_confidence[0][0]]
    features2 = features[this_confidence[0][1]]

    features1_index = features.index(features1)
    features2_index = features.index(features2)

    this_support = support[features1_index, features2_index]

    print("premise:{0:^10} |   conclusion:{1:^10} |   Confidence is {2:^10.3f} |    Support is {3:^10}".format(features1, features2,  this_confidence[1], this_support))
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值