Web開発におけるコンピュータサイエンス - 機械学習編2

この教科書は、はてなサマーインターンの講義資料として作成されたものです: https://github.com/hatena/Hatena-Textbook


機械学習編1(基礎編)では、最も初歩的な分類器である単純パーセプトロンを題材に、機械学習の基本について勉強しました。機械学習編2(実用編)では、実問題に機械学習を適用する上でのコツや、各種の機械学習アルゴリズムの使い分け、高次元データへの対処法、といったトピックについて解説していきます。

\def\bm#1{\boldsymbol{#1}} \def\set#1{\{#1\}}

実問題に機械学習を適用する

1日目の課題はいかがでしたか?難しかったですか?現実の問題は、1日目の課題とは比べものにならないくらい難しくなります。この章では、そのような実問題に立ち向かっていく方法について解説していきます。

タスクを定義する

まず、あなたの解きたい問題についてよく考えてみましょう。機械学習編1では、以下のような代表的な機械学習タスクを紹介しました。

  • 教師あり学習
    • 分類: カテゴリを予測する
    • 回帰: 数量を予測する
  • 教師なし学習
    • クラスタリング: データを(未知の)グループに分ける
    • 次元削減(次元圧縮): データの特徴量の次元を下げる
    • 頻出パターンマイニング: データから法則性を見つける
    • 異常値検出: データから統計的な外れ値を見つける

まず最初に、あなたの問題が、これらのどの問題に当てはめられそうかを考えてみましょう。

たとえば、数字の画像認識の場合を考えてみます。数量を予測するので回帰問題のように思えてしまうかもしれませんが、これは分類問題にあたります。画像にどの数字が書かれているか を知りたいのであって、5の画像が3の画像よりどれくらい大きいとかいったことには興味はないからです。また、数字は0から9までですので、10クラスの多値分類問題ということになります。

このように、実問題を既存のタスクに結びつけることがまず第一歩です。機械学習で解決できる問題のほとんどが、これらのタスクのいずれかに帰着できます。このステップでは、ものごとを抽象化して考える思考法が重要になってきます。具体的に機械学習で解かれている問題の事例などを知ることで、だんだんできるようになるでしょう。

データを特徴ベクトルに変換する

つぎに、データからなんらかの方法で特徴を抽出し、実ベクトル(実数を要素にもつベクトル)に変換する方法を考えます。多くの機械学習アルゴリズムは実ベクトル空間を前提としています(これとは別に、ナイーブベイズなど、確率モデルを基礎とするアルゴリズムもあります)。ここで変換したベクトルのことを 特徴ベクトル (feature vector) といいます。

このステップでは、問題に対するドメイン知識が最も重要になります。たとえば分類問題の場合では、分類するために重要な特徴量を選ぶのが鍵になります。データをよく観察し、隠れた構造を見出すようにしましょう。

最初から特徴量を完璧に特定しなくても構いません。特徴量は多めに出すようにするのがおすすめです。無駄な特徴量は、この後のプロセスで見つけ出して取り除いてしまうことができるからです(この後の特徴選択の項目で説明します)。

データをベクトルにできればこっちのものです。これで現実の問題を機械学習アルゴリズムの問題に変換することができました!

評価方法を決める

次に、機械学習アルゴリズムをどう評価するかを考えましょう。評価方法の設計はとても大事です。当たり前のことですが、決めた評価軸のなかでしか、得られたモデルの「良さ」は計れません。どのような機械学習アルゴリズムが欲しいかを考えて、評価指標を選ぶようにしましょう。評価指標には、以下のようなものがあります。

  • 適合率 (Precision)
  • 再現率 (Recall)
  • F値 (Fスコア、F_1スコアとも)
  • 混同行列 (confusion matrix)
  • ROC曲線
  • AUC (Area Under the Curve)
  • 尤度・対数尤度 (確率モデルの場合)

一例として、機械学習による分類器を自分たちのWebサービスに組み込むことを考えてみます。たとえば、たくさんの商品のなかから、ユーザに商品をおすすめするレコメンドエンジンを作っているとしましょう。この問題は、教師あり学習における分類のタスクとして定義してみます。つまり、「この商品をユーザが見ているページに出すべきかどうか」を判定する2値分類器をつくることを考えます。このとき、あなたはどんな分類器が欲しいでしょうか?

この問題設定の場合、あまりにたくさんの商品を見せられても、ユーザは選びきれません。できるだけノイズが少ない分類器が望ましいでしょう(実務ではありがちな要求です)。このように、再現率 (recall) よりも、適合率 (precision) を重視したい場面は、開発の現場でしばしば直面します。そういう場合は、適合率寄りのF_\betaスコアを使って評価するとよいでしょう。F_\betaスコアの式は以下の通りです。どこかで見たことのある形ですね。

\displaystyle F_\beta = (1 + \beta^2)\cdot\frac{\text{precision}\cdot\text{recall}}{(\beta^2\cdot\text{precision})+\text{recall}}

実は、F_\betaスコアはF_1スコアの拡張になっています。\beta = 1のときF_1スコアと一致することが確認できますね。

\displaystyle F_1 = 2\cdot\frac{\text{precision}\cdot\text{recall}}{\text{precision}+\text{recall}}

また、\beta = 0のとき適合率 (precision) と一致することも簡単に確かめられます(逆に、\beta \rightarrow \inftyのとき再現率 (recall) に近づきます)。つまり、適合率重視にしたい場合は、\betaを小さくすればよさそうです。どのくらい小さくすればよいかはタスク次第ですが、まずは\beta = 0.5F_{0.5}スコアなどでやってみるとよいでしょう。こうすることで、ある程度の再現率を担保した状態で、適合率を高めた分類器を得ることができそうです。

逆に、商品のR18判定の分類器もつくったとしましょう。多少誤分類があってページに出してもよい商品を落としてしまったとしても、ユーザに不快な思いをさせたり、サービスのブランドを毀損するよりはまし、といった状況もあるでしょう。この場合には再現率が高めのものがほしいので、再現率寄りのF_\betaスコアを使って評価するとよさそうです。たとえば\beta = 2.0F_2スコアなどです。

論文では、平均的に性能がよいアルゴリズム、たとえば AUC やF_1スコアが高いアルゴリズムが一般的には良しとされます。しかし、本当になにが重要かは、実際のタスク・アプリケーションによって異なります。このように、どんな指標で評価するかは、機械学習を使ったプロダクトの品質を保つうえで重要になってきます。

重要なのは、1つの軸で評価する ということです。これにより、ハイパーパラメータの調整など、機械学習のトライ&エラーがやりやすくなります。具体的には、F_\betaスコアやF_1スコア、AUCあたりがおすすめです。

