Vous pouvez effectuer des prédictions à l'aide d'un modèle de régression linéaire ou logistique existant, avec des pondérations connues et sans utiliser ML.PREDICT
, même sans accéder au modèle lui-même. Pour ce faire, vous devez utiliser une solution de contournement permettant d'utiliser des modèles de régression à confidentialité différentielle dans les requêtes d'activation d'audience d'Ads Data Hub.
Cet exemple détaillé va vous apprendre à simuler l'inférence pour des modèles de régression logistique binaire et linéaire réels, puis à comparer les résultats avec ceux de ML.PREDICT
pour déterminer la justesse.
Vous verrez également comment créer une liste d'audience à l'aide d'un modèle logistique binaire visant à appliquer un modèle de conversion à l'activation d'audience.
Présentation de l'exemple :
- Générer des données
- Entraîner le modèle
- Obtenir les pondérations et l'interception
- Simuler la prédiction
- Comparer les résultats
Exemple détaillé
1. Générer des données
Créez une table avec des données simulées pour entraîner le modèle. Marquez une fraction des lignes pour l'ensemble réservé.
Régression linéaire
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
Régression logistique binaire
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. Entraîner le modèle
Entraînez un modèle de régression à partir de l'ensemble d'entraînement.
Régression linéaire
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
Notez que nous avons ajouté suffisamment de bruit aux données simulées pour obtenir un modèle avec R2 = 0,9009.
Mesure | Valeur |
---|---|
Erreur absolue moyenne | 0,7359 |
Erreur quadratique moyenne | 0,8432 |
Erreur logarithmique quadratique moyenne | 0,0810 |
Erreur absolue médiane | 0,6239 |
Coefficient de détermination (r-carré) | 0,9009 |
Régression logistique binaire
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
Échantillonnez les résultats. Notez la justesse de 0,9260.
Mesure | Valeur |
---|---|
Classe positive | 1 |
Classe négative | 0 |
Précision | 0,0810 |
Rappel | 0,9315 |
Justesse | 0,9260 |
Score F1 | 0,9328 |
Les valeurs en gras de cette matrice de confusion indiquent à quelle fréquence le modèle a classé chaque étiquette correctement. Les valeurs qui ne sont pas en gras indiquent à quelle fréquence le modèle a mal classé chaque étiquette.
Étiquette réelle | Étiquette prédite 1 | Étiquette prédite 2 |
---|---|---|
1 | 93 % | 7 % |
0 | 8 % | 92 % |
3. Obtenir les pondérations et l'interception
Obtenez les pondérations et l'interception pour le modèle :
Régression linéaire
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 |
Régression logistique binaire
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. Simuler la prédiction
Régression linéaire
Utilisez le produit scalaire des valeurs de caractéristiques avec les pondérations, puis ajoutez l'interception pour effectuer la prédiction en SQL standard sans utiliser ML.PREDICT
. Cette requête compare les prédictions utilisant cette technique à celles utilisant ML.PREDICT
. Notez que les lignes SQL en gras correspondent au produit scalaire des valeurs de caractéristiques pour la ligne avec les pondérations du modèle, ajouté à l'interception.
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
Régression logistique binaire
Pour la régression logistique binaire, la technique de simulation des prédictions est très semblable à la régression linéaire. La différence est que la fonction sigmoïde est ajoutée à la dernière étape avec le seuil souhaité.
Utilisez le produit scalaire des valeurs de caractéristiques avec les pondérations, puis ajoutez l'interception pour effectuer la prédiction en SQL standard sans utiliser ML.PREDICT
.
Appliquez ensuite la fonction sigmoïde avec un seuil de 0,5 sur le résultat pour prédire 0 ou 1. Cette requête compare les prédictions utilisant cette technique à celles utilisant 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
Le bloc de code SQL en gras dans la requête ci-dessus effectue le produit scalaire des valeurs de caractéristiques pour chaque ligne avec les pondérations du modèle et ajoute l'interception pour obtenir la prédiction de la régression linéaire :
IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)
La fonction sigmoïde Y = 1 / (1+e^-z)
est ensuite appliquée au produit scalaire et à l'interception en utilisant le langage SQL standard :
IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)
Enfin, le résultat de la fonction sigmoïde est comparé à la valeur de seuil de 0,5 pour obtenir une prédiction de régression logistique binaire égale à 0 si le résultat est inférieur à 0,5 ou égale à 1 dans le cas contraire. Notez que vous pouvez utiliser n'importe quelle valeur de seuil comprise entre 0 et 1.
IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)
Cette technique peut également être étendue à la régression logistique multiclasse. Dans ce cas, les pondérations du modèle seraient une matrice nxn plutôt qu'un vecteur, et les pondérations seraient un vecteur plutôt qu'un scalaire. Vous multiplieriez le vecteur des valeurs de caractéristiques par la matrice des pondérations, et vous ajouteriez le vecteur d'interception. Le vecteur résultant aurait un score pour chaque étiquette, et vous pourriez choisir l'étiquette avec le score le plus élevé pour votre prédiction. Pour renvoyer un tableau de probabilités, vous appliqueriez la fonction sigmoïde à chaque élément du tableau.
5. Comparer les résultats
Régression linéaire
Les résultats des échantillons sont presque identiques, à l'exception d'une petite erreur d'arrondi :
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 |
Régression logistique binaire
La comparaison de l'inférence simulée avec les résultats réels de ML.PREDICT
est parfaite : pas une seule contradiction dans l'ensemble réservé de 10 000 lignes. Il existe quelques lignes où ML.PREDICT
et l'inférence simulée sont en désaccord avec l'étiquette réelle, ce qui est attendu, car la justesse du modèle est d'environ 93 %, et il existe des valeurs petites, mais non nulles, dans les cellules hors diagonale de la matrice de confusion.
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 |
Créer une liste d'activation d'audience avec le ML
Un cas d'utilisation typique consisterait à créer un modèle de régression logistique binaire à confidentialité différentielle pour prédire les conversions, puis à appliquer l'inférence sur ce modèle lors de la création d'une liste d'audience. Supposons que le modèle logistique binaire créé dans l'exemple ci-dessus modélise des conversions, et que chaque ligne des ensembles d'entraînement et d'évaluation représente un utilisateur distinct.
La requête suivante montre comment créer une liste d'audience avec les utilisateurs qui, selon la prédiction du modèle, effectueront une conversion :
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;