機械学習実践 データの初期解析

パッケージのダウンロードとインポート

import numpy as np
#!pip install numpy
#!conda install numpy

import pandas as pd 
#!pip install pandas
#!conda install pandas

import pandas_profiling as pdp
#!pip install pandas_profiling

※ condaでパッケージの管理されている方はpandas_profilingのパッケージのインストールには、
Anaconda Promptから下記 のコマンドをお試し下さい。
conda install -c conda-forge pandas-profiling

import matplotlib 
#!pip install matplotlib 
#!conda install matplotlib 

import seaborn
#!pip install seaborn
#!conda install seaborn

import sklearn
#!pip install scikit-kearn
#!conda install scikit-kearn

import xgboost
#!pip install xgboost

※ condaでパッケージの管理されている方はxgboostのパッケージのインストールには、
Anaconda Promptから下記OSに対応したのコマンドをお試し下さい。
Windows : conda install -c conda-forge py-xgboost
Mac or Linux : conda install -c conda-forge xgboost

import numpy as np
import pandas as pd
import pandas_profiling as pdp
import matplotlib.pyplot as plt
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import seaborn as sns
import pickle
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, f1_score, roc_curve, roc_auc_score
from sklearn.ensemble import RandomForestClassifier
import xgboost as xgb
import warnings
warnings.simplefilter('ignore')
Pythonでは廃止予定の関数を使った場合などに警告(Warning)が出力されることがあります。
本講座ではwarningsを用いて警告を非表示にします。

データの確認

パスの指定

以下のパス指定はこの.ipynbファイルとUCI_Credit_Card_light.csvファイルが同一ディレクトリ(フォルダ)内に存在する場合の指定方法

csvDataPath = 'UCI_Credit_Card_light.csv'
#csvDataPath = 'UCI_Credit_Card.csv'

ファイルの読み込み

  • .read_csv()の引数でengine=’python’とすることで、ファイル名に日本語が含まれる場合の読み込みエラーを回避
  • .read_csv()の引数でencoding=’utf-8′とすることで、Mac環境下で作成されたcsvファイル(配布データ)の読み込みエラーを回避
data = pd.read_csv(csvDataPath, engine='python', encoding='utf-8')

※Windows環境下で作成されたcsvファイルをMac環境下で読み込む際にはencoding=’cp932′と変更

データの形状確認

data.shape
(1000, 25)

1000行、25列のデータ

Columnsで列名確認

data.columns
Index(['ID', 'LIMIT_BAL', 'SEX', 'EDUCATION', 'MARRIAGE', 'AGE', 'PAY_0',
       'PAY_2', 'PAY_3', 'PAY_4', 'PAY_5', 'PAY_6', 'BILL_AMT1', 'BILL_AMT2',
       'BILL_AMT3', 'BILL_AMT4', 'BILL_AMT5', 'BILL_AMT6', 'PAY_AMT1',
       'PAY_AMT2', 'PAY_AMT3', 'PAY_AMT4', 'PAY_AMT5', 'PAY_AMT6',
       'default.payment.next.month'],
      dtype='object')

dtypeでデータの型の確認

data.dtypes
ID                              int64
LIMIT_BAL                     float64
SEX                             int64
EDUCATION                       int64
MARRIAGE                        int64
AGE                             int64
PAY_0                           int64
PAY_2                           int64
PAY_3                           int64
PAY_4                           int64
PAY_5                           int64
PAY_6                           int64
BILL_AMT1                       int64
BILL_AMT2                       int64
BILL_AMT3                     float64
BILL_AMT4                       int64
BILL_AMT5                       int64
BILL_AMT6                       int64
PAY_AMT1                        int64
PAY_AMT2                        int64
PAY_AMT3                        int64
PAY_AMT4                      float64
PAY_AMT5                      float64
PAY_AMT6                        int64
default.payment.next.month      int64
dtype: object

info でも詳細な情報を確認
.dtypesよりもindexの開始と終了の情報、null情報まで含まれたデータの詳細を一覧で取得

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 25 columns):
 #   Column                      Non-Null Count  Dtype  
