概要

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というファイルで行います。