Posted at

機械学習の理論Python編 #5 Unit 2: 分類学習の準備のための探索的データ解析 [MOOC/edX]

edXの「Principles of Machine Learning: Python Edition(機械学習の理論 Python編)」をまとめています。

前回の記事←→次回の記事

各回のソースコード全体はこちら。記事のコードは抜粋です。

今回は、分類学習(Classification)の解析をするための準備段階にやるべきことを学びます。

クレジットカード保有者のデータを例に、箱ひげ図とバイオリンプロットで数値データを可視化して分布を確認したり、ヒストグラムでカテゴリカルデータを可視化して分布を確認したりします。

クレジットカード保有者のデータセットはこんな感じ(長いので一部省略)

Screen Shot 2018-11-16 at 08.54.50.png

Screen Shot 2018-11-16 at 08.55.27.png

画像2枚目一番右のラベルにあるbad_creditは、1だと信用がないユーザ、0がそれ以外の普通のユーザ。このようなラベルを今後の機械学習の解析に使うことを想定して、このラベルに紐づいた数値データの特徴、カテゴリカルデータの特徴を調べるのが今回の目標です。


1. データの可視化


1.1 箱ひげ図とバイオリンプロットで数値データの可視化

箱ひげ図とバイオリンプロットをいくつも実行してみる。目立った特徴を発見できたグラフ('loan_duration_mo', 'loan_amount', 'payment_pcnt_income')とその解説だけ抜粋して載せます。コードは全部いっぺんに描画するように書いてあるものを載せています。


箱ひげ図の描画とバイオリンプロットの描画

# 箱ひげ図

def plot_box(credit, cols, col_x = 'bad_credit'):
for col in cols:
sns.set_style("whitegrid")
sns.boxplot(col_x, col, data=credit)
plt.xlabel(col_x) # Set text for the x axis
plt.ylabel(col)# Set text for y axis
plt.show()

num_cols = ['loan_duration_mo', 'loan_amount', 'payment_pcnt_income',
'age_yrs', 'number_loans', 'dependents']
plot_box(credit, num_cols)

# バイオリンプロット
def plot_violin(credit, cols, col_x = 'bad_credit'):
for col in cols:
sns.set_style("whitegrid")
sns.violinplot(col_x, col, data=credit)
plt.xlabel(col_x) # Set text for the x axis
plt.ylabel(col)# Set text for y axis
plt.show()

plot_violin(credit, num_cols)


Picture1.png


1.2 棒グラフでカテゴリカルデータの可視化

棒グラフをいくつも実行してみる。これも目立った特徴を発見できたグラフ('checking_account_status', 'credit_history')とその解説だけ抜粋して載せます。


棒グラフの描画

import numpy as np

cat_cols = ['checking_account_status', 'credit_history', 'purpose', 'savings_account_balance',
'time_employed_yrs', 'gender_status', 'other_signators', 'property',
'other_credit_outstanding', 'home_ownership', 'job_category', 'telephone',
'foreign_worker']

credit['dummy'] = np.ones(shape = credit.shape[0])
for col in cat_cols:
print(col)
counts = credit[['dummy', 'bad_credit', col]].groupby(['bad_credit', col], as_index = False).count()
temp = counts[counts['bad_credit'] == 0][[col, 'dummy']]
_ = plt.figure(figsize = (10,4))
plt.subplot(1, 2, 1)
temp = counts[counts['bad_credit'] == 0][[col, 'dummy']]
plt.bar(temp[col], temp.dummy)
plt.xticks(rotation=90)
plt.title('Counts for ' + col + '\n Bad credit')
plt.ylabel('count')
plt.subplot(1, 2, 2)
temp = counts[counts['bad_credit'] == 1][[col, 'dummy']]
plt.bar(temp[col], temp.dummy)
plt.xticks(rotation=90)
plt.title('Counts for ' + col + '\n Good credit')
plt.ylabel('count')
plt.show()


Picture2.png

ラベル(今回はbad_creditかどうか)を判断するのに使えそうな数値的な特徴を調べるために、箱ひげ図とバイオリンプロットを使いました。また、棒グラフを使って、ラベルを分けるようなカテゴリカルデータの特徴を調べました。


2. 度数分布表

ラベルがどんなバランスで分布しているかを把握するのに便利な、カテゴリカルデータの度数(データの中にそのカテゴリがいくつあるか)について考えます。


  • [度数分布表が必要な理由 1] :
    カテゴリカルデータが均一に分布していないと、統計的に有意な推論に基づくモデリングに影響を及ぼすから。

# #4とかで扱っていた車のデータより、製造業者や燃料のタイプなどのカテゴリカルデータを見る

def count_unique(auto_prices, cols):
for col in cols:
print('\n' + 'For column ' + col)
# PandasのSeries(1列)を作って、value_counts()を使う
# cf. 2次元以上の度数分布表も作れるけどね
print(auto_prices[col].value_counts())

cat_cols = ['make', 'fuel_type', 'aspiration', 'num_of_doors', 'body_style',
'drive_wheels', 'engine_location', 'engine_type', 'num_of_cylinders',
'fuel_system']
count_unique(auto_prices, cat_cols)

# 製造業者の度数分布表

For column make
toyota 32
nissan 18
mazda 13
... (長いので省略)
Name: make, dtype: int64

# 燃料タイプの度数分布表
For column fuel_type
gas 175
diesel 20
Name: fuel_type, dtype: int64

... (他の度数分布表もあるが省略)


  • [度数分布表が必要な理由 2]:
    一つのラベルの中でデータが均一に分布していない(= Class imbalances)と、特に分類学習がうまくいかないから。

# 「クレジットカード保有者のデータ」より、bad_creditとそれ以外の度数の分布を見る

credit_counts = credit['bad_credit'].value_counts()
print(credit_counts)

# bad_creditとそれ以外の度数分布表

0 710
1 302 #bad_creditの方がとても少ない
Name: bad_credit, dtype: int64


今後の予定

随時記事のリンク追加予定


その他(いつか)まとめる予定の他の講座の記事一覧