Функции ADQM для машинного обучения

ADQM/ClickHouse предоставляет набор функций для машинного обучения — агрегатные функции, реализующие алгоритмы машинного обучения, которые можно обучить на известных наборах данных, а затем использовать для прогнозирования неизвестных значений.

Основные понятия

В этой статье алгоритмы машинного обучения и особенности применения соответствующих функций ADQM описаны с использованием следующей терминологии:

  • Независимые и зависимые переменные. Независимые переменные являются входными данными для алгоритма машинного обучения. Зависимые переменные — это выходные (прогнозируемые, целевые) данные, которые зависят от независимых переменных. Другими словами, независимые переменные — это признаки (features), описывающие характеристики объекта или явления, по значениям которых можно прогнозировать значение целевой переменной (target) с помощью обученной модели машинного обучения.

  • Обучающий и тестовый наборы данных. Обучающий набор данных (training data) — данные, которые используются для обучения модели машинного обучения. Обучающие данные должны включать столбцы со значениями независимых переменных и столбец с целевым значением, которое необходимо научиться предсказывать. Тестовый набор данных (test data) — другой набор данных, который не зависит от обучающих данных и используется для оценки модели, построенной с помощью обучающего набора данных.

  • Обучение модели. Алгоритм машинного обучения находит закономерности в предоставленных обучающих данных, сопоставляя значения независимых переменных с целевым значением, и выводит модель машинного обучения, которая фиксирует эти закономерности. Затем модель можно использовать для получения прогнозов на основе новых данных, для которых значения зависимой переменной неизвестны.

  • Параметры модели или веса (коэффициенты) регрессии. Параметры модели (или веса регрессии) определяют, как независимые переменные влияют на зависимую переменную. Например, в функциональном уравнении линейной регрессии параметрами модели являются константы (  — свободный коэффициент или смещение). Параметры модели автоматически вычисляются в процессе обучения модели на основе обучающих данных и возвращаются функцией машинного обучения ADQM.

  • Гиперпараметры модели. Гиперпараметры — характеристики модели, которые вручную настраиваются до начала процесса обучения и определяют структуру модели и способ ее обучения. Правильный подбор гиперпараметров может значительно повлиять на эффективность модели и точность результатов обучения.

Алгоритмы машинного обучения

В ADQM функции машинного обучения реализуют следующие алгоритмы регрессии.

Простая линейная регрессия

Функция simpleLinearRegression(<feature>, <target>) выполняет простую линейную регрессию, то есть вычисляет линейную зависимость между двумя переменными — одной независимой и целевой. В качестве параметров <feature> и <target> в функцию передаются столбцы обучающего набора данных со значениями независимой и целевой переменных соответственно.

Стохастическая регрессия

Для прогнозирования значений целевой переменной на основе нескольких независимых переменных ADQM предоставляет следующие функции множественной регрессии, использующие стохастический градиентный спуск в качестве способа обучения модели:

  • stochasticLinearRegression([<hyperparameters>])(<target>, <feature1>, <feature2>, …​) — вычисляет линейную зависимость между целевой переменной (<target>) и набором независимых переменных (<feature1>, <feature2>, …​) и позволяет получить прогноз непрерывных числовых значений зависимой переменной на основе наблюдаемых значений независимых переменных.

  • stochasticLogisticRegression([<hyperparameters>])(<target>, <feature1>, <feature2>, …​) — позволяет оценить вероятность наступления некоторого события по значениям множества признаков. Зависимая переменная может принимать одно из двух значений — обычно это 0 (событие не произошло) и 1 (событие произошло). Используется для задач бинарной классификации.

При использовании функции стохастической регрессии для построения модели машинного обучения можно указать четыре гиперпараметра (<hyperparameters> в приведенных выше описаниях синтаксиса функций). В следующей таблице гиперпараметры перечислены в том порядке, в котором они должны последовательно передаваться в функцию.

Гиперпараметр Описание Значение по умолчанию

learning rate

Скорость обучения, которая указывается как коэффициент длины шага при выполнении градиентного спуска. Слишком большая скорость обучения может привести к бесконечным весам модели

0.00001

l2 regularization coefficient

Коэффициент регуляризации L2, который позволяет избежать переобучения (мешает модели подгоняться под обучающие данные)

