0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Flaskで囲碁オンライン対戦アプリをつくる (続き)人対botの対戦、をできるように

0
Last updated at Posted at 2025-07-27

 これは、https://qiita.com/tkoji3744/items/b51981aa8d9c3e02d454
の続きである。

 昔の開発で ( https://qiita.com/tkoji3744/items/d564f55bfc6076a6074a ) 
ランダムbotの着手は、まさに脈略がなく、またモンテカルロbotの手は、1路、2路ばかりうつようなものだった。なにより、囲んで石をとる、ような動きや、あたりで逃げるような動きは皆無だった。要するに、弱すぎて、話にならなかった。このとき、Pyaqをもとにしたbotを開発したつもりだったが、そのとき一度うまくいったと思ったのだが、その後再現性はなかった。
 そこで今回、もう一度、機械学習bot作成に挑戦してみた。そして、さらに、それをオンラインで「人 対 機械学習bot」ができるようにするという目標を掲げた。
 結論からいうと、Pyaq( ymgaq/AQ: A Go game engine. Download here: http://github.com/ymgaq/AQ/releases )
( https://colab.research.google.com/drive/1qTJY_0AfrtwiyGYnmd6PZweWw1zG7n33#scrollTo=ODfvSX7fCFKl ) やdlGo
( https://github.com/maxpumperla/deep_learning_and_the_game_of_go )
を応用、あるいは模倣した機械学習botは敷居が高く、あきらめた。かわりに、一応、TensorFlow(機械学習のパックージ 例 Keras)とNumPy(高速な配列計算のパックージ)を用いた、原始的な機械学習botを作成して、このFlaskによる囲碁オンライン対戦アプリに組み込むことに目標を下げ、何とか成功したので、報告する。
 だが、この方法では、 9路盤限定であればある程度は打てるようになるが、がんばっても5〜7級相当が限界、ということだ。
  なぜなら、この方法は、機械学習botの以下の3つの力のうち、ほんの少ししかとりれてないからだ。

△ 深層学習:最善手の直感(形の模倣)
   シンプルなニューラルネット(例: Keras/TensorFlow, PyTorchでのMLPや小型CNN)のみ
X 強化学習:よみ、経験
   self-play: 自己対戦による経験(よみ) ⇒このモデルでは不可能
X 探索:先読みする力 
   ?モンテカルロ木探索 は導入せず

 機会がもしあれば、強い機械学習botもいつか挑戦してみたいものだ。

(参考)なぜ dlgo を今回あきらめたか?
• dlgo(Deep Learning and the Game of Go)は、Python 3.6 時代のコードで、
o 依存関係が複雑
o Keras + TensorFlow 1.x 前提
o Windows 環境ではインストールや修正が非常に手間

(1)まず、tkinkerで、main_gui.py「人 対 機械学習bot」を作成する。
これに関して、パッケージ(バージョン)の組み合わせはたいへん狭く、厳しくエラーが続出。結果:

 現在のぼくのPCのパッケージ(バージョン)
   Python 3.10.x NumPy 1.24.3 TensorFlow 2.13.0
 では機械学習botはつくれなかった。

 必要なのは、
   Python3.8 Numpy==1.21.6 Tensorflow==2.10.0
  (むしろ、最新バージョンよりダウングレード)

 そのため、PC内に「仮想環境」をつくることになった。この「仮想環境」の場所も、最初は
(venv) C:\Users\koji3\deep_learning_and_the_game_of_go>
につくっていたが、CUI(Character User Interface)に弱く、GUI(Graphical User Inerface)にたよるぼく(Linuxはできず、WindowsやVSCのターミナルがなんとできる)にとっては使いにくく、結局、デストップにフォルダをつくって、そこを「仮想環境」にする(venv) PS C:\Users\koji3\デスクトップ\ml_test_project> )という方法におちついた。
 実際的には、ml_test_projectフォルダ内に、「機械学習bot対 人」のコードを書いたmain_gui.pyをおいく。そして、VSC→Open Folder→ml_test_projectフォルダ選択→画面左のエクスプローラでml_bot_project_fixed内のapp.pyを選択 →右クリックで、一番下の「Run Pythin file in terminal」を選択(VSCのターミナルが、(venv) PS C:\Users\koji3\デスクトップ\ml_test_project>でWindowの右下がvenv(3.8)となっていることを確認)、というやり方を、コードを書き換えるたびにおこなって、起動テストをおこないながら完成させていった。

 ①まず、最初にtest.pyをつくり、これがうまく動けば、このしくみが成功した証拠とする。

test.py

import tensorflow as tf
import numpy as np
 
print("TensorFlow version:", tf.__version__)
print("NumPy version:", np.__version__)
 
hello = tf.constant('Hello, TensorFlow!')
print(hello)

② sgfフォルダ内に1,028局分をよみこむ
サイト:yenw/computer-go-dataset: datasets for computer go
(参考)最終的には、1028局→10327局、にふやした

③sgf_to_csv.pyを用いて
sgf→csvへ変換  (csvフォルダ内に1028局分)

④prepare_dataset.pyを用いて
「AIの学習用データセット作成」上記の1028局分から、1つの、train_data.csv ファイル作成

⑤train.py「モデル学習」
イメージは、うちかたの形のまね。
画像識別のようなもの
(これは、地になるから、とか相手の地を消すとか、相手の石をとる、とか自の石をとられないように、とかはない。

python

import pandas as pd
import numpy as np
import ast
import tensorflow as tf

# 1. データ読み込み
df = pd.read_csv("../data/train_data.csv") # パスは適宜調整

X_list, Y_list = [], []

for idx, row in df.iterrows():
# 盤面情報
board = ast.literal_eval(row["board"])
board = np.array(board, dtype=np.int8)
board_flat = board.flatten() # (81,)
# 手番(b/w → 1/-1)
player = 1 if row["player"] == "b" else -1
X = np.concatenate([board_flat, [player]])
X_list.append(X)
# 着手点 (row, col) → 0〜80
move_idx = row["move"]
if isinstance(move_idx, str):
move_idx = ast.literal_eval(move_idx)
move_flat = move_idx[0]*9 + move_idx[1]
Y_list.append(move_flat)

X = np.stack(X_list)
Y = np.array(Y_list)

# 2. モデル定義
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(82,)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(81, activation='softmax') # 9x9=81手
])

model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])

