Как оценить модель spark.ml без DataFrames/SparkContext?

С помощью Spark MLLib я бы построил модель (например, RandomForest), а затем можно было оценить ее вне Spark, загрузив модель и используя predict для передачи вектора функций.

Похоже, что в Spark ML predict теперь называется transform и действует только на DataFrame.

Есть ли способ построить DataFrame вне Spark, поскольку кажется, что для создания DataFrame нужен SparkContext?

Я что-то упускаю?


person MrE    schedule 15.03.2016    source источник
comment
у него все еще есть методы predict, predictProbablity и predictRaw, работающие с векторами, разве вы не можете их использовать?   -  person Mateusz Dymczyk    schedule 15.03.2016
comment
Я не вижу этих методов в документации: spark.apache.org/docs/latest/api/scala/ Где вы видите их для RandomForest в spark.ml?   -  person MrE    schedule 15.03.2016
comment
ну теоретически вы, вероятно, могли бы написать класс, расширяющий RFClassictionaModel (используя пакеты scala) из мл, и сделать некоторые общедоступные методы, раскрывающие вышеупомянутые защищенные, но не уверены, что это лучший способ. Нельзя ли использовать реализацию из пакета mllib? Я не уверен, что они все еще поддерживают его, но он есть.   -  person Mateusz Dymczyk    schedule 16.03.2016
comment
насколько я понимаю, spark ml заменяет mllib, а mllib в какой-то момент устаревает. Я использовал mllib раньше, но я пытаюсь получить вероятности для каждого класса, и эта функция доступна только с недавнего времени и только в реализации spark ml.   -  person MrE    schedule 16.03.2016
comment
Да, к сожалению, вы правы... Вы смотрели H2O? Не уверен, что у них есть вероятности, которые вы ищете (;-)) но вы можете использовать свои модели как pojo и использовать их где угодно.   -  person Mateusz Dymczyk    schedule 17.03.2016


Ответы (3)


Re: Есть ли способ создать DataFrame вне Spark?

Это невозможно. DataFrames живут внутри SQLContext, а они живут в SparkContext. Возможно, вы могли бы обойти это каким-то образом, но вся история заключается в том, что связь между DataFrames и SparkContext является преднамеренной.

person Jacek Laskowski    schedule 16.03.2016
comment
ну, это не тот ответ, который я хочу услышать... Искра, кажется, движется назад, если это так. Это мощный инструмент для обучения моделей, но необходимость использовать его для оценки просто раздражает. Есть ли способ экспортировать модель в формат, который можно использовать без DataFrames? - person MrE; 16.03.2016
comment
Думаю да. Вы можете экспортировать модель, но я очень мало знаю, насколько это может быть полезно. Какую информацию о модели вы хотели бы сохранить (сохранить)? - person Jacek Laskowski; 16.03.2016
comment
Я знаю, что могу сохранить модель, это то, что я делал с MLLib. то, что я хочу, это формат, который я могу загрузить как объект, на котором я могу затем запустить eval. В mllib я мог бы сохранить RandomForestModel как таковой, а затем загрузить его куда-нибудь еще и запустить eval, передав ему вектор. в ML, кажется, нет способа сделать это. Мне нужно иметь возможность оценивать вне Spark. - person MrE; 16.03.2016
comment
Что-то не так с MLlib? Каждое преимущество, которое вы получаете от использования ML, тесно связано с DataFrame как со структурой данных. Если вы удалите все функции, связанные с DataFrame (преобразование схемы, обработка метаданных), вы все равно получите простую модель MLlib или что-то эквивалентное. - person zero323; 20.03.2016
comment
@MrE, вы когда-нибудь это понимали? Я работаю над проектом, в котором мы пытаемся добиться одного и того же. - person dmux; 29.07.2016

Вот мое решение использовать искровые модели вне искрового контекста (используя PMML):

  1. Вы создаете модель с конвейером следующим образом:

SparkConf sparkConf = new SparkConf();

