LoginSignup
57
39

More than 3 years have passed since last update.

BigQuery MLの使い方についてのまとめ

Last updated at Posted at 2019-07-24

これなに?

この記事はBQMLで利用できるアルゴリズム、モデルを作成する方法と、特徴量生成や評価値の確認などを行うための関数についてのまとめです
一応続き物ということになってますが、前回記事と前々回記事はデータセットの作成までしか行っていないので、BQMLの使い方自体については、この記事だけで完結してます

興味ある方は

をお読みいただけると嬉しいです

なお、すべての処理はjupyter上で行い、この記事自体もjupyterで書きました(jupyter上でbqを使用する方法については前々回記事参照)

from google.cloud.bigquery import magics
from google.oauth2 import service_account
credentials = (service_account.Credentials.from_service_account_file('[/path/to/key.json]'))
magics.context.credentials = credentials
%load_ext google.cloud.bigquery
PROJECT ='自身で作成したプロジェクトID'

BQMLの使いどころ

  • 大量のデータセットから、素早く学習、予測を行いたい場合
    • アルゴリズムによりますが数千万レコードのデータセットでも数分で学習が実行できます
  • 素早く機械学習システムをプロダクトに導入したい場合
    • 機械学習が実行でき、かつクエリを定期実行することも可能なので、極端に高い精度が求められなければ、低コストで機械学習システムを導入できます
  • とりあえず、機械学習を試してみたい場合
    • 上記に似てますが、SQLで完結するのと、パラメータのチューニングや必要最低限の前処理などはよしなにやってくれるので、あまり機械学習に触れたことがない人でも簡単に試せます

アルゴリズム一覧(2019/7月時点)

普通に使える

  • linear_reg
    • 線形回帰
  • logistic_reg
    • ロジスティック回帰
  • kmeans
    • k-平均法
    • 唯一の教師なしアルゴリズム

betaにだけある

  • tensorflow
    • cloud storage に保存してあるmodel fileを呼び出して実行

発表だけあった

  • matrix_factorization

    • 協調フィルタリング
    • 4月のNext19で発表
    • いまのところbetaにもなし
  • dnn_classifier

    • いわゆるDeep Learning
    • 4月のNext19で発表
    • いまのところbetaにもなし

使用するデータセット

前回の記事で作成したgoogle_analyticsのdatasetから、特定の商品をclickする確率を予測します
(下のはすでに加工済みのデータセットです)

%%bigquery --project $PROJECT 
SELECT * FROM `google_analytics.ga_dataset_feature` LIMIT 5
countryHour browserMobile priceBin isClick
0 {'country_hour': 'Peru_9'} {'browser_isMobile': 'Chrome_false'} bin_1 0
1 {'country_hour': 'Peru_9'} {'browser_isMobile': 'Chrome_false'} bin_1 0
2 {'country_hour': 'Peru_9'} {'browser_isMobile': 'Chrome_false'} bin_1 0
3 {'country_hour': 'Peru_9'} {'browser_isMobile': 'Chrome_false'} bin_1 0
4 {'country_hour': 'Peru_9'} {'browser_isMobile': 'Chrome_false'} bin_1 0

特徴量生成(ML.BUCKETIZEML.FEATURE_CROSS)

BQMLには、モデル作成以外にも特徴量生成のための関数も用意されてます。

  • ML.FEATURE_CROSS
    • 交差特徴量を生成します
  • ML.BUCKETIZE
    • 連続値を任意のしきい値で分けて、カテゴリにできます

具体的な使い方は前記事を参考にしてください

%%bigquery --project $PROJECT 
SELECT
    browser,
    isMobile,
    -- ブラウザとモバイルかどうかの交差特徴量
    ML.FEATURE_CROSS(
    STRUCT(
            browser,
            isMobile
    )) 
    AS browserMobile,
    productPrice,
    -- 商品の値段をbin化
    ML.BUCKETIZE(
    productPrice,
    [2, 5, 16, 17, 20, 50]
    ) AS priceBin
