将密集向量的pyspark dataframe列转换为numpy数组

时间:2018-07-06 15:41:54

标签: python numpy apache-spark pyspark classification

我有一个数据帧,该数据帧具有一列密集的向量,即多类分类预测概率。我想将该列转换为numpy数组,并面临形状不匹配的问题。有我尝试过的东西。

  1. 我在here上找到的一个答案确实将值转换为numpy数组,但是在原始数据帧中它具有4653个观测值,但numpy数组的形状为(4712, 21)。我不明白它是如何增加的,并且在另一尝试中使用相同的代码numpy数组形状降低了原始数据帧的计数。我不明白为什么?

  2. 我也尝试过predictions.select("probability").toPandas().values.shape,但是形状仍然不匹配。我使用pyspark数据框的count()方法来检查数据框的长度。

  3. 我还尝试了pyspark数据框列的toArray()方法使用UTF,导致出现类似org.apache.spark.SparkException: Job aborted due to stage failure: Task 2 in stage 116.0 failed 4 times, most recent failure: Lost task 2.3 in stage 116.0 (TID 6254, 10.2.1.54, executor 0): net.razorvine.pickle.PickleException: expected zero arguments for construction of ClassDict (for numpy.core.multiarray._reconstruct)

  4. 的奇怪错误

这是我在做什么

rf = RandomForestClassifier(
        featuresCol="features",
        labelCol=TARGET_COL,
        predictionCol=TARGET_COL + "_predicted",
        # impurity="entropy"
        # maxDepth=5,
        # numTrees=1000,
        # minInfoGain=0.2,
        # subsamplingRate=0.8
    )

    evaluator = MulticlassClassificationEvaluator(
        predictionCol=TARGET_COL + "_predicted",
        labelCol=TARGET_COL,
        metricName="accuracy"
    )

    paramGrid = ParamGridBuilder(). \
        addGrid(rf.maxDepth, [3, 5, 7, 9, 11]). \
        addGrid(rf.numTrees, [20, 50, 100, 200, 500]). \
        addGrid(rf.minInfoGain, [0.0, 0.2, 0.5, 1.0]). \
        addGrid(rf.subsamplingRate, [0.5, 0.8, 1.0]). \
        addGrid(rf.impurity, ["entropy", "gini"]). \
        build()

    paramGrid = ParamGridBuilder(). \
        addGrid(rf.maxDepth, [3]). \
        addGrid(rf.numTrees, [2]). \
        addGrid(rf.minInfoGain, [0.0]). \
        addGrid(rf.subsamplingRate, [0.5]). \
        addGrid(rf.impurity, ["entropy"]). \
        build()

    tvs = TrainValidationSplit(estimator=rf,
                               estimatorParamMaps=paramGrid,
                               evaluator=evaluator,
                               trainRatio=0.8)

    print("~~~~~~~~~~~ Model Training Started ~~~~~~~~~~~")
    model = tvs.fit(train_df)

    best_model = model.bestModel
    print(best_model._java_obj.parent().getImpurity())
    print(best_model._java_obj.parent().getMaxDepth())
    print(best_model._java_obj.parent().getNumTrees())
    print(best_model._java_obj.parent().getMinInfoGain())
    print(best_model._java_obj.parent().getSubsamplingRate())

    prob_array = []

    predictions = model.transform(test_df)
    print(predictions.count())
    print(test_df.count())

    pprint(predictions.select("probability").head(1)[0].probability)
    pprint(predictions.select("probability").head(1)[0].probability.toArray())
    pprint(type(predictions.select("probability").head(1)[0].probability.toArray()))
    pprint(predictions.select("probability").head(1)[0].probability.toArray().shape)
    print(predictions.select("probability").count())
    print(predictions.select("probability").toPandas())
    print(predictions.select("probability").toPandas().values.shape)

1 个答案:

答案 0 :(得分:0)

我不知道SO上的某些人怎么了,而没有真正理解问题的负面反应。 无论如何,因为我在网上的任何地方都没有得到答案。我必须自己做所有事情,而我意识到需要做更多的研究。

因此,我尝试将numpy数组的形状与count()方法返回的数字进行比较。但是实际上存在差异,collect()返回的行数与列表的长度匹配numpy数组的形状,但与count()方法返回的数不匹配。所以我不明白为什么collect()方法返回的列表长度与count()方法返回的数字之间为什么会有区别。