Категориальные и числовые особенности в Spark MlLib (Java) - PullRequest
0 голосов
/ 30 мая 2018

Я работаю с Apache Spark MlLib версии 2.11 на Java.Мне нужно передать в RandomForestClassifier как категориальные, так и числовые функции (строки и числа).

Какой API лучше использовать в таком случае?Пример был бы очень полезен.

Редактировать

Я пытался использовать VectorIndexer, но он принимает только цифры, и я не мог понять, как интегрировать OneHotEncoder в него,Кроме того, мне не ясно, как определить, какие функции являются категориальными, а какие числовыми.Где мне нужно установить все возможные категории?

Вот код, который я пробовал:

StructType schema = DataTypes.createStructType(new StructField[] {
        new StructField("label", DataTypes.StringType, false, Metadata.empty()),
        new StructField("features", new ArrayType(DataTypes.StringType, false), false,
                Metadata.empty()),
});

JavaRDD<Row> rowRDD = trainingData.map(record -> {
    List<String> values = new ArrayList<>();
    for (String field : fields) {
        values.add(record.get(field));
    }
    return RowFactory.create(record.get(Constants.GROUND_TRUTH), values.toArray(new String[0]));
});

Dataset<Row> trainingDataDataframe = spark.createDataFrame(rowRDD, schema);

StringIndexerModel labelIndexer = new StringIndexer()
        .setInputCol("label")
        .setOutputCol("indexedLabel")
        .fit(trainingDataDataframe);

OneHotEncoder encoder = new OneHotEncoder()
        .setInputCol("features")
        .setOutputCol("featuresVec");
Dataset<Row> encoded = encoder.transform(trainingDataDataframe);

VectorIndexerModel featureIndexer = new VectorIndexer()
        .setInputCol("featuresVec")
        .setOutputCol("indexedFeatures")
        .setMaxCategories(maxCategories)
        .fit(encoded);

StringIndexerModel featureIndexer = new StringIndexer()
        .setInputCol("features")
        .setOutputCol("indexedFeatures")
        .fit(encoded);

RandomForestClassifier rf = new RandomForestClassifier();
        .setNumTrees(numTrees);
        .setFeatureSubsetStrategy(featureSubsetStrategy);
        .setImpurity(impurity);
        .setMaxDepth(maxDepth);
        .setMaxBins(maxBins);
        .setSeed(seed)
        .setLabelCol("indexedLabel")
        .setFeaturesCol("indexedFeatures");

IndexToString labelConverter = new IndexToString()
        .setInputCol("prediction")
        .setOutputCol("predictedLabel")
        .setLabels(labelIndexer.labels());

Pipeline pipeline = new Pipeline()
        .setStages(new PipelineStage[] {labelIndexer, featureIndexer, rf, labelConverter});

PipelineModel model = pipeline.fit(encoded);

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Я нашел решение проблемы.Я обновил версию Spark MlLib до 2.3.0.В этой версии они включили класс с именем OneHotEncoderEstimator.Он имеет входные данные всех категориальных столбцов (Doubles) и выводит соответствующие векторы.

Затем я использовал класс VectorAssembler, чтобы объединить все функции (числовые и категориальные) в один вектор, который я отправил в RandomForestClassifier.

0 голосов
/ 31 мая 2018

Случайный лес, как и дерево решений, не нуждается в кодировании One Hot для управления категориальными функциями, это один из немногих методов, которые могут управлять категориальными функциями изначально (то есть без преобразования в двоичные функции, то естьцель одного горячего кодирования).

Самый простой способ одновременно работать с непрерывными и категориальными функциями - это правильно установить параметр maxCategories.Когда вы будете тренировать свой лес, будут учитываться отдельные значения каждого объекта, и столбцы с менее чем maxCategories различными значениями в данных обучения будут считаться категориальными.

Вы можете проверить, что функциякатегорически печатая дерево / лес, с toDebugString.Если это категорично, вы увидите что-то вроде if feature0 in {0,1,2} вместо обычного <=.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...