【初心者】コピペでできるロジスティック回帰

スポンサーリンク
Python




非エンジニアであるサラリーマンにとって、機械学習の細かいアルゴリズムは必要ない!

まずは、Pythonにコードをコピペして実行させることが大切です。その結果をどう判断するかは、現場経験があるサラリーマンの腕のみせどころです。サラリーマンによるデータ解析の方が問題解決に直結します。

なお、今回のデータはPythonで実行できるscikit-learnにあるデータセットを使用しています。

では早速初めていきましょう。

環境構築は、【2020年最新】Anacondaのインストール方法

データの形を整える

【超重要】はじめてのデータ収集方法

データ収集する場合は下図のように、横に測定項目(緑)、縦に固有のもの(オレンジ)、そして枠内に入れる数値や文字はひとつだけにします。

たとえば、青枠のひとの赤枠測定項目は 94.74 です。

ちなみに、

赤枠の測定項目のことを列

青枠の固有のものを行

と呼びます。

 

この状態から解析に入ります。

import pandas as pd
df = pd.read_csv("〇〇〇〇.csv")

同じ作業場(ディレクトリといい、Pyhonを起動している場所とCSVファイルが同じ場所という意味)ならこれで、データの読み込みができます。(〇〇〇〇にファイル名を入れる)

今回使用するデータはガンが良性か悪性かを目的変数とし、その他の測定項目を説明変数にしています。(ここではデータ内容の詳細は省きます。)また、開発環境はJupytrLab(JupyterNotebook)で行っています。

X = df.iloc[:,0:30].values  # 説明変数
y = df.iloc[:,-1].values    # 目的変数

1行目:このデータは32列(32の測定項目)あり、最初の31列の説明変数をXに入れる(Pyhtonでは1から、ではなく0から数え始めるため)
2行目:このデータの一番最後の目的変数をyに入れる

mapping = {'benign': 0, 'malignant': 1}
df['cancer'] = df['cancer'].map(mapping)
df

目的変数は文字なので、数値に変換します
1行目:benign(良性)を0に、malihnant(悪性)を1に、という命令文を作ります。
2行目:それを実行し、もとの文字を数値に変換します
3行目:変換後のデータを確認します。

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size = 0.25,
    random_state = 0,
    stratify = y)

これは、説明変数のXと目的変数のyをトレーニング用とテスト用に分けています。
トレーニングデータで学習し、テストデータで学習後の予測モデルを検証するためです。
学習したデータでテストをしても、汎用性が高いとはいえないからです。(参考書の内容が、そのままテストにでる。みたいなイメージです)

ロジスティック回帰の実行

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline

pipe_svc = make_pipeline(StandardScaler(),
                         PCA(n_components=5),
                         LogisticRegression(random_state=1))

param_range = [0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]

param_grid = [{'logisticregression__C': param_range}]      

gs = GridSearchCV(estimator = pipe_svc, 
                  param_grid = param_grid, 
                  scoring = 'accuracy', 
                  cv = 10,
                  n_jobs = -1)
gs_lr = gs.fit(X_train, y_train)

# 最良のスコアとなるパラメータ値を出力
print('Train accuracy_LogisticRegression: %.3f' % gs_lr.best_score_)
print(gs_lr.best_params_)

いろいろ書いていますが、ここでは難しいことはやめましょう。これを実行すると、
Train accuracy_LogisticRegression: 0.977
{‘logisticregression__C’: 10.0}
が出力されます。これは、正解率が97.7%ということを表しています。だいたのデータは、このコードである程度の結果が出ると思います。

評価

from sklearn.metrics import confusion_matrix
# テストと予測のデータから混合行列を生成
confmat = confusion_matrix(y_true=y_test, y_pred=y_pred)

fig, ax = plt.subplots(figsize=(3, 3),dpi=200)
# matshow関数で行列からヒートマップを描画
ax.matshow(confmat, cmap=plt.cm.Blues, alpha=0.3)
for i in range(confmat.shape[0]):       # クラス0の繰り返し処理
    for j in range(confmat.shape[1]):   # クラス1の繰り返し処理
        ax.text(x=j, y=i, s=confmat[i, j], va='center', ha='center')  # 件数を表示

plt.xlabel('Predicted label')
plt.ylabel('True label')
plt.tight_layout()
plt.show()

この図が分かりやすいと思います。この図の意味は、下記の図に対応しています。

つまり、塗りつぶされている枠の数が大きい方が、正しい予測が多いということになります。

以下のコードは上記の図を数値化したものです。

y_pred=gs_lr.predict(X_test)
from sklearn.metrics import precision_score, recall_score, f1_score, roc_auc_score
print('Test accuracy: %.3f' % gs_lr.score(X_test, y_test))
print('Precision: %.3f' % precision_score(y_test, y_pred))
print('Recall: %.3f' % recall_score(y_test, y_pred))
print('F1: %.3f' % f1_score(y_test, y_pred))
print('roc_auc: %.3f' % roc_auc_score(y_test, y_pred))

from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))

Test accuracy:正解率:(FP+FN) / (FP+FN+TP+TN)

Precision:適合率:TP / (TP+FP)

Recall:再現率:TP / (FN+TP)

F1:F1スコア:2×(適合率×再現率) / (適合率+再現率)

これらの数値で予測精度を判断します。場合によっは、間違った陰性と間違った陽性のどちらを許容できるかによっても判断が違ってくると思います。そこは、現場感覚が試されると思います。

これで、ロジスティック回帰のコピペを終わります。

以下にこのコードを書くための前段階のコードを書いておきます。参考にしてみて下さい。

import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
df = pd.DataFrame(data=cancer.data, columns=cancer.feature_names)
df
series1 = pd.Series(data=[cancer.target_names[i] for i in cancer.target], name="cancer")
series1
df = pd.concat([df,series1], axis=1)
df



コメント

タイトルとURLをコピーしました