Cloudera: 機械学習が広がる中でのデータモデル

https://www.youtube.com/watch?v=IgfRdDjLxe0

1 comment | 1 point | by WazanovaNews 3年弱前 edited


Jshiike 3年弱前 edited | ▲upvoteする | link

Josh Willsは、Googleで広告オークションシステムとデータ分析インフラの開発を担当し、現在は、ClouderaのSenior Director of Data Scienceを勤めています。

機械学習によるデータ分析が、Googleなどに限らず、AirbnbやEtsyなどその他のネット企業にも広がっていく中、今後必要とされるデータモデルについて 、Midwest.ioGraphLab Conference で講演しています。

複数の機械学習分析を操るGoogleのチャレンジ

  • 機械学習分析のベースとなる各サービスの仕様が頻繁に変更になる。
  • 機械学習分析はそれぞれ単体でも複雑なのに、Googleの場合、それらが相互に関連があるケースが多かった。一つの機械学習分析の変更が、他の機械学習にどう影響がでるかが把握しきれない。その結果、広告配信システムを理解できない(= コントロールできない。)状況が発生し、(誤った機械学習分析結果に従って)広告配信量が漸減してしまう障害の原因を見つけるのに数週間かかったこともあった。
  • 本当に大変なのは、最適化ではなく、自分のシステムを理解すること。どのようにシステムが振る舞うか仮説をたて、テストをし、それをもとに改善を繰り返す。

世の中で機械学習が広がる前提条件が揃ってきた

  • ログの取得、モニタリングなどDevOpsの習慣が常識になってきた。
  • 各サービスで、データの相互関係の手がかりになるような機能(例えば、Twitterのハッシュタグ)が増えてきた。

機械学習の広がりと課題

  • AirbnbやEtsyなどが機械学習の採用をブログで公開しはじめた。
    • Etsyの機械学習システム Conjectureは、ほとんどがオープンソース化されている。
    • まだ、単一の機械学習アルゴリズムを複数のケースに適用しているだけで、ケースごとに最適なアルゴリズムを用意するような仕組みにはなっていない。
    • 実際のオペレーションと分析モデルづくりでは、開発言語が違っているが、こういうケースは多い。Etsyは、分析モデルはScalaで、DevOpsの仕組みはPHPで書かれている。Airbnbは、PythonとJava。

最適なデータモデルの模索

  • 機械学習の採用を宣伝する各ネット企業のブログでは、アルゴリズムや成果などについてしか語られないが、実はFeature Engineeringが一番重要なポイント。様々なデータソースを利用可能なかたちにどううまく整形/変換するかというプロセスが大変。
  • かつて、複雑なスキーマよりも最終的にはスプレッドシートにまとめたいという分析チームの嗜好と、複雑なリレーショナルDBという組み合わせが、妥協策として、スタースキーマを生み出した。エンタープライズITの世界では、スタースキーマをサポートするソリューションが大きなビジネスになっている。
  • 一方、機械学習は基本的にはレコメンデーションエンジン。シンプルなkey/valueデータを用意して、ひたすら計算/学習させていくといくという方式。リレーショナルDBでなく、ログファイル / JSONファイルをどうシンプルに処理するかというのがポイント。
  • また機械学習では、一つのデータに対して様々な分析をするということになる。データに対するニーズが多様化していると言える。よって、もっとシンプルで汎用性のあるデータモデルが必要になるのではないか。

スーパーノバスキーマ

  • Supernova Schemaとは、エンティティ単位での一つにまとまった非正規化データスキーマを用意すること。例えば、ユーザ単位でまとめる。これによるメリットは、

    • シンプルなkey/value構造なので、機械学習に最適。
    • DevOpsがBashスクリプトを書いてサーバ全体に適用するように、データの分析の伝播/集計がやりやすくなると期待している。
    • Hive, Pigのように、オフライン前提の分析でなくとも、MongoDBやHbase他のオンライン分析にも応用できる。
    • SQLでなくとも書けるので汎用性あり。SASにも同じ考えは適用できる。

スーパーノバスキーマの事例

また、Joshは最新のブログHilary Masonの言葉

ビッグデータを理解するという本当の意味は、サイズに関わらずデータを高速に数えることができるかどうかにある。テクニカルな差異ではなく、どう認識できるかで違いがでる。

を引用し、それを実現するスーパーノバスキーマを、モバイルアプリの検索を改善するプロジェクトを例にあげ紹介しています。

