将棋ソフトを用いた次の一手問題の自動生成

本稿は技術書典5にて頒布する科学するコンピュータ将棋シリーズの宣伝記事です。

 

大判解説などの将棋イベントで特に人気があるのが指導対局です。プロ棋士と実際に対局を行い、指し手の良し悪しについて幾つかのアドバイスを貰えるこのイベントは将棋の体験としても、また、棋力を上げる上でも非常に良いものです(*)。

 

しかし指導対局は何時でも受けられるわけではありません。最近では将棋ソフトはプロ並みの強さを手に入れては居ますが、奴らは只管に無慈悲であり只々負け星を積み続けることになります。

 

そこで、自分と似たような棋力の人間やソフトと戦い、その対局をソフトに振り返ってもらうことで擬似指導対局が出来ないだろうかと考えました。以下、そのやり方と結果についてご報告します。

 

【悪手を元に次の一手問題を作る】

筆者と似たような棋力の持ち主としてGameDesignの将棋Flashのレベル9と対局を行いました。棋譜の局面を一つずつQhapaqに評価させ、私と将棋FlashのCOMがドレだけ悪い手を指したかを可視化してみました。

 

f:id:qhapaq:20181003234706p:plain

横軸が手を指す前の評価値(から計算された勝率)、縦軸が手を指した後の評価値です。私もソフトもかなりの数の酷い手を指しているのがわかります。

 

このままでは、感想戦というより指したほぼ全ての手をdisられるだけの処刑大会になってしまいます。

 

そこで、限りなく沢山有る悪い手の中から、指導に向いた局面を抽出することにします。以下のガイドラインに従い、検討するべき手を絞ることで、比較的教育的な悪手を引っ張ってくることが出来ました。

 

1.正解の手が一つに絞られている局面を使う(答えが複数ある複雑な局面を避ける)

2.悪い手を指した前後の局面を使う(プレイヤーが間違える程度には複雑な局面を使う)

 

【例題】

 

f:id:qhapaq:20181003235051p:plain

穴熊の対抗系の終盤。双方の玉が危ないですが、此処で先手番が指すべき手は?

(答えは下に記載)

 

 

 

 

 

 

この問題の唯一の答えは26銀です。その他の手は17桂成、同香、39銀打、18金、38龍で寄り筋となってしまいます。26銀には47桂成から絡みつかれるのが怖いですが、26銀、47桂成、13金、同香、76角で龍を攻めながら先手を取ることが出きます。この局面の評価値は1200前後であり、相当先手が有利なのですが、受けの手を誤ると後手勝勢となります。

 

筆者はこの局面で44角と指してしまいました。ただし、相手のソフトも弱かったため上述の詰み筋に気付かず、最終的には勝つことが出来ました。twitterでこの問題を流したところ、恐らく私と似たような棋力の人が44角と答えてしまっていたので、教育的には悪くないのではないかと思います。

 

【今後】

web上にある棋譜を集める、ユーザ投稿するなどをして大量に棋譜データを集め、今回のような自動生成を行えば、毎日次の一手を呟くbotのようなものが作れるかも知れません。ソフトによる指導対局という新しい分野が切り開かれれば何よりです。

 

【最後に宣伝】

10月8日に開催の技術書典5に参加します。技術書典4で頒布した科学するコンピュータ将棋の改訂版と2018年流行の新技術を主に取り扱った別冊Qha学習を、それぞれ700円、300円で頒布します。

 

イベントのページ:

https://techbookfest.org/event/tbf05
https://techbookfest.org/event/tbf05/circle/53170003

 

githubにアップしたサンプル:

 Release 科学するコンピュータ将棋 サンプル · qhapaq-49/Kusokappa · GitHub

(特にQha学習は誤植が有る可能性が高いので見つけたら教えて頂けると助かります ><)

 

足を運んでいただければ幸いです。

技術書典4同様、webでの頒布も予定しております。リリース時期は未定ですが、遠方の方などにご活用いただければと思います。

 

