概要
この記事では、Kaggleの初心者向けコンペティションとして有名な「Titanic - Machine Learning from Disaster(タイタニック号の乗客の生存予測)」を例に、
CSV形式で保存されている数値データを読込・学習させて、未知データを予測するプログラムを紹介います。
多くのデータは人間が処理しやすいように、CSV形式(もしくはExcelブック)で保存されていることが多いと思います。
実際、私の職場でも多くのデータはCSV形式で取得します。
とりあえずニューラルネットワークで機械学習をさせることを主目的としているため、細かな説明・解説は割愛します。
(また、時間があれば別途記事作成したいと思います。)
プログラムの説明
データ準備・前処理
まず、Kaglleに登録して、Taitanicのコンペティションに参加、データのダウンロードをします。
すると、zipファイルの中に"train.csv" "test.csv"があるので、これらを使っていきます。
train.csv(モデル学習用のデータ)は、
Survived(生存情報 1=生 0=死)と、性別や名前や客室情報といったデータで構成されています。
一方、test.csvはこれから予測する対象なので生存情報は含まれていません。
これらのデータには、欠損データやテキストデータ(文字列)が含まれているため、データの前処理をしていきます。
先頭列に予測させたいデータ(目的変数)、それ以降の列に予測に使うデータ(説明変数)という形にします。
文字列はそのまま学習させることはできないので、
性別や客室情報といった、分類データやカテゴリーデータは数値に変換します。
名前・チケット情報といった数値置き換えが難しい文字列データは今回無視(削除)します。
テストデータも同様の処理を行ってください。
本当はこのデータの前処理こそがデータサイエンスの肝であり、知識・センスが試されるところですが、この記事では割愛します。
CSVデータの読み込み
ここからプログラムの中身となります。
まず、numpyの".loadtext"を使って、訓練データCSVを読み込みします。
import numpy as np
# 訓練データのpathを指定
path="C:\\Users\\●●●\\・・・前処理後訓練データ.csv"
#numpyを使ってCSV読込
# delimiter=ファイルの区切り文字
# skiprows=先頭の何行を無視するか(項目名は読み込まない)
TRAIN_ALLdata = np.loadtxt(path,delimiter=",",skiprows=1)
データの分割
次に、読み込んだデータを目的変数と説明変数に分割します。
#目的変数(out_var)と説明変数(in_var)に分割、
# [x]はx番目で分割
# axis=1は列方向で分割(=0の場合は行方向で分割)
out_var , in_var = np.split(TRAIN_ALLdata,[1],axis=1)
モデルの定義
ここからいよいよニューラルネットワークを作っていきます。
まずは、モデルの定義です。
ここで、中間層の数やノードの数などを定義して、モデルの形を決定します。
import tensorflow as tf
from tensorflow import keras
from keras import layers
#モデルの条件(変数で指定したほうが、後のパラメータ調整が簡単になります。)
h_cnl=20 #ニューロン数(中間層ノード数)
layers_N=3 #中間層数
#モデルの準備(空の箱を準備)
model = keras.Sequential()
#入力層を定義
model.add(layers.Dense(h_cnl, activation='relu',name='input', input_shape=(in_var.shape[1],)))
#中間層を定義
# (単純に"model.add"を複数記載してもよいのですが、後のパラメータ調整がしやすいようにfor文記載)
for i in range(layers_N):
model.add(layers.Dense(h_cnl,activation='relu'))
#出力層を定義
model.add(layers.Dense(2,activation='softmax',name='output'))
#モデルの評価関数(loss)、最適化手法(optimizer)を指定
model.compile(loss= "sparse_categorical_crossentropy", optimizer="adam",metrics=['accuracy'])
#モデルの概要を表示(なくてもOK)
model.summary()
上記のモデルイメージを図示すると下図のようになります。
tensorflowでのモデル定義の記述方法は複数あります。
また、より詳しくモデル条件を指定することもできますが、今回はとりあえずニューラルネットワークの機械学習をやってみることを目的としているので詳しい説明は割愛します。
モデルの学習実行
いよいよモデルの学習を実行してきます。
epoch_num= 200 #学習数
batch_num= 32 #バッチサイズ
# modelの学習開始
# verbose:学習ログの表示(1=ON,0=OFF)
# validation_split:訓練データを分割して検証に用います
history=model.fit(in_var, out_var,
epochs=epoch_num,
batch_size=batch_num,
verbose=1,validation_split=0.2)
ここまでのプログラムが問題なく実行されていれば、実行時に下記のような表示になります。
(loss,accuracyの値は若干異なる可能性があります。)
結果の表示
続いて、学習の結果を表示させます
ここでは、"matplotlib"を使用します。
横軸「学習回数」縦軸「正答率」として、グラフ描画し、学習が進むにつれて正答率が上昇していく様子を確認します。
import matplotlib.pyplot as plt
#学習結果表示
plt.plot(history.history['accuracy'],label='accuracy')
plt.plot(history.history['val_accuracy'],label='val_accuracy')
plt.legend(frameon=False)
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.show()
こちらを実行すると、下図のようなグラフが表示されると思います。
ニューラルネットワークは学習の過程で乱数を使用するため、毎回結果は異なります。
(seed値の固定をすれば毎回一緒にすることもできます。)
なので、細かい値は異なると思いますが、おおまかな形(最初大きく上昇して、徐々に緩やかになっていく形)が一緒でいればOKです。
テストデータの予測
モデル学習が完了したら、次はテストデータ(未知データ)を予測させます。
#テストデータの読み込み(上記のCSVファイル読込と同じ)
path="C:\\Users\\●●●\\・・・前処理後テストデータ.csv"
TEST_data = np.loadtxt("前処理後テストデータ.csv",delimiter=",",skiprows=1)
#予測の実行
y_predict = model.predict(TEST_data)
#予測結果をCSVファイルで書き出し
np.savetxt("予測結果.csv", y_predict, delimiter=",")
上記実行すると、"予測結果.CSV"が生成されます。
中を除いてみると、下図のようになっていると思います。
これらの数字は「予測される確率」を表しており、
それぞれ、
- A列:0=死亡の確率
- B列:1=生存の確率
を意味しています。
そしてこれらは合計すると1=100%になっています。
なので、確率が高い方を予測結果としましょう。
結果の評価
予測結果をKaggleで提出して、正解率を教えてもらいます。
予測結果は指定されたフォーマット(zipファイル内の"gender_submission.csv")で提出しましょう。
私の結果は約74.4%の正解率だったようです。
この結果を良しとするか、悪しとするかは、その時応じて異なります。
私の経験上、単純な分類問題において正解率7割~8割程度であれば、比較的単純なデータの前処理や学習条件の調整で達成できます。
しかし、それ以上に精度を上げたいとなると、泥臭い作業が必要になってきます。
(そして現実問題、正解率7割~8割程度では使い物ならないことが多いです・・・)
ここから先は、データ分析のテクニック的な話になるので、今回は省略します。(また、機会があれば記事を書こうと思います。)
まとめ
いかがだったでしょうか
この記事のプログラムをコピペすれば、ひとまずニューラルネットワークを使った分類予測ができると思います。
ぜひご活用ください。