Java实现Apriori算法进行关联规则挖掘

该博客介绍了使用Java实现Apriori算法进行关联规则挖掘的过程。实验基于retail.txt数据集的前1000条记录,挖掘频繁项集和关联规则。Apriori算法通过扫描数据集、计数、比较和剪枝找出频繁项集。实验结果显示,最小支持度为4%时发现多个频繁项集,最小置信度为70%时挖掘出8项关联规则。由于Apriori算法效率问题,对于大数据集,FpGrowth可能是更好的选择。文章还讨论了算法优化和数据集大小对结果的影响。
摘要由CSDN通过智能技术生成

实验描述:

对指定数据集进行关联规则挖掘,选择适当的挖掘算法,编写程序实现,提交程序和结果报告。

数据集: retail.txt ,根据数据集中的数据利用合适的挖掘算法得到频繁项集,并计算置信度,求出满足置信度的所有的关联规则

retail.txt中每个数字表示一种商品的ID,一个{}内的表示一次交易

实验环境和编程语言:

本实验使用的编程语言为:Java

编程环境为:Intellij idea

实现频繁项集的挖掘算法为Apriori算法

用于挖掘的样本个数为:1000个(retail.txt的前1000条数据)

样本示例:

{ 38,39,47,48}

表示一个顾客购买了ID为38、39、47、48的四种商品。

算法分析:

Apriori算法是一种最有影响的挖掘布尔关联规则频繁项集的算法Apriori使用一种称作逐层搜索的迭代方法,“K-1项集”用于搜索“K项集”。

首先,找出频繁“1项集”的集合,该集合记作L1。L1用于找频繁“2项集”的集合L2,而L2用于找L3。如此下去,直到不能找到“K项集”。找每个Lk都需要一次数据库扫描。

核心思想是:连接步和剪枝步。连接步是自连接,原则是保证前k-2项相同,并按照字典顺序连接。剪枝步,是使任一频繁项集的所有非空子集也必须是频繁的。反之,如果某个候选的非空子集不是频繁的,那么该候选肯定不是频繁的,从而可以将其从CK中删除。

简单的讲,利用Apriori算法挖掘关联规则步骤如下:

1、发现频繁项集,过程为(1)扫描(2)计数(3)比较(4)产生频繁项集(5)连接、剪枝,产生候选项集   重复步骤(1)~(5)直到不能发现更大的频集,示例如图1-1所示。

2、产生关联规则,过程为:根据前面提到的置信度的定义,关联规则的产生如下:

(1)对于每个频繁项集L,产生L的所有非空子集;

(2)对于L的每个非空子集S,如果

P(L)/P(S)≧min_conf

则输出关联规则“{ S } =>>{L-S}”

注:L-S表示在项集L中除去S子集的项集




实验结果分析:

根据程序运行的结果,利用retail.txt的前1000条数据进行关联规则挖掘,在最小支持度为4%的时候(即支持度计数大于40时)其得到的频繁项集如图1-2所示,总共发现了9个一项集、10个二项集、4个三项集、1个四项集。





对频繁项集进行置信度计算,在最小置信度为70%的时候,挖掘出8项关联规则,其结果如图1-3所示。





思考与改进:

1.   本次实验使用Apriori算法对数据集进行关联规则的挖掘,虽然算法实现起来相对简单,但是由于其在计算支持度的时候需要每次都要扫描整个数据集,所以其效率十分低下,同时也造成了很多不必要的重复计算,因此本次实验只能选取retail.txt总共80000多条数据中的前1000条进行关联规则挖掘,如果使用完整的数据集则连一项集都需要相当长的时间才能统计出来。因此在面对大数据量的时候,Apriori算法并不是最好的选择。对于大数据集,使用Fpgrowth算法可能效率更高,但由于其实现更加复杂,在这里就不做过多赘述。

