使用Apriori算法进行关联分析--代码学习

#-*- coding: utf-8 -*-
def loadDataSet():
    return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]

#构建集合C1,C1是大小为1的所有候选项集的集合
def createC1(dataSet):
    C1 = [] #创建一个空列表,用来存储所有不重复的项值
    #遍历数据集中的所有交易记录,transaction依次为数据集中的每条交易记录,即每个项集,
    # 如依次为[1,3,4],[2,3,5],[1,2,3,5],[2,5]
    for transaction in dataSet:
        for item in transaction: #遍历记录中的每一个项,item是每条交易记录中的物品,如项集[1,3,4]中的1,3,4
            if not [item] in C1:#如果某个物品项没有在C1中出现,则将其添加到C1中
                #不是简单地添加每个物品项,而是添加只包含该物品项的一个列表,
                # 目的是为每个物品构建一个集合,因为后面要进行集合操作
                C1.append([item])
    C1.sort() #对大列表进行排序
    #将列表中的每个单元素列表映射到frozenset(),最后返回frozenset的列表
    #frozenset是指被冰冻的集合,就是它们是不可改变的,这里必须使用frozenset而不是set类型,因为之后
    #必须要将这些集合作为字典键值使用,使用frozenset可以实现,而set却做不到
    return map(frozenset, C1)

#数据集Ck,包含候选集合的列表D,感兴趣项集的最小支持度minSupport
def scanD(D,Ck,minSupport):
    ssCnt = {}
    for tid in D:#遍历数据集中的所有交易记录
        for can in Ck: #遍历C1中的所有候选集
            if can.issubset(tid): #如果C1中的集合是记录的一部分,那么增加字典中对应的计数值
                if not ssCnt.has_key(can):  ssCnt[can] = 1
                else: ssCnt[can] += 1
    numItems = float(len(D)) #numItems是数据集中交易记录的条数
    retList = []
    supportData = {}
    for key in ssCnt:
        support = ssCnt[key] / numItems #计算支持度
        if support >= minSupport:
            retList.insert(0,key) #retList列表中包含了满足最小支持度要求的集合,insert(0,key)表示在列表的首部插入新的集合
        supportData[key] = support #以字典的形式将满足最小支持度要求的集合和其支持度存储在supportData
    return retList, supportData


#*********************** Apriori算法 **********************


# 输入参数为频繁项集列表Lk,k位输出的合成的项集的元素个数,
# 如当k = 2时,输出为CK [frozenset([1, 3]), frozenset([1, 2]), frozenset([1, 5]), frozenset([2, 3]), frozenset([3, 5]), frozenset([2, 5])]
# 输出中,每个项集都是两个元素
def aprioriGen(Lk,k):
    retList = [] #创建一个空列表
    lenLk = len(Lk) #计算Lk中的元素数目
    for i in range(lenLk):
        for j in range(i+1, lenLk):
            #从这步开始,就是取列表Lk中每个集合的前面k-2个元素进行比较,
            # 如果相等,就将这两个集合合为一个大小为k的集合
            L1 = list(Lk[i])[:k-2]; L2 = list(Lk[j])[:k-2]
            L1.sort(); L2.sort()
            if L1 == L2:
                retList.append(Lk[i] | Lk[j])
    return retList

#输入为数据集,以及支持度,函数会生成候选项集的列表
def apriori(dataSet, minSupport = 0.5):
    C1 = createC1(dataSet) # 创建C1
    D = map(set, dataSet) # 读入数据集并将其转化为D(集合列表)
    L1,supportData = scanD(D,C1,minSupport) # 利用scanD创建L1,
    L = [L1] # 将L1放入列表L中,L会包含L1,L2, L3 ....通过下面的while循环依次放入,直到下一个大的项集为空
    k = 2
    while(len(L[k-2]) > 0): # 代表直到下一个大的项集为空时,停止循环
        CK = aprioriGen(L[k-2], k) # 首先使用aprioriGen来创建Ck
        # 使用scanD基于Ck来创建Lk,Ck是一个候选项集列表,然后scanD会遍历Ck,丢掉不满足最小支持度要求的项集
        LK, supK = scanD(D, CK, minSupport)
        supportData.update(supK)
        L.append(LK) # Lk列表被添加到L中
        k += 1 # 同时增加k的值
    return L, supportData

