AIプログラミング

ロジスティック回帰によるデータ分類

ロジスティック回帰とは

機械学習に取り組む前段階として,まずはロジスティック回帰を行ってみます.ロジスティック回帰の詳細はWikipedia参照.ものすごく大雑把(かつ不正確)に言うと,2クラス分類問題を解く手法です.これが不正確な表現ってわかる人は,既にわかっている人だと思います.ということで上の雑駁な表現をお許しください.

データの説明

データファイル

ここでの練習用に,データファイルを作りました.

ここからダウンロード(binarize.csv)

また,以下のソースコードの全体像(jupyter notebook形式)と,データをまとめたファイルを圧縮して以下に置いておきます.
Example2.zip

特になんということもないデータです.完全に架空のデータです.左から2つの列は説明変数,一番右の列は被説明変数というイメージで,0か1かの2クラスに分かれています.

このデータを使ってやりたいこと

ここでやりたいことは,説明変数2つから,クラスが0か1かを当てたい,というものです.やり方は色々とあり,機械学習手法で次回以降解いていきたいと思いますが,まずは歴史のあるロジスティック回帰を用いて行う,ということです.

サンプルコード

以下,サンプルコードです.

基本的にコメントをつけた通りですが、改めて。
最初の文章はおまじないのようなもので、これが無いと一般的にはpythonを動かす際に、日本語コメントが入っているとエラーを吐き出します。でも、Google Colaboratoryでは内部で処理してくれているようで無くても大丈夫なのですが、一応つけています。
3行目からは、ライブラリを使うための宣言です。Pandasはデータを扱うための、numpyは数値計算を効率的に行うための拡張です。両方とも(特にnumpyは)、今後多くのプログラムで利用します。matplotlibも同様に頻出のライブラリです。これらについてもおまじないのように書くのがいいです。

上のコードは、Google Colaboratoryの場合にのみ必要なワンステップです。
サーバー上で解析を行うため、ローカルのファイルを読み込むことができません。対策は色々とあり、Google Driveにアップする方法などもあって場合によってはそちらが便利なのですが(というか、そっちにしないとできない場合もある)、今回のbinarize.csvのような小さなファイルを扱う場合にはこのくらいでも十分です。
上のコードを実行するとファイルを読み込むダイアログが出てきます。それに従いファイルを読み込むと、以下のような感じになります。

ダイアログを使って読み込んだのは、あくまでもシステムでファイルを扱えるように読み込んだものです。このプログラムの中では読み込めていません。このプログラムで使えるように、さっき最上部でpandas as pdと書いてpdとしてimportしたpandasを使って、データを読み込みます。pandasにはread_csvという関数があり、それを使ってbinarize.csvを読み込みます。
そして、左から2列を説明変数として、Xに代入します。pythonは数え方が0からスタートするため、0:2列目を読み込め、と書いています。pythonでは、0:2というのは、0からスタートして2になるまで、なので、0列目と1列目という意味です。そして、1番右の列を被説明変数としてYに読み込みます。

ここは無くてもいいのですが、基本的にビビりなので、ちゃんと作れているか表示しています。最初の5行くらい。また,最後のprint文は,行列の形を調べています.
実行すると,以下のような結果が得られます.

[[5.1 1.5 0. ]
[4.2 3.2 1. ]
[0.7 0.9 0. ]
[1.2 0.7 0. ]
[8.8 1.7 1. ]]
[[5.1 1.5]
[4.2 3.2]
[0.7 0.9]
[1.2 0.7]
[8.8 1.7]]
[0. 1. 0. 0. 1.]
(200, 3)

最初に示したテーブル通りのデータになっていることがわかると思います。よかった。

説明変数が2つなので、それぞれを横軸、縦軸として、それらとクラスの分布についてプロットしてみました。こんな感じの図になっています.意図的に作ったデータだけあって、まあまあ分かりやすく分布しているものの、ちらちらと例外データもあったりします。

sklearn.model_selectionから,train_test_splitという関数を読み込んでいます.sklearnはscikit-learnといって,Pythonの機械学習用ライブラリです.
こういうfrom … import …みたいなやつは,普通はプログラムの最初に書くんですが,今回は説明用に,関数を使う場所の近所に書きました.
X, yを,それぞれ,学習用8割,テスト用2割,といった分け方をしています.
で,下2行のprint文で,本当に8割,2割になっているか確認しています.

train size: 160
test size: 40

実行すると,確かにそうなっています.

次は,sklearnから,ロジスティック回帰を行うための関数LogisticRegressionのインポートを行っています.
で,次の行とその次の行で,X_trainとy_trainという入力と出力の組み合わせを与えることで,それにもっともマッチする係数を出すことができます.lr.fitというのがポイントです.下2行は,それぞれ切片と係数を確かめています.(なお,train_test_splitはランダムで分割するので,以下の結果はランダムで変わります)

[-3.25466321]
[[0.36590136 0.68987314]]

求まった係数をw_0, w_1, w_2に代入します.ちなみに,w_0+w_1*X1+w_2*X2 = 0という関係があります.その線をもとにクラスが分かれます.
で,下半分はプロットのための部分です.np.arange(0,10,0.01)で,0から10まで0.01刻みでxx1を設定します.そして,xx2 = (-w_1 * xx1 – w_0)/w_2という関係のプロットを描いて,上の分布図と合わせます.それが以下の結果ですが,それなりにまっとうなところで分割できている様子がわかります.

ここでは,テスト用に確保してあったX_testを,先程作ったモデルに入れたらどうなるかということを確認しています.
lr.predictとすれば,予測をしてくれます.で,テスト用データの正解と比較した正解率を,lr.scoreで出してくれます.

とはいえ,後ろ2割を引っ張ってきても全体が合っているかどうかこころもとないので,ここでは交差検証を行っています.
Wikipediaによれば,交差検証とは,統計学において標本データを分割し、その一部をまず解析して、残る部分でその解析のテストを行い、解析自身の妥当性の検証・確認に当てる手法を指す...らしいです.というか実際にそうです.特に,K分割交差検証というのをここではやりました.StratifiedKFoldというのはその関数です.で,ここではK=8としています.つまり,標本群を8個に分割し,そのうち7つを用いて学習を行い,そして残り1つをテストデータとして精度を評価する,というのをテストデータを変えながら8回繰り返しています.
以下はその結果を示しています.

Cross-Validation scores: [0.84615385 0.80769231 0.76923077 0.8 0.84 0.875
0.95833333 0.79166667]
Average score: 0.8360096153846154

最初の行列は8回それぞれの正解率,最後はその平均です.だいたい83.6%の正解率であることがわかります.

ABOUT ME
P-Chun
P-Chun
Pythonの書き方に未だに慣れないので,このHPを備忘録にするつもりで作っていきます.本業にもっと活かしたいです.