データ分析関連備忘録

# はじめに
昔作成したチートシートを転記したもので、参照元は不明です。
また、私の資料整理のために記載しています。ご容赦ください。

# 決定係数

決定係数とは、回帰分析によって求められた目的変数の予測値が、実際の目的変数の値とどのくらい一致しているかを表している指標。１に近いほど分析の精度が高いことを表す。

「（自由度調整済み）決定係数さえ高ければなんでもよい」という考え方はもちろん不適切。
分析を行うからにはその目的があり、検証したい仮説があるはずです。こうした目的や仮説とは一切関係ない変数を、決定係数が上がるからという理由だけで無秩序に分析に加えてしまうと、そのモデルは解釈が難しくなり当初の目的を果たせないでしょう。
また決定係数はあくまで「予測の当てはまりの良さ」を表す指標です。分析の目的が「ある変数の値を予測したい」の場合には適切な指標ですが、「雨が降った日数がコンビニの月間の売上に影響があるかどうか知りたい」のように、ある変数の影響の有無が主眼であり予測は重視しない場合には、決定係数に注目することはあまり意味がないと言えます。この場合には「雨が降った日数」という説明変数の回帰係数や、その係数に対する検定の結果（有意かどうか）にまず注目すべきでしょう。
決定係数は分かりやすく便利な指標であるため、分析の際にはどうしてもここだけに目が行きがちです。しかしながら、本当に価値のある分析をするためには、数字の意味をしっかり理解した上で、分析の目的と照らし合わせて正しく使うことが求められます。


# 線形回帰とロジスティック回帰

### 異なる点

- 線形回帰は実際の値を予測するのに対して、ロジスティック回帰は発生確率（0~1の値）を予測する

つまり握力の例で言えば、線形回帰は「年齢から平均握力そのものを予測する」のに対して、ロジスティック回帰は「（例えば）30歳での平均握力が30kgとなる確率」を予測します。


# 実際のデータ分析での流れ

では、実際のデータ分析ではどのような流れで処理されることが多いのでしょうか。
機械学習をする場合、元データが存在した場合には、それをまずはPandasのDataFrameに落とし込んで加工します。そして、DataFrame内の必要なデータをNumPyのndarrayに変換し、機械学習の演算や高度なアルゴリズムによる処理を行う、というのがよくある方法だと思います。