FROM  `google_analytics.ga_dataset_cleansed`  
browser isMobile browserMobile productPrice priceBin
0 Safari True {'browser_isMobile': 'Safari_true'} 37.99 bin_6
1 Chrome False {'browser_isMobile': 'Chrome_false'} 55.99 bin_7
2 Chrome False {'browser_isMobile': 'Chrome_false'} 20.99 bin_6
3 Chrome False {'browser_isMobile': 'Chrome_false'} 1.59 bin_1
4 Internet Explorer False {'browser_isMobile': 'Internet Explorer_false'} 11.99 bin_3

モデルの構築(CREATE MODEL)

モデルを構築してみます。作り方はCREATE TABLEによく似ています

今回は分類問題をときたいので、アルゴリズムはロジスティック回帰(logistic_reg)で行います

モデルに入力する特徴量が順序特徴量として使われるか、カテゴリ特徴量として使われるかはカラムで定義されている型によって決定し、INT64FLOAT64等の場合は数値として入力され、STRINGTIMESTAMP等の場合は、カテゴリ型として、自動でone-hot encodingされた後、モデルに入力されます

%%bigquery  --project $PROJECT 
CREATE OR REPLACE MODEL google_analytics.ga_model_log  
OPTIONS(
    INPUT_LABEL_COLS=['isClick'], 
    MODEL_TYPE='logistic_reg',
    -- 今回はclickしないレコード数が多い不均衡データのため、
    -- 重み値を頻度の逆数で重み付けする
    AUTO_CLASS_WEIGHTS=True,
    -- 下2つのパラメータはテスト用のデータを多くしたいがために設定。
    -- 何も指定しないと2割のデータが自動でテスト用に使用される
    DATA_SPLIT_METHOD='RANDOM',
    DATA_SPLIT_EVAL_FRACTION=0.4
    )
AS 
SELECT * FROM `google_analytics.ga_dataset_feature` 

INPUT_LABEL_COLSには正解ラベルとなるカラム名を、MODEL_TYPEには使用するアルゴリズムを入力します

その他のパラメータを指定しないと、l2正則化や学習率などのハイパーパラメータや、trainデータとセットtestデータセットの分割方法などは自動で行われますが、指定したい場合はオプションで設定できます(詳細はドキュメント参照)

ga_model_logという名前でモデルが生成されました。なお、モデルを修正したり消去したいときは、table作成と同じようにREPLACE MODELDROP MODELで行えます

トレーニング結果を確認(ML.TRAINING_INFO)

イテレーション毎に適用されたパラメータと評価値がわかります。(ただし、コンソール上から見たほうが見やすいです)

%%bigquery  --project $PROJECT 
SELECT * 
FROM 
ML.TRAINING_INFO(MODEL `google_analytics.ga_model_log`)
training_run iteration loss eval_loss duration_ms learning_rate
0 0 1 0.690266 0.690282 4934 0.4
1 0 0 0.692706 0.692721 3718 0.2

モデルの評価(ML.EVALUATEML.ROC_CURVEML.CONFUSION_MATRIX)

作成したモデルの性能を確認するための関数です。本来ならば、BQコンソール上からGUIで確認したほうがきれいに可視化されており、そちらで見たほうがわかりやすいのですが、今回jupyterで完結させるため、あえてクエリを実行して確認します

ML.EVALUATE

基本的なモデルの性能の評価値を確認します。どのアルゴリズム(ただしTensorFlowを除く)で作成したモデルでも実行可能です(アルゴリズムごとに項目は変わります)

%%bigquery  --project $PROJECT 
SELECT *
FROM ML.EVALUATE(MODEL google_analytics.ga_model_log)
precision recall accuracy f1_score log_loss roc_auc
0 0.03053 0.687421 0.531938 0.058464 0.690282 0.661142

ML.ROC_CURVE

その名の通り、ROCカーブを確認できます。二値分類のロジスティック回帰のみ実行可能です。可視化を行うため、返り値をpandas.DataFrameで受け取ります(受け取り方は、前々記事参照)

%%bigquery  roc --project $PROJECT 
SELECT *
FROM ML.ROC_CURVE(MODEL `google_analytics.ga_model_log` )
roc.head()
threshold recall false_positive_rate true_positives false_positives true_negatives false_negatives
0 0.780942 0.001271 0.000000 1 0 36441 786
1 0.594805 0.035578 0.009632 28 351 36090 759
2 0.565863 0.052097 0.019703 41 718 35723 746
3 0.552784 0.063532 0.029500 50 1075 35366 737
4 0.543293 0.076239 0.039598 60 1443 34998 727

