频繁项集挖掘(单机版本 + 分布式版本)

频繁项集挖掘的基本概念请直接看我参考的文章,我这里只给出频繁项集单机版和分布式版本的实现。
通过单机版本熟悉算法的基本思想,分布式版本则是用于工业界实践

参考文章:https://www.jianshu.com/p/fba9e41334a8

单机版本(apriori算法)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 22 10:00:39 2019
定义:
支持度(support):support(A=>B) = P(A∪B),表示A和B同时出现的概率。
置信度(confidence):confidence(A=>B)=support(A∪B) / support(A),表示A和B同时出现的概率占A出现概率的比值。
频繁项集:在项集中频繁出现并满足最小支持度阈值的集合,例如{牛奶,面包}、{手机,手机壳}等。
强关联规则:满足最小支持度和最小至此年度的关联规则

算法步骤:
从记录中计算所有的候选1项集,并计算频繁1项集及支持度。
由频繁1项集生成k项候选集,并由k项候选集计算k项频繁集。
用k项频繁集生成所有关联规则,计算生成规则置信度,筛选符合最小置信度的关联规则。

@author: xxxx
"""

data_set = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]


#item_set = c1 = {frozenset({2}),frozenset({3}),frozenset({1}),frozenset({5}),frozenset({4})}
#generate_freq_supports(data_set, c1, min_support)

def generate_freq_supports(data_set, item_set, min_support):
    """ Input:原始的data_set, n-1频繁项集,以及最小支持度
        Return: n频繁项集以及对应的支持度
    """
    freq_set = set()  # 保存频繁项集元素
    item_count = {}  # 保存元素频次,用于计算支持度
    supports = {}  # 保存支持度

    # 如果项集中元素在数据集中则计数
    for record in data_set:
        for item in item_set:
            if item.issubset(record):
                if item not in item_count:
                    item_count[item] = 1
                else:
                    item_count[item] += 1

    data_len = float(len(data_set))

    # 计算项集支持度
    for item in item_count:
        if (item_count[item] / data_len) >= min_support:
            freq_set.add(item)
            supports[item] = item_count[item] / data_len

    return freq_set, supports


def generate_new_combinations(freq_set, k):
    new_combinations = set()  # 保存新组合
    sets_len = len(freq_set)  # 集合含有元素个数,用于遍历求得组合
    freq_set_list = list(freq_set)  # 集合转为列表用于索引

    for i in range(sets_len):
        for j in range(i + 1, sets_len):
            l1 = list(freq_set_list[i])
            l2 = list(freq_set_list[j])
            l1.sort()
            l2.sort()

            # 项集若有相同的父集则合并项集
            if l1[0:k-2] == l2[0:k-2]:
                freq_item = freq_set_list[i] | freq_set_list[j]
                new_combinations.add(freq_item)

    return new_combinations



data_set = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
L, support_data = apriori(data, min_support=0.5)

def apriori(data_set, min_support, max_len=None):
    max_items = 2  # 初始项集元素个数,开始应该由 1—>2 的频繁项集
    freq_sets = []  # 保存所有频繁项集
    supports = {}  # 保存所有支持度

    # 候选项1项集
    c1 = set()
    for items in data_set:
        for item in items:
            item_set = frozenset([item])
            c1.add(item_set)

    # 频繁项1项集及其支持度
    l1, support1 = generate_freq_supports(data_set, c1, min_support)

    freq_sets.append(l1)
    supports.update(support1)

    if max_len is None:
        max_len = float('inf')

    while max_items and max_items <= max_len:
        ci = generate_new_combinations(freq_sets[-1], max_items)  # 生成候选集
        li, support = generate_freq_supports(data_set, ci, min_support)  # 生成频繁项集和支持度

        # 如果有频繁项集则进入下个循环
        if li:
            freq_sets.append(li)
            supports.update(support)
            max_items += 1
        else:
            max_items = 0

    return freq_sets, supports

def association_rules(freq_sets, supports, min_conf):
    rules = []
    max_len = len(freq_sets)

    # 生成关联规则,筛选符合规则的频繁集计算置信度,满足最小置信度的关联规则添加到列表
    # k代表K项集
    for k in range(max_len - 1):
        for freq_set in freq_sets[k]:
            for sub_set in freq_sets[k + 1]:
                if freq_set.issubset(sub_set):
                    conf = supports[sub_set] / supports[freq_set]
                    rule = (freq_set, sub_set - freq_set, conf)
                    if conf >= min_conf:
                        rules.append(rule)
    return rules
if __name__ == '__main__':
    data_set = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]

    L, support_data = apriori(data_set, min_support=0.5)
    association_rules = association_rules(L, support_data, min_conf=0.7)

分布式版本(基于spark)

import org.apache.spark.ml.fpm.FPGrowth
import org.apache.spark.ml.fpm.FPGrowthModel
import org.apache.spark.sql.functions._
import org.apache.spark.sql.{DataFrame, SparkSession}

// 模型参数配置
val fpgrowth = new FPGrowth().setItemsCol("photo_set").
            setMinSupport(0.1).  
            setMinConfidence(0.9).
            setNumPartitions(2000)
val fpmodel = fpgrowth.fit(photo_set)
fpmodel.write.overwrite().save(outPath + "/fpModel")

val fpModel = FPGrowthModel.load(outPath + "/fpModel")
// 获取频繁项集
val freItemSeqDF_ = fpModel.freqItemsets

值得注意的是,当数据量非常大的时候会出现堆溢出的问题,这个时候需要在启动spark的时候分配更大的堆内存

executor_jvm_argu='-XX:+UseG1GC -Xss81280k -Djava.net.preferIPv4Stack=true -XX:ParallelGCThreads=3 -verbose:gc -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC'

--conf spark.executor.extraJavaOptions="${executor_jvm_argu}"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351