分類アルゴリズムは基本的に2値分類の場合は特に線形の場合ルールベースとしてモデルで算出結果が0.5を超えた場合に陽性、0.5未満の場合に陰性と判断する事が多いです。
ところで線形モデルと一言で言っても色々とあります。
例えば
- SVM
- ロジスティック回帰
- 線形回帰
- ポアソン回帰
などがあります。
しかしそれぞれアルゴリズムが違ったり、数式が違ったり、確率分布(ベイズ統計)が違うなどあります。
そこで、上記4つのアルゴリズムについて実際に係数と切片を見てみようと思います。
コーディング
ライブラリのインポート
使用するデータセットにはScikit-Learnのmake_blobsを使ってみます。
from sklearn.datasets import make_blobs
from sklearn import preprocessing
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import PoissonRegressor
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
データセットの可視化
どんなデータセットか可視化します。
x, y = make_blobs(n_samples=100, centers=2,random_state=0, cluster_std=0.60)
plt.scatter(x[:, 0], x[:, 1], c=y, s=50, cmap="brg")
plt.show()
係数の名前を入れる
index = ["x0", "x1", "intercept"]
columns = ["coef"]
とても分類しやすいようになっています。
では実際に分類をしてみましょう。
係数と切片の確認
SVM
SVMは2値分類の場合陽性と陰性のデータの境目について平行に支持直線(多次元の場合超平面)と呼ばれる線を引き、その線と線の間の幅が最も広くなるように決定境界を作ります。
model1 = SVC(kernel="linear")
model1.fit(x, y)
model1.coef_
model1.intercept_
svm_coef = np.array([])
svm_coef = np.append(svm_coef, model1.coef_)
svm_coef = np.append(svm_coef, model1.intercept_)
df_svm = pd.DataFrame(svm_coef)
df_svm.index = index
df_svm.columns = columns
ロジスティック回帰
ロジスティック回帰は陽性と陰性に対してシグモイド関数を多次元化してしきい値を設定する事で分類しています。
model2 = LogisticRegression()
model2.fit(x, y)
model2.coef_
model2.intercept_
lor_coef = np.array([])
lor_coef = np.append(lor_coef, model2.coef_)
lor_coef = np.append(lor_coef, model2.intercept_)
df_lor = pd.DataFrame(lor_coef)
df_lor.index = index
df_lor.columns = columns
線形回帰
線形回帰はExcelにもあります重回帰分析と同じく最小二乗法と呼ばれる方法で回帰するアルゴリズムです。
本来は回帰に用いるアルゴリズムですが先述した通りしきい値を用いる事で1と0の場合だと回帰の算出結果が0.5以上だと陽性でそうでなければ陰性なら分類にも使えます。
model3 = LinearRegression()
model3.fit(x, y)
model3.coef_
model3.intercept_
lir_coef = np.array([])
lir_coef = np.append(lir_coef, model3.coef_)
lir_coef = np.append(lir_coef, model3.intercept_)
df_lir = pd.DataFrame(lir_coef)
df_lir.index = index
df_lir.columns = columns
ポアソン回帰
主にカウントデータを分析するアルゴリズムで名前の通りポアソン分布を基にしています。
model4 = PoissonRegressor()
model4.fit(x, y)
model4.coef_
model4.intercept_
pos_coef = np.array([])
pos_coef = np.append(pos_coef, model4.coef_)
pos_coef = np.append(pos_coef, model4.intercept_)
df_pos = pd.DataFrame(pos_coef)
df_pos.index = index
df_pos.columns = columns
結果を見てみる
df_coef = pd.concat([df_svm, df_lor, df_lir, df_pos], axis=1)
df_coef.columns = ["SVM", "LogisticRegression", "LinearRegression", "PoissonRegressor"]
df_coef
こうやってみてみると意外とというか全然違うことが分かります。やはり使う数式やアルゴリズムが違うから当然と言えば当然の結果なのでしょうね。
※でも線形回帰は単純に当てはめられるし、ロジスティック回帰はオッズ比に使えるから←ここ重要
図示
ここまで係数と切片について見ましたが今度は図示してみましょう。
図示する関数
まず分類用の関数です。
仕組みとしては正規化した二次元平面に対してデータを学習して細かく平面を分割し、分割した場所を予測して色を付けるということです。
def showline_clf(x, y, model, modelname, x0="x0", x1="x1"):
fig, ax = plt.subplots(figsize=(8, 6))
X, Y = np.meshgrid(np.linspace(*ax.get_xlim(), 1000), np.linspace(*ax.get_ylim(), 1000))
XY = np.column_stack([X.ravel(), Y.ravel()])
x = preprocessing.minmax_scale(x)
model.fit(x, y)
Z = model.predict(XY).reshape(X.shape)
plt.contourf(X, Y, Z, alpha=0.1, cmap="brg")
plt.scatter(x[:, 0], x[:, 1], c=y, cmap="brg")
plt.xlim(min(x[:, 0]), max(x[:, 0]))
plt.ylim(min(x[:, 1]), max(x[:, 1]))
plt.title(modelname)
plt.colorbar()
plt.xlabel(x0)
plt.ylabel(x1)
plt.show()
次に回帰で分類用の関数です。回帰の場合はしきい値を設定します。
def showline_reg(x, y, model, modelname, x0="x0", x1="x1"):
fig, ax = plt.subplots(figsize=(8, 6))
X, Y = np.meshgrid(np.linspace(*ax.get_xlim(), 1000), np.linspace(*ax.get_ylim(), 1000))
XY = np.column_stack([X.ravel(), Y.ravel()])
x = preprocessing.minmax_scale(x)
model.fit(x, y)
Z = model.predict(XY)
Z = np.where(Z >= 0.5, 1, 0).reshape(X.shape)
plt.contourf(X, Y, Z, alpha=0.1, cmap="brg")
plt.scatter(x[:, 0], x[:, 1], c=y, cmap="brg")
plt.xlim(min(x[:, 0]), max(x[:, 0]))
plt.ylim(min(x[:, 1]), max(x[:, 1]))
plt.title(modelname)
plt.colorbar()
plt.xlabel(x0)
plt.ylabel(x1)
plt.show()
SVM
showline_clf(x, y, SVC(kernel="linear"), modelname="SVM")
ロジスティック回帰
showline_clf(x, y, LogisticRegression(), modelname="LogisticRegression")
線形回帰
showline_reg(x, y, LinearRegression(), modelname="LinearRegression")
ポアソン回帰
showline_reg(x, y, PoissonRegressor(), modelname="PoissonRegressor")
こうやって見てみると、ポアソン回帰とロジスティック回帰が少し似ていて、SVMと線形回帰が似ているように見えます。
まとめ
そりゃアルゴリズム違えば係数は違うよ。