私の保有している資格の一つ「ビジネス統計スペシャリスト」という資格で重回帰分析というのを様々な形に応用する単元があるのですが、その中で面白いと思ったのが重回帰分析で判別をするというものがあります。
仕組みはロジスティック回帰と似ていて(というかその資格でもロジスティック回帰を推奨していた)、回帰の結果が0.5を超えた場合に1、未満の場合は0としていました。
また、多値分類については記載はありませんでしたが、SVMなども「model.coef_」とやると多値分類の場合クラスの数だけ数式の係数が出力される通りクラスの数だけモデルを作ります。そこで最も大きい値を取ったモデルの結果が陽性という風になります。
コーディング
二値分類
ライブラリのインポート
from sklearn.linear_model import LinearRegression as LR
from sklearn.metrics import classification_report
import pandas as pd
import numpy as np
データの読み込み
まずは二値分類なので乳がんのデータを読み込みます。
df = pd.read_csv("breast_cancer.csv")
df.head()
※見切れているのはご容赦ください
説明変数と目的変数の切り分けと前処理
前処理は標準化をします。(するのとしないとでは精度が変わります)
y = df["y"]
x = df.drop("y", axis=1)
for col in x.columns:
x[col] = (x[col] - x[col].mean()) / x[col].std()
モデル作成と予測
回帰を二値分類で行うため先述した通り0.5をしきい値にして陰性と陽性を決めます。
model = LR()
model.fit(x, y)
y_pred_val = model.predict(x)
y_pred = np.where(y_pred_val >= 0.5, 1, 0)
print(classification_report(y, y_pred))
precision recall f1-score support
0.0 0.99 0.92 0.95 212
1.0 0.95 0.99 0.97 357
accuracy 0.96 569
macro avg 0.97 0.95 0.96 569
weighted avg 0.97 0.96 0.96 569
意外と重回帰分析でも高いスコアが出ました。
多値分類
今度は二値分類で用いたしきい値ではなく最大値を取ったインデックスを用いて分類を行います。使用するのはWineデータです。
データの読み込み
df = pd.read_csv("wine.csv")
df.head()
クラスの値の確認
最終的には最大値のインデックスを使用するのでインデックスの値をそのまま使うか、あるいは少し工夫しないといけないかを見ます。
set(df["Wine"].values)
{1, 2, 3}
ここで「0,1,2」と出力されなかったためインデックスの値に1を足す必要がある事が分かります。
yの値の準備
多値分類の場合はインデックスを使用しますのでクラスをダミー変数にします。
ys = []
dum = pd.get_dummies(df, columns=["Wine"])
dum.head()
説明変数と目的変数の切り分けとyの値の追加
今度はyが多値なのでysのリストに値を格納します。また、説明変数は先述した通り標準化します。
ys.append(dum["Wine_1"].values)
ys.append(dum["Wine_2"].values)
ys.append(dum["Wine_3"].values)
x = dum.drop(["Wine_1", "Wine_2", "Wine_3"], axis=1)
for col in x.columns:
x[col] = (x[col] - x[col].mean()) / x[col].std()
値の予測
ダミー変数の数だけモデルを作成してその予測結果を格納します。
y_pred_val = []
for i in range(len(ys)):
model = LR()
model.fit(x, ys[i])
y_pred_val.append(model.predict(x))
インデックスから多値分類
予測された値の中で最も値の大きかったインデックスに1を足します。
y_pred = []
for i in range(len(ys[0])):
y_pred.append(np.argmax([y_pred_val[0][i], y_pred_val[1][i], y_pred_val[2][i]])+1)
print(classification_report(y, y_pred))
precision recall f1-score support
1 1.00 1.00 1.00 59
2 1.00 1.00 1.00 71
3 1.00 1.00 1.00 48
accuracy 1.00 178
macro avg 1.00 1.00 1.00 178
weighted avg 1.00 1.00 1.00 178
一応100%予測できました
注意点
今回は適合用データと予測用データを分けていないから高精度で予測できただけで、実際はもっと低い結果になりますのでそこは当方は責任持ちません。
これはあくまで分類アルゴリズムの仕組みのお話なので。
補足
今回は標準化のみ前処理を行いましたが、ダミー変数による前処理はクラス分類の前処理のみならず時系列データ(月別)や質的変数などにもダミー変数を使うことで精度を向上させることができますが、説明変数でダミー変数を使う場合は必ずどれか一つダミー変数を削除して多重共線性を考慮しないといけません。
まとめ
だいたいの分類アルゴリズムは回帰した値や確率からルールベースで分類を行っています。そういった観点で見るとこういった重回帰分析から分類をしてみるというのも一度やってみると分類アルゴリズムに対する理解も深まるかもしれません。