0.1

mini-batch size

Количество элементов обучающей выборки, градиенты которых будут вычисляться и суммироваться при выполнении одного шага градиентного спуска. Чистый стохастический спуск использует один элемент, однако использование мини-пакета из фиксированного небольшого числа элементов (около 10 элементов) делает градиентные шаги более стабильными

15

method for updating weights

Метод обновления весов. Возможные значения: Adam (по умолчанию), SGD, Momentum и Nesterov. Последние два метода более требовательны к вычислительным ресурсам и памяти, однако они имеют высокую скорость сходимости и устойчивость методов стохастического градиента

Adam

Использование функций машинного обучения

Функции машинного обучения используются на двух этапах: построение модели и прогнозирование новых данных.

Построение модели

Для построения модели необходимо выполнить следующие действия:

  1. Создайте таблицу на основе набора данных для обучения. Пример запроса:

    CREATE TABLE train_data
    (
        feature1 Float64,
        feature2 Float64,
        target Float64
    )
    ENGINE = MergeTree;

    Для линейной регрессии независимые (feature1, feature2…​) и целевая (target) переменные должны быть числовыми. Для логистической регрессии целевая переменная должна быть бинарной (то есть принимает только два значения — например, 0 и 1), а прогнозируемые значения (вероятности) будут находиться в диапазоне от 0 до 1.

  2. Используйте функцию машинного обучения с комбинатором State, чтобы построить модель и сохранить ее состояние для дальнейшего использования. Пример запроса с функцией stochasticLinearRegression:

    CREATE TABLE my_model ENGINE = Memory AS SELECT
    stochasticLinearRegressionState(0.001, 0.1, 10, 'SGD')(target, feature1, feature2)
    AS state FROM train_data;

    Если не применять комбинатор State к функции машинного обучения, можно получить параметры созданной модели без ее сохранения. Например, следующий запрос построит модель и вернет ее параметры (столбец, в котором первые значения соответствуют весам регрессии, а последнее — смещению):

    stochasticLinearRegression(0.001, 0.1, 10, 'SGD')(target, feature1, feature2) FROM train_data;

Прогнозирование

Сохраненное в таблице состояние модели можно использовать несколько раз для прогнозирования или объединить с другими состояниями и создать новые (улучшенные) модели.

  1. Создайте таблицу на основе набора данных для тестирования (test_data в приведенном ниже примере синтаксиса). Эта таблица по структуре должна быть аналогична train_data, но может не содержать целевое (прогнозируемое) значение.

  2. Для прогнозирования используйте функцию evalMLMethod, которая принимает в качестве аргументов состояние модели и признаки для прогнозирования. Например, следующий запрос возвращает столбец значений целевой переменной, прогнозируемых по значениям признаков feature1 и feature2 в таблице test_data:

    WITH (SELECT state FROM my_model) AS model SELECT
    evalMLMethod(model, feature1, feature2) FROM test_data;

Пример

