LoginSignup
0
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-06-07

昨日までのはこちら

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

こんな感じのデータです。

前回はいろいろデータの中身をみて、どんなデータが使えそうなのかと言うところをやりました。
今回はその続きで、使えそうなデータを使って、機械学習用のデータに落とし込んでいきます。

欠損値の確認

データを読み込みした際に、データが無い場合はデータフレーム上では欠損値と言う扱いになります。

欠損値がどれくらいあるかは
データフレーム.isnull().sum()
で各列の欠損値の個数を確認できます。

train_df.isnull().sum()

PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64

これを見るといくつかの列にのみ欠損値があるようですね。
「Age」「Cabin」「Embarked」に欠損があるようです

欠損値のある部分だけを表示してみましょう。

条件に合致する行を抽出する

データフレーム[条件式]

欠損値のある行を抽出する

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

train_df[train_df['Embarked'].isnull()]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
61 62 1 1 Icard, Miss. Amelie female 38 0 0 113572 80 B28 NaN
829 830 1 1 Stone, Mrs. George Nelson (Martha Evelyn) female 62 0 0 113572 80 B28 NaN

Embarked列の値を見るとNaNになっていますね。
データフレーム上での欠損値はNaNと表示されます。

数値の欠損の場合は
・平均値
・中央値
・任意の値
などで欠損値を補完することが多いです。

Embarkedなどカテゴリ値は数値ではないので、なにかしらの数値で置き換えることは出来ません。

欠損値を埋めたい場合はfillnaで補完することができます。

欠損値を任意の値で補完する

データフレーム.fillna(補完値)

その列の平均値などで補完したい場合は、まず平均値などを求めます。

列の平均を求める

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

列の中央値を求める

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

print(train_df['Fare'].mean())
print(train_df['Fare'].median())

32.2042079685746
14.4542

# 年齢を平均値で補完する
train_df['Age'] = train_df['Age'].fillna(train_df['Age'].mean())

カテゴリ値のベクトル化

機械学習では計算に用いる値は基本的に全て数値で無ければなりません。
文字列で構成されるカテゴリ値の場合、一部のモデルを除いて多くの場合はそのままの形では機械学習のデータとして用いることが出来ません。

そのためone-hotベクトルとしてカテゴリ値から数値に変換を行います。

カテゴリ値をone-hotベクトルにする

one-hotベクトルはカテゴリ値の列を作成し、値がその列名なら1、違えば0にしたデータです。

pd.get_dummies(データフレーム[['列名']])
※prefix='前置詞'を付けるとカラム名の前に名前を付けられる
これで新しいデータフレームを作ります。

# 乗船場所のカテゴリ化
train_df["Embarked"] = train_df["Embarked"].fillna('N')
one_hot_df = pd.get_dummies(train_df["Embarked"],prefix='Em')
one_hot_df.head()
Em_C Em_N Em_Q Em_S
0 0 0 0 1
1 1 0 0 0
2 0 0 0 1
3 0 0 0 1
4 0 0 0 1

Embarked列は欠損があるので欠損をNに置き換えたのちカテゴリ値にしています。
カテゴリ値が有るところは 1 無いところは 0 で置き換えられたデータフレームを新たに生成します。

データの種類分の列を作ることになります。
データの種類が多すぎる場合はデータが素(ほとんど0)になってしまうので
ある程度種類が限られるものだけに絞ってカテゴリ変数を作るのが得策です。

数値と文字列の変換
データが文字列のものを数値に変更したり、数値のものを文字列に直したりして機械学習に使えるデータに直していきます。

性別(Sex)は文字列であるためこのままでは機械学習に用いることが出来ません。
文字列から数値に変換をしていきます。

データフレーム['カラム名'].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

新しく性別の列を作成しました。

数値から文字列に変換する際もreplaceが使えます。
列のデータ型を丸ごと変更する際は

データフレーム['カラム名'].astype(np.データ型)

数値のカテゴリ化

年齢を用いて年代を算出してみましょう。
年齢を10で切り捨て除算すると年代になります。
欠損のものは年齢無しとしてカラムを作成することも出来ます。


# 年代のカテゴリ化
train_df['period'] = train_df['Age']//10
train_df['period'] = train_df['period'].fillna('NaN')
train_df['period'] = train_df['period'].astype(np.str)
period_df = pd.get_dummies(train_df["period"],prefix='Pe')
period_df.head()
Pe_0.0 Pe_1.0 Pe_2.0 Pe_3.0 Pe_4.0 Pe_5.0 Pe_6.0 Pe_7.0 Pe_8.0
0 0 0 1 0 0 0 0 0 0
1 0 0 0 1 0 0 0 0 0
2 0 0 1 0 0 0 0 0 0
3 0 0 0 1 0 0 0 0 0
4 0 0 0 1 0 0 0 0 0

データフレームの結合

新しく作成したデータフレームを1つにまとめていきます。まとめるにはpd.concatを用います。

pd.concat([データフレーム,データフレーム],axis=1)
※axis=1 は横に、axis=0は縦に結合する,結合する際のカラム数や行数は合わせておく必要がある。


con_df = pd.concat([train_df,period_df],axis=1)
con_df = pd.concat([con_df,one_hot_df],axis=1)
con_df.head(1)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare ... Pe_3.0 Pe_4.0 Pe_5.0 Pe_6.0 Pe_7.0 Pe_8.0 Em_C Em_N Em_Q Em_S
0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 ... 0 0 0 0 0 0 0 0 0 1

これで横方向にデータフレームを連結することができました。

不要データの削除

データフレームを結合する際に、変換前のデータは特に必要ありませんので元の列を削除します。

データフレーム.drop(['列名'], axis=1)

data_df = con_df.drop(['PassengerId','Pclass','Name','Age','Ticket','Cabin','Embarked','period','Sex'], axis=1)
data_df.head()
Survived SibSp Parch Fare Sex2 Pe_0.0 Pe_1.0 Pe_2.0 Pe_3.0 Pe_4.0 Pe_5.0 Pe_6.0 Pe_7.0 Pe_8.0 Em_C Em_N Em_Q Em_S
0 0 1 0 7.25 0 0 0 1 0 0 0 0 0 0 0 0 0 1
1 1 1 0 71.2833 1 0 0 0 1 0 0 0 0 0 1 0 0 0
2 1 0 0 7.925 1 0 0 1 0 0 0 0 0 0 0 0 0 1
3 1 1 0 53.1 1 0 0 0 1 0 0 0 0 0 0 0 0 1
4 0 0 0 8.05 0 0 0 0 1 0 0 0 0 0 0 0 0 1

全て数値のデータになりました。
このような形で最終的な機械学習用のデータとすることが出来ます。

まとめ

本日はデータを加工して機械学習用のデータマートを作成しました。
本日紹介したのは加工手法のごく一部です。

まずはざっくりとした流れを覚えましょう。
そして、ある程度理解ができたら、より精度を高めるための工夫をしたり、新しい手法を試してみるのが良いかと思います。

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

作者の情報

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

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

Twitter:
https://twitter.com/otupython

0
0
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
0