irisでロジスティック回帰
アルゴリズム
基本的な考え方は線形回帰と同様で、データに対して重みベクトルを掛けてバイアスを加えたを計算する。ロジスティック回帰では確率を計算するため出力の範囲を0以上1以下に制限する必要がある。そのため、シグモイド関数を用いることで0から1の間の数値を返している。シグモイド関数は以下のようになる。
シグモイド関数を用いることで0から1の間の数値を返している。シグモイド関数をグラフに書くと次のような形状になる。
import math # シグモイド関数 def sigmoid(x): y = 1 / (1 + math.e**(-x)) return y
プロットしてみる。
import numpy as np import matplotlib.pyplot as plt x = np.linspace(-10, 10, 100) y = sigmoid(x) plt.plot(x, y) plt.show()
このシグモイド関数を用いて、データ が与えられたときに、そのラベルが である確率 を で計算する。二値分類であれば が0.5未満のとき0、0.5以上のとき1というように分類を行う。
学習では、ロジスティック損失を誤差関数として用い、これを最小化する。最小化では勾配降下法を用いる。
具体例
irisのデータセットでロジスティック回帰をしてみる。
import pandas as pd from sklearn.datasets import load_iris from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split # irisデータセットの読み込み data = load_iris() X = pd.DataFrame(data.data, columns=data.feature_names) y = pd.DataFrame(data.target, columns=['Species']) df = pd.concat([X, y], axis=1) df.head()
sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | Species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | 0 |
1 | 4.9 | 3.0 | 1.4 | 0.2 | 0 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | 0 |
0 | 4.6 | 3.1 | 1.5 | 0.2 | 0 |
0 | 5.0 | 3.6 | 1.4 | 0.2 | 0 |
irisのデータセットにはあやめの sepal length(がくの長さ)、sepal width(がくの幅)、petal length(花弁の長さ)、petal width(花弁の幅)に加え、それぞれの品種(setosa、versicolor、virginica)の情報がある。
今回は品種 setosa、versicolor のpatal length、petal widthのデータを使用してロジスティック回帰をしてみる。
# 品種 setosa、versicolorを抽出 df2 = df[(df['Species']==0) | (df['Species']==1)] # 説明変数 X = df2.iloc[:, [2, 3]] # 目的変数 y = df2.iloc[:, 4] # 学習データと検証データを分割 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
model = LogisticRegression()
# 学習
model.fit(X_train, y_train)
切片と傾きを確認する。
# 切片 print(model.intercept_)
[-7.3018626]
# 傾き print(model.coef_)
[[2.41092643, 1.01214654]]
ここで、決定境界をプロットしてみる。決定境界とは、分類結果が切り替わる境目のことで、ロジスティック回帰の場合、決定境界は確率を計算した結果がちょうど50%になる箇所を指す。
まず、以下の通り定義する。
: petal length (cm)
: petal width (cm)
バイアス:
重みベクトル
データ
データ が与えられたとき、そのラベルが である確率 は
であるから
確率0.5のとき決定境界が求まるので
となり、これが平面の場合の決定境界となる。
Pythonでプロットしてみる。
w_0 = model.intercept_ w_1 = model.coef_[0, 0] w_2 = model.coef_[0, 1] x1 = np.linspace(0, 6, 30) x2 = (-w_1 * x1 - w_0) / w_2 # プロット plt.plot(x1, x2, color='gray') plt.scatter(X.iloc[:, 0][y==0], X.iloc[:, 1][y==0], color='lightskyblue', label=data.target_names[0]) plt.scatter(X.iloc[:, 0][y==1], X.iloc[:, 1][y==1], color='sandybrown', label=data.target_names[1]) plt.ylim(-0.25, 2) plt.xlabel(X.columns[0]) plt.ylabel(X.columns[1]) plt.legend() plt.show()
今回はもともときれいに分かれていたので、決定境界もいい感じに引けていた。
特徴量の解釈について
ロジスティック回帰では各特徴量の係数を見ることができる。目的変数としてsetosaを0、versicolorを1として用いているとき、各特徴量は以下のようになる。
petal length (cm) | petal width (cm) |
---|---|
2.41092643 | 1.01214654 |
先ほどのグラフの軸petal length、petal widthの重みは正の値だったため、どちらも大きくなるとversicolorである割合が大きくなることが分かる。
各特徴量の係数の符号を見ることで、正の影響を与えているのか負の影響を与えているのかが解釈できる。
おわりに
scikit-learnライブラリでロジスティック回帰をする方法についてirisデータセットを使って記述した。ロジスティック損失なども記述していけたらと思う。