Apriori算法源代码解析

关于Apriori算法的原理介绍参考:

点击打开链接

点击打开链接

算法主要包括两个步骤:

1、频繁项集的寻找

2、关联规则的产生

核心公式:

support(AB)=P(AB)

confidence(AB)=P(B|A)=support(AB)support(A)

先看看处理好的数据

   Java  PHP  Python爬虫  Spark  数据分析  机器学习
0   1.0  1.0       1.0    1.0   1.0   1.0
1   1.0  1.0       0.0    1.0   0.0   1.0
2   0.0  0.0       1.0    0.0   0.0   0.0
3   0.0  0.0       1.0    0.0   1.0   0.0
4   0.0  0.0       1.0    0.0   1.0   1.0
5   0.0  0.0       0.0    0.0   1.0   0.0
6   0.0  0.0       1.0    0.0   0.0   1.0
7   1.0  0.0       1.0    1.0   0.0   0.0
8   1.0  1.0       0.0    0.0   1.0   0.0
9   0.0  0.0       1.0    0.0   0.0   1.0

每一行代表一个学员,1表示购买了该课程

定义连接函数:

import pandas as pd
# 自定义连接函数,用于实现L_{k-1}到C_k的连接
def connect_string(x, ms):
    x = list(map(lambda i: sorted(i.split(ms)), x))
    l = len(x[0])
    r = []
    for i in range(len(x)):
        for j in range(i, len(x)):
            if x[i][:l - 1] == x[j][:l - 1] and x[i][l - 1] != x[j][l - 1]:
                r.append(x[i][:l - 1] + sorted([x[j][l - 1], x[i][l - 1]]))
    return r
x传入的参数是L_{K-1},即所有频繁K-1项集的集合,ms是自己设定的分隔符,这里用的‘--’。

循环的思路:两两判断,如果两个项集的前K-1项相同,但第K项不同,则把两者拼接起来,组成备选项集,继而形成C_K。

def find_rule(d, support, confidence, ms=u'--'):
    support_series = 1.0 * d.sum() / len(d)  # 单项支持度序列

d为数据,support为支持度阈值,confiden为置信度阈值。

>>>support_series
Java        0.4
PHP         0.3
Python爬虫    0.7
Spark       0.3
数据分析        0.5
机器学习        0.5
dtype: float64
column = list(support_series[support_series > support].index)  # 初步根据支持度筛选
>>>column
['Java', 'Python爬虫', '数据分析', '机器学习'] #这里支持度设置为0.3
while len(column) > 1:
        column = connect_string(column, ms)#连接
        sf = lambda i: d[i].prod(axis=1, numeric_only=True) #定义连乘函数
        d_2 = pd.DataFrame(list(map(sf, column)), index=[ms.join(i) for i in column]).T  #创建连接数据
>>>column
[['Java', 'Python爬虫'], ['Java', '数据分析'], ['Java', '机器学习'], ['Python爬虫', '数据分析'], ['Python爬虫', '机器学习'], ['数据分析', '机器学习']] 
>>> d_2
   Java--Python爬虫  Java--数据分析  Java--机器学习  Python爬虫--数据分析  Python爬虫--机器学习  \
0             1.0         1.0         1.0             1.0             1.0   
1             0.0         0.0         1.0             0.0             0.0   
2             0.0         0.0         0.0             0.0             0.0   
3             0.0         0.0         0.0             1.0             0.0   
4             0.0         0.0         0.0             1.0             1.0   
5             0.0         0.0         0.0             0.0             0.0   
6             0.0         0.0         0.0             0.0             1.0   
7             1.0         0.0         0.0             0.0             0.0   
8             0.0         1.0         0.0             0.0             0.0   
9             0.0         0.0         0.0             0.0             1.0   ...

dataframe.prod()表示对数据框内每一列的值进行累乘,参数axis=1就是对行相乘,通过累乘可以判断某个事务中是否包含该项集。

如:

>>> data[['Java', 'Python爬虫']].prod(axis=1, numeric_only=NONE)
0    1.0
1    0.0
2    0.0
3    0.0
4    0.0
5    0.0
6    0.0
7    1.0
8    0.0
9    0.0
dtype: float64
support_series_2 = 1.0 * d_2[[ms.join(i) for i in column]].sum() / len(d)  # 计算连接后的支持度
        column = list(support_series_2[support_series_2 > support].index)  # 新一轮支持度筛选
        support_series = support_series.append(support_series_2)  #将频繁项集添加到支持度序列中

