将转换应用于新数据Spark

时间:2018-06-18 15:58:32

标签: apache-spark apache-spark-mllib

我使用Spark(core / mlib)和Java,版本2.3.1。

我将三个转换应用于数据集 - StringIndexer,OneHotEncoderEstimator,VectorAssember - 这是将我的数据集中的分类变量转换为每个类别的1和0的单个列。在我的火车数据上,这个转换没有任何问题,一切都按预期进行,我将此模型保存到文件中。

当我尝试在新的数据点上使用此模型时,我的问题出现了:

public static double loadModel(Obj newData) {
    SparkSession spark = Shots.buildSession();

    //Function which applies transformations
    Dataset<Row> data = buildDataset(spark, Arrays.asList(newData));

    LogisticRegressionModel lrModel = LogisticRegressionModel.load(modelPath);
    //Error is thrown here as the model doesn't seem to understand the input
    Dataset<Row> preds = lrModel.transform(data);
    preds.show();
}

我认为,问题在于,转换现在只应用于一行数据,这些数据只输出分类特征的一个类别和转换后只有一个元素的矢量。当应用LogisticRegressionModel变换时,这会导致错误,该变换期望长度大于1的向量...我认为。

我知道我的错误不知道如何将火车变换应用于新数据...但我不确定错误究竟在哪里,因此,不知道在哪里找到答案(问题是什么)保存模型,我是否需要保存管道等其他内容。

请帮助:)

编辑:抛出的实际错误是 -

java.lang.IllegalArgumentException: requirement failed: BLAS.dot(x: Vector, y:Vector) was given Vectors with non-matching sizes: x.size = 7, y.size = 2 - the reason why I have come to the conclusions above is a visual examination of the data.

EDIT2:一个例子可能有助于解释:我有一个具有3个值[Yes,No,Maybe]的分类特征。我的列车数据包括所有三个值,我最终得到一个长度为3的矢量特征,表示该类别。

然后我在单个数据点上使用相同的pipline来预测值,但分类功能只能是Yes,No或Maybe,因为只有一个数据点。因此,当您应用与上面相同的转换时,您最终得到一个带有一个元素的向量,而不是三个,导致模型转换引发错误。

4 个答案:

答案 0 :(得分:0)

一般情况下,您无法正确使用API​​。正确的工作流程应该包括保留一整套Models(在您的情况下,它至少为StringIndexerModel,其他组件看起来像Transformers)在流程中受过培训并在新数据上重新应用这些。

最方便的方法是使用Pipeline

 val pipeline = new Pipeline().setStages(Arrray(indexer, encoder, assembler, lr))
 val pipelineModel = pipeline.fit(data)

 pipelineModel.transform(data)

PipelineModels可以保存为任何其他组件,只要它的所有阶段都是可写的。

答案 1 :(得分:0)

这里的问题是我在错误的位置保存了模型。

要保留以前的转换效果,您需要使流水线适应数据,然后写入/保存模型。这意味着保存PipelineModel而不是Pipeline。如果在加载数据后适合,则将完全重新应用转换,并且将丢失转换起作用所需的状态。

答案 2 :(得分:0)

我也面临着同样的问题。对于测试中的新值或新数据,StringIndexer将失败,因此我们可以选择跳过那些未知值。

new StringIndexer().setHandleInvalid("skip")

或将火车和测试数据的联合传递到管道,并在转换后将其拆分。

答案 3 :(得分:0)

您有两个选择:

  1. handle_data_PipelineModel ==> df ---> split_dataset ==> train_df/test_df--> arithmetic_PipelineModel----->test_model--->evaluate

  2. df == > split_dataset ==> train_df/test_df--> PipelineModel(handle_data_stage and arithmetic_stage) ---> probably error

选项 1 是安全的:您需要保存 handle_data_PipelineModelarithmetic_PipelineModel

选项 2 不好:无论您如何保存模型。当你先拆分数据时,train_dftest_df的分布会发生变化。

注意:分割后的数据集不能在 PipelineModel 之前处理数据。