正解データの正例と負例は均等に

2値分類では、学習データのラベルには +1 (正例)と -1 (負例)の2種類の事例があります。このとき、正例と負例ができるだけ同じくらいの数になるように注意します。正例のデータをたくさん持っているなら、できるだけ負例のデータを集めるようにしましょう(アノテーションにおいて、分類器の性能向上に有効なデータを選んでくれる能動学習 (Active Learning) という手法もありますので、興味のある方は調べてみてください)。偏りがあると、望んだ結果は得られません。データのクラス間に極端な偏りがあるようなデータセットのことを、不均衡データ (imbalanced data) とよびます。たとえば、がん検診を2値分類の機械学習で行うことを考えてみましょう。この場合、本当に +1 (陽性)である事例は非常に少なく、 -1 (陰性)であることがほとんどでしょう。だからといって、常に -1 (陰性)と答える分類器が学習されても(見かけ上のスコアは高くなるかもしれませんが)役に立ちません。

とはいえ、そもそもデータを恣意的に選んでアノテーション(正解ラベルを付けること)をすることができない場合もあります(そもそもデータを恣意的に選んでよいかという問題もありますが)。このような場合には、学習アルゴリズムで工夫することもできます。単純パーセプトロンでは、分類を間違えたときに、分離超平面からの距離に応じて重みw_iを更新していましたね。大きく離れている次元iに対しては重みw_iを大きく増やし(もしくは減らし)ていました。そこで、たとえば +1 (正例)が少ない場合には、正例を誤って -1 (負例)と判定してしまったときには、すべての次元に対して、大きく重みを更新することにします。つまり、各クラスのデータ数に応じて重み付けをするということです。正例:負例が1:3なら、正例を間違えたときには、たとえば3倍の幅で更新する、といった具合です。以上はヒューリスティックな方法ですが、分類を間違えた場合の罰則(コスト)を学習アルゴリズムに組み込んだ コスト考慮型学習 (cost-sensitive learning) と呼ばれる、より一般的な学習手法も提案されています。興味のある方は調べてみるとよいでしょう。

不均衡データへのもうひとつの対策法として、機械学習アルゴリズムに与えるデータセットを工夫する方法もあります。例えば少ないほうの事例をオーバーサンプリングする、多いほうの事例をサブサンプリング(アンダーサンプリング)する、またはその両方を実施する、などです。

不均衡データの扱いについては、以下も参考にしてみてください。

ベースラインとなる手法を実装する

機械学習アルゴリズムを実装するときに大事なのは、まず最初に もっとも簡単な方法で実装・実験・評価を行う ことです。最初は次元削減などの高度な処理もせずに、ナイーブにやってみることを心がけましょう。ここで出てきた結果がベースラインとなり、この後により高度な手法を試すときに、どれくらい良くなっているのかを定量的に比較することができます。

ベースラインを実装したときに、あまりにも性能が低いときは、タスク設定自体を疑いましょう。難しすぎる問題を解こうとしていないでしょうか。たとえば、自然言語処理は近年急速に発展してきましたが、ことばの意味を扱うようなタスクでは苦戦しています。二値分類問題で正例・負例がそれぞれ半分ずつのテストデータに対して、正解率 (accuracy) が 0.5 しかない(50%しか当たらない)ようであれば、コイン投げと同じようなものなので、問題設定自体を考えなおしたほうがいいかもしれません。

また、ベースラインを実装、評価してみることで、データの量が少ない、特徴ベクトルに有効な特徴が含まれていない、などの問題に対してもある程度当たりをつけることができます(機械学習編1の 学習曲線による分析 も参照)。

さらに、より複雑な手法を実装した際にバグを入れてしまった場合、より早く気付くことができます。少しずつ工夫を足していって、性能の向上を積み重ねていくようにしましょう(ただし実際には、複雑な手法でほんの少し精度が上がるより、実は簡単な手法のほうが予測が速かったり、メンテナブルであったりして有用なこともあります)。

実データに向き合うときの心構え

現実のデータは汚いです。思った以上に汚いです。なにか精度が出ない、といったときには、エラー分析が大事になってきます。うまくいかないからといって機械学習アルゴリズムを変えるまえに、実際のデータを見てみましょう。どのような事例で誤分類しているかを観察してみます。変なデータが混ざっていたり、前処理にバグがあるのを見つけられるかもしれません。

それに関連して、前処理しても必ず生データは捨てないようにしましょう。前処理を失敗していたときにまたデータを取得するところからやり直しになってしまいます。

また、トライアンドエラーするときには、ある程度前処理した中間ファイルを使ってもよいでしょう。中間ファイルを使うことで、時間がかかる前処理をスキップすることができます(ただし、そのぶん管理は多少煩雑になります)。

生データや中間ファイルの管理法については、以下のエントリーが参考になるでしょう。

機械学習のワークフロー

前の章では、実問題を扱ううえでのいくつかのトピックを紹介しました。ここでは、実際に何をどのような順番で進めていくかについて、ざっと俯瞰していきます。大まかには、以下のようなステップで進めていくことになります。

  1. 前処理
    • データセット作成
    • サンプリング
    • 特徴抽出
    • 欠損値対応
    • スケーリング
    • 特徴選択
    • 次元削減
  2. 学習
  3. 評価・改善
    • 学習曲線を描画
    • エラー分析と対策
  4. 適用
    • システムへの組み込み

機械学習アルゴリズムに入力されるデータセット(実ベクトルからなるデータの集まり)を作成・加工するのが 前処理 (preprocessing) と呼ばれるフェーズです。そのデータを学習アルゴリズムに入力し、学習済みのモデルを得るフェーズが2つめの 学習 フェーズです。次に、得られたモデルの 評価(evaluation) を行います。ここで、満足する結果が得られなければ、前処理もしくは学習フェーズでの条件を変えて、再度評価を行います。これが 改善 のフェーズです。ここでは、なぜうまくいかなかったかを自分なりに分析し、対策を考えるのが重要になります。評価・改善の結果、求める性能が得られれば、実システムへの 適用 を行います。また現実には、この後にも運用のフェーズが必要になることが多いと思いますが、その方法は個別の事例ごとに大きく異なるため、ここでは扱いません。

参考: Python 機械学習プログラミング 1.7 機械学習システムを構築するためのロードマップ および 6.1.2 パイプラインで変換器と推定器を結合する

1. 前処理

データセット作成

まず最初に、データセットを作成する必要があります。自分たちのデータを使う場合には、それを取得します。RDBにデータが入っているなら、SQLでデータを抽出することになります。逆に、自分たちでデータを持っていない場合には、データの持ち主にお願いしてデータを送付してもらう、クロールする、などの作業が必要になります。

