2016-08-05 111 views
2

檢查更新的問題線性迴歸星火MLlib只返回單調的預測

摘要的底部:我有一個不線性表現的數據集。我試圖使用Spark的MLlib(v1.5.2)來擬合一個更像多項式函數的模型,但我總是得到一個線性模型。我不知道是否可以使用線性迴歸來獲得非線性模型。

[TL; DR]我想適合代表足夠好以下數據模型:(每教程很像)

enter image description here

我的代碼很簡單

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 
    } 
} 

獲得的結果是在正確的範圍內,但它們始終處於單調遞增的行中。我試圖把頭圍繞在它周圍,但我無法弄清楚爲什麼更好的曲線不適合。

任何提示?

謝謝大家

更新 問題是由火花的版本引起的火花毫升,我們使用的庫。出於某種原因,即使我提供了更多功能(輸入數據的平方或立方版本),版本1.5.2也不適合更好的曲線。在升級到版本2.0.0並從主API(不是RDD API)的棄用LinearRegressionWithSGD切換到LinearRegression後,該算法表現得如預期。採用這種新方法,模型符合正確的曲線。

回答

4

這裏沒有什麼意外的。您使用的形式的線性模型

Y = βx + ε 

所以擬合結果將總是形成一條線通過原點去(不像例如R,火花默認放不下截距)並且只要該模型是至少略微穩健它應該越來越接近數據的分佈。

雖然細節可能是關於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) 

enter image description here

Spark中創建的模型或多或少等同於:

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

enter image description here

既然我們將與您的數據的一個非常粗略的估計開始很明顯,模型傳遞槽的起源並不是一個好的讓我們嘗試添加一個截距:

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

enter image description here

最後,我們知道我們需要一些非線性:

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

enter image description here

這裏帶走的消息是:在創建模型時

  • 使用setIntercept(true)LinearRegressionModel
  • 向模型添加一些非線性特徵。

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

感謝@ zero323,雖然我們發現了問題的根源,你在正確的方向指向我們。出於這個原因,我打算將您的答案標記爲正確答案。我會在問題的更新中發佈真正的問題。 – omrsin