二元分类的spark logistic回归:应用新阈值来预测2个类

时间:2017-12-08 03:47:47

标签: python apache-spark pyspark classification logistic-regression

我是Spark和Python的新手。我使用Spark来训练一个只有两个类(0和1)的Logistic回归模型。我用我的火车数据框训练了它。

这是我的管道模型的定义方式:

# Model definition:
lr = LogisticRegression(featuresCol = "lr_features", labelCol = "targetvar")
# Pipeline definition:
lr_pipeline = Pipeline(stages = indexStages + encodeStages +[lr_assembler, lr])
# Fit the logistic regression model:
lrModel = lr_pipeline.fit(train)

然后我使用我的测试数据框运行预测:

lr_predictions = lrModel.transform(test)

现在,我的lr_predictions有一个列'概率'这对我来说就像一个嵌套列表。例如,它的第一个单元格包含: 并[1,2,[],[0.88,0.11]]
我假设,这意味着:第1类(= 0)的概率为0.88,第2类(即= 1)的概率为0.11。

默认情况下(阈值= 0.5)预测此观察结果 因为,我找到了一个最大化F-measure的值(bestThreshold)(在我的例子中它是0.21):

fMeasure = lr_summary.fMeasureByThreshold
bestThreshold = fMeasure.orderBy(fMeasure['F-Measure'].desc()).first().threshold

我想将bestThreshold应用于'概率'专栏并获得一个新的 列(' pred_new',例如)包含基于bestThreshold而非0.5的类分配(0或1)。

我无法使用下面的代码,因为'概率'列过于复杂:

from pyspark.sql.functions import when
lr_predictions = lr_predictions.withColumn("prob_best", \
              when(lr_predictions["probability"] >= bestThreshold, 1).otherwise(0)

我觉得我需要映射概率'基于新阈值的新列。但我不知道该怎么做 - 鉴于这个复杂的(对我而言)概率的结构'列。

非常感谢你的建议!

1 个答案:

答案 0 :(得分:3)

如果lrModelLogisticRegressionModel

type(lrModel)
## pyspark.ml.classification.LogisticRegressionModel

您可以使用内部Java对象来设置阈值

lrModel._java_obj.setThreshold(bestThreshold)

并转换:

lrModel.transform(data)

您也可以这样做来修改rawPredictionColpredictionColprobabilityCol

这将成为未来公共API的一部分(2.3):

lrModel.transform(data, {lrModel.threshold: bestThreshold})

您也可以使用UDF:

from pyspark.sql.functions import udf, lit

@udf("integer")
def predict(v, threshold):
    return 0 if v[0] >= bestThreshold  else 1

lr_predictions.withColumn(
   "prob_best",
   predict(lr_predictions["probability"], lit(bestThreshold)))

修改

使用PipelineModel,您可以尝试访问LogisticRegressionModel(如your previous question中所述)并执行相同的操作。