Bonanza6からKKPテーブルを抜き出す
Bonanza6からKKPテーブルだけを抜き出す方法について書いておきます。
Bonanza6ではKKPはmake_listのなかで行なっています。
持ち駒もKKPのPの一種と考えられ、以下のところで計算しています。
sq_bk0 = SQ_BKING; sq_wk0 = SQ_WKING; sq_bk1 = Inv(SQ_WKING); sq_wk1 = Inv(SQ_BKING); score += kkp[sq_bk0][sq_wk0][ kkp_hand_pawn + I2HandPawn(HAND_B) ]; score += kkp[sq_bk0][sq_wk0][ kkp_hand_lance + I2HandLance(HAND_B) ]; score += kkp[sq_bk0][sq_wk0][ kkp_hand_knight + I2HandKnight(HAND_B) ]; score += kkp[sq_bk0][sq_wk0][ kkp_hand_silver + I2HandSilver(HAND_B) ]; score += kkp[sq_bk0][sq_wk0][ kkp_hand_gold + I2HandGold(HAND_B) ]; score += kkp[sq_bk0][sq_wk0][ kkp_hand_bishop + I2HandBishop(HAND_B) ]; score += kkp[sq_bk0][sq_wk0][ kkp_hand_rook + I2HandRook(HAND_B) ]; score -= kkp[sq_bk1][sq_wk1][ kkp_hand_pawn + I2HandPawn(HAND_W) ]; score -= kkp[sq_bk1][sq_wk1][ kkp_hand_lance + I2HandLance(HAND_W) ]; score -= kkp[sq_bk1][sq_wk1][ kkp_hand_knight + I2HandKnight(HAND_W) ]; score -= kkp[sq_bk1][sq_wk1][ kkp_hand_silver + I2HandSilver(HAND_W) ]; score -= kkp[sq_bk1][sq_wk1][ kkp_hand_gold + I2HandGold(HAND_W) ]; score -= kkp[sq_bk1][sq_wk1][ kkp_hand_bishop + I2HandBishop(HAND_W) ]; score -= kkp[sq_bk1][sq_wk1][ kkp_hand_rook + I2HandRook(HAND_W) ];
冒頭のsq_bk1の代入式のところにSQ_WKINGとなっていて、一瞬バグかと疑いますが、これはこれで正しく、KKPでは自駒しか評価できません。
すなわち、KKPをK1K2Pと書くとしたら、PはK1側の駒でなければなりません。そこで、相手の駒(K2側の駒)を評価するときは盤面を180度回転させて(Invマクロ)、この回転させたK1,K2をK1',K2'と書くとしたらK2'K1'Pを調べて、このスコアを引き算してやる必要があります。
それで、このときにK1K2とK2'K1'だと対称に見えにくいのでK1'K2'の順番で書きたいのですが、そのためには、K1'としてInv(K2)を代入しておこうというそういうトリックです。
そのあと、それぞれの駒のKKPの値を加算していきます。
score += kkp[sq_bk0][sq_wk0][ kkp_pawn + sq ];
こういう感じですね。
ところがこうして計算したscoreは全く出鱈目で、このままですと大変弱くなります。
おかしいなーと思って、いろいろ検証してみたのですが、KPPのほうの値も拾ってくる必要があります。具体的に言いますとKPPをKP1P2と書くとして、P2 = 手駒のときのKPPの値も考慮する必要があります。
おそらく棋譜からの学習のときに、そっちにも値が散らばって学習されてしまっているのでしょう。KP1P2でP2が手駒無しのときはこの値が0になるように正規化(?)したほうがKKPの値だけ取り出すときに都合が良いのですが..
ともかくKP1P2でP2が手駒なしのときの値が0になっていないので、この分をKKPテーブルに対してオフセットをしてやる必要があると私は考えました。
そこで以下のようにfv.binの読み込み後にKKPテーブルを修正するようにしました。こうしますとひよこカルロ将棋neo1.12に対して勝率9割以上で勝ち越すようになりました(修正前はほぼ互角か負け越し)ので、そこそこ正しいであろうことがわかります。
しかし初代Bonanzaには追いついていないので、やはりこれでも正しくKKPテーブルを抽出出来ていないのではないかと思います。
このことに関して、もし何かお気づきの点がありましたら、コメント欄にて教えてください。
void Eval::setup_bona6_kkp() { // KKPのPを評価するときに手駒0に対するPになっていないと評価値がおかしいのではなかろうかという疑問 BonaPiece list0[52], list1[52]; BoardPosition sq_bk, sq_wk; Score sum = 0; Score score = 0; // tree_macroを使うためのトリック Tree tree0; Tree* tree = &tree0; HAND_B = 0; HAND_W = 0; list0[ 0] = BonaEval::f_hand_pawn + Hands::Pawn(HAND_B); list0[ 1] = BonaEval::e_hand_pawn + Hands::Pawn(HAND_W); list0[ 2] = BonaEval::f_hand_lance + Hands::Lance(HAND_B); list0[ 3] = BonaEval::e_hand_lance + Hands::Lance(HAND_W); list0[ 4] = BonaEval::f_hand_knight + Hands::Knight(HAND_B); list0[ 5] = BonaEval::e_hand_knight + Hands::Knight(HAND_W); list0[ 6] = BonaEval::f_hand_silver + Hands::Silver(HAND_B); list0[ 7] = BonaEval::e_hand_silver + Hands::Silver(HAND_W); list0[ 8] = BonaEval::f_hand_gold + Hands::Gold(HAND_B); list0[ 9] = BonaEval::e_hand_gold + Hands::Gold(HAND_W); list0[10] = BonaEval::f_hand_bishop + Hands::Bishop(HAND_B); list0[11] = BonaEval::e_hand_bishop + Hands::Bishop(HAND_W); list0[12] = BonaEval::f_hand_rook + Hands::Rook(HAND_B); list0[13] = BonaEval::e_hand_rook + Hands::Rook(HAND_W); list1[ 0] = BonaEval::f_hand_pawn + Hands::Pawn(HAND_W); list1[ 1] = BonaEval::e_hand_pawn + Hands::Pawn(HAND_B); list1[ 2] = BonaEval::f_hand_lance + Hands::Lance(HAND_W); list1[ 3] = BonaEval::e_hand_lance + Hands::Lance(HAND_B); list1[ 4] = BonaEval::f_hand_knight + Hands::Knight(HAND_W); list1[ 5] = BonaEval::e_hand_knight + Hands::Knight(HAND_B); list1[ 6] = BonaEval::f_hand_silver + Hands::Silver(HAND_W); list1[ 7] = BonaEval::e_hand_silver + Hands::Silver(HAND_B); list1[ 8] = BonaEval::f_hand_gold + Hands::Gold(HAND_W); list1[ 9] = BonaEval::e_hand_gold + Hands::Gold(HAND_B); list1[10] = BonaEval::f_hand_bishop + Hands::Bishop(HAND_W); list1[11] = BonaEval::e_hand_bishop + Hands::Bishop(HAND_B); list1[12] = BonaEval::f_hand_rook + Hands::Rook(HAND_W); list1[13] = BonaEval::e_hand_rook + Hands::Rook(HAND_B); for(sq_bk = 0;sq_bk < nsquare ; ++sq_bk) { for(sq_wk = 0;sq_wk < nsquare ; ++sq_wk) { for(BoardPosition sq = 0; sq < nsquare; ++sq) { for(int i=0;i<14;++i) { // sq > list0[i] , sq > list1[i] if (sq >= 9) { BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] += PcPcOnSq( sq_bk , BonaEval::f_pawn + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_pawn + BoardPositions::Inv(sq) , list1[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] += PcPcOnSq( sq_bk , BonaEval::f_lance + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_lance + BoardPositions::Inv(sq) , list1[i] ); } if (sq >= 18) { BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] += PcPcOnSq( sq_bk , BonaEval::f_knight + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_knight + BoardPositions::Inv(sq) , list1[i] ); } BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] += PcPcOnSq( sq_bk , BonaEval::f_silver + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_silver + BoardPositions::Inv(sq) , list1[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] += PcPcOnSq( sq_bk , BonaEval::f_gold + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_gold + BoardPositions::Inv(sq) , list1[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] += PcPcOnSq( sq_bk , BonaEval::f_bishop + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_bishop + BoardPositions::Inv(sq) , list1[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] += PcPcOnSq( sq_bk , BonaEval::f_horse + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_horse + BoardPositions::Inv(sq) , list1[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] += PcPcOnSq( sq_bk , BonaEval::f_rook + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_rook + BoardPositions::Inv(sq) , list1[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] += PcPcOnSq( sq_bk , BonaEval::f_dragon + sq , list0[i] ); BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_dragon + BoardPositions::Inv(sq) , list1[i] ); } } } } }