(*) 余談ですが筆者は2014年の竜王戦の大判解説で藤井猛九段の指導対局を受けたことがあります。将棋界のスーパースターが来るとだけあって、参加希望者が異様に多く、少なく見積もって倍率5倍のクジを引きあてることに成功したわけですが、当時は其のありがたさがイマイチ解っていなかった気がします(結果は二枚落ちで挑戦して負け。21手詰が炸裂した瞬間にギャラリーが湧いていたのが印象的でした)

将棋ソフトから見る昨今の女流棋士の急激な成長

棋士ランキング(レーティング)のレーティング最下位は誰でしょう。

長きにわたってこの問の答えは「女流棋士」だったのですがそれも今は昔。2018年になってから女流棋士はそのレートを80超上げる急激な成長を遂げ、レーティング最下位の座を脱出しています。

確かに、女流棋士界で不動の王者である里見女流四冠の男性プロ棋士成績(巷でいう公式プロ棋戦)での勝率は3割弱であることを考えると、男女プロ棋士間に大きなレート差があることは間違いないでしょう。

とはいえ、同じ負けでも完敗と惜敗がありますし、年に数局しか組まれないカードだけで判断するのも早計というものではないでしょうか。そこで本稿では女流棋士棋譜を将棋ソフトを用いて解析することで、女流棋士の近年の成長を見ていきたいと思います。

 

【悪手率は大差ない】

今回はQhapaqを使って里見女流四冠の棋譜を解析してみました。Qhapaqを用いて手が指された前後の評価値の差を計算しその差分(悪手率)を見ることで、各プレイヤーがどの程度の割合で悪手を指すかを可視化しています。解析条件は豊島棋聖と永瀬七段の棋譜を解析したときと同じです。計算して得られた悪手率の比較(豊島棋聖、里見女流四冠と其々の対局相手の平均)がこちらです。横軸が手を指す前の評価値で縦軸が悪手率です。基本的に値が小さいほど悪手が少なく強いことになります。

 

f:id:qhapaq:20180922135548p:plain

 

驚くべきことに、里見女流四冠の悪手率はプロ棋士で最強クラスのレーティングを持つ豊島棋聖とほぼ同じとなってます(*)。

 

(*) 詳細は省きますが点数ごとの悪手率だけでなく、全局を通じた悪手率の平均も大差ありませんでした

 

【一致率によるレーティングの再評価】

 悪手率だけで強さを見積もると、強さの順位は、豊島棋聖≧里見女流四冠>里見女流四冠対局相手>豊島棋聖対局相手となります。ただ、これは今までの対戦成績から来る予想とは大幅に異なります。各種棋戦でシードを持つ豊島棋聖の対局相手はプロ棋士の中でもかなりの上位棋士であること、里見女流四冠が昨年参加した奨励会三段で負け越していることを考えると、豊島棋聖>豊島棋聖対局相手>里見女流四冠>里見女流四冠対局相手となる方がより自然であると考えられます。

 

そこで、悪手率の代わりに手の一致率も比較してみることにしました。

 

・豊島棋聖:54.0%(15036/27842)

・永瀬七段:52.3%(8954/17106)

・豊島棋聖対局相手:51.6%(14348/27761)

・永瀬七段対局相手:51.4%(8704/16923)

・里見女流四冠:50.3%(4171/8290)

・里見女流四冠対局相手:50.2%(4163/8290)

 

一致率ベースの解析のほうが、悪手率よりも結果がより信頼できる印象を受けます。

 

【里見女流四冠の成長】

里見女流四冠の此処最近の躍進に敬意を払い、里見女流四冠の2014年以降の棋譜とそれ以前の棋譜で一致率を比較した結果がこちらです。

 

・里見女流四冠(2014-):50.3%(4171/8290)

・里見女流四冠対局相手(2014-):50.2%(4163/8290)

・里見女流四冠(-2014):48.8%(3318/6795)

・里見女流四冠対局相手(-2014):45.7%(3111/8290)

 

こうして比較すると里見女流四冠の此処数年での成長の著しさを見ることが出来ます。また、対局相手である他の女流棋士も成長をしている(ただし、2014年以降の棋譜には奨励会三段の棋譜が含まれるため、相当な底上げもされている)ことが示唆されています。どのぐらい強くなったのかを定量的に見るのは困難ですが、豊島棋聖や永瀬七段の勝率と一致率から予想するに、レートに換算して100は上がってるのではないかなと思います(これは正直ほぼ妄想ですが)。

 

