我可以使用稀疏向量的数据帧进行交叉验证调整吗?

时间:2017-11-06 06:59:30

标签: machine-learning scikit-learn pyspark cross-validation apache-spark-ml

我正在训练我的多层感知器分类器。这是我的训练集。这些特征是稀疏矢量格式。

df_train.show(10,False)
+------+---------------------------+
|target|features                   |
+------+---------------------------+
|1.0   |(5,[0,1],[164.0,520.0])    |
|1.0   |[519.0,2723.0,0.0,3.0,4.0] |
|1.0   |(5,[0,1],[2868.0,928.0])   |
|0.0   |(5,[0,1],[57.0,2715.0])    |
|1.0   |[1241.0,2104.0,0.0,0.0,2.0]|
|1.0   |[3365.0,217.0,0.0,0.0,2.0] |
|1.0   |[60.0,1528.0,4.0,8.0,7.0]  |
|1.0   |[396.0,3810.0,0.0,0.0,2.0] |
|1.0   |(5,[0,1],[905.0,2476.0])   |
|1.0   |(5,[0,1],[905.0,1246.0])   |
+------+---------------------------+

所有的拳头,我想用一种保持方法评估我的估算器,这是我的代码:

from pyspark.ml.classification import MultilayerPerceptronClassifier
from pyspark.ml.evaluation import MulticlassClassificationEvaluator

layers = [4, 5, 4, 3]
trainer = MultilayerPerceptronClassifier(maxIter=100, layers=layers, blockSize=128, seed=1234)
param = trainer.setParams(featuresCol = "features",labelCol="target")

train,test = df_train.randomSplit([0.8, 0.2])
model = trainer.fit(train)
result = model.transform(test)
evaluator = MulticlassClassificationEvaluator(
    labelCol="target", predictionCol="prediction", metricName="accuracy")
print("Test set accuracy = " + str(evaluator.evaluate(result)))

但事实证明错误:无法执行用户定义的函数($ anonfun $ 1 :( vector)=> double)。这是因为我的功能中有稀疏矢量吗?什么可以我呢?

对于交叉验证部分,我编码如下:

X=df_train.select("features").collect()
y=df_train.select("target").collect()
from sklearn.model_selection import cross_val_score,KFold
k_fold = KFold(n_splits=10, random_state=None, shuffle=False)
print(cross_val_score(trainer, X, y, cv=k_fold, n_jobs=1,scoring="accuracy"))

我得到:它似乎不是一个scikit-learn估算器,因为它没有实现'get_params'方法。 但是当我查阅文档时,我没有找到get_params方法。有人可以帮我这个吗?

1 个答案:

答案 0 :(得分:1)

您的问题存在许多问题......

关注第二部分(实际上是一个单独的问题),错误消息声明,即

  

它似乎不是一个scikit-learn估算器

确实是正确的,因为您在scikit-learn方法MultilayerPerceptronClassifier中使用来自PySpark ML的trainer作为cross_val_score(它们兼容)

此外,您的第二个代码段与PySpark类似,但与scikit-learn类似:当您正确使用第一个代码段中的输入时(单个 2列数据框,在一列中的功能和另一列中的标签/目标中,您似乎忘记了第二个片段中的这一课,您可以在其中构建单独的数据框Xy以输入分类器(应该是scikit-learn的案例,而不是PySpark中的情况。有关正确用法的简单示例,请参阅CrossValidator docs

从更一般的角度来看:如果你的数据适合主内存(即你可以像你的CV一样collect),那么绝对没有理由去理解Spark ML ,你用scikit-learn会好得多。

-

关于第1部分:您显示的数据似乎只有2个标签0.0/1.0;我无法确定(因为您只显示了10条记录),但如果您确实只有2个标签,则不应使用MulticlassClassificationEvaluator,而应使用BinaryClassificationEvaluator - 但是,它没有metricName="accuracy"选项... [编辑:不顾一切,似乎MulticlassClassificationEvaluator确实可以用于二进制分类,并且它是获得准确性的一种方便方法,而二进制对应物没有提供这种准确性!]

但这不是您收到此错误的原因(BTW与evaluator无关 - 您可以使用result.show()result.collect()获取此错误);出错的原因是第一层(layers[0])中的节点数为4,而输入向量显然是5维。来自docs

  

输入数量必须等于特征向量的大小

layers[0]更改为5可解决问题(未显示)。同样,如果你确实只有2个类,你也应该将layers[-1]更改为2(否则你不会得到错误,但从分类的角度来看它没有多大意义)