2016-04-29

「詳解 Apache Spark」を共著で執筆しました (ので、みなさんぜひご購入ください!)

はじめに

昨年の秋ごろから、リクルートテクノロジーズの石川有さんらとともに共著で執筆していた「詳解 Apache Spark」 が遂に本日 4/29 に、技術評論社より発売となりました! なお、発売に先立って出版社および共著陣より献本させていただいた方々から、ありがたいことに書評や感想をいただいております。ぜひご購入の際の参考にしていただければと思います。

また、Amazon では Kindle 版も発売開始になった ようです。ですので、普段使いには物理書籍を、外出時には Kindle 版をご利用いただければと思います。

担当の「第 7 章 MLlib」について

書籍内ではあまり明確に謳ってはいないのですが、僕が担当した MLlib の章はデータ分析者だけではなく Web エンジニアを想定読者と考えています。仮に機械学習にあまり詳しくない方が読んだとしても、MLlib を利用するのに必要最低限の知識が獲得できつつ、MLlib を使ったアプリケーション開発ができるようになるであろう内容の構成としています。

章の前半では、RDD や DataFrame で表現されたデータに対して、MLlib の各機能 (特徴抽出や機械学習アルゴリズム、交差検証、評価メトリクスなど) を適用する説明に重点を置いた解説をしています。後半では、機械学習によって問題解決をするアプリケーションの開発イメージを掴むことを目的に、パブリックなデータセットを用いた具体例を提示しています。

紙面の都合もあり、機械学習の各種アルゴリズムの解説を事細かに網羅的に書くことは叶いませんでしたが、具体例で取り上げたアルゴリズムについては、そこそこ丁寧に説明をしました (したつもりです)。Spark 上で、より高度な機械学習の活用をしたいのであれば本書とあわせて、オライリー社の「Spark による実践データ解析」の書籍も読むのがいいでしょう。

また私の担当章以外も、GraphX や Spark Streaming など、MLlib の章以上に読み応えのある内容が盛りだくさんですので、このゴールデンウィークの勉強時間のお供にぜひ、本書をご購入いたければと思います。

おまけ

23:15No comments

2016-03-08

OS X で XGBoost & xgboost4j をビルドする手順 2016-03-07 版

追記: 2016-09-27 最新のビルド手順は こちら に記載しています。


いつのまにやら XGBoost のビルド手順が変更されていたので、メモしておきます (と言っても、 Installation guide に書いていることをほとんどそのまま日本語に直しただけですけどね)。

リポジトリの clone

手元に XGBoost の git リポジトリが存在しない場合は、以下のコマンドで submodule 含めて clone してしまいましょう。

git clone --recursive https://github.com/dmlc/xgboost

もし手元にリポジトリが存在する場合は、 git pull したのちに

git submodule init
git submodule update

として、submodule を手元に持ってきます。

XGBoost のビルド

clone したリポジトリに cd して、次の作業をします。

マルチスレッド非対応版で構わない場合

単に

cp make/minimum.mk ./config.mk
make -j4

とすれば OK です。

マルチスレッド対応版が欲しい場合

Installation guide 曰く、マルチスレッド (OpenMP) 対応した XGBoost をビルドするには、OpenMP-enabled なコンパイラである gcc-5.x.x が必要になるとのことです。なのでまず先に、 Homebrew で gcc をインストールしておきます (時間がかかるので、お茶でも飲んで待ちましょう)。

brew install gcc --without-multilib

なお、Homebrew で gcc-5.x.x をインストールしても gcc のコマンドが置き換わるわけではなく、 gcc-5 という名前でインストールされることに注意が必要です。そのため、Installation guide の手順をなぞっただけではマルチスレッド対応版の XGBoost をビルドすることはできません。

ここでは、Installation guide にある make/config.mk を単に cp する手順の代わりに、同ファイルで定義している CC および CXX をそれぞれ gcc-5, g++-5 に置き換えてコピーし、make する手順を紹介します。

cat make/config.mk | sed -e 's/# export CC = gcc/export CC = gcc-5/' | sed -e 's/# export CXX = g++/export CXX = g++-5/' >./config.mk
make -j4

