重回帰分析で重判別分析

私の保有している資格の一つ「ビジネス統計スペシャリスト」という資格で重回帰分析というのを様々な形に応用する単元があるのですが、その中で面白いと思ったのが重回帰分析で判別をするというものがあります。
仕組みはロジスティック回帰と似ていて(というかその資格でもロジスティック回帰を推奨していた)、回帰の結果が0.5を超えた場合に1、未満の場合は0としていました。
また、多値分類については記載はありませんでしたが、SVMなども「model.coef_」とやると多値分類の場合クラスの数だけ数式の係数が出力される通りクラスの数だけモデルを作ります。そこで最も大きい値を取ったモデルの結果が陽性という風になります。
# コーディング
## 二値分類
### ライブラリのインポート
```Python3
from sklearn.linear_model import LinearRegression as LR
from sklearn.metrics import classification_report
import pandas as pd
import numpy as np
```

### データの読み込み
まずは二値分類なので乳がんのデータを読み込みます。
```Python3
df = pd.read_csv("breast_cancer.csv")
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/df254574-d0b7-4976-33c7-74a6c6cc3295.png)

※見切れているのはご容赦ください
### 説明変数と目的変数の切り分けと前処理
前処理は標準化をします。(するのとしないとでは精度が変わります)
```Python3
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をしきい値にして陰性と陽性を決めます。
```Python3
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データです。
### データの読み込み
```Python3
df = pd.read_csv("wine.csv")
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/a12b5a10-f5a1-1f82-fe1f-af7bb071c0a3.png)


### クラスの値の確認
最終的には最大値のインデックスを使用するのでインデックスの値をそのまま使うか、あるいは少し工夫しないといけないかを見ます。
```Python3
set(df["Wine"].values)
```
```
{1, 2, 3}
```
ここで「0，1，2」と出力されなかったためインデックスの値に1を足す必要がある事が分かります。
### yの値の準備
多値分類の場合はインデックスを使用しますのでクラスをダミー変数にします。
```Python3
ys = []
dum = pd.get_dummies(df, columns=["Wine"])
dum.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/caa13f7e-aebd-b897-0022-68f0e994ded0.png)
### 説明変数と目的変数の切り分けとyの値の追加
今度はyが多値なのでysのリストに値を格納します。また、説明変数は先述した通り標準化します。
```Python3
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()
```
### 値の予測
ダミー変数の数だけモデルを作成してその予測結果を格納します。
```Python3
y_pred_val = []
for i in range(len(ys)):
    model = LR()
    model.fit(x, ys[i])
    y_pred_val.append(model.predict(x))
```
### インデックスから多値分類
予測された値の中で最も値の大きかったインデックスに1を足します。
```Python3
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%予測できました

# 注意点
今回は適合用データと予測用データを分けていないから高精度で予測できただけで、実際はもっと低い結果になりますのでそこは当方は責任持ちません。
これはあくまで分類アルゴリズムの仕組みのお話なので。

# 補足
今回は標準化のみ前処理を行いましたが、ダミー変数による前処理はクラス分類の前処理のみならず時系列データ(月別)や質的変数などにもダミー変数を使うことで精度を向上させることができますが、説明変数でダミー変数を使う場合は必ずどれか一つダミー変数を削除して多重共線性を考慮しないといけません。

# まとめ
だいたいの分類アルゴリズムは回帰した値や確率からルールベースで分類を行っています。そういった観点で見るとこういった重回帰分析から分類をしてみるというのも一度やってみると分類アルゴリズムに対する理解も深まるかもしれません。