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:
- Wygeneruj dane
- Wytrenuj model
- Odczytaj wagi i punkt przecięcia
- Przeprowadź symulację prognozy
- 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.
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. Wytrenuj model
Wytrenuj model regresji na treningowym zbiorze danych.
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 |
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:
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. Przeprowadź symulację prognozy
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
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
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 |
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;