#主函数
# 输入参数为频繁项集列表,包含那些频繁项集支持数据的字典,最小可信度阈值
# 函数输出为一个包含可信度的规则列表
def generateRules(L, supportData, minConf = 0.7):
    bigRuleList = []
    # 因为无法从单元素项集中构建关联规则,所以要从包含两个或更多元素的项集开始构建
    for i in range(1, len(L)):  #只可获取有两个或更多元素的集合,所以i从1开始
        for freqSet in L[i]:# 遍历L中的每一个频繁项集,并对每个频繁项集创建只包含单个元素集合的列表H1
            H1 = [frozenset([item]) for item in freqSet]
            if (i > 1):
                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf) # 如果i > 1,频繁项集的元素数目超过2,则进一步合并
            else:
                calcConf( freqSet, H1, supportData, bigRuleList, minConf) # 当i=1时,频繁项集的元素数目为2,此时直接进行计算可信度
    return bigRuleList

# 计算规则的可信度以找到满足最小可信度要求的规则
def calcConf(freqSet, H, supportData, brl, minConf = 0.7):
    prunedH = [] #创建一个空列表,用来保存符合最小可信度要求的规则列表
    for conseq in H: #遍历H中的所有项集
        # 根据可信度的计算式:一条规则P--> H的可信度定义为support(P | H) / support(P)
        # 所有一个项集 conseq的可信度计算如下:
        conf = supportData[freqSet] / supportData[freqSet - conseq]  # 计算可信度
        if conf >= minConf:
            print freqSet-conseq, '-->',conseq,'conf:',conf # 如果满足最小可信度,则将规则输出到屏幕显示
            brl.append((freqSet - conseq, conseq, conf)) # 将通过检查的规则保存在brl中,即是bigRuleList
            prunedH.append(conseq) # 保存符合最小可信度要求的规则列表,并返回
    return prunedH

# 输入参数,freqSet是频繁项集,H是可以出现在规则右部的元素列表
def rulesFromConseq(freqSet, H, supportData, brl, minConf = 0.7):
    m = len(H[0]) # 计算H中的频繁集大小为m
    if (len(freqSet) > (m+1)): #看该频繁项集是否大到可以移除大小为m的子集
        Hmp1 = aprioriGen(H, m+1) # 生成H中元素的无重复组合,结果存储在Hmp1中,这也是下一次迭代的H列表,Hmp1中包含所有的规则
        Hmp1 = calcConf( freqSet, Hmp1, supportData, brl, minConf) # 测试Hmp1中的规则的可信度以确定规则是否满足要求,返回一个符合最小可信度要求的规则列表
        if (len(Hmp1) > 1): #如果不止一天规则满足,那么使用Hmp1迭代调用函数rulesFromConseq
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

