Edited at

機械学習の理論Python編 #4 Unit 2: 回帰の準備のための探索的データ解析(2) [MOOC/edX]

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

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

回帰(Regression)の解析をするための準備段階にやるべきことを学びます。


2. データの可視化 - 実践2: 高次元のデータを可視化してみる

前回の自動車の例での可視化は2次元の情報しか表せないので、Aesthetics(色とか大きさとか)を加味した可視化について考えてみます。


(1) Aestheticsな手法を使う


a) プロットの形

Screen Shot 2018-10-23 at 16.35.59 copy.png

Screen Shot 2018-10-23 at 16.35.59.png

プロットの形を、{gas/diesel}というカテゴリカルデータで分けた例です。燃費(city_mpg)、値段の2軸と合わせて、3次元のデータを2次元に表現できました。


プロットの形

def plot_scatter_shape(auto_prices, cols, shape_col = 'fuel_type', col_y = 'price', alpha = 0.2):

shapes = ['+', 'o', 's', 'x', '^'] # pick distinctive shapes
unique_cats = auto_prices[shape_col].unique()
for col in cols: # loop over the columns to plot
# snsはseaborn(matplotlibのグラフ描画を美しくするライブラリ)のなんか
sns.set_style("whitegrid")
for i, cat in enumerate(unique_cats): # loop over the unique categories
temp = auto_prices[auto_prices[shape_col] == cat]
# shape[i]でプロットの形を変えてる
sns.regplot(col, col_y, data=temp, marker = shapes[i], label = cat,
scatter_kws={"alpha":alpha}, fit_reg = False, color = 'blue')
plt.title('Scatter plot of ' + col_y + ' vs. ' + col) # Give the plot a main title
plt.xlabel(col) # Set text for the x axis
plt.ylabel(col_y)# Set text for y axis
plt.legend()
plt.show()

num_cols = ['curb_weight', 'engine_size', 'horsepower', 'city_mpg']
plot_scatter_shape(auto_prices, num_cols)



b) プロットの大きさ

a)形に加えて、{外側の重さ}をプロットの大きさで示しています。燃費(city_mpg)、値段の2軸と、プロットの形の{gas/diesel}と合わせて、4次元のデータを2次元に表現できました。

Screen Shot 2018-10-23 at 16.42.10.png


プロットの大きさ

def plot_scatter_size(auto_prices, cols, shape_col = 'fuel_type', size_col = 'curb_weight',

size_mul = 0.000025, col_y = 'price', alpha = 0.2):
shapes = ['+', 'o', 's', 'x', '^'] # pick distinctive shapes
unique_cats = auto_prices[shape_col].unique()
for col in cols: # loop over the columns to plot
sns.set_style("whitegrid")
for i, cat in enumerate(unique_cats): # loop over the unique categories
temp = auto_prices[auto_prices[shape_col] == cat]
sns.regplot(col, col_y, data=temp, marker = shapes[i], label = cat,
scatter_kws={"alpha":alpha, "s":size_mul*auto_prices[size_col]**2},
fit_reg = False, color = 'blue')
plt.title('Scatter plot of ' + col_y + ' vs. ' + col) # Give the plot a main title
plt.xlabel(col) # Set text for the x axis
plt.ylabel(col_y)# Set text for y axis
plt.legend()
plt.show()

num_cols = ['engine_size', 'horsepower', 'city_mpg']
plot_scatter_size(auto_prices, num_cols)



c) プロットの色

a)形とb)大きさに加えて、{std/turbo}というカテゴリカルデータをプロットの色で示しています。反例が少し複雑ですが、燃費(city_mpg)、値段の2軸と、プロットの形の{gas/diesel}、プロットの大きさの{外側の重さ}と合わせて、5次元のデータを2次元に表現できました。

