'21/06/19更新:内容を刷新しました。利便性を考えて、JupyterLabのようにインタラクティブに使用できる雛形コードにしました。勿論、テキストファイルに保存してコマンドプロンプトで実行することも可能です。
本記事では、グリッドサーチも使用したランダムフォレスト分類(RandomForestClassifier)で分類学習器を作成する雛形コードを載せました。Pythonライブラリにはscikit-learn(sklearn,サイキットラーン)を使用します。処理の流れは次の通りです。
1. 訓練データを読み込む
2. 分析に不要な列の削除
3. 欠損値のある行の削除
4. カテゴリ変数の数値化であるOne-hotエンコーディング
5. 訓練データで学習して、分類学習器を作成する
6. テストデータを読み込む
7. テストデータの欠損値の穴埋め(平均値, 中央値, 最頻値)
8. 予測する
9. 作成した学習器を評価する
10. 分析結果を可視化(予測結果を混合行列, 特徴量を感度順にランキング)
11. 予測結果をcsvファイルに保存する
12. 作成した分類学習器をバイナリファイル(joblib)に保存する
はじめに、本雛形コードを載せます。その後に処理の説明を記載しました。
▼本プログラム
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.size'] = 14
import seaborn as sns
from sklearn.preprocessing import OneHotEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
import joblib
import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d")
df = pd.read_csv('train.csv')
df
df.isnull().sum()
df.dtypes
drop_list = ['Name', 'Ticket', 'Cabin']
df2 = df.drop(drop_list, axis=1)
df2
df3 = df2.dropna()
df3
df3.isnull().sum()
df3.hist()
plt.tight_layout()
plt.savefig(now + '_01_hist.jpg')
plt.close()
df3.dtypes
n_Sex = df3['Sex'].unique()
print(n_Sex)
n_Embarked = df3['Embarked'].unique()
print(n_Embarked)
sns.set_context('talk')
ax = sns.pairplot(
df3,
y_vars = 'Survived',
hue = 'Sex',
palette = 'gnuplot2',
kind = 'reg',
markers = '.',
diag_kind = 'kde',
diag_kws = dict(shade = True),
)
plt.tight_layout()
plt.savefig(now + '_02_pariplot.jpg')
plt.close()
df4 = pd.get_dummies(df3)
df4
train_data = df4.drop(['PassengerId', 'Survived'], axis=1)
train_data
train_label = df4[['Survived']]
train_label
print('RandomForestClassifier ...')
params = {
'n_estimators' : [80, 100, 120],
'criterion' : ['gini', 'entropy'],
'min_samples_leaf' : [2, 3, 4],
'max_depth' : [3, 4, 5, 7, 9]
}
clf = GridSearchCV(
RandomForestClassifier(),
param_grid = params,
cv = 5)
train_label = train_label.values.ravel()
clf.fit(train_data, train_label)
best_clf = clf.best_estimator_
best_clf
df_test = pd.read_csv('test.csv')
df_test
drop_list.append('PassengerId')
df_test2 = df_test.drop(drop_list, axis=1)
df_test2
df_test2.isnull().sum()
df_test2.dtypes
df_test3 = df_test2.fillna(df_test2.median())
df_test3
df_test3.isnull().sum()
test_data = pd.get_dummies(df_test3)
test_data
predict = best_clf.predict(test_data)
predict
df_test = pd.read_csv('gender_submission.csv')
df_test
train_score = 'train_score,' + str(best_clf.score(train_data, train_label))
test_score = 'test_score,' + str(best_clf.score(test_data, df_test['Survived']))
print(train_score)
print(test_score)
with open(now + '_03_model_score.csv', 'w') as f:
f.write(train_score + '\n')
f.write(test_score + '\n')
accuracy_score(df_test['Survived'], predict)
my_matrix = confusion_matrix(df_test['Survived'], predict)
class_names = ["died","survived"]
df_matrix = pd.DataFrame(
my_matrix,
index = class_names,
columns = class_names)
sns.heatmap(df_matrix, annot=True, cmap="Reds")
plt.tight_layout()
plt.ylabel("True")
plt.xlabel("Predict")
plt.title('Confusion Matrix')
plt.tight_layout()
plt.savefig(now + '_04_heatmap.jpg')
plt.close()
my_features = train_data.columns
my_importance = best_clf.feature_importances_
my_index = np.argsort(my_importance)
plt.figure(dpi=100)
plt.barh(range(len(my_index)), my_importance[my_index], color='g', align='center')
plt.yticks(range(len(my_index)), my_features[my_index])
plt.xlabel('Variable Importance')
plt.ylabel('Features')
plt.title('Feature Importance Plot')
plt.tight_layout()
plt.savefig(now + '_05_Feature_Importance.jpg')
plt.close()
results = pd.Series(predict, name = "Survived")
results
DF = pd.concat([df_test[['PassengerId']], results], axis = 1)
DF
DF.to_csv(now + '_06_titanic_submission.csv', index = False)
joblib.dump(best_clf, now + '_07_titanic_RandomForestClassifier.joblib', compress=3)
以下、説明です。
例題に使用した分析データは、タイタニック生存者データでありTitanic: Machine Learning from Disaster | Kaggleより無料で入手できます。但し、アカウント登録が必要です。Google(グーグル)アカウント等があれば、それを使用することで簡単にログイン出来ます。
上記リンク先よりcsvファイル3つ「train.csv」,「test.csv」,「gender_submission.csv」があるのでダウンロードします。訓練データ「train.csv」は次のようになっています。
日本語では次の通りです。Survivedを予測するための学習器を作成することが目的です。
PassengerID |
乗客ID |
Survived |
生存結果 (0: 死亡, 1: 生存)
|
Pclass |
乗客の階級 |
Name |
乗客の名前 |
Sex |
性別 |
Age |
年齢 |
SibSp |
兄弟、配偶者の数 |
Parch |
両親、子供の数 |
Ticket |
チケット番号 |
Fare |
乗船料金 |
Cabin |
部屋番号 |
Embarked |
乗船した港 |
まずはカテゴリ変数以外の数値データで、全体像を視覚的に把握してゆきます。下図は、ヒストグラムです。2曲かしたり、極端な分布の偏りはなさそうです。
次に、下図は散布図です。縦軸がSurvivedで、色が赤と青の2種類あって青は男性で赤が女性です。横軸はその他の特徴量(説明変数)です。ここで、いずれを見ても青が0(死亡)に近い方に多く分布していることがわかります。つまり、予測するための情報としてSexが重要なのは視覚的にわかります。
そしてデータ分析に使用する列名(説明変数, 特徴量)を考えることになります。Name(乗客の名前), Ticket(チケット番号), Cabin(部屋番号)は、関係ないかと今回は前処理でそれらの列を省きました(Cabinは、全員が部屋に居てたら関係するかもしれませんが。。)
次に欠損値を調べると、下図のように欠損値もあることがわかります。Ageは関係あると想像します(当時の文化、雰囲気でボートに載せて助けようとするのが、若い人なのか年寄りなのか。。)ここで、この欠損値を省くのか、何かで穴埋めするのかが判断の分かれ目です。今回、予測のためには曖昧なデータは使いたくないという判断で削除しています。
前処理の続きで、One-hotエンコーディングでカテゴリ変数を数値「0」or「1」にします。SexとEmbarkedが、下図右のように変換します。
そして、学習します。この時、グリッドサーチにより、探索範囲内でのハイパーパラメータの最適解を得ます。
下図が選定された分類学習器の結果です。
作成した学習器を用いて、テストデータ(本来は未知データ)を予測します。冒頭のリンクで入手した「test.csv」は次の通りです。正解データであるSurvivedの列がありません。これは、「gender_submission.csv」にすでに分けてあるためです。
ここで、上図をみると、AgeにNaN(欠損値)があります。ここでは削除することはできません。削除したら情報の欠如で予測できないためです。平均値か中央値か最頻値、もしくは自分の判断で何かしらで穴埋めすることになります。
更に、カテゴリ変数もワンホットエンコーディングでデータ変換する必要があります。作成した学習器でデータを読み込んで分析するためには、データ分析情報に整合を持たす必要があります。最終的なテストデータは下図のようになりました。
そして、上記418行のテストデータに対して予測した結果が下図です。0が死亡で1が生存。
上記予測結果データと正解データをpandasデータフレーム形式に加工して、可視化のために図示したのが下図です。混合行列と呼び、左下と右上が予測が外れた数です。
学習によって得られた特徴量(説明変数)の感度のランキングも、可視化のために下図のように横棒グラフ化します。
最後に、予測結果はcsvファイルに保存し、作成した学習器も下図のようにバイナリファイル(.joblib)に保存します。
保存した機械学習モデルの再利用方法と手順は次のリンクを参照下さい。
Python joblibで保存した機械学習モデルを読み込んで利用する - PythonとVBAで世の中を便利にする
(参考)ランダムフォレストの本家サイトは下記です。
scikit-learn.org
以上
<広告>
リンク