特徴ベクトル変換器を作った話

25
特徴ベクトル変換器を作った話 @tokoroten

Upload: shinta-nakayama

Post on 19-Jul-2015

4.373 views

Category:

Technology


4 download

TRANSCRIPT

特徴ベクトル変換器を作った話

@tokoroten

データ分析の流れ

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習結果学習精度

教師データ

テストデータ

前処理

マエショリスト

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習結果学習精度

教師データ

テストデータ

前処理

前処理は、データ分析においてすごく大事データ分析の仕事の多くが前処理だったりするそこから先は既存フレームワークで自動化可能

Jubatusのfv_converterはすごくよく出来てた……

前処理のニーズ• 特徴量チューニングがしたい

– 特徴量を手動チューニングするだけで、機械学習の精度が大きく改善する

• 特徴量チューニングでよくやること– 利用する変数の取捨選択、欠損値の対応– 変数のクリップ(最大値、最小値)– 変数のログスケール変換(負の値の対応)– 変数を演算して、線形分離しやすい新しい変数を作る

• 足し算、引き算、割り算、正規化、分散

– bool値を0,1に変換、特定のラベルを0,1に変換

• 実例– アクセス時刻と、イベント発生時刻をunixタイムに直して差分をとって、発生までの秒数にして、それをイベント発生回数で割り算して正規化して、それをログスケールに変換して……

データ分析のよくあるソース管理

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習結果学習精度

教師データ

テストデータ

前処理

一つのソースで一気通貫で処理

データソースごとに別の前処理を行うことが難しい実験や特別対応の試行錯誤結果が、レポジトリに残らない「この学習結果って、どんな設定で出したんだっけ?」

前処理分離モデル

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習結果学習精度

教師データ

テストデータ

前処理と機械学習を切り離す

前処理

設定ファイル

前処理を設定ファイルに切り出すことで、データソースごとの個別対応が可能になる設定ファイルをレポジトリにコミットすることで、再現性が生まれる

勝ったッ!第3部完!

• 前処理を分離して設定ファイルに切り出す

– 特徴量チューニングでソースコードが汚れない

– クライアントごとに別のファイルになるので、レポジトリで管理可能になる

– 特徴量チューニングの試行錯誤がやりやすくなる

• ここからが本当の地獄だ

– データ分析で閉じた世界なら問題ないが、本番システムが絡むと厄介な問題になる

データ分析の本番適用(オフライン)

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

分類結果

データ分析の世界(Pythonとか、Rとか)

テストデータ

前処理

生データ

コピー

本番環境の世界(RubyとかNodeとか)

教師データ

分類結果

コピー

本番システム参照ログ

オフライン系では、バッチで生成された分類結果のみを利用するため、データ分析環境と、本番環境の言語の違いは問題になりにくいオフライン環境では、チューニング結果を即座に本番投入できる

データ分析の世界(Pythonとか、Rとか)

本番環境の世界(RubyとかNodeとか)

データ分析の本番適用(オンライン)

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習精度テストデータ

前処理

生データ

コピー

特徴ベクトル

分類器推定器

前処理

本番データ結果

教師データ

コピー

オンライン系では、生データに対してリアルタイムに分類を行うデータ分析と、本番環境で同じ前処理が必要になる

せっかく分離した前処理も、本番環境に合わせて再実装が必要オンライン環境ではチューニング結果の本番投入に時間がかかる

データ分析の世界(Pythonとか、Rとか)

本番環境の世界(RubyとかNodeとか)

データ分析の本番適用の課題

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習精度テストデータ

前処理

生データ

コピー

特徴ベクトル

分類器推定器

前処理

本番データ結果

教師データ

コピー

本番環境にチューニング結果を適用するには時間がかかる別の言語で同じ前処理が行われているのか別の言語で同じパラメータを利用可能な分類器・推定器が存在するのか

課題の解決案• データ分析と本番環境で言語を統一する

– 心折れる

• 本番環境からデータ分析のコードを呼び出す– いわゆるSandbox、呼び出しのコストが高い– 実験であればこれでOK

• 前処理と分類器を別々に担保する– 同質な前処理を保証・生成する

• 独自言語で前処理を記述し、PythonやNode上のインタプリタで実行or 対象となる言語にコンパイルする

– 同質な分類器を保証する• 分類器だけsandboxに包む• フルスクラッチで頑張る

– 決定木やロジスティック回帰、重回帰、線形分類器などは、容易に再実装可能

課題の解決案• データ分析と本番環境で言語を統一する

– 心折れる

• 本番環境からデータ分析のコードを呼び出す– いわゆるSandbox、呼び出しのコストが高い– 実験であればこれでOK

• 前処理と分類器を別々に担保する– 同質な前処理を保証・生成する

• 独自言語で前処理を記述し、PythonやNode上のインタプリタで実行or 対象となる言語にコンパイルする

– 同質な分類器を保証する• 分類器だけsandboxに包む• フルスクラッチで頑張る

– 決定木やロジスティック回帰、重回帰、線形分類器などは、容易に再実装可能

→ベクトルコンバーター

ベクトルコンバーターの提案• ベクトルコンバーター