また、実際には、取得した生データに対してなんらかの加工をすることが多いでしょう(テキストの場合には Unicode 正規化や、Webページを対象にする場合には、 HTML タグの除去や本文抽出をするなど)。この部分が性能に大きく影響することもあるので、正しく抽出・加工ができているか確認してから次に進むようにしましょう。

サンプリング

作成したデータセットをランダムサンプリングし、訓練セット (training set)テストセット (test set) の2つに分割します。訓練セットというのは、実際に機械学習アルゴリズムの学習に使うデータセットのことです。もう1つのテストセットは、学習した結果であるモデルのよさを評価するためのデータセットです。

どのくらいの割合をテストセットにするかは、自明ではありません。訓練にはできるだけたくさんのデータを使いたいのですが、テストセットの数が少なくなってしまうと評価結果が信頼できないものになってしまいます。データセット全体がどのくらいの量かにもよるので一概には言えませんが、一般的な目安としてはテストセットにはデータセット全体の1割〜3割くらいを使うことが多いと思います。このように、データセットを2つに分割し、一部をテストセットとする方法を ホールドアウト法 (holdout method) と呼びます。

より発展的な方法として、 交差検証 (cross-validation) があります。 k分割交差検証 (k-fold cross-validation) は、データセットをk個に分割し、そのうちの1つをテストセット、残りを訓練セットにします。この設定で評価したあと、k個のうち、別のものを選んで、それをテストセット、残りを訓練セットにします。これをk回繰り返すことで、すべてのデータがテストデータとして1回ずつ選ばれることになります。k回の評価結果の平均を最終的な評価結果とします。こうすることで、テストセットの選ばれ方による影響をできるだけ排した、より公平な評価が可能となります。データ数をNとしたとき、k=Nの場合のk分割交差検証を Leave-one-out交差検証 (Leave-one-out cross-validation, LOO または LOOCV) と呼びます。

kの選び方はデータ数やコンピューティングリソースによって変わってきます。kを小さくすると誤差が大きくなって結果が信用できなくなりますが、逆にkを大きくするとその回数だけ学習・テストを繰り返すわけですから、実行時間が長くなります(ただし分散実行は可能です)。つまり、評価結果の信頼性とコンピューティングリソース(計算時間)とのトレードオフになるわけです。データが少ない場合は、計算時間はそれほど問題ではなく、逆にデータが少ないことによる評価結果のばらつきは大きくなるため、kを大きく(理想的にはLOO)するのがよいでしょう。逆にデータが多い場合にはkを小さくして、現実的な時間で計算が可能な範囲とします。kの選び方と評価結果のばらつきについては、以下のエントリーで詳しく考察されていますので、ぜひ参考にしてみてください。

特徴抽出

機械学習アルゴリズムに入力するためには実ベクトルにする必要があります。非ベクトルのデータの場合(テキスト・画像・音声など)は、 なんらかの方法で 特徴ベクトルに変換します。

このとき、できるだけデータの性質をよく表すようなベクトルにしてあげると、結果として得られるモデルの性能が向上します。実は、この特徴抽出が最も精度に影響する部分といっても過言ではありません。

当然、データやタスクによって特徴抽出の方法はまったく異なります。テキスト(自然言語)の場合、単語分割が必要になりますし(あとの 自然言語処理 (NLP) と機械学習 の章で詳しく説明します)、画像処理の場合、 SIFT や SURF などの画像特徴量を使う方法が伝統的によく用いられています。

欠損値・欠測値への対応

データがそもそもない、計測の失敗などの原因で、 欠損値・欠測値 (missing value) が発生することがあります。これらに対してどのように対処するかも大事なトピックです。どのように扱えばよいかはタスクの性質にもよりますが、以下のような方法が取られることが多いです。

  • 欠測値をもつデータを削除 (drop)
  • 欠測値を補完 (interpolation/imputation)

詳しくは、朱鷺の杜の以下のエントリーが参考になるでしょう。

値のスケーリング

ここまでで、実ベクトル(特徴ベクトル)が得られました。ほとんどの機械学習アルゴリズムは、与えられたベクトルの次元ごとに値のスケールがバラバラだと、性能を発揮できないことが知られています(たとえば、ベクトルの中のいくつかの要素だけ異常に値が大きいとか)。具体的には、学習が収束するまでにすごく時間がかかったり、得られたモデルの精度が悪かったり、といった弊害があらわれます。詳しく知りたい方には、参考として以下を挙げておきます。

対処法としては、すべての次元でだいたい同じような値の範囲になるよう、スケール変換(スケーリング)することが挙げられます。現実的には、以下の2つの手法のどちらかが使われることが多いです。

  1. 標準化 (standardization)
    • 平均 0 分散 1 にスケーリング
    • Z-score によるスケーリング
    • 以下の計算式で Z-score を計算する
      • \displaystyle z = \frac{x - \mu}{\sigma}
    • 外れ値の影響が小さい
  2. 正規化 (normalization)
    • [0, 1]などの固定の範囲にスケーリング
    • 最小値が0、最大値が1になるように
    • Min-Max スケーリングとも呼ばれる
    • 値が特定の範囲内に入っていることが必要な場合
    • 以下の式で正規化する
      • \displaystyle x_{norm} = \frac{x - x_{min}}{x_{max}}

スケーリングについては、以下のエントリーが詳しいです。

特徴選択

得られた特徴ベクトルは、特徴量の設計次第では非常に高次元になる(ベクトルの要素数が多い)ことがあります。特徴ベクトルが高次元になると、学習に多くの計算リソースを要したり、過学習が起こりやすくなったりします。これらの特徴量(次元)のうち、重要なものだけを残す手法が 特徴選択 (feature selection) です。

特徴量の選択は、一般には組み合わせ最適化問題になります。特徴空間の次元数をNとすると、その取りうる組み合わせは2^{N}です。その中から、最適な組み合わせを選ぶことになります。特徴空間が高次元の場合、とりうる組み合わせは膨大な数となり、ナイーブな方法では計算量が爆発して実行不可能です。

そこで、通常は貪欲法で特徴選択を行うことになります。これは、何らかの関数を使って、各特徴量(各次元)に対して重要度を計算し、重要度が最大の特徴量を順番に選んでいく方法です(参考:Python 機械学習プログラミング 4.5.2)。

ランダムフォレスト (Random Forest) という機械学習アルゴリズムを使って特徴量の重要度をランク付けすることもできます(参考:Python 機械学習プログラミング 4.6 ランダムフォレストで特徴量の重要度にアクセスする )。逆にいうと、ランダムフォレストは特徴選択が組み込まれた学習アルゴリズムと考えることもできます。)

