检查问题底部的更新
总结:我的数据集不是线性的。我正在尝试使用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
后,算法按预期运行。使用这种新方法,模型拟合了正确的曲线。
答案 0 :(得分:4)
这里没有任何意外。您使用形式的线性模型
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))