このままではよくわからないので、matplotlibで可視化します

import matplotlib.pyplot as plt
roc.plot(x='false_positives', y='true_positives', label='ROC')
plt.show()

output_26_0.png

ML.CONFUSION_MATRIX

その名の通り、混同行列の形で評価値を確認します。(多分類含む)ロジスティック回帰のみ実行可能です

%%bigquery --project $PROJECT 
SELECT *
FROM ML.CONFUSION_MATRIX(MODEL `google_analytics.ga_model_log` )
expected_label _0 _1
0 0 19262 17179
1 1 246 541

構築したモデルで予測(ML.PREDICT)

構築したモデルで予測を行います

%%bigquery  --project $PROJECT 
SELECT 
    predicted_isClick_probs,
    predicted_isClick,
    isClick
FROM ML.PREDICT(
    MODEL `google_analytics.ga_model_log`,
    -- 予測を行うためのデータセットを読み込む(今回は学習に使ったものを流用)
    (
    SELECT *
    FROM `google_analytics.ga_dataset_feature` 
    -- 適当にサンプリング
    WHERE RAND() < 0.001
    LIMIT 5
    ),
    -- positiveと判定する閾値を0.55以上とする(デフォルト0.5)
    -- 二値分類のロジスティック回帰のみ適用可能
    STRUCT(0.55 AS threshold))
predicted_isClick_probs predicted_isClick isClick
0 [{'label': 1, 'prob': 0.6119019220195546}, {'l... 1 0
1 [{'label': 1, 'prob': 0.5540411720040493}, {'l... 1 0
2 [{'label': 1, 'prob': 0.5093257989158975}, {'l... 0 0
3 [{'label': 1, 'prob': 0.5032699831732143}, {'l... 0 0
4 [{'label': 1, 'prob': 0.4976015874326989}, {'l... 0 0

predicted_isClick_probsの中には以下のようなSTRUCTを持った配列が入っており、それぞれのラベルを取るときの予測値が入っています

今回は不均衡データを是正する関係で、予測値は普通の値よりも高く出ていることに注意してください

[{'label': 1, 'prob': 0.4582647505087995},
 {'label': 0, 'prob': 0.5417352494912004}]

モデルの重み値の確認(ML.WEIGHTS)

重み値の大きさを出力します

%%bigquery  --project $PROJECT 
WITH weights AS(
SELECT * 
FROM
ML.WEIGHTS(MODEL `google_analytics.ga_model_log`))

SELECT 
    category_weight.category,
    category_weight.weight
FROM weights, UNNEST(weights.category_weights) AS  category_weight LIMIT 5
category weight
0 Haiti_10 -0.149425
1 Georgia_9 -0.149508
2 Denmark_8 -0.151037
3 United States_10 0.031624
4 United States_1 -0.100186

モデルで使用したの特徴量の確認(ML.FEATURE_INFO)

使用した特徴量の統計的な情報を確認できます。イメージとしてはpandas.DataFrame.describe()のような感じです

%%bigquery  --project $PROJECT 
SELECT *
FROM ML.FEATURE_INFO(MODEL `google_analytics.ga_model_log`)
input min max mean median stddev category_count null_count
0 countryHour_country_hour None None None None None 229 0
1 browserMobile_browser_isMobile None None None None None 13 0
2 priceBin None None None None None 7 0

まとめ

BQMLで実行できるほぼすべての関数を実行してまとめました  
BQMLでは、SQLを土台としているため、学習コストが低いことと、本来やらなければ行けない前処理やパラメータの調整など、機械学習になれていない人が本来はまりそうな落とし穴を『よしなに』自動で行ってくれるおかげで、非常に扱いやすいと思いました

同時に、細かいパラメータの調整や、モデルや特徴量の概要について確認できる関数が用意されているおかげで、モデルをブラッシュアップしてある程度までは精度を向上させることができると思います

まだ、基本的なアルゴリズムしかありませんが、今後より増えていくことは確実なので、さまざまなプロダクトで使えるようになることを期待します

参考文献

57
39
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
39