---  ------                      --------------  -----  
 0   ID                          1000 non-null   int64  
 1   LIMIT_BAL                   1000 non-null   float64
 2   SEX                         1000 non-null   int64  
 3   EDUCATION                   1000 non-null   int64  
 4   MARRIAGE                    1000 non-null   int64  
 5   AGE                         1000 non-null   int64  
 6   PAY_0                       1000 non-null   int64  
 7   PAY_2                       1000 non-null   int64  
 8   PAY_3                       1000 non-null   int64  
 9   PAY_4                       1000 non-null   int64  
 10  PAY_5                       1000 non-null   int64  
 11  PAY_6                       1000 non-null   int64  
 12  BILL_AMT1                   1000 non-null   int64  
 13  BILL_AMT2                   1000 non-null   int64  
 14  BILL_AMT3                   1000 non-null   float64
 15  BILL_AMT4                   1000 non-null   int64  
 16  BILL_AMT5                   1000 non-null   int64  
 17  BILL_AMT6                   1000 non-null   int64  
 18  PAY_AMT1                    1000 non-null   int64  
 19  PAY_AMT2                    1000 non-null   int64  
 20  PAY_AMT3                    1000 non-null   int64  
 21  PAY_AMT4                    1000 non-null   float64
 22  PAY_AMT5                    1000 non-null   float64
 23  PAY_AMT6                    1000 non-null   int64  
 24  default.payment.next.month  1000 non-null   int64  
dtypes: float64(4), int64(21)
memory usage: 195.4 KB

.dtypes.infoどちらを見ても欠損値が無さそうなことが確認できます。

.value_counts()でユニークな値とその出現頻度を確認
【Point】.value_counts()はPandasのDataFrame型では使用不可なので、
 列名を指定してSeries型などで使用するのが一般的です。

data['default.payment.next.month'].value_counts()
0    786
1    214
Name: default.payment.next.month, dtype: int64
data['SEX'].value_counts()
2    591
1    409
Name: SEX, dtype: int64

ユニークな値とその出現頻度の確認は下記メソッドでも取得可能です。

data.groupby('SEX').size()
groupbyの時のみ.size()が使用できる
SEX
1    409
2    591
dtype: int64

先頭の5行を出力

data.head()

ID
LIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_0PAY_2PAY_3PAY_4BILL_AMT4BILL_AMT5BILL_AMT6PAY_AMT1PAY_AMT2PAY_AMT3PAY_AMT4PAY_AMT5PAY_AMT6default.payment.next.month
0120000.02212422-1-1000068900.00.001
12120000.022226-12003272345532610100010001000.00.020001
2390000.02223400001433114948155491518150010001000.01000.050000
3450000.02213700002831428959295472000201912001100.01069.010000
4550000.012157-10-10209401914619131200036681100009000.0689.06790

tail()で読み込んだデータの末尾5行を出力

data.tail()
IDLIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_0PAY_2PAY_3PAY_4BILL_AMT4BILL_AMT5BILL_AMT6PAY_AMT1PAY_AMT2PAY_AMT3PAY_AMT4PAY_AMT5PAY_AMT6default.payment.next.month
995996200000.011239-2-2-2-206080000020060800.00.000
996997140000.01114500004445245433463831600160031691700.01700.014950
997998360000.0111381-2-2-20000000.00.001
99899950000.022223-1-1-1039039050007800390.0500.0183001
9991000120000.01222522008385886434888020500031583934.03802.020000

データ基礎集計

【Point】基礎集計とは

  • 異常値(定義上ありえない値)の確認
  • 外れ値(他の値から大きく外れた値)の確認
  • 頻度の少ないデータがないの確認
  • 学習、評価データで分布に偏りがないかの確認

などの確認をすることです。

.describe()で各列の要約統計量を確認

.describe()メソッドで各列の要約統計量を取得可能

  • count : 列毎のデータの総数(欠損値を除いた総数)
  • mean : 列毎のデータの平均
  • std : 列毎のデータの分散
  • min : 列毎のデータの最小値
  • 25% : 列毎のデータの1/4分位数
  • 50% : 列毎のデータの中央値
  • 75% : 列毎のデータの3/4分位数
  • max : 列毎のデータの最大値
data.describe()

