LoginSignup
0
3

More than 3 years have passed since last update.

100日後にエンジニアになるキミ - 78日目 - プログラミング - 機械学習について3

Posted at

昨日までのはこちら

100日後にエンジニアになるキミ - 76日目 - プログラミング - 機械学習について

100日後にエンジニアになるキミ - 70日目 - プログラミング - スクレイピングについて

100日後にエンジニアになるキミ - 66日目 - プログラミング - 自然言語処理について

100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1

100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて

100日後にエンジニアになるキミ - 53日目 - Git - Gitについて

100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて

100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて

100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1

100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1

100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1

100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1

今回は機械学習についてのお話の続きです。

機械学習のデータ加工流れについて

機械学習を取り入れる際の業務としては次のような流れになっていきます。

0.目的を決める
1.データ取得
2.データ理解・選択・加工
3.データマート(データセット)作成
4.モデル作成
5.精度検証
6.システム実装

このうち2-3の部分をデータの前処理などと言っています。

今回はこの前処理のうちのデータ理解についてやっていきたいと思います。

データ理解について

具体的に機械学習におけるデータの前処理の作業がどのようなものなのか、ざっくりですが一部のコードを交えてやっていきましょう。

言語はPython
機械学習用のライブラリはPandasNumpy
可視化用のライブラリはseaborn,matplotlibを用います。

ライブラリの読み込み

# ライブラリの読み込み
import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')

%matplotlib inline

データの詳細

今回用いるデータはタイタニック号の乗船者名簿です。

PassengerID: 乗客ID
Survived:   生存結果 (0=死亡 , 1=生存)
Pclass:    乗客の階級(1が最も良いらしい)
Name:      乗客の名前
Sex:      性別
Age:      年齢
SibSp      兄弟、配偶者の数
Parch     両親、子供の数
Ticket     チケット番号
Fare      乗船料金
Cabin     部屋番号
Embarked    乗船した港

titanic_train.csvと言うファイルがあると想定してください。

ファイルの読み込み

pandasライブラリではread_xxxと言うファイル形式に合わせた読み込みメソッドがたくさんあるのでそれを用いてファイルを読み込みします。今回はCSVファイルなのでread_csvです。

pandasライブラリは表形式のデータフレームと言うデータ形式を取り扱うライブラリです。
データフレームにファイルを読み込みします。

# ファイルからデータの読み込み
file_path = 'data/titanic_train.csv'
train_df = pd.read_csv(file_path,encoding='utf-8')
train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S
4 5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 NaN S

こんな感じのデータです。
データフレームでは行と列でデータの操作を行えます。

データの確認

まずはデータフレームの確認をします。
どんなカラムが有るかをみていきます。


print(train_df.columns)
print(len(train_df.columns))

Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
dtype='object')
12

次にデータ型の確認です。pandasライブラリでは列ごとにデータの型が決まっています。
型に合わせて操作をする必要があります。

train_df.dtypes

PassengerId int64
Survived int64
Pclass int64
Name object
Sex object
Age float64
SibSp int64
Parch int64
Ticket object
Fare float64
Cabin object
Embarked object
dtype: object

objectは文字列などのデータ型、他は数値のデータ型になっています。

列の参照
データフレームでは列ごとにデータを参照することもできます。
1列の場合は文字列で、複数列の場合はリスト型の列名で指定するとそのデータだけを参照できます。

データフレーム[列名]
データフレーム[[列名,列名]]

データフレームの基礎集計

データをもらってまずやることといえば、基礎集計です。
pandasではデータフレームの基本統計量の算出を行うことができます。

# 数値データの基礎統計
train_df.describe()
PassengerId Survived Pclass Age SibSp Parch Fare
count 891 891 891 714 891 891 891
mean 446 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 1 0 1 0.42 0 0 0
25% 223.5 0 2 20.125 0 0 7.9104
50% 446 0 3 28 0 0 14.4542
75% 668.5 1 3 38 1 0 31
max 891 1 3 80 8 6 512.3292

数値型の列の基本統計量が出ます。
データがどれくらいあるか、どんな感じのデータなのかを見ることができます。

データの種類の確認
文字列型のデータは基礎集計はできないので、どういうカテゴリのデータがどれくらいの量あるのかは
value_countsというメソッドで算出できます。

データフレーム['列名'].value_counts()

train_df['Pclass'].value_counts()

3 491
1 216
2 184
Name: Pclass, dtype: int64

グループバイ集計

複数の列を用いて集計を行う場合はgroupbyを用います。

