Моделирование регрессии для списков аудиторий

Прогнозы с помощью существующей модели линейной или логистической регрессии (с известными весовыми значениями) можно создавать без ML.PREDICT, даже если у вас нет доступа к самой модели. Для этого вам понадобится обходное решение, позволяющее использовать модели регрессии с дифференциальной приватностью в запросах активации аудиторий через Ads Data Hub.

В пошаговом примере ниже рассказывается, как выполнить симуляцию логического вывода для существующих моделей линейной и бинарной логистической регрессии, а затем сравнить результаты с результатами ML.PREDICT, чтобы подтвердить точность симуляции. Также здесь приводится пример того, как с помощью бинарной логистической модели создать список аудитории, который будет использоваться для применения модели конверсий к активации аудиторий.

Обзор примера

  1. Создание данных
  2. Обучение модели
  3. Получение весовых значений и точек пересечения
  4. Симуляция прогноза
  5. Сравнение результатов

Пошаговый пример

1. Создание данных

Создайте для обучения модели таблицу, содержащую смоделированные данные. Пометьте часть строк как ограниченный набор.

Линейная регрессия

CREATE OR REPLACE TABLE DATASET_NAME.LIN_REG_TRAINING_SET AS
  WITH
  A AS (
    SELECT
      *
    FROM
      UNNEST(GENERATE_ARRAY(1, 100000)) AS row_number),
  B AS (
    SELECT
      row_number,
      RAND() AS rand_label,
      RAND() AS rand_feature_1,
      RAND() AS rand_feature_2,
      RAND() AS rand_feature_3,
      RAND() AS rand_feature_4,
      RAND() AS rand_feature_5,
      RAND() AS rand_feature_6,
      RAND() AS rand_feature_7,
      RAND() AS rand_feature_8,
      RAND() AS rand_feature_9,
      RAND() AS rand_feature_10
    FROM
      A),
  C AS (
    SELECT
      rand_label AS label,
      *
    FROM
      B),
  D AS (
    SELECT
    row_number,
    CAST(round(10 * label) AS INT64) AS label,
    (rand_label + rand_feature_1) / 2 AS feature_1,
    (rand_label + rand_feature_2) / 2 AS feature_2,
    (rand_label + rand_feature_3) / 2 AS feature_3,
    (rand_label + rand_feature_4) / 2 AS feature_4,
    (rand_label + rand_feature_5) / 2 AS feature_5,
    (rand_label + rand_feature_6) / 2 AS feature_6,
    (rand_label + rand_feature_7) / 2 AS feature_7,
    (rand_label + rand_feature_8) / 2 AS feature_8,
    (rand_label + rand_feature_9) / 2 AS feature_9,
    (rand_label + rand_feature_10) / 2 AS feature_10
    FROM
    C)

SELECT
  label,
  feature_1,
  feature_2,
  feature_3,
  feature_4,
  feature_5,
  feature_6,
  feature_7,
  feature_8,
  feature_9,
  feature_10,
  RAND() < 0.1 AS holdback -- Ten percent will be true.
FROM
  D

Бинарная логистическая регрессия

SELECT
  CASE
    WHEN label < 5 THEN 0
    WHEN label >= 5 THEN 1
  END
  AS label,
  * EXCEPT (label)
FROM
  `DATASET_NAME.BIN_LOG_REG_TRAINING_SET`

2. Обучение модели

Используйте обучающий набор.

Линейная регрессия

CREATE OR REPLACE MODEL `DATASET_NAME.LIN_REG_MODEL` OPTIONS (model_type="linear_reg") AS
  SELECT
    * except (holdback)
  FROM
    `DATASET_NAME.LIN_REG_TRAINING_SET`
  WHERE
    NOT holdback

Мы добавили в смоделированные данные достаточно шума, чтобы получить модель, в которой R2 = 0,9009.

Показатель Значение
Средняя абсолютная ошибка 0,7359
Среднеквадратическая ошибка 0,8432
Средняя квадратическая логарифмическая ошибка 0,0810
Медианная абсолютная ошибка 0,6239
R-квадрат 0,9009

Бинарная логистическая регрессия

CREATE OR REPLACE MODEL `DATASET_NAME.BIN_LOG_REG_MODEL` OPTIONS (model_type="logistic_reg") AS
  SELECT
    * EXCEPT (holdback)
  FROM
    `DATASET_NAME.BIN_LOG_REG_TRAINING_SET`
  WHERE
    NOT holdback

Пример результатов. Точность составляет 0,9260.