![data_flow_chart](https://deepage.net/img/pandas/numpy/data_flow_chart.png)


機械学習や画像処理を含む高度なアルゴリズムはDataFrameではなく、ndarrayを引数にとることが多いです。NumPyに落とし込むのは最後の最後の段階で、NumPyが処理するのが得意な形に持っていくようPandasで色々前処理をする役割になることが多いです。
データ分析では作業時間の5割以上は前処理に割くといっても過言ではありません。そう考えると、Pandasを使った処理を覚えておくと役立つ場面が多いでしょう。


# Feature Scalingとは

特徴量の取りうる値の範囲（スケール）を変えることです。
データセットの特徴量間でスケールが異なることは多々あります。例えば、体重と身長、家の価格と部屋数では、その単位と値の範囲が異なります。
そのような特徴量間で異なるスケールのデータセットをモデルで学習させた場合、うまく学習できないということがおこるのです。
そのため、学習前の前処理で、特徴量間のスケールを揃える必要があります。

## Feature Scalingの種類

主なFeature Scalingの種類として、以下の2つがあります。

- 正規化(normalization)
- 標準化(standardization)

**正規化(normalization)とは**
正規化とは、特徴量の値の範囲を一定の範囲におさめる変換になります。主に[0, 1]か、[-1, 1]の範囲内におさめることが多いです。

**標準化(standardization)とは**
標準化とは、特徴量の平均を0、分散を1にする変換になります。


### 正規化と標準化の使い分け

基本は標準化を用います。理由は、正規化の場合、外れ値が大きく影響してしまうためです。
ただし、画像データの場合は学習コストを下げるため、[0,1]の範囲に収まるよう255.0で割ることで正規化するのが一般的です。
**正規化**
使うとき:
- 画像処理におけるRGBの強さ[0,255]
- sigmoid, tanhなどの活性化関数を用いる、NNのいくつかのモデル

**標準化**
使うとき:
- ロジスティック回帰、SVM、NNなど勾配法を用いたモデル
- kNN, k-meansなどの距離を用いるモデル
- PCA, LDA(潜在的ディリクレ配分法), kernel PCA などのfeature extractionの手法
使わないとき:
決定木、ランダムフォレスト



# 機械学習コード

## Scikit-Learn

```py
    # 基本のライブラリインポート手順
    
    # アルゴリズム、データセット、などのライブラリをインポート
    from sklearn import neighbors, datasets, preprocessing
    # トレーニング用とテスト用に分けてくれる便利な関数
    from sklearn.model_selection import train_test_split
    # 予測に対する正解率（accuracy）を出すために必要
    from sklearn.metrics import accuracy_score
    
    # 基本の学習方法手順
    
    # データセットからアヤメの花のデータを取り出す。
    iris = datasets.load_iris()
    # データの列0番目から1番目までの全行をXに入れて、
    # データの目的変数をyに入れる。
    X, y = iris.data[:, :2], iris.target
    # トレーニング用とテスト用に分ける。
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=33)
    
    # StandardScalerを使ってデータセットを標準化する。
    scaler = preprocessing.StandardScaler().fit(X_train)
    # 実際の変換作業。
    X_train = scaler.transform(X_train)
    X_test = scaler.transform(X_test)
    
    # K近傍法を使ってモデルを作成。
    knn = neighbors.KNeighborsClassifier(n_neighbors=5)
    # トレーニング用データで学習をさせる。
    knn.fit(X_train, y_train)
    # テスト用データで予測値を出す。
    y_pred = knn.predict(X_test)
    # 正解率をテスト用目的変数と予測値を使って計算する。
    accuracy_score(y_test, y_pred)
```

## Linear Regression（線形回帰）

```py
    from sklearn.linear_model import LinearRegression
    linear_model = linear_model.LinearRegression()
    linear_model.fit(X_train,y_train)
    
    # R2(決定係数)
    linear_model.score(X_test,y_test)
    # coefficient(偏回帰係数)
    print('偏回帰係数: ', linear_model.coef_)
    # indercept(切片)
    print('切片: ', linear_model.intercept_)
    #予測値を出す。
    predicted = linear_model.predict(X_test)
```

## LogisticRegression（ロジスティック回帰）

線形回帰と似てますが、目的変数が０か１、YES・NOなどの時に使います。

```py
    from sklearn.linear_model import LogisticRegression
    model = model.LogisticRegression()
    model.fit(X_train,y_train)
    
    # R2(決定係数)
    model.score(X_test,y_test)
    # coefficient(偏回帰係数)
    print('偏回帰係数: ', model.coef_)
    # indercept(切片)
    print('切片: ', model.intercept_)
    #予測値を出す。
    predicted = model.predict(X_test)
```

## Decision Tree（決定木）

```py
    from sklearn import tree
    
    # 不純度の指標をジニ係数にする。エンロトピーと使い分ける必要がある。
    model = tree.DecisionTreeClassifier(criterion='gini')
    model.fit(X_train, y_train)
    model.score(X_test, y_test)
    predicted = model.predict(X_test)
```

## SVM (サポートベクターマシン)

```py
    from sklearn import svm
    
    # クラス分類問題において、データの数がそこまで大きくない場合は
    # SVC(Linear SVM)を使います。
    model = svm.svc() 
    
    model.fit(X_train, y_train)
    model.score(X_test, y_test)
    predicted= model.predict(X_test)
```

## Naive Bayes (ナイーブベイズ)

```py
    # 数種類あるうちのガウシアン分布（正規分布）
    # を使ったベイズ分類器をインポート
    from sklearn.naive_bayes import GaussianNB
    
    model.fit(X_train, y_train)
    predicted= model.predict(X_test)
```

## kNN (K近傍法)

```py
    from sklearn.neighbors import KNeighborsClassifier
    
    # n_neighbors:Kの数はデフォルトでは5に設定されている。
    KNeighborsClassifier(n_neighbors=6)
    
    model.fit(X_train, y_train)
    predicted= model.predict(X_test)
```

## K-Means（K平均法）

```py
    from sklearn.cluster import KMeans
     
    # n_clusters:何個にクラス分けするか、random_stateは0に設定。
    k_means = KMeans(n_clusters=3, random_state=0)
    
    model.fit(X)
    predicted= model.predict(x_test)
```

## Random Forest（ランダムフォレスト）

```py
    from sklearn.ensemble import RandomForestClassifier
    
    # 決定木の深さを100に設定
    model= RandomForestClassifier(max_depth=100)
    
    model.fit(X, y)
    predicted= model.predict(x_test)
    
    # 深さ100の時の各特徴量の重要性。
    print(model.feature_importances_)
```

## Dimensionality Reduction Algorithms（次元削減）

```py
    # PCA (線形アルゴリズム)を使用
    from sklearn.decomposition import PCA
    
    # n_components:2次元に次元を削減する
    pca = PCA(n_components=2)
    
    # トレーニング用のデータセットの次元をPCAを用いて削減する。
    train_reduced = pca.fit_transform(train)
    # テスト用のデータセットの次元をPCAを用いて削減する。
    test_reduced = pca.transform(test)
```

## Gradient Boosting Algorithms（勾配ブースティング）

```py
    from sklearn.ensemble import GradientBoostingClassifier
    
    # n_estimators: 決定木の数
    # learning_rate: 結果に対する各決定木の影響度合。小さい値が良いとされているが、
    # 大きい数値で試した後小さい数値にして試すのがセオリー。
    # max_depth: 決定木の深さ。
    model= GradientBoostingClassifier(n_estimators=100, learning_rate=1.0, max_depth=1, random_state=0)
    model.fit(X, y)
    predicted= model.predict(x_test)
```

## XGBoost

XGBoostとは、先程のGradient BoostingとRandom Forestsを組み合わせたアンサンブル学習である。
アンサンブル学習とは、複数のモデル（学習器）を使い、1つの学習モデルを作成する手法。
pythonパッケージのインストールは以下のURLを参考に。

https://github.com/dmlc/xgboost/tree/master/python-package

```py
    from xgboost import XGBClassifier
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score
    X = dataset[:,0:10]
    Y = dataset[:,10:]
    seed = 1
    
    X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=seed)
    
    model = XGBClassifier()
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
```

# Scikit-Learn目的別

 
## データ前処理
 

```py
    # Standardization(標準化)
    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler().fit(X_train)
    standardized_X = scaler.transform(X_train)
    standardized_X_test = scaler.transform(X_test)

    # Normalization(正規化)
    
    from sklearn.preprocessing import Normalizer
    scaler = Normalizer().fit(X_train)
    normalized_X = scaler.transform(X_train)
    normalized_X_test = scaler.transform(X_test)

    # Binarization（二値化）
    from sklearn.preprocessing import Binarizer
    binarizer = Binarizer(threshold=0.0).fit(X)
    binary_X = binarizer.transform(X)

    # Encoding Categorical Features（文字列要素を数値コードに変換）
    from sklearn.preprocessing import LabelEncoder
    enc = LabelEncoder()
    y = enc.fit_transform(y)

    # Imputing Missing Values（欠損値の穴埋め。）
    from sklearn.preprocessing import Imputer
    # strategyで平均か中央値か最頻値を選択。
    imp = Imputer(missing_values=0, strategy='mean', axis=0)
    imp.fit_transform(X_train)

    # Generating Polynomial Features (多項式の特徴量を作る)
    from sklearn.preprocessing import PolynomialFeatures
    poly = PolynomialFeatures(5)
    poly.fit_transform(X)
```
 
## モデルの成果を評価する
 
### 分類結果を評価
 

```py
    # Accuracy Score (正解率)
    knn.score(X_test, y_test)
    from sklearn.metrics import accuracy_score
    accuracy_score(y_test, y_pred)

    # Classification Report (結果の詳細なレポートを表示)
    from sklearn.metrics import classification_report
    print(classification_report(y_test, y_pred))

    # Confusion Matrix (混同行列)
    # 正しく識別できた件数、誤って識別した件数を比較
    from sklearn.metrics import confusion_matrix
    print(confusion_matrix(y_test, y_pred))
```
 
### 回帰結果を評価
 

```py
    # Mean Absolute Error (平均絶対誤差)
    from sklearn.metrics import mean_absolute_error
    y_true = [5, -0.25, 3]
    mean_absolute_error(y_true, y_pred)

    # Mean Squared Error (平均二乗誤差)
    from sklearn.metrics import mean_squared_error
    mean_squared_error(y_test, y_pred)

    # R² Score (決定係数)
    from sklearn.metrics import r2_score
    r2_score(y_true, y_pred)
```
 
### クラスタリング結果を評価
 

```py
    # Adjusted Rand Index (ランド指数)
    from sklearn.metrics import adjusted_rand_score
    adjusted_rand_score(y_true, y_pred)    

    # Homogeneity (均一性)
    from sklearn.metrics import homogeneity_score
    homogeneity_score(y_true, y_pred) 

    # V-measure
    from sklearn.metrics import v_measure_score
    metrics.v_measure_score(y_true, y_pred)
```
 
### 交差検証
 

```py
    from sklearn.cross_validation import cross_val_score
    
    print(cross_val_score(knn, X_train, y_train, cv=4))
    print(cross_val_score(lr, X, y, cv=2))    
```
 
## 学習モデルの調整
 
### グリッドサーチ
 

```py
    from sklearn.grid_search import GridSearchCV
    
    # 最適化したいパラメータを設定
    params = {"n_neighbors": np.arange(1,3), "metric": ["euclidean", "cityblock"]}
    # パラメータを最適化
    grid = GridSearchCV(estimator=knn, param_grid=params)
    grid.fit(X_train, y_train)
    print(grid.best_score_)
    print(grid.best_estimator_.n_neighbors   
```
 
### ランダムサーチ
 

```py
    from sklearn.grid_search import RandomizedSearchCV
    
    # 最適化したいパラメータを設定
    params = {"n_neighbors": range(1,5), "weights": ["uniform", "distance"]}
    rsearch = RandomizedSearchCV(estimator=knn, param_distributions=params, cv=4, n_iter=8, random_state=5)
    rsearch.fit(X_train, y_train)
    print(rsearch.best_score_)  
```
 
# Numpy

```py
    # Numpy配列を作り、同時に2行4列にする。
    np.array([1,2,3,5,6,7,8,9]).reshape(2,4)
    
    # ゼロ埋め
    np.zeros((3,4))
    
    # 1で埋める
    np.ones((2,3,4),dtype=np.int16)
    
    # ランダムな要素をもつ4行5列の配列を作る
    np.empty((4, 5))
    
    # 10から25までの整数を5間隔の配列にする
    np.arange(10,25,5)             
    
    # 0から2までを等間隔で9に分割
    np.linspace(0,2,9)
    
    # 正規分布の乱数を100個生成
    np.random.randn(100)
    
    # 20から100までの整数の中から一つだけランダムで選ぶ
    np.random.randint(20,100)
    
    # 転置
    # bは3行5列の配列
    t = np.T(b)
    # tは5行3列の配列に入れ替わる
    
    # 行列の掛け算
    np.dot(t,b)
    
    # 配列の連結
    # axis=1は列方向への結合
    # axis=0は行方向への結合
    a=np.array([[1,2,3,4,5,6],[1,2,3,4,5,6]])
    d=np.array([[1,2,3,4,5,6],[1,2,3,4,5,6]])
    np.concatenate((a,d),axis=1)
    np.concatenate((a,d),axis=0) 
    
    # 行方向への結合
    np.vstack((a,b))             
    
    # 列方向への結合
    np.hstack((e,f))             
    
    # 列方向に指定した数で等分する。                  
    np.hsplit(matrix_arr,3)    
    
    # 行方向に指定した数で等分する。
    np.vsplit(matrix_arr,2)    
```
 
# pandas

```py
    # データフレームを作る
    columns = ['A','B','C']
    rows = [[1,2,3],[4,5,6],[7,8,9]]
    df = pd.DataFrame(rows,columns=columns)
    
    # ファイルを読み込む。
    df = pd.read_csv('file.csv')
    df = pd.read_json('file.json')
    df = pd.read_excel('file.xlsx')
    
    # ファイルを書き込む。
    df.to_csv('file.csv')
    df.to_json('file.json')
    df.to_excel('file.xlsx')
    
    # URLからでも読み込める
    df = pd.read_csv('http://example/bacon/spam/ham/egg/file.csv')
    
    # エクセルシートで指定してデータフレームを作る。
    xlsx = pd.ExcelFile('file.xlsx')
    df = pd.read_excel(xlsx, 'Sheet1')
    
    # 行と列を整数で指定
    df.iloc[[0],[0]]
    
    # 列を文字列で指定
    df.loc[[0], ['Country']]
    
    # 条件を指定して行や列の値を取る
    df[df['A']>2]        
    df[df['B']==1]
    
    # 行や列に関数を働かせる
    df['A'].apply(str)
    df['A'].apply(lambda x: str(x) if x>2 else x)
    
    # 欠損値を見つけ、欠損値を削除
    df.isnull()
    # すべてが欠損値の行であれば、その行は削除される。
    df.dropna(how='all')
    # axis=1なら行方向が削除される。
    # つまり、すべてが欠損値の列であれば、その列は削除される。
    df.dropna(how='all', axis=1)
    # howにanyを指定すると、
    # 欠損値が一つでも含まれる行が削除される。
    df2.dropna(how='any')
    # axis=1にすると列に適用。つまり行方向に適用。
    # 欠損値が一つでも含まれる列が削除される。
    df2.dropna(how='any', axis=1)
    
    # 新しい列を加える。
    # 目的変数や分析結果を加えるさいに便利。
    df['new_columns'] = new_row
    
    # 基本的だが本当によく使う
    
    # 行列数を表示
    df.shape
    # インデックスの情報
    df.index 
    # 列の情報を表示
    df.columns
    # 欠損値やオブジェクトタイプを調べるさいに便利 
    df.info()
    # ユニークなオブジェクトの個数をカウント
    df.count()
    
    # axisなどで行方向や列方向も指定できるものがある。
    # すべての列を足す
    df.sum() 
    # 一つ上の行から順番に足して表示         
    df.cumsum()
    # 最小値、最大値を表示
    df.min()/df.max()
    # 最大値・最小値の要素のインデックス（ラベル）が取得できる。
    df.idxmin()/df.idxmax()
    #  平均値や偏差や最大値などの数値情報がまとめて表示される。
    df.describe()
    # 平均値を求める。
    df.mean()  
    # 中央値を取得する
    df.median()
```