【问题标题】:LogisticRegressionModel prediction manuallyLogisticRegressionModel 手动预测
【发布时间】:2016-05-04 19:11:16
【问题描述】:

我试图预测DataFrame 中每一行的标签,但由于别有用心,我没有使用LinearRegressionModeltransform 方法,而是试图使用经典公式1 / (1 + e^(-hθ(x))) 手动计算它,请注意,我从Apache Spark 的存储库中复制了代码,并将private 对象BLAS 中的几乎所有内容复制到了它的公共版本中。 PD:我没有使用任何regParam,我只是拟合了模型。

//Notice that I had to obtain intercept, and coefficients from my model
val intercept = model.intercept
val coefficients = model.coefficients

val margin: Vector => Double = (features) => {
  BLAS.dot(features, coefficients) + intercept
}

val score: Vector => Double = (features) => {
  val m = margin(features)
  1.0 / (1.0 + math.exp(-m))
}

在定义了这些函数并获得模型的参数后,我创建了一个UDF 来计算预测(它接收与DenseVector 相同的特征),然后我将我的预测与真实模型的预测进行比较,它们是 非常不同! 那么我错过了什么?我做错了什么?

val predict = udf((v: DenseVector) => {
  val recency = v(0)
  val frequency = v(1)
  val tp = score(new DenseVector(Array(recency, frequency)))
  new DenseVector(Array(tp, 1 - tp))
})

// model's predictions
val xf = model.transform(df)

df.select(col("id"), predict(col("features")).as("myprediction"))
  .join(xf, df("id") === xf("id"), "inner")
  .select(df("id"), col("probability"), col("myprediction"))
  .show

+----+--------------------+--------------------+
|  id|         probability|        myprediction|
+----+--------------------+--------------------+
|  31|[0.97579780436514...|[0.98855386037790...|
| 231|[0.97579780436514...|[0.98855386037790...|
| 431|[0.69794428333266...|           [1.0,0.0]|
| 631|[0.97579780436514...|[0.98855386037790...|
| 831|[0.97579780436514...|[0.98855386037790...|
|1031|[0.96509616791398...|[0.99917463322937...|
|1231|[0.96509616791398...|[0.99917463322937...|
|1431|[0.96509616791398...|[0.99917463322937...|
|1631|[0.94231815700848...|[0.99999999999999...|
|1831|[0.96509616791398...|[0.99917463322937...|
|2031|[0.96509616791398...|[0.99917463322937...|
|2231|[0.96509616791398...|[0.99917463322937...|
|2431|[0.95353743438055...|           [1.0,0.0]|
|2631|[0.94646924057674...|           [1.0,0.0]|
|2831|[0.96509616791398...|[0.99917463322937...|
|3031|[0.96509616791398...|[0.99917463322937...|
|3231|[0.95971207153567...|[0.99999999999996...|
|3431|[0.96509616791398...|[0.99917463322937...|
|3631|[0.96509616791398...|[0.99917463322937...|
|3831|[0.96509616791398...|[0.99917463322937...|
+----+--------------------+--------------------+

编辑

我什至尝试在udf 中定义这样的函数,但没有成功。

def predict(coefficients: Vector, intercept: Double) = {
  udf((v: DenseVector) => {
    def margin(features: Vector, coefficients: Vector, intercept: Double): Double = {
      BLAS.dot(features, coefficients) + intercept
    }

    def score(features: Vector, coefficients: Vector, intercept: Double): Double = {
      val m = margin(features, coefficients, intercept)
      1.0 / (1.0 + math.exp(-m))
    }

    val recency = v(0)
    val frequency = v(1)
    val tp = score(new DenseVector(Array(recency, frequency)), coefficients, intercept)
    new DenseVector(Array(tp, 1 - tp))
  })
}

【问题讨论】:

  • 乍一看,公式似乎没有任何问题,Spark 似乎返回了预期的结果,但您的代码有异味。由于 val 在定义时进行评估并且您从外部范围获得系数,因此很可能使用了超出您预期的其他东西。
  • @zero323 我使用模型的截距和具有某些特征的系数计算了点积,它们的计算方式与我的代码中的完全相同,实际上结果与我的公式中的结果完全相同,但与 spark 的结果不同.但是,我会将它们定义为函数,并将其他值作为参数传递,以防万一。

标签: scala apache-spark logistic-regression


【解决方案1】:

这很尴尬但实际上问题是因为我使用了Pipeline并添加了MinMaxScaler作为阶段,因此在模型训练之前对数据集进行了缩放,因此两个参数coefficientsintercept被捆绑缩放数据,所以当我使用它们计算预测时,结果完全有偏差。因此,为了解决这个问题,我只是对训练数据集进行了非标准化处理,这样我就可以获得coefficientsintercept。在我重新执行代码后,我得到了与Spark 相同的结果。另一方面,我听取了@zero323 的意见,并将marginscore 定义移到udf 的第一个lambda 声明中。

【讨论】:

    猜你喜欢
    • 2020-11-06
    • 1970-01-01
    • 2019-11-07
    • 2020-02-24
    • 1970-01-01
    • 2018-07-20
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多