PCAをデータに適用してから、変換されたデータにRandomForestを適用しようとしました。ただし、PCA.transform(data)はDataFrameを提供しましたが、RandomForestにフィードするためにmllib LabeledPointsが必要です。どうやってやるの?私のコード:
import org.Apache.spark.mllib.util.MLUtils
import org.Apache.spark.{SparkConf, SparkContext}
import org.Apache.spark.mllib.tree.RandomForest
import org.Apache.spark.mllib.tree.model.RandomForestModel
import org.Apache.spark.ml.feature.PCA
import org.Apache.spark.mllib.regression.LabeledPoint
import org.Apache.spark.mllib.linalg.Vectors
val dataset = MLUtils.loadLibSVMFile(sc, "data/mnist/mnist.bz2")
val splits = dataset.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
val trainingDf = trainingData.toDF()
val pca = new PCA()
.setInputCol("features")
.setOutputCol("pcaFeatures")
.setK(100)
.fit(trainingDf)
val pcaTrainingData = pca.transform(trainingDf)
val numClasses = 10
val categoricalFeaturesInfo = Map[Int, Int]()
val numTrees = 10 // Use more in practice.
val featureSubsetStrategy = "auto" // Let the algorithm choose.
val impurity = "gini"
val maxDepth = 20
val maxBins = 32
val model = RandomForest.trainClassifier(pcaTrainingData, numClasses, categoricalFeaturesInfo,
numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins)
error: type mismatch;
found : org.Apache.spark.sql.DataFrame
required: org.Apache.spark.rdd.RDD[org.Apache.spark.mllib.regression.LabeledPoint]
次の2つの可能な解決策を試しましたが、うまくいきませんでした。
scala> val pcaTrainingData = trainingData.map(p => p.copy(features = pca.transform(p.features)))
<console>:39: error: overloaded method value transform with alternatives:
(dataset: org.Apache.spark.sql.DataFrame)org.Apache.spark.sql.DataFrame <and>
(dataset: org.Apache.spark.sql.DataFrame,paramMap: org.Apache.spark.ml.param.ParamMap)org.Apache.spark.sql.DataFrame <and>
(dataset: org.Apache.spark.sql.DataFrame,firstParamPair: org.Apache.spark.ml.param.ParamPair[_],otherParamPairs: org.Apache.spark.ml.param.ParamPair[_]*)org.Apache.spark.sql.DataFrame
cannot be applied to (org.Apache.spark.mllib.linalg.Vector)
そして:
val labeled = pca
.transform(trainingDf)
.map(row => LabeledPoint(row.getDouble(0), row(4).asInstanceOf[Vector[Int]]))
error: type mismatch;
found : scala.collection.immutable.Vector[Int]
required: org.Apache.spark.mllib.linalg.Vector
(上記の例ではorg.Apache.spark.mllib.linalg.Vectorsをインポートしました)
何か助け?
ここでの正しいアプローチは、2番目に試みたアプローチです。各Row
をLabeledPoint
にマッピングして_RDD[LabeledPoint]
_を取得します。ただし、2つの誤りがあります。
Vector
クラス(_org.Apache.spark.mllib.linalg.Vector
_)は型引数を取りません(例_Vector[Int]
_)-したがって、適切なインポートがあったとしても、コンパイラは_scala.collection.immutable.Vector
_を意味すると結論しました何をします。PCA.fit()
から返されるDataFrameには3つの列があり、列番号4を抽出しようとしました。たとえば、最初の4行を表示します。
_+-----+--------------------+--------------------+
|label| features| pcaFeatures|
+-----+--------------------+--------------------+
| 5.0|(780,[152,153,154...|[880.071111851977...|
| 1.0|(780,[158,159,160...|[-41.473039034112...|
| 2.0|(780,[155,156,157...|[931.444898405036...|
| 1.0|(780,[124,125,126...|[25.5114585648411...|
+-----+--------------------+--------------------+
_
これを簡単にするために、私はそれらのインデックスの代わりに列namesを使用することを好みます。
したがって、必要な変換は次のとおりです。
_val labeled = pca.transform(trainingDf).rdd.map(row => LabeledPoint(
row.getAs[Double]("label"),
row.getAs[org.Apache.spark.mllib.linalg.Vector]("pcaFeatures")
))
_