データサイエンティスト養成読本機械学習入門編の振り返りと補足

9月10日,技術評論社より「データサイエンティスト養成読本 機械学習入門編」が発売され,おかげさまで約1ヶ月後には増刷が決定しました.
お読みいただいた方々に深くお礼申し上げます.

データサイエンティスト養成読本 機械学習入門編 (Software Design plus)

データサイエンティスト養成読本 機械学習入門編 (Software Design plus)

また,出版日の夜には,KDDIウェブコミュニケーションズ様で刊行記念イベントが行われました.

「データサイエンティスト養成読本 機械学習入門編」刊行記念イベント

私も著者の一人として参加させていただきました.
足元が優れない中ご参加いただいた方々,会場を提供いただいたKDDIウェブコミュニケーションズ様,
運営していただいた技術評論社様の方々にお礼を申し上げます.

以下では,出版後1ヶ月半を経てあらためて本書の見どころ,出版日当日の刊行記念イベントについて,主観的な感想を綴っていこうと思います.
また最後に,私が担当した第2部特集1「機械学習ソフトウェアの概観」に関する補足を行います.

あらためて本書のみどころを

本書は,企画構想時点から取りまとめを行われていた比戸さんによるブログ
機械学習の入門本を書きました(データサイエンティスト養成読本)
や以下のように既に多くの方々に書評を書いていただいており,大変感謝しております.

ヌケ,モレがあれば教えていただけると幸いです.

世間では人工知能機械学習,深層学習(ディープラーニング)などのキーワードが過熱気味の昨今,
本書は機械学習の入門としてデータサイエンティストを養成するという名の下に出版されました.
機械学習は素晴らしい,何でもできる,そんな謳い文句とともに機械学習の技術的な記事が並んでいるのだろうと思って手に取る方は,
冒頭の比戸さんの記事を読んで面食らうことでしょう.
機械学習のコンセプト,メリット,そして限界,人工知能/機械学習の歴史を踏まえて今注目される理由や実用化に向けたハードルなどが
非常に簡潔に書かれています.
最後のQ&Aでは,機械学習の等身大の姿が書かれており,
ともすれば人工知能機械学習により自動化が進み人間にとって代わるという現在の風潮に対して,非常に地に足のついた回答が提示されています.

個人的には,この記事は実際に機械学習を使用しようと思っている方だけでなく,
少しでも人工知能機械学習のキーワードを耳にしたことのある方は全員読んでいただきたいと思っています.
また,特に最後のQ&Aは業務の分析報告や提案活動の中で質問されそうな内容が並んでおり,
機械学習を使用しているデータ分析者の方にも少なからず得るものがあるのではないかと思います.
比戸さんがご自身のブログの中で"Demystifying Machine Learning"(機械学習の化けの皮を剥がす)として,
機械学習にまつわる2つの神話*1を打ち砕きたかったとおっしゃっていますが,その目的は十分に果たされ,
機械学習の良きも限界も理解した上で上手な付き合いを行なっていくための足がかりとなる名記事です.

比戸さんの記事を読んで腰を落ち着けた後は,馬場先生の記事で機械学習の中身を勉強すると良いと思います.
馬場先生の記事には数式が出てきますが,嬉しいのは数式の意味,あるいは意図を明確に書いていただいており,
図を多用して直感的な理解も促して下さっていることです.
たとえば,

  • 『「非雇用率が 0 のとき犯罪率は w_{0}」「非雇用率が 1 のときの犯罪率は w_{0} + w_{1}」であることを表現しています』
    といったように,数式の意味が書かれている.
  • 損失関数  l(w_{0}, w_{1}, x, y) = (y - (w_{0} + w_{1} x))^{2} について,
    『損失関数は、実際の犯罪率の値 y と犯罪率の予測値  w_{0}+w_{1}x の差が大きいほど値が大きくなるように設計されています。』
    と値の見方について書かれている.さらに,続けて具体例で
    「予測器  f(x)=0.1+0.5x の二乗誤差を示します。たとえば1番目の都市では、実際の犯罪率は0.04 であるのに対して予測器による予測値は0.15 であるため、二乗誤差は  (0.04-0.15)^{2}=0.0121

といった具合です.
数式だけでなく,文章や図も合わせて読むことにより理解を深めていくと良いと思います.

その後は興味に合わせて,いろいろな読み方ができると思います.たとえば,

  • ビジネスでどう使えば良いか知りたい,どう適用するかイメージを湧かせたい
    → 第1部特集3「ビジネスに導入する機械学習」,第2部特集3「推薦システム入門」(レコメンデーションの基本とともに,4章で筆者の実務経験を踏まえた見解が述べられています)
  • 実際に手を動かしながら,機械学習を体感したい
    → 第2部特集1「機械学習ソフトウェアの概観」,特集2「Pythonによる機械学習入門」,特集3「推薦システム入門」,特集4「Pythonで画像認識にチャレンジ」,特集5「Jubatusによる異常検知」
  • 最先端の話題について知りたい(深層学習,ディープラーニング
    → 第1部特集4「深層学習最前線」

といったように,様々な目的に合わせて記事を選んでいけるのも本書の特徴の一つかなと思っています.

第2部はPythonソースコードが多くなっていますが,
特集2でOSごとのインストール方法から説明していただいているので,Python初心者にも問題はないと思います.
この記事はscikit-learnだけでなく,NumPy, matplotlibについても丁寧に説明されており,
Rは使ったことがあるけどPythonはあまりないという方にも導入として非常に取っ付きやすいと思います.
また,個人的な感想ですが,第2部はまず特集2を読んでPythonで基本的なことができるようにしておいて,
Pythonを使って機械学習を実践したい場合は特集3, 4, 5を,
他のソフトウェアと比較してPythonがどのような位置付けとなっているかを知りたい場合は私が執筆した特集1を読む
という進め方も一つの手かもしれません.

第1部特集3と第2部特集1には,Rのソースコードが出てきます.
Rの初歩については解説が少ないので,本書の前作にあたる「データサイエンティスト養成読本」,
「データサイエンティスト養成読本 R活用編」を参照すれば良いかと思います.

データサイエンティスト養成読本 [ビッグデータ時代のビジネスを支えるデータ分析力が身につく! ] (Software Design plus)

データサイエンティスト養成読本 [ビッグデータ時代のビジネスを支えるデータ分析力が身につく! ] (Software Design plus)

データサイエンティスト養成読本 R活用編 【ビジネスデータ分析の現場で役立つ知識が満載! 】 (Software Design plus)

データサイエンティスト養成読本 R活用編 【ビジネスデータ分析の現場で役立つ知識が満載! 】 (Software Design plus)

以上,簡単ですが,機械学習って結局何?というところから,ビジネス応用,技術的な入門まで揃えられた本書が,
機械学習を正しく理解し,手を動かしながら使うイメージを持つための入門書として必携の一冊となることを願っています.

刊行記念イベント

刊行記念イベントでは,執筆者からLT(Lightning Talk)が行われた後に,Q&Aが行なわれました.
詳細については,技術評論社様のページにフォトレポートが上がっていますのでご参照ください.
「データサイエンティスト養成読本 機械学習入門編」刊行記念イベント フォトレポート

その後の懇親会と合わせて,様々な分野でデータ分析に関わる方々と情報・意見交換ができて非常に貴重な時間を過ごすことができました.

執筆担当箇所に関する補足

以下では,私が担当した第2部特集1「機械学習ソフトウェアの概観」について,執筆後に出てきた参考資料の紹介や補足を行います.
なお,出版社の許諾を得て掲載しています

代表的なソフトウェアに関する記事

本文とは少し違った観点で,Python, R, Julia等のデータ解析を実行するソフトウェアに関して綴られた以下の記事は,
ぜひ合わせてお読みいただければと考えています.

Python, Machine Learning, and Language Wars. A Highly Subjective Point of View(2015-08-24) by Sebastian Raschka

和訳版:Pythonや機械学習、そして言語の競争について – 極めて主観的な見地から

著者はミシガン州立大学で計算生物学を専攻する博士課程の学生で,
2015年9月に刊行された"Python Machine Learning"(Packt Publishing)を執筆されています.
冒頭で,著者は(1)アイデアをコードで書き出す時にかかった時間,(2)デバッギングにかかった時間,(3)実行にかかった時間の合計時間を想定し,
著者にとってはPythonがベストだったと説明しています.
MATLABやJuliaについても言及しており,Rについても誤解を解く記述もあります.
最後には,様々な言語を使用する読者からのコメントも複数掲載されており,参考になります.
著者はツールや言語は目的を達成するための手段というスタンスであり,私も同じ考えのため非常に共感を持ちます.

また,RとPythonの比較については特にKDnuggetsなどに多く記事が掲載されています.
たとえば,

などです.

レコメンデーションを実行するライブラリ/パッケージについて

第1章の「各ソフトウェアで実行可能なタスク」節で,
「Juliaでは,筆者の知る限りレコメンデーションを実行するライブラリは公式的には提供されていません」
と記載しました.
この点について,@chezouさんから,
「JuliaにはNMF.jlがあるのでレコメンデーションを実行できるのではないか」
というご指摘をいただきました.
ありがとうございます!

NMF(Non-negative Matrix Factorization, 非負値行列分解)は行列分解の手法で,レコメンデーションにおいてもよく用いられるようです.
詳細については,以下のブログ等をご参照ください.

このようにレコメンデーションで使用されるものの,第2部特集3で紹介されているナイーブベイズ分類器などと同様に,
必ずしもレコメンデーションに特化しているわけではない手法を実行するライブラリ/パッケージを紹介するかどうかは結構迷いましたが,
結局紹介しない方針を採りました.
一方で,確かに広義には含めた方が良い気がするので,ここで紹介しておきます.

またNMFは,RでもNMFパッケージが,Pythonでもscikit-learnのdecompositionモジュールに実装されています.

== 2015/11/4 追記 ==
kndt84さんに,PythonでNMFを用いてレコメンデーションを実装するには,scikit-learnのdecompositionモジュールのNMFクラスよりも,
nimfaを用いた方が良いのではないかというコメントをいただきました.
ありがとうございます!

kndt84さんのQiitaのページで,crabやpython-recsysとともにnimfaが紹介されています.
Pythonでのレコメンデーション実装についての備忘録

また,以下の記事も参考になります.
PythonのnimfaでNMFを試す
nimfaでNMF

nimfaは,"A Python Library for Nonnegative Matrix Factorization Techniques"とあるように,
まさに非負値行列分解のためのライブラリです.
公式ページの手法一覧表や上記のid: SAMさんのブログにあるように,
NMFの様々な手法が提供されています.
開発者はリュブリャナ大学の研究者や大学院生のようで,2012年にJMLRに論文を書かれています.

Marinka Zitnik and Blaz Zupan,
NIMFA : A Python Library for Nonnegative Matrix Factorization,
Journal of Machine Learning Research 13 (2012) 849-853.
http://www.jmlr.org/papers/volume13/zitnik12a/zitnik12a.pdf

この論文内では,nimfaは以下のメリット

  • モダンなNMFの手法,初期化方法,スコアリング指標を提供している.
  • nimfaは密行列も疎行列も扱える.
  • 部品ベースで実装され,階層的な設計が行われているため,既に実装した手法を組み込みやすい

があると主張されています.
また,関連して,PyMFNMFbioNMFといった行列分解のライブラリとの比較も行われています.

機会があれば,nimfaを使用してMovieLensデータセットなどでレコメンデーションを実行する例について,
別エントリで書ければと思います.

R/Python/Juliaによる統計量の算出・可視化

記事の2章では,R, Python, Julia, Spark MLlibを用いて予測モデルを構築する例を示しています.
刊行記念イベントでもお話ししたように,記事の主要な目的は機械学習のソフトウェアにはどのようなものがあり,
それぞれのメリットとデメリット,そしてどれを選択するのが良いかの指針を示すことにあると考えています.
ただ,これまでの業務経験から文章で話すだけではなく具体例を入れた方が初学者の方にはイメージがわきやすいとも考えており,
2章の例を入れました.

記事の中では特徴量の統計量を算出したり可視化する工程を省略していますが,機械学習アルゴリズムを適用する前に必ず行わなければならない作業です.
また,実際の分析では生のログデータから特徴量を構築する工程も非常に重要です.
ここでは,記事中でも用いたBank Marketingデータセットを対象に,
R, Python, Juliaでそれぞれ統計量の算出や可視化を実行する方法について説明します.

ここでは,以下の3つの処理

  1. データの読み込み(サンプル × 特徴量のテーブル形式のデータを想定)
  2. 1変数の分析:各特徴量(説明変数)の要約統計量の算出,分布の確認
  3. 2変数の関係性の分析:目的変数と各特徴量(説明変数)の相関の確認

について説明します.

1点目のデータの読み込みについては記事中でも説明しています.
2点目,3点目については,以下の表の内容を説明します.

R Python Julia
1変数の分析 要約統計量の算出 summary関数 pandas.DataFrame.describeメソッド describe関数(DataFrames.jl),DataFramesMeta.jl
分布のプロット ggplot2パッケージ pandas.DataFrame.plot, pandas.DataFrame.boxplot, pandas.DataFrame.hist PyPlot.jl,Gadfly.jl
層別集計 by関数 pandas.DataFrame.groupbyメソッド aggregate関数
2変数の関係性の分析 相関係数の算出 cor関数 pandas.DataFrame.corrメソッド cor関数
多変量連関図 pairs関数, ggpairs関数(GGallyパッケージ) 等 pandas.tools.plotting.scatter_matrix, seaborn.pairplot PyPlot.jlを用いた自作関数

なお,OS X 10.10で実行しており,使用したR, Python, Juliaのバージョンは以下のとおりです.

  • R 3.2.2
  • Python 2.7.9
  • Julia 0.3.10

本書執筆後にJuliaは0.4.0が出ましたが,ここでは書籍に合わせて0.3.10を使用しています.

データの読み込み

データの読み込みは記事中でも説明しています.

R

read.csv関数を用いてBank Marketingデータセットを読み込みます.

Python

Pandasのread_csv関数を用いてBank Marketingデータセットを読み込みます.

Julia

DataFrames.jlのreadtable関数を用いてBank Marketingデータセットを読み込みます.

要約統計量の算出

R

各列の要約統計量は,summary関数を用いて算出します.

Python

各列の要約統計量は,DataFrameクラスのdescribeメソッドにより算出できます.

上記を見ればわかるように,DataFrameクラスのdescribeメソッドはデフォルトでは数値の列しか統計量を算出しません.
ここで,DataFrameクラスのオブジェクトのdtypesを見て,各列のデータ型を確認してみましょう.

各列のデータ型は,ageやbalanceなどの数値の項目はint64,
jobやyなどのカテゴリ変数の項目はobjectとなっていることを確認できます.

以上の結果を受けて,describeメソッドのinclude引数に'object'をリストで指定します.
これは,データ型がobjectの項目のみを要約するという指定です.
その結果,カテゴリレコード数(count),ユニーク値の個数(unique),最も出現したカテゴリ値(top)とその頻度(freq)が
各項目に対して算出されることを確認できます.

Julia

DataFrames.jlのdescribe関数を用いて,データフレームの各列の要約統計量を算出します.

数値の項目に対しては,最小値(Min),第一四分位点(1st Qu.),中央値(Median),平均値(Mean),
第三四分位点(3rd Qu.),最大値(Max),欠損値の個数(NAs),欠損値の割合(NA%)が算出されていることを確認できます.
一方で,カテゴリ値の項目に対しては,データ数(Length),データ型(Type),欠損値の個数(NAs),
欠損値の割合(NA%),ユニーク値の個数(Unique)が算出されています.

各列のデータ型は,showcols関数を用いて確認できます.
1列目Col #に列番号,2列目Nameに列名,3列目Eltypeにデータ型,4列目Missingに欠損値の個数が表示されていることを確認できます.

なお,各列のデータ型は以下のようにeltypes関数を用いても確認できますが,
showcols関数を用いた方が列番号や列名などよりリッチな情報が出力されるので個人的には重宝しています.

層別集計

続いて,各説明変数と目的変数の関係を調べてみましょう.
目的変数yが'yes'であるか'no'であるかによって,各説明変数の統計量がどのように異なるかについて確認します.

R

by関数を用いて,目的変数のカテゴリごとに各列の要約統計量を算出します.
集計する対象は目的変数y以外であり,データ項目を選択するためにdplyrパッケージを使用しています.

目的変数のカテゴリ別に特徴量の分布などをプロットするには,ggplot2パッケージを使用すると便利です.

Python

Pythonで層別集計を実行するためには,DataFrameクラスのgroupbyメソッドにより層別に分割し,
その後,適用するメソッドを指定します.
次の例では,目的変数のカテゴリごとに分割し,describeメソッドにより各列の要約統計量を算出しています.

目的変数の値ごとに,数値の項目のヒストグラムをプロットするには,histメソッドを使用します.
layout引数には,図の行数,列数をタプルで与えています.

PythonでもRのggplot2と同様のグラフィクス機能を提供するggplotライブラリが提供されています.
ggplotライブラリは,pipによりインストールします.

$ pip install ggplot

次の例は,目的変数yのカテゴリごとに項目ageのヒストグラムをプロットしています.

Julia

Juliaでは,aggregate関数やby関数等を用いて,集計軸ごとに集計を実行できます.
次の例は,aggregate関数を用いて,quantile関数により数値の項目に対して分位点を算出しています.

出力結果は,

  • 負例は,1行目が最小値, ... , 5行目が最大値
  • 正例は,6行目が最小値, ... , 10行目が最大値

となっています.

カテゴリ値の項目に対しては,aggregate関数やby関数などを用いて,目的変数の値ごとにカテゴリ値を集計します.
以下では,aggregate関数を用いて,countmap関数により各カテゴリのレコード数を集計しています.

Juliaでは可視化のライブラリがいくつか提供されています.

などがあります.
これらの概要については,たとえば以下の資料などがまとまっています.
Graphics in Julia by Andee Kaplan
Introducing Julia/Plotting
また,Gadfly.jl/Immerse.jl, PyPlot.jl, UnicodePlots.jl, Qwt.jlの機能を統一したインタフェースで利用できる
Plots.jlというパッケージも提供されています.

ここではPyPlot.jlとGadfly.jlを用いて,目的変数yのカテゴリごとに特徴量の分布を可視化してみます.

PyPlot.jlは,Pythonのmatplotlib,特にpyplotとの連携に強いインタフェースです.
以下ではsubplot関数で2行1列の図を描くことを指定して,1行目に負例,2行目に正例のageの分布をプロットしています.

Gadfly.jlはRのggplot2パッケージと同様に,"Grammar of Graphics"の理念に基づいて開発されているパッケージです.
以下の例では,plot関数のx引数に描画する項目,ygroupに層別に用いる項目を指定しています.
Geom.subplot_gridの引数にGeom.histogramを与えることでヒストグラムを層別にプロットする指定を行っています.


2変数の関係性の分析

ここでは,2変数の関係性を分析するために,相関係数の算出と多変量連関図をプロットします.

R

相関係数は次のようにcor関数により算出します.

多変量連関図は,pairs関数を用いる方法がありますが,カテゴリ変数を適切に扱っているとは言い難いため,
ここではGGallyパッケージのggpairs関数を使用します.

Python

相関係数は次のようにDataFrameクラスのcorrメソッドにより計算します.

多変量連関図は,pandas.tool.plottingモジュールのscatter_matrix関数を用いてプロットします.

Pandas 0.17.0の時点では,多変量連関図は数値の項目のみに対してプロットされます.
RのGGallyパッケージのggpairs関数のように,カテゴリ変数の項目に対してもプロットされるようにするためには少し工夫が必要です.
この対処は少々紙面を要するため,別エントリで書ければと思います.

なお,多変量連関図については,seabornを用いた方が見栄えが良いかもしれません.
seabornはmatplotlibのラッパとなっており,洗練されたグラフィクスを多数提供します.

まずは,pipコマンドを用いてseabornインストールします.

$ pip install seaborn

seabornのpairplot関数を用いて多変量連関図をプロットします.
ここでは,目的変数である'y'をhue引数に指定することによって色を変えています.

Julia

相関係数は次のようにcor関数により計算します.
cor関数は,データフレームに対してそのままでは適用できないため,convert関数でDataArrayに変換しておきます.

多変量連関図は,ここでは以下のページで定義されているpairs関数を参考にして,自作の関数pairsを作成します.
https://gist.github.com/ahwillia/43c2cfb894f2bfec6760

DSML_my_pairs.jl

こうして定義したpairs関数を用いて多変量連関図をプロットします.

Juliaのデータフレームのハンドリングについては,以下の資料などが役立ちます.

また,以上では紹介できませんでしたが,Juliaで集計やデータ加工を実行するパッケージにDataFramesMeta.jlがあります.
このパッケージを使用すると,Rのdplyrパッケージと同様に,行の抽出,列の抽出,グループ化処理などの操作,
およびこれらの操作をパイプで連結することが可能になります.
2015年4月に行われた第3回JuliaTokyoの@weda654さんのスライドがわかりやすいです.


以上,少々長めになってしまいましたが,何かのご参考になれば幸いです.

*1:「数学も統計もわからないし、難しくて自分にはとても使えない、使いこなせない」という悲観的な神話と「よくわからないけど機械学習の専門家に今データで困っていることは全部解決できそうだ」という楽観的な神話