모델 자체에 대한 액세스 권한이 없어도, ML.PREDICT를 사용하지 않고 알려진 가중치를 가진 기존 선형 혹은 로지스틱 회귀 모델을 사용하여 예측할 수 있습니다. 이렇게 하려면 Ads Data Hub의 잠재고객 활성화 쿼리 내에서 개인 정보 차등 보호(DP) 회귀 모델을 사용하는 해결 방법을 활용해야 합니다.
이 단계별 예에서는 실제 선형 및 바이너리 로지스틱 회귀 모델에 시뮬레이션된 추론을 실행한 다음 결과를 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 |
| F1 점수 | 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. 예측 시뮬레이션
선형 회귀
가중치가 있는 특성값의 내적을 사용하고 절편을 추가하여 ML.PREDICT를 사용하지 않고 표준 SQL을 사용하여 예측합니다. 이 쿼리는 이 기법을 사용하는 예측을 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
바이너리 로지스틱 회귀
바이너리 로지스틱 회귀의 경우 예측을 시뮬레이션하는 기법이 선형 회귀와 매우 유사하며 원하는 기준점으로 마지막 단계에서 시그모이드 함수를 적용합니다.
가중치가 있는 특성값의 내적을 사용하고 절편을 추가하여 ML.PREDICT를 사용하지 않고 표준 SQL을 사용하여 예측합니다.
그런 다음 결과에서 기준점이 0.5인 시그모이드 함수를 사용하여 0 또는 1을 예측합니다. 이 쿼리는 이 기법을 사용하는 예측을 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, 0.5 이상인 경우 1인 바이너리 로지스틱 회귀 예측에 도달합니다. 0과 1 사이의 기준점 값을 사용할 수 있습니다.
IF((1 / (1 + EXP(-(SUM(element1 * element2) -17.922169920432161)))) < 0.5, 0, 1)
이 기법은 멀티클래스 로지스틱 회귀로도 확장할 수 있습니다. 이 경우 모델의 가중치는 벡터가 아니라 nxn 행렬이고 가중치는 스칼라가 아니라 벡터입니다. 특성값 벡터에 가중치 행렬을 곱하고 절편 벡터를 추가합니다. 결과 벡터에는 각 라벨에 대한 점수가 있으며 예측을 위해 점수가 가장 높은 라벨을 선택할 수 있습니다. 확률 배열을 반환하려면 배열의 각 요소에 시그모이드 함수를 적용합니다.
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,000개의 행 홀드백 세트에서 하나도 상충하지 않습니다. ML.PREDICT와 시뮬레이션된 추론이 모두 실제 라벨과 일치하지 않는 행이 몇 개 있습니다. 이는 모델 정확성이 약 93%이고 혼동 행렬의 대각선 셀에 작지만 0이 아닌 값이 있기 때문에 예상되는 결과입니다.
| 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 |
ML을 사용하여 잠재고객 활성화 목록 만들기
일반적인 사용 사례는 개인 정보 차등 보호 바이너리 로지스틱 회귀 모델을 만들어 전환을 예측한 다음 잠재고객 목록을 만드는 동안 이 모델에 추론을 적용하는 것입니다. 위의 예에서 만든 바이너리 로지스틱 모델이 전환을 모델링하며 학습 및 평가 세트의 각 행이 고유한 사용자를 나타낸다고 가정해 보겠습니다.
다음 쿼리는 모델이 전환할 것으로 예측한 사용자로 잠재고객 목록을 만드는 방법을 보여줍니다.
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;