<jupyter_start><jupyter_text>关联分析关联分析：从大数据集中寻找物品间的隐含关系频繁项集：经常出现在一起的物品集合关联规则：暗示两种物品之间可能存在很强的关系频繁的衡量尺度：* 支持度：数据集中包含该项集记录所占比例* 置信度：如{尿布}->{葡萄酒}的置信度为 `r = 支持度({尿布，葡萄酒}) / 支持度({尿布})`，意味着对于包含{尿布}的记录，对其中的r * 记录数都适用 要想找到支持度大于0.8的项集，我们就需要对所有的物品进行排列组合得到所有可能的项集，再进行支持度的计算。这会十分耗时低效，我们将分析Apriori原理，该原理可以减小关联学习的计算量。  Apriori原理>a priori —— 一个先验。在拉丁语中指“来自以前”。我们在贝叶斯统计时经常使用先验知识作为判断的条件，这些知识来自领域的知识，先前的测量结果等等。原理内容：如果某个项集是频繁的，那么它所有的子集也是频繁的。同理，如果某个项集是非频繁集，那么它的所有超集也是非频繁的。利用此原理可有效降低项集的指数级增长  用Apriori发现频繁集算法描述：    生成所有单个物品的项集列表    对每个数据记录        对每个项集            包含该项集就增加总计数值    对每个项集的的总数/总数据记录数        如果满足最小支持度，则保留此项集    对剩下的项集组合以生成包含两个元素的项集    重复上述去除项集的操作，直到所有的项集删除  生成候选项集* 加载数据集<jupyter_code>def load_data():
    return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]<jupyter_output><empty_output><jupyter_text>* 对 dataSet 进行去重，排序，放入 list 中，然后转换所有的元素为 frozenset<jupyter_code>def create_c1(dataset):
    c1 = []
    for row in dataset:
        for item in row:
            if not [item] in c1:
                c1.append([item])
    c1.sort()
    return list(map(frozenset, c1))<jupyter_output><empty_output><jupyter_text>* 计算候选数据集 CK 在数据集 D 中的支持度，并返回支持度大于最小支持度（minSupport）的数据<jupyter_code>def scan(dataset, candidate, min_support):
    sscnt = {}
    for row in dataset:
        for can in candidate:
            if can.issubset(row):
                if can not in sscnt:
                    sscnt[can] = 1
                else:
                    sscnt[can] += 1
    num = float(len(dataset))
    retlist = []
    support_data = {}
    for key in sscnt:
        support = sscnt[key]/num
        if support >= min_support:
            retlist.insert(0, key)
        support_data[key] = support
    return retlist, support_data
dataset = load_data()
c1 = create_c1(dataset)
print(c1)
D = list(map(set, dataset))
D<jupyter_output><empty_output><jupyter_text>使用0.5作为最小支持度<jupyter_code>L1, supportdata0 = scan(D, c1, 0.5)
L1<jupyter_output><empty_output><jupyter_text>发现4被删除，说明4没有达到最小支持度  组织完整Apriori算法        当集合中的个数大于0时        构建一个k个项组成的候选项集的列表        检查数据以确认每个项集都是频繁的        保留频繁项集并构建k+1项组成的候选项集的列表  在候选项集中生成新的项集，前k-2个项相同时，合并这两个项<jupyter_code>def apriori_gen(Lk, k):
    relist = []
    lenLk = len(Lk)
    for i in range(lenLk):
        for j in range(i+1, lenLk):
            L1 = list(Lk[i])[:k-2]
            L2 = list(Lk[j])[:k-2]
            L1.sort()
            L2.sort()
            if L1 == L2:
                relist.append(Lk[i] | Lk[j])
    return relist<jupyter_output><empty_output><jupyter_text>构造所有可能的集合并算出其支持度<jupyter_code>def apriori(dataset, min_sup = 0.5):
    c1 = create_c1(dataset)
    d = list(map(set, dataset))
    L1, sup_data = scan(d, c1, min_sup)  # 选择达到最小支持度的项集
    L = [L1]
    k = 2
    while len(L[k-2]) > 0:
        CK = apriori_gen(L[k-2], k)   # 建立大小为K的项集
        Lk, supK = scan(dataset, CK, min_sup)  # 删选达到最小支持度的项集
        sup_data.update(supK)  # 更新支持字典
        L.append(Lk)        # 记录所有项集记录
        k += 1
    return L, sup_data
