K-频繁项集挖掘并行化算法(Apriori算法在Spark上的实现)

大家好,下面为大家分享的实战案例是K-频繁相机挖掘并行化算法。相信从事数据挖掘相关工作的同学对频繁项集的相关算法

比较了解,这里我们用Apriori算法及其优化算法实现。

首先说一下实验结果。对于2G,1800W条记录的数据,我们用了18秒就算完了1-8频繁项集的挖掘。应该还算不错。

给出题目:

本题的较第四题难度更大。我们在写程序的时候一定要注意写出的程序是并行化的,而不是只在client上运行的单机程序。否

则你的算法效率将让你跌破眼镜。此外还需要对算法做相关优化。在这里主要和大家交流一下算法思路和相关优化。

对于Apriori算法的实现在这里不做过多赘述,百度一下大片大片。在Spark上实现这个算法的时候主要分为两个阶段第一阶段

是一个整体的循环求出每个项集的阶段,第二阶段主要是针对第i个项集求出第i+1项集的候选集的阶段。

对于这个算法可以做如下优化:

  1. 观察!这点很重要,经过观察可以发现有大量重复的数据,所谓方向不对努力白费也是这个道理,首先需要压缩重复的数据。不然会做许多无用功。
  2. 设计算法的时候一定要注意是并行化的,大家可能很疑惑,Spark不就是并行化的么?可是你一不小心可能就写成只在client端运行的算法了。
  3. 因为数据量比较大,切记多使用数据持久化以及BroadCast广播变量对中间数据进行相应处理。
  4. 数据结构的优化,BitSet是一种优秀的数据结构他只需一位就可以存储以个整形数,对于所给出的数据都是整数的情况特别适用。 
下面给出算法实现源码:
  • import scala.util.control.Breaks._
  • import scala.collection.mutable.ArrayBuffer
  • import java.util.BitSet
  • import org.apache.spark.SparkContext
  • import org.apache.spark.SparkContext._
  • import org.apache.spark._


  • object FrequentItemset {
  •   def main(args: Array[String]) {
  •     if (args.length != 2) {
  •       println("USage:<Datapath> <Output>")
  •     }
  •     //initial SparkContext
  •     val sc = new SparkContext()
  •     val SUPPORT_NUM = 15278611 //Transactions total is num=17974836, SUPPORT_NUM = num*0.85
  •     val TRANSACITON_NUM = 17974836.0
  •     val K = 8


  •     //All transactions after removing transaction ID, and here we combine the same transactions.
  •     val transactions = sc.textFile(args(0)).map(line =>
  •       line.substring(line.indexOf(" ") + 1).trim).map((_, 1)).reduceByKey(_ + _).map(line => {
  •       val bitSet = new BitSet()
  •       val ss = line._1.split(" ")
  •       for (i <- 0 until ss.length) {
  •         bitSet.set(ss(i).toInt, true)
  •       }
  •       (bitSet, line._2)
  •     }).cache()


  •     //To get 1 frequent itemset, here, fi represents frequent itemset
  •     var fi = transactions.flatMap { line =>
  •       val tmp = new ArrayBuffer[(String, Int)]
  •       for (i <- 0 until line._1.size()) {
  •         if (line._1.get(i)) tmp += ((i.toString, line._2))
  •       }
  •       tmp
  •     }.reduceByKey(_ + _).filter(line1 => line1._2 >= SUPPORT_NUM).cache()
  •     val result = fi.map(line => line._1 + ":" + line._2 / TRANSACITON_NUM)
  •     result.saveAsTextFile(args(1) + "/result-1")


  •     for (i <- 2 to K) {
  •       val candiateFI = getCandiateFI(fi.map(_._1).collect(), i)
  •       val bccFI = sc.broadcast(candiateFI)
  •       //To get the final frequent itemset
  •       fi = transactions.flatMap { line =>
  •         val tmp = new ArrayBuffer[(String, Int)]()
  •         //To check if each itemset of candiateFI in transactions
  •         bccFI.value.foreach { itemset =>
  •           val itemArray = itemset.split(",")
  •           var count = 0
  •           for (item <- itemArray) if (line._1.get(item.toInt)) count += 1
  •           if (count == itemArray.size) tmp += ((itemset, line._2))
  •         }
  •         tmp
  •       }.reduceByKey(_ + _).filter(_._2 >= SUPPORT_NUM).cache()
  •       val result = fi.map(line => line._1 + ":" + line._2 / TRANSACITON_NUM)
  •       result.saveAsTextFile(args(1) + "/result-" + i)
  •       bccFI.unpersist()
  •     }
  •   }


  •   //To get the candiate k frequent itemset from k-1 frequent itemset
  •   def getCandiateFI(f: Array[String], tag: Int) = {
  •     val separator = ","
  •     val arrayBuffer = ArrayBuffer[String]()
  •     for(i <- 0 until f.length;j <- i + 1 until f.length){
  •       var tmp = ""
  •       if(2 == tag) tmp = (f(i) + "," + f(j)).split(",").sortWith((a,b) => a.toInt <= b.toInt).reduce(_+","+_)
  •       else {
  •         if (f(i).substring(0, f(i).lastIndexOf(',')).equals(f(j).substring(0, f(j).lastIndexOf(',')))) {
  •           tmp = (f(i) + f(j).substring(f(j).lastIndexOf(','))).split(",").sortWith((a, b) => a.toInt <= b.toInt).reduce(_ + "," + _)
  •         }
  •       }
  •       var hasInfrequentSubItem = false //To filter the item which has infrequent subitem
  •       if (!tmp.equals("")) {
  •         val arrayTmp = tmp.split(separator)
  •         breakable {
  •           for (i <- 0 until arrayTmp.size) {
  •             var subItem = ""
  •             for (j <- 0 until arrayTmp.size) {
  •               if (j != i) subItem += arrayTmp(j) + separator
  •             }
  •             //To remove the separator "," in the end of the item
  •             subItem = subItem.substring(0, subItem.lastIndexOf(separator))
  •             if (!f.contains(subItem)) {
  •               hasInfrequentSubItem = true
  •               break
  •             }
  •           }
  •         } //breakable
  •       }
  •       else hasInfrequentSubItem = true
  •       //If itemset has no sub inftequent itemset, then put it into candiateFI
  •       if (!hasInfrequentSubItem) arrayBuffer += (tmp)
  •     } //for
  •     arrayBuffer.toArray
  •   }
  • }
