ディープラーニングで作る世界一シンプルでわかりやすい競馬予想AI①(モデル作成編)
競馬の着順(1〜18着)を予測するために、世界一シンプルなディープラーニングモデルを作成します。
全3回+まとめ編1回のシリーズを予定しています。今回の内容が最も長くなりますが、一度に全て理解する必要はありませんのでご安心ください。
早速ですが、下記のコードがそのディープラーニングモデルです。行数はわずか21行で、そのうち5行は関数の呼び出し部分ですので、実質的には16行のコードです。
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Dense, Activation
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.callbacks import ModelCheckpoint
from sklearn.metrics import accuracy_score
# ディープラーニングモデルの作成とトレーニングを行う目的関数
def objective(X, Y):
model = Sequential([
Input(shape=(X.shape[1],)),
Dense(128),
Activation('relu'),
Dense(64),
Activation('relu'),
Dense(18), # 18個のクラスラベル
Activation('softmax')
])
# 整数値のクラスラベルをOne-hotエンコーディング
Y = to_categorical(Y - 1, num_classes=18) # -1 しているのは、クラスラベルが1から18であるため
# モデルのコンパイルとトレーニング
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# ベストモデルの保存
checkpoint = ModelCheckpoint('/content/drive/MyDrive/sample/best_model.keras', monitor='val_loss', save_best_only=True)
# モデルの訓練
history = model.fit(X, Y, epochs=10, batch_size=64, validation_split=0.2,callbacks=[checkpoint])
# テストデータでの予測値の取得
y_pred = model.predict(X)
# 正解率の計算
accuracy = accuracy_score(Y.argmax(axis=1), y_pred.argmax(axis=1))
# ベストモデルの評価を返す(最大化のため、そのまま返す)
return accuracy
この先、1行ずつ解説していきますが、もしややこしいと感じたらここまででも大丈夫です。次回や後でじっくり見直してもらえば問題ありません。また、まとめ編を先に読んで大まかな流れを理解するのもおすすめです。
覚えておいてほしいのは「objective(X, Y)という関数でディープラーニングモデルを作成した」という事実だけです。(Xが入力、Yが出力)
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Dense, Activation
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.callbacks import ModelCheckpoint
from sklearn.metrics import accuracy_score
Sequential:順次モデルを定義するためのクラス。各層を順番に積み重ねる形式。
Input:最初の層に入力データの形状を定義。ここで特徴量の数を指定。
Dense:全結合層(ニューラルネットワークの基本構造)。指定したユニット数の出力を持つ。
Activation:活性化関数。reluやsoftmaxを用いて、非線形変換を行う。
to_categorical:クラスラベルをOne-hotエンコーディングに変換するユーティリティ。
ModelCheckpoint:モデルの訓練時にベストな状態のモデルを保存するコールバック。
accuracy_score:正解率を計算する関数
def objective(X, Y):
目的関数objective。X(特徴量データ)、Y(ターゲットデータ)を受け取る。
model = Sequential([
Sequential:ニューラルネットワークの各層を順番に追加する構造のモデルを定義。
Input(shape=(X.shape[1],)),
Input:入力層。入力データの形状(特徴量の数)を指定して、モデルに入力する準備をする。X.shape[1]は特徴量の数を示す。
Dense(128),
Dense(128):全結合層で、128個のユニット(ニューロン)を持つ。この層は各入力に対して重み付けされた合計を計算し、次の層に渡す。
Activation('relu'),
Activation('relu'):relu(Rectified Linear Unit)活性化関数を使う。非線形性を導入し、負の値を0に変換してモデルに複雑な関係を学習させる。
Dense(64),
Dense(64):全結合層で、64個のユニット(ニューロン)を持つ。この層は各入力に対して重み付けされた合計を計算し、次の層に渡す。
Activation('relu'),
Activation('relu'):relu(Rectified Linear Unit)活性化関数を使う。非線形性を導入し、負の値を0に変換してモデルに複雑な関係を学習させる。
Dense(18), # 18個のクラスラベル
Dense(18):出力層で、18個のユニットを持つ。これは18クラスの分類問題を想定しているため、それぞれのクラスに対応するユニットを設定している。
Activation('softmax')
Activation('softmax'):出力層にソフトマックス活性化関数を適用。クラスごとの確率分布を計算し、最も確率の高いクラスを予測するために使用。
Y = to_categorical(Y - 1, num_classes=18) # -1 しているのは、クラスラベルが1から18であるため
to_categorical:ターゲットデータY(1から18の整数)をOne-hotエンコーディング形式に変換。クラスラベルが1から18まであるため、0ベースに合わせるためにY-1を行う。
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
compile:モデルのコンパイル。adamは最適化アルゴリズム、categorical_crossentropyは損失関数(多クラス分類用)、accuracyは評価指標。
checkpoint = ModelCheckpoint('/content/drive/MyDrive/sample/best_model.keras', monitor='val_loss', save_best_only=True)
ModelCheckpoint:モデルのチェックポイントを設定。val_loss(検証データの損失)を監視し、ベストなモデルのみ保存する。
history = model.fit(X, Y, epochs=10, batch_size=64, validation_split=0.2, callbacks=[checkpoint])
fit:モデルの訓練。データXとラベルYを使い、10エポック、バッチサイズ64で訓練。データの20%を検証データに使用し、checkpointでベストモデルを保存。
y_pred = model.predict(X)
predict:訓練後のモデルに対して入力データXを用いて予測を行い、クラスの確率を得る。
accuracy = accuracy_score(Y.argmax(axis=1), y_pred.argmax(axis=1))
accuracy_score:Yと予測値y_predの正解率を計算。argmaxを使って、One-hot形式から元のクラスラベルを取得。
return accuracy
最終的に正解率(accuracy)を返す。
モデルの基本的な構造は以上です。次回はデータ作成編で、X(入力データ)とY(ラベルデータ)について詳しく説明します。
ここまで読んで少し難しく感じた方もいるかもしれませんが、全てを理解する必要はありません。分からない点は、後からでも確認できますし、まとめ編やコメントで補足を受けることも可能です。気軽に質問してください!