Modelowanie regresji w przypadku list odbiorców

Prognozy możesz formułować za pomocą obecnego modelu regresji liniowej lub logistycznej ze znanymi wagami bez użycia funkcji ML.PREDICT nawet wtedy, gdy nie masz dostępu do samego modelu. Aby to robić, musisz skorzystać z obejścia pozwalającego na stosowanie w zapytaniach dotyczących aktywacji odbiorców w Centrum danych reklam modeli regresji zgodnych z wymaganiami prywatności różnicowej.

Ten szczegółowy przykład pokazuje, jak przeprowadzić symulowane wnioskowanie w przypadku rzeczywistych modeli regresji liniowej i binarnej regresji logistycznej, a następnie porównać uzyskane wyniki z wynikami podawanymi przez funkcję ML.PREDICT, aby sprawdzić poprawność symulowanych wyników. Zademonstrujemy też praktyczny przykład tworzenia listy odbiorców za pomocą modelu binarnej regresji logistycznej, którego można używać do stosowania modelu konwersji na potrzeby aktywacji odbiorców.

Omówienie przykładu:

  1. Wygeneruj dane
  2. Wytrenuj model
  3. Odczytaj wagi i punkt przecięcia
  4. Przeprowadź symulację prognozy
  5. Porównaj wyniki

Przykład szczegółowy

1. Wygeneruj dane

Utwórz tabelę z symulowanymi danymi na potrzeby trenowania modelu. Oznacz część wierszy jako należącą do odizolowanego zbioru danych.

Regresja liniowa

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

Binarna regresja logistyczna

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. Wytrenuj model

Wytrenuj model regresji na treningowym zbiorze danych.

Regresja liniowa

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

Pamiętaj, że do symulowanych danych dodaliśmy wystarczającą ilość szumu, aby uzyskać model z wartością R2 = 0,9009.

Pomiar Wartość
Średni błąd bezwzględny 0,7359
Błąd średniokwadratowy 0,8432
Logarytmiczny błąd średniokwadratowy 0,0810
Medianowy błąd bezwzględny 0,6239
R-kwadrat 0,9009

Binarna regresja logistyczna

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

Przykładowe wyniki. Zwróć uwagę na dokładność 0,9260.

Pomiar Wartość
Klasa wyników pozytywnych 1
Klasa wyników negatywnych 0
Precyzja 0,0810
Czułość 0,9315
Dokładność 0,9260
Wynik F1 0,9328

Wartości pogrubione w tej tablicy pomyłek pokazują, jak często model prawidłowo klasyfikował poszczególne etykiety. Wartości bez pogrubienia pokazują, jak często model błędnie klasyfikował poszczególne etykiety.

Etykieta z wartością „Prawda” Prognozowana etykieta 1 Prognozowana etykieta 2
1 93% 7%
0 8% 92%

3. Odczytaj wagi i punkt przecięcia

Odczytaj w przypadku modelu wagi i punkt przecięcia:

Regresja liniowa

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

Binarna regresja logistyczna

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. Przeprowadź symulację prognozy

Regresja liniowa

Użyj iloczynu skalarnego wartości cech razem z wagami i dodaj punkt przecięcia, aby sformułować prognozę za pomocą standardowego kodu SQL bez zastosowania funkcji ML.PREDICT. To zapytanie porównuje prognozy korzystające z tej metody z tymi, które używają funkcji ML.PREDICT. Zwróć uwagę, że pogrubione wiersze kodu SQL wykonują iloczyn skalarny wartości cech w wierszu z wagami modelu, a potem dodają punkt przecięcia.

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

Binarna regresja logistyczna

W przypadku binarnej regresji logistycznej metoda symulowania prognoz jest bardzo podobna do regresji liniowej, ale z dodatkowym zastosowaniem w ostatnim kroku funkcji sigmoidalnej z odpowiednią wartością progową.

Użyj iloczynu skalarnego wartości cech razem z wagami i dodaj punkt przecięcia, aby sformułować prognozę za pomocą standardowego kodu SQL bez korzystania z funkcji ML.PREDICT. Następnie zastosuj do wyniku funkcję sigmoidalną z wartością progową równą 0,5, aby otrzymać prognozowany wynik 0 lub 1. To zapytanie porównuje prognozy korzystające z tej metody z tymi, które używają funkcji 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