ID
LIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_0PAY_2PAY_3PAY_4BILL_AMT4BILL_AMT5BILL_AMT6PAY_AMT1PAY_AMT2PAY_AMT3PAY_AMT4PAY_AMT5PAY_AMT6default.payment.next.month
count1000.0000001000.0000001000.0000001000.0000001000.000001000.000001000.0000001000.0000001000.0000001000.0000001000.0000001000.000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.000000
mean500.500000167080.0000001.5910001.7760001.6050034.93800-0.002000-0.153000-0.161000-0.28000040737.46700038964.4860037992.6700005373.2560005048.4340004089.6580004570.4860005330.3930005102.2910000.214000
std288.819436130632.8386680.4918950.7499240.532229.228181.1736161.2300831.2604241.18279368198.05983863073.3699163056.50713412186.99637915634.44303510171.73384512929.41055616820.51240323669.3635880.410332
min1.00000010000.0000001.0000001.0000000.0000021.00000-2.000000-2.000000-2.000000-2.000000-3684.000000-28335.00000-339603.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000
25%250.75000050000.0000001.0000001.0000001.0000028.00000-1.000000-1.000000-1.000000-1.0000001441.7500001240.50000859.2500001000.000000390.000000231.750000149.500000194.2500000.0000000.000000
50%500.500000140000.0000002.0000002.0000002.0000033.000000.0000000.0000000.0000000.00000017743.00000017539.5000015860.0000002148.0000001700.0000001200.0000001368.0000001304.5000001274.0000000.000000
75%750.250000240000.0000002.0000002.0000002.0000041.000000.0000000.0000000.0000000.00000048698.00000045890.0000046551.0000005086.2500004500.0000003705.0000004000.0000003739.7500003800.0000000.000000
max1000.000000700000.0000002.0000006.0000003.0000075.000008.0000007.0000007.0000007.000000628699.000000484612.00000473944.000000199646.000000285138.000000133657.000000188840.000000195599.000000528666.0000001.000000

pandas_profilingパッケージ

データの基礎集計を自動的に出力してくれる便利なパッケージを紹介
出力を保存することができないので、報告書の作成などには使用できませんが、
データ分析をしていくにあたって非常に有効なパッケージです。
※2020年1月現在
このパッケージで出力される主な項目

  • データの基礎集計
  • データの列毎に値の可視化
  • データの列間の相関係数の可視化
  • データの先頭5行の出力
pdp.ProfileReport(data)

恐らくパソコンに負荷がかかるので、すぐにはできないし、表示でバグる

データの次元削除

今回のデータ分析における機械学習タスクはデフォルトの支払い(1 =はい、0 =いいえ)を予測するモデルを生成することです。

【Point】次元削減の目的

  • データの圧縮
  • データの可視化

データの圧縮を利用して、上手く可視化ができれば、
この後の機械学習モデルを用いた予測タスクでも結果に期待が持てます。
次項より、実際にモデルを作成する前にデータ圧縮アルゴリズムを適応し、
データが分離できるかを確認しましょう!!

この節でのデータの次元削減&圧縮の流れ

  1. データ圧縮のアルゴリズム(PCA or t-SNE)を選択
  2. 1.で選択したアルゴリズムを用いてデータを圧縮
  3. 元のラベルに対応したもので色分けして可視化
  4. 図から結果を解釈

PCAでデータを2次元に圧縮
sklearn.decompositionからPCAを呼び出しPCAのアルゴリズムを使用

from sklearn.decomposition import PCA

PCAモデルをパッケージからPCA()で呼び出し
n_componentsで出力したい次元数を指定

pca2 = PCA(n_components=2)

【Point】PCAを使用する場合にはデータのスケーリングは必須
スケーリングとは

  • 特徴量において値を一定のルールに基づいて一定の範囲に変換する処理のことを指します。
  • スケーリングには、以下が含まれます。
    • 正規化
      • 0〜1に変換します。
    • 標準化
      • 平均を0、分散を1に変換します。
  • スケーリングは、全ての機械学習モデルに有効に働くわけではない。

今回はStandardScaler()の標準化オブジェクトを使用

normalizeData = StandardScaler().fit_transform(data.iloc[:,:-1].values)

.fit_transform()は引数に入れたデータを変換

dim2PcaData = pca2.fit_transform(normalizeData)  
dim2PcaData
array([[-1.80038036,  0.81909525],
       [-0.71967801,  2.13931444],
       [-0.77658719,  1.09908465],
       ...,
       [-2.70233593, -2.08333828],
       [-2.17130871,  0.15167891],
       [ 2.34242597,  1.10493742]])
type(dim2PcaData)
numpy.ndarray

出力がnumpy配列で出力されるのでデータを扱いやすくするためにDataFrame型に変換します。
変換にはpd.DataFrame()を使用

dim2PcaData = pd.DataFrame(dim2PcaData)  
dim2PcaData
01
0-1.8003800.819092
1-0.7196782.139315
2-0.7765871.099085
3-0.1136460.788312
4-0.556334-0.161409
995-2.458492-3.022611
9960.7646561.429973
997-2.702336-2.083340
998-2.1713090.151679
9992.3424261.104936

PCAでデータを2次元に圧縮したデータを可視化

.unique()でカテゴリのユニーク値を取得

data['default.payment.next.month'].unique()
array([1, 0], dtype=int64)

len()でユニークな値の総数を取得

num= len(data['default.payment.next.month'].unique())
num
2

default.payment.next.month列が0の行を真偽値(True or False)で取得

