5

Ich versuche, Genauigkeit mit 5-fach Kreuz Validierung mit Random Forest Classifier Modell in SCALA zu finden. Aber ich bin immer die folgende Fehlermeldung beim Laufen:RandomForestClassifier erhielt Eingabe mit ungültigen Label-Spalte Fehler in Apache Spark

java.lang.IllegalArgumentException: RandomForestClassifier wurde gegebene Eingabe mit ungültiger Etikett Spaltenbeschriftung, ohne die Anzahl der Klassen angegeben. Siehe StringIndexer.

Abrufen der obige Fehler in Zeile ---> val cvModel = cv.fit (Trainieren Data die Trainieren)

Der Code, i für Kreuzvalidierung der Daten verwendeten Satz unter Verwendung von Zufalls Wald sich wie folgt:

import org.apache.spark.ml.Pipeline 
import org.apache.spark.ml.tuning.{ParamGridBuilder, CrossValidator} 
import org.apache.spark.ml.classification.RandomForestClassifier 
import org.apache.spark.ml.evaluation.MulticlassClassificationEvaluator 
import org.apache.spark.mllib.linalg.Vectors 
import org.apache.spark.mllib.regression.LabeledPoint 

val data = sc.textFile("exprogram/dataset.txt") 
val parsedData = data.map { line => 
val parts = line.split(',') 
LabeledPoint(parts(41).toDouble, 
Vectors.dense(parts(0).split(',').map(_.toDouble))) 
} 


val splits = parsedData.randomSplit(Array(0.6, 0.4), seed = 11L) 
val training = splits(0) 
val test = splits(1) 

val trainingData = training.toDF() 

val testData = test.toDF() 

val nFolds: Int = 5 
val NumTrees: Int = 5 

val rf = new  
RandomForestClassifier() 
     .setLabelCol("label") 
     .setFeaturesCol("features") 
     .setNumTrees(NumTrees) 

val pipeline = new Pipeline() 
     .setStages(Array(rf)) 

val paramGrid = new ParamGridBuilder() 
      .build() 

val evaluator = new MulticlassClassificationEvaluator() 
    .setLabelCol("label") 
    .setPredictionCol("prediction") 
    .setMetricName("precision") 

val cv = new CrossValidator() 
    .setEstimator(pipeline) 
    .setEvaluator(evaluator) 
    .setEstimatorParamMaps(paramGrid) 
    .setNumFolds(nFolds) 

val cvModel = cv.fit(trainingData) 

val results = cvModel.transform(testData) 
.select("label","prediction").collect 

val numCorrectPredictions = results.map(row => 
if (row.getDouble(0) == row.getDouble(1)) 1 else 0).foldLeft(0)(_ + _) 
val accuracy = 1.0D * numCorrectPredictions/results.size 

println("Test set accuracy: %.3f".format(accuracy)) 

Kann jemand bitte erklären, was der Fehler im obigen Code ist.

Antwort

8

RandomForestClassifier, wie viele andere ML-Algorithmen, müssen bestimmte Metadaten in der Beschriftungsspalte festgelegt werden, und die Werte müssen als ganzzahlige Werte aus [0, 1, 2 ..., #Klassen] als Doppel dargestellt werden. Typischerweise wird dies von einem vorgeschalteten Transformers wie StringIndexer gehandhabt. Da Sie Labels manuell konvertieren, werden Metadatenfelder nicht festgelegt und der Klassifizierer kann nicht bestätigen, dass diese Anforderungen erfüllt sind.

val df = Seq(
    (0.0, Vectors.dense(1, 0, 0, 0)), 
    (1.0, Vectors.dense(0, 1, 0, 0)), 
    (2.0, Vectors.dense(0, 0, 1, 0)), 
    (2.0, Vectors.dense(0, 0, 0, 1)) 
).toDF("label", "features") 

val rf = new RandomForestClassifier() 
    .setFeaturesCol("features") 
    .setNumTrees(5) 

rf.setLabelCol("label").fit(df) 
// java.lang.IllegalArgumentException: RandomForestClassifier was given input ... 

Sie können entweder Re-Encoding-Label Spalte StringIndexer:

import org.apache.spark.ml.feature.StringIndexer 

val indexer = new StringIndexer() 
    .setInputCol("label") 
    .setOutputCol("label_idx") 
    .fit(df) 

rf.setLabelCol("label_idx").fit(indexer.transform(df)) 

oder set required metadata manually:

val meta = NominalAttribute 
    .defaultAttr 
    .withName("label") 
    .withValues("0.0", "1.0", "2.0") 
    .toMetadata 

rf.setLabelCol("label_meta").fit(
    df.withColumn("label_meta", $"label".as("", meta)) 
) 

Hinweis:

Labels erstellt mit StringIndexer abhängig von der Frequenz nicht Wert:

indexer.labels 
// Array[String] = Array(2.0, 0.0, 1.0) 

PySpark:

from pyspark.sql.types import StructField, DoubleType 

StructField(
    "label", DoubleType(), False, 
    {"ml_attr": { 
     "name": "label", 
     "type": "nominal", 
     "vals": ["0.0", "1.0", "2.0"] 
    }} 
) 
:

In Python Metadatenfelder können direkt auf dem Schema festgelegt werden