我正在使用Scala并使用StringIndexer为我的训练集中的每个类别分配索引。它根据每个类别的频率分配指数。
问题在于,在我的测试数据中,类别的频率不同,因此StringIndexer为类别分配不同的索引,这使我无法正确评估模型(随机森林)。
我正在以完全相同的方式处理训练/测试数据,并且不保存模型。
我尝试手动创建标签(通过获取类别的索引),但得到此错误
java.lang.IllegalArgumentException: RandomForestClassifier was given input with invalid label column label, without the number of classes specified. See StringIndexer.
似乎我必须使用StringIndexer,那么如何确保我用于测试的未来数据集以与训练集相同的方式对类别进行索引?
编辑添加我尝试过的解决方法的代码
这就是数据框的样子,称之为mydata
+--------+-----+---------+---------+
|category|label| x| y|
+--------+-----+---------+---------+
| a| 0.0| -0.166992|-0.256348|
| b| 1.0| -0.179199| -0.22998|
| c| 2.0| -0.172119|-0.105713|
| d| 3.0| -0.064209| 0.050293|
我使用矢量汇编程序来准备功能
val assembler = new VectorAssembler().setInputCols(Array("x, y")).setOutputCol("features")
使用上面的汇编程序转换mydata,它使用功能列
val predValues = assembler.transform(mydata)
因此该模型需要2列,功能和标签。所以我想用我自己的标签。 我从predvalues中选择了特征
val features = sqlContext.sql("SELECT features from predValues")
从我的df中选择标签
val labelDF = sqlContext.sql("SELECT label FROM filterFeaturesOnly")
然后将两者连接在一起,这样我就可以将功能和标签传递给模型
val featuresAndLabels = features.join(labelDF)
这是我传递给模型的内容,我得到了上面提到的错误。
val label = predValues.join(labelDF)
答案 0 :(得分:13)
如果您想要一致地标记内容,则需要保存合适的stringIndexer
。
从文档中考虑this sample code:
val indexer = new StringIndexer()
.setInputCol("category")
.setOutputCol("categoryIndex")
val indexed = indexer.fit(df).transform(df)
indexer.fit(df)
件返回StringIndexerModel,然后可以运行transform
函数。所以相反:
val indexerModel = indexer.fit(trainDF)
val indexed = indexerModel.transform(trainDF)
稍后您可以使用indexerModel.transform(testDF)
为相同的输入获取相同的标签。