이 글은 https://cloud.google.com/bigquery/docs/create-machine-learning-model?hl=ko 의 내용을 수행한 기록입니다.
다수의 기업에서 GCP의 BigQuery를 데이터 웨어하우스 혹은 데이터 레이크로 채택하여 사용하고 있다.
ML 프로젝트에선 이 데이터를 이용해서 모델을 학습하고 배포한다. 여기서 어디서 학습을 진행하느냐에 따라 데이터 전송 비용이 발생한다.
데이터 전송을 어떻게 하느냐에 따라 크고 작은 비용이 발생한다. 학습 시 추가로 필요한 증분 데이터만을 전달하는 게 좋겠지만 매 학습 때 마다 필요한 데이터를 전부 전송하기도 한다.
빅쿼리 ML은 사용자가 직접 SQL 쿼리를 통해 머신러닝 모델을 생성, 학습, 평가할 수 있는 서비스이다.
이제 튜토리얼을 수행해보자.
1. 데이터 불러오기
학습을 위한 데이터로 BigQuery용 Google 애널리틱스 샘플 데이터 세트를 사용한다. 이는 특정 사이트를 방문한 사용자가 구매를 했는지 아닌지에 대한 데이터이다.
- 라벨 피쳐: totals.transactions
- 학습 피쳐:
- device.operatingSystem
- device.isMobile
- geoNetwork.country
- totals.pageviews
사용자의 구매 여부를 예측하기 위한 피쳐로 위와같은 4개 피쳐를 튜토리얼에선 선택했다.
데이터를 한번 확인해보자.
쿼리를 통해 아래 스크린샷과 같은 데이터가 있음을 확인했다.
SELECT * FROM `bigquery-public-data.google_analytics_sample.ga_sessions_20170101`
우리가 사용할 데이터는 빅쿼리에 공개된 데이터로 아래 위치에 있다.
- 프로젝트: bigquery-public-data
- 데이터세트: google_analytics_sample
- 테이블: ga_sessions_* (날짜로 샤딩된 테이블)
2. 모델 학습하기
모델을 학습하기 위해 필요한 명령어는 유추할 수 있듯이 다음과 같다.
- 어디서 데이터를 가져올 것인가?
- (Optional) 피쳐들에 대한 전처리는 어떻게 할 것인가?
- 어떤 모델을 선택할 것인가?
- 모델의 이름은 뭘로 지을건가?
간단하지만 하나씩 살펴보자.
1. 어디서 데이터를 가져올 것인가?
앞서 데이터 불러오기에서 아래 위치의 테이블 데이터를 사용할 것이라고 했었다.
- 프로젝트: bigquery-public-data
- 데이터세트: google_analytics_sample
- 테이블: ga_sessions_* (날짜로 샤딩된 테이블)
우리는 여기서 2016년 08월 01일 데이터부터 2017년 6월 30일까지 약 10개월치 데이터를 사용할 것이다.
SELECT
*
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20160801' AND '20170630'
날짜로 샤딩된 테이블에서 _TABLE_SUFFIX
를 WHERE 절에 사용해서 필요한 데이터를 불러올 수 있다.
확인해보니 총 829,285개의 데이터이다.
2. (Optional) 피쳐들에 대한 전처리는 어떻게 할 것인가?
Optional이라고 표기한 건 전처리된 테이블로부터 학습을 수행할 수도 있고 EDA를 통해 결정되어야 할 사항이라 생각되어 그렇게 작성했다.
튜토리얼에선 피쳐들에 대한 fill na 처리만을 수행했다.
또한 중요하게 기억해야 하는 게 BigQueryML에서 타겟 피쳐를 명시하기 위해 "label"이라고 명시해야 한다.
SELECT
IF(totals.transactions IS NULL, 0, 1) AS label,
IFNULL(device.operatingSystem, "") AS os,
device.isMobile AS is_mobile,
IFNULL(geoNetwork.country, "") AS country,
IFNULL(totals.pageviews, 0) AS pageviews
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20160801' AND '20170630'
아래와 같이 전처리된 데이터를 확인할 수 있다.
행 | label | os | is_mobile | country | pageviews | |
---|---|---|---|---|---|---|
1 | 0 | Samsung | true | Sudan | 3 | |
2 | 0 | Windows Phone | true | United States | 3 | |
3 | 0 | Xbox | false | Kuwait | 5 | |
4 | 0 | Windows Phone | true | India | 1 | |
5 | 0 | Windows Phone | true | Malaysia | 1 | |
6 | 0 | Samsung | true | India | 1 | |
7 | 0 | Windows Phone | true | Netherlands | 1 | |
8 | 0 | Samsung | true | India | 1 | |
9 | 0 | Windows Phone | true | India | 1 | |
10 | 0 | Windows Phone | true | Pakistan | 4 | |
11 | 0 | Windows Phone | true | Vietnam | 2 | |
12 | 0 | Samsung | true | Pakistan | 2 | |
13 | 0 | Windows Phone | true | Vietnam | 3 | |
14 | 0 | Windows Phone | true | Belgium | 1 | |
15 | 0 | BlackBerry | true | Australia | 1 | |
16 | 0 | Windows Phone | true | India | 1 | |
17 | 0 | Windows Phone | true | Greece | 1 | |
18 | 0 | Samsung | true | India | 1 | |
19 | 0 | FreeBSD | false | Norway | 4 | |
20 | 0 | Windows Phone | true | Bangladesh | 8 | |
21 | 0 | Windows Phone | true | Vietnam | 1 |
3. 어떤 모델을 선택할 것인가?
앞선 전처리에서 확인했듯이 우리의 label 데이터는 트랜잭션 여부에 따라 0 혹은 1을 갖는다.
BigQueryML에서 사용할 수 있는 모델 리스트는 다음과 같다.
MODEL_TYPE = { 'LINEAR_REG' | 'LOGISTIC_REG' | 'KMEANS' | 'PCA' |'MATRIX_FACTORIZATION' | 'AUTOENCODER' | 'AUTOML_REGRESSOR' |'AUTOML_CLASSIFIER' | 'BOOSTED_TREE_CLASSIFIER' | 'BOOSTED_TREE_REGRESSOR' |'RANDOM_FOREST_CLASSIFIER' | 'RANDOM_FOREST_REGRESSOR' |'DNN_CLASSIFIER' | 'DNN_REGRESSOR' | 'DNN_LINEAR_COMBINED_CLASSIFIER' |'DNN_LINEAR_COMBINED_REGRESSOR' | 'ARIMA_PLUS' | 'ARIMA_PLUS_XREG' |'TENSORFLOW' | 'TENSORFLOW_LITE' | 'ONNX' | 'XGBOOST'}
우리는 여기서 Logistics Regression 모델을 사용할 것이다. 이는 모델이 확률을 반환할 것임을 알 수 있다.
4. 모델의 이름은 뭘로 지을건가?
BigQueryML을 학습한 뒤 모델은 데이터세트 내에 저장된다.
따라서 . 과 같이 지정해야 한다.
튜토리얼에 따라 bqml_tutorial
라는 이름의 데이터세트를 만들었고 모델 이름은 sample_model
로 설정한 뒤 쿼리를 완성하면 다음과 같다.
CREATE MODEL
`bqml_tutorial.sample_model`
OPTIONS(model_type='logistic_reg')
AS
SELECT
IF(totals.transactions IS NULL, 0, 1) AS label,
IFNULL(device.operatingSystem, "") AS os,
device.isMobile AS is_mobile,
IFNULL(geoNetwork.country, "") AS country,
IFNULL(totals.pageviews, 0) AS pageviews
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20160801' AND '20170630'
쿼리를 수행하면 아래 스크린샷과 같은 메트릭을 확인할 수 있다.
또한, 지정했던 데이터세트 아래에 sample_model을 확인하면 더 많은 정보를 확인할 수 있다.
3. 모델 평가하기
이제 학습된 모델을 평가해보자.
당연히 학습할 때 사용하지 않은 데이터로 평가해야 한다.
SELECT
*
FROM
ML.EVALUATE
(
MODEL `bqml_tutorial.sample_model`,
(
SELECT
IF(totals.transactions IS NULL, 0, 1) AS label,
IFNULL(device.operatingSystem, "") AS os,
device.isMobile AS is_mobile,
IFNULL(geoNetwork.country, "") AS country,
IFNULL(totals.pageviews, 0) AS pageviews
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20170701'AND '20170801'
)
)
아래 결과를 확인할 수 있다.
행 | precision | recall | accuracy | f1_score | log_loss | roc_auc | |
---|---|---|---|---|---|---|---|
1 | 0.468503937007874 | 0.11080074487895716 | 0.98534315834767638 | 0.17921686746987953 | 0.046242211011767891 | 0.98174425574425 |
4. 모델로 예측하기
모델 학습에 사용했던 feature는 아래 4가지이다.
- os
- is_mobile
- country
- pageviews
위 피쳐들을 모델에 입력하면 label 결과가 나오는 지 확인해보자.
여기서 ML.PREDICT 명령어를 이용한다.
아래 쿼리를 통해 확인해보자.
SELECT
predicted_label
FROM
ML.PREDICT(MODEL `bqml_tutorial.sample_model`, (
SELECT
"Samsung" AS os,
true AS is_mobile,
300 AS pageviews,
"Korea" AS country
))
이는 아래와 같이 1을 반환했다.
행 | predicted_label | |
---|---|---|
1 | 1 |
마무리
BigQueryML은 빅쿼리 데이터를 기반으로 직관적이고 손쉽게 모델을 학습 할 수 있게 도와준다.
학습이 잘 되었다면 모델을 배포해야 하는데, 배치 서빙의 경우 ML_PREDICT를 통해 충분히 수행 가능할 것이라 생각된다.
언급하지 않았지만 빅쿼리내 연산은 슬롯이라는 컴퓨팅 단위로 수행된다. 이는 부하가 많은 온라인 서빙의 경우 적합하지 않을 수 있다.
빅쿼리ML에선 학습된 모델을 Export 할 수 있게 지원하며 이는 다양한 플랫폼에서 모델을 배포할 수 있게 한다.
https://cloud.google.com/bigquery/docs/export-model-tutorial?hl=ko 이 가이드 같이 Tensorflow Serving을 이용해 Vertex AI를 통해 배포할 수도 있다.
잘 활용하면 복잡한 ML 인프라 구성이나 관리 없이도 학습 파이프라인 구성이 가능할 것이라 생각된다.