先写到这里,欢迎大家提出相关的建议或意见。
            (by老杨,转载请注明出处)


转载于:https://www.cnblogs.com/yangmu/p/4216103.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你解答有关 Python 中的频繁项集和 Apriori 算法的问题。 频繁项集是指在一个数据集中经常同时出现的一组项,例如在一个购物清单中,经常一起被购买的商品就是一个频繁项集。Apriori 算法是一种挖掘频繁项集算法,它的基本思想是利用项集的支持度来筛选出频繁项集。 下面是一个简单的 Python 示例,演示如何使用 Apriori 算法从数据中挖掘频繁项集: ```python # 导入需要的库 from itertools import combinations from collections import defaultdict # 定义 Apriori 算法 def apriori(data, min_support=0.5): # 计算项集的支持度 item_counts = defaultdict(int) for trans in data: for item in trans: item_counts[item] += 1 # 筛选出频繁项集 freq_items = set() n = len(data) for item, count in item_counts.items(): support = count / n if support >= min_support: freq_items.add(item) k = 2 freq_sets = set(combinations(freq_items, k)) while freq_sets: item_counts = defaultdict(int) for trans in data: for item_set in freq_sets: if set(item_set).issubset(set(trans)): item_counts[item_set] += 1 freq_items = set() for item_set, count in item_counts.items(): support = count / n if support >= min_support: freq_items.add(item_set) freq_sets = set(combinations(freq_items, k)) k += 1 return freq_items # 测试数据 data = [ ['apple', 'banana', 'orange', 'pear'], ['banana', 'orange'], ['apple', 'banana', 'orange'], ['apple', 'pear'], ['apple', 'banana', 'orange', 'pear'] ] # 挖掘频繁项集 freq_items = apriori(data, 0.5) print(freq_items) ``` 在这个示例中,我们定义了一个 `apriori` 函数来实现 Apriori 算法。该函数接受一个数据集 `data` 和一个最小支持度 `min_support` 作为参数,并返回一个包含频繁项集的集合。在函数内部,我们首先计算每个项的支持度,然后筛选出频繁项集。接下来,我们以递增的大小迭代项集的长度,直到没有更多的频繁项集为止。 在这个示例中,我们使用了一个简单的示例数据集,包含了一些购物清单。我们使用 `apriori` 函数来挖掘该数据集中的频繁项集,并输出结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值