大师兄的数据分析学习笔记(二十九):关联

大师兄的数据分析学习笔记(二十八):聚类(四)
大师兄的数据分析学习笔记(三十):半监督学习

一、关联规则

  • 关联规则反应一个事物与其他事物之间的相互依存性关联性
  • 几个重要概念:
  • 项目:一个字段,对交易来说一般指一次交易中的一个物品,如:尿布。
  • 事务:某个客户在一次交易中,发生的所有项目的集合,如:尿布、啤酒。
  • 项集:包含一次事务中的若干个项目的集合。
  • 频繁项集:某个相集的支持度大于阈值,则称为频繁项集。
  • 频繁项集中的几个概念:
  • 支持度Support:相集{X,Y}在总项集中出现的概率。
  • 置信度Condifence:在先决条件X发生的条件下,由关联规则{X->Y}退出Y的概率。
  • 提升度:表示含有X的条件下同时含有Y的概率,与无论含不含X含有Y的概率之比。(Confidence({X}->{Y})/Support({Y}))。
  • 关联规则的目的,就是找到数据中的频繁项集
1. Apriori算法
  • Apriorio算法是关联规则中的常用算法,思路如下:
  • 首先指定一个支持度的阈值,
  • 用阈值将频繁项集分出来,比如下图中深色的部分为频繁项集
  • 图中的数字表示项集项目的个数。
  • 其中频繁项集的组合不一定是频繁项集,因为项集组合取的是两个频繁项集的交集,结果要看交集的结果是否大于阈值。
  • 同理,两个非频繁项集的组合一定是非频繁项集
  • 频繁项集非频繁项集的组合也一定是非频繁项集
  • 在经过若干组合后,只需要输出频繁项集即可。

二、序列规则

  • 序列规则将时间因素考虑进来,剔除关联规则中时间点靠后的项目对时间点靠前的项的支持。
1. Apriori-All算法
  • Apriori-All算法通常分为两步:

ForwardApriori算法过程。
Backward:去掉时间序列之后的项对之前的项的支持。

三、代码实现

>>>from itertools import combinations


>>>def comb(lst):
>>>    ret = []
>>>    for i in range(1, len(lst) + 1):
>>>        ret += list(combinations(lst, i))
>>>    return ret


>>>class AprLayer(object):
>>>    d = {}
>>>    def __init__(self):
>>>        self.d = {}


>>>class AprNode(object):
>>>    def __init__(self, node):
>>>        self.s = set(node)
>>>        self.size = len(self.s)
>>>        self.lnk_nodes = {}
>>>        self.num = 0

>>>    def __hash__(self):
>>>        return hash("__".join(sorted([str(itm) for itm in list(self.s)])))

>>>    def __eq__(self, other):
>>>        return "__".join(sorted([str(itm) for itm in list(self.s)])) == "__".join(
>>>            sorted([str(itm) for itm in list(other.s)]))

>>>    def isSubnode(self, node):
>>>        return self.s.issubset(node.s)

>>>    def incNum(self, num=1):
>>>        self.num += num

>>>    def addLnk(self, node):
>>>        self.lnk_nodes[node] = node.s


>>>class AprBlk():
>>>    def __init__(self, data):
>>>        cnt = 0
>>>        self.apr_layers = {}
>>>        self.data_num = len(data)
>>>        for datum in data:
>>>            cnt += 1
>>>            datum = comb(datum)
>>>            nodes = [AprNode(da) for da in datum]
>>>            for node in nodes:
>>>                if not node.size in self.apr_layers:
>>>                    self.apr_layers[node.size] = AprLayer()
>>>                if not node in self.apr_layers[node.size].d:
>>>                    self.apr_layers[node.size].d[node] = node
>>>                self.apr_layers[node.size].d[node].incNum()
>>>            for node in nodes:
>>>                if node.size == 1: continue
>>>                for sn in node.s:
>>>                    sub_n = AprNode(node.s - set([sn]))
>>>                    self.apr_layers[node.size - 1].d[sub_n].addLnk(node)

>>>    def getFreqItems(self, thd=1, hd=1):
>>>        freq_items = []
>>>        for layer in self.apr_layers:
>>>            for node in self.apr_layers[layer].d:
>>>                if self.apr_layers[layer].d[node].num < thd: continue
>>>                freq_items.append((self.apr_layers[layer].d[node].s, self.apr_layers[layer].d[node].num))
>>>        freq_items.sort(key=lambda x: x[1], reverse=True)
>>>        return freq_items[:hd]

>>>    def getConf(self, low=True, h_thd=10, l_thd=1, hd=1):
>>>        confidence = []
>>>        for layer in self.apr_layers:
>>>            for node in self.apr_layers[layer].d:
>>>                if self.apr_layers[layer].d[node].num < h_thd: continue
>>>                for lnk_node in node.lnk_nodes:
>>>                    if lnk_node.num < l_thd: continue
>>>                    conf = float(lnk_node.num) / float(node.num)
>>>                    confidence.append([node.s, node.num, lnk_node.s, lnk_node.num, conf])

>>>        confidence.sort(key=lambda x: x[4])
>>>        if low:
>>>            return confidence[:hd]
>>>        else:
>>>            return confidence[-hd::-1]


>>>class AssctAnaClass():

>>>    def fit(self, data):
>>>        self.apr_blk = AprBlk(data)
>>>        return self

>>>    def get_freq(self, thd=1, hd=1):
>>>        return self.apr_blk.getFreqItems(thd=thd, hd=hd)

>>>    def get_conf_high(self, thd, h_thd=10):
>>>        return self.apr_blk.getConf(low=False, h_thd=h_thd, l_thd=thd)

