いしたーです。アルバイトで機械学習やってます。こんにちは。
とある勉強会に出席したときに、「機械学習をやりたいけどわからないことが多い」という意見を聞いたので、いくつかアドバイスを載せておきます。
##読む前の注意
- 研究についてのアドバイスは書いていません。趣味で機械学習をやろうと思っている方が対象です。
- この記事は他の方の意見をまとめたものではありません。私個人の経験に基づいて書いたものです。よって、この記事の内容はほとんど「私の意見」です。
以上2つの注意点を踏まえた上でお読みください。
##「機械学習で何をしたいのか」を決めてほしい
機械学習を学ぶ前に、機械学習を使って何をしたいのかを決めてください。
機械学習は数式がたくさん登場したり、難しい概念を理解しなければならなかったりすることがあります。
やりたいことを決めてから学ぶと、今自分はある目的を達成するために学んでいるんだと思うことができます。これは学習の進み具合に大きく影響します。
学ぶ前に何をしたいのかを決めるべきだというのは、機械学習に限らずプログラミング全体を通して言えることだと思います。
例えば、機械学習を使うと以下のようなことができます。
- 車載カメラの映像から歩行者を検出して車の事故防止に役立てる
- CT画像を解析して病気の原因をコンピュータに探させる
- コンピュータに将棋をさせる
- Siriのような対話インターフェースを作ってコンピュータと会話をする
他にもさまざまなことができます。
機械学習は応用範囲が非常に広いので、自分が本当に作りたいもの、やりたいことが必ず見つかるはずです。ぜひ自分の作りたいものを探して、実際に作ってみてください。
##理論の完璧な理解は後回しでいい
###最初から理論を理解するのは無理
勉強会ではこんなことを聞きました。
「アルゴリズムの実装もやりたいんだけど、その前に理論を理解したい」
アルゴリズムを完璧に理解してからコードを書きたくなるというのはプログラマとしてすごくいい癖(素質)だと思います。
しかし、機械学習に関しては、最初から完璧に理論を理解しようとするのはあまり良くないと私は思います。なぜなら、単純に難しいからです。
機械学習の理論の大半は高度な数式で構成されています。
最も単純なアルゴリズムであるパーセプトロンなら、高校レベルの数学力があれば容易に理解できます。しかし、それより少し性能のいいSVM(サポートベクターマシン)などを理解しようとすると、とたんに難しい部分がたくさん出てきます。
例えば、SVMの最も重要な部分であるカーネル関数の原理を理解しようとすると、非常に高度な数学が必要になります。どのくらい高度か知りたい方は、「カーネル関数 原理」などでググってみて出てくる数式を眺めてみるといいでしょう。
要は、「機械学習をやってみたい」もしくは「機械学習を始めてみた」という方がいきなり理論を完璧に理解するのはまず無理だということです。
###ある程度の理解でいいから、アルゴリズムを実装してみよう
カーネル関数は理論は難しいですが、コード上では1行で実装できます。
例えばガウシアンカーネルはPythonでは以下のようになります。
def gaussian_kernel(x1, x2, sigma):
return np.exp(-norm(x1-x2)**2 / (2*(sigma**2)))
概念は難しくても、コードにするのは難しくありません。
数式さえ読めれば、理論が理解できなくてもアルゴリズムを実装することは可能です。
理論の理解はアルゴリズムを実装してからで十分です。
最初はとにかく作ってみて、そのアルゴリズムがどのような手順で動いているのか、なぜ動くのかを大まかに理解することをおすすめします。
アルゴリズムの動作の大まかな理解が済んだ後に、その動作を数式で表すとどうなるかを学ぶのが良いでしょう。
##入力データをそのまま学習できるわけではない
機械学習ではしばしば「識別」を扱います。
例えば、ブドウとリンゴを見分けたいだとか、防犯カメラに写っている人物が顔を隠しているかどうかを見分けたい、などといったものです。
さて、機械学習には様々な識別アルゴリズムが存在します。先ほど登場したSVMもその一つです。
「じゃあブドウとリンゴを見分けたいんだったらブドウとリンゴの画像をそのままSVMに入力すればいいんだね」
じつはこれは間違いです。
機械学習アルゴリズムは高次元の(有用でない)入力データが与えられると十分なパフォーマンスを発揮できません。
いきなり言われてもよくわからないかもしれないので、解説します。
例えば、5x5の大きさの白黒の画像はこんな感じで表わせます。
[[0 3 3 8 6]
[5 7 8 0 1]
[1 8 7 1 4]
[2 0 8 1 5]
[9 9 5 7 4]]
つまり、画像の縦x横の大きさの配列に、ピクセルごとの明るさを格納すればいいわけです。
これを1次元の配列になおしてみるとこうなります。
[0 3 3 8 6 5 7 8 0 1 1 8 7 1 4 2 0 8 1 5 9 9 5 7 4]
これはベクトルの形をしていますね。
ところで、多くの機械学習アルゴリズムの入力はベクトルです。つまり、1次元配列の形をしていれば何でも入力することができます。
「じゃあブドウとリンゴを識別したいんだったら、ブドウとリンゴの画像を1次元配列に展開して入力すればいいじゃん」
と思うかもしれませんがそうではないんです。
機械学習アルゴリズムにこのベクトルを入力しても、うまく学習を行うことができません。
画像をベクトルに変換できたし機械学習アルゴリズムに入力して学習させてみよう!と意気込んでやってみると精度が出なくてがっかりします。
これを__次元の呪い__といいます。
なぜこのようなことが起きるかというと、機械学習アルゴリズムは「ブドウとリンゴのどこに着目すれば両者を分類できるか」を判断できないからです。
ブドウとリンゴの色に着目すればいいのか、形に着目すればいいのか。どこを見れば両者を分類できるかを、機械学習アルゴリズムが判定することは基本的にはできません。
よって、ブドウとリンゴのどこを見ればいいのかを、人間が教えてあげる必要があります。
ブドウとリンゴそれぞれの特徴をうまく表現できるものを、我々がベクトルとして取り出さなければなりません。
皆さんならリンゴとブドウを見分けたいとしたら何を頼りに見分けますか?
リンゴは赤い、ブドウは青い。つまり、色で見分けることができますね。
例えばこんなベクトルを抽出してみるとうまく識別できるでしょう。
[赤の濃さ 青の濃さ]
何千次元もある画像のベクトルをそのまま学習アルゴリズムに入力するより、色という有用な情報を学習アルゴリズムに入力するほうが楽に識別を行えます。
この識別したい物体やデータからより有用な情報を取り出す操作を__特徴抽出__といいます。
機械学習アルゴリズムを使って識別などを行うときには、特徴抽出を行った後のデータをアルゴリズムに入力するということをよく覚えておいてください。
##おわりに
間違っている場所、読んでいて疑問に思った点などがあったら気軽にコメントしてください。