Почему LinearRegressionWithSGD в Spark работает очень медленно локально?

Вопрос или проблема

Я уже некоторое время пытаюсь запустить линейную регрессию с помощью SGD, которая находится в Spark mllib, и испытываю огромные проблемы с производительностью. Все примеры, которые я рассматривал, имеют число итераций, равное 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 минут, чтобы обучить модель на 70 000 записей с вектором признаков размером 2. И результаты, которые я получаю, совсем не хороши. Я начинаю получать приемлемые результаты только при numberOfIterations = 1000, но это займет вечность.

Это нормально, что линейная регрессия с SGD работает так медленно для 70 000 векторов размером 2?

Минимальная и начальная память моей JVM установлена на 4g. Я также пытался установить следующее (безрезультатно): System.setProperty("spark.executor.memory", "3g")

Я запускаю это локально, и поскольку обычная линейная регрессия, написанная в MatLab, завершала бы работу очень быстро, я задаюсь вопросом, что я делаю неправильно?

Редактирование: Когда я смотрю на интерфейс Spark в разделе задач, я вижу, что он создает слишком много задач для градиентного спуска. Есть ли способ, которым я мог бы сказать Spark создавать очень мало задач – т.е. не разбивать данные, выполнять все в одном потоке? Возможно, это поможет мне дальше разобраться в проблеме.

Spark предназначен для распределенной работы в кластере и использует стохастический градиентный спуск (SGD) для оптимизации линейной регрессии.

Существует накладные расходы на инфраструктуру кластера (даже когда “кластер” — это одна локальная нода). Кроме того, SGD — это итеративный метод, который использует много батчей для нахождения решения.

Учитывая, что ваша задача состоит из 70k строк, лучше использовать однопоточную среду (например, scikit-learn) и метод наименьших квадратов (OLS), который является аналитическим решением для оптимизации линейной регрессии. Эти два изменения значительно ускорят процесс обучения.

Ответ или решение

Использование библиотеки Spark для выполнения линейной регрессии с пошаговым градиентным спуском (SGD) может быть затруднительным при локальном запуске, особенно в случае небольших объемов данных. Ваша ситуация с 70,000 векторами размером 2 является примером, когда кластерные вычисления Spark могут быть избыточными и даже контрпродуктивными. Давайте рассмотрим причины, по которым Spark и его алгоритм LinearRegressionWithSGD могут показывать низкую производительность при локальной работе, и как можно улучшить ситуацию.

Проблемы и решения

  1. Накладные расходы инициализации Spark:
    Spark разработан для работы с большими данными в распределенных системах. Даже при запуске на локальном узле, он создает инфраструктуру, которая влечет за собой значительные накладные расходы. Настройка cluster mode, даже при локальной работе, может привести к множественным избыточным заданиям.

    Решение:
    Используйте библиотеку, оптимизированную для однопроцессорных вычислений, такую как scikit-learn, которая идеально подходит для работы с объемами данных до нескольких сотен тысяч записей.

  2. Метод итеративного спуска при малых данных:
    Stochastic Gradient Descent (SGD) — это итеративный метод оптимизации, который требует нескольких проходов по данным для достижения сходимости. Это может занять значительное время на маломощных системах.

    Решение:
    Рассмотрите возможность использования методов, которые предоставляют аналитическое решение, таких как метод наименьших квадратов (OLS), доступный, например, в библиотеке scikit-learn. Он более эффективен для таких скромных объемов данных.

  3. Качество данных и эффективность алгоритма:
    Нехватка нормализации данных или недостаточная настройка параметров градиентного спуска также могут замедлить процесс обучения и ухудшить его результаты.

    Решение:
    Убедитесь, что данные правильно нормализованы, а параметры модели, такие как скорость обучения и количество итераций, оптимизированы для вашей задачи.

Основные выводы

Для небольшой выборки данных лучше всего использовать библиотеку, подходящую для работы на локальном уровне, например, scikit-learn. Это позволит избежать избыточных накладных расходов Spark и получить быстрое и точное решение задачи линейной регрессии. При этом важно помнить, что применение Spark оправдано только тогда, когда у вас действительно большие данные, требующие распределенной обработки.

Оцените материал
Добавить комментарий

Капча загружается...