apriori(dataset)
apriori(dataset, 0.7)<jupyter_output><empty_output><jupyter_text>从频繁项中挖掘关联规则关联规则的量化方法：* 可信度：    一条规则P-->H的可信度定义为：        support(P | H) / support(P)        **假设0， 1， 2 ——> 3 并不满足最小可信度要求，那么任何左部为{0， 1， 2}的子集的规则也不会满足最小可信度要求**利用上述性质来减少需要测试的规则项目：* 分级法：    首先从一个频繁项开始，创建一个规则列表，此列表右部只有一个元素，然后对这些规则进行测试    然后合并所有剩余规则来创建一个新的规则列表，其中列表右部包含两个元素    重复上述过程，直到列表右部不再增加<jupyter_code># 生成关联规则
def generateRules(L, supportData, minConf=0.7):
    """generateRules

    Args:
        L 频繁项集列表
        supportData 频繁项集支持度的字典
        minConf 最小置信度
    Returns:
        bigRuleList 可信度规则列表（关于 (A->B+置信度) 3个字段的组合）
    """
    bigRuleList = []
    # 假设 L = [[frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])], [frozenset([1, 3]), frozenset([2, 5]), frozenset([2, 3]), frozenset([3, 5])], [frozenset([2, 3, 5])]]
    for i in range(1, len(L)):
        # 获取频繁项集中每个组合的所有元素
        for freqSet in L[i]:
            # 假设: freqSet= frozenset([1, 3]), H1=[frozenset([1]), frozenset([3])]
            # 组合总的元素并遍历子元素，并转化为 frozenset 集合，再存放到 list 列表中
            H1 = [frozenset([item]) for item in freqSet]
            # 2 个的组合，走 else, 2 个以上的组合，走 if
            if (i > 1):
                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
            else:
                calcConf(freqSet, H1, supportData, bigRuleList, minConf)
    return bigRuleList
# 计算可信度（confidence）
def calcConf(freqSet, H
, supportData, brl, minConf=0.7):
    """calcConf（对两个元素的频繁项，计算可信度，例如:  {1,2}/{1} 或者 {1,2}/{2} 看是否满足条件）

    Args:
        freqSet 频繁项集中的元素，例如: frozenset([1, 3])    
        H 频繁项集中的元素的集合，例如: [frozenset([1]), frozenset([3])]
        supportData 所有元素的支持度的字典
        brl 关联规则列表的空数组
        minConf 最小可信度
    Returns:
        prunedH 记录 可信度大于阈值的集合
    """
    # 记录可信度大于最小可信度（minConf）的集合
    prunedH = []
    for conseq in H: # 假设 freqSet = frozenset([1, 3]), H = [frozenset([1]), frozenset([3])]，那么现在需要求出 frozenset([1]) -> frozenset([3]) 的可信度和 frozenset([3]) -> frozenset([1]) 的可信度

        print ('confData=', freqSet, H, conseq, freqSet-conseq)
        conf = supportData[freqSet]/supportData[freqSet-conseq] # 支持度定义: a -> b = support(a | b) / support(a). 假设  freqSet = frozenset([1, 3]), conseq = [frozenset([1])]，那么 frozenset([1]) 至 frozenset([3]) 的可信度为 = support(a | b) / support(a) = supportData[freqSet]/supportData[freqSet-conseq] = supportData[frozenset([1, 3])] / supportData[frozenset([1])]
        if conf >= minConf:
            # 只要买了 freqSet-conseq 集合，一定会买 conseq 集合（freqSet-conseq 集合和 conseq 集合是全集）
            print(freqSet-conseq, '-->', conseq, 'conf:', conf)
            brl.append((freqSet-conseq, conseq, conf))
            prunedH.append(conseq)
    return prunedH
