最近,我必须为学生准备一些实验材料,以便使用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;并且看起来不是正确的方法。任何人都可以对这个问题有所了解吗?
答案 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)
}