概要
https://reversi.kajindowsxp.comで「フィールド情報」と「自分の操作する色」を入力とし、最良な手を返すAPIを公開しました。
コード例↓
let field = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 2, 0, 0, 0],
[0, 0, 0, 2, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
]
let param = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({field:field, color:1})
}
let res = await fetch("https://reversi.kajindowsxp.com/", param)
await res.json()
仕様
・メソッド: POST
・プロパティ: field 譜面のデータで整数の二次元配列(0なにもなし、1白い石、2黒い石)
・プロパティ: color 予測するプレイヤーの色(1白、2黒)
Github:
https://github.com/kajikentaro/ml-reversi
簡易的なコード解説
教師データ取得
教師データはフランスのFFOが公開しているWTHORを利用します。
https://www.ffothello.org/informatique/la-base-wthor/
バイナリデータでの配布となっているので、こちらの便利すぎるWebサイトを拝借し、CSVに変換します。
https://qiita.com/tanaka-a/items/e21d32d2931a24cfdc97
https://lavox.github.io/wthor.html
今回は勝ったプレイヤー、負けたプレイヤーに関わらず教師データとして採用するため、一番最後の列のデータのみ抜き出し、別のテキストファイルにコピーします
※抜粋
f5f6e6f4e3d7d3d6e7d8g4f3g5g3f7c5e8e2d2c4c2f2c3b3d1c1c7f1e1g2h3h5h1g1c8g7c6b6h8g6h7h6h2g8f8b7h4a7a8b8a6a5a4b5b4a2a3b1a1b2
f5d6c3d3c4f4c5b3c2e3d2c6b4b5f2e2f3c1a3a4a5d1f1g6e1e6b1a6f6a2h6g5h5g4g3h3b7d7c7b6a7a8b8f7g7g1h1h8h2h7g2h4e7c8d8e8g8f8b2a1
f5d6c5f4e3c6d3e2f3g6e6f6g5h4h6b5f7e7c4f8d7e8c8b3b6c3a5b4c7c2g4d8g8h3a4a3d2d1f1e1f2g1b1a7a6g2g3h2h5h7h1b8h8c1g7b7a8a1b2a2
教師データを学習用のデータに変換する
文字列のままでは教師データとして扱えないので、入力を(2, 8, 8) = (プレイヤーの数, 縦のマス, 横のマス)、それぞれのマスが0か1の値を持つように整形していきます。
get_fetching_data.pyというファイルで行います。
学習をする
学習をするためにモデルを定義します。
Sequentialモデルを用います。これを工夫することでもっと賢いAIが作れるかもしれません。
main.pyというファイルで行います。
# モデル定義
def make_model():
model: tf.keras.Model = tf.keras.Sequential([
Input(shape=(2, 8, 8,)),
Flatten(),
Dense(128, activation='relu'),
Dense(128, activation='relu'),
Dense(128, activation='relu'),
Dense(128, activation='relu'),
Dense(96, activation='relu'),
Dense(64),
Reshape((8, 8)),
Softmax()
])
model.summary()
return model
APIをたてる
fastAPIを用いてhttp://localhost:8000に待ち受けます。
api.pyというファイルで行います。