# 递归计算频繁项集的规则
def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
    """rulesFromConseq

    Args:
        freqSet 频繁项集中的元素，例如: frozenset([2, 3, 5])    
        H 频繁项集中的元素的集合，例如: [frozenset([2]), frozenset([3]), frozenset([5])]
        supportData 所有元素的支持度的字典
        brl 关联规则列表的数组
        minConf 最小可信度
    """
    # H[0] 是 freqSet 的元素组合的第一个元素，并且 H 中所有元素的长度都一样，长度由 aprioriGen(H, m+1) 这里的 m + 1 来控制
    # 该函数递归时，H[0] 的长度从 1 开始增长 1 2 3 ...
    # 假设 freqSet = frozenset([2, 3, 5]), H = [frozenset([2]), frozenset([3]), frozenset([5])]
    # 那么 m = len(H[0]) 的递归的值依次为 1 2
    # 在 m = 2 时, 跳出该递归。假设再递归一次，那么 H[0] = frozenset([2, 3, 5])，freqSet = frozenset([2, 3, 5]) ，没必要再计算 freqSet 与 H[0] 的关联规则了。
    m = len(H[0])
    if (len(freqSet) > (m + 1)):
        print('freqSet******************', len(freqSet), m + 1, freqSet, H, H[0])
        # 生成 m+1 个长度的所有可能的 H 中的组合，假设 H = [frozenset([2]), frozenset([3]), frozenset([5])]
        # 第一次递归调用时生成 [frozenset([2, 3]), frozenset([2, 5]), frozenset([3, 5])]
        # 第二次 。。。没有第二次，递归条件判断时已经退出了
        Hmp1 = apriori_gen(H, m+1)
        # 返回可信度大于最小可信度的集合
        Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
        print('Hmp1=', Hmp1)
        print('len(Hmp1)=', len(Hmp1), 'len(freqSet)=', len(freqSet))
        # 计算可信度后，还有数据大于最小可信度的话，那么继续递归调用，否则跳出递归
        if (len(Hmp1) > 1):
            print('----------------------', Hmp1)
            # print len(freqSet),  len(Hmp1[0]) + 1
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
L, supportdata = apriori(dataset, min_sup=0.5)
rules = generateRules(L, supportdata, minConf=0.7)
rules<jupyter_output>confData= frozenset({2, 3}) [frozenset({2}), frozenset({3})] frozenset({2}) frozenset({3})
confData= frozenset({2, 3}) [frozenset({2}), frozenset({3})] frozenset({3}) frozenset({2})
confData= frozenset({3, 5}) [frozenset({3}), frozenset({5})] frozenset({3}) frozenset({5})
confData= frozenset({3, 5}) [frozenset({3}), frozenset({5})] frozenset({5}) frozenset({3})
confData= frozenset({2, 5}) [frozenset({2}), frozenset({5})] frozenset({2}) frozenset({5})
frozenset({5}) --> frozenset({2}) conf: 1.0
confData= frozenset({2, 5}) [frozenset({2}), frozenset({5})] frozenset({5}) frozenset({2})
frozenset({2}) --> frozenset({5}) conf: 1.0
confData= frozenset({1, 3}) [frozenset({1}), frozenset({3})] frozenset({1}) frozenset({3})
confData= frozenset({1, 3}) [frozenset({1}), frozenset({3})] frozenset({3}) frozenset({1})
frozenset({1}) --> frozenset({3}) conf: 1.0
freqSet****************** 3 2 frozenset({2, 3, 5}) [frozenset({2}), frozenset({3}), frozenset({5})] frozenset({2})
confData= frozenset({2, 3[...]<jupyter_text>计算项集的置信度<jupyter_code>def calc_conf(freqset, H, supportdata, br1, min_conf=0.7):
    prunedH = []
    for conseq in H:
        conf = supportdata[freqset] / supportdata[freqset - conseq]
        if conf >= min_conf:
            print(freqset-conseq ,'——>', conseq, 'conf:',conf )
            br1.append((freqset-conseq, conseq, conf))
            prunedH.append(conseq)
    return prunedH<jupyter_output><empty_output><jupyter_text>将多元素集合拆分为两个子集合<jupyter_code>def rules_from_conseq(freqset, H, supportdata, br1,min_conf=0.7):
    m = len(H[0])
    if len(freqset) > m+1:
        Hmp1 = apriori_gen(H, m+1)
        Hmp1 = calc_conf(freqset, Hmp1, supportdata, br1, min_conf)
        if len(Hmp1) > 1:
            rules_from_conseq(freqset, Hmp1, supportdata, br1, min_conf)<jupyter_output><empty_output><jupyter_text>生成规则<jupyter_code>def generate_rules(L, supportdata, min_conf=0.7):
    big_rule_list = []
    for i in range(1, len(L)):
        for freqset in L[i]:
            H1 = [frozenset([item]) for item in freqset]
            if i > 1:
                rules_from_conseq(freqset, H1, supportdata, big_rule_list, min_conf)
            else:
                calc_conf(freqset, H1, supportdata, big_rule_list, min_conf)
    return big_rule_list
generate_rules(L, supportdata, min_conf=0.7)
generate_rules(L, supportdata, min_conf=0.5)<jupyter_output>frozenset({3}) ——> frozenset({2}) conf: 0.6666666666666666
frozenset({2}) ——> frozenset({3}) conf: 0.6666666666666666
frozenset({5}) ——> frozenset({3}) conf: 0.6666666666666666
frozenset({3}) ——> frozenset({5}) conf: 0.6666666666666666
frozenset({5}) ——> frozenset({2}) conf: 1.0
frozenset({2}) ——> frozenset({5}) conf: 1.0
frozenset({3}) ——> frozenset({1}) conf: 0.6666666666666666
frozenset({1}) ——> frozenset({3}) conf: 1.0
frozenset({5}) ——> frozenset({2, 3}) conf: 0.6666666666666666
frozenset({3}) ——> frozenset({2, 5}) conf: 0.6666666666666666
frozenset({2}) ——> frozenset({3, 5}) conf: 0.6666666666666666<jupyter_text>示例：发现国会投票的模式(API废旧无法使用)  示例：发现毒蘑菇的相似特征<jupyter_code>mushroom = [line.split() for line in open('mushroom.dat').readlines()]
L, supportdata = apriori(mushroom, min_sup=0.3)
mushroom<jupyter_output><empty_output><jupyter_text>寻找包含有毒特征值为2的频繁项集<jupyter_code>for item in L[1]: # 项集元素为2
    if item.intersection('2'):
        print(item)
for item in L[3]: 项集元素数为4
    if item.intersection('2'):
        print(item)<jupyter_output>frozenset({'2', '28', '90', '39'})
frozenset({'2', '28', '34', '90'})
frozenset({'2', '28', '59', '90'})
frozenset({'2', '28', '85', '90'})
frozenset({'2', '28', '86', '90'})
frozenset({'2', '28', '34', '53'})
frozenset({'2', '28', '59', '34'})
frozenset({'2', '28', '34', '63'})
frozenset({'2', '28', '59', '63'})
frozenset({'2', '28', '85', '53'})
frozenset({'2', '28', '85', '34'})
frozenset({'2', '28', '85', '59'})
frozenset({'2', '28', '85', '63'})
frozenset({'2', '28', '86', '53'})
frozenset({'2', '28', '86', '34'})
frozenset({'2', '28', '86', '59'})
frozenset({'2', '28', '86', '63'})
frozenset({'2', '28', '86', '85'})
frozenset({'2', '28', '53', '39'})
frozenset({'2', '28', '34', '39'})
frozenset({'2', '28', '59', '39'})
frozenset({'2', '28', '63', '39'})
frozenset({'2', '28', '85', '39'})
frozenset({'2', '28', '86', '39'})
frozenset({'2', '90', '53', '39'})
frozenset({'2', '34', '90', '53'})
frozenset({'2', '85', '90', '53'})
frozenset({'2', '86', '90', '53'})
frozenset({'2', '28'[...]
{'fraction_non_alphanumeric': 0.1862669741224699, 'fraction_numerical': 0.057135536766589806, 'mean_word_length': 3.779591836734694, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 8, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '37311', 'license': 'MIT', 'n_tokens_mistral': 6106, 'n_tokens_neox': 6116, 'n_words': 923, 'path': 'Apriori/Apriori.ipynb', 'repo_name': 'Dream-Fu/ML_In_Action', 'size': '11709'}