追加発注したパソコンが届かなくてすっかり死亡フラグが立っておりますが、今回は表題の件について張り切って記事を書いていきたいと思います。
初代Bonanzaが大規模パラメーターの機械学習に初めて成功させたときは入玉が思いっきり弱かったのは皆様ご存知の通りです。
これはBonanzaが学習に使っている棋譜のなかに入玉の棋譜が圧倒的に少なくて、玉が敵陣にいるときのKPPの値を学習できていなかったためです。
その後、NDFが相対KPPによる次元下げというのを発明し(WCSC24のアピール文書にて発表)、これにより入玉模様の将棋もそこそこ強くなりました。
http://www.computer-shogi.org/wcsc24/appeal/NineDayFever/NDF.txt
最終的な絶対KPP = 絶対KPP + 相対KPP + PP絶対 + PP相対
これは簡単に言ってしまえば、「玉がどこにいようが(敵陣にいようが、自陣にいようが)、右隣の金(金と同じ動きをする駒)には一定の価値があるはずだ」という玉と他の駒との相対的な位置関係は一定であるという仮定に基いています。
当然、そうではない部分もあります。最上段にいる玉にとっては後方から攻められるわけですから、下側にいる金のほうが、右側にいる金より価値が高いと思われます。
これを改善するには、玉の段ごとに相対KPPを学習させることですが、そうすると入玉棋譜が少ないので適切に学習が出来なくなってしまいます。
最終的な絶対KPP = 絶対KPP + 相対KPP + PP絶対 + PP相対 + 玉が特定の段にいるときの相対KPP + …
去年のやねうら王2014ではこの次元下げもやったのですが、あまり効果は出ませんでした。
少し時代を戻って、それでは相対KPP以前は他のソフトはどうやっていたのでしょうか。
多くの強豪ソフトではK(玉の位置による定数)を手打ちしていました。Ponanza然り、Apery然り、…。
こうしておいて機械学習させると、それと辻褄をあわせるように他のパラメーターが自動的に調整されるので、そこそこ入玉が上手なソフトに仕上がります。
これは現代でも有効な対策で、現代のソフトの入玉対策はKPP相対とKの手打ちという2つによって成り立っていると言っても過言ではありません。
ちなみに昨年のやねうら王では、このKの手打ちをしていませんでした。
次元下げをしまくったら自動的に学習するかと思っていたのですが、そこそこ入玉を阻止するものの、そんなに甘くはなかったようです。
これを手打ちすることで入玉模様の将棋が改善されて数%勝率が伸びました。
入玉将棋なんて滅多にならないと思われるかも知れませんが、将棋でも棋力の高い者同士の試合になってくると千日手による引き分けや入玉模様の将棋が増えてくると私は思っています。統計的なデータはありませんが、実際チェスの試合がそうなってきているので将棋もそうなる可能性が高いと私は思います。
話を先に進めます。
ここで、AperyのKの手打ちパラメーターを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#if defined USE_K_FIX_OFFSET const s32 Evaluater::K_Fix_Offset[SquareNum] = { 2000*FVScale, 1700*FVScale, 1350*FVScale, 1000*FVScale, 650*FVScale, 350*FVScale, 100*FVScale, 0*FVScale, 0*FVScale, 1800*FVScale, 1500*FVScale, 1250*FVScale, 1000*FVScale, 650*FVScale, 350*FVScale, 100*FVScale, 0*FVScale, 0*FVScale, 1800*FVScale, 1500*FVScale, 1250*FVScale, 1000*FVScale, 650*FVScale, 350*FVScale, 100*FVScale, 0*FVScale, 0*FVScale, 1700*FVScale, 1400*FVScale, 1150*FVScale, 900*FVScale, 550*FVScale, 250*FVScale, 0*FVScale, 0*FVScale, 0*FVScale, 1600*FVScale, 1300*FVScale, 1050*FVScale, 800*FVScale, 450*FVScale, 150*FVScale, 0*FVScale, 0*FVScale, 0*FVScale, 1700*FVScale, 1400*FVScale, 1150*FVScale, 900*FVScale, 550*FVScale, 250*FVScale, 0*FVScale, 0*FVScale, 0*FVScale, 1800*FVScale, 1500*FVScale, 1250*FVScale, 1000*FVScale, 650*FVScale, 350*FVScale, 100*FVScale, 0*FVScale, 0*FVScale, 1900*FVScale, 1600*FVScale, 1350*FVScale, 1000*FVScale, 650*FVScale, 350*FVScale, 100*FVScale, 0*FVScale, 0*FVScale, 2000*FVScale, 1700*FVScale, 1350*FVScale, 1000*FVScale, 650*FVScale, 350*FVScale, 100*FVScale, 0*FVScale, 0*FVScale }; #endif |
9一玉や1一玉に対して2000点の加点を行なっています。最終的な評価値としては、歩がAperyでは90点になっていますから(これはKPP/KKPをすべて足し合わせてFVScaleで割ったときに16bit符号型整数に収まるようにするためのスケールダウン)、歩が100点となるように正規化されて(つまり100/90が乗じられて)、将棋所に表示されます。
1 |
const Score PawnScore = static_cast |
要するに先手の9一玉や1一玉には2000×100/90 ≒ 2222点分の価値があるということですね。すごい!(「こんな大きな値を足していいのか?」という気がしますが、「他の部分で辻褄が合うように調整されるから問題ないやろ」というのが平岡さんの考えのようです。実際、Aperyは入玉将棋、とても上手いですしね。)
ここで注意したいことは、上記のKの定数は16bit符号型にギリギリ収まる範囲ではありますが、足し込んでしまうと16bit符号型に収まらなくなってきます。
具体的には、BonanzaのKKP/KPPをFV38に変換したときにKKによる位置定数が出てきます。
Bonanzaのmake_listの38要素化
http://d.hatena.ne.jp/LS3600/20141024
この定数が要るのか、要らないのかという議論があります。
というのも、この定数が大きすぎてこれをどこかに足し込むとしたらKKPテーブル自体が16bitに収まらない可能性が出てくるからです。
そこでAperyでは別途KKによる位置定数だけ32bitで持っておいて、これだけ特別に足し込むという方法が採られています。これはイケてない感じです。
FV38においては、KKPのPは平手において必ず38駒ありますから、この38駒にKK定数を均等に足し込むという方法が考えられます。この手法の考案者はAperyの平岡さんです。
KKって評価要素、あんまりいらん気しかしない。Bonanza形式との互換の為に必要だっただけやからな。
— 平岡 拓也@Ponanza倒したい (@HiraokaTakuya) November 8, 2015
@HiraokaTakuya KKPに1/38ずつ足しておけば良いしな。
— 平岡 拓也@Ponanza倒したい (@HiraokaTakuya) November 8, 2015
逆にこのように足し込めるということは、もともとKKの位置定数はKKPに含まれていると考えられるのでそのように次元下げしてしまえばそもそもこの定数は要らないということになります。つまり以下の次元下げを行います。
K1K2P = K1P + Inv(K2)InvPiece(P) + 相対K1P + 相対Inv(K2)InvPiece(P) + K1/38 + Inv(K2)/38
※ Inv(sq)は盤面を180度回転させたときのsqの移動先。InvPiece(p)も180度回転させたときの駒(敵駒への変換を含む)
※ Inv(K2)/38はK2を盤面を180度回転させた位置を求め、そのときにおけるKによる位置定数を38で割ったものという意味。
それとは別に、KKPテーブルが本当に16bitの精度でいいのかという問題はあります。
KKPは、KPもそこに含まれますから、KP自体は出現頻度は高く、それなりの値に収束するはずで、32bitぐらいの精度があったほうが棋力が高くなるという考え方もあります。新やねうら王は32bitで持っています。
KPPはともかくKKPはテーブルサイズも小さいし参照回数も少ないので32bit化しても速度的なデメリットはほぼないのでそれならば32bitで持っているほうが気分が良いというのはあります。最新のPonanzaもKKPはおそらく32bitで持っています。
一方、合議実験(評価関数のパラメーターにノイズを加えて指し手がどの程度ばらけるか、そして勝率がどの程度落ちるかを調べる)において、少々のノイズでは勝率が落ちないこともわかっています。(Ponanzaの山本君の修士論文)
逆に言えば16bitから32bitにすることによって勝率は上がらないということも言えそうですが、当時は機械学習がそれほど洗練されていなくて、入力棋譜が少なく、収束の精度もよろしくなかったので、いまとは事情が違うというのもあります。
そこで機械学習のメソッドが改良され、大量の局面を自動生成する(Ponanzaでは100億局面!)ようになれば、今後KKPは32bit化が主流になると私は考えています。
昨年のような、AWSを利用した学習は行わないのですか?
AWS、オンデマンドインスタンスでかつWindowsですとスポットインスタンスかつLinuxの10倍ぐらいの値段がかかりまして、平岡さん(月$300程度)の10倍ぐらいの金額になると試算しました。
もうそれならばPCを購入したほうが安いんじゃないかと思ったのですが、DDR4メモリの在庫がないらしく到着が遅れています。(´;ω;`)
>機械学習のメソッドが改良され、大量の局面を自動生成する(Ponanzaでは100億局面!)ようになれば、、、
プロ棋士の棋譜から学習した評価関数をつかって「大量の局面を自動生成する」と読みました。
その自動生成の棋譜を使ってもう一度「機械学習させた評価関数」の方が「ベースになった評価関数」より優秀になるのですか?
そうすると「ループさせればさせるほど優秀になる」理論になりますが、、、。
それは本当なのでしょうか?
> その自動生成の棋譜を使ってもう一度「機械学習させた評価関数」の方が「ベースになった評価関数」より優秀になるのですか?
なります。NDFとかそのiterationで強くなっています。ただ、iterationごとに伸び幅は小さくなってきて、どこかで頭打ちになります。
>iterationごとに伸び幅は小さくなってきて、どこかで頭打ちになります。
この話はピンボケ写真を画像処理してピントがあった絵を手に入れる、、、という話と似ていますね。
画像処理方法が正しければ今までピンボケで読めなかった文字が読めるようになる。
でも、一度ピントが合えばそれ以上の情報はそこからは入手できない。
そうなると、プロ棋士の棋譜の集合には「隠れた情報量がある」ということになりそうですね。
ご教授ありがとうございます。
すみません、調子に乗ってもうひとつ教えてください。
>最終的な絶対KPP = 絶対KPP + 相対KPP + PP絶対 + PP相対 + 玉が特定の段にいるときの相対KPP + …
Bonanza型3駒関係を使った評価関数の形式的な形はどのソフトでも似たようなもの、、、ということなのでしょうか?
そうして、それぞれのソフトの違いというのは、それぞれの学習の結果として、各項目にかかるウエイトパラメータの値が異なってくる、、、という理解でいいのでしょうか?
> Bonanza型3駒関係を使った評価関数の形式的な形はどのソフトでも似たようなもの、、、ということなのでしょうか?
「Bonanza型3駒関係」と書く場合は、そうです。(半数ぐらいのソフトがそうだと思います)下記の記事の一番下にある10行のソースコードと内容的には等価なものです。
http://yaneuraou.yaneu.com/2015/11/02/30%E5%88%86%E3%81%A7bonanza%E3%81%AE%E8%A9%95%E4%BE%A1%E9%96%A2%E6%95%B0%E3%81%AE%E8%A6%81%E7%82%B9%E3%82%92%E8%A9%B1%E3%81%97%E3%81%BE%E3%81%99%EF%BC%81/
毎回、興味深い記事を有難うございます。
ところで、やねうら王さんは、どのような開発環境を使っておられるのでしょうか。たとえば、VisualC++とか。。。
GCCであれば、WindowsでもLinuxでも動きますし、思考部の開発等GUI関連でなければ、OS依存の部分はない様に思えます。
また、Linuxで開発している人は、本番では、Windowsで動かしているのでしょうか、自分でOSを入れ替えているのでしょうか。
すこし気になりました。
今年のやねうら王はVisualC++2015を使って開発してます。VisualStudioのデバッガーが一番使いやすいですね。またgccはある規模のソースコードだと色々バグを踏む確率が高いので使いたくないですね。昔からgccで何度も痛い目に遭ってます。一方、MSVCはC++の規約違反の実装になっているところはたくさんありますが、バグは比較的少ないです。リアルワールドにおいてどちらがより重要なことか。偉い人にはそれがわからんのです。
ちなみにLinuxを使ってる平岡さんは前日にOSをLinuxをインストールしなおしておられます。Linux + wine + 将棋所なんて地雷の塊のような気がしますが、最悪、Windows用にビルドできるからなんとかなるのでしょう。いやはや。
そろそろ、PCが届いた頃ですね。残り日数が少なくなってきましたが、がんばってください。
自分は、いわゆる printf デバグと、必要に応じて 関数や機能単位の前後で 変数をファイルに落として比較する方法でデバグしています。
VisualStudioのデバッガは使いやすいですか。。。
若いうちに デバッガ に習熟しておくべきでした。
大変貴重な脳内リソースを費やして デバッガ を使える様にする価値があるのでしょうね。
(すみません、”脳内リソース”のフレーズを使ってみたくて、パクリました。)
ではでは。
PCが届くのは明日の夕方以降…(´;ω;`)
>・・・32bitぐらいの精度があったほうが棋力が高くなるという考え方もあります。
感覚的な話ではありますが、パラメーターの高精度化の効果が出るとしたら序盤~中盤にかけての局面の様な気がします。
終盤の指し手についてはあまり効果がないように思うのですが、このあたりいかがお考えでしょうか?
あるいは、詰みまで読みきる時に、評価関数の重要性はどのくらいあるとお考えでありましょうか?
はい、おっしゃるように、特にKPの計算精度は序盤における感覚の改善に役立つと私は考えています。序盤では評価値は大きな値はつきにくいので…。
詰みまで読み切るときも評価関数の質で詰みを発見する速度はずいぶん変わってきますが、詰み付近では、計算精度よりは、詰みやすい形に対して詰みやすさに応じた値がついているかのほうがより重要ですね。
> 少々のノイズでは勝率が落ちないこともわかっています
とすると…対人の研究対策として、複数の学習パラメータを用意して、起動時もしくは一定手数ごとに切り替えるのは意味があるのかな…
あると思いますよ。対局の1手ごとにfv.binを読みなおして乱数を加算してもいいと思いますし。