data['default.payment.next.month'] == 0
0      False
1      False
2       True
3       True
4       True
       ...  
995     True
996     True
997    False
998    False
999     True
Name: default.payment.next.month, Length: 1000, dtype: bool
data[data['default.payment.next.month'] == 0]
IDLIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_0PAY_2PAY_3PAY_4BILL_AMT4BILL_AMT5BILL_AMT6PAY_AMT1PAY_AMT2PAY_AMT3PAY_AMT4PAY_AMT5PAY_AMT6default.payment.next.month
2390000.02223400001433114948155491518150010001000.01000.050000
3450000.02213700002831428959295472000201912001100.01069.010000
4550000.012157-10-10209401914619131200036681100009000.0689.06790
5650000.0112370000193941961920024250018156571000.01000.08000
67500000.011229000054265348300347394455000400003800020239.013750.0137700
99099150000.023139002-1298863051031276787616174354927.01089.091000
99299380000.02222700006107762394636552200220022002300.02300.026000
995996200000.011239-2-2-2-206080000020060800.00.000
996997140000.01114500004445245433463831600160031691700.01700.014950
9991000120000.01222522008385886434888020500031583934.03802.020000

圧縮したデータのdefault.payment.next.month列が0の行を取得

dim2PcaData[data['default.payment.next.month'] == 0]
01
2-0.7765871.099085
3-0.1136460.788312
4-0.556334-0.161409
5-0.1369550.771869
614.196500-7.098182
9900.7252260.156061
9920.5190970.645022
995-2.458492-3.022611
9960.7646561.429973
9992.3424261.104936
num = len(data['default.payment.next.month'].unique())
fig = plt.figure(num)
for i in range(num):
    target = dim2PcaData[data['default.payment.next.month'] == i]
    plt.scatter(x=target.iloc[:, 0], y=target.iloc[:, 1], label=str(i), alpha=0.5)

t-sneでデータを2次元に圧縮

sklearn.manifoldからTSNEを呼び出しt-SNEのアルゴリズムを使用

from sklearn.manifold import TSNE
dim2TsneData = TSNE(n_components=2).fit_transform(data.iloc[:,:-1])
dim2TsneData = pd.DataFrame(dim2TsneData)  

T-sneでは正規化は必要ない?

t-SNEでデータを2次元に圧縮したデータを可視化

num = len(data['default.payment.next.month'].unique())
for i in range(num):
    target = dim2TsneData [data['default.payment.next.month'] == i]
    plt.scatter(x=target.iloc[:, 0], y=target.iloc[:, 1], label=str(i), alpha=0.5)

PCAでデータを3次元に圧縮

pca3 = PCA(n_components=3)
normalizeData = StandardScaler().fit_transform(data.iloc[:,:-1].values)
dim3PcaData = pca3.fit_transform(normalizeData)  
dim3PcaData = pd.DataFrame(dim3PcaData)  
dim3PcaData

0
12
0-1.8002960.818727-0.487829
1-0.7196992.139406-0.706373
2-0.7766091.099165-0.431466
3-0.1136250.7882120.506859
4-0.556319-0.1614872.834209
995-2.458509-3.022545-0.888508
9960.7646481.4299831.232998
997-2.702318-2.0834000.341959
998-2.1713030.151652-0.841872
9992.3424581.104799-1.074316

PCAでデータを3次元に圧縮したデータを可視化

num= len(data['default.payment.next.month'].unique())
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in range(num):
    target =dim3PcaData[data['default.payment.next.month'] == i]
    ax.scatter(
        xs=target.iloc[:, 0], ys=target.iloc[:, 1],  zs=target.iloc[:, 2],label=str(i), alpha=0.5)

t-SNEでデータを3次元に圧縮

dim3TsneData = TSNE(n_components=3).fit_transform(data.iloc[:,:-1])
dim3TsneData = pd.DataFrame(dim3TsneData) 

t-SNEでデータを3次元に圧縮したデータを可視化

num= len(data['default.payment.next.month'].unique())
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in range(num):
    target =dim3TsneData[data['default.payment.next.month'] == i]
    ax.scatter(
        xs=target.iloc[:, 0], ys=target.iloc[:, 1],  zs=target.iloc[:, 2],label=str(i), alpha=0.5)

今回可視化した4つ図のどれを見てもデータが上手に分割されている様子は伺えません。
残念ながら、データ圧縮・可視化だけでは今回の機械学習タスクが上手くいくかの見通しは立ちませんでした。
実際のデータ分析においてもこのような場面に多く遭遇しますので、様々な仮説をもって、
多角的な視点からEDAをすることはデータサイエンティストにとって非常に重要なことになります。

コメント

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