2.   为了实现简单,本次实验中实现的是最简单的Apriori算法,其在每次的计算中是有很多无用的计算,所以其实我们可以利用一些技术来提高Apriori算法的执行效率例如使用基于散列的技术、事务压缩等方法,来提高计数的效率同时减少不必要的计数,从而实现算法效率的提高。

3.   同时在本次实验中发现一个现象,如果加大数据集,例如使用retail.txt中的前2000项数据进行挖掘,在相同的支持度和置信度下,频繁项集和关联规则甚至会减少。经过分析发现,由于本次实验是利用百分比来作为支持度的阈值,当总数据集增大时,相当于支持度计数的阈值也成倍的增长,满足支持度计数的项集反而会减少,由此可见根据不同的数据集规模,选择合适的支持度百分比对于能否得到有效的关联规则至关重要。




编程实现:

 

本实验的工程项目和数据集可访问以下网址下载:

http://download.csdn.net/detail/qq_24369113/9712408

https://github.com/muziyongshixin/Association-rule-mining-with-Apriori


函数设计与分析

1.      public staticList<List<String>> getRecord(String url)  
//加载数据文件并进行预处理
2.      public static void Apriori()
//实现Apriori算法的迭代
3.      public static voidAssociationRulesMining()
//根据频繁项集进行关联规则的挖掘
4.      public  static double isAssociationRules(List<String> s1,List<String>s2,List<String> tem)
//判断s1和tem-s1是否为一个关联规则
5.      public static intgetCount(List<String> in)
//得到输入频繁项集in的支持度计数
6.      public static  List<String>gets2set(List<String> tem, List<String> s1)
//得到集合{tem-s1},即为s2
7.      public staticList<List<String>> getSubSet(List<String> set)
//得到一个集合是所有的非空真子集
8.      private staticList<List<String>> getNextCandidate(List<List<String>>FrequentItemset)
//有当前频繁项集自连接求下一次候选集
9.      private static booleanisnotHave(HashSet<String> hsSet, List<List<String>>nextCandidateItemset)
//判断新生成的候选集是不是在已经在候选集集合中
10.   private staticList<List<String>>getSupprotedItemset(List<List<String>> CandidateItemset)
//对候选集进行支持度计数
11.   private static intcountFrequent1(List<String> list)
//进行支持度计数
12.   private staticList<List<String>> findFirstCandidate()
//找到一项集的候选集


源码实现:

/**
 * Created by muziyongshixin on 2016/12/6.
 * 
 *
 * 本工程包含两个数据文件
 * fulldata为老师给的原始数据文件,由于数据量过大程序跑不出来结果,没有选用进行测试
 * top1000data是从fulldata中摘取的前1000条数据,本程序运行的结果是基于这前1000条数据进行的频繁项集挖掘和关联度分析
 *
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.*;

/**
 * Apriori算法实现 最大模式挖掘,涉及到支持度,但没有置信度计算
 *
 * AssociationRulesMining()函数实现置信度计算和关联规则挖掘
 */
public class AprioriMyself {

    public static  int times=0;//迭代次数
    private static  double MIN_SUPPROT = 0.02;//最小支持度百分比
    private static   double MIN_CONFIDENCE=0.6;//最小置信度
    private static boolean endTag = false;//循环状态,迭代标识
    static List<List<String>> record = new ArrayList<List<String>>();//数据集
    static  List<List<String>> frequentItemset=new ArrayList<>();//存储所有的频繁项集
    static List<Mymap> map = new ArrayList();//存放频繁项集和对应的支持度技术

    public static void main(String args[]){

        System.out.println("请输入最小支持度(如0.05)和最小置信度(如0.6");
        Scanner in=new Scanner(System.in);
        MIN_SUPPROT=in.nextDouble();
        MIN_CONFIDENCE=in.nextDouble();


        /*************读取数据集**************/
        record = getRecord("top1000data");
        //控制台输出记录
        System.out.println("读取数据集record成功===================================");
        
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算法中的候选项集计算、支持度计算、频繁项集计算和关联规则挖掘等步骤。你可以根据自己的需求进行调整和修改。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值