Blok kodu SQL pogrubiony w zapytaniu powyżej wykonuje iloczyn skalarny wartości cech w przypadku każdego wiersza z wagami modelu i dodaje punkt przecięcia, aby uzyskać prognozę na podstawie regresji liniowej:

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

Następnie stosuje do iloczynu skalarnego i punktu przecięcia funkcję sigmoidalną Y = 1 / (1+e^-z), korzystając ze standardowego kodu SQL:

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

Na koniec funkcja sigmoidalna jest porównywana z wartością progową 0,5, aby uzyskać prognozę na podstawie regresji liniowej wynoszącą 0, jeśli wynik jest mniejszy niż 0,5, lub 1, jeśli jest on większy od 0,5. Pamiętaj, że możesz użyć dowolnej wartości progowej z przedziału od 0 do 1.

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

Tę metodę można też stosować do wieloklasowej regresji logistycznej. W jej przypadku wagi modelu będą miały postać tablicy nxn, a nie wektora, a wagi będą wektorem, a nie skalarem. Musisz pomnożyć wektor wartości cech przez tablicę wag i dodać wektor punktu przecięcia. Otrzymany wektor będzie miał osobny wynik dla każdej etykiety. Do swojej prognozy możesz wybrać etykietę o najwyższym wyniku. Aby w razie potrzeby zwrócić tablicę prawdopodobieństwa, zastosuj do każdego elementu tablicy funkcję sigmoidalną.

5. Porównaj wyniki

Regresja liniowa

Przykładowe wyniki są niemal identyczne z wyjątkiem niewielkiego błędu wynikającego z zaokrągleń.

actual_label ml_predicted_label sql_predicted_label diff_is_negligible
6 5.2062349420751834 5.2062349420751826 prawda
0 0.40318472770048075 0.403184727700479 prawda
3 3.0703766078249597 3.0703766078249597 prawda
7 7.0588171538562 7.0588171538562 prawda
6 6.7802375930646 6.7802375930646 prawda
6 5.1088569571339368 5.1088569571339377 prawda
4 4.051839078116874 4.051839078116874 prawda
4 5.1810254680219243 5.1810254680219234 prawda
6 6.1440349466401223 6.1440349466401205 prawda
1 2.0842399472783519 2.0842399472783519 prawda
2 2.1911209811886847 2.1911209811886838 prawda
3 3.0236086790006622 3.0236086790006613 prawda
2 2.573083132964213 2.5730831329642125 prawda
7 5.68662973136732 5.6866297313673186 prawda
9 8.1860026312677938 8.1860026312677938 prawda

Binarna regresja logistyczna

Porównanie efektów symulowanego wnioskowania z rzeczywistymi wynikami działania funkcji ML.PREDICT wypada idealnie – żadnej sprzeczności w odizolowanym zbiorze danych o 10 tys. wierszy. W niektórych wierszach ani funkcja ML.PREDICT, ani symulowane wnioskowanie nie wskazuje rzeczywistej etykiety. Można się było tego spodziewać, ponieważ dokładność modelu wynosi około 93%, a w komórkach tablicy pomyłek leżących poza przekątną występują wprawdzie niewielkie, ale niezerowe wartości.

actual_label ml_predicted_label sql_predicted_label simulation_is_accurate
0 1 1 prawda
0 0 0 prawda
0 0 0 prawda
0 0 0 prawda
0 0 0 prawda
0 0 0 prawda
0 0 0 prawda
0 0 0 prawda
0 0 0 prawda
0 0 0 prawda
0 1 1 prawda
0 0 0 prawda

Tworzenie listy aktywacji odbiorców za pomocą systemów uczących się

Typowym zastosowaniem byłoby utworzenie modelu binarnej regresji logistycznej zgodnego z wymaganiami prywatności różnicowej w celu prognozowania konwersji, a potem użycie wyniku wnioskowania przeprowadzonego przez ten model podczas tworzenia listy odbiorców. Załóżmy, że model binarnej regresji logistycznej utworzony w przykładzie powyżej modeluje konwersje oraz że każdy wiersz w zbiorze treningowym i weryfikacyjnym to oddzielny użytkownik.

Za pomocą podanego niżej zapytania dowiesz się, jak utworzyć listę odbiorców zawierającą użytkowników, którzy według przewidywań modelu dokonają konwersji:

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;