データフレーム[['列名','列名','列名']].groupby(['列名','列名']).集計関数()

# 男女別で生存数の確認(0:死亡 , 1:生存)
train_df[['Sex','Survived','PassengerId']].groupby(['Sex','Survived']).count()
PassengerId
Sex Survived
female 0 81
1 233
male 0 468
1 109

グループバイ集計では様々な集計を行えます。(平均、最小値、最大値など)

これで見ると、女性の生存割合と、男性の生存割合ではかなり差が出ているように見えます。
男性はSurvived=0が多く圧倒艇に亡くなっているのが見えます。

クロス集計

複数列をまとめてクロス集計(個数のカウント)を行うことが出来ます。

pd.crosstab(データフレーム[列名],データフレーム[列名])

pd.crosstab([データフレーム[列名],データフレーム[列名]],[データフレーム[列名],データフレーム[列名]])
※margins=True をつけると合計も表示する

pd.crosstab([train_df['Sex'], train_df['Survived']], train_df['Pclass'])
Pclass 1 2 3
Sex Survived
female 0 3 6 72
1 91 70 72
male 0 77 91 300
1 45 17 47
pd.crosstab([train_df['Sex'], train_df['Survived']], [train_df['Pclass'], train_df['Embarked']],margins=True)
Pclass 1 2 3
Embarked C Q S C Q S C Q S
Sex Survived
female 0 1 0 2 0 0 6 8 9 55
1 42 1 46 7 2 61 15 24 33
male 0 25 1 51 8 1 82 33 36 231
1 17 0 28 2 0 15 10 3 34
All 85 2 127 17 3 164 66 72 353

こういった列ごとの集計を行ったりして、どんなデータなのかをのぞいていきます。

データの可視化

matplotlibを用いるとデータの可視化を行うことが出来ます。

図表はヒストグラムや棒グラフ、散布図などをデータから作ることが出来ます。
ヒストグラムを描いてみましょう。

ヒストグラムは横軸を値、縦軸をその個数、とした際の図表になります。
ビンはデータを段階で区分けする際の段回の数です。

ヒストグラムを表示する

データフレーム['列名'].plot(kind='hist',bin=ビンの数)

データフレーム['列名'].hist(bin=ビンの数)

※figsize=(横幅, 縦幅)を加えると図表のスケールを変更できる

train_df['Fare'].plot(figsize=(16, 5),kind='hist',bins=20)
plt.show()

image.png

train_df['Age'].plot(figsize=(16, 5),kind='hist',bins=20)
plt.show()

image.png

条件指定

データフレームに抽出条件を加えることで、可視化するものを層別で分けることが出来ます。

データフレーム[条件式]['列名']
※データフレームの条件式は下記の記号で複数条件をつなげることが出来る

条件 記号
and条件の場合 &
or条件の場合 |
not条件の場合 ~
# 条件指定でデータフレームを抽出する
train_df[train_df['Survived']==0]['Age'].head()

0 22.0
4 35.0
5 NaN
6 54.0
7 2.0
Name: Age, dtype: float64

# 年齢別で生存者と死亡者を分けてヒストグラムを描く
train_df[train_df['Survived']==0]['Age'].hist(figsize=(16,5),bins=16,color="#F8766D", alpha=0.3)
train_df[train_df['Survived']==1]['Age'].hist(figsize=(16,5),bins=16,color="#5F9BFF", alpha=0.3)
plt.show()

image.png

# 男性のみ年齢別で生存者と死亡者を分けてヒストグラムを描く
train_df[(train_df['Survived']==0)&(train_df['Sex']=='male')]['Age'].hist(figsize=(16,5),bins=10,color="#F8766D", alpha=0.3)
train_df[(train_df['Survived']==1)&(train_df['Sex']=='male')]['Age'].hist(figsize=(16,5),bins=10,color="#5F9BFF", alpha=0.3)
plt.show()

image.png

# 女性のみ年齢別で生存者と死亡者を分けてヒストグラムを描く
train_df[(train_df['Survived']==0)&(train_df['Sex']=='female')]['Age'].hist(figsize=(16,5),bins=10,color="#F8766D", alpha=0.3)
train_df[(train_df['Survived']==1)&(train_df['Sex']=='female')]['Age'].hist(figsize=(16,5),bins=10,color="#5F9BFF", alpha=0.3)
plt.show()

image.png

いろいろな集計の結果を可視化してあげると違いが見やすくなり、データの中から予測に効きそうな物が発見しやすくなります。