dataSet = loadDataSet()
L, supportData = apriori(dataSet, 0.5)
rules = generateRules(L, supportData, minConf = 0.5)
print rules

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Apriori算法是一种基于频繁项集的关联规则挖掘算法,它可以用来发现事物之间的相关性,并且在市场营销、销售预测、商品推荐等领域都有广泛的应用。 Java中实现Apriori算法主要分为以下步骤: 1. 数据预处理:将原始数据转化为事务集合形式,每个事务包含多个项,项之间用逗号或其他符号分隔。 2. 建立候选项集:根据用户设定的最小支持度阈值,生成大小为1的候选项集。 3. 频繁项集生成:根据候选项集和事务数据集,计算每个项集的支持度,并根据最小支持度阈值筛选出频繁项集。 4. 关联规则挖掘:根据频繁项集,生成关联规则,并计算每个规则的置信度和支持度。 以下是一个简单的Java代码实现: ``` public class Apriori { // 计算候选项集 public static List<Set<String>> candidateSet(List<Set<String>> frequentItemSets) { List<Set<String>> candidateSets = new ArrayList<>(); for (int i = 0; i < frequentItemSets.size(); i++) { for (int j = i + 1; j < frequentItemSets.size(); j++) { Set<String> set1 = frequentItemSets.get(i); Set<String> set2 = frequentItemSets.get(j); // 求并集 Set<String> candidateSet = new HashSet<>(set1); candidateSet.addAll(set2); if (candidateSet.size() == set1.size() + 1) { candidateSets.add(candidateSet); } } } return candidateSets; } // 计算支持度 public static int supportCount(List<Set<String>> transactions, Set<String> itemSet) { int count = 0; for (Set<String> transaction : transactions) { if (transaction.containsAll(itemSet)) { count++; } } return count; } // 计算频繁项集 public static List<Set<String>> frequentItemSet(List<Set<String>> transactions, double minSupport) { List<Set<String>> frequentItemSets = new ArrayList<>(); Map<Set<String>, Integer> itemSetCount = new HashMap<>(); // 统计每个项集的支持度计数 for (Set<String> transaction : transactions) { for (String item : transaction) { Set<String> itemSet = new HashSet<>(); itemSet.add(item); if (itemSetCount.containsKey(itemSet)) { itemSetCount.put(itemSet, itemSetCount.get(itemSet) + 1); } else { itemSetCount.put(itemSet, 1); } } } // 获得频繁项集 for (Set<String> itemSet : itemSetCount.keySet()) { double support = (double) itemSetCount.get(itemSet) / transactions.size(); if (support >= minSupport) { frequentItemSets.add(itemSet); } } // 迭代计算频繁项集 List<Set<String>> lastItemSets = frequentItemSets; while (!lastItemSets.isEmpty()) { List<Set<String>> candidateSets = candidateSet(lastItemSets); itemSetCount.clear(); for (Set<String> transaction : transactions) { for (Set<String> candidateSet : candidateSets) { if (transaction.containsAll(candidateSet)) { if (itemSetCount.containsKey(candidateSet)) { itemSetCount.put(candidateSet, itemSetCount.get(candidateSet) + 1); } else { itemSetCount.put(candidateSet, 1); } } } } lastItemSets = new ArrayList<>(); for (Set<String> itemSet : itemSetCount.keySet()) { double support = (double) itemSetCount.get(itemSet) / transactions.size(); if (support >= minSupport) { frequentItemSets.add(itemSet); lastItemSets.add(itemSet); } } } return frequentItemSets; } // 计算关联规则 public static List<Rule> associationRules(List<Set<String>> transactions, double minSupport, double minConfidence) { List<Rule> rules = new ArrayList<>(); List<Set<String>> frequentItemSets = frequentItemSet(transactions, minSupport); for (Set<String> frequentItemSet : frequentItemSets) { if (frequentItemSet.size() > 1) { List<Set<String>> subSets = getSubSets(frequentItemSet); for (Set<String> subSet : subSets) { Set<String> complementSet = new HashSet<>(frequentItemSet); complementSet.removeAll(subSet); double confidence = (double) supportCount(transactions, frequentItemSet) / supportCount(transactions, subSet); if (confidence >= minConfidence) { rules.add(new Rule(subSet, complementSet, confidence)); } } } } return rules; } // 获取所有子集 public static List<Set<String>> getSubSets(Set<String> itemSet) { List<Set<String>> subSets = new ArrayList<>(); if (itemSet.isEmpty()) { subSets.add(itemSet); } else { List<Set<String>> subSetsWithoutFirst = getSubSets(itemSet.stream().skip(1).collect(Collectors.toSet())); subSets.addAll(subSetsWithoutFirst); subSetsWithoutFirst.forEach(subSet -> { Set<String> subSetWithFirst = new HashSet<>(subSet); subSetWithFirst.add(itemSet.iterator().next()); subSets.add(subSetWithFirst); }); } return subSets; } // 关联规则类 public static class Rule { private Set<String> antecedent; private Set<String> consequent; private double confidence; public Rule(Set<String> antecedent, Set<String> consequent, double confidence) { this.antecedent = antecedent; this.consequent = consequent; this.confidence = confidence; } public Set<String> getAntecedent() { return antecedent; } public Set<String> getConsequent() { return consequent; } public double getConfidence() { return confidence; } @Override public String toString() { return antecedent + " => " + consequent + " (confidence: " + confidence + ")"; } } public static void main(String[] args) { List<Set<String>> transactions = new ArrayList<>(); transactions.add(new HashSet<>(Arrays.asList("A", "B", "C"))); transactions.add(new HashSet<>(Arrays.asList("A", "C", "D", "E"))); transactions.add(new HashSet<>(Arrays.asList("A", "C", "E", "F"))); transactions.add(new HashSet<>(Arrays.asList("B", "C", "E"))); transactions.add(new HashSet<>(Arrays.asList("B", "D", "E", "F"))); double minSupport = 0.4; double minConfidence = 0.7; List<Rule> rules = associationRules(transactions, minSupport, minConfidence); rules.forEach(System.out::println); } } ``` 以上代码实现了Apriori算法中的候选项集计算、支持度计算、频繁项集计算和关联规则挖掘等步骤。你可以根据自己的需求进行调整和修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值