SparkSession session = SparkSession.builder().enableHiveSupport().config(sparkConf).getOrCreate();   
String tableName = "schema.table";
Properties dbProperties = new Properties();
dbProperties.setProperty("user",vKey);
dbProperties.setProperty("password",password);
dbProperties.setProperty("AuthMech","3");
dbProperties.setProperty("source","jdbc");
dbProperties.setProperty("driver","com.cloudera.impala.jdbc41.Driver");
String tableName = "schema.table";
String simpleUrl = "jdbc:impala://host:21050/schema"
Dataset<Row> data = session.read().jdbc(simpleUrl ,tableName,dbProperties);
String[] inputCols = {"column1"};
StringIndexer indexer = new StringIndexer().setInputCol("column1").setOutputCol("indexed_column1");
StringIndexerModel alphabet  = indexer.fit(data);
data = alphabet.transform(data);
VectorAssembler assembler = new VectorAssembler().setInputCols(inputCols).setOutputCol("features");
Predictor p = new GBTRegressor();
p.set("maxIter",20);
p.set("maxDepth",2);
p.set("maxBins",204);
p.setLabelCol("faktor");
PipelineStage[] stages = {indexer,assembler, p};
Pipeline pipeline = new Pipeline();
pipeline.setStages(stages);
PipelineModel pmodel = pipeline.fit(data);
PMML pmml = ConverterUtil.toPMML(data.schema(),pmodel);
FileOutputStream fos = new FileOutputStream("model.pmml");
JAXBUtil.marshalPMML(pmml,new StreamResult(fos));
  1. Использование PPML для прогнозов (локально, без искрового контекста, который можно применить к карте аргументов, а не к DataFrame):

    PMML pmml = org.jpmml.model.PMMLUtil.unmarshal(new FileInputStream(pmmlFile));
    ModelEvaluatorFactory modelEvaluatorFactory = ModelEvaluatorFactory.newInstance();
    MiningModelEvaluator evaluator = (MiningModelEvaluator) modelEvaluatorFactory.newModelEvaluator(pmml);
    inputFieldMap = new HashMap<String, Field>();     
    Map<FieldName,String> args = new HashMap<FieldName, String>();
    Field curField = evaluator.getInputFields().get(0);
    args.put(curField.getName(), "1.0");
    Map<FieldName, ?> result  = evaluator.evaluate(args);
    
person Volokh    schedule 19.02.2018

Тоже потратил сутки на эту проблему. Это не просто. Мое третье предложение касается кода, который я написал специально для этой цели.

Вариант 1

Как уже говорили другие комментаторы, predict(Vector) теперь доступен. Однако вам нужно знать, как построить вектор. Если нет, см. Вариант 3.

Вариант 2

Если цель состоит в том, чтобы избежать настройки сервера Spark (автономный или кластерный режимы), то можно запустить Spark в локальном режиме. Все это будет работать внутри одной JVM.

val spark = SparkSession.builder().config("spark.master", "local[*]").getOrCreate()
// create dataframe from file, or make it up from some data in memory
// use model.transform() to get predictions

Но это приводит к ненужным зависимостям в вашем модуле прогнозирования и потребляет ресурсы вашей JVM во время выполнения. Кроме того, если задержка прогнозирования имеет решающее значение, например, выполнение прогноза в течение миллисекунды после поступления запроса, то этот вариант слишком медленный.

Вариант 3

MLlib FeatureHasher может быть использован в качестве входных данных для вашего ученика. Класс хорош для одного горячего кодирования, а также для фиксации размера вашего измерения функции. Вы можете использовать его, даже если все ваши функции числовые. Если вы используете это в своем обучении, то все, что вам нужно во время прогнозирования, — это логика хеширования. Его реализован как искровой преобразователь, поэтому его нелегко повторно использовать вне искровой среды. Итак, я проделал работу по извлечению хэш-функции в библиотеку. Вы применяете FeatureHasher и своего ученика во время обучения, как обычно. Тогда вот как вы используете уменьшенный хэшер во время прогнозирования:

// Schema and hash size must stay consistent across training and prediction
val hasher = new FeatureHasherLite(mySchema, myHashSize)

// create sample data-point and hash it
val feature = Map("feature1" -> "value1", "feature2" -> 2.0, "feature3" -> 3, "feature4" -> false)
val featureVector = hasher.hash(feature)

// Make prediction
val prediction = model.predict(featureVector)

Вы можете увидеть подробности в моем github по адресу tilayealemu/sparkmllite. Если вы предпочитаете копировать мой код, взгляните на FeatureHasherLite.scala. Также есть образцы кода и модульные тесты. Не стесняйтесь создавать проблему, если вам нужна помощь.

person tilish    schedule 21.03.2020