【筆者によるポエム】

追記:将棋より数年先にソフトによる研究が隆盛しているチェス業界に於いて、新しい測定方法が示唆されたようです。次はこの手法を取り入れたレーティングをやってみたい所....です。

 残念ながらチェスの考察はvalidationがしっかりしていない、アルゴリズムの詳細が公開されていないなどハズレしか見つからなかったため諦めました。ただ、chess.comの考察でも一致率は使われており、推定レートと良い相関を示しているので一致率ベースの解析は基本路線として悪くないと考えられます。

 

YSSの研究でアマチュアのレート測定に絶大な効果をもたらしていた悪手率測定がプロ棋士のレート測定では脆弱である可能性が示唆されました。今回の研究の結果を見ると、悪手率よりも一致率のほうがプロ棋士のレート測定には適しているように見えますが、一致率こそ戦型の依存性が強いのではないかと考えていたので正直意外です。

豊島棋聖の研究でも、上位棋士は相手がソフト指ししてもジリ貧になるような戦型へ相手を誘導することに長けていることが示唆されているので、ソフトを用いたレート測定はまだまだ難点が沢山潜んでいそうです。

 

【宣伝】

技術書典5にQhapaqも参加し「科学するコンピュータ将棋」シリーズを販売します。今回から、LTSバージョン(数式やモデルなどを中心とした教科書的な解説)とQha学習バージョン(1年後にはゴミになってるかも知れないが、今流行している技術)をお送りいたします。詳細な宣伝ページは来週頃作る予定ですが、LTSは700円(そして前作購入者は無料)、Qha学習は300円を予定しています。

 

【宣伝2】

二次元婚活エンジンを作りました。16個の質問に答えることで、脳内で想像した二次元キャラをあてたり、オススメの二次嫁を教えてくれるサービスです(質問を心理テストに絞ったakinatorのようなものだと思うとわかりやすい)。現在絶賛教師データ募集中です。是非遊んで教師データを増やしてください

 

 

【宣伝3】

Qhapaq Research Labでコンピュータ将棋まとめwikiの作成を進めています。まだまだ記事を募集していますのでぜひご協力ください。

コンピュータ将棋纏めサイトの設立と記念評価関数(R4330)の公開

コンピュータ将棋の纏めサイトを設立しました。

https://www.qhapaq.org/

 

コンピュータ将棋に関する様々な情報を纏めることを目的としており、現在レーティング、wiki機能が実装されています。

 

また、公開を記念してillqhaシリーズを改造した評価関数orqhaを公開します。

ダウンロードはこちらから。

 

【成績】

dolphin1/orqha vs dolphin2/illqha2 145-104

dolphin1/orqha vs dolphin2/nnuekai6 418-398

 

nnuekai6とは拮抗していますが、illqhaにはnnuekai6より良いスコアで勝てているようです。

 

総合的には現時点までに公開されている評価関数よりレート20〜30程度上のようです。

今後もQhapaq Research Labは様々なコンテンツを公開していきます。どうぞ応援してください。

 

orqha絡みの棋譜棋譜ダウンローダのページから取得できます。

ロタさんの棋譜(測定を依頼した)のQh18xxxxシリーズがorqhaです。ファイル名のtypoの影響で名前が統一されていないですが、バイナリを調べることで問題ないことを確認しています。

 

# ソシャゲよろしく皆様の協力が集まるほど強い評価関数が公開されるシステムです。その気になれば4370ぐらいまでは出せるんじゃないかな....... wcscまでに4400の大台を超えたいですね

豊島棋聖と永瀬七段の強さの秘訣をAIに聞いてみた

将棋星人が攻めてきたら地球代表を誰にするか。この問に「豊島棋聖」と答えると「こいつ将棋通だな」と思われることでしょう。というのも、豊島棋聖は非公式の棋士レーティングに於いて長らく頂点に君臨し続けているからです。

豊島棋聖は長きにわたって勝ち星を積み重ね続けていますが、その棋風は掴みどころが難しく、あえて言うなら「最後は勝ってしまう」(豊島の将棋 実戦と研究 (マイナビ将棋BOOKS)より)「序盤中盤隙がない」と評されるぐらいです。