{Screen Shot 2018-10-23 at 16.46.32.png


プロットの色

def plot_scatter_shape_size_col(auto_prices, cols, shape_col = 'fuel_type', size_col = 'curb_weight',

size_mul = 0.000025, color_col = 'aspiration', col_y = 'price', alpha = 0.2):
shapes = ['+', 'o', 's', 'x', '^'] # pick distinctive shapes
# 赤色と緑色の区別が難しい人のために赤は使わず代わりにmagentaを使う
colors = ['green', 'blue', 'orange', 'magenta', 'gray'] # specify distinctive colors
unique_cats = auto_prices[shape_col].unique()
unique_colors = auto_prices[color_col].unique()
for col in cols: # loop over the columns to plot
sns.set_style("whitegrid")
for i, cat in enumerate(unique_cats): # loop over the unique categories
for j, color in enumerate(unique_colors):
temp = auto_prices[(auto_prices[shape_col] == cat) & (auto_prices[color_col] == color)]
sns.regplot(col, col_y, data=temp, marker = shapes[i],
scatter_kws={"alpha":alpha, "s":size_mul*temp[size_col]**2},
label = (cat + ' and ' + color), fit_reg = False, color = colors[j])
plt.title('Scatter plot of ' + col_y + ' vs. ' + col) # Give the plot a main title
plt.xlabel(col) # Set text for the x axis
plt.ylabel(col_y)# Set text for y axis
plt.legend()
plt.show()

num_cols = ['engine_size', 'horsepower', 'city_mpg']
plot_scatter_shape_size_col(auto_prices, num_cols)


これでだいぶ高次元のデータを表現できるようになりましたが、それでも5次元という限界があります。Aesthetics手法を使わずに、2次元プロットの枠を超え、それ以上に拡張する手法を見ていきます。


(2) 多軸プロット(Multi-Axis Plot)


a) Pair-wise Scatter Plot(全通りの散布図の組み合わせを使う)

download copy.png

5つの変数の全通りの散布図。対角部分はKDFプロット。左下は通常の散布図、右上は等高線状(conter plot)に示した散布図。


Pair-wiseScatterPlot

# 5つの数値データと1つのカテゴリカルデータ(fuel_type)

num_cols = ["curb_weight", "engine_size", "horsepower", "city_mpg", "price", "fuel_type"]
# 多軸プロットにはseabornのpairplot()を使う
# hue='fuel_type' をカテゴリカルfuel-typeの表示に使うことにした
# diag_kind="kde"でカーネル密度推定プロットを使うことにした
sns.pairplot(auto_prices[num_cols], hue='fuel_type', palette="Set2", diag_kind="kde", size=2).map_upper(sns.kdeplot, cmap="Blues_d")


b) 他の方法を使う(faceting, conditioning method)

全てのグリッドで横軸を共有して描画する。別のグリッド同士でも直接比較できる。空欄もできるが、空欄ができたとしても、大規模データを見るには効果的な手法。


・ヒストグラム

Screen Shot 2018-10-23 at 17.36.16 copy.png


多軸のヒストグラム

## Function to plot conditioned histograms

def cond_hists(df, plot_cols, grid_col):
import matplotlib.pyplot as plt
import seaborn as sns
## Loop over the list of columns
for col in plot_cols:
grid1 = sns.FacetGrid(df, col=grid_col)
grid1.map(plt.hist, col, alpha=.7)
return grid_col

## Define columns for making a conditioned histogram
plot_cols2 = ["length",
"curb_weight",
"engine_size",
"city_mpg",
"price"]

cond_hists(auto_prices, plot_cols2, 'drive_wheels')



・散布図

download (3).png


多軸の散布図

def cond_plot(cols):

import IPython.html.widgets
import seaborn as sns
for col in cols:
g = sns.FacetGrid(auto_prices, col="drive_wheels", row = 'body_style',
hue="fuel_type", palette="Set2", margin_titles=True)
g.map(sns.regplot, col, "price", fit_reg = False)

num_cols = ["curb_weight", "engine_size", "city_mpg"]
cond_plot(num_cols)


コードのコメントなど細かい部分は、復習しつつ追記する予定です。ひとまず先に進むことを第一に進めてます。


今後の予定

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


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