hive/pigを使ったkdd'12 track2の広告クリック率予測

15
Hive/Pigを使ったKDD'12 track2 の広告クリック率予測 油井 [email protected] 産業技術総合研究所 情報技術研究部門 Twitter ID: @myui スライド http://www.slideshare.net/myui/dsirnlp-myuilt http://goo.gl/Ulf3A 1

Upload: makoto-yui

Post on 10-May-2015

2.534 views

Category:

Documents


2 download

DESCRIPTION

LT@DSIRNLP http://partake.in/events/9a6f86d3-5cd0-4c3b-8082-fd20ce332350

TRANSCRIPT

Page 1: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

Hive/Pigを使ったKDD'12 track2の広告クリック率予測

油井 誠 [email protected]

産業技術総合研究所 情報技術研究部門

Twitter ID: @myui

スライド http://www.slideshare.net/myui/dsirnlp-myuilt http://goo.gl/Ulf3A 1

Page 2: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

KDDcup 2012 track2

• 検索ログを基に、検索エンジンの広告のクリック率(Click-Through Rate)を推定するタスク

– 中国の3大検索エンジンの一つsoso.comの実データ

• 検索語などはHash値などを利用してすべて数値化されている

– Trainingデータ(約10GB+2.2GB, 15億レコード)

– Testデータ(約1.3GB, 2億レコード)

• 学習データの1.33割が評価用データセット

– CTRがsubmission format

• クラス分類というより回帰(もちろんクラス分類でも解ける)

2

Page 3: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

学習データのテーブル構成

UserID AdID QueryID Depth Position Impression Click

DisplayURL AdvertiserID KeywordID TitleID DescriptionID

AdID properties Training table

UserID Gender Age User table

QueryID Tokens

Query table

KeywordID Tokens TitleID Tokens DescriptionID Tokens

Keyword table Title table Description table

評価用のテーブルにはimpression、click以外の素性(feature) 基本的に、全部、質的変数 → 二値変数の素性に分解

Click = Positive Impression – Click = Negative CTR = Click / Impression

Label A B

1 1 9

-1 2 7

1 3 8

Label A:1 A:2 A:3 B:7 B:8 B:9

1 1 0 0 0 1 0

-1 0 1 0 0 0 1

1 0 0 1 1 0 0 3

Page 4: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

ロジスティック回帰での発生予測

• 発生確率を予測する手法

• 各変数の影響力の強さを計算(Train)

– 入力: Label, Array<feature>

– 出力: 素性ごとの重みのMap<feature, float>

– # of features = 54,686,452

• ただし、token tableは利用していない (Token ID = <token,..,token>)

• 影響力を基に生起確率を計算(Predict)

– P(X) = Pr(Y=1|x1,x2,..,xn)

– f: X → Yとなる関数fを導出したい s.t. empirical lossを最小化 • 勾配降下法を使う

𝑎𝑟𝑔𝑚𝑖𝑛1

𝑛 𝑙𝑜𝑠𝑠(𝑓(𝑥𝑖

𝑛

𝑖=0

; 𝑤), 𝑦𝑖)

各素性の重み 4

Page 6: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

𝑤𝑡+1 = 𝑤𝑡 − 𝛾𝑡1

𝑛 𝛻𝑙𝑜𝑠𝑠(𝑓(𝑥𝑖

𝑛

𝑖=0

; 𝑤𝑡), 𝑦)

勾配の並列計算

mappers

single reducer

勾配をmapperで並列に計算 重みの更新をreducerで行う

• 実際には重みの更新の時に更新されたfeature(xi)が必要 • wはMap<feature, weight>でMap.size()=54,686,452

• Iteration数が多く必要で、入出力がDFSを介すMapReduceに向かない

• Reducerでの計算がボトルネックになる 6

Page 7: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

確率的勾配降下法

• Gradient Descent

• Stochastic Gradient Descent (SGD)

– Iterative Parameter Mixで処理すれば、実際意外とうまく動くし、そんなにイテレーション数が必要でない • データ分割して、各mapperで並列に を計算

• モデルパラメタはイテレーション/epochごとに配る

𝑤𝑡+1 = 𝑤𝑡 − 𝛾𝑡1

𝑛 𝛻𝑙𝑜𝑠𝑠(𝑓(𝑥𝑖

𝑛

𝑖=0

; 𝑤𝑡), 𝑦)

モデルの更新に全てのトレーニングインスタンスが必要(バッチ学習)

𝑤𝑡+1 = 𝑤𝑡 − 𝛾𝑡𝛻𝑙𝑜𝑠𝑠(𝑓(𝑥;𝑤𝑡), 𝑦)

それぞれのトレーニングインスタンスで重みを更新(オンライン学習)

𝑤𝑡+1 = 𝑤𝑡 − 𝛾𝑡𝛻𝑙𝑜𝑠𝑠(𝑓(𝑥;𝑤𝑡), 𝑦)

7

Page 8: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

よくある機械学習のデータフロー

Label, array<feature>

Map <feature, weight>

Trainingデータ Modelデータ

array<feature>

Testデータ

train

predict

Label/Prob

8

Page 9: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

よくある並列trainのデータフロー

Label, array<feature>

Map <feature, weight>

