我使用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,因为只有一个数据点。因此,当您应用与上面相同的转换时,您最终得到一个带有一个元素的向量,而不是三个,导致模型转换引发错误。
答案 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)
您有两个选择:
handle_data_PipelineModel ==> df ---> split_dataset ==> train_df/test_df--> arithmetic_PipelineModel----->test_model--->evaluate
df == > split_dataset ==> train_df/test_df--> PipelineModel(handle_data_stage and arithmetic_stage) ---> probably error
选项 1 是安全的:您需要保存 handle_data_PipelineModel
和 arithmetic_PipelineModel
。
选项 2 不好:无论您如何保存模型。当你先拆分数据时,train_df
和test_df
的分布会发生变化。
注意:分割后的数据集不能在 PipelineModel 之前处理数据。