simk_kkp

評価関数の学習を始めています。とりあえず、理解と動作確認のため
ボナンザを使って学習して、どれくらい強くなるか試しています。
オリジナルのfv.binを超えるのは無理だろうけど、R2000行きたいところ。

ボナンザを使って学習する方法のメモです。
もっといい方法があると思うけど、とりあえず動いたということで。

shogi.hの変更

まず、shogi.hに以下を追加。

#define TLP
#define NDEBUG
#define exam_bb(a) a

TLPを定義すると、学習時にマルチスレッドで並列処理できるようです。
あと、NDEBUGを定義しないと、学習時にassertに引っかかったので。
exam_bbは局面に間違いがないかチェックする関数みたいだけど、コンパイルエラーがでたので
無効にした。

学習データ

学習にはrecords.csaというcsa形式のデータが必要です。これを準備します。
ボナンザはプロ棋譜3万+将棋クラブ3万(24万局のデータは6000円くらいで売っている模様)
のデータを学習させたらしいけど、手元にないので、2chkifu.csaというもので学習させています。
江戸時代からのプロ棋譜が5万局くらい入っている。
ただし、2chkifu.csaをボナンザに入れてもうまく読み込めなかったので
以下の適当なコードで変換しました。

2chkifu.csaは1局が1行・差手が6文字ずつならんでいるので、それを切り出して
recoards.csaに保存する。このコードではとりあえず、4万局切り出します。

#include <stdio.h>
#include <stdlib.h>

void main()
{
	FILE *fp   = fopen("./2chkifu.csa", "r");

	if(fp)
	{
		FILE *fp_o = fopen("./records.csa", "w");
		char buf[10000];
		char pm[] = {'+','-'};
		int i, n, l, p;
		for(i = 0;i < 40000;i++)
		{
			fgets(buf, 10000, fp);
			fgets(buf, 10000, fp);
			l = strlen(buf) - 6;
			if(i>0)
			fprintf(fp_o, "/\n");
			fprintf(fp_o, "PI\n+\n");
			p = 0;
			for(n = 0;n < l;n += 6)
			{
				fprintf(fp_o, "%c%c%c%c%c%c%c\n", pm[p], buf[n + 0], buf[n + 1], buf[n + 2], buf[n + 3], buf[n + 4], buf[n + 5]);
				p = 1 - p;
			}
			fprintf(fp_o, "%%TORYO\n");
		}
		fclose(fp);
		fclose(fp_o);
	}
}

ボナンザのコンパイル&実行

gcc+linux環境では以下のようにしたら動きました。

>gcc *.c -c -O3
>rm learn1.o
>gcc learn1.c *.o -O3 -lm -lpthread
>./a.out

ボナンザのコマンドラインが立ち上がるので、6コアマシンの場合は

>learn ini 32 -1 -1 6 6

とすれば6並列で学習が始ります。
iniを指定すればfv.binがゼロの状態から始まります。
no-iniにすれば、前回のfv.binから続きを学習。
4万局だと1回のイタレーションで1日かかります。

結果

これで、一応、矢倉ぽく組むようになりました。
あと、1万局より4万局で学習させた方が強くなった気がします。
floodgateにsimk_kpp_100で流していますが、当然ながら
オリジナルfv.binを使ったバージョン(simk)よりもかなり弱いです。

プロの棋譜だけではなく、将棋クラブの棋譜も学習に入れた方がよいのかもしれません。