Показатель Значение
Позитивный класс 1
Негативный класс 0
Точность 0,0810
Полнота 0,9315
Точность 0,9260
F-мера 0,9328

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

Фактический ярлык Спрогнозированный ярлык 1 Спрогнозированный ярлык 2
1 93 % 7 %
0 8 % 92 %

3. Получение весовых значений и точек пересечения

Получите весовые значения и точки пересечения для модели.

Линейная регрессия

SELECT
  *
FROM
  ML.WEIGHTS(MODEL `DATASET_NAME.LIN_REG_MODEL`)
weight category_weights.category
feature_1 1,8263055528635743
feature_2 1,8143804404490813
feature_3 1,8601204874033492
feature_4 1,8507603439031859
feature_5 1,7899764387123640
feature_6 1,8645246630251291
feature_7 1,8698005281925356
feature_8 1,7904637080330201
feature_9 1,8036887855406274
feature_10 1,8117115890624449
INTERCEPT -4,1428754911504306

Бинарная логистическая регрессия

SELECT
  *
FROM
  ML.WEIGHTS(MODEL `DATASET_NAME.BIN_LOG_REG_MODEL`)
weight category_weights.category
feature_1 3,823533928
feature_2 3,734812819
feature_3 3,842239823
feature_4 3,785488823
feature_5 3,737386716
feature_6 3,567663961
feature_7 3,819643052
feature_8 3,734673763
feature_9 3,839301406
feature_10 3,787306994
INTERCEPT -17,922169920

4. Симуляция прогноза

Линейная регрессия

Чтобы создать прогноз, используя стандартный SQL без ML.PREDICT, возьмите скалярное произведение значений функций и весовых значений и добавьте точки пересечения. Приведенный здесь запрос сравнивает прогнозы, созданные подобным образом, и запросы с ML.PREDICT. Выделенные полужирным строки на SQL позволяют получить скалярное произведение значений функций для строки с весовыми значениями модели, а затем добавить точку пересечения.

WITH
T AS (
SELECT
  label AS actual_label,
  predicted_label AS ml_predicted_label,
  [feature_1,
  feature_2,
  feature_3,
  feature_4,
  feature_5,
  feature_6,
  feature_7,
  feature_8,
  feature_9,
  feature_10] AS features,
  [1.8263055528635743,
  1.8143804404490813,
  1.8601204874033492,
  1.8507603439031859,
  1.789976438712364,
  1.8645246630251291,
  1.8698005281925356,
  1.7904637080330201,
  1.8036887855406274,
  1.8117115890624449] AS weights
FROM
  ML.PREDICT(MODEL `DATASET_NAME.LIN_REG_MODEL`,
    (
    SELECT
      *
    FROM
      `PROJECT_NAME.DATASET_NAME.LIN_REG_TRAINING_SET`))
WHERE
  holdback),
P AS (
SELECT
  actual_label,
  ml_predicted_label,
  (
   SELECT
    SUM(element1 * element2) - 4.1428754911504306
  FROM
    T.features element1
  WITH
  OFFSET
    pos
  JOIN
    T.weights element2
  WITH
  OFFSET
    pos
  USING
    (pos) ) sql_predicted_label,
  features,
  weights
FROM
  T)
SELECT
  actual_label,
  ml_predicted_label,
  sql_predicted_label,
  ABS(ml_predicted_label - sql_predicted_label) < 0.00000000001 AS diff_is_negligible
FROM
  P

Бинарная логистическая регрессия

Моделирование прогнозов для бинарной логистической регрессии выполняется примерно так же, как для линейной. Но на последнем этапе применяется сигмоида с желаемым пороговым значением.

Чтобы создать прогноз, используя стандартный SQL без ML.PREDICT, возьмите скалярное произведение значений функций и весовых значений и добавьте точки пересечения. Затем спрогнозируйте 0 или 1 с помощью сигмоиды с пороговым значением 0,5. Приведенный здесь запрос сравнивает прогнозы, созданные подобным образом, и запросы с ML.PREDICT.

WITH
T AS (
SELECT
  label AS actual_label,
  predicted_label AS ml_predicted_label,
  [feature_1,
  feature_2,
  feature_3,
  feature_4,
  feature_5,
  feature_6,
  feature_7,
  feature_8,
  feature_9,
  feature_10] AS features,
  [3.8235339279050287,
  3.7348128191185244,
  3.8422398227859471,
  3.7854888232502479,
  3.7373867156553713,
  3.5676639605351026,
  3.8196430517007811,
  3.7346737628343032,
  3.8393014063170749,
  3.7873069939244743] AS weights
FROM
  ML.PREDICT(MODEL `DATASET_NAME.BIN_LOG_REG_MODEL`,
    (
    SELECT
      *
    FROM
      `PROJECT_NAME.DATASET_NAME.BIN_LOG_REG_TRAINING_SET`))
WHERE
  holdback),
