ロジスティック回帰による分類

#ワインの分類モデルを作成
##概要
フリーで手に入るワインのデータを用いて分類のモデルを作成する。 実際にモデルを作成、採択する際にどのような手順を踏んで行くかを追って行く。
###1:データ獲得

````data_get.py
import pandas as pd
import numpy as np
wine_data = pd.read_csv(
'https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',
header = None)
wine_data.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols', 'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue', 'OD280/OD315 of diluted wines', 'Proline']
````
###2:データ概要
上記で獲得したデータwine_dataは178行14列であり、'Class label'が被説明変数、それ以外のカラムが分類先のラベルを予測するための説明変数となる。 
以下の関数でデータの要約を見ることができる。

````describe.py
wine_data.describe()
````
###3:実践
では、ここからが実践。実際にモデルを作成して行く時に僕が気にしていることをなるべく残しながら進める。 
まずは、データの欠損値を調べる。 
欠損値があると、モデルの作成ができないので、欠損値を含む行か列の削除、もしくはパディングを行う必要がある。*1 

````missing_value.py
wine_data.isnull().sum()
````
結果は

````
Class label                     0
Alcohol                         0
Malic acid                      0
Ash                             0
Alcalinity of ash               0
Magnesium                       0
Total phenols                   0
Flavanoids                      0
Nonflavanoid phenols            0
Proanthocyanins                 0
Color intensity                 0
Hue                             0
OD280/OD315 of diluted wines    0
Proline                         0
dtype: int64
````
となり、欠損値はない。 
続いて、データにカテゴリカル変数が含まれているかを調べる。 
ここまで、データを実際に見てもいないので、複数行を取り出して見てみて、実際にカテゴリカル変数が含まれているかも確認する。 

````head.py
wine_data.head()
````
結果を見ると、カテゴリカル変数はないので、このデータでは特別な対応は必要ない。*2 
実際にモデルを作成、採択をする際には、データの前処理、モデル作成、モデル評価を行う必要があり、データの様子や、モデルの使用環境に応じた評価方法を取る必要がある。 
クラスラベルの数に偏りがあるかを調べる。
````class_label_check.py
wine_data['Class label'].value_counts()
````
これで、各ターゲットラベルがそれぞれいくつずつあるのかを見てみると 

````
2    71
1    59
3    48
dtype: int64
````
ラベル1が59個、ラベル2が71個、ラベル3が48個となっている。 
均等とは言えないが極端すぎる量の差があるわけではないので、評価の方法は、予測と実測データが一致しているものの割合で取る。 

モデルの作成を開始。 
使用するライブラリをインポート。  

````library_import.py
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import cross_val_score
````
今回はロジスティック回帰を使用。  
データ数が178個と多くはないので、ホールドアウト法でテストデータに多くは使用したくはないため、k分割交差検証を利用。 
また、データを標準化する。 
まとめて、データを標準化した後、ロジスティック回帰のモデルを作成するが、その際には交差検証法を用いて評価を行う。 
sklearnのpipelineを使用すると前処理からモデル作成までを一つにまとめることができる。 

````logistic.py
pipe_lr = Pipeline([
        ('sc', StandardScaler()),
        ('lr', LogisticRegression())
    ])
scores = cross_val_score(estimator=pipe_lr,
                        X=wine_data.ix[:,1:],
                        y=wine_data.ix[:,0],
                        cv = 10,
                        n_jobs = 1)
````
これでscoresには、交差検証によるそれぞれの正答率がリストとして入る。  

````
print scores
[ 1.          0.94444444  1.          0.94444444  1.          0.94444444
  1.          1.          1.          1.        ]
````
正答率の平均を出して  

````
print np.mean(scores)
0.983333333333
````
このデータを標準化し、作成したロジスティック回帰によるモデルの精度はだいたい0.98。 
実際に、何かしらに使用するためのモデルを作成するとなると、上記と同じ要領で複数の種類の前処理、手法を試し、その精度を比較して採用する処理、モデルを採用することになる。 
*1 
欠損値がある時の対応は、欠損値を含む行や列の削除、もしくは、代表値を用いてのパディングを行う。  

````
# 欠損値を含む行の削除
wine_data.dropna()

# 欠損値を含む列の削除
wine_data.dropna(axis=1)

# 欠損値の補完
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values = 'NaN', strategy = 'mean', axis = 0)
imp.fit(wine_data)
data = imp.transform(wine_data.values)
````
欠損値の補完はオプションによって、代表値の種類や、行方向、列方向の選択などが可能である。  
*2 
カテゴリカル変数がある時の対応は、ダミー特徴量を作成するなどの方法がある。pandasのget_dummies関数などを用いることで得られる。 

````
import pandas as pd

data = pd.Series(['red', 'blue', 'red', 'green'])

data
0      red
1     blue
2      red
3    green
dtype: object
````

````
pd.get_dummies(data)
````
|   | blue | green | red |
|:-:|:----:|:-----:|:---:|
| 0 |   0  |   0   |  1  |
| 1 |   1  |   0   |  0  |
| 2 |   0  |   0   |  1  |
| 3 |   0  |   1   |  0  |