为什么 Spark 的 LinearRegressionWithSGD 在本地很慢?

数据挖掘 预测建模 回归 阿帕奇火花
2022-02-24 04:12:41

一段时间以来,我一直在尝试使用 Spark mllib 中的 SGD 运行线性回归,但我遇到了巨大的性能问题。我正在查看的所有示例都将迭代次数设置为 100,并说 Spark mllib 可以非常快速地处理大数据。

这是我遇到问题的代码:

    def train(data: RDD[TrainFeature], scalerModel: StandardScalerModel): LinearRegressionModel = {
    val labeledData = data map { trainFeature =>
      LabeledPoint(trainFeature.relevance.value, toVector(trainFeature.feature, scalerModel))
    }
    labeledData.cache()

    val algorithm = new LinearRegressionWithSGD()
    algorithm.optimizer
      .setNumIterations(10)
      .setRegParam(0.01)
      .setStepSize(0.1)

    algorithm run labeledData
  }

private def toVector(feature: Feature, scalerModel: StandardScalerModel): Vector = scalerModel transform toVector(feature)

private def toVector(feature: Feature): Vector = Vectors dense feature.coordinates.toArray

我先对数据进行了缩放,然后运行算法来训练模型。即使我使用 10 次迭代,也需要大约 10 分钟来训练具有大小为 2 的特征向量的 70,000 个条目的模型。而且我得到的结果一点也不好。在 numberOfIterations = 1000 之后,我开始得到不错的结果,但这需要很长时间。

对于 70,000 个大小为 2 的向量,使用 SGD 的线性回归如此缓慢是否正常?

我的 JVM 最小和初始内存设置为 4g。我也尝试过设置以下内容(失败的尝试):System.setProperty("spark.executor.memory", "3g")

我在本地运行它,因为用 MatLab 编写的普通 LinearRegression 会很快完成这项工作,我想知道我做错了什么?

编辑:当我在作业部分查看 spark UI 时,我发现它为梯度下降创造了太多的作业。有没有一种方法可以告诉 Spark 创建非常少的作业——即不要拆分数据,在单个线程中运行所有内容?也许这可以帮助我进一步调试问题。

1个回答

Spark 旨在跨集群分布,并使用随机梯度下降 (SGD) 来优化线性回归。

集群基础设施存在开销(即使“集群”是单个本地节点)。此外,SGD 是一种迭代方法,它使用许多批次来寻找解决方案。

鉴于您的问题是 70k 行,最好使用单节点框架(例如 scikit-learn)和普通最小二乘法 (OLS)(一种封闭形式的解决方案)来优化线性回归。这两个变化将大大加快训练速度。