我可以使用带有稀疏向量的DataFrame来进行交叉验证调参吗?

我在训练我的多层感知器分类器。这是我的训练集。特征采用稀疏向量格式。

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 MultilayerPerceptronClassifierfrom pyspark.ml.evaluation import MulticlassClassificationEvaluatorlayers = [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,KFoldk_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方法。有人能帮我解决这个问题吗?


回答:

你的问题存在多个问题…

重点关注第二部分(实际上这是个独立的问题),错误信息的说法,即

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

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

此外,你的第二个代码片段完全不像PySpark,而更像是scikit-learn:虽然你在第一个片段中正确地使用了输入(一个包含特征和标签/目标的两列数据框),但在第二个片段中,你似乎忘记了这一课,你为分类器构建了单独的数据框Xy(这在scikit-learn中是正确的,但在PySpark中不是)。请参阅CrossValidator文档,以了解正确用法的简单示例。

从更广泛的角度来看:如果你的数据可以装入主内存(即你可以像在CV中那样collect它们),那么完全没有必要使用Spark ML,你会用scikit-learn得到更好的效果。

关于第一部分:你展示的数据似乎只有两个标签0.0/1.0;我无法确定(因为你只展示了10条记录),但如果你确实只有两个标签,你不应该使用MulticlassClassificationEvaluator,而应该使用BinaryClassificationEvaluator – 但是,它没有metricName="accuracy"选项… [编辑:尽管如此,似乎MulticlassClassificationEvaluator确实也可以用于二元分类,并且这是获取准确率的方便方法,而这在其二元对应物中是没有提供的!]

但这不是你得到这个错误的原因(顺便说一下,这个错误与evaluator无关 – 你使用result.show()result.collect()时也会得到它);错误的原因是你的第一层节点数(layers[0])是4,而你的输入向量显然是5维的。根据文档

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

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

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注