使用Spark MLLib,我构建了一个模型(如RandomForest
),然后通过加载模型并在其上使用predict
传递一个模型,可以在Spark外部对它进行评估。特征向量。
似乎与Spark ML一样,predict
现在称为transform
,仅对DataFrame
起作用。
有没有办法在Spark之外构建DataFrame
,因为看起来需要一个SparkContext来构建一个DataFrame?
我错过了什么吗?
答案 0 :(得分:2)
Re:有没有办法在Spark之外构建一个DataFrame?
这是不可能的。 DataFrames位于SQLContext中,它位于SparkContext中。也许你可以用以某种方式来解决它,但整个故事是DataFrames和SparkContext之间的连接是设计的。
答案 1 :(得分:1)
这是我在spark上下文之外使用spark模型的解决方案(使用PMML):
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));
使用PPML进行预测(本地,没有spark上下文,可以应用于参数Map而不是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);
答案 2 :(得分:0)
在此问题上也花费了几天。这并不简单。我的第三个建议涉及我为此目的专门编写的代码。
选项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的输出可用作学习者的输入。该类适用于一种热编码,也适合于固定要素尺寸的大小。即使所有特征都是数字,您也可以使用它。如果在训练中使用它,那么在预测时所需的就是那里的哈希逻辑。其implemented作为火花变压器,因此在火花环境之外不容易重复使用。因此,我已经完成了将哈希函数提取到lib的工作。您可以像往常一样在训练期间应用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)
您可以在tilayealemu/sparkmllite的github中查看详细信息。如果您想复制我的代码,请查看FeatureHasherLite.scala。还有示例代码和单元测试。如果您需要帮助,请随时提出问题。