Vet Analytics技術ブログ

機械学習・フロントエンド・獣医関連のことについて更新していきます

ロジスティック回帰の原理とPythonを用いた実装 ~基礎から実践まで~

こんには、Vet Analyticsでデータアナリストをやっている富永です。

Vet Analyticsは獣医学機械学習の知見を導入しようと日々奮闘しているデータサイエンス・エンジニアチームです! 東京大学本郷キャンパス付近でいつも活動しているので興味がありましたらtwitterアカウントから連絡してください。

前回は機械学習の基本的なアルゴリズムの1つであるSVM(サポートベクトルマシン)について解説しました。 vetanalytics.hatenablog.com

今回は同じく基本的なアルゴリズムの1つであるロジスティック回帰(Logistic Regression)の原理とPythonによる実装について書いて行きます。

そもそもロジスティック回帰って??

ロジスティック回帰はよく研究に使われるので生物系研究者の方や獣医師の方にも馴染みが深いアルゴリズムの1つですね。 例えば、下のような研究でロジスティック回帰が用いられています。

www.nature.com

www.nature.com

これらの論文のようにロジスティック回帰を使っているを研究は数多く存在します。 しかし、なんとなく統計的処理の一環と思ってる方もいると思うのでこれを期に理解を深めましょう!笑

ロジスティック回帰は回帰という名前ながらも実際には分類問題に使われるアルゴリズムです。 基本的には二値分類(0 or 1のような)のためのモデルですが、拡張することで多クラスの分類に対しても 応用することができるようになります。

今回は、理論に関しては二値分類に関するアルゴリズムを実装に関しては多クラスの分類に関して扱っていきたいと思います!

ロジスティック回帰の理論

例えば疾患有りか疾患無しかを判定する問題があったとする。疾患有りの時の確率をpとすると、疾患無しの群の確率は1-pとなります。 よって疾患有りのオッズ比を見ると \frac{p}{p-1}となります。オッズ比はその現象の起こりやすさを表す指標で、呼ばれるもので疫学研究などで出てくる指標の1つですね。今回はこの疾患の起こりやすさを表しています。

この対数をとったものをロジット関数といい、次の式になる。

 log_{\frac{p}{p-1}}

この式は病気にかかっている確率を入れることでオッズ比の対数を出力すると言うものです。しかし、多くの問題の場合求めたいのは病気にかかっている確率ですよね。 なので、ロジット関数の逆関数をとると

 log{\frac{1}{1+e^{-z}}}

となり、これによって出力が0から1までの確率になります!これをグラフ化すると次のようになります。

f:id:vetanalytics:20200316222309p:plain

これのとき閾値関数を定めて二値分類問題として扱います。 この場合は、病気の確率が0.5以上のものを疾病群0.5未満のものをコントロール群とすると

f:id:vetanalytics:20200316222525p:plain

これがロジスティック回帰による二値分類の基本的な仕組みです。

Pythonとscikit-learnを使ったロジスティック回帰の実装

今回も架空のデータを生成してロジスティック回帰による分類を行っていきたいと思います。

上記のような基礎的なロジスティック回帰では二値分類のみでしたが、Pythonモジュールの1つであるScikit-learnのロジスティック回帰では多クラス分類のモデル として拡張されています。

そこで今回は、scikit-learnを用いてロジスティック回帰で多クラス分類にチャレンジしたいと思います。

%matplotlib inline
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression as LR

まずは例の如く、scikit-learnと可視化のためのmatplotlibをインポートしていきましょう その次にロジスティック回帰を学習させるためのtrain dataとtest dataを作成していきましょう。

x_train,y_train = make_blobs(n_samples=200, #plotするサンプル数
                n_features=2, #特徴量(2次元)
                centers=4, #クラスターの数
                cluster_std=0.6, #クラスターごとの標準偏差
                shuffle=True, 
                random_state=0)
x_test,y_test = make_blobs(n_samples=300, #plotするサンプル数
                n_features=2, #特徴量(2次元)
                centers=4, #クラスターの数
                cluster_std=0.8, #クラスターごとの標準偏差
                shuffle=True, 
                random_state=0)

これによってロジスティック回帰分類器を学習させる準備が整いました。 まずは、このサンプルの分散を確認してみましょう

plt.scatter(x_train[:,0], x_train[:,1], c="red", marker="o", s=40)
plt.tight_layout()
plt.show()
plt.scatter(x_test[:,0], x_test[:,1], c="green", marker="o", s=40)
plt.tight_layout()
plt.show()

f:id:vetanalytics:20200317153116p:plain
trainデータの分布
f:id:vetanalytics:20200317153146p:plain
testデータの分布

そして分類が確認できたら、学習と予測を行ってみましょう。

lr = LR(C=100.0, random_state=0)
lr.fit(x_train, y_train)
predict = lr.predict(x_test)

予測結果はpredictに格納されているので、これをplotしてみましょう。

plt.scatter(x_test[predict==0,0],
           x_test[predict==0,1],
           s=40,
           c="red",
           marker="o",
           label="1")
plt.scatter(x_test[predict==1,0],
           x_test[predict==1,1],
           s=40,
           c="green",
           marker="o",
           label="2")
plt.scatter(x_test[predict==2,0],
           x_test[predict==2,1],
           s=40,
           c="blue",
           marker="o",
           label="3")
plt.scatter(x_test[predict==3,0],
           x_test[predict==3,1],
           s=40,
           c="yellow",
           marker="o",
           label="4")
plt.legend(scatterpoints=1)
plt.tight_layout()
plt.show()

f:id:vetanalytics:20200317153920p:plain
ロジスティック回帰による分類の結果

ちゃんとクラスターごとに分類できてることがわかりました。

次回は交差検証について書きます。

Vet Analyticsは様々な方のコンタクトを歓迎しています!DMへのご連絡をお待ちしております!