关联项的求解问题非常常见,最典型的例子如“牛奶面包”问题。然而常常需要通过对具体数据的分析来获悉一些不是很明显的关联对。例如我们熟知的“啤酒尿布”关联。如果不是事先听说过这两者之间微妙的关联,我想很多人是很难想像到其中的关联的。相信还有许多微妙的关联关系只有通过对具体数据的分析才能被发现。
求解关联pair或者更大的关联集合的最朴素的想法就是列举并统计所有可能的pair的出现频数,判断其是否足够大。但是组合结果通常过大,而使得计算量过大。可以发现#{K-子集合}>...>#{triple}>#{pair},其中K>N/2,N表示所有物品的个数。
“Mining of massive dataset”中提及的“单调原理”可以避免上述朴素想法中大量的不必要的组合:
If a set I of items is frequent, then so is every subset of I.
这个命题:子集I是频繁子集=>其中元素形成的的组合也是频繁的。其逆否命题:某组合x不是频繁的=>不会有任何频繁集中会包含x。
进而可以迭代地求解{pair} -> {triple} ...这个过程就是Apriori算法。如下图:
Construct和Filter过程是关键的两步。
1) Construct即从{i-itemset}构建{i+1 itemset}。伪代码如下:
for itemset i in {i-itemset} temp <- i for itemset j in {i-itemset}.{after i} if #{{i}-{j}}==2 # i and j has n-1 items the same, only one difference for_return.add(temp.append(diff)) # diff is in j but not i
2) Filter即统计1)中创建的每个新的itemset出现的频数是否足够多。
1)中可以进一步对上一步的itemset进行trim:书中提到,如果{i-itemset}中出现的item至少在i+1个set中出现才能作为求解{i+1-itemset}的candidate。
例如:假设L2={1,2},{2,3},{3,4},{4,5}。1和5只出现了一次,不可能出现在L3中,因为L3中出现的每个item再进行2元组合肯定都会出现在L2中,这决定了L3中每个元素在L2中都至少出现2次。
这个trim会减少Filter步骤的判断,但是一般而言#{pair}以及之后出现的candidate的数量都比较少,这个trim可以不做。
代码如下(测试数据见附件):
package com.apriori; import java.io.*; import java.util.*; /** * */ public class Apriori { public static void main(String[] args) throws Exception { new Apriori(args); } /** the list of current itemsets */ private List<int[]> itemsets; /** the name of the transcation file */ private String transaFile; /** number of different items in the dataset */ private int numItems; /** total number of transactions in transaFile */ private int numTransactions; /** minimum support for a frequent itemset in percentage, e.g. 0.8 */ private double minSup; /** by default, Apriori is used with the command line interface */ /** * * generates the apriori itemsets from a file * * * * @param args * * configuration parameters: args[0] is a filename, args[1] the * * min support (e.g. 0.8 for 80%) */ public Apriori(String[] args) throws Exception { configure(args); go(); } /** starts the algorithm after configuration */ private void go() throws Exception { // start timer long start = System.currentTimeMillis(); // first we generate the candidates of size 1 createItemsetsOfSize1(); int itemsetNumber = 1; // the current itemset being looked at int nbFrequentSets = 0; while (itemsets.size() > 0) { calculateFrequentItemsets(); if (itemsets.size() != 0) { nbFrequentSets += itemsets.size(); log("Found " + itemsets.size() + " frequent itemsets of size " + itemsetNumber + " (with support " + (minSup * 100) + "%)"); createNewItemsetsFromPreviousOnes(); } itemsetNumber++; } // display the execution time long end = System.currentTimeMillis(); log("Execution time is: " + ((double) (end - start) / 1000) + " seconds."); log("Found " + nbFrequentSets + " frequents sets for support " + (minSup * 100) + "% (absolute " + Math.round(numTransactions * minSup) + ")"); log("Done"); } /** triggers actions if a frequent item set has been found */ private void foundFrequentItemSet(int[] itemset, int support) { System.out.println(Arrays.toString(itemset) + " (" + ((support / (double) numTransactions)) + " " + support + ")"); } /** outputs a message in Sys.err if not used as library */ private void log(String message) { System.out.println("log\t" + message); } /** computes numItems, numTransactions, and sets minSup */ private void configure(String[] args) throws Exception { // setting transafile if (args.length != 0) transaFile = args[0]; else transaFile = "chess.dat"; // default // setting minsupport if (args.length >= 2) minSup = (Double.valueOf(args[1]).doubleValue()); else minSup = .8;// by default if (minSup > 1 || minSup < 0) throw new Exception("minSup: bad value"); // going thourgh the file to compute numItems and numTransactions numItems = 0; numTransactions = 0; BufferedReader data_in = new BufferedReader(new FileReader(transaFile)); while (data_in.ready()) { String line = data_in.readLine(); if (line.matches("\\s*")) continue; // be friendly with empty lines numTransactions++; StringTokenizer t = new StringTokenizer(line, " "); while (t.hasMoreTokens()) { int x = Integer.parseInt(t.nextToken()); // log(x); if (x + 1 > numItems) numItems = x + 1; } } outputConfig(); } /** * * outputs the current configuration */ private void outputConfig() { // output config info to the user log("Input configuration: " + numItems + " items, " + numTransactions + " transactions, "); log("minsup = " + minSup + "%"); } /** * * puts in itemsets all sets of size 1, i.e. all possibles items of the * * datasets */ private void createItemsetsOfSize1() { itemsets = new ArrayList<int[]>(); for (int i = 0; i < numItems; i++) { int[] cand = { i }; itemsets.add(cand); } } /** * if m is the size of the current itemsets, generate all possible itemsets * of size n+1 from pairs of current itemsets replaces the itemsets of * itemsets by the new ones */ private void createNewItemsetsFromPreviousOnes() { // by construction, all existing itemsets have the same size int currentSizeOfItemsets = itemsets.get(0).length; log("Creating itemsets of size " + (currentSizeOfItemsets + 1) + " based on " + itemsets.size() + " itemsets of size " + currentSizeOfItemsets); HashMap<String, int[]> tempCandidates = new HashMap<String, int[]>(); // temporary // candidates compare each pair of itemsets of size n-1 for (int i = 0; i < itemsets.size(); i++) { for (int j = i + 1; j < itemsets.size(); j++) { int[] X = itemsets.get(i); int[] Y = itemsets.get(j); assert (X.length == Y.length); // make a string of the first n-2 tokens of the strings int[] newCand = new int[currentSizeOfItemsets + 1]; for (int s = 0; s < newCand.length - 1; s++) { newCand[s] = X[s]; } int ndifferent = 0; // then we find the missing value for (int s1 = 0; s1 < Y.length; s1++) { boolean found = false; // is Y[s1] in X? for (int s2 = 0; s2 < X.length; s2++) { if (X[s2] == Y[s1]) { found = true; break; } } if (!found) { // Y[s1] is not in X ndifferent++; // we put the missing value at the end of newCand newCand[newCand.length - 1] = Y[s1]; } } // we have to find at least 1 different, otherwise it means that // we have two times the same set in the existing candidates assert (ndifferent > 0); if (ndifferent == 1) { // HashMap does not have the correct "equals" for int[] :-( // I have to create the hash myself using a String :-( // I use Arrays.toString to reuse equals and hashcode of // String Arrays.sort(newCand); tempCandidates.put(Arrays.toString(newCand), newCand); } } } // set the new itemsets itemsets = new ArrayList<int[]>(tempCandidates.values()); log("Created " + itemsets.size() + " unique itemsets of size " + (currentSizeOfItemsets + 1)); } /** put "true" in trans[i] if the integer i is in line */ private void line2booleanArray(String line, boolean[] trans) { Arrays.fill(trans, false); StringTokenizer stFile = new StringTokenizer(line, " "); // read a line while (stFile.hasMoreTokens()) { int parsedVal = Integer.parseInt(stFile.nextToken()); trans[parsedVal] = true; // if it is not a 0, assign the value to } } /** * * passes through the data to measure the frequency of sets in * * {@link itemsets}, then filters thoses who are under the minimum support * * (minSup) */ private void calculateFrequentItemsets() throws Exception { log("Passing through the data to compute the frequency of " + itemsets.size() + " itemsets of size " + "!!! "+itemsets.get(0).length); List<int[]> frequentCandidates = new ArrayList<int[]>(); // the frequent boolean match; // whether the transaction has all the items in an // itemset int count[] = new int[itemsets.size()]; // the number of successful // matches, initialized by zeros load the transaction file BufferedReader data_in = new BufferedReader(new InputStreamReader( new FileInputStream(transaFile))); boolean[] trans = new boolean[numItems]; // for each transaction for (int i = 0; i < numTransactions; i++) { // boolean[] trans = extractEncoding1(data_in.readLine()); String line = data_in.readLine(); line2booleanArray(line, trans); // check each candidate for (int c = 0; c < itemsets.size(); c++) { match = true; // reset match to false // tokenize the candidate so that we know what items need to be // present for a match int[] cand = itemsets.get(c); // check each item in the itemset to see if it is present in the // transaction for (int xx : cand) { if (trans[xx] == false) { match = false; break; } } if (match) { // if at this point it is a match, increase the // count count[c]++; } } } data_in.close(); for (int i = 0; i < itemsets.size(); i++) { // if the count% is larger than the minSup%, add to the candidate to // the frequent candidates if ((count[i] / (double) (numTransactions)) >= minSup) { foundFrequentItemSet(itemsets.get(i), count[i]); frequentCandidates.add(itemsets.get(i)); } } // new candidates are only the frequent candidates itemsets = frequentCandidates; } }
相关推荐
基于Apriori关联规则算法的消防大数据分析 本文基于Apriori关联规则算法,旨在消防大数据分析,并研究Apriori关联规则算法模型,以探索火灾发生因素之间的关联关系,最大程度地减少火灾发生。 一、Apriori关联规则...
### C语言实现的Apriori关联规则算法 #### Apriori算法概述 Apriori算法是一种广泛应用于数据挖掘中的关联规则学习方法,主要用于发现频繁项集。这些频繁项集能够帮助我们理解数据间的潜在关系,比如超市购物篮分析...
【标题】中的“python实现2022美赛C题(时间序列预测,Apriori关联规则算法...)”指的是2022年美国数学建模竞赛(MCM/ICM,也称为“美赛”)中的一道题目,该题目涉及到使用Python编程语言进行时间序列预测以及应用...
Apriori关联规则算法源代码目前已提出了许多挖掘关联规则的算法,其中最 为经典的是Ap riori算法[ 123 ] ,算法思想是使用逐层搜索的迭代方法。算法主要包括三个步骤:连接步、剪枝步和扫描数据库。而本文通过对剪枝步...
Apriori 算法是关联规则挖掘的经典算法之一,尤其在零售业中的商品购物篮分析中应用广泛。本项目深入探讨了如何利用 Apriori 算法来揭示消费者购买行为的模式。 首先,我们要理解 Apriori 算法的基本原理。Apriori ...
### Weka中的Apriori关联规则算法解析 #### 一、引言 在数据挖掘领域,关联规则是一种非常重要的分析方法,主要用于发现事物之间隐藏的相关性。Weka是一款开源的数据挖掘软件工具集,支持多种机器学习算法,包括...
Apriori算法是一种经典的关联规则挖掘算法,它主要用于发现数据集中项集...在关联规则挖掘的场景中,可以先使用灰色关联度来分析数据集中的变量相关性,然后使用Apriori或其他关联规则算法来发现变量之间的关联规则。
Apriori算法是关联规则挖掘中广泛使用的经典算法,由R. Agrawal于上世纪90年代提出。该算法通过反复扫描数据库找出频繁项集,生成满足最小支持度和最小可信度要求的强关联规则。 然而,Apriori算法存在若干不足。...
数据挖掘中关联规则算法Apriori的java程序
在这个实例中,我们将重点关注关联规则分析中的Apriori算法,以及如何用它来挖掘电影导演之间的关联规则。 关联规则分析是数据挖掘的一种技术,主要用来发现数据集中项集之间的频繁模式,如购物篮分析中商品之间的...
关联规则挖掘在数据挖掘领域中占据重要位置,其核心算法是Apriori算法。该算法由Agrawal于1993年提出,是挖掘布尔关联规则频繁项集的基础算法。Apriori算法的基本原理是“逐层搜索的迭代方法”,通过利用频繁项集...
Apriori关联规则是一种基于频繁项集的挖掘算法,由Raghu Ramakrishnan和Gehrke于1994年提出。该算法的基本思想是:首先找出数据集中频繁出现的项集,然后通过这些频繁项集生成强关联规则。在中医证型的研究中,我们...
在提供的压缩包文件"apriori关联分析matlab实现"中,应该包含了完成上述步骤的代码示例,可以帮助初学者理解Apriori算法的实现细节。通过阅读和运行这些代码,你可以更深入地了解如何在实际项目中应用关联规则学习。...
Apriori算法是关联规则学习中最经典的算法之一,它由R. Agrawal和R. Srikant于1994年提出。本实例将探讨如何在Python中实现Apriori算法,以发现给定数据集中频繁项集。 **Apriori算法的核心思想:** Apriori算法...
Apriori算法对购物篮进行关联分析-Apriori算法进行购物篮关联分析.rar 大家好,出来乍到,看到好多高手分享自己的程序,我也想分享一下,做出自己的贡献。 虽然学MATLAB已经一年有余,但是一直忙着数学建模,对...
本实验报告主要聚焦于使用Apriori算法进行关联规则挖掘,这是由Rakesh Agrawal和Ramakrishnan Srikant在1994年提出的经典算法。此算法主要应用于零售数据分析,例如发现顾客购买商品之间的关联性。 Apriori算法的...
总的来说,"c++实现关联规则Apriori算法"涉及的知识点包括数据挖掘、关联规则学习、Apriori算法、C++编程、VS2010开发环境、数据结构和算法优化。掌握这些知识,将有助于我们开发出适用于各种场景的高效数据挖掘工具...