Spark/MLlib: 添加特征的平方来训练非线性模型
Spark/MLlib: adding squares of features to train non-linear model
最近我必须准备一些实验室 material 供学生使用 Spark/MLlib/Scala 学习机器学习。我熟悉机器学习,但对 Spark 不熟悉。
机器学习的一个 "textbook" 技巧是添加原始特征的更高阶项以允许非线性模型。比方说,在我从 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))
})
不知何故,我觉得这种实现方式太过 "heavyweight" 并且看起来不是正确的方法。任何人都可以阐明这个问题吗?
并行化每个特征向量定义了过大的杀伤力,为每个 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)
}
最近我必须准备一些实验室 material 供学生使用 Spark/MLlib/Scala 学习机器学习。我熟悉机器学习,但对 Spark 不熟悉。
机器学习的一个 "textbook" 技巧是添加原始特征的更高阶项以允许非线性模型。比方说,在我从 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))
})
不知何故,我觉得这种实现方式太过 "heavyweight" 并且看起来不是正确的方法。任何人都可以阐明这个问题吗?
并行化每个特征向量定义了过大的杀伤力,为每个 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)
}