Прогнозы с помощью существующей модели линейной или логистической регрессии (с известными весовыми значениями) можно создавать без ML.PREDICT
, даже если у вас нет доступа к самой модели. Для этого вам понадобится обходное решение, позволяющее использовать модели регрессии с дифференциальной приватностью в запросах активации аудиторий через Ads Data Hub.
В пошаговом примере ниже рассказывается, как выполнить симуляцию логического вывода для существующих моделей линейной и бинарной логистической регрессии, а затем сравнить результаты с результатами ML.PREDICT
, чтобы подтвердить точность симуляции.
Также здесь приводится пример того, как с помощью бинарной логистической модели создать список аудитории, который будет использоваться для применения модели конверсий к активации аудиторий.
Обзор примера
- Создание данных
- Обучение модели
- Получение весовых значений и точек пересечения
- Симуляция прогноза
- Сравнение результатов
Пошаговый пример
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;