Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

6,699 views

Published on

本番環境とデータ分析環境の言語の差がツライ

Published in: Technology

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

  1. 1. 特徴ベクトル変換器を作った話 @tokoroten
  2. 2. データ分析の流れ 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習結果 学習精度 教師データ テストデータ 前処理
  3. 3. マエショリスト 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習結果 学習精度 教師データ テストデータ 前処理 前処理は、データ分析においてすごく大事 データ分析の仕事の多くが前処理だったりする そこから先は既存フレームワークで自動化可能 Jubatusのfv_converterはすごくよく出来てた……
  4. 4. 前処理のニーズ • 特徴量チューニングがしたい – 特徴量を手動チューニングするだけで、機械学習の精度が大き く改善する • 特徴量チューニングでよくやること – 利用する変数の取捨選択、欠損値の対応 – 変数のクリップ(最大値、最小値) – 変数のログスケール変換(負の値の対応) – 変数を演算して、線形分離しやすい新しい変数を作る • 足し算、引き算、割り算、正規化、分散 – bool値を0,1に変換、特定のラベルを0,1に変換 • 実例 – アクセス時刻と、イベント発生時刻をunixタイムに直して差分 をとって、発生までの秒数にして、それをイベント発生回数で 割り算して正規化して、それをログスケールに変換して……
  5. 5. データ分析のよくあるソース管理 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習結果 学習精度 教師データ テストデータ 前処理 一つのソースで一気通貫で処理 データソースごとに別の前処理を行うことが難しい 実験や特別対応の試行錯誤結果が、レポジトリに残らない 「この学習結果って、どんな設定で出したんだっけ?」
  6. 6. 前処理分離モデル 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習結果 学習精度 教師データ テストデータ 前処理と機械学習を切り離す 前処理 設定 ファイル 前処理を設定ファイルに切り出すことで、 データソースごとの個別対応が可能になる 設定ファイルをレポジトリにコミットすることで、 再現性が生まれる
  7. 7. 勝ったッ!第3部完! • 前処理を分離して設定ファイルに切り出す – 特徴量チューニングでソースコードが汚れない – クライアントごとに別のファイルになるので、レ ポジトリで管理可能になる – 特徴量チューニングの試行錯誤がやりやすくなる • ここからが本当の地獄だ – データ分析で閉じた世界なら問題ないが、 本番システムが絡むと厄介な問題になる
  8. 8. データ分析の本番適用(オフライン) 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 分類結果 データ分析の世界(Pythonとか、Rとか) テストデータ 前処理 生データ コピー 本番環境の世界(RubyとかNodeとか) 教師データ 分類結果 コピー 本番システム 参照ログ オフライン系では、バッチで生成された分類結果のみを利用するため、 データ分析環境と、本番環境の言語の違いは問題になりにくい オフライン環境では、チューニング結果を即座に本番投入できる
  9. 9. データ分析の世界(Pythonとか、Rとか) 本番環境の世界(RubyとかNodeとか) データ分析の本番適用(オンライン) 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習精度 テストデータ 前処理 生データ コピー 特徴 ベクトル 分類器 推定器 前処理 本番データ 結果 教師データ コピー オンライン系では、生データに対してリアルタイムに分類を行う データ分析と、本番環境で同じ前処理が必要になる せっかく分離した前処理も、本番環境に合わせて再実装が必要 オンライン環境ではチューニング結果の本番投入に時間がかかる
  10. 10. データ分析の世界(Pythonとか、Rとか) 本番環境の世界(RubyとかNodeとか) データ分析の本番適用の課題 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習精度 テストデータ 前処理 生データ コピー 特徴 ベクトル 分類器 推定器 前処理 本番データ 結果 教師データ コピー 本番環境にチューニング結果を適用するには時間がかかる 別の言語で同じ前処理が行われているのか 別の言語で同じパラメータを利用可能な分類器・推定器が存在するのか
  11. 11. 課題の解決案 • データ分析と本番環境で言語を統一する – 心折れる • 本番環境からデータ分析のコードを呼び出す – いわゆるSandbox、呼び出しのコストが高い – 実験であればこれでOK • 前処理と分類器を別々に担保する – 同質な前処理を保証・生成する • 独自言語で前処理を記述し、PythonやNode上のインタプリタで実行 or 対象となる言語にコンパイルする – 同質な分類器を保証する • 分類器だけsandboxに包む • フルスクラッチで頑張る – 決定木やロジスティック回帰、重回帰、線形分類器などは、容易に再実装可能
  12. 12. 課題の解決案 • データ分析と本番環境で言語を統一する – 心折れる • 本番環境からデータ分析のコードを呼び出す – いわゆるSandbox、呼び出しのコストが高い – 実験であればこれでOK • 前処理と分類器を別々に担保する – 同質な前処理を保証・生成する • 独自言語で前処理を記述し、PythonやNode上のインタプリタで実行 or 対象となる言語にコンパイルする – 同質な分類器を保証する • 分類器だけsandboxに包む • フルスクラッチで頑張る – 決定木やロジスティック回帰、重回帰、線形分類器などは、容易に再実装可能 →ベクトルコンバーター
  13. 13. ベクトルコンバーターの提案 • ベクトルコンバーター – 設定ファイル(という名のプログラム)を読み込んで、 インタプリタで実行、生データを特徴ベクトルに変換 – 設定ファイルをJSやPythonのコードに変換することが可能、 ポータビリティを確保 – 特徴量チューニングで利用される主要な操作をカバー – 言語仕様がコンパクトなので、任意の操作を容易に機能追加可 能 生データ 特徴 ベクトル ベクトル コンバータ 設定 ファイル JSの前処理 コード 特徴 ベクトル JSのコードを出力
  14. 14. ベクトルコンバータによる解決 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習精度 テストデータ 生データ コピー 特徴 ベクトル 分類器 推定器 本番データ 結果 教師データ コピー ベクトルコン バーター 前処理 前処理 前処理記述言語で前処理を共通化する 前処理記述言語から、PythonやJSのコードを出力 上位言語で前処理の同一性を保証する (分類器に関してはsandboxか、フルスクラッチで頑張る……) Sandbox 設定 ファイル
  15. 15. コード例:単純参照 { a: 10.0, b: 200.0, c: 50.0, e: { hoge: 1000 } } a b c d e.hoge 10.0 200.0 50.0 0.0 1000 入力されるjson 設定ファイル 出力特徴ベクトル jsonに対して、透過的にアクセス可能 入れ子になっている変数もアクセス可能 欠損値は自動的に0.0になる 変数の取捨選択はこれだけでOK
  16. 16. コード例:演算 a b add a b sub a b div a c add log1p a b div log1p a 100 200 chop 210.0 -190.0 0.05 4.1108 0.0487 100.0 入力されるjson 設定ファイル 出力特徴ベクトル a + b a – b a / b log((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)で行われる
  17. 17. コード例:簡易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)と等価 をステップ実行してみる スタックの一番上 が取り出される
  18. 18. forthの予約語の追加 forthの実行 予約語の定義 初期化 • forthは言語実装がコンパクトなので、 予約語をモリモリ増やせる • 同等のインタプリタを別言語で実装 するのが容易 • JSなどの別言語を吐くコンパイラを 記述することが容易
  19. 19. 等価な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で最適化されるといいなぁ・・・
  20. 20. 等価なJavaScriptの実行結果
  21. 21. まとめ • データ分析の課題 – 特徴量チューニングのために、前処理を外部に切り出す必 要がある • 本番環境の課題 – 本番環境は、データ分析環境と別言語であることが多い • データ分析の結果を本番に生かすことが難しい • データ分析部門が、ただの社内コンサルになってることが多い – 同質の前処理の再実装が必要 • ベクトルコンバータの提案 – 前処理を記述するforth風の言語 • Python上で動くforthインタプリタとして実装 • 同質なJSを出力する機能を持つ – 同質の前処理をデータ分析環境と、本番環境に提供
  22. 22. リクルーティング • ZenClerkではメンバー募集中 – http://www.zenclerk.com/ – 新しいデータからパターン発見をするのが好 きなデータ分析者を募集中 • 人はなぜ買うのか、人はなぜ買わないのか • 人はどうやって買うのか • 人は何を買うのか
  23. 23. その他スライド 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
  24. 24. (付録)サンドボックスによる解決 生データ 特徴 ベクトル 機械学習 パラメータ 分類器 推定器 学習精度 データ分析の世界(Pythonとか、Rとか) テストデータ 前処理 生データ コピー 特徴 ベクトル 分類器 推定器 前処理 本番データ 結果 本番環境の世界(RubyとかNodeとか) 教師データ コピー Sandboxの世界(PythonとかRとか) Sandboxでデータ分析環境と同じコードを動かす コードの同質性を保証する オーバーヘッドが大きい

×