PySpark MLLIB 随机森林:预测总是为 0

4

使用ml, Spark 2.0(Python)和一个包含120万行数据的数据集,我尝试创建一个使用Random Forest Classifier预测购买意向的模型。然而,当将转换应用于拆分的test数据集时,预测总是为0。

数据集如下:

[Row(tier_buyer=u'0', N1=u'1', N2=u'0.72', N3=u'35.0', N4=u'65.81', N5=u'30.67', N6=u'0.0'....

tier_buyer是用作标签索引器的字段。其余字段包含数字数据。

步骤

1.加载parquet文件并填充可能的null值:

parquet = spark.read.parquet('path_to_parquet')
parquet.createOrReplaceTempView("parquet")
dfraw = spark.sql("SELECT * FROM parquet").dropDuplicates()
df = dfraw.na.fill(0)

2. 创建特征向量:

features = VectorAssembler(
                inputCols = ['N1','N2'...],
                outputCol = 'features')

3. 创建字符串索引器:

label_indexer = StringIndexer(inputCol = 'tier_buyer', outputCol = 'label')

4.-分割训练和测试数据集:

(train, test) = df.randomSplit([0.7, 0.3])

训练数据集结果

enter image description here

测试数据集结果

enter image description here

5.- 定义分类器:

classifier = RandomForestClassifier(labelCol = 'label', featuresCol = 'features')

6. 将阶段进行流水线处理并拟合训练模型:

pipeline = Pipeline(stages=[features, label_indexer, classifier])
model = pipeline.fit(train)

7.- 转换测试数据集:

predictions = model.transform(test)

8. - 按预测结果分组输出测试结果:

predictions.select("prediction", "label", "features").groupBy("prediction").count().show()

在此输入图片描述

如您所见,结果始终为0。我尝试了多种特征组合以减少噪音,并尝试从不同的来源推断模式,但仍然没有运气和相同的结果。

问题

  • 上述当前设置是否正确?
  • 原始数据集中的null值填充是否会导致无法有效执行预测?
  • 在上面显示的屏幕截图中,某些特征看起来是元组形式,而其他特征则是列表形式,这是为什么?我猜这可能是一个可能的错误来源。(它们是密集和稀疏向量的表示)

我之前在我的个人Gist上回答过一个类似的问题。你可以看一下这个链接:https://gist.github.com/eliasah/8709e6391784be0feb7fe9dd31ae0c0a - eliasah
1
谢谢@eliasah,我会看一下分层抽样。你知道为什么有些特征结果以元组的形式出现,而其他特征结果则以列表的形式出现吗? - TMichel
这些只是密集向量和稀疏向量的表示。 - eliasah
预测方面怎么样?在训练后,您是否关心按预测结果进行分组?我还相信我已经回答了您有关向量表示的问题。它不是错误的来源。还有一个问题,您的数据是否有重复项? - eliasah
3个回答

0

看起来你的特征 [N1, N2, ...] 是字符串。你可能想把所有的特征都转换成 FloatType() 或类似的类型。在类型转换之后进行 fillna() 可能是明智的选择。


0

高度不平衡的数据集。

上采样少数类,下采样多数类,或两者兼而有之。

SMOTE 可以帮助,合成数据 会使其效果更佳。


0

你的训练数据集严重不平衡。

Training samples with label 0 = 896389
Training samples with label 1 = 11066
Total training samples        = 907455

通过预测每个记录都有标签0,您的模型实现了98.78%(896389/907455)的准确率,但正如您所指出的那样,这并不起作用,因为它完全无法识别标签=1的样本。

为了创建一个更平衡的训练数据集,使得2个输出标签的样本分布更均衡,您可以使用两种方法:

  1. 对多数类进行欠采样,例如只取11,000个随机样本作为标签=0和11,000个样本作为标签=0
  2. 对少数类进行过采样,即创建具有标签=1的数据副本。

在这种情况下,您的少数类样本仅占大多数类样本的1.2%,因此简单地复制数据将导致自身的过度拟合问题。您可以考虑使用SMOTE进行合成少数类过采样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接