そこで今回は次世代の将棋星人である豊島棋聖の強さの秘訣を将棋ソフトを使って解析してみます。

 

【評価方法】

評価値毎の悪手率(手を指す前の評価値と後の評価値の差から求められる悪い手を指す確率)を計算しています。粘り強さが重要となる劣勢局面での悪手率、研究の深さが重要となる互角局面での悪手率、詰めの腕が重要となる優勢局面での悪手率を比べることでプレイヤーの棋力を可視化していきます。詳細は中学生棋士のレーティング考察をご覧ください。

今回は豊島棋聖、豊島棋聖の対戦相手(の平均)に加え、ソフト同士の1手1秒の自己対局、レーティング3位で負けない将棋に定評がある永瀬拓矢七段の解析を行いました。

解析は最新のQhapaq(レーティングサイト基準でレート4300超)で行っています。

 

【勝ちが見えた局面での差し回しが大事】

以下に豊島棋聖、永瀬七段、その対局相手、ソフト(nnue)の自己対局の悪手率を示します。横軸が手を指す前の評価値、縦軸が悪手を指す確率(厳密には手を差した前後での評価値の減少分の平均)です。端的に言って低いほど強いです。

f:id:qhapaq:20180818223723p:plain

 

結果を比べると豊島棋聖、永瀬七段ともに、対局相手に比べ、勝ちが見えている局面(評価値0-2000程度)での悪手率の低さが目立ちます。有利な局面での差し回しの正確さがレーティングと強い相関を持つという結果は 中学生棋士のレーティング考察と同じです(注:解析ソフトを変えたので豊島棋聖/永瀬七段と中学生棋士定量的な比較をすることはできません)。

豊島棋聖はソフトと比較しても0〜200点程度の序盤の差し回しが正確であること、永瀬七段は評価値が悪い局面全体での粘りが特に優れて居ます。さすがは負けない将棋。

 

【ソフト指しをしても勝てない豊島/永瀬将棋の恐ろしさ】

「ソフトや検討の言うとおりに局面が進んだのに気がついたら決着が付いている」という展開は今のソフトをもってしても起こることです。そこで、各プレイヤーについて「解析ソフトと手が一致した局面だけ抽出した悪手率」を計算してみました。普通に考えれば全てのプレイヤーの結果は同じになるはずです。が、しかし......

 

f:id:qhapaq:20180818225147p:plain

豊島棋聖/永瀬七段の対局相手の悪手率の分布はソフトと同じような結果になっている一方で、豊島棋聖/永瀬七段の悪手率は他よりも低くなっています。これはソフトが推奨する手(≒悪手でない自然な手)を指すことで良くなりやすい局面に相手を誘導できているからであると考えられます。

 

【考察】

上位棋士の強さの秘訣が有利な局面で間違えないことにあることが改めて確認されました。加えて、ソフトの言う通りの手を指しても評価値が悪くなりやすい局面へ相手を誘導する序盤の構想力が求められていることが示唆されました。

 

【筆者のポエム】

将棋ソフトは大体の局面で99点程度の手を指すことができるし、終盤は基本間違えません。それ故に、嘗て神の一手と言われるような手は減りつつありますが、ソフトからすれば人間が生み出した定跡こそが神の一手だと思います。

 

【最後に宣伝】

マイナビ 将棋神 やねうら王にQhapaqも搭載されます。対局相手のレベル調整や考察向けの機能など、将棋ソフトを使い尽くす上で便利な機能が搭載されています。やねうら王はたぬきやQhapaqなどの上位ソフトや、将棋ソフトを使って棋譜解析を行っている有志にも用いられており、今後もどんどん機能が追加されていくと思われます。是非、検討していただければ幸いです(そして、仮に購入するならこのリンクから買うのです。買うのです......多分sdtでQhapaqがちょっと強くなります)

 

技術書典5に出ます。サークル名は河童2.0です。ソフトを使った棋風解析や最近のNNUE関数の学習方法について何かを述べるつもりです(そう、まだ何もできていないのだ)。

