Apache spark Spark MLlib:为每个数据组构建分类器

Apache spark Spark MLlib:为每个数据组构建分类器,apache-spark,apache-spark-mllib,Apache Spark,Apache Spark Mllib,我用一些组号标记了向量(LabeledPoint-s)。对于每个组,我需要创建一个单独的逻辑回归分类器: import org.apache.log4j.{Level, Logger} import org.apache.spark.mllib.classification.LogisticRegressionWithLBFGS import org.apache.spark.{SparkContext, SparkConf} import org.apache.spark.mllib.regr

我用一些组号标记了向量(LabeledPoint-s)。对于每个组,我需要创建一个单独的逻辑回归分类器:

import org.apache.log4j.{Level, Logger}
import org.apache.spark.mllib.classification.LogisticRegressionWithLBFGS
import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.linalg.{Vector, Vectors}

object Scratch {

  val train = Seq(
    (1, LabeledPoint(0, Vectors.sparse(3, Seq((0, 1.0), (2, 3.0))))),
    (1, LabeledPoint(0, Vectors.sparse(3, Seq((1, 1.5), (2, 4.0))))),
    (1, LabeledPoint(0, Vectors.sparse(3, Seq((0, 2.0), (1, 1.0), (2, 3.5))))),
    (8, LabeledPoint(0, Vectors.sparse(3, Seq((0, 3.0), (2, 7.0))))),
    (8, LabeledPoint(0, Vectors.sparse(3, Seq((0, 1.0), (1, 3.0))))),
    (8, LabeledPoint(0, Vectors.sparse(3, Seq((0, 1.5), (2, 4.0)))))
  )

  def main(args: Array[String]) {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)
    // set up environment
    val conf = new SparkConf()
      .setMaster("local[5]")
      .setAppName("Scratch")
      .set("spark.executor.memory", "2g")
    val sc = new SparkContext(conf)

    val trainRDD = sc.parallelize(train)
    val modelByGroup = trainRDD.groupByKey().map({case (group, iter) => 
                           (group, new LogisticRegressionWithLBFGS().run(iter))})
  }

}
LogisticRegressionWithLBFGS().run(iter)
不会编译,因为
run
使用
RDD
而不是
groupBy
返回的迭代器。 请建议如何构建尽可能多的分类器,因为输入数据中有组(标记)

更新-证明嵌套RDD迭代不起作用:

import org.apache.log4j.{Level, Logger}
import org.apache.spark.mllib.classification.LogisticRegressionWithLBFGS
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.linalg.{Vector, Vectors}

object Scratch {

  val train = Seq(
    (1, LabeledPoint(0, Vectors.sparse(3, Seq((0, 1.0), (2, 3.0))))),
    (1, LabeledPoint(0, Vectors.sparse(3, Seq((1, 1.5), (2, 4.0))))),
    (1, LabeledPoint(0, Vectors.sparse(3, Seq((0, 2.0), (1, 1.0), (2, 3.5))))),
    (8, LabeledPoint(0, Vectors.sparse(3, Seq((0, 3.0), (2, 7.0))))),
    (8, LabeledPoint(0, Vectors.sparse(3, Seq((0, 1.0), (1, 3.0))))),
    (8, LabeledPoint(0, Vectors.sparse(3, Seq((0, 1.5), (2, 4.0)))))
  )

  def main(args: Array[String]) {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)
    // set up environment
    val conf = new SparkConf()
      .setMaster("local[5]")
      .setAppName("Scratch")
      .set("spark.executor.memory", "2g")
    val sc = new SparkContext(conf)

    val trainRDD = sc.parallelize(train)
    val keys : RDD[Int] = trainRDD.map({case (key,_) => key}).distinct
    for (key <- keys) {
    // key is Int here!
      // Get train data for the current group (key):
      val groupTrain = trainRDD.filter({case (x, _) => x == key }).cache()

      /**
       * Which results in org.apache.spark.SparkException:
       * RDD transformations and actions can only be invoked by the driver,
       * not inside of other transformations; for example, rdd1.map(x => rdd2.values.count() * x) is invalid
       * because the values transformation and count action cannot be performed inside of the rdd1.map transformation.
       * For more information, see SPARK-5063. at org.apache.spark.rdd.RDD.sc(RDD.scala:87)
       */
    }
  }
}
import org.apache.log4j.{Level,Logger}
使用LBFGS导入org.apache.spark.mllib.classification.logisticRegression
导入org.apache.spark.rdd.rdd
导入org.apache.spark.{SparkContext,SparkConf}
导入org.apache.spark.mllib.regression.LabeledPoint
导入org.apache.spark.mllib.linalg.{Vector,Vectors}
物体划痕{
val列=序号(
(1,标签点(0,向量稀疏(3,序列((0,1.0),(2,3.0 ')),
(1,标签点(0,向量稀疏(3,序列((1,1.5),(2,4.0‘‘‘)’),
(1,标签点(0,向量稀疏(3,序列((0,2.0),(1,1.0),(2,3.5щщ)),
(8,标签点(0,向量稀疏(3,序列((0,3.0),(2,7.0 ')),
(8,标签点(0,向量稀疏(3,序列((0,1.0),(1,3.0 ')),
(8,标签点(0,向量稀疏(3,序列((0,1.5),(2,4.0‘‘)’))
)
def main(参数:数组[字符串]){
Logger.getLogger(“org.apache.spark”).setLevel(Level.WARN)
getLogger.getLogger(“org.eclipse.jetty.server”).setLevel(Level.OFF)
//建立环境
val conf=new SparkConf()
.setMaster(“本地[5]”)
.setAppName(“Scratch”)
.set(“spark.executor.memory”、“2g”)
val sc=新的SparkContext(配置)
val列车RDD=sc.并行化(列车)
valkeys:RDD[Int]=trainRDD.map({case(key,)=>key}).distinct
for(key x==key}).cache()
/**
*这将导致org.apache.spark.SparkException:
*RDD转换和操作只能由驱动程序调用,
*不在其他转换中;例如,rdd1.map(x=>rdd2.values.count()*x)无效
*因为无法在rdd1.map转换内执行值转换和计数操作。
*有关更多信息,请参阅SPARK-5063.org.apache.SPARK.rdd.rdd.sc(rdd.scala:87)
*/
}
}
}

看起来没有办法在其他转换中使用转换,对吗?

如果在每个组上使用分类器,则不需要mllib。Mllib设计用于分布式集合(您的集合不是您的集合,而是每个辅助对象上都有一组本地集合)。您可以使用一些本地机器学习库,如地图功能中的每个组

编辑:

val keys=wholeRDD.map(u._1).distinct.collect
var models=List()

对于(每个组中的键),我有大量的数据集来为组训练分类器,这就是为什么我不能使用Weka。还有其他想法吗?@zork如果没有太多的组,你可以为每个组创建一个rdd。只需
oneKeyRDD=wholeTrainSetRDD.filter(u.\u 1==key)
。是的,我也考虑过这一点。不幸的是我有30个组!@zork我仍然认为这是唯一的方法。问题是,通过将您的数据分组,使给定密钥的数据成为一个本地集,这样就没有办法以分布式方式使用它(即使这些集不太大,无法安装在一台机器上)。我想您可以循环使用30个键。@zork您需要收集键。您希望在键列表上迭代,而不是在键的rdd上迭代。这样就不会有嵌套。