Подготовка данных

  1. Создайте таблицы с данными для обучения (trips_train) и тестирования (trips_test), как описано в примере New York Taxi Data документации ClickHouse:

    CREATE TABLE trips_train (
        trip_id             UInt32,
        pickup_datetime     DateTime,
        dropoff_datetime    DateTime,
        pickup_longitude    Nullable(Float64),
        pickup_latitude     Nullable(Float64),
        dropoff_longitude   Nullable(Float64),
        dropoff_latitude    Nullable(Float64),
        passenger_count     UInt8,
        trip_distance       Float32,
        fare_amount         Float32,
        extra               Float32,
        tip_amount          Float32,
        tolls_amount        Float32,
        total_amount        Float32,
        payment_type        Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
        pickup_ntaname      LowCardinality(String),
        dropoff_ntaname     LowCardinality(String)
    )
    ENGINE = MergeTree
    PRIMARY KEY (pickup_datetime, dropoff_datetime);
    CREATE TABLE trips_test (
        trip_id             UInt32,
        pickup_datetime     DateTime,
        dropoff_datetime    DateTime,
        pickup_longitude    Nullable(Float64),
        pickup_latitude     Nullable(Float64),
        dropoff_longitude   Nullable(Float64),
        dropoff_latitude    Nullable(Float64),
        passenger_count     UInt8,
        trip_distance       Float32,
        fare_amount         Float32,
        extra               Float32,
        tip_amount          Float32,
        tolls_amount        Float32,
        total_amount        Float32,
        payment_type        Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
        pickup_ntaname      LowCardinality(String),
        dropoff_ntaname     LowCardinality(String)
    )
    ENGINE = MergeTree
    PRIMARY KEY (pickup_datetime, dropoff_datetime);
  2. Заполните таблицы trips_train и trips_test данными из файлов trips_0.gz и trips_1.gz хранилища S3 соответственно:

    INSERT INTO trips_train
    SELECT
        trip_id,
        pickup_datetime,
        dropoff_datetime,
        pickup_longitude,
        pickup_latitude,
        dropoff_longitude,
        dropoff_latitude,
        passenger_count,
        trip_distance,
        fare_amount,
        extra,
        tip_amount,
        tolls_amount,
        total_amount,
        payment_type,
        pickup_ntaname,
        dropoff_ntaname
    FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_0.gz', 'TabSeparatedWithNames');
    INSERT INTO trips_test
    SELECT
        trip_id,
        pickup_datetime,
        dropoff_datetime,
        pickup_longitude,
        pickup_latitude,
        dropoff_longitude,
        dropoff_latitude,
        passenger_count,
        trip_distance,
        fare_amount,
        extra,
        tip_amount,
        tolls_amount,
        total_amount,
        payment_type,
        pickup_ntaname,
        dropoff_ntaname
    FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_1.gz', 'TabSeparatedWithNames');

Построение модели машинного обучения

  1. Создайте модель машинного обучения для прогнозирования стоимости проезда в такси (целевая переменная — fare_amount) в зависимости от количества пассажиров и дальности поездки (независимые переменные — passenger_count и trip_distance):

    SELECT stochasticLinearRegression(0.001, 0.1, 5)(fare_amount, passenger_count, trip_distance)
    FROM trips_train;

    В результате выполнения этого запроса выводятся параметры модели, которые определяют коэффициенты уравнения линейной регрессии ( ):

    ┌─stochasticLinearRegression(0.001, 0.1, 5)(fare_amount, passenger_count, trip_distance)─┐
    │ [0.08194997204590103,2.706812913667359,4.897836872083942]                              │
    └────────────────────────────────────────────────────────────────────────────────────────┘
    
    1 row in set. Elapsed: 0.036 sec. Processed 1.00 million rows, 9.01 MB (27.71 million rows/s., 249.35 MB/s.)
    Peak memory usage: 2.38 MiB.

    Как видно, стоимость проезда не сильно зависит от количества пассажиров.

  2. Сохраните состояние модели в таблицу taxi_trips_model на базе движка Memory:

    CREATE TABLE taxi_trips_model ENGINE = Memory AS
    SELECT stochasticLinearRegressionState(0.001, 0.1, 5)(fare_amount, passenger_count, trip_distance)
    AS state FROM trips_train;

Оценка модели

Используйте обученную модель для получения прогнозов по тестовому набору данных и сравните эти прогнозы с фактическими значениями (обратите внимание, в функцию evalMLMethod передается состояние модели и тот же набор независимых переменных, который использовался для обучения — passenger_count и trip_distance):

WITH (SELECT state FROM taxi_trips_model) AS model
SELECT
    fare_amount,
    evalMLMethod(model, passenger_count, trip_distance) AS prediction
FROM trips_test LIMIT 10;

В результирующей таблице видно, что полученные прогнозы довольно близки к фактическим данным:

┌─fare_amount─┬─────────prediction─┐
│         8.5 │   9.20394916259993 │
│        13.5 │ 13.714548983540645 │
│        41.5 │  41.78716293769729 │
│          24 │ 22.230999964014817 │
│         8.5 │  9.018605114531145 │
│         6.5 │ 7.6682400731869595 │
│        19.5 │ 21.287184808552087 │
│          19 │ 20.377558220769647 │
│         7.5 │ 7.8100114849842495 │
│           9 │  8.954756513157905 │
└─────────────┴────────────────────┘

Для более точных прогнозов можно подобрать другие гиперпараметры модели.

Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней