こんにちは、@ikeayです。
機械学習にもいろいろなモデル(アルゴリズム)があります。これらのモデルは優劣だけではなく、得意分野・不得意分野があったりするので、解きたい問題に応じて最適なものを選びます。
scikit-learnより
どういう時にどういうモデルを使えばいいか、scikit-learnが用意しているチャートを参考にすると分かりやすいですね。
機械学習はまずは大きく、「教師あり学習」「教師なし学習」「強化学習」に分けられます。ざっくり説明すると、「教師あり学習」は問題と答えがセットになって学習する方法、「教師なし学習」は正解不正解のデータが入っていないので、クラスタリングや外れ値検出で傾向をつかむ学習方法、「強化学習」はいいことをしたら報酬を与えていく学習方法です。以下の記事にざっくりとまとめてあります。
learning.ikeay.net
今回はその中でも教師あり学習のモデルにフォーカスしてみたいと思います。
事前準備
今回はscikit-learnを使った各モデルのプログラムも書いていきたいと思うので、事前に分析するデータを準備しておきましょう!
事前準備として、データセットをインポートしたり、そのデータを学習しやすいかたちに整える必要があります。
まずは、scikit-learn上でテスト用に用意されているデータ(irisといわれるあやめの花のデータ)をインポートして、そのインポートしたデータを学習用データとテスト用データに分割します。
from sklearn import datasets
from sklearn import cross_validation
iris = datasets.load_iris()
train_X, test_X, train_y, test_y = cross_validation.train_test_split(iris.data, iris.target, test_size=0.3, random_state=0)
次にデータを標準化します。だいたいデータというものは、カラムごとに値の幅にバラつきがあるので、そのバラつきを抑えていきます!
(平均0、分散1になるようにします)
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(train_X)
train_X = sc.transform(train_X)
test_X = sc.transform(test_X)
こうすることで、こんなデータを
[[ 5. 2. 3.5 1. ]
[ 6.5 3. 5.5 1.8]
[ 6.7 3.3 5.7 2.5]
[ 6. 2.2 5. 1.5]...
こんなデータにすることができます。
[[-1.02366372 -2.37846268 -0.18295039 -0.29145882]
[ 0.69517462 -0.10190314 0.93066067 0.73721938]
[ 0.92435306 0.58106472 1.04202177 1.6373128 ]
[ 0.1222285 -1.92315077 0.6522579 0.35146505]...
下準備完了です!
決定木
まずは決定木というモデルについて触れていきます。
決定木はツリー構造になっている人間にも非常にわかりやすいモデルです!
Yes、No、Yes、Noというかんじでたどっていくかんじ。
決定木 - Wikipediaより
いいところ
- ツリー構造になっているので、人間にとって意味がわかりやすいモデル!
- 決定木の派生モデルで、大量の決定木を作成して、それぞれの決定木が導いた答えから多数決するモデル「RandomForest」も優秀なモデルとして有名。(Kinectの身体部位推定に採用されていたりします)
わるいところ
- 過学習しやすい。
- 難しいデータは苦手。
- X軸やY軸などの軸と平行にざっくざっく切り分けることしか出来ない。
コードにするとこんなかんじ
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
clf = DecisionTreeClassifier()
clf.fit(train_X,train_y)
pred_y = clf.predict(test_X)
accuracy_score(test_y, pred_y)
出力!
0.97777777777777775
accuracy_scoreメソッドは正解率を出してくれます。
決定木でも約97.7%と、けっこういいスコア出ますね!
図を出力してみるとこうなりました。
人のニューロンをモデル化したモデルです。これがいま活躍しているモデルたちのだいたい元祖となっています!ディープラーニングもそうです。
高卒でもわかる機械学習 (2) 単純パーセプトロン | 頭の中に思い浮かべた時にはより
いいところ
わるいところ
- まっすぐ線でしか情報を切り分けれません!!(これを「線形分離」と呼びます)
- 第一次ブームの立役者でありながら、「線形分離しかできないじゃん!精度悪いじゃん!!」と言われて研究費をがっつり引かれてしまうことになるのであった…
from sklearn.linear_model import Perceptron
from sklearn.metrics import accuracy_score
clf = Perceptron(n_iter=100, eta0=0.1)
clf.fit(train_X, train_y)
pred_y = clf.predict(test_X)
accuracy_score(test_y, pred_y)
こちらも97.7%ほど。
0.97777777777777775
ロジスティック回帰
ディープラーニングの一層版。ディープラーニングはこのモデルの多層版と考えると分かりやすいかも。
https://inst.eecs.berkeley.edu/~cs194-26/fa15/upload/files/projFinalUndergrad/cs194-au/より
いいところ
- どのくらい確信をもてるのか、確信度が分かる(上のグラフでいうとグラデーションの色が濃いところほど確信度が高い)
- 学習が簡単
わるいところ
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
clf = LogisticRegression()
clf.fit(train_X, train_y)
pred_y = clf.predict(test_X)
accuracy_score(test_y,pred_y)
あれれ
0.82222222222222219
82.2%。だいぶ落ちたなあ。データセットとの相性が良くないのかも。
区切り(識別超平面)とデータの距離を最大となるようにするモデル。超平面の近くにあるデータ(サポートベクトル)だけをみてどこで区切るかを決めているので、計算量が少なくてすむ。
OpenCVで遊ぼう!: 年賀はがき当たりチェックアプリとSVMより
いいところ
わるいところ
- 学習にちょっと時間がかかる
- 通常はバッチ学習。データを1回で全部学習してしまおうとするので、データ量が多いと学習時間が苦しくなります。
- 通常は線形分離しかできない…!ただし、カーネルトリックと呼ばれる魔法を使うと非線形にもできたり、パラメーターをなんやかんや調整すると、かなり優秀なモデルになります!scikit-learnではデフォルトで非線形になっている模様。
from sklearn.svm import SVC
clf = SVC()
clf.fit(train_X, train_y)
pred_y = clf.predict(test_X)
accuracy_score(test_y,pred_y)
97.7%ほど。最強なはずなのにこのデータセットだと差が出ませんねw
ちなみに上記のプログラムはデフォルト値になってますが、パラメータサーチでパラメーター調整をしても、今回は値は変わりませんでした。
0.97777777777777775
scikit-learnではデフォルトで非線形モデルが採用されています。
ここではカーネルトリックという次元の呪いを解決できる魔法を使っています。これもSVMが最強だといわれる所以のひとつ。
まとめ
まだまだいろいろなモデルが存在しますが、代表的なモデルについてとりあげてみました。
たとえ決定木のように直線にしか切れなくても一概にダメなアルゴリズムとは言えません。その分、計算がめちゃめちゃ早くて優秀だったりします。
初心者の場合、まずはいろいろなモデルを試して、精度と速度を吟味して決めましょう!
Special Thanks: 松尾研 鈴木さん、PARTY 宮本さん