今年の将棋AI界隈に起きた大きな革命としてSPSAの導入が挙げられる。
SPSAの手法については、以下の記事に簡単な説明がある。
SPSA、探索パラメーターの自動調整手法について
この手法を私が知ったのは、KaggleのチェスAIのコンペに参加したのがきっかけである。
Kaggleで高額賞金のChess AIのコンペが始まる
上のコンペは、チェスAIで競うのだが、メモリ制限がめちゃめちゃに厳しく、結局、古いバージョンのStockfishをいかに省メモリで動かすか、また省メモリで動かしつついかに強くできるか(なるべく新しいStockfishの改良をとりこめるか)という勝負であったと言っても過言ではなかった。
しかし、そのように部分的にStockfishの様々なcommitを取り込むと、探索の枝刈りなどのパラメーター(いわゆるハイパーパラメーター)が最適値からは外れていくので、自分で調整し直す必要がある。
その調整には、StockfishではSPSAが使われており、SPSAを実施してくれるfishtestというフレームワークが使用される。
https://github.com/official-stockfish/fishtest
このfishtest、サーバーに設置して、各自がworkerとなるマシンを(サーバーに対して)提供し、サーバー側はそれらのマシンを使ってA/Bテストやら、SPSAやらを行うのである。
コンペの終盤ぐらいになって、氷彗の作者の大森さんも誘ってチームに参加してもらうことになったが、大森さんも、このときにfishtest(SPSA)の洗礼を受けるわけである。
しかし、fishtestは、Windows環境でストレートに動かなかったり、GitHubのアカウントとの連携が必要であったりと、なかなかに使いづらいところがあった。
そのため、fishtestは、チームのメンバーから(特に私から)はすこぶる不評であった。
チームメンバーであるQhapaqさんは、「このコンペ終わったら今年(2025年)は、将棋AI用にこれを移植したいですね」などと言っていたが、私は、「こんなもんぐらい自作したほうがいいんじゃないっすか?」とfishtestの移植には極めて否定的であった。
私がfishtestに否定的であったのは、自作しても簡単だし、色々改良したいところがあったからである。
たとえば、SPSAでは、少しパラメーターを変異させて基準ソフトと2回対局させる。1回目に変異させる方向と2回目に変異させる方向は真逆にしておく。
こうして1回目と2回目とで、どちらが優れていそうかを知りたい。
このとき、2回とも引き分けだとか、2回ともプレイヤー1が勝ちだとか、2回ともプレイヤー2が勝ちだとかだと、どちらに変異させたほうが良いのか優劣がつかない。(ゆえに、このときパラメーターの変動をさせられない。)
まあ、引き分けはそんなに起きるわけではないので、いまないものとして考える。
そうすると、「2回ともプレイヤー1が勝ち」と「2回ともプレイヤー2が勝ち」というパターンが起こらないでほしいわけだ。
対局したときに、プレイヤー1がプレイヤー2に勝つ確率をpとする。
2回ともプレイヤー1が勝つ確率
$$ P_1 = p^2 $$
2回ともプレイヤー2が勝つ確率
$$ P_2 = (1-p)^2 $$
「2回ともプレイヤー1が勝ち」もしくは「2回ともプレイヤー2が勝ち」との確率は、この合計だから、
$$ P = P_1 + P_2 = p^2 + (1-p)^2 $$
これが最小となるpを求めたい。
$$ \frac{dP}{dp} = 4p – 2 , これが0となるのは、p=0.5のとき。$$
よって、Pが最小となるのは、p=0.5のとき。
ということで、プレイヤー1とプレイヤー2が同じ強さのときに、パラメーターの変動が起きる確率が最大となる。
だから、つねにプレイヤー1(パラメーターを調整している思考エンジン)とプレイヤー2(基準となる思考エンジン)が同じぐらいの強さになるように自動的にSPSAフレームワークがプレイヤー2の探索ノード数を調整してほしいわけである。
しかし、このようなことをfishtestはしてくれないので、自作したほうがいいなぁと思ったわけである。
そんなことを考えながらも、私はマシンの提供以外はあまりチームに貢献できずに、コンペを終えた。我々のチームは8位に入賞し、見事Kaggle金メダルを獲得した。ひとえにたぬきの開発者の野田さん(nodchip)のおかげである。
そうして、しばらくSPSAのことは忘れていたのだが、今年の夏に氷彗と水匠のエキシビションマッチ(YouTubeで行われた81番勝負)で、水匠がぼこぼこにされているのを自宅のPCで見ながら、これはやねうら王を大改修せねばなるまいと思った。これが後に言う「やねうら王2025年夏の大改修」である。
そのときにSPSAフレームワークを私は1日足らずで書いた。ここで、速くコードが書けたことを自慢したいわけではなく、対局フレームワーク自体は私はPythonですでに書いてあったので、それを少し改造するだけで書けたから1日足らずで済んだということである。だから、この結果から見ても私はfishtestを将棋用に移植しなくて良かったと思うわけである。
また、そのあと、氷彗の大森さんも氷彗にSPSAを導入された。(詳しいことは聞いていないので、SPSAフレームワークを自作されたのか何なのかは知らない)
そうして、今月開催された第6回世界将棋AI電竜戦の決勝では、1位が氷彗チーム、2位が私(やねうらお)が率いる水匠Concertoチームとなった。
第6回世界将棋AI電竜戦参戦記
Kaggleのコンペで同じ釜の飯を食った門下生たちが、時を経て、今度は大舞台で刃を交える。
結果は1位と2位。
少年漫画なら最終回にこそふさわしい胸熱展開だ。こんなドラマみたいな展開、現実であるんやなと思った。
そんなわけで、個人的には、今年の将棋AI界の三大ニュースには是非SPSAを入れていただきたい。
「「プレイヤー1が1回勝ってプレイヤー2が1回勝つ」というパターンだけが起こらないでほしい」というのは分かったのですが、その続きで
「プレイヤー1が1回勝ってプレイヤー2が1回勝つ」確率は、この合計だから、
P=P1+P2=2p(1−p)
これが最大となるpを求めたい。
となっているのは矛盾していませんか?Pは小さくしたいのではないですか?
この記事、本日オンラインで会議中に暇だったからこそこそ書いてたので、数式のところが盛大に間違っておりました。そのあと自ら間違いに気づいて修正致しました。
(25日の23時には修正済み。ブラウザでリロードしないと古い記事が見えているかも…)
いずれにせよ、御指摘、ありがとうございます。
夕方ごろに後で読もうとタブで開いたままにしてたので、修正前の文章を読んでいました。
コメント送信後、少ししてからリロードしたら、かなりの量の修正が入っていて「こんな遅い時間なのに、やねさん、すげぇ!(感嘆)」と思ってましたw