BQMLに新たに追加されたTRANSFORM句で、モデルの前処理を自動的に行う
これなに?
F81アドベントカレンダー二日目担当の長谷川です。
BQMLに新たに追加されたTRANSFORM
句についての解説します。2019/12/2時点で、まだ日本語の公式ドキュメントが存在しないことから、記事にしようと思いました。なお、現時点ではまだこの機能はBeta
です。英語の公式ドキュメントは存在するので、興味があれば、こちらも参考することをお勧めします。
今回の記事では、BigQuery(ML)の基本事項は一切説明しません。BQMLで使用できる関数などについては前記事を参照してください。
TRANSFORM句とは?
行いたい前処理をモデル構築時に定義し、予測、評価時に自動的に実行するためにしようするSQLの句(clause)です。
これにより、BQMLで作成するアルゴリズムとそれに伴う前処理を一体化させ、モデルを構築することができます。
前処理をモデルの中に集約し、隠蔽できるので、モデルを使う側は行われる前処理について何も知らなくても良くなります。
イメージはこんなかんじ
- 使わない場合
- 使う場合
具体例
今回は例として、bigquery-public-data.samples.natality
配下にある、新生児のデータを使用し、出産時の体重を目的変数とするモデルを構築してみたいと思います
SELECT
weight_pounds, -- 目的変数
is_male, --性別
plurality,--出産で生まれた子供の数
gestation_weeks, -- 妊娠期間
alcohol_use,-- 母親が飲酒してたか
cigarette_use -- 母親がタバコを吸っていたか
FROM
`bigquery-public-data.samples.natality`
LIMIT
5
weight_pounds | is_male | plurality | gestation_weeks | alcohol_use | cigarette_use | |
---|---|---|---|---|---|---|
0 | 7.625790 | True | NaN | 38 | None | None |
1 | 7.438397 | False | 1.0 | 38 | None | None |
2 | 8.437091 | False | 1.0 | 41 | None | None |
3 | 7.374463 | True | 1.0 | 99 | None | None |
4 | 5.813590 | False | 1.0 | 99 | None | None |
BQMLの場合、そのままデータを入力しても基本的な前処理は自動で行ってくれますが、自分で特徴量を作成したほうがより良い精度が期待できます。
そこで、以下のような特徴量を作成します。
- 多胎児で生まれたか否か
- 妊娠期間が(一般的な期間である)37-42週に当てはまっているかどうか
- (母親が)アルコールを摂取していたかと、タバコを吸っていたかの交差特徴量
SELECT
weight_pounds,
is_male,
IF(plurality > 1, 1, 0) AS plurality,
ML.BUCKETIZE(gestation_weeks, [37, 42]) AS gestation_weeks,
ML.FEATURE_CROSS(
STRUCT(
CAST(alcohol_use AS STRING) AS alcohol_use,
CAST(cigarette_use AS STRING) AS cigarette_use
)
) AS alcohol_cigarette_use
FROM
`bigquery-public-data.samples.natality`
LIMIT
5
weight_pounds | is_male | plurality | gestation_weeks | alcohol_cigarette_use | |
---|---|---|---|---|---|
0 | 6.311835 | False | 0 | bin_2 | {'alcohol_use_cigarette_use': 'true_true'} |
1 | 6.062712 | True | 0 | bin_2 | {'alcohol_use_cigarette_use': None} |
2 | 8.728101 | False | 0 | bin_2 | {'alcohol_use_cigarette_use': 'true_true'} |
3 | 6.946766 | True | 0 | bin_2 | {'alcohol_use_cigarette_use': 'true_true'} |
4 | 6.999677 | True | 0 | bin_2 | {'alcohol_use_cigarette_use': 'true_true'} |
上記の関数については、公式ドキュメントか、以前の記事を参照してください。
さて、問題はここからです。上記の処理をした上でモデルに食わせ、学習させる必要がありますが、そのままだと、評価、予測時に,もう一度同じ前処理を行った上でモデルに入力する必要があります。
これだと、二度同じ処理が発生するともに、うっかり学習時と違う処理をしてしまったりして、面倒なバグを生む温床になりかねません
学習(TRANSFORM句を使わない)
-- TRANSFORM句を使わない場合
CREATE MODEL `transform_tutorial.natality_model` OPTIONS (
model_type = 'linear_reg',
input_label_cols = ['weight_pounds']
) AS
SELECT
weight_pounds,
is_male,
IF(plurality > 1, 1, 0) AS plurality,
ML.BUCKETIZE(gestation_weeks, [37, 42]) AS gestation_weeks,
ML.FEATURE_CROSS(
STRUCT(
CAST(alcohol_use AS STRING) AS alcohol_use,
CAST(cigarette_use AS STRING) AS cigarette_use
)
) AS alcohol_cigarette_use
FROM
`bigquery-public-data.samples.natality`
WHERE
weight_pounds IS NOT NULL
AND RAND() < 0.001 -- 適当にサンプリング
予測
-- TRANSFORM句を使わない場合
SELECT
predicted_weight_pounds
FROM
ML.PREDICT(
MODEL `transform_tutorial.natality_model`,
(
SELECT
is_male,
-- イチイチ同じ前処理を実行しなければいけない
IF(plurality > 1, 1, 0) AS plurality,
ML.BUCKETIZE(gestation_weeks, [37, 42]) AS gestation_weeks,
ML.FEATURE_CROSS(
STRUCT(
CAST(alcohol_use AS STRING) AS alcohol_use,
CAST(cigarette_use AS STRING) AS cigarette_use
)
) AS alcohol_cigarette_use
FROM
`bigquery-public-data.samples.natality`
LIMIT
5
)
)
predicted_weight_pounds | |
---|---|
0 | 7.658442 |
1 | 7.385880 |
2 | 7.385880 |
3 | 7.385880 |
4 | 7.385880 |
同じ前処理を予測時にも行わければいけないため、メンドイですね。
TRANSFORMを使う
そこで、TRANSFORM
句の出番です。モデル学習時に、以下のように行う前処理の関数とともに定義します。
学習(TRANSFORM句を使用)
CREATE MODEL `transform_tutorial.natality_model_with_trans` TRANSFORM(
-- 前処理の関数を定義
weight_pounds,
is_male,
IF(plurality > 1, 1, 0) AS plurality,
ML.BUCKETIZE(gestation_weeks, [37, 42]) AS gestation_weeks,
ML.FEATURE_CROSS(
STRUCT(
CAST(alcohol_use AS STRING) AS alcohol_use,
CAST(cigarette_use AS STRING) AS cigarette_use
)
) AS alcohol_cigarette_use
) OPTIONS (
model_type = 'linear_reg',
input_label_cols = ['weight_pounds']
) AS
SELECT
*
FROM
`bigquery-public-data.samples.natality`
WHERE
weight_pounds IS NOT NULL -- 適当にサンプリング
AND RAND() < 0.001
予測
SELECT
predicted_weight_pounds
FROM
ML.PREDICT(
MODEL `transform_tutorial.natality_model_with_trans`,
(
SELECT *
FROM
`bigquery-public-data.samples.natality`
LIMIT
5
)
)
predicted_weight_pounds | |
---|---|
0 | 7.646798 |
1 | 7.376921 |
2 | 7.376921 |
3 | 7.715983 |
4 | 7.446106 |
TRANSFORM
句を使わない場合と比較すると、元のデータを読み込ませるだけで自動的に前処理が実行されるので、予測のクエリがだいぶ簡略化できますね。 また、モデルの評価のときも同様に前処理を省略できます。さらに、前処理について何も知らなくても、ただ生データを読み込ませるだけで良いので、モデルの使い勝手がいいです
最後に
BQMLはまだサービスを開始してから間もないですが、続々と新しいアルゴリズム、前処理用の関数などが出てきています。これからも新しい機能が発表されたらまたまとめてきたいです。
Author And Source
この問題について(BQMLに新たに追加されたTRANSFORM句で、モデルの前処理を自動的に行う), 我々は、より多くの情報をここで見つけました https://qiita.com/Hase8388/items/2b95533c491879f7719f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .