Spark mllib线性回归给出了非常糟糕的结果

时间:2016-06-08 23:34:09

标签: python apache-spark pyspark linear-regression apache-spark-mllib

在尝试使用Spark使用Spark mllib的LinearRegressionWithSGD进行线性回归时,我得到了非常差的结果

我查看了类似的问题,如下所示:

我很清楚关键是调整参数恰到好处

我也理解随机梯度下降不一定会找到最佳解决方案(如交替最小二乘方式),因为它有可能陷入局部最小值。但至少我期望找到一个好的模型。

以下是我的设置,我选择使用Journal of Statistics教育中的this example和相应的dataset。我从本文中了解到(并在JMP中复制结果)如果我只使用数字字段,我应该得到类似下面的等式(R ^ 2为~44%,RMSE为~7400):< / p>

价格= 7323 - 0.171里程+ 3200缸 - 1463门+ 6206巡航 - 2024声音+ 3327皮革

由于我不知道如何设置参数恰到好处,我运行了以下蛮力方法:

from collections import Iterable
from pyspark import SparkContext
from pyspark.mllib.regression import LabeledPoint
from pyspark.mllib.regression import LinearRegressionWithSGD
from pyspark.mllib.evaluation import RegressionMetrics

def f(n):
    return float(n)

if __name__ == "__main__":
    sc = SparkContext(appName="LinearRegressionExample")

    # CSV file format:
    # 0      1        2     3      4     5     6         7      8      9       10     11
    # Price, Mileage, Make, Model, Trim, Type, Cylinder, Liter, Doors, Cruise, Sound, Leather
    raw_data = sc.textFile('file:///home/ccastroh/training/pyspark/kuiper.csv')

    # Grabbing numerical values only (for now)
    data = raw_data \
        .map(lambda x : x.split(','))  \
        .map(lambda x : [f(x[0]), f(x[1]), f(x[6]), f(x[8]), f(x[9]), f(x[10]), f(x[11])])
    points = data.map(lambda x : LabeledPoint(x[0], x[1:])).cache()

    print "Num, Iterations, Step, MiniBatch, RegParam, RegType, Intercept?, Validation?, " + \
        "RMSE, R2, EXPLAINED VARIANCE, INTERCEPT, WEIGHTS..."
    i = 0
    for ite in [10, 100, 1000]:
      for stp in [1, 1e-01, 1e-02, 1e-03, 1e-04, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09, 1e-10]:
        for mini in [0.2, 0.4, 0.6, 0.8, 1.0]:
          for regP in [0.0, 0.1, 0.01, 0.001]:
            for regT in [None, 'l1', 'l2']:
              for intr in [True]:
                for vald in [False, True]:
                  i += 1

                  message = str(i) + \
                      "," + str(ite) + \
                      "," + str(stp) + \
                      "," + str(mini) + \
                      "," + str(regP) + \
                      "," + str(regT) + \
                      "," + str(intr) + \
                      "," + str(vald)

                  model = LinearRegressionWithSGD.train(points, iterations=ite, step=stp, \
                      miniBatchFraction=mini, regParam=regP, regType=regT, intercept=intr, \
                      validateData=vald)

                  predictions_observations = points \
                      .map(lambda p : (float(model.predict(p.features)), p.label)).cache()
                  metrics = RegressionMetrics(predictions_observations)
                  message += "," + str(metrics.rootMeanSquaredError) \
                     + "," + str(metrics.r2) \
                     + "," + str(metrics.explainedVariance)

                  message += "," + str(model.intercept)
                  for weight in model.weights:
                      message += "," + str(weight)

                  print message
    sc.stop()

正如您所看到的,我基本上运行了3960种不同的变体。在这些中,我得到的任何东西都与纸张或JMP中的公式非常相似。以下是一些亮点:

  • 在很多次跑步中,我获得了拦截和重量的NaN
  • 我得到的最高R ^ 2是-0.89。我甚至不知道你可以得到负R ^ 2。事实证明,负值表示所选模型fits worse than a horizontal line
  • 我得到的最低RMSE是13600,这比预期的7400差。

我也尝试了normalizing the values,以便在[0,1]范围内,并且没有任何帮助

有没有人知道如何获得一半体面的线性回归模型?我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

有类似的问题。 使用DecisionTree和RandomForest回归工作正常,如果你想要一个非常准确的解决方案,那么生成连续标签并不是很好。

然后测试线性回归也像你为每个参数使用多个值并使用多个数据集并且没有得到任何远离真实值的解决方案。 在训练模型之前,还尝试使用StandardScaler进行特征缩放,但也完全不满意。 : - (

编辑:将拦截设置为true可能会解决问题。