Trainingデータ

map

map

map

map

Map <feature,weight>

reduce

map

Modelデータ

重みの平均をとる

𝑤𝑡+1 = 𝑤𝑡 − 𝛾𝑡𝛻𝑙𝑜𝑠𝑠(𝑓(𝑥;𝑤𝑡), 𝑦)

SGDで重みを計算

機械学習はaggregationの問題

直感的にはHive/PigのUDAF(user defined aggregation function)で実装すればよい ほんとはM/Rよりもparallel aggregationに特化したDremelに向いてる

イテレーションする場合は 古いmodelを渡す

9

Page 10: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

よくある並列trainのデータフロー

Label, array<feature>

Map <feature, weight>

Trainingデータ

map

map

map

map

Map <feature,weight>

reduce

map

Modelデータ

重みの平均をとる

𝑤𝑡+1 = 𝑤𝑡 − 𝛾𝑡𝛻𝑙𝑜𝑠𝑠(𝑓(𝑥;𝑤𝑡), 𝑦)

SGDで重みを計算

最初は素直にmapを返すUDAFで作った create table model as select trainLogisticUDAF(features,label [, params]) as weight from training

イテレーションする場合は 古いmodelを渡す

mapはsplitサイズの調整でメモリ内に収まるけど、より規模がでかくなると reduceでメモリ不足になるのでデータ量に対してスケールしない

10

Page 11: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

Think relational

Label, array<feature>

Map <feature, weight>

Trainingデータ Modelデータ

array<feature>

Testデータ

train

predict

Label/Prob Scaler値として返すのはダメ リレーションでfeature, weightを返そう でも、UDAFは使えない →そこでUDTF (User Defined Table Function)

11

Page 12: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

UDTF (parameter-mix)

select feature, CAST(avg(weight) as FLOAT) as weight from ( select TrainLogisticSgdUDTF(features,label,..) as (feature,weight) from train ) t group by feature;

どうやってiterative parameter mixさせよう???

古いmodelを渡さないといけない 毎行渡すのはあれだし…

12

HadoopのInputSplitSizeの設定に応じたmapperが 立ち上がる(map-only)

Page 13: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

UDTF(iterative parameter mix) create table model1sgditor2 as

select

feature,

CAST(avg(weight) as FLOAT) as weight

from (

select

TrainLogisticIterUDTF(t.features, w.wlist, t.label, ..) as (feature, weight)

from

training t join feature_weight w on (t.rowid = w.rowid)

) t

group by feature; ここで必要なのは、各行の素性ごとに古いModel

Map<feature, weight>, label相当を渡せばよいので、 Array<feature>に対応するArray<weight>をテーブルを作って inner joinで渡す

13

Page 14: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

Pig版のフローの一例 training_raw = load '$TARGET' as (clicks: int, impression: int, displayid: int, adid: int, advertiserid: int, depth: int, position: int, queryid: int, keywordid: int, titleid: int, descriptionid: int, userid: int, gender: int, age: int); training_bin = foreach training_raw generate flatten(predictor.ctr.BinSplit(clicks, impression)), displayid, adid, advertiserid, depth, position, queryid, keywordid, titleid, descriptionid, userid, gender, age; training_smp = sample training_bin 0.1; training_rnd = foreach training_smp generate (int)(RANDOM() * 100) as dataid, TOTUPLE(*) as training; training_dat = group training_rnd by dataid; model = foreach training_dat generate predictor.ctr.TrainLinear(training_rnd.training.training_smp); store model into '$MODEL'; model = load '$MODEL' as (mdl: map[]); model_lmt = limit model 10; testing_raw = load '$TARGET' as (dataid: int, displayid: int, adid: int, advertiserid: int, depth: int, position: int, queryid: int, keywordid: int, titleid: int, descriptionid: int, userid: int, gender: int, age: int); testing_with_model = cross model_lmt, testing_raw; result = foreach testing_with_model generate dataid, predictor.ctr.Pred(mdl, displayid, adid, advertiserid, depth, position, queryid, keywordid, titleid, descriptionid, userid, gender, age) as ctr; result_grp = group result by dataid; result_ens = foreach result_grp generate group as dataid, predictor.ctr.Ensemble(result.ctr); result_ens_ord = order result_ens by dataid; result_fin = foreach result_ens_ord generate $1; store result_fin into '$RESULT';

14

弱学習

アンサンブル学習

Page 15: Hive/Pigを使ったKDD'12 track2の広告クリック率予測

まとめ

• データ量に対してちゃんとスケールするものができた – インターン生にpig版を作ってもらった

• こちらはUTDFではやっていなくて、モデルファイルを分割して作って、アンサンブル学習させる戦略

– オンラインのモデル更新とかをやるには、updateのないhiveだとinsertにしないといけないので一工夫いる

– Passive-aggressive版も作る予定

• 現状、AUC=0.75程度(優勝者の台湾国立大は0.8) – a9aデータセットだとlibsvm, svm-light, liblinear, tinysvmなどと同程度の精度(0.85ぐらい)

• 余裕があったらHiveにパッチとして送る – でも、ドキュメントとかテストとかxxxxx

実データを持つ共同研究先募集 (一件、広告配信企業とやってる) 15