ユーザから、インストールしたいアプリを見つけづらいという苦情がきた場合、

  • スマホのキーボードではアプリの名称を正確にタイプするのは難しく、タイプミスしてしまうか、オートコレクトがあれば利用したいということになる。
  • 変わった名前のアプリだと、正確なスペルを思いつかない。
  • 人気のアプリは、コピーアプリが氾濫するので、どれが正しいアプリか判断つきづらい。

幸いスペルミスの状況を分析するためのデータはHadoopにあるとする。

1   > DESCRIBE searches;
2
3   event_id: bigint
4   account_id: bigint
5   query: string
6   tstamp_sec: bigint
7   (some other columns)
8
9   > DESCRIBE installs;
10
11  event_id: bigint
12  account_id: bigint
13  app_id: bigint
14  search_event_id: bigint
15  (some other columns)

まずは、検索したがインストールに至らないパターン。searchesテーブルにある event_ids が、インストールテーブルの search_event_id カラムにでてこない件数を調べる。

しかしそれだけでは、ユーザはアプリを眺めるためにブラウジングしていただけかもしれなし、アプリは見つけたけど思ったより値段が高くてやめたのかもしれないし、アプリのサイズが大きすぎたのでWifiが拾える場所にくるまでインストールを控えたのかもしれない、ので判別つかない。タイプミスのケースとうまく切り分ける必要がある。タイプミスかどうかは、イベントをうまく関連づける必要がある。

  • ユーザはタイプした後、検索結果を確認するが、何もインストールしない。
  • 数秒後、少し違う内容の入力をする。新しい検索結果をみて、その中から1個以上のアプリをインストールする。

この場合、同じテーブルに対する複数の検索イベントの相関関係を分析しなくてはいけない。self-join だと、相当スピードが遅く、リソースを必要とするが、LAGやLEADのような分析SQL functionを使えば高速にカウントできる。

これでかなり改善するが、まだ課題は残る。スペルミスを修正した検索の候補としては、従前の検索のすぐ後に行われたものだけを対象としている。しかし、ユーザが複数回スペルミスすることはありえる。ユーザがインストールに成功するまでの一定時間の間に行われた検索は全て考慮に入れるかたちとしたい。しかし、考慮にいれるべき検索アクションをどの範囲までにすべきかを、 lag/lead などの分析SQL functionでは判断しがたい。

現状、ユーザごとのデータは、異なるテーブルの異なる行に分散している。ではそれを、ユーザごとにデータを一つのテーブルにまとめ、各行でそのユーザの全ての情報(この場合は、全ての検索 + インストール)をカバーする仕組みにしてはどうか。

1   > DESCRIBE sessions;
2
3   account_id: bigint
4   search_events: array<struct<event_id: bigint, query: string, tstamp_sec: bigint>>
5   install_events: array<struct<event_id: bigint, serach_event_id: bigint, app_id: bigint>>

これをスーパーノバスキーマと名付けている。理由は、スタースキーマのfactテーブルが、一つの次元の方に折り畳まれたようなかたちになっているから。ここからは、HiveQLはstructのarrayに対応できる拡張ビルトインfunctionがないので、JavaかPythonで書く人が多いかと思うが、SQLでクエリできる小さなDBテーブルであるかのように、Hiveの拡張を用意して、あえて各行内でstructのarrayを扱えるようにしてみる。

1   -- Execute the spell correction analysis;
2   SELECT qw, qr, count(*) as cnt
3   FROM sessions
4   LATERAL VIEW WITHIN(
5     "SELECT t1.query qw, t2.query qr
6     FROM t1 as bad, t1 as good
7     WHERE bad.tstamp_sec < good.tstamp_sec
8     AND good.tstamp_sec - bad.tstamp_sec < 30
9     AND bad.event_id NOT IN (select search_event_id FROM t2)
10    AND good.event_id IN (select search_event_id FROM t2)",
11  search_events, install_events)
12  GROUP BY qw, qr;

WITHINは、Hiveのテーブル生成functionである。テーブルの行全体の結果をまとめるfunctionを表現するのに、Hiveの LATERAL VIEW構文を使っている。ネストされたSQLクエリの後に渡されてる各arrayは、位置ベースのエイリアスをアサインされていて、search_event は t1、install_event は t2 となる。WITHIN内では、最近できたApache Opticを利用し、30秒の範囲でのスペルミス修正クエリ候補を全て見つけるために、(小さな)search_event arrayにおいて、self-join を実行している。

SQLのネストについては、Joshが、Githubにサンプルコードを用意してくれています。

#cloudera #機械学習

Back