P AS (
SELECT
  actual_label,
  ml_predicted_label,
  (
   SELECT
    IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)
  FROM
    T.features element1
  WITH
  OFFSET
    pos
  JOIN
    T.weights element2
  WITH
  OFFSET
    pos
  USING
    (pos) ) sql_predicted_label,
  features,
  weights
FROM
  T)
SELECT
  actual_label,
  ml_predicted_label,
  sql_predicted_label,
  ml_predicted_label = sql_predicted_label AS simulation_is_accurate
FROM
  P

Выделенный полужирным фрагмент SQL-кода позволяет получить скалярное произведение значений функций для строки с весовыми значениями модели, а затем добавить точку пересечения, чтобы спрогнозировать линейную регрессию.

IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)

После этого с помощью стандартного SQL к скалярному произведению и точке пересечения применяется сигмоида Y = 1 / (1+e^-z).

IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)

Наконец, результат сигмоиды сравнивается с пороговым значением 0,5. Если оно меньше 0,5, будет спрогнозирована бинарная логистическая регрессия 0, а если не меньше – 1. Можно задать любое пороговое значение в диапазоне от 0 до 1.

IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)

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

5. Сравнение результатов

Линейная регрессия

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

actual_label ml_predicted_label sql_predicted_label diff_is_negligible
6 5,2062349420751834 5,2062349420751826 true
0 0,40318472770048075 0,403184727700479 true
3 3,0703766078249597 3,0703766078249597 true
7 7,0588171538562 7,0588171538562 true
6 6,7802375930646 6,7802375930646 true
6 5,1088569571339368 5,1088569571339377 true
4 4,051839078116874 4,051839078116874 true
4 5,1810254680219243 5,1810254680219234 true
6 6,1440349466401223 6,1440349466401205 true
1 2,0842399472783519 2,0842399472783519 true
2 2,1911209811886847 2,1911209811886838 true
3 3,0236086790006622 3,0236086790006613 true
2 2,573083132964213 2,5730831329642125 true
7 5,68662973136732 5,6866297313673186 true
9 8,1860026312677938 8,1860026312677938 true

Бинарная логистическая регрессия

Сравнение смоделированного логического вывода и реальных результатов ML.PREDICT показывает, что в ограниченном наборе из 10 тыс. строк нет ни одного противоречия. Это отличный результат. В нескольких строках и ML.PREDICT, и моделирование расходятся с реальным ярлыком. Это ожидаемо поскольку точность модели составляет около 93 %, и во внедиагональных ячейках матрицы ошибок содержатся отличные от нуля значения, пусть и небольшие.

actual_label ml_predicted_label sql_predicted_label simulation_is_accurate
0 1 1 true
0 0 0 true
0 0 0 true
0 0 0 true
0 0 0 true
0 0 0 true
0 0 0 true
0 0 0 true
0 0 0 true
0 0 0 true
0 1 1 true
0 0 0 true

Создание списка активации аудитории с помощью машинного обучения

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

Ниже приводится запрос, позволяющий создать список аудитории, содержащий пользователей, которые согласно прогнозу совершат конверсию.

WITH
T AS (
SELECT
  *,
  label AS actual_label,
  [feature_1,
  feature_2,
  feature_3,
  feature_4,
  feature_5,
  feature_6,
  feature_7,
  feature_8,
  feature_9,
  feature_10] AS features,
  [3.8235339279050287,
  3.7348128191185244,
  3.8422398227859471,
  3.7854888232502479,
  3.7373867156553713,
  3.5676639605351026,
  3.8196430517007811,
  3.7346737628343032,
  3.8393014063170749,
  3.7873069939244743] AS weights
FROM
  `PROJECT_NAME.DATASET_NAME.BIN_LOG_REG_TRAINING_SET`
WHERE
  holdback),
P AS (
SELECT
  *,
  (
  SELECT
  IF
    ((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)
  FROM
    T.features element1
  WITH
  OFFSET
    pos
  JOIN
    T.weights element2
  WITH
  OFFSET
    pos
  USING
    (pos) ) predicted_label,
  features,
  weights
FROM
  T),
SELECT
  user_id
FROM
  P
WHERE
  predicted_label = 1;