关联规则的产生:

        column2 = []
        for i in column:  # 关联规则的发现
            i = i.split(ms)
            for j in range(len(i)):
                column2.append(i[:j] + i[j + 1:] + i[j:j + 1])

        cofidence_series = pd.Series(index=[ms.join(i) for i in column2])  # 定义置信度序列

        for i in column2:  # 计算置信度序列
            cofidence_series[ms.join(i)] = support_series[ms.join(sorted(i))] / support_series[ms.join(i[:len(i) - 1])]

置信度筛选

result = pd.DataFrame(index=['support', 'confidence'])  # 定义输出结果
for i in cofidence_series[cofidence_series > confidence].index:  # 置信度筛选
            result[i] = 0.0
            result[i]['confidence'] = cofidence_series[i]
            result[i]['support'] = support_series[ms.join(sorted(i.split(ms)))]
result = result.T.sort_values(['confidence', 'support'], ascending=False)  # 结果整理,输出
print(result)
return resul

示例:

spt=0.2
cfd=0.5
find_rule(data,spt,cfd,"-->")
结果:
结果为:
                 support  confidence
PHP-->Java           0.3    1.000000
Spark-->Java         0.3    1.000000
机器学习-->Python爬虫      0.4    0.800000
Java-->PHP           0.3    0.750000
Java-->Spark         0.3    0.750000
数据分析-->Python爬虫      0.3    0.600000
Python爬虫-->机器学习      0.4    0.571429

完整代码:

# -*- coding: utf-8 -*-
from __future__ import print_function
import pandas as pd


# 自定义连接函数,用于实现L_{k-1}到C_k的连接
def connect_string(x, ms):
    x = list(map(lambda i: sorted(i.split(ms)), x))
    l = len(x[0])
    r = []
    for i in range(len(x)):
        for j in range(i, len(x)):
            if x[i][:l - 1] == x[j][:l - 1] and x[i][l - 1] != x[j][l - 1]:
                r.append(x[i][:l - 1] + sorted([x[j][l - 1], x[i][l - 1]]))
    return r


# 寻找关联规则的函数
def find_rule(d, support, confidence, ms=u'--'):
    result = pd.DataFrame(index=['support', 'confidence'])  # 定义输出结果

    support_series = 1.0 * d.sum() / len(d)  # 支持度序列
    column = list(support_series[support_series > support].index)  # 初步根据支持度筛选
    k = 0

    while len(column) > 1:
        k = k + 1
        print(u'\n正在进行第%s次搜索...' % k)
        column = connect_string(column, ms)
        print(u'数目:%s...' % len(column))
        sf = lambda i: d[i].prod(axis=1, numeric_only=None)  # 新一批支持度的计算函数

        # 创建连接数据,这一步耗时、耗内存最严重。当数据集较大时,可以考虑并行运算优化。
        d_2 = pd.DataFrame(list(map(sf, column)), index=[ms.join(i) for i in column]).T

        support_series_2 = 1.0 * d_2[[ms.join(i) for i in column]].sum() / len(d)  # 计算连接后的支持度
        column = list(support_series_2[support_series_2 > support].index)  # 新一轮支持度筛选
        support_series = support_series.append(support_series_2)
        column2 = []

        for i in column:  # 遍历可能的推理,如{A,B,C}究竟是A+B-->C还是B+C-->A还是C+A-->B?
            i = i.split(ms)
            for j in range(len(i)):
                column2.append(i[:j] + i[j + 1:] + i[j:j + 1])

        cofidence_series = pd.Series(index=[ms.join(i) for i in column2])  # 定义置信度序列

        for i in column2:  # 计算置信度序列
            cofidence_series[ms.join(i)] = support_series[ms.join(sorted(i))] / support_series[ms.join(i[:len(i) - 1])]

        for i in cofidence_series[cofidence_series > confidence].index:  # 置信度筛选
            result[i] = 0.0
            result[i]['confidence'] = cofidence_series[i]
            result[i]['support'] = support_series[ms.join(sorted(i.split(ms)))]

    result = result.T.sort_values(['confidence', 'support'], ascending=False)  # 结果整理,输出
    print(u'\n结果为:')
    print(result)

    return result

数据和源码是《数据挖掘与分析》课程的文件,此文只是本人学习过程中的笔记。













  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值