CentOS 7 でblas(cblas)を使う方法

CentOS(wiki)はそのサポート期間の長さから、企業や大学のサーバによく用いられるOSです。

CentOSはパッケージ一つ入れるだけでも検索戦争に耐えねばなりません。というのも、シェアが少ない故に情報に乏しいことに加え、tensorflowなどの近代的なパッケージはubuntuでの利用を想定していることが多いからです。故にCentOSを個人が使う理由はないと思っているのですが、残念ながら上の人間(組織)からCentOSを使うことを強いられるシーンは多々あります

以下のシンプルなcblasのc++用のサンプルコード(sample.cpp)を動かすことを考えましょう。
因みに筆者はこれで3時間ぐらいを溝に捨てました。

#include <cblas.h>
#include <stdio.h>

// based on https://github.com/xianyi/OpenBLAS/wiki/User-Manual                                                          

int main(){
  int i=0;
  double A[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0};
  double B[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0};
  double C[9] = {.5,.5,.5,.5,.5,.5,.5,.5,.5};
  cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans,3,3,2,1,A, 3, B, 3,2,C,3);

  for(i=0; i<9; i++){
    printf("%lf ", C[i]);
    printf("\n");
   }
  return 0;
}

【openblasを使おう】
悪いことは言いません。以下のコマンドでopenblasを導入し、ライブラリとヘッダファイルへのリンクを貼りましょう。

sudo yum install openblas*
g++ sample.cpp -lopenblas -I/usr/include/openblas

【個人的アドバイス:atlasを使うのはよそう】
CentOS cblasで検索するとatlasを使う方法の記事が沢山でてきますが、atlasはオススメしません
ベンチマークで負けていることが多く、CentOSのバージョンによって名称が変わってくれたりundefined referenceを頻発するからです(私の手元のCentOS7ではsatlasやtatlasをリンクしてもundefined referenceが出続けた)。

【間違ったcblasをインクルードしていないか気をつけよう】
運悪く(または何らかの圧力、必要性に屈して)atlasを入れてしまった人はこれに気をつけなければなりません。openblasのcblas.hは/usr/include/openblas/cblas.h に、atlas由来のcblas.hは/usr/include/cblas.h に配置されます。openblasを使う際にatlas由来のcblas.hをインクルードしてしまうと(例えば上述のコンパイルから-Iを除去すると)コンパイルの最後でundefined referenceが出てきて心を砕かれる羽目になります。-Iでちゃんとどのディレクトリからcblasをインクルードするかを明記しておくと良いでしょう。

undefined referenceの一例

