機械学習(分類問題)の最適なモデルを選択したい!!

#データの中身確認
機械学習の練習の際頻繁に使われるsklearnの乳癌のデータ（breast_cancer）。
まずはこのデータの中身がどうなっているか見ていきましょう。

```dataset.py
#sklearnからdatasetを読み込む
from sklearn import datasets

#datasetの中から乳癌のデータを取得する
cancer = datasets.load_breast_cancer()

#乳癌データのデータフレームを作成して上位５つのデータを表示する
breast_cancer_df = pd.DataFrame(cancer.data, columns=cancer.feature_names)
breast_cancer_df.head()
```
こんな感じ

|mean radius|mean texture|mean perimeter|mean area|mean smoothness|mean compactness|mean concavity|mean concave points|mean symmetry|mean fractal dimension|radius error|texture error|perimeter error|area error|smoothness error|compactness error|concavity error|concave points error|symmetry error|fractal dimension error|worst radius|worst texture|worst perimeter|worst area|worst smoothness|worst compactness|worst concavity|worst concave points|worst symmetry|worst fractal dimension|
|----------:|-----------:|-------------:|--------:|--------------:|---------------:|-------------:|------------------:|------------:|---------------------:|-----------:|------------:|--------------:|---------:|---------------:|----------------:|--------------:|-------------------:|-------------:|----------------------:|-----------:|------------:|--------------:|---------:|---------------:|----------------:|--------------:|-------------------:|-------------:|----------------------:|
|      17.99|       10.38|         122.8|     1001|        0.11840|         0.27760|        0.3001|            0.14710|       0.2419|               0.07871|      1.0950|       0.9053|          8.589|    153.40|        0.006399|          0.04904|        0.05373|             0.01587|       0.03003|               0.006193|       25.38|        17.33|          184.6|      2019|          0.1622|           0.6656|         0.7119|              0.2654|        0.4601|                0.11890|
|      20.57|       17.77|         132.9|     1326|        0.08474|         0.07864|        0.0869|            0.07017|       0.1812|               0.05667|      0.5435|       0.7339|          3.398|     74.08|        0.005225|          0.01308|        0.01860|             0.01340|       0.01389|               0.003532|       24.99|        23.41|          158.8|      1956|          0.1238|           0.1866|         0.2416|              0.1860|        0.2750|                0.08902|
|      19.69|       21.25|         130.0|     1203|        0.10960|         0.15990|        0.1974|            0.12790|       0.2069|               0.05999|      0.7456|       0.7869|          4.585|     94.03|        0.006150|          0.04006|        0.03832|             0.02058|       0.02250|               0.004571|       23.57|        25.53|          152.5|      1709|          0.1444|           0.4245|         0.4504|              0.2430|        0.3613|                0.08758|

30個の特長量（説明変数）が準備されていますが、**mean radius** :平均半径、**mean texture**　:テクスチャをグレースケールにした際の平均 のような内容になっています。
詳細は　https://ensekitt.hatenablog.com/entry/2018/08/22/200000　
↑上記リンクを確認してみてください。

さて、それでは次に目的変数である乳がんの腫瘍が良性or悪性を判断するtargetの中身を確認してみましょう。

```dataset.py
breast_cancer_df_tgt = pd.DataFrame(cancer.target, columns=['target'])
breast_cancer_df_tgt.head(3)
```

|target|
|-----:|
|     0|
|     0|
|     0|

頭から３つのデータだけ確認するとtargetが'0'しかありませんが、**breast_cancer_df_tgt.head(20)**で20番目のデータまで確認すると'1'もあることが見て取れます。
targetのデータですが、良性の腫瘍の場合は'0'、悪性の腫瘍の場合は'1'を表しています。

#最適なモデルの選択
さて、ここからが本題です。
targetが良性か悪性か判断するための分類モデル（ロジスティック回帰？　決定木？　サポートベクターマシン？　K近傍法?）はさまざまありますが、どのモデルが最もこの問題を解決するのに適しているかみていきましょう！

モデルを確認するためのコードはざっとこんな感じ。

```model_decision.py

#必要モデル作成に必要なライブラリのインポート
#上からK近傍法,決定木,ロジスティック回帰,線形SVM,SVM
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.svm import SVC


#乳癌データの読み込み
cancer = datasets.load_breast_cancer()

#説明変数'X',目的変数'y'に定義
X = cancer.data
y = cancer.target 

#訓練用データとテストデータを分割する
X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, stratify = cancer.target, random_state = 50)

#StandardScalerを使用してデータを標準化
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

#複数のモデルの設定
models = {'knn' : KNeighborsClassifier(),
        'tree' : DecisionTreeClassifier(random_state=0),
        'logistic' : LogisticRegression(random_state=0),
        'svc1' : LinearSVC(random_state=0),
        'svc2' : SVC(random_state=0)}

#スコアを持たせる空の辞書
scores = {}

for model_name, model in models.items():
    model.fit(X_train_std, y_train)
    scores[model_name, 'train'] = model.score(X_train_std, y_train)
    scores[model_name, 'test'] = model.score(X_test_std, y_test)
    print('{}:訓練データ正答率(train):{:.3f}'.format(model_name,model.score(X_train_std, y_train)))
    print('{}:テストデータ正答率(train):{:.3f}'.format(model_name,model.score(X_test_std, y_test)))

```

さて、実行結果をみてみましょう。

```
knn:訓練データ正答率(train):0.969
knn:テストデータ正答率(train):0.972
tree:訓練データ正答率(train):1.000
tree:テストデータ正答率(train):0.944
logistic:訓練データ正答率(train):0.988
logistic:テストデータ正答率(train):0.986
svc1:訓練データ正答率(train):0.986
svc1:テストデータ正答率(train):0.979
svc2:訓練データ正答率(train):0.986
svc2:テストデータ正答率(train):0.979
```

print文では上記のように表示されました。

次にデータフレームを使用して結果を整理していきます。

```model_decision.py
pd.Series(scores).unstack().sort_values('train', ascending = False)
```

||       test       |      train       |
|-----------------:|-----------------:|-----------------:|
|tree|0.9440559440559441|1.0000000000000000|
logistic|0.9860139860139860|0.9882629107981221|
|svn1|0.9790209790209791|0.9859154929577465|
|svn2|0.9790209790209791|0.9859154929577465|
|knn|0.9720279720279720|0.9694835680751174|


この結果を確認して、最も今回のケースに適しているモデルは何か一概に決定することは難しいですが、testとtrainデータの正答率の差が最も低く、正答率がどちらとも高いロジスティック回帰が最も適しているのではないか。。。と判断することができそうですね。。。