パッケージのダウンロードとインポート
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_BAL | SEX | EDUCATION | MARRIAGE | AGE | PAY_0 | PAY_2 | PAY_3 | PAY_4 | … | BILL_AMT4 | BILL_AMT5 | BILL_AMT6 | PAY_AMT1 | PAY_AMT2 | PAY_AMT3 | PAY_AMT4 | PAY_AMT5 | PAY_AMT6 | default.payment.next.month | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 20000.0 | 2 | 2 | 1 | 24 | 2 | 2 | -1 | -1 | … | 0 | 0 | 0 | 0 | 689 | 0 | 0.0 | 0.0 | 0 | 1 |
1 | 2 | 120000.0 | 2 | 2 | 2 | 26 | -1 | 2 | 0 | 0 | … | 3272 | 3455 | 3261 | 0 | 1000 | 1000 | 1000.0 | 0.0 | 2000 | 1 |
2 | 3 | 90000.0 | 2 | 2 | 2 | 34 | 0 | 0 | 0 | 0 | … | 14331 | 14948 | 15549 | 1518 | 1500 | 1000 | 1000.0 | 1000.0 | 5000 | 0 |
3 | 4 | 50000.0 | 2 | 2 | 1 | 37 | 0 | 0 | 0 | 0 | … | 28314 | 28959 | 29547 | 2000 | 2019 | 1200 | 1100.0 | 1069.0 | 1000 | 0 |
4 | 5 | 50000.0 | 1 | 2 | 1 | 57 | -1 | 0 | -1 | 0 | … | 20940 | 19146 | 19131 | 2000 | 36681 | 10000 | 9000.0 | 689.0 | 679 | 0 |
tail()で読み込んだデータの末尾5行を出力
data.tail()
ID | LIMIT_BAL | SEX | EDUCATION | MARRIAGE | AGE | PAY_0 | PAY_2 | PAY_3 | PAY_4 | … | BILL_AMT4 | BILL_AMT5 | BILL_AMT6 | PAY_AMT1 | PAY_AMT2 | PAY_AMT3 | PAY_AMT4 | PAY_AMT5 | PAY_AMT6 | default.payment.next.month | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
995 | 996 | 200000.0 | 1 | 1 | 2 | 39 | -2 | -2 | -2 | -2 | … | 0 | 60800 | 0 | 0 | 0 | 200 | 60800.0 | 0.0 | 0 | 0 |
996 | 997 | 140000.0 | 1 | 1 | 1 | 45 | 0 | 0 | 0 | 0 | … | 44452 | 45433 | 46383 | 1600 | 1600 | 3169 | 1700.0 | 1700.0 | 1495 | 0 |
997 | 998 | 360000.0 | 1 | 1 | 1 | 38 | 1 | -2 | -2 | -2 | … | 0 | 0 | 0 | 0 | 0 | 0 | 0.0 | 0.0 | 0 | 1 |
998 | 999 | 50000.0 | 2 | 2 | 2 | 23 | -1 | -1 | -1 | 0 | … | 390 | 390 | 500 | 0 | 780 | 0 | 390.0 | 500.0 | 18300 | 1 |
999 | 1000 | 120000.0 | 1 | 2 | 2 | 25 | 2 | 2 | 0 | 0 | … | 83858 | 86434 | 88802 | 0 | 5000 | 3158 | 3934.0 | 3802.0 | 2000 | 0 |
データ基礎集計
【Point】基礎集計とは
- 異常値(定義上ありえない値)の確認
- 外れ値(他の値から大きく外れた値)の確認
- 頻度の少ないデータがないの確認
- 学習、評価データで分布に偏りがないかの確認
などの確認をすることです。
.describe()で各列の要約統計量を確認
.describe()
メソッドで各列の要約統計量を取得可能
count
: 列毎のデータの総数(欠損値を除いた総数)mean
: 列毎のデータの平均std
: 列毎のデータの分散min
: 列毎のデータの最小値25%
: 列毎のデータの1/4分位数50%
: 列毎のデータの中央値75%
: 列毎のデータの3/4分位数max
: 列毎のデータの最大値
data.describe()
ID | LIMIT_BAL | SEX | EDUCATION | MARRIAGE | AGE | PAY_0 | PAY_2 | PAY_3 | PAY_4 | … | BILL_AMT4 | BILL_AMT5 | BILL_AMT6 | PAY_AMT1 | PAY_AMT2 | PAY_AMT3 | PAY_AMT4 | PAY_AMT5 | PAY_AMT6 | default.payment.next.month | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.00000 | 1000.00000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 | … | 1000.000000 | 1000.00000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 |
mean | 500.500000 | 167080.000000 | 1.591000 | 1.776000 | 1.60500 | 34.93800 | -0.002000 | -0.153000 | -0.161000 | -0.280000 | … | 40737.467000 | 38964.48600 | 37992.670000 | 5373.256000 | 5048.434000 | 4089.658000 | 4570.486000 | 5330.393000 | 5102.291000 | 0.214000 |
std | 288.819436 | 130632.838668 | 0.491895 | 0.749924 | 0.53222 | 9.22818 | 1.173616 | 1.230083 | 1.260424 | 1.182793 | … | 68198.059838 | 63073.36991 | 63056.507134 | 12186.996379 | 15634.443035 | 10171.733845 | 12929.410556 | 16820.512403 | 23669.363588 | 0.410332 |
min | 1.000000 | 10000.000000 | 1.000000 | 1.000000 | 0.00000 | 21.00000 | -2.000000 | -2.000000 | -2.000000 | -2.000000 | … | -3684.000000 | -28335.00000 | -339603.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
25% | 250.750000 | 50000.000000 | 1.000000 | 1.000000 | 1.00000 | 28.00000 | -1.000000 | -1.000000 | -1.000000 | -1.000000 | … | 1441.750000 | 1240.50000 | 859.250000 | 1000.000000 | 390.000000 | 231.750000 | 149.500000 | 194.250000 | 0.000000 | 0.000000 |
50% | 500.500000 | 140000.000000 | 2.000000 | 2.000000 | 2.00000 | 33.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | … | 17743.000000 | 17539.50000 | 15860.000000 | 2148.000000 | 1700.000000 | 1200.000000 | 1368.000000 | 1304.500000 | 1274.000000 | 0.000000 |
75% | 750.250000 | 240000.000000 | 2.000000 | 2.000000 | 2.00000 | 41.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | … | 48698.000000 | 45890.00000 | 46551.000000 | 5086.250000 | 4500.000000 | 3705.000000 | 4000.000000 | 3739.750000 | 3800.000000 | 0.000000 |
max | 1000.000000 | 700000.000000 | 2.000000 | 6.000000 | 3.00000 | 75.00000 | 8.000000 | 7.000000 | 7.000000 | 7.000000 | … | 628699.000000 | 484612.00000 | 473944.000000 | 199646.000000 | 285138.000000 | 133657.000000 | 188840.000000 | 195599.000000 | 528666.000000 | 1.000000 |
pandas_profilingパッケージ
データの基礎集計を自動的に出力してくれる便利なパッケージを紹介
出力を保存することができないので、報告書の作成などには使用できませんが、
データ分析をしていくにあたって非常に有効なパッケージです。
※2020年1月現在
このパッケージで出力される主な項目
- データの基礎集計
- データの列毎に値の可視化
- データの列間の相関係数の可視化
- データの先頭5行の出力
pdp.ProfileReport(data)
恐らくパソコンに負荷がかかるので、すぐにはできないし、表示でバグる
データの次元削除
今回のデータ分析における機械学習タスクはデフォルトの支払い(1 =はい、0 =いいえ)
を予測するモデルを生成することです。
【Point】次元削減の目的
- データの圧縮
- データの可視化
データの圧縮を利用して、上手く可視化ができれば、
この後の機械学習モデルを用いた予測タスクでも結果に期待が持てます。
次項より、実際にモデルを作成する前にデータ圧縮アルゴリズムを適応し、
データが分離できるかを確認しましょう!!
この節でのデータの次元削減&圧縮の流れ
- データ圧縮のアルゴリズム(PCA or t-SNE)を選択
- 1.で選択したアルゴリズムを用いてデータを圧縮
- 元のラベルに対応したもので色分けして可視化
- 図から結果を解釈
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
0 | 1 | |
---|---|---|
0 | -1.800380 | 0.819092 |
1 | -0.719678 | 2.139315 |
2 | -0.776587 | 1.099085 |
3 | -0.113646 | 0.788312 |
4 | -0.556334 | -0.161409 |
… | … | … |
995 | -2.458492 | -3.022611 |
996 | 0.764656 | 1.429973 |
997 | -2.702336 | -2.083340 |
998 | -2.171309 | 0.151679 |
999 | 2.342426 | 1.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]
ID | LIMIT_BAL | SEX | EDUCATION | MARRIAGE | AGE | PAY_0 | PAY_2 | PAY_3 | PAY_4 | … | BILL_AMT4 | BILL_AMT5 | BILL_AMT6 | PAY_AMT1 | PAY_AMT2 | PAY_AMT3 | PAY_AMT4 | PAY_AMT5 | PAY_AMT6 | default.payment.next.month | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2 | 3 | 90000.0 | 2 | 2 | 2 | 34 | 0 | 0 | 0 | 0 | … | 14331 | 14948 | 15549 | 1518 | 1500 | 1000 | 1000.0 | 1000.0 | 5000 | 0 |
3 | 4 | 50000.0 | 2 | 2 | 1 | 37 | 0 | 0 | 0 | 0 | … | 28314 | 28959 | 29547 | 2000 | 2019 | 1200 | 1100.0 | 1069.0 | 1000 | 0 |
4 | 5 | 50000.0 | 1 | 2 | 1 | 57 | -1 | 0 | -1 | 0 | … | 20940 | 19146 | 19131 | 2000 | 36681 | 10000 | 9000.0 | 689.0 | 679 | 0 |
5 | 6 | 50000.0 | 1 | 1 | 2 | 37 | 0 | 0 | 0 | 0 | … | 19394 | 19619 | 20024 | 2500 | 1815 | 657 | 1000.0 | 1000.0 | 800 | 0 |
6 | 7 | 500000.0 | 1 | 1 | 2 | 29 | 0 | 0 | 0 | 0 | … | 542653 | 483003 | 473944 | 55000 | 40000 | 38000 | 20239.0 | 13750.0 | 13770 | 0 |
… | … | … | … | … | … | … | … | … | … | … | … | … | … | … | … | … | … | … | … | … | … |
990 | 991 | 50000.0 | 2 | 3 | 1 | 39 | 0 | 0 | 2 | -1 | … | 29886 | 30510 | 31276 | 7876 | 161 | 74354 | 927.0 | 1089.0 | 9100 | 0 |
992 | 993 | 80000.0 | 2 | 2 | 2 | 27 | 0 | 0 | 0 | 0 | … | 61077 | 62394 | 63655 | 2200 | 2200 | 2200 | 2300.0 | 2300.0 | 2600 | 0 |
995 | 996 | 200000.0 | 1 | 1 | 2 | 39 | -2 | -2 | -2 | -2 | … | 0 | 60800 | 0 | 0 | 0 | 200 | 60800.0 | 0.0 | 0 | 0 |
996 | 997 | 140000.0 | 1 | 1 | 1 | 45 | 0 | 0 | 0 | 0 | … | 44452 | 45433 | 46383 | 1600 | 1600 | 3169 | 1700.0 | 1700.0 | 1495 | 0 |
999 | 1000 | 120000.0 | 1 | 2 | 2 | 25 | 2 | 2 | 0 | 0 | … | 83858 | 86434 | 88802 | 0 | 5000 | 3158 | 3934.0 | 3802.0 | 2000 | 0 |
圧縮したデータのdefault.payment.next.month
列が0の行を取得
dim2PcaData[data['default.payment.next.month'] == 0]
0 | 1 | |
---|---|---|
2 | -0.776587 | 1.099085 |
3 | -0.113646 | 0.788312 |
4 | -0.556334 | -0.161409 |
5 | -0.136955 | 0.771869 |
6 | 14.196500 | -7.098182 |
… | … | … |
990 | 0.725226 | 0.156061 |
992 | 0.519097 | 0.645022 |
995 | -2.458492 | -3.022611 |
996 | 0.764656 | 1.429973 |
999 | 2.342426 | 1.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 | 1 | 2 | |
---|---|---|---|
0 | -1.800296 | 0.818727 | -0.487829 |
1 | -0.719699 | 2.139406 | -0.706373 |
2 | -0.776609 | 1.099165 | -0.431466 |
3 | -0.113625 | 0.788212 | 0.506859 |
4 | -0.556319 | -0.161487 | 2.834209 |
… | … | … | … |
995 | -2.458509 | -3.022545 | -0.888508 |
996 | 0.764648 | 1.429983 | 1.232998 |
997 | -2.702318 | -2.083400 | 0.341959 |
998 | -2.171303 | 0.151652 | -0.841872 |
999 | 2.342458 | 1.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をすることはデータサイエンティストにとって非常に重要なことになります。
コメント