男性の分布と女性の分布では生死にかなり差が出ているのが分かります。

次に散布図を表示してみます。

散布図を表示する

散布図はscatterです。二つの数値を用いての可視化なので何かしらの数値の列を二つ指定をします。

データフレーム[['列名','列名']].plot(x='横方向の列名', y='縦方向の列名' , kind='scatter')
※figsize=(横幅, 縦幅)を加えると図表のスケールを変更できる
日本語は設定しないと表示されないので注意

train_df[['Fare','Age']].plot(x='Fare', y='Age', figsize=(16, 9),kind='scatter')
plt.show()

image.png

性別で色づけしたいのですが、データは文字列なので数値する必要があります。
1列追加して、種別を数値に直した値を代入します。

データフレームの列の追加

データフレーム['列名'] = 値

データフレームの文字の置き換え

データフレーム.replace({'置換する前の文字列':置換後の値})

# 性別の数値化(男性を0 , 女性を1)
train_df['Sex2'] = train_df['Sex'].replace({'male':0,'female':1})
train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Sex2
0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S 0
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C 1
2 3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 NaN S 1
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S 1
4 5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 NaN S 0

一番最後に性別を0,1にした列が出来上がります。

これで性別を数値にした値の列が追加できました。

色づけして散布図を書いてみます。

# 散布図の色づけ(男性を0 , 女性を1)
train_df[['Fare','Age']].plot(x='Fare', y='Age', figsize=(16, 5),kind='scatter',c=train_df['Sex2'],cmap='winter')
plt.show()

image.png

生存者と死亡者で色分けしてみましょう。

# 散布図の色づけ(0:死亡 , 1:生存)
train_df[['Fare','Age']].plot(x='Fare', y='Age', figsize=(16, 5),kind='scatter',c=train_df['Survived'],cmap='winter')
plt.show()

image.png

性別と生死で色分けした際のものがかなり似ているように感じられると思います。

seabornでの可視化

matplotlibをもう少しきれいに表示させるためのライブラリでseabornと言うものが有ります。
seabornライブラリではmatplotlibでは表現できない可視化の方法も有ります。

数値型のデータ同士の散布図をまとめて表示します。

sns.pairplot(データフレーム , hue"文字列型の種別の列")

# 欠損値があると表示できないものも有るので、一旦欠損値を平均値で埋める
for name in ['Age']:
    train_df[name] = train_df[name].fillna(train_df[name].mean())

train_df['Survived2'] = train_df['Survived'].replace({0:'death',1:'survived'})
train_df['Sex2'] = train_df['Sex'].replace({'male':0,'female':1})

# pairplot
# データ系列同士の相関性などを確認
# 同データ同士の場合は棒グラフ、異なる場合は散布図を表示
sns.pairplot(train_df[['Pclass','Age','Fare','Sex2','Survived2']], hue="Survived2")
plt.show()

image.png

factorplot

factorplotは要因別で図表を振り分けることが出来ます。

factorplot(x='横方向カラム名', y='縦方向カラム名', hue='種別用カラム名', col='カラム名', data=データフレーム)

# factorplot (種別比較図)
sns.factorplot(x='Pclass', y='Age', hue='Survived', col='Sex2', data=train_df)
plt.show()

image.png

kind='box' を付け加えると箱ひげ図に変えることが出来ます。

sns.factorplot(x='Pclass', y='Age', hue='Survived', col='Sex2',kind='box', data=train_df)
plt.show()

image.png

lmplot

2変数間の散布図と線形回帰線を可視化するグラフです。

sns.lmplot(x=横軸のカラム, y=縦軸のカラム, hue='色づけするもの', data=データフレーム, x_bins=ビン値)

# 年齢層を指定
generations = [10,20,30,40,50,60,70,80]
# 客層、年齢ごとの生存率、および回帰直線を描画
sns.lmplot('Age', 'Survived', hue='Pclass', data=train_df,hue_order=[1,2,3], x_bins=generations)
plt.show()

image.png

まとめ

データの理解では全体を集計してどんなデータがあるのかを把握し、層別で様々な可視化を試してみて
どんなデータの分布になっているのかをみていきます。

データをあらかた見終わった後は、どんなデータが予測に使えそうなのかを整理して
ここから、機械学習に使えるデータに直していきます。

まずはざっくりとした流れを覚えましょう。

君がエンジニアになるまであと22日

作者の情報

乙pyのHP:
http://www.otupy.net/

Youtube:
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw

Twitter:
https://twitter.com/otupython

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3