Spark / MLlib:添加特征的平方来训练非线性模型

时间:2015-01-09 11:24:06

标签: scala apache-spark apache-spark-mllib

最近,我必须为学生准备一些实验材料,以便使用Spark / MLlib / Scala学习机器学习。我熟悉机器学习,但对Spark来说是新手。

One"教科书"机器学习的技巧是添加更高程度的原始特征,以允许非线性模型。假设从LIBSVM文件加载训练数据后,我想添加除原始特征之外的所有特征的平方。我目前的有限知识产生了以下实现:

// Load training data in LIBSVM format.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
val data_add_square = data.map(s => {
  val tmp = sc.parallelize(s.features.toArray)
  val tmp_sqr = tmp.map(x => x*x)
  new LabeledPoint(s.label, Vectors.dense(s.features.toArray ++ tmp_sqr.collect))
})

不知怎的,我觉得这个实施太过重要了#34;并且看起来不是正确的方法。任何人都可以对这个问题有所了解吗?

1 个答案:

答案 0 :(得分:0)

它定义了过度杀戮来并行化每个特征向量,为每个LabeledPoint创建RDD会非常慢,你只会杀死你的Spark群集。

我还建议分别使用稀疏和密集的向量。如果你最初有稀疏矢量,我强烈建议为方形特征建立稀疏矢量。

代码看起来有点沉重,甚至比你的更重,但是在巨大的特征向量的情况下它应该更好

  val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")
  val dataWithSquares = data map { labeledPoint =>

    val featuresWithSquared = labeledPoint.features match {
      case denseVector: DenseVector =>
        val original = denseVector.values
        val squared = original.map(v => v * v)
        Vectors.dense(original ++ squared)

      case sparseVector: SparseVector =>
        val builder = collection.mutable.ListBuffer.empty[(Int, Double)]
        // Collect original values firsts
        sparseVector foreachActive { case (idx, v) => builder += idx -> v}
        // Collect squared
        sparseVector foreachActive { case (idx, v) => builder += idx -> v * v}
        Vectors.sparse(sparseVector.size * 2, builder)
    }

    LabeledPoint(labeledPoint.label, featuresWithSquared)
  }