>>>    def get_conf_low(self, thd, hd, l_thd=1):
>>>        return self.apr_blk.getConf(h_thd=thd, l_thd=-l_thd, hd=hd)


>>>def main():
>>>    data = [
>>>        ["魔兽世界", "博德之门", "仙剑奇侠传", "反恐精英"],
>>>        ["魔兽世界", "博德之门", "最终幻想", "心跳回忆"],
>>>        ["博德之门", "最终幻想", "心跳回忆"],
>>>        ["最终幻想", "生化危机", "空之轨迹"],
>>>        ["魔兽世界", "博德之门", "最终幻想", "心跳回忆"],
>>>        ["魔兽世界", "最终幻想", "心跳回忆"],
>>>    ]
>>>    aac = AssctAnaClass().fit(data)
>>>    print(f"Fred", aac.get_freq(thd=2, hd=10))
>>>    print(f"Conf", aac.get_conf_high(thd=1, h_thd=3))


>>>if __name__ == '__main__':
>>>    main()
Fred [({'最终幻想'}, 5), ({'魔兽世界'}, 4), ({'博德之门'}, 4), ({'心跳回忆'}, 4), ({'心跳回忆', '最终幻想'}, 4), ({'博德之门', '魔兽世界'}, 3), ({'魔兽世界', '最终幻想'}, 3), ({'魔兽世界', '心跳回忆'}, 3), ({'博德之门', '最终幻想'}, 3), ({'博德之门', '心跳回忆'}, 3)]
Conf [[{'博德之门', '心跳回忆'}, 3, {'博德之门', '心跳回忆', '最终幻想'}, 3, 1.0], [{'博德之门', '最终幻想'}, 3, {'博德之门', '心跳回忆', '最终幻想'}, 3, 1.0], [{'魔兽世界', '心跳回忆'}, 3, {'魔兽世界', '心跳回忆', '最终幻想'}, 3, 1.0], [{'魔兽世界', '最终幻想'}, 3, {'魔兽世界', '心跳回忆', '最终幻想'}, 3, 1.0], [{'心跳回忆'}, 4, {'心跳回忆', '最终幻想'}, 4, 1.0], [{'最终幻想'}, 5, {'心跳回忆', '最终幻想'}, 4, 0.8], [{'心跳回忆', '最终幻想'}, 4, {'博德之门', '心跳回忆', '最终幻想'}, 3, 0.75], [{'心跳回忆', '最终幻想'}, 4, {'魔兽世界', '心跳回忆', '最终幻想'}, 3, 0.75], [{'心跳回忆'}, 4, {'博德之门', '心跳回忆'}, 3, 0.75], [{'心跳回忆'}, 4, {'魔兽世界', '心跳回忆'}, 3, 0.75], [{'博德之门'}, 4, {'博德之门', '心跳回忆'}, 3, 0.75], [{'博德之门'}, 4, {'博德之门', '最终幻想'}, 3, 0.75], [{'博德之门'}, 4, {'博德之门', '魔兽世界'}, 3, 0.75], [{'魔兽世界'}, 4, {'魔兽世界', '心跳回忆'}, 3, 0.75], [{'魔兽世界'}, 4, {'魔兽世界', '最终幻想'}, 3, 0.75], [{'魔兽世界'}, 4, {'博德之门', '魔兽世界'}, 3, 0.75], [{'博德之门', '心跳回忆', '最终幻想'}, 3, {'博德之门', '魔兽世界', '心跳回忆', '最终幻想'}, 2, 0.6666666666666666], [{'魔兽世界', '心跳回忆', '最终幻想'}, 3, {'博德之门', '魔兽世界', '心跳回忆', '最终幻想'}, 2, 0.6666666666666666], [{'博德之门', '心跳回忆'}, 3, {'博德之门', '魔兽世界', '心跳回忆'}, 2, 0.6666666666666666], [{'博德之门', '最终幻想'}, 3, {'博德之门', '魔兽世界', '最终幻想'}, 2, 0.6666666666666666], [{'魔兽世界', '心跳回忆'}, 3, {'博德之门', '魔兽世界', '心跳回忆'}, 2, 0.6666666666666666], [{'魔兽世界', '最终幻想'}, 3, {'博德之门', '魔兽世界', '最终幻想'}, 2, 0.6666666666666666], [{'博德之门', '魔兽世界'}, 3, {'博德之门', '魔兽世界', '心跳回忆'}, 2, 0.6666666666666666], [{'博德之门', '魔兽世界'}, 3, {'博德之门', '魔兽世界', '最终幻想'}, 2, 0.6666666666666666], [{'最终幻想'}, 5, {'博德之门', '最终幻想'}, 3, 0.6], [{'最终幻想'}, 5, {'魔兽世界', '最终幻想'}, 3, 0.6], [{'博德之门', '魔兽世界'}, 3, {'博德之门', '魔兽世界', '反恐精英'}, 1, 0.3333333333333333], [{'博德之门', '魔兽世界'}, 3, {'仙剑奇侠传', '博德之门', '魔兽世界'}, 1, 0.3333333333333333], [{'博德之门'}, 4, {'博德之门', '反恐精英'}, 1, 0.25], [{'博德之门'}, 4, {'仙剑奇侠传', '博德之门'}, 1, 0.25], [{'魔兽世界'}, 4, {'魔兽世界', '反恐精英'}, 1, 0.25], [{'魔兽世界'}, 4, {'仙剑奇侠传', '魔兽世界'}, 1, 0.25], [{'最终幻想'}, 5, {'空之轨迹', '最终幻想'}, 1, 0.2], [{'最终幻想'}, 5, {'生化危机', '最终幻想'}, 1, 0.2]]

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

推荐阅读更多精彩内容