【问题标题】:Linear regression with Spark MLlib only returns monotonic predictionsSpark MLlib 的线性回归仅返回单调预测
【发布时间】:2016-12-12 00:59:12
【问题描述】:

查看问题底部的更新

总结:我有一个行为不是线性的数据集。我正在尝试使用 Spark 的 MLlib(v1.5.2) 来拟合一个更像多项式函数的模型,但我总是得到一个线性模型。我不知道是否无法使用线性回归获得非线性模型。

[TL;DR] 我正在尝试拟合一个模型,该模型可以充分代表以下数据:

我的代码非常简单(和每个教程中的差不多)

object LinearRegressionTest {

   def main(args: Array[String]): Unit = {
      val sc = new SparkContext("local[2]", "Linear Regression")
      val data = sc.textFile("data2.csv")
      val parsedData = data.map { line =>
         val parts = line.split(',')
         LabeledPoint(parts(1).toDouble, Vectors.dense(parts(2).toDouble))
       }.cache()

      val numIterations = 1000
      val stepSize = 0.001

      val model = LinearRegressionWithSGD.train(parsedData, numIterations, stepSize)
      sc.stop
   }
}

获得的结果在正确的范围内,但它们始终处于单调递增的行中。我试图绕着它转,但我无法弄清楚为什么没有拟合更好的曲线。

有什么建议吗?

谢谢大家

更新 问题是由我们使用的 spark 和 spark-ml 库的版本引起的。出于某种原因,即使我提供了更多功能(输入数据的平方或立方版本),1.5.2 版也没有拟合更好的曲线。在升级到版本 2.0.0 并从主 API(不是 RDD API)的弃用 LinearRegressionWithSGD 切换到 LinearRegression 后,算法的行为符合预期。使用这种新方法,模型拟合了正确的曲线。

【问题讨论】:

    标签: scala apache-spark linear-regression apache-spark-mllib


    【解决方案1】:

    这里没有什么意外的。您使用形式的线性模型

    Y = βx + ε
    

    所以拟合结果将始终形成一条穿过原点的线(与 R 不同,Spark 默认情况下不拟合截距)并且只要模型至少略微健全,它就应该增加到近似数据分布。

    虽然 StackOverflow 上的细节可能不是主题,但您应该从添加更多功能开始。很明显,这里的近似值必须是二次的,所以让我们一步一步地说明这一点。我们将从对您的数据进行非常粗略的近似开始:

    y <- c(0.6, 0.6, 0.6, 0.6, 0.575, 0.55, 0.525, 0.475, 0.45, 0.40, 0.35, 0.30)
    df <- data.frame(y=c(y, rev(y)), x=0:23)
    plot(df$x, df$y)
    

    在 Spark 中创建的模型或多或少等同于:

    lm1 <- lm(y ~ x + 0, df)
    lines(df$x, predict(lm1, df), col='red')
    

    既然很明显模型通过低谷原点是不好的,让我们尝试添加一个截距:

    lm2 <- lm(y ~ x, df)
    lines(df$x, predict(lm2, df), col='blue')
    

    最后我们知道我们需要一些非线性:

    df$x2 <- df$x ** 2
    lm3 <- lm(y ~ x + x2, df)
    lines(df$x, predict(lm3, df), col='green')
    

    这里的外卖信息是:

    • 创建模型时使用setIntercept(true)LinearRegressionModel,
    • 为模型添加一些非线性特征。

      val x = arts(2).toDouble
      LabeledPoint(parts(1).toDouble, Vectors.dense(x, x*x))
      

    【讨论】:

    • 感谢@zero323,尽管我们找到了问题的根源,您为我们指明了正确的方向。出于这个原因,我会将您的答案标记为正确的答案。我将在问题更新时发布真正的问题。
    猜你喜欢
    • 2019-12-31
    • 2018-10-09
    • 2014-07-19
    • 2014-12-03
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多