# 3. 学習
model.fit(X, Y, epochs=20, batch_size=64)

# 4. モデル保存
model.save("../model/model9x9.h5") # フォルダは適宜
print("モデル保存完了!")

このtrain.pyを実行 → model9x9.h5ができれば成功!

image.png

学習の最中
このtrain.pyのパラメーター:Epock 1/10 ⇒ 1/50 とすると、学習完了までの時間、数十秒→40分程度 に延長。すなわち。強化学習がより強くおこなわれることになる。

できた、main_gui.pyで動かすと

image.png

(2) Flaskでこのmodel9x9.h5を動かす

①まずは、PC本体で「ランダムbot対人」(go_flask_app_dl2)をFlaskで作成。これをml_test_projectフォルダにいれて、main_gui.pyが動くその仮想環境にて実行してみる。動いたら、これをもとに、main_gui.pyを参考にしながら、go_flask_app_dl2を「機械学習bot対人」(model9x9.h5使用):ml_bot_projectに変更していく。Flaskのバージョンは3.0.3で、本体PCでも、仮想環境Python3.8 Numpy==1.21.6 Tensorflow==2.10.0 でも、ともにバッチングしなかった。

②ml_test_projectフォルダの仮想環境内に、Flaskファイル ml_bot_projectをつくり、app.pyで実行→オンラインで、「機械学習bot対人」対戦をする準備ができた。

フォルダ構成は、
ml_test_project/
├── venv/
├── ml_bot_project/
│ ├── app.py ←★この中でFlaskアプリ実行
│ ├── bot.py ←★model9x9.h5を利用してBot応答
│ ├── go_board.py
│ ├── go_types.py
│ ├── templates/
│ │ └── play.html
├── model9x9.h5 ←★この場所(親フォルダ直下)

最初、
A 前回つくった囲碁SNSのFlaskの起動時に、仮想環境を利用する。
 ⇒pythonanywhereにデプロイ時、SNSを扱うgo_flask_app_dl3 と機械学習を利用するml_test_projectを分割する。
  (なぜなら、それぞれ、つかう、Python、tensorflow、numpyのバージョンが違う)
B 簡易法:go_flask_app_dl3をml_test_projectの仮想環境内でうごくよう改変(=go_flask_app_dl3_env)して、一括してpythonanywhereにデプロイ

のどちらかか?、と思ってしばらう開発したが、結局、SNS本体サイト:
Flask(最新・通常の環境、AI無し)
→ 投稿・掲示板・碁会所マップ・人同士の対局
→ 「Botと対戦したい人はここからどうぞ」のリンクボタンを設置

と、Bot対戦専門サイト:
Flask(Python3.8/TensorFlow2.10.0/NumPy1.21.6などAI環境にあわせたvenv)
→ 9路盤人対bot専用(自分のAIモデルやPyAQ/KataGo導入もOK)
→ 「トップページ」や「戻る」ボタンでSNS本体に戻れるようにする

をわける方針とした。

最終的に、ml_test_projectフォルダ内に、「機械学習bot対 人」のコードを書いた、ml_bot_project_fixedをおく。VSC→Open Folder→ml_test_projectフォルダ選択→画面左のエクスプローラでml_bot_project_fixed内のapp.pyを選択 →右クリックで、一番下の「Run Pythin file in terminal」を選択(VSCのターミナルが、(venv) PS C:\Users\koji3\デスクトップ\ml_test_project>でWindowの右下がvenv(3.8)となっていることを確認(なぜか、右クリックで、一番下の「Run Pythin file in terminal」を選択を3回おこなわねばならない)。そして、model9x9.h5をつかったbotを使うプログラムをFlask で起動して成功した(下図)。実力は予想どおり。

image.png

最後の最後で碁盤の描画(play.html)で意外につまづいた。
その原因を、かいつまんでいえば、
当初HTMLは table を使って碁盤を描いてた。だが、これは以下の理由でうまく動作しにくいです: 問題点項目 内容📏 サイズ table だと碁盤の正方形レイアウトが崩れやすく、CSSでの細かい位置指定が難しい🎯 中心点 囲碁の石は「交点」に打ちますが、

は「マスの中央」を基準とするため、ズレる🎨 描画制御 CSSによる自由なレイヤー(線、石、ボタン)の配置が難しい📱 ブラウザ差 ブラウザの種類やバージョンによって微妙に見え方が変わり、意図した表示にならない ✅ 代案(divベース構成に置き換え)、 ではなく、以下のような構成にすれることで思う盤面 が描けた: 1つの div.board(サイズ固定の碁盤) div.grid-line(absoluteで縦線・横線を配置) div.stone.black/white(石を自由に配置) button.click-point(クリック可能な交点)

「打つ一手に、その人の全てがある。」
― 囲碁 SNS & AIプロジェクト 2025 夏

(参考)COSUMI:bot対戦 https://www.cosumi.net/play.html
  OGS: 人対人のオンライン対戦 https://online-go.com/
囲碁SNS: goxi https://goxi.jp/
 

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?