特徴選択についてさらに詳しく知りたい方は、 統計的学習の基礎 pp.69- 3.3 変数選択 を読んでみてください。

次元削減

次元削減 (dimension reduction) は、高次元な特徴ベクトルを低次元なベクトルに変換する手法です(たとえば数千次元のデータを数十次元に圧縮するなど)。次元の呪い(特徴空間が高次元だと学習がうまくできない現象)による影響が緩和されて、精度が向上することがあります。また、学習の高速化・省メモリ化も期待できます(もちろん、次元削減のための計算は余分に必要になります)。ただし当然、予測するときもベクトルの変換が必要になることに注意しましょう。学習結果の解釈も難しくなります。

他にも、可視化という応用もあり、2次元〜3次元に次元削減することで図にすることができます。高次元データを目で見ることができるようになるため、データの特徴をつかむことができるかもしれません。

2. 学習

実際に訓練データを与えて学習させるフェーズです。前処理フェーズでも、この学習フェーズでも、 テストセットのデータを使ってはいけないことに注意 しましょう(テストセットを見てしまうことは、テストでカンニングをしている、つまりズルをしていることになります)。

モデル選択(ハイパーパラメータの調整)

学習アルゴリズムには通常、ハイパーパラメータ(最適化の対象となるモデルのパラメータとは別のパラメータ)が存在します。たとえば、機械学習編1の パーセプトロン の節で解説した、単純パーセプトロンの学習率\etaがそれです。他にも、学習アルゴリズムに正則化を導入した場合の正則化パラメータや、ニューラルネットワークの層の数や各層のユニット数もハイパーパラメータといえます。学習フェーズでは、ハイパーパラメータを指定する必要がありますが、どんな値を使えばよいかは、データセットによって異なります。ハイパーパラメータの選択は、一般には モデル選択 (model selection) という分野になります。

試行するパラメータの選び方

一般に、とりうるハイパーパラメータの組み合わせは無限にあります。ハイパーパラメータのパターンを選択する方法には、以下のようなものがあります。まずは最も基本的でわかりやすいグリッドサーチから試してみるとよいでしょう。

  • グリッドサーチ (Grid Search)
    • 各ハイパーパラメータの範囲を指定し、それらの組み合わせのパターンをすべて試行する
    • ハイパーパラメータが2つあり、それぞれ5パターンずつ試行するとしたら、5x5=25通りのパターンを試行する
  • ランダムサーチ (Random Search)
    • 各ハイパーパラメータについて、ランダムな値を選択する
  • ベイズ最適化 (BO; Bayesian Optimization)
    • ハイパーパラメータを選択し、得られた評価結果から、よいと思われるハイパーパラメータを自動選択して試行する
    • この教科書の範囲を超えているため、興味のある方は各自で調べてみてください
    • 「ベイズ最適化」でGoogle検索

検証セット

ハイパーパラメータ選択の最もナイーブなアプローチは、いくつかのパラメータの組み合わせで実際に訓練セットで学習してみて、訓練セットに対する評価がもっとも良かったもの(訓練誤差が小さいもの)を選択するという方法です。しかし、このナイーブな方法には問題があります。特定の訓練セットに対して結果がよかったからといって、他のデータ、たとえばテストセットに対して良い性能が得られるとは限らないからです。

機械学習編1の 訓練データとテストデータ の節で説明したとおり、私たちの目標は汎化性能の高いモデルを得ることです。そこで、訓練セットをさらに2つに分割し、1つを 検証セット (validation set) 、残りを訓練セットとします(検証セットは開発セット (development set) とも呼ばれます)。ハイパーパラメータの組み合わせに対して、検証セットを選んだ後に残った訓練セットで学習したあと、検証セットで性能を評価します(このようにデータセットを2つに分割することをホールドアウト法というのでした)。検証セットを見ないで学習したことで、汎化性能の高いモデルとハイパーパラメータの組み合わせを得られることが期待できます。

モデル選択における交差検証

検証セットを使ったハイパーパラメータの選択にも、もう1つ問題があります。検証セットは訓練セットの一部しか使っていないため、ある意味で公平な結果とは言えないからです。ここでも交差検証の手法が役に立ちます。k分割交差検証を使って検証セットを選ぶことで、よりよいハイパーパラメータを得ることができるでしょう。なお、試すハイパーパラメータを10パターン、テストセットの選択に10分割交差検証、検証セットの選択に5分割交差検証を使った場合、500回の訓練・テストを繰り返すことになります。このように交差検証を組み合わせる方法を 入れ子の交差検証 (nested cross-validation) と呼び、この場合は、10x5交差検証となります。このスキームについては、Python機械学習プログラミング 6.4.2 入れ子式の交差検証によるアルゴリズムの選択 に詳しく書かれています。

3. 評価・改善

評価方法を決める で決定した評価指標で、取っておいたテストセットに対して評価を行います。求める性能に達しなかった場合には、なんらかの対策を打つことになります。

テストセットのデータに対する前処理

このフェーズでは、とっておいたテストセットを使って評価をしますが、このとき、スケーリングや特徴選択、次元削減のパラメータは、前処理フェーズ・学習フェーズで得られたものを使うことに注意しましょう。逆に言うと、繰り返しになりますが前処理フェーズ・学習フェーズではテストセットのデータを使ってはいけません。スケーリングなどの前処理も含めてモデルであると考えるとよいでしょう。

エラー分析と改善のプロセス

評価した結果、満足いく性能が得られなければ、何らかの工夫をする必要があります。

  • 特徴量を見直す?
  • データを増やす?
  • モデルを変える?
  • 学習アルゴリズムを変える?

学習曲線を見たり、エラー分析をするのが対策の第一歩です。学習曲線については、機械学習編1を参照してください。エラー分析では、実際にエラー(false positive/false negative)になっているインスタンス(事例)を見てみるのが重要です。そもそもデータそのものにノイズが多い、なども考えられます。たとえば、ラベルを付ける人の基準がぶれていた、といったことが見つけられるかもしれません。このような場合、データセットのタグ付け(教師ラベル付け)を見直してみる、などの打ち手が考えられるでしょう。

機械学習アルゴリズムのデバッグ

まずは、学習曲線を見て、イテレーション数に応じて誤差が減っていることを確認しましょう。減っていかない場合、どこかにバグがある可能性が高いです。機械学習アルゴリズムのデバッグは難しいですが、根気強く頑張りましょう。

パラメータの値が途中で発散している場合、以下を確認しましょう。

  • 更新式がちゃんと実装されているか
  • 計算誤差の問題が起こっていることも
  • そもそも更新式の導出(手計算)が間違っていることも

とくに更新式の実装のバグは、一見正しく動いているように見えたりして非常に気付きにくいので注意しましょう。他に、機械学習アルゴリズムを実装するときのコツとしては、細かくテストする、既存のライブラリによる実装と結果を突き合わせてみるなどがあります。また、既存実装のソースコードを読むのも勉強になります(とくに scikit-learn は様々な機械学習アルゴリズムをサポートしており、コードも読みやすくおすすめです)。

4. 適用

システムへの組み込み

Web開発においては、機械学習アルゴリズムはシステムに組み込まれ、運用されることで価値を発揮します。この後の 機械学習プログラミング の章で詳しく説明していきます。

機械学習プログラミング

ここまでで、機械学習を使った開発の進め方について、ある程度イメージできたと思います。ただ、これらを実行するためには、なんらかのプログラミングをする必要があります。

これを読んでいる方は、いくらかのプログラミングの経験があると思いますが、機械学習を実際のサービスに適用するとなると、通常のWebプログラミングにはない特有のポイントがあります。この章ではそのうちの一部のトピックを紹介します。

機械学習に使われるプログラミング言語

まずは、どの言語で実装するかを決めなければなりません。大きくは、プロトタイピングによる試行錯誤に向いている言語と、サーバサイドやバッチで実行するのに向いている言語の2つに分けられます。

  • プロトタイピングに向く
    • R, Python, Octave/MATLAB
  • 実運用、ハイパフォーマンス用途に向く
    • Scala, Java, C, C++

R, Python, Octave/MATLABはインタプリタで対話的に実行できることや、機械学習・統計・科学技術計算のライブラリが豊富なこともあり、多くのトライアンドエラーを行う、機械学習を使った開発では非常に有用です。一方、サーバサイド(バックエンド側)で運用するには、比較的パフォーマンスの問題が起こりやすいため、プロトタイピングして実用性を評価したあと、本番環境の言語(たとえばJavaなど)で実装しなおして組み込まれることもしばしばあります。

Scala, Javaはサーバサイドに組み込むには良い選択肢だと言えます。C, C++には一歩及ばないものの、パフォーマンス面でも問題ありませんし、かっちり実装するにはもってこいです。

C, C++は非常に高速な反面、メモリ管理やバグに悩まされるかもしれません。科学技術計算系のライブラリは利用しやすいので、機械学習アルゴリズムをスクラッチで組むには良いでしょう。また、多くの言語でCやC++で書かれたコードを呼び出す仕組みがありますので、コア部分のみCやC++で実装するアプローチも有効です。

機械学習に関して、現状もっともエコシステムが発達しているのはPythonでしょう。機械学習フレームワークのscikit-learnはデファクトの地位を築きつつあります。一方、R もライブラリが充実しています。どちらかというと、機械学習よりも統計的な手法に強いイメージがあります。

また、最近では書きやすさを保ちつつ高速な処理を実現したJuliaも登場しており、今後注目です。

その他の言語やフレームワークについては、以下の書籍が参考になります。さらに、R, Python(scikit-learn), Julia, Spark/MLibによる学習と予測について、具体的なコードが掲載されていますので、それぞれの雰囲気を掴むのによいでしょう。とくにscikit-learnについては実例が豊富です。

  • データサイエンティスト養成読本 第2部

大規模データの取り扱い

データセットが大きくなると、コモディティーな計算機ではメモリに乗り切らなくなります。これでは学習ができません。どうすればいいでしょうか。

一般的な解決策は、メモリ使用量が、データサイズに比例しないようなプログラムにすることです。たとえば、バッチ学習ではデータセット全体をメモリに乗せるため、巨大なデータセットでは学習途中でメモリが枯渇して異常終了してしまうでしょう。この場合、オンライン学習を検討しましょう。オンライン学習やミニバッチでは、データを少し読み込んだあと、そのデータを捨てる(=メモリから解放する)ことができます。他にも、機械学習アルゴリズムによっては大規模な問題に対応した拡張があったりしますので、適宜調べてみてください。

さらに大規模なデータセットを取り扱いたい場合には、ミドルウェアやクラウドサービスを利用することを考えましょう。

ミドルウェアと機械学習での用途

ここでは、機械学習を使った開発で利用することになるかもしれないミドルウェア・クラウドサービスと、考えられるそれらのユースケースを紹介します。ここで挙げた以外にもたくさんのミドルウェアが存在し、これからも増えていくでしょう。

リレーショナルデータベース(RDB)

データの格納・インデックスを使った検索ができます。信頼性が高く、運用も行いやすいため、データの格納場所としては第一の候補になるでしょう。ただし、大規模構成ではそれなりにノウハウが必要になります。また、フルスキャンするような用途には向きません。

全文検索エンジン

自然言語テキストの格納・検索に向いていますが、数値や位置情報などテキスト以外のデータを格納・検索することもできます。テキストの検索が高速に行えるため、自然言語処理(NLP)用途ではRDBよりもこちらが優れています。とくにElasticsearchはAggregationという機能で複雑な集計が高速に行えるため、応用範囲が広く、実際にはてなブックマークでも様々なところで使われています。ただし、全文検索エンジンはあくまでインデックスという位置づけのため、データをロストしないためにもRDBに置いた上で利用するのがよいでしょう。

分散処理フレームワーク

Hadoopは巨大なデータをフルスキャンするような重いI/Oのバッチ処理でも、分散処理することで比較的高速に捌けるという利点があります。Hadoopの上で動作するApache MahoutHivemallという機械学習ライブラリがあります。たくさんのマシンで学習を分散処理できるため、学習時間が問題となる場合は検討してみるとよいでしょう。

一方、Sparkも分散処理フレームワークですが、こちらはオンメモリでの処理が得意という違いがあります。また、Sparkの上で動作するMLibというライブラリには、多くの基本的な機械学習ライブラリが実装されています。Mahoutと同じく、学習を分散処理できますが、こちらはスループットよりレイテンシを重視する用途に向いています。

Jubatusはオンライン学習向けの機械学習フレームワークです。複数のマシンでそれぞれ学習を行い、それらの学習モデルを交換・共有することで、学習の分散処理を実現しています。

クラウドストレージ

クラウド上にファイルのアップロード・ダウンロードができます。実験用のデータセットや、学習済みのモデルファイルを置いて配布したりするのに便利です。転送量に対して多く課金されるため、重いデータを頻繁に出し入れするには向いていません。

機械学習アルゴリズムをミドルウェアに載せる

メモリに載りきらない大規模なデータに対しては、ディスクを使う(もしくはApahe Sparkのように複数のコンピューターで分散処理する)必要があります。通常、なんらかの既存のミドルウェアを利用することになると思います。自分でミドルウェアのようなものを作るのは、メンテナンスコストなど、労力に対してペイしないでしょう。

上で紹介したMLib, Mahout, Hivemall, Jubatusのように、ミドルウェアを活用した機械学習フレームワークも多数登場しています。ただし、自分たちが使いたい機械学習アルゴリズムが実装されていないこともあるため、その場合は自分たちで書く必要があります(多くの機械学習フレームワーク・ライブラリはオープンソースです)。

機械学習アルゴリズムをミドルウェアに載せるための方法論はケースバイケースで、自明ではありません。プロダクトやそれぞれの環境によって最適解は異なります。ミドルウェアも年々進化していますし、新しいものもどんどん出てきています。アーキテクチャの選定においてもっとも大事なのは、バランス感覚です。

  • 学習・実行、それぞれの時間的・空間的計算量は?
  • 運用時の計算機環境(リソース)は?
  • メンバーの持っているスキルは?
  • そのソフトウェアのコミュニティーは活発か?

これら以外にもさまざまなパラメータがあるでしょう。あなたの腕の見せ所です。

代表的な機械学習アルゴリズムの紹介

この章では、代表的な機械学習アルゴリズムの名前を紹介します。それぞれのアルゴリズムの詳細については説明しませんので、これらを実際に適用したり、他の高度な手法を探すときには、ここに書かれたキーワードやリンクから各自調べてみてください。

教師あり学習

  • 線形モデル
    • 単純パーセプトロン, 線形SVM, ロジスティック回帰(MEM)
  • 非線形モデル
    • (多層)ニューラルネットワーク, 決定木
  • 事例(インスタンス)に基づく手法(モデルのなかにデータが含まれる)
    • k-NN, 非線形SVM (ref. 言語処理のための機械学習)

教師なし学習

  • クラスタリング
  • 次元削減
    • PCA, kernel PCA, ICA, SVD(特異値分解), NMF, MDS(多次元尺度構成法), t-SNE
    • (NLP 系) LSA/LSI, pLSA/pLSI, LDA
    • 参考: すべてがMFになる - Fire and Motion SVD, PCA, CUR, NMF あたりのまとめ
  • 頻出パターンマイニング
    • アプリオリアルゴリズム
  • 単語の表現学習(NLP での次元削減)

アンサンブル学習

  • バギング
  • ブースティング
    • AdaBoost
  • ランダムフォレスト

機械学習アルゴリズムの使い分け

前の章で、たくさんの機械学アルゴリズムを紹介しました。この中から、あなたの問題に合わせたアルゴリズムを選択しなければなりません(もちろん、複数の機械学習アルゴリズムを組み合わせて解くこともできますが、まずは1つずつ試してみましょう)。ここでは、どういうときにどのアルゴリズムを選択するかの指針を紹介します。

まずは、あなたのタスクの設定を振り返ってみてください。どんな機械学習アルゴリズムを使えばいいか、おおまかには絞り込めるはずです。

  • データセットは教師あり?教師なし?
  • タスクは分類?回帰?クラスタリング?次元削減?可視化?

次に、機械学習アルゴリズムの特性や得意分野で選びます。万能のアルゴリズムは存在しません。どんな機械学習アルゴリズムにも、不得意な領域は存在します(このことをノーフリーランチ定理といいます)。目的に合わせて手法を選ぶようにしましょう。たとえば、以下のような基準があります。

  • データ量・次元数は多い?少ない?
  • 欠損データ・ノイズは多い?少ない?
  • モデルが出した結果の説明性は必須?

実際にどれを選べば良いかについては、利用しようとしているフレームワーク・ライブラリのドキュメントが参考になるでしょう。たとえば、scikit-learnAzure Machine Learningには、チートシートとよばれるマニュアルが提供されており、それに従って機械学習アルゴリズムを選べるようになっています。

また、統計的学習の基礎 10.7 データマイニングの「万能」手法 (p.401) にも、いくつかの機械学習アルゴリズムについて、特徴がまとめられています。

機械学習の研究の最先端では、どんどん新しい手法が発見されていますが、実務では、複雑で性能のよいアルゴリズムより、性能は少し劣っても単純なアルゴリズムが好まれる傾向にあります。実運用で求められる要件は、以下のようなものです。

  • 数パーセントの精度より運用のしやすさ
  • 精度が安定している
  • 予測が速い(サーバー費用の削減・応答速度の向上)
  • アルゴリズムの理論や実装が簡単(バグがあったときに原因を見つけやすい・メンテナンスしやすい)
  • あとから手で微調整しやすい

複雑だが性能のよいアルゴリズムを検討するとき、上記の要件と照らし合わせて、本当にその精度・パフォーマンスが必要なのか、よく考えてみることが大事です。あとであなたや同僚が困らないように。

自然言語処理(NLP)と機械学習

この章では、自然言語処理(NLP)の概要と、そこで必要になる特有のテクニックを紹介します。

代表的な自然言語処理タスク

さまざまな自然言語処理タスクで機械学習が応用されています。たとえば以下のようなタスクです。

  • 文書分類(スパム判定など)
  • 文書要約
  • 情報抽出
  • 著者推定・属性推定(性別推定など)
  • かな漢字変換
  • 情報検索
  • 情報推薦(レコメンド)
  • 評判分析
  • 音声認識
  • 機械翻訳
  • 質問応答
  • などなど

このような応用以外にも、自然言語処理には要素技術となる基礎的なタスクがあります。代表的なものは以下です。

  • 形態素解析(分かち書き)
  • 構文解析
  • 述語項構造解析
  • 意味解析
  • 照応解析
  • 共参照解析
  • 語義曖昧性解消(多義性解消)
  • 固有表現抽出 (NER; Named Entity Recognition)
  • 関連語・類義語抽出
  • キーフレーズ抽出
  • など

これらの基礎的なタスクでも機械学習が利用され、性能の向上に成功しています。こうして学習されたものは、ツールとして公開されていることが多くあります。代表的なものに、日本語の形態素解析を行うMeCabや、係り受け解析を行うCaboChaがあります。

自然言語処理の要素技術は、より応用的な自然言語処理タスクに使われることがしばしばあります。たとえば、文書分類には形態素解析した結果を使うことが多いです。ただし、要素技術・応用という区分は相対的なものであり、要素技術となっているものの中にも、他のさらに基礎的な要素技術を使うものもあります。たとえば構文解析や固有表現抽出には、形態素解析の解析結果を使うことが一般的です。このように、自然言語処理タスクでは、いくつかの技術をパイプライン的につなげて処理することがしばしばあります。

自然言語処理の概要については、以下のスライドが参考になるでしょう。

自然言語処理関連の書籍については、以下がよくまとまっています。ここに書かれているアドバイスを参考にしつつ、あなたのバックグラウンドや興味に応じて選ぶとよいでしょう。

BoW (Bag of Words)モデル

機械学習では、データを特徴ベクトルに変換することが必要でした。ここではテキストをベクトル表現するための一般的な方法である BoW (Bag of Words)モデル を解説します。

BoWモデルは、文書分類などのNLPタスクでよく使われる文書(テキスト)の表現です。テキストをただの単語の集まり(= Bag of Words)としてモデル化します。つまり、 単語の順番は区別しない というところに特徴があります。

  • Pros: 文書(テキスト)をコンパクトなベクトルで表現できる
  • Cons: この表現方法では「キャベツ/太郎/が/好き」と「太郎/が/キャベツ/好き」を区別できない(「キャベツ太郎」が辞書にない場合)

テキストのモデル化について、より詳しくは以下の書籍を参考にしてください。

  • 言語処理のための機械学習入門 2章 文書および単語の数学的表現

テキストの前処理

テキストを特徴ベクトルに変換するためには、以下のようなステップが必要になるでしょう。

  1. 文字単位の正規化
  2. 単語分割
  3. 単語単位の正規化
  4. ストップワード除去

ここでは、これらのステップを1つずつ解説していきます。テキストの前処理全般に関しては、以下を参考文献として挙げておきます。

文字単位の正規化

一般に、文字の意味としては同じでも、複数の内部表現(文字のマッピング)が存在することがあります。たとえば、「カ+゛(濁点)」と「ガ」は意味は同じですが、2つの内部表現を組み合わせたものと、1文字で表したもの、という違いがあります。「US(全角)」と「US(半角)」は全角文字と半角文字で、これも内部表現としては異なります。

文字の内部表現としては、Unicodeが広く使われています。文字の正規化ではUnicode正規化、とくにNFKCによる正規化がおすすめです。たとえばNFKCで正規化することで、以下のように内部表現が異なった2つの文字列を、同じものとして扱うことができます。

  • 「カ+゛(濁点)」->「ガ」
  • 「US(全角)」->「US(半角)」

ただ、文字の表記(全角・半角の違いなど)が重要になるようなタスクであれば、このような文字の正規化をすると精度が下がってしまうかもしれませんので注意してください。

Unicode正規化がどういうことをやっているか、またNFKC以外の正規化にどういうものがあるかを知りたい方は、以下の文書を参照してください。

単語分割

すでに見てきたように、テキストをBoWモデルで表現するためには、テキストの文字列を単語に分割する必要があります。この処理を 単語分割 、もしくは分かち書き、トークナイズといいます。

英語の場合は、ホワイトスペース(空白文字)で区切ればよいので、それほど難しい処理ではありません。

日本語のように、単語が明示的に分かれていない言語の単語分割には、形態素解析器を利用することが一般的です。詳しくはこのあとで説明します。有名な形態素解析器には、MeCab, Kuromoji, JUMAN, KyTea, Rosettaなどがあります。

単語単位の正規化

単語単位で正規化する方法には、大きく分けて以下の2種類があります。

  1. ステミング(語幹の取り出し)
    • 英単語のステマー Porter stemmer / Lancaster stemmer / Snowball stemmer など
    • 英単語特有のルールを使って語幹を取り出す
    • 例: runs / ran / runner -> run
    • ルールベースなので高速
    • 誤爆もある(例:international -> intern など)
  2. 見出し語化 (lemmatization)
    • 複数形を単数形になど、単語を基本形に戻す
    • 文脈も考慮して処理される
    • そのぶん、処理は少し重くなる

ただし、繰り返しになりますが、実際にこれらのどの正規化を採用するか(もしくは正規化しないか)はタスク依存です。タスクの意味や、データをよく観察して決定するようにしましょう。

日本語の単語分割/形態素解析

ここでは日本語テキストに限定した前処理について説明します。形態素解析 (morphological analysis) は、以下の複数のタスクを同時に解きます(英語では別々に行っていることが多い)。

  • 単語分割 (tokenize)
  • 品詞タグ付け (POS tagging)
  • 見出し語化 (lemmatization)

日本語テキストの前処理において、単語分割だけを行うのがいいのか、品詞の情報まで使ったり原形復元まで行うのがいいかは、タスク依存です。 形態素解析で得られる情報にはたとえば以下のものがあります(ただし形態素解析器が使っている辞書によって、得られる情報は異なります)。

  • 見出し語(表層形) (surface form)
  • 品詞 (POS; Part of Speech)
  • 原形 (basic form)
  • 読み (reading)

kuromoji.js のデモで形態素解析がブラウザで試せます。形態素解析の雰囲気を知るにはちょうどよいでしょう。なお、辞書にはIPADicが使用されています。

形態素解析(単語分割)のアルゴリズムについて詳しく知りたい方は、以下のスライドを読んでみてください。

ストップワードの除去

ストップワード (stop words) の除去とは、a, the, isなどの頻出語を除去する処理のことです。

明示的にストップワードを列挙した辞書を用意する方法と、品詞情報を使って、たとえば助詞(日本語の場合)や冠詞(英語の場合)の単語をすべて除去する方法があります。もちろん、これらを組み合わせることも有効です。ただし後者の方法は、前のステップで品詞タグ付けが行われていることが前提です。

ストップワードのような単語を無視することで、よりテキストの内容にフォーカスしたモデル化が実現できるため、精度の向上が狙えます。また、モデル自体がコンパクトになるため、学習や分類のパフォーマンス向上も期待できます。

またまた繰り返しになってしまいますが、ストップワード除去も、やっていいかどうか、もしくはどこまでやるかはタスク依存です。文書分類では、ストップワードを除去して内容語に注目して行うと、性能が上がることが多いです。

テキストをBoWモデルで特徴ベクトルに変換する

以上のステップで前処理を行って、テキストを単語の集合にすることができたとします。さて、これを具体的にどんな特徴ベクトルにすればよいでしょうか?

BoWモデルでは、1つの単語が1つの次元に対応します。次元の順番は適当に決めて大丈夫です。単語にIDを振り、単語IDと特徴ベクトルの次元とを対応づけるのが一般的です。ここで作った単語とIDの組のことも、 辞書 (dictionary) と呼びます(自然言語処理では辞書という単語が、文脈によっていろいろな意味で使われるので注意してください)。学習・予測それぞれにおいて、一貫して同じ辞書を使わなければならないことに注意してください。

