关联规则挖掘——Apriori及其优化
关联规则挖掘基本介绍研究方向
Apriori算法理论介绍代码实现手动编写Apriori(超级精炼版)使用Apyori包的Apriori方法
FP-Growth算法
关联规则挖掘
基本介绍
关联规则的概念最早是在Agrawal等人在1993年发表的论文 Miniing association rules between sets of items in large databases 中提出。关联规则挖掘(关联分析)用于发现隐藏在大型数据集中的联系或者规律。如今随着数据行业的快速发展,我们面对的数据规模愈发巨大,人们对于挖掘海量数据中隐含的关联知识也越来越感兴趣。
研究方向
目前来看,关联规则的主要研究方向有:
经典方法——Apriori算法串行算法 · Park等人提出的基于散列(Hash)技术产生频繁项集的算法 · 基于划分(Partition)的算法 · Toivonen提出基于采样(Sampling)思想的关联规则算法 · Han等人提出的不产生候选集的FP-Growth算法并行分布式算法 · Agrawal等人提出了CD、DD及CaD三种并行算法 · Park等人提出的PDM算法 · 基于DIC思想,Cheung等人提出的APM并行算法 · 针对DD算法的优化,引入IDD和HD算法数据流 · Giannella等人提出的FP-Stream算法 · Chi等人提出的Moment算法(基于滑动窗口) · Manku 等人提出的Sampling Lossy Counting算法图 · AGM,FSG(基于广度优先) · gSpan,FFSM,closeGraph(基于FP-Growth) · 不确定频繁子图挖掘技术EDFS(基于划分思想混合深度与宽度搜素)序列 · Zaki 等人提出的SPADE · 基于投影的PrefixSpan · Lin等人提出的MEMISP
以上罗列了一些已知的关联规则挖掘算法,并不全只是我花一个小时查出来的。接下来我主要介绍比较经典的两种算法——Apriori以及FP-Growth的实现方法。
Apriori算法
理论介绍
核心思想: 频繁项集的子集必定是频繁项集。反之,若子集非频繁,则超集必定非频繁。 算法原理: 关联规则—Apriori算法—FPTree
代码实现
手动编写Apriori(超级精炼版)
import pandas as pd
import numpy as np
from itertools import combinations
from operator import itemgetter
from time import time
import warnings
warnings.filterwarnings("ignore")
# 拿到购物栏数据
dataset = pd.read_csv('retail.csv', usecols=['items'])
# 定义自己的Aprior算法
def my_aprior(data, support_count):
"""
Aprior关联规则挖掘
@data: 数据
@support_count: 项集的频度, 最小支持度计数阈值
"""
start = time()
# 对数据进行处理,删除多余空格
for index, row in data.iterrows():
data.loc[index, 'items'] = row['items'].strip()
# 找出所有频繁一项集
single_items = (data['items'].str.split(" ", expand = True)).apply(pd.value_counts) \
.sum(axis = 1).where(lambda value: value > support_count).dropna()
print("找到所有频繁一项集")
# 创建频繁项集对照表
apriori_data = pd.DataFrame({'items': single_items.index.astype(int), 'support_count': single_items.values, 'set_size': 1})
# 整理数据集
data['set_size'] = data['items'].str.count(" ") + 1
data['items'] = data['items'].apply(lambda row: set(map(int, row.split(" "))))
single_items_set = set(single_items.index.astype(int))
# 循环计算,找到频繁项集
for length in range(2, len(single_items_set) + 1):
data = data[data['set_size'] >= length]
d = data['items'] \
.apply(lambda st: pd.Series(s if set(s).issubset(st) else None for s in combinations(single_items_set, length))) \
.apply(lambda col: [col.dropna().unique()[0], col.count()] if col.count() >= support_count else None).dropna()
if d.empty:
break
apriori_data = apriori_data.append(pd.DataFrame(
{'items': list(map(itemgetter(0), d.values)), 'support_count': list(map(itemgetter(1), d.values)),
'set_size': length}), ignore_index=True)
print("结束搜索,总耗时%s"%(time() - start))
return apriori_data
运行
my_aprior(dataset, 5000)