xgboost4j のビルド

xgboost4j のビルドについては、以前の手順 よりハマりどころがなくなって楽になりました。詳しい手順は doc/jvm/index.md に書かれているとおりですが、ここでは次のように mvn package install して、ローカルの maven リポジトリにインストールしてしまいます (spark の依存が入っているため、最初の mvn install の実行でかなり時間がかかります。二杯目のお茶でも飲んで、待ちましょう)。

cd jvm-packages
./create_jni.sh
mvn package install

以上で xgboost4j のビルドは完了です。

1:16No comments

2016-02-09

エンジニアと機械学習、そして自分自身の振り返り ( #CROSS2016 に登壇しました)

2/5 (金) に開催された CROSS 2016 の「おーい、いそのー、エンジニアにとっての機械学習について考えようぜー!」というセッションにパネラーとして登壇してきました。セッションの内容はリンク先からの引用になりますが、

「機械学習は興味あるが、身に付けるためには何が必要?」
「機械学習を学ぶためにはいったい何からはじめればいい?」
「機械学習を身に付けたとして、その先のエンジニアとしてのキャリアはどうなる?」
と思ってる、そこのアナタ。
本セッションでは、機械学習や統計はもともと専門じゃないけど気がついたらバリバリ使ってた、そんなエンジニア連中が以下について語ります。
・エンジニアが機械学習を身に付けるために必要なこと
・どのように機械学習を学ぶのが効率的か
・エンジニアのキャリアパスとして考えた時、機械学習はどうなのか

というものでした。

当日は会場の音響の状況的に聞こえづらいところもあったかと思うので、僕がお話した内容(伝えたかったこと)+αをざっとまとめておきます。

エンジニアが機械学習を身に付けるには何が必要か?

まず最初は「エンジニアが機械学習を身に付けるために必要なこと」について議論しました。

そもそも、エンジニアにとって「機械学習を身に付ける」とはどういうことなのか、その点について共通認識がないままトピックが設定され議論をしていましたが、エンジニアと機械学習の関わり方には、主に以下の 2 つのタイプがあるんじゃないかと僕は考えています。

  • 機械学習を利用する人 :既存の機械学習のフレームワークやライブラリを用いる、またそれをアプリケーションに組み込んで利用する
  • 機械学習を実装する人 :既存の機械学習フレームワークなどには存在しない新しいアルゴリズムを実装する、もしくは特定のアプリケーションに最適化した形で既存のアルゴリズムを再実装する

前者のタイプであれば、機械学習の各種アルゴリズムがどのように動作するのか? というような、アルゴリズムに対するそこそこの理解が最低限必要になるかと思います。加えて、特徴エンジニアリング的な知識も必要になるかな… と、セッションを終えた後に議論を振り返っていて思ったのでした。

一方で後者のタイプであれば、機械学習アルゴリズムに対する深い理解が必要なのはもちろんのこと、アルゴリズムやデータ構造、時間・空間計算量などのある程度高水準なコンピューターサイエンスの知識、それと統計学の知識が必要になると考えています。また僕自身の経験から、微積や線形代数などの高校・大学レベルの数学の知識があると何かと助かるんじゃないかと思っています。その他には、英語力をつけておくと、最新の英語論文を読んでそれを実装したりもできていい感じです。

このトピックの僕の意見をまとめると、

  • 機械学習を利用する人:機械学習アルゴリズムに対する知識や特徴エンジニアリングの知識を身につけるべき
  • 機械学習を実装する人:上記に加えてコンピューターサイエンスや統計学、数学力、英語力を身につけるべき

となります。

機械学習を効率的に学習するにはどうしたらよいか?

次のトピックは「どのように機械学習を学ぶのが効率的か」でした。

これは僕自身の経験にもよるのですが、何よりも「仕事で機械学習を使わざるを得ない状況に身をおく」ことが一番効率的に機械学習を学べると実感しています。加えて言うと「機械学習の師匠」と呼べるような、理論面でも実活用面でも秀でた人物のそばで機械学習を利用する仕事ができるとベストだと思います(僕がいまいる会社がまさにそのような、理想的な状況にあるわけです)。

もちろん、そんな恵まれた状況に誰しもが巡り合えるわけではないことは重々承知していますが、本気で機械学習のお仕事をする覚悟があれば、転職をするのもありだと僕は考えています。ただし、転職をするにも多少なりとも機械学習の知識が必要になることもあるかと思います。そのような場合には、TokyoWebmining や TokyoR などの機械学習系の勉強会に顔を出したり、各種書籍の読書会に参加して発表するのが次善の策と言えるでしょう。

エンジニア+機械学習のキャリアパス

続いてのトピックは「エンジニアのキャリアパスとして考えた時、機械学習はどうなのか(機械学習を身につけることによって得られるリターンはいかほどか)」でした。

ここでいう「リターン」とは給与などのことを指すとして、現時点において機械学習を利用できるレベルのエンジニアの給与水準は、他の一般的なエンジニアの給与水準よりは幾分高いのではないかと推測しています。また、機械学習を実装できるレベルのエンジニアともなれば、相当な高水準の給与を得ているのではないでしょうか。

これは別に、機械学習の世界でだけ言えることではなくて、世間一般的に言えることなんじゃないかと思います。つまり、専門的かつ高度な技術・知識を持っていれば、給与水準は自ずと高くなるはずです。

ただその一方で、「機械学習を利用するエンジニア」の給与水準が今後も幾分高い水準を保てるかと言うと、僕は No だと考えています。現時点でも既に、Python 界隈は機械学習関連の機能が充実して使いやすくなってきているようですし、また Spark の MLlib が登場したことによって、一般的なエンジニアが機械学習を利用するまでのハードルが相当低くなっている = 技術コモディティ化が進んでいると思っています。この傾向は今後も継続して進んでいくものでしょうし、そうなるとただ単に「機械学習を扱える」だけのエンジニアの価値は並のエンジニアとさほど変わらなくなるでしょう。

また、機械学習が活用できるシチュエーションは、現実世界にはそう多くはない、ということにも注意が必要です。今は「人工知能」などのキーワードに引っ張られる形で機械学習も世間的に盛り上がっているようではありますが、この盛り上がりが落ち着いたときに、どれだけ「機械学習」が必要とされる仕事があるのか… というのを考えると、そう多くはないのでは? というのは想像に難くないかと思います。つまりは、機械学習を活用する仕事 = 需用が少なく、一方で供給 = 機械学習を扱えるエンジニアが多いと需給的には買い手市場となり、結果として給与水準が並のエンジニアとそう変わらない状況も生じるのではないかと思います。まあ、これはちょっと悲観的過ぎる推測でしたが…

そのため、機械学習を利用できるだけではなく、必要とあらば機械学習のアルゴリズムを実装できるぐらいのスキルがなければ中長期的にみて見合うリターンは見込めない、というのが僕の意見になります。というか、これは機械学習に限ったことじゃないですね… スペシャリスト的な働き方を目指すのであれば、それぐらいの覚悟がなければダメですよね。

機械学習を業務で扱う、その苦労

最後のトピックは「業務で大変だったこと、それをどう乗り越えたか」でした。

一般的にソフトウェア開発では、その品質を高めるために手動もしくは自動でのテストをするわけですが、機械学習においては知ってのとおり、手動や自動の議論以前に、そもそもテストを適用すること自体がそう簡単なことではありません。そのため、機械学習を組み込んだアプリケーションがあったとして、そのアプリケーションの実行結果がなんとも思わしくない結果が得られた場合、機械学習アルゴリズムにおける精度の制約なのか、それとも実装上の不具合なのかを切り分けることは困難な問題になります。

実際に僕も、この切り分けが困難な問題に何度も直面し、そのたびにつらみを感じてきました。そのため、今では機械学習の実装に対してできるかぎり自動テストを適用し、「実装上の不具合」を回避するように心がけるようにしています。

参考: 機械学習のテスト自動化コトハジメ #MLCT Machine Learning Casual Talks #1 // Speaker Deck

自分自身の振り返り

こんな感じで、当日のセッションでは識者ぶってお話をしてきました。でも今の僕は、「機械学習 黒帯」みたいなものを名乗るにはまだほど遠いところにいると思っています(「黒帯」とかただただ恥ずかしいだけだし、名乗りたいとは思っていません)。引き続き学習あるのみ、です。

そして、ふといままでの自分のキャリアを振り返ってきたときに、今となっては何の役に立たない残念な技術をいったいどれほど学習 = 貴重な時間を投資してきてしまったんだろうか… とも思いました。これまでの経験上、ソフトウェアエンジニアを続けている限りは「コンピューターサイエンス」を除いて廃れない技術はない、と僕は考えているので、機械学習もまたいつか廃れる日が来るのかもしれません。でもその日が来るまではしばらく、もうちょっと機械学習に投資してみようかな、と思っています。

2:391 comment

2016-01-15

弊社主催のイベント #SmartTechNight で、広告の配信最適化について喋りました

僕は最近こんなお仕事をしているんですよー、という意味をこめて喋りました。 機械学習だけが「アドテク」じゃない。最適化も重要なんだよ、という気持ちで。

よろしければ、こちらも合わせて御覧ください。

プレゼンテーションに盛り込む内容について、細かいことを言わない上司に恵まれているので、僕が担当している・していたお仕事の特に興味深そうなところをほぼすべてを余すことなくしたためた資料です。 遡ること 1 年半前、広告について何も知らなかった僕は必死の思いで関連文献を読み漁っていたわけですが、当時にこれくらい充実した資料があれば、もっと楽して開発できたのになあ、と資料を作りながら思ったのでした。 ですので、この資料が他の誰かの助けになれば幸いです。

そして、こういう話題であーでもないこーでもないと盛り上がれる仲間が欲しいです! 応募は こちら からお気軽に☆ 応募するのはまだちょっと踏ん切りが付かないけど、広告システムやその分析について議論してみたい! という方がいましたら僕宛にコンタクトください。

今日の反省点:Space cats や Shibe のネタスライドは受けがよくない。

0:094 comments

2015-12-12

Spark/MLlib 向けに、評価メトリクスとして Logarithmic loss (LogLoss) を利用する Evaluator を実装してみた

ロジスティック回帰を使って確率を予測したいときに「評価メトリクスとして使いたいのは AUC (areaUnderROC) じゃなくて Logarithmic loss (LogLoss) なんだよ!」と常々思っているのですが、現在の MLlib には二値分類 (BinaryClassificationEvaluator) 、多クラス分類 (MulticlassClassificationEvaluator)、回帰 (RegressionEvaluator) 用の Evaluator 実装しか用意されていなかったので、ついカッとなって実装してしまった次第です。

これくらいの機能は標準で取り揃えていてもいいんじゃないかと思うんだけどなあ…

16:54No comments

2015-11-08

xgboost4j より数千倍速く predict できる Pure Java な XGBoost 互換の予測器を作ってみた

TL;DR

XGBoost で構築した予測モデルを Java から利用したい、それも特徴ベクトルが一つ一つ、任意のタイミングで与えられるような オンライン環境下リアルタイムな予測 を実現するために利用したい、という目的を叶えるためのモジュールを作りました。

(XGBoost の凄さとか XGBoost そのものの使い方とか GBDT/GBRT の解説は本エントリにはありませんので、そのような情報を求めている方は他のブログエントリを読まれることをおすすめします。)

xgboost4j という選択肢

Java から XGBoost を利用しようとすると、XGBoostをJavaのwrapperを使用して実行する - TASK NOTES にあるように、DMLC が提供している xgboost4j を利用する手段がすでに存在しています。ただ、この xgboost4j をオンライン予測に適用する場合、下記に挙げるようないくつかの懸念があります。

  • XGBoost の Java wrapper でしかないので、オンライン予測の目的で利用をするにはインタフェースがちょっと使いづらい
    • 大量の特徴ベクトルを入力して一括予測するようなバッチ処理に適したインタフェースになっている
  • LIBSVM フォーマットじゃないデータを入力するのに手間がかかる
    • 特に疎な特徴ベクトルを DMatrix で表現するのが面倒
  • JNI 由来のオーバーヘッドが気になる
    • 予測処理などが C++ で書かれているので高速処理が期待できる一方で、特徴ベクトルを一つ一つ与えて予測させる場合、ネイティブコードの呼び出しにかかるオーバーヘッドが全体のパフォーマンスに大きな影響を与えそう
  • どこの Maven repository にもアップロードされていないので、自前で mvn install する必要がある
    • OS X で開発をしている場合、ネイティブライブラリをビルドするのも一苦労 (参考)

Pure Java での予測を実現する

そういうわけで、

  • 速度性能がオンラインでの利用に耐えうる水準で
  • そこそこ使いやすいインタフェースで
  • ネイティブコードを必要としない (= Pure Java な)

XGBoost 互換な予測器を作って jCenter で公開しました。

使い方

README.md にもサンプルコード込みで使い方を書いていますので、合わせてご参照ください。

なお、タイトルでも「予測器」と明言しているとおり、学習 (training) 機能については割りきって一切実装をしていません (モデルの構築をオンラインですることは流石にないと思うので)。 そのため学習データを用意し、XGBoost を CLI で直接実行、もしくは Python や R のラッパーを経由するなどして別途モデルの構築を事前に済ませておく必要があります。

学習済みのモデルが用意できたら、そのモデルを new Predictor("/path/to/model-file") としてロードします。 予測をするには Predictor#predict() のメソッドを呼び出します。

予測の際の入力となる特徴ベクトルは、FVec インタフェースのオブジェクトとして表現する必要があります。 基本はお手持ちのデータの形式に合わせて FVec インタフェースを実装したクラスを用意していただくことになりますが、配列や Map でデータが表現されている場合には、以下のユーティリティメソッドを利用することができます。

  • double の配列で表現された密な特徴ベクトルで → FVec.Transformer#fromArray()FVec オブジェクトに変換できます
  • 特徴量のインデックスと値の対を表現した Map オブジェクト → FVec.Transformer#fromMap()FVec オブジェクトに変換できます

また GBDT/GBRT のモデルを特徴ベクトルの変換に利用することを目的に、(分類・回帰の結果を出力するのではなく) GBDT/GBRT の各ツリーにおいて辿り着いたリーフのノード番号を出力する Predictor#predictLeaf() メソッドも用意されています。

ベンチマーク

元々このモジュールを作った動機の一つとして、オンライン利用に耐えうる速度性能で予測をしたい、という目的があったので xgboost4j と合わせてベンチマークをとってみました。 ベンチマーク計測の詳細は こちら のプログラムにあるとおりです。

機能 xgboost-predictor xgboost4j 性能比
モデルの読み込み 49017.60 ops/s 39669.36 ops/s 1.24
単一の特徴ベクトルでの予測 6016955.46 ops/s 1018.01 ops/s 5910.48
複数の特徴ベクトルの予測 44985.71 ops/s 5.04 ops/s 8931.47
リーフノードの出力 11115853.34 ops/s 1076.54 ops/s 10325.53

結果は上記のとおり、

  • 予測処理は 1ms 以下で処理できている
  • xgboost4j と比較して約 6,000 倍近い速度性能がでている (要は xgboost4j よりも十分速い)

となります。Pure Java にしただけで xgboost4j との性能差がこんなに出るものなのか… とちょっと不思議ではありますが、今回のベンチマークの計測に利用したテストデータは人工的に生成されたものなので、その影響があるのかもしれません。 そのため、実世界のデータを与えた場合にはまた違った結果になる可能性がありますのでご注意ください。

制限

現時点の xgboost-predictor は、モデルとしては “gbtree” のみをサポートしています。また目的関数は “binary” および “multi” のみのサポートとなります。 (“gblinear” や他の目的関数のサポートについては、必要そうであれば対応する予定です。)

21:095 comments