– 設定ファイル(という名のプログラム)を読み込んで、インタプリタで実行、生データを特徴ベクトルに変換

– 設定ファイルをJSやPythonのコードに変換することが可能、ポータビリティを確保

– 特徴量チューニングで利用される主要な操作をカバー– 言語仕様がコンパクトなので、任意の操作を容易に機能追加可能

生データ特徴ベクトル

ベクトルコンバータ

設定ファイル

JSの前処理コード

特徴ベクトル

JSのコードを出力

ベクトルコンバータによる解決

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習精度テストデータ

生データ

コピー

特徴ベクトル

分類器推定器

本番データ結果

教師データ

コピーベクトルコンバーター

前処理

前処理

前処理記述言語で前処理を共通化する前処理記述言語から、PythonやJSのコードを出力

上位言語で前処理の同一性を保証する(分類器に関してはsandboxか、フルスクラッチで頑張る……)

Sandbox

設定ファイル

コード例:単純参照

{a: 10.0,b: 200.0,c: 50.0,e: {

hoge: 1000}

}

abcde.hoge

10.0200.0 50.0 0.01000

入力されるjson 設定ファイル 出力特徴ベクトル

jsonに対して、透過的にアクセス可能入れ子になっている変数もアクセス可能

欠損値は自動的に0.0になる変数の取捨選択はこれだけでOK

コード例:演算

a b adda b suba b diva c add log1pa b div log1pa 100 200 chop

210.0-190.00.054.11080.0487100.0

入力されるjson 設定ファイル 出力特徴ベクトル

a + ba – ba / blog((a + c) + 1)log((a / b) + 1)max(100, min(200, a))

中置記法による疑似コード

※chopの実態は sorted([a,100,200])[1]

{a: 10.0,b: 200.0,c: 50.0,e: {

hoge: 1000}

}

演算は逆ポーランド記法(簡易forth)で行われる

コード例:簡易forthによる処理例入力されるjson

{a: 10.0,b: 200.0,c: 50.0,e: {

hoge: 1000}

}

a c add log1p

10.0 10.0

50.0

a c

60.0

add

4.110

log1p

4.110

• forthはスペースセパレータで、ワード単位で実行• ワードが予約語であれば、予約語を実行• ワードが予約語でなければ、入力されたjsonを参照• 入力されたjsonに値が存在すれば、スタックに積む• 入力されたjsonに値が存在しなければ、0.0を積む

※log1p(x)は、log(x+1)と等価

をステップ実行してみる

スタックの一番上が取り出される

forthの予約語の追加

forthの実行

予約語の定義

初期化

• forthは言語実装がコンパクトなので、予約語をモリモリ増やせる

• 同等のインタプリタを別言語で実装するのが容易

• JSなどの別言語を吐くコンパイラを記述することが容易

等価なJavaScriptの出力

a c add log1p

function(target_obj) {var t1, t2, t3;var stack = new Array();stack.push(target_obj.a === undefined ? 0.0 : target_obj.a);stack.push(target_obj.c === undefined ? 0.0 : target_obj.c);stack.push(stack.pop() + stack.pop())t1 = stack.pop();stack.push(t1 > -1.0 ? Math.log(t1 + 1.0) : -744.4400719213812);return stack.pop();

}

forthの処理がすべて1つの関数に展開される元となるオブジェクトに関数を適用すると、特徴変数が得られる

JITで最適化されるといいなぁ・・・

等価なJavaScriptの実行結果

まとめ• データ分析の課題

– 特徴量チューニングのために、前処理を外部に切り出す必要がある

• 本番環境の課題– 本番環境は、データ分析環境と別言語であることが多い

• データ分析の結果を本番に生かすことが難しい• データ分析部門が、ただの社内コンサルになってることが多い

– 同質の前処理の再実装が必要

• ベクトルコンバータの提案– 前処理を記述するforth風の言語

• Python上で動くforthインタプリタとして実装• 同質なJSを出力する機能を持つ

– 同質の前処理をデータ分析環境と、本番環境に提供

リクルーティング

• ZenClerkではメンバー募集中

– http://www.zenclerk.com/

–新しいデータからパターン発見をするのが好きなデータ分析者を募集中

• 人はなぜ買うのか、人はなぜ買わないのか

• 人はどうやって買うのか

• 人は何を買うのか

その他スライド

https://speakerdeck.com/yujiosaka/enzinia3ren-dezhi-eruyue-jian-10yi-pv

https://speakerdeck.com/yujiosaka/yue-jian-10yi-pvkaraxue-ndamongodbantipatan

http://www.slideshare.net/TokorotenNakayama/jubatusec-jubatushackathon

(付録)サンドボックスによる解決

生データ特徴ベクトル

機械学習 パラメータ

分類器推定器

学習精度

データ分析の世界(Pythonとか、Rとか)

テストデータ

前処理

生データ

コピー

特徴ベクトル

分類器推定器

前処理

本番データ結果

本番環境の世界(RubyとかNodeとか)

教師データ

コピー

Sandboxの世界(PythonとかRとか)

Sandboxでデータ分析環境と同じコードを動かすコードの同質性を保証するオーバーヘッドが大きい