sample.cpp:(.text+0x1c1): `cblas_dgemm(CBLAS_ORDER, CBLAS_TRANSPOSE, CBLAS_TRANSPOSE, int, int, int, double, double cons\
t*, int, double const*, int, double, double*, int)' に対する定義されていない参照です
collect2: エラー: ld はステータス 1 で終了しました

次世代の将棋思考エンジン、NNUE関数を学ぼう(その2.改造/学習編)

前回の記事からかなり時間が空いてしまいましたが、引き続きNNUE関数について議論していきます。
現在、まふ氏が作成したNNUE型の評価関数がQQR(KPPT型)とならび、将棋ソフトの評価関数で最強の座についています。学習パラメタなどについては、まふ氏の解説も参考になるでしょう。

ここではNNUE関数のネットワークの弄り方や、改造の大まかな指針について解説いたします。
NNUEはKPPTに比べ改造が加えやすい(おかげで開発者の計算資源がマッハで削れる)ので、工夫の入れようが多々あるでしょう。

qhapaq.hatenablog.com

【NNUE関数はやねうら王本家にマージされています】
NNUE関数がやねうら王にマージされたことで、やねうら王でNNUE関数の学習、対局が出来るようになりました。
今後の探索部の拡張や評価関数の解析機能などの追加機能はやねうら王で行われる可能性が高いため、NNUE関数はやねうら王上で扱うことをお勧めします。マージに伴い、本稿のファイル名、関数名もやねうら王基準に変更します。

【ネットワークサイズガチャのやり方】
ネットワークのサイズは以下のコードを書き換えることで変更できます。

【1. /source/eval/nnue/architecture.h を改造する】

// NNUE評価関数で用いる入力特徴量とネットワーク構造                
// 中略
// 入力特徴量とネットワーク構造が定義されたヘッダをincludeする 

// ここのファイル名を変える
#include "architectures/your_network.h"

// 元のファイルをコメントアウト
//#include "architectures/halfkp_256x2-32-32.h"
//#include "architectures/k-p_256x2-32-32.h"                                    
// 以下略

【2. eval/nnue/architectures/your_network.h でネットワークのサイズを定義する】

// architectures/halfkp_256x2-32-32.h をコピペした後に以下を書き換える
// kp -> 128x2 -> 32 -> 32 -> 1 のネットワークを構築
// 変換後の入力特徴量の次元数                                                                                                                  
constexpr IndexType kTransformedFeatureDimensions = 128;

namespace Layers {

// ネットワーク構造の定義                                                                                                                      
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
using OutputLayer = AffineTransform<HiddenLayer2, 1>;

【2.5 (optional) . extra/config.h を編集する】

#if defined(YANEURAOU_2018_TNK_ENGINE)
#define ENGINE_NAME "YaneuraOu 2018 T.N.K."
#define EVAL_NNUE
# USE_BLAS を追加することでblasが使えるようになる(学習が高速になる。探索は高速にはならない)
#define USE_BLAS


【3. Makefileを編集する】

# デフォルトではKPPTになっているので、以下のコメントアウトを外す
YANEURAOU_EDITION = YANEURAOU_2018_TNK_ENGINE
# gccの場合、フラグにlblasを足さないといけない(筆者計算環境の場合)
ifeq ($(findstring g++,$(COMPILER)),g++)
        OPENMP   = -fopenmp -lblas
        OPENMP_LDFLAGS =
endif


【4. ビルドし直す】

make evallearn

【5. 学習させる】

./YaneuraOu-by-gcc
# SkipLoadingEvalをtrueにしないと評価関数のフォルダがないよと怒られる
# このオプションはEVAL_LEARNがonじゃないと動かない様子
setoption name SkipLoadingEval value true
setoption name Threads value 8                                                                                                                 
learn shuffled_sfen.bin ....

【ありがちな学習の失敗】
ネットワークの形を変えるとゼロから再学習になるため、それなりの計算資源が必要です。
例のごとくQhapaqチームにはそれを回す元気はないので、評価関数はあんまり強くなっていないです。

なお、よくある失敗としてtest_cross_entropy(ちゃんと教師データの外からvalidation用のデータを用意している)
は、デフォルトとさほど変わらない一で、move accuracyが落ちるパターンがあるようです。例えば私が用意した教師データに対し、tttakさんの評価関数では一致率が38%前後になるところ、小さいネットワークをゼロから学ばせると31%前後になります。

cross_entropyは据え置きにしながら手の一致率が落ちる理由は幾つか考えられますが、私自身はNNUEの学習にはランダムムーブによる局面の分散がKPPT以上に重要なのではないかと予想しています。

この予想を支持するデータ、理論は幾つかあるのですが、QhapaqはNNUEの実験に現状乗り遅れているので、秘密にしておきます。

【学習パラメタに関する議論】
詳しい解説はtttakさんの記事透さんの記事まふさんの記事をご覧頂きたいのですが、学習パラメタについてbatch_size_nnをどのぐらいにするか、教師をどのように作るか、lambdaをどうするか、newbob_decayを幾つにするかについて議論がされています。

画像認識の業界ではbatch_size_nnを大きくしすぎると精度が落ちることが報告されているようです。ただ、NNUE関数は通常のディープラーニングに比べてニューロンの数が少ないので、画像認識と同じ発想が使えるかは謎です。

次世代の将棋思考エンジン、NNUE関数を学ぼう(その1.ネットワーク構造編)

update 18/06/03 12:00

NNUE評価関数とは将棋ソフトの思考エンジン(もとい、局面の良し悪しを評価するための関数)です。NNUE関数は今流行りのニューラルネットディープラーニングの小さいやつ)を盤面評価に取り入れており第28回コンピュータ将棋選手権で多くの既存評価関数ユーザをぶちのめしてきた新機軸評価関数です。

2018年6月時点で多くの開発者、有志がNNUE関数をイジって遊んでいます。公開されてから未だ日が浅いため、もしNNUE関数の学習で大当たりを引けば、次の電王の座を手に入れられるかも知れません。

というわけで、このゴールデンカムイに乗っかろうとする皆様のために、NNUE関数の成り立ちについて解説していきます。今回はネットワークの構造と、学習のルーチンの仕様について紹介していきます。

開発者による解説文書(正直結構難しい)
tnk-のgithub (現在NNUE評価関数はやねうら王にマージされており、ファイル名がtnk-とは異なるなどの違いがあるようです。本稿ではファイル名は暫定的にtnk-を基準としています)
やねうら王のgithub (NNUEが既にマージされています。)

【1ページで解るNNUE関数】
NNUEのネットワーク構造は以下のような浅いニューラルネットワークになっています。ニューラルネットディープラーニングについては此方の本などを参照してください。

f:id:qhapaq:20180603123332p:plain

この辺の実装はeval/nn/architectures/halfkp_256x2-32-32.h などに書かれています。
NNUEの強さの秘訣は点線で囲んだ最初の層の計算をCPUベースで高速に行なえるようにした(SIMD計算と差分計算を使えるようにした)ことです。また、NNUEのコードはテンプレートを上手く使いこなし、高速且つ拡張性が高い形になっています。

【NNUE関数を自前で作る】
NNUE関数はCPUベースで動くように作られているため、基本的にやねうら王の学習方法を使い回すことが出来ます。例えば以下のようなコマンドで学習が出来ます。
(NNUE開発チームの一人であるnodchipさんの呟きからインプットの例を復元しました)

# 学習前の評価関数を決める
setoption name EvalDir value nn_20180519
# 学習させる
learn teacherdata.bin lambda 0.5 eta 0.1 newbob_decay 0.5 batchsize 1000000 nn_batch_size 1000 eval_save_interval 100000000 validation_set_file_name varidationfile.bin

これをやると例えば以下のような出力が得られます。
各インプットの意味は#以下に書き記しておきます(実際の出力ファイルにはでてきません)

# gensfenで作った教師データ
learn from teacherdata.bin,
# 過学習回避のためのバリデーションデータ
# 各iteration毎にvalidationの中身は全て読むので巨大なファイルにしないこと!
validation set  :  varidationfile.bin
# 学習ファイルを何らかのフォルダにまとめて入れる場合
base dir        :
target dir      :
# 学習のループ回数
loop              : 1
# 学習データとして用いる評価値の上限
eval_limit        : 32000
# 保存を一度だけするか
save_only_once    : false
# 学習時に棋譜のシャッフルを飛ばすか
# 教師データをデフォでシャッフルしてるなら多分意味はない
no_shuffle        : false
# 使う目的関数。elmo型を使う
Loss Function     : ELMO_METHOD(WCSC27)
# lossを表示し評価関数を更新するinterval
# 実効的にこいつはミニバッチサイズではないことに注意
mini-batch size   : 1000000
# 真のミニバッチサイズに相当。
nn_batch_size     : 1000
# ニューラルネットに特殊なオプションを送る
nn_options        :
# 学習率
learning rate     : 0.1 , 0 , 0
# 学習率をiteration毎に変える場合の係数。詳しくはやねうら王のドキュメント参照
eta_epoch         : 0 , 0
# lossを見張り学習率を動的に動かすためのパラメタ newbob = 1.0で無効化される
scheduling        : newbob with decay = 0.5, 2 trials
discount rate     : 0
reduction_gameply : 1
# elmo学習のlambda
LAMBDA            : 0.5
LAMBDA2           : 0.33
LAMBDA_LIMIT      : 32000
# 盤面の鏡像化の頻度
mirror_percentage : 0
# 保存する頻度を指定
eval_save_interval  :  100000000 sfens
# mini-batch-sizeと同値
loss_output_interval: 1000000 sfens

【重要な注意点】
NNUE型を回す際に特に以下の点に注意する必要があります。

・validation_set_file_name をちゃんと作る。かつ大きくし過ぎない
validationファイルは過学習をしていないか確かめるためのデータで、教師データとは異なる(教師データにはない局面を使う)必要があります。
また、validationファイルは各iteration毎に全て読み込まれるようなので、これを大きくし過ぎると学習時間が伸びます。

・実効的なミニバッチサイズはnn_batch_sizeである
パラメタにbatch_sizeとnn_batch_sizeがありますが、実効的なbatchsizeはnn_batch_sizeです。
どういう原理で動いているかを時系列で表すと

1.読ませた局面数がbatch_sizeになったら評価関数の更新を行う
2.評価関数の更新ではbatch_size個の教師をnn_batch_size個毎の教師グループ
(即ち、グループ数はbatch_size / nn_batch_size個になる)に分ける
3.教師グループ0を用いて、評価関数の勾配を求める
4.勾配を用いて評価関数を更新する
5.教師グループ1,2,について同様の処理を行う

という設計になっています。(eval/nn/evaluate_nn_learner.cpp、および、eval/nn/trainer/trainer_affine_transform.h を参照)
本家やねうら王のbatch_sizeがbatch_sizeとして機能していないことに注意しましょう。

KPPTと比べるとかなりbatchsizeが小さいですが、開発者曰く、ニューラルネットワーク的にはnn_batch_sizeの1000は大きめの値だそうです。そして、大きくしすぎると学習が上手く行かなくなるそうです。

なお、NNUEでは学習時はblasを使い複数の局面の評価値を並列的に求めて高速化しているため、nn_batch_sizeは大きくしたほうが学習が早くなるようです。ただし、nn_batch_sizeを大きくした分だけメモリも消費することにはご注意ください。


・学習率の調整オプションがKPPTと異なる

NNUEには現時点ではadagradなどのadaptiveな学習ルーチンは実装されていません。学習が進むに連れてネットワークの変化量が少なくさせるためにnewbob_decayというパラメタを使います。
これは評価関数を保存する(eval_save_interval)毎にvalidation用のデータに対するlossを観察し、lossが大きくなった場合は学習率を下げる(newbob_decay倍する)と同時に、評価関数を最もlossが少なかったものに戻す機能を持っています。

ただ、newbob_decayの効果がどのぐらいあるかは不明です。tttakさんが作ったNNUE関数ではoffにされているようです。
(リストアを一時的にoffにするというのがコレに相当すると予想。本人に聞いたわけではないので定かではありません)

newbob_decayではvalidation用のデータのlossを参照するので、validation用のデータはちゃんと用意する必要があります。
データの数を大きくしすぎると評価に時間がかかりますが、小さくしすぎても学習に悪影響をもたらします。
newbob_decayは1.0にすることで無効化出来ます。

ただし、newbob_decayを1にしてetaを一定とした場合、ネットワークの変化量が少なくなるということはありません。
newbob_decayを無効化し、かつ動的に学習率を下げたい場合は、iteration毎に学習率を変える必要があります。
これは、やねうら王に実装されている動的学習率変化を用いて実現可能です。

・nn_optionsという魔境
learn nn_options hoge とすることで、各ニューロンに命令を送ることが出来ます。
ただし、nn_optionsの用法については謎が多く(今公開されている評価関数群で使われた形跡がない)、
その効果も定かではないので現在調査中です。

# 高度な構文解析機能を用いて様々な命令を遅れるようにしてるみたいですが、c++の文字列制御コード読むの怠いんよ

【ここまでの纏め】
NNUEは良くも悪くも新しい関数であり、その学習のさせ方についても不明な点が多いです。
本稿ではネットワークの構造と新しく増えたパラメタ、その使い方や注意点について解説しました。

具体的にどの程度の深さの棋譜がどのぐらい必要か、エントロピーの減少を見る以外に
学習の進度を見る方法があるか、学習パラメタは何を選べばいいのか、などは今後検討していかねばならない
内容であり、私自身は最終的には数の力で全部試すことになるのだろうと思っています。

ただ、各パラメタの意味を知っておくことで、同じガチャでも無駄な引きを避けられるのではと期待しています。

次回はNNUEの内部構造と改造に仕方について紹介する予定です。
コレ長編になるぞ..... orz