#前提
私:これまで機械学習を勉強したことも触れたこともない初心者
今後機械学習は知っておくべき技術だし、ちょっと使ってみたいなぁと思った
細かい部分は深堀りせず、とりあえず動く状態を目指して実装してみようというスタンスでやる
(本当に軽い気持ちで、機械学習への心理的ハードルを下げようくらいの気持ちです)
#環境準備
とりあえずpythonでpandasとscikit-learnが使える状態にする
pipでインストールすれば完了のはず…
$ pip install pandas
Traceback (most recent call last):
File "/home/myuser/.local/bin/pip", line 7, in <module>
from pip._internal import main
ImportError: No module named 'pip._internal'
詳しくはよく分からないけど、とりあえず動かないと話にならないので、
公式サイトからget-pip.pyをダウンロード
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python,python3で実行
$ sudo python get-pip.py
$ sudo python3 get-pip.py
pipコマンドが使用可能か確認
$ pip --version
pip 20.2.4 from /Library/Python/3.7/site-packages/pip (python 3.7)
無事pipが使用できる状態になった
これでpandas,scikit-learnをインストールできる
↓インストールできたことを確認
$ pip show pandas
Name: pandas
Version: 1.1.4
Summary: Powerful data structures for data analysis, time series, and statistics
Home-page: https://pandas.pydata.org
Author: None
Author-email: None
License: BSD
Location:
Requires: python-dateutil, numpy, pytz
Required-by:
$ pip show scikit-learn
Name: scikit-learn
Version: 0.23.2
Summary: A set of python modules for machine learning and data mining
Home-page: http://scikit-learn.org
Author: None
Author-email: None
License: new BSD
Location:
Requires: joblib, threadpoolctl, scipy, numpy
Required-by: sklearn
#機械学習のおおまかな手順
さらっと調べてみると機械学習はおおまかに以下の流れで進めていくみたい
- データの入手
- データの事前処理
- 手法の選択
- ハイパーパラメータの選択
- モデルの学習
- 評価 (→ 2 or 3 or 4 に戻って試行錯誤)
#Titanic: Machine Learning from Disaster(タイタニック号生存予測)
とりあえず機械学習の入門でよく目にするKaggleのタイタニック号生存予測をやってみる
##データの入手
###Kaggleのサイトから使用するデータをダウンロード
Kaggleのサイトから以下のデータをダウンロード(データをダウンロードするにはKaggleへのアカウント登録が必要)
- gender_submission.csv:こんな感じで提出してねっていう例
- test.csv:テストデータ
- train.csv:学習用データ
内容を確認するとこんな感じ
>>> import pandas as pd
>>> gender_submission = pd.read_csv("./Data/gender_submission.csv")
>>> test = pd.read_csv("./Data/test.csv")
>>> train = pd.read_csv("./Data/train.csv")
>>>
>>> gender_submission.head(5)
PassengerId Survived
0 892 0
1 893 1
2 894 0
3 895 0
4 896 1
>>> test.head(5)
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q
1 893 3 Wilkes, Mrs. James (Ellen Needs) female 47.0 1 0 363272 7.0000 NaN S
2 894 2 Myles, Mr. Thomas Francis male 62.0 0 0 240276 9.6875 NaN Q
3 895 3 Wirz, Mr. Albert male 27.0 0 0 315154 8.6625 NaN S
4 896 3 Hirvonen, Mrs. Alexander (Helga E Lindqvist) female 22.0 1 1 3101298 12.2875 NaN S
>>> train.head(5)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
gender_submission(PassengerId, Survived)
test(PassengerId, Pclass, Name, Sex, Age, SibSp, Parch, Ticket, Fare, Cabin, Embarked)
train(PassengerId, Survived, Pclass, Name, Sex, Age, SibSp, Parch, Ticket, Fare, Cabin)
###各列間の相関係数を確認
pandasではcorr()メソッドでデータフレームの各列間の相関係数が求められる
ちなみにcorr()メソッドは引数methodを指定することで3つの算出方法を指定できるらしい
今回はよくわからないのでデフォルトを使用
- 'pearson' : ピアソンの積率相関係数 ← デフォルト
- 'kendall' : ケンドールの順位相関係数
- 'spearman' : スピルマンの順位相関係数
>>> train_corr = train.corr()
>>> train_corr
PassengerId Survived Pclass Age SibSp Parch Fare
PassengerId 1.000000 -0.005007 -0.035144 0.036847 -0.057527 -0.001652 0.012658
Survived -0.005007 1.000000 -0.338481 -0.077221 -0.035322 0.081629 0.257307
Pclass -0.035144 -0.338481 1.000000 -0.369226 0.083081 0.018443 -0.549500
Age 0.036847 -0.077221 -0.369226 1.000000 -0.308247 -0.189119 0.096067
SibSp -0.057527 -0.035322 0.083081 -0.308247 1.000000 0.414838 0.159651
Parch -0.001652 0.081629 0.018443 -0.189119 0.414838 1.000000 0.216225
Fare 0.012658 0.257307 -0.549500 0.096067 0.159651 0.216225 1.000000
###ヒートマップにしてみる
seabornというライブラリを使うと簡単にヒートマップとして可視化できるらしい
やってみよう!
>>> import seaborn
>>> import matplotlib as mpl
>>> import matplotlib.pyplot as plt
>>>
>>> seaborn.heatmap(train_corr,vmax=1, vmin=-1, center=0)
<AxesSubplot:>
>>> plt.show()
なるほど、見やすくなった
たぶんこの中だとPclassとFareの相関が強いってことかな…?
今回予測するSurvivedとはPclassとFareが弱いけど相関がありそう…?
##データの事前処理
NA(欠損値)の補完、SexやEmbarked、Cabinなどの文字列を数値に補正する
今回NAは基本的には平均値を補完するが、Embarkedは最も多い"S"に補完する
Cabinは頭文字のみに補正し(おそらく客室のランクとか表してるよね)、NAは最も多いCに補完
>>> train.Embarked.value_counts()
S 644
C 168
Q 77
Name: Embarked, dtype: int64
↓使用した補正用関数
def CorrectTitanicData(df):
#Age : NA -> 平均値
df.Age = df.Age.fillna(df.Age.median())
#Sex : male -> 0, female -> 1
df.Sex = df.Sex.replace(['male', 'female'],[0,1])
#Embarked : NA -> S, C -> 0, S -> 1, Q -> 2
df.Embarked = df.Embarked.fillna("S")
df.Embarked = df.Embarked.replace(['C', 'S', 'Q'], [0, 1, 2])
#Fare : NA -> 平均値
df.Fare = df.Fare.fillna(df.Fare.median())
#Cabin : NA -> C, A~G -> 0~6, T -> 7
df.Cabin = df.Cabin.fillna('C')
df.Cabin = df.Cabin.replace('A(.*)','A',regex=True)
df.Cabin = df.Cabin.replace('B(.*)','B',regex=True)
df.Cabin = df.Cabin.replace('C(.*)','C',regex=True)
df.Cabin = df.Cabin.replace('D(.*)','D',regex=True)
df.Cabin = df.Cabin.replace('E(.*)','E',regex=True)
df.Cabin = df.Cabin.replace('F(.*)','F',regex=True)
df.Cabin = df.Cabin.replace('G(.*)','G',regex=True)
df.Cabin = df.Cabin.replace(['A','B','C','D','E','F','G','T'], [0,1,2,3,4,5,6,7])
return df
事前処理後に再度各列間の相関を確認
>>> train = CorrectTitanicData(train)
>>> train_corr = train.corr()
>>> train_corr
PassengerId Survived Pclass Sex Age SibSp Parch Fare Cabin Embarked
PassengerId 1.000000 -0.005007 -0.035144 -0.042939 0.034212 -0.057527 -0.001652 0.012658 -0.035748 -0.017443
Survived -0.005007 1.000000 -0.338481 0.543351 -0.064910 -0.035322 0.081629 0.257307 0.080643 -0.125953
Pclass -0.035144 -0.338481 1.000000 -0.131900 -0.339898 0.083081 0.018443 -0.549500 0.009851 0.305762
Sex -0.042939 0.543351 -0.131900 1.000000 -0.081163 0.114631 0.245489 0.182333 0.070780 -0.022521
Age 0.034212 -0.064910 -0.339898 -0.081163 1.000000 -0.233296 -0.172482 0.096688 -0.032105 -0.040166
SibSp -0.057527 -0.035322 0.083081 0.114631 -0.233296 1.000000 0.414838 0.159651 0.000224 0.030874
Parch -0.001652 0.081629 0.018443 0.245489 -0.172482 0.414838 1.000000 0.216225 0.018232 -0.035957
Fare 0.012658 0.257307 -0.549500 0.182333 0.096688 0.159651 0.216225 1.000000 -0.098064 -0.268865
Cabin -0.035748 0.080643 0.009851 0.070780 -0.032105 0.000224 0.018232 -0.098064 1.000000 0.069852
Embarked -0.017443 -0.125953 0.305762 -0.022521 -0.040166 0.030874 -0.035957 -0.268865 0.069852 1.000000
>>>
>>> seaborn.heatmap(train_corr,vmax=1, vmin=-1, center=0)
<AxesSubplot:>
>>> plt.show()
##手法の選択
今回予測因子として使用するのは"Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Cabin", "Embarked"の8項目(PassengerID以外)
学習手法としては以下の7つの手法で実施して、交差検証を行う
- LgisticRegression
- SVC
- LinearSVC
- KNeighbors
- DecisionTree
- RandomForest
- MLPClassifier
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.svm import SVC, LinearSVC
>>> from sklearn.neighbors import KNeighborsClassifier
>>> from sklearn.tree import DecisionTreeClassifier
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.neural_network import MLPClassifier
>>> from sklearn.model_selection import cross_val_score
>>>
>>> predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Cabin", "Embarked"]
>>> models = []
>>> models.append(("LogisticRegression",LogisticRegression()))
>>> models.append(("SVC",SVC()))
>>> models.append(("LinearSVC",LinearSVC()))
>>> models.append(("KNeighbors",KNeighborsClassifier()))
>>> models.append(("DecisionTree",DecisionTreeClassifier()))
>>> models.append(("RandomForest",RandomForestClassifier()))
>>> models.append(("MLPClassifier",MLPClassifier(solver='lbfgs', random_state=0)))
>>>
>>> results = []
>>> names = []
>>>
>>> for name,model in models:
... result = cross_val_score(model, train[predictors], train["Survived"], cv=3)
... names.append(name)
... results.append(result)
...
>>> for i in range(len(names)):
... print(names[i],results[i].mean())
...
LogisticRegression 0.7811447811447811
SVC 0.6554433221099888
LinearSVC 0.7317620650953985
KNeighbors 0.7070707070707071
DecisionTree 0.7721661054994389
RandomForest 0.7957351290684623
MLPClassifier 0.7901234567901234
RandomForestが最もよい評価みたい
##提出用に予測結果をCSVファイルに保存
ランダムフォレストで学習用データを学習し、テストデータで予想を行う。
結果をCSV形式で保存
>>> test = pd.read_csv("./Data/test.csv")
>>> test = CorrectTitanicData(test)
>>> algorithm = RandomForestClassifier()
>>> algorithm.fit(train[predictors], train["Survived"])
RandomForestClassifier()
>>> predictions = algorithm.predict(test[predictors])
>>> submission = pd.DataFrame({
... "PassengerId":test["PassengerId"],
... "Survived":predictions
... })
>>> submission.to_csv("submission.csv", index=False)
###提出結果
せっかくなのでKaggleで提出してみました
結果Scoreは0.74162
ここから色々試行錯誤して正答率を上げていきたいけど、今回は一旦ここまで
scikit-learnにはハイパーパラメータを探索するGridSearchCVとかがあるみたいなので、
それを使うともっと正答率があがりそうだなぁ…