我应该如何使用Scala中FPGrowth提供的规则?

时间:2018-02-02 10:35:51

标签: scala apache-spark

我在Spark中使用FpGrowth算法生成了关联规则。 这是代码源:

public Class Data : MonoBehaviour

但是如何使用生成的规则进行预测呢?

2 个答案:

答案 0 :(得分:1)

我自己仍在努力处理无类型的Dataframe-Rows,所以我无法告诉你应该如何使用这些规则。所以我只会告诉你如何使用它们。解决方案可能不是很惯用。

无论如何......以下是似乎有效的代码:

import org.apache.spark.ml.fpm._

val dataset = spark.createDataset(Seq(
   "a b e","b c e", "a b", "a b e", "a b d e", 
   "a e c f", "a b f e", "a f c e",
   "c d w x", "c x p d", "p q c d", "c p d r a",
   "a c b d", "c d p q", "c r p d"
)).map(t => t.split(" ")).toDF("items")
val fpgrowth = new FPGrowth().setItemsCol("items").
  setMinSupport(0.3).setMinConfidence(0.5)
val model = fpgrowth.fit(dataset)
val rules = model.associationRules

val exampleShoppingCart = Array("a", "b", "c", "d")
val proposals = rules.rdd.map{ rule => 
  val antecedent = rule.getAs[Seq[String]]("antecedent")
  val consequent = rule.getAs[Seq[String]]("consequent")
  if (antecedent.forall(exampleShoppingCart.contains)) {
    consequent.toSet
  } else {
    Set.empty[String]
  }
}.reduce(_ ++ _)

val nonTrivialProposals = proposals.filterNot(exampleShoppingCart.contains)

println(
  "Your shopping cart: " + exampleShoppingCart.mkString(",") + 
  "; You might also be interested in: " + nonTrivialProposals
)

// Output:
// Your shopping cart: a,b,c,d; You might also be interested in: Set(e, p)

简要说明:model.associationRules为您提供了一个包含三列的Dataframeantecedentconsequentconfidence。如果您要使用此类规则为特定交易exampleShoppingCart的扩展程序提出建议,则必须检查antecedent中的所有项目是否都出现在交易exampleShoppingCart中。如果是这种情况,您可以将consequent的所有元素添加到提案中。如果antecedent中的某些项目未在事务中出现,则规则不匹配,并且您不提议任何内容(Set.empty)。一旦您计算了所有规则中的所有提案,只需将它们简化为一个提案即可。最后,您可能希望删除事务中已包含的项目(这是filter有用的内容)。

有趣的是找出如何将规则集减少到较小的等效规则集,例如,如果包含{x} => {y},则{x, z} => {y}不会重复。

答案 1 :(得分:1)

  

但是如何使用生成的规则进行预测呢?

这很简单:

const arr = [{"label":"label-1","published":1,"draft":2,"id":"some1"},{"label":"label-1","published":2,"status":0,"draft":1,"id":"some4"},{"label":"label-2","published":1,"draft":14,"id":"some2"},{"label":"label-2","published":12,"status":0,"draft":14,"id":"some3"}]

const result = [...arr.reduce((m, o) => {
  m.has(o.label) || m.set(o.label, {})
  
  const obj = m.get(o.label)
  
  Object.keys(o).forEach((k) => {
    if(k === 'id') return
    
    obj[k] = typeof o[k] === 'number' ? (obj[k] || 0) + o[k] : o[k]
  })
  
  return m
}, new Map()).values()]
  
console.log(result)