たとえば、以下のような単語とIDの組(辞書)があったとします。

  • { 太郎: 1, 花子: 2, 三四郎: 3, キャベツ: 4, 白菜: 5, 好き: 6 }

「キャベツ/太郎/が/好き」というテキストは、たとえば以下のような特徴ベクトルにすることができます(ただし、「が」はストップワードとして除去したとします)。

  • (1, 0, 0, 1, 0, 1)

このように、単語が現れた場合に1、現れなかった場合に0、という2値でベクトル化する方法もありますが、単語の出現回数や重要度で、各次元(各単語)に重み付けをすることもできます。

  • 単語頻度 (TF; term frequency):その文書に単語が現れた回数
  • 文書頻度 (DF; document frequency):データセットのうち、いくつの文書にその単語が現れたか
  • 逆文書頻度 (IDF; inverse document frequency):DF の逆数。単語の重要度を表すと考えられる

重み付けの方法にはいろいろありますが、一般的には以下のようなものがあります。

  1. 単語が現れた次元には1、現れなかった次元には0を入れる(2値)
  2. 単語が現れた回数、つまり単語頻度 (TF) を入れる
  3. 単語頻度(TF)の log(対数)をとったものを入れる(単語頻度をtfとしたとき 1 + log(tf) など)
  4. 単語の逆文書頻度(IDF)を入れる(全文書数をN、文書頻度(DF)をnとしたとき log(N/n) など)
  5. 単語頻度(TF)と逆文書頻度(IDF)をかけたもの = TF-IDF

逆文書頻度(IDF)を考えることで、単語の重要度を考えることができます。よく出てくる単語(= IDFが低い)は特徴量としてあまりふさわしくないので重みを下げるという効果があります。一方で、逆文書頻度(IDF)は、ある程度の規模のテキストがないと信頼性が低いので注意しましょう。また、ベクトル化する前に単語をカウントして文書頻度n(データセットのうち、いくつの文書にその単語が現れたか)を求めておかなければなりません。場合によっては、Wikipediaなどの文書集合を使って、文書頻度を事前に計算しておくといったことも考えられます(対象テキストの性質が似たものであれば)。

単語頻度(TF)や逆文書頻度(IDF)を考慮すべきかどうかは、タスクによります。いくつかの重み付けの方法で実際に評価してみるとよいかもしれません。ともあれ、まずは最もシンプルな2値で試してみるとよいでしょう。

高次元でスパースなデータの取り扱い

自然言語処理では、しばしば特徴空間が高次元になります(特徴ベクトルの次元が高くなる)。これは過学習(Overfitting)が起きやすい条件です。ここでは、BoWでモデル化した文書(テキスト)の次元を減らす工夫について紹介します。また、次元が減ることで、高速に学習・予測できるようになるといった副次的な効果もあります。

  • 特徴選択
    • 単語を基本形に戻す、同義語・類義語辞書を使うなどの正規化を行う
    • 1回しか出てこない単語(=DFが1の単語)は無視する(ヒューリスティクス)
    • なんらかの手法で単語の重要度(重み)を計算し、上位 k 個の単語を貪欲法的に選ぶ
      • 単語の重要度の計算方法:TF-IDF、カイ二乗値、情報利得 (Gain)、自己相互情報量 (PMI) など
  • 次元削減
    • 教師なし学習による次元削減手法
    • Feature Hashing という手法もあり、少し乱暴に見えるが、文書分類タスクではそれなりにうまくいくことがわかっている

以下のスライドでは、高次元データに対して、学習アルゴリズムやデータ構造で対処する方法について詳しく説明されています。

さらに詳しく学ぶには、少し難しいかもしれませんが以下の書籍が参考になります。

  • 統計的学習の基礎 18 章 高次元の問題: p >> N

その他のトピック

機械学習に関連する計算機科学分野

  • データ構造とアルゴリズム
    • 高速な機械学習アルゴリズムを実装するためには必要不可欠
    • メモリ消費を小さくする(同じデータに対してより少ないメモリで動作すれば、それだけ大きいデータを扱える)
  • 数値計算
    • 機械学習は浮動小数点の世界。計算誤差についても知っておく
    • 機械学習アルゴリズムを自分で実装したときに、計算誤差のために壊滅することも
  • データベース、ミドルウェア
    • データは RDB に格納されていることが多い
    • SQL を知らないとデータが取り出せない!
    • 最近では大規模データを分散データベース(Mahout, Spark など)に格納し、その上で機械学習を走らせることもある
    • 環境に合わせて個別に勉強する
  • 情報理論
    • 特徴選択手法と関連
    • 機械学習の理論を勉強していると登場することがある

さらに学ぶために

わからないことがでてきたら

  • 知らない用語が出てきたら、とりあえず朱鷺の杜Wikiで検索してみましょう
    • 概要だけでなく、関連文献へのリンクも豊富

オンラインコース (MOOC)

  • CourseraのMachine Learningコース
    • オンラインかつ無料で、機械学習分野の第一人者の講義が受講できます
    • この教科書で詳しく説明できなかった線形回帰やロジスティック回帰、ニューラルネットワーク、SVMなどについて学べます
    • 絶対おすすめです
    • 参考までにこちらもどうぞ: Coursera を利用した機械学習勉強会

書籍

機械学習(入門)

機械学習(発展)

自然言語処理

確率・統計

最適化数学

線形代数

数値計算

Web

  • 機械学習の分類の話 - Jupyter Notebook Viewer
    • chezou さんのエントリ
    • 分類問題についての解説と、それを解くための機械学習アルゴリズムについて詳しく書かれています
    • パーセプトロン、ロジスティック回帰、SVM、ニューラルネットワーク、k近傍法、決定木、ランダムフォレスト、GBDTなど
  • クラスタリング(PDF)
    • 神嶌先生によるスライド
    • 教師なし学習の一種であるクラスタリングについて、よくまとめられています
    • クラスタリングのさまざまな手法が紹介されています
  • Graham Neubig - チュートリアル資料
    • NLPプログラミングチュートリアル には、今回扱わなかったNLPのトピックについてのスライド(PDF)が公開されています
    • 言語モデルやトピックモデル、係り受け解析など
  • 自然言語処理を独習したい人のために - 首都大学東京 自然言語処理研究室(小町研)
    • 小町さんによるおすすめ独学情報です
    • 自然言語処理を志す学部生を対象に書かれていますが、実務でNLPを使うITエンジニアにとっても参考になるでしょう