【連載】評価関数を作ってみよう!その8

前回の続き。今回は、駒の置かれている升に利きがある時の価値を考えてみます。

駒×味方の利き

駒のある升の味方の利き(駒が先手の駒であれば先手の利き)がある時にその価値を調べてみます。

駒に味方の利きがあれば(俗に言う「駒に紐がついている」状態)タダ取りされないので、駒の価値に比例する価値が、その利きにはあると考えられます。

そこで、加点するとして、
piece_value(駒の価値)× X / 1024
のXの部分をoptimizerに尋ねてみたのですが、この値が小さすぎるんです。1024だと計算精度が不足しているようでしたので、分母を4096にしてみました。そうすると、optimizerは X = 33 と返してきました。

駒に味方の利きがある時の価値:
piece_value × 33 / 4096

というわけです。

値小さすぎない?

歩の価値は90なので、歩の場合、90×33/4096 = 0.725です。1点にも満たない価値です。評価値の計算自体は、前回記事に書いたように32倍して計算することにしたので、評価値には乗っているでしょうけども、非常に小さい値です。

前回記事にあるように、将棋ベーシックが駒に味方の利きがあれば1点加点していたのはわりと正しくて、味方の利きがある歩に対して2点以上加点すると弱くなることがわかりました。

利きの数によって価値はどう変わる?

ある駒に味方の利きが2つある時は、さきほどより価値があるのでしょうか?
optimizerに尋ねてみると、

駒に味方の利きが2つある時の価値:
piece_value × 43 / 4096

と返ってきました。わずかですが、2つ利きがあるほうが価値が高いようです。

味方の利きの評価でどれだけ強くなる?

+R10ほど強くなりました。

駒×相手の利き

駒に相手の利きがある時、これは将棋では「質駒(しちごま)」と呼ばれ、「質(しち)に入っている」(いつでも取れる)状態を意味します。

そこで、自駒に相手の利きがある場合、大きなペナルティがあるはずで、これも駒自体の価値×係数 みたいなペナルティが発生していると考えられます。

また、相手の利きが1つの場合と2つの場合とで、それを回避しやすさが異なります。

いまは評価関数では手番を考慮していないのですが、仮に自分の手番だとして、自駒に利きをつけている相手の駒が1つであれば、その駒を取ったり、利きを遮断したりできます。ところが利きが2つですと、相手の駒を取ったり、利きを遮断したりして、1手で対象駒への利きの数を0にすることはできなくなります。

ということは、相手の利きは1つより2つのほうが大きなペナルティがあるはずです。

このペナルティの大きさをoptimizerに聞いてみました。

駒に相手の利きが1つある時のペナルティ:
piece_value × 113 / 4096

駒に相手の利きが2つ以上ある時のペナルティ:
piece_value × 122 / 4096

あまり違いはないですが、後者のほうが1割ほど多いですね。

角が質に入っている時のペナルティは1歩損の1/8

角の価値は、第一回で出てきたように855です。(歩の価値を90とする)

角が質に入っている(相手の利きが1つある)場合、上の計算式ですと
855 × 113 / 4096 ≒ 23.6
だけペナルティがあることになります。

1歩得は歩の価値の倍 = 90×2 = 180ですから、角が質に入っていると、1歩損の1/8ぐらいの損であるということです。

今回のソースコード(抜粋)

相手の利きの評価でどれほど強くなる?

+R15ほど強くなりました。

何の駒の利きであるか問題

そうは言っても、角が歩で取られそうなのと飛車で取られそうなのとは全く意味が異なります。

利きの数には、何の駒による利きなのかは区別がないので、利きをつけている駒が一緒くたになっています。

さきほどの例では、角に相手の利きがある時、その利きをつけている駒ごとにペナルティの大きさは本来異なるはずで、それを均した値が 113/4096 だということです。

しかし、いま、KKPEEテーブルは、対象升の利きの数しか見ていないので、それが何の駒による利きなのかはわかりません。よって、利きのつけている駒ごとにペナルティを調整したくとも、KKPEEテーブルではそれはできないということです。

KPPのような3駒関係ですと、近接駒(長い利きを持っていない駒)は、どの駒による利きがその駒に当たっているかはわかるので、この部分は正確に計算できていると考えられます。

ただし、KPPでは、ある駒に相手の駒が複数利いている時は、過剰にそれを評価していることになります。上の例で見たように、相手の利きが1つの場合と2つの場合は10%しかそのペナルティは違いません。2つの利きがある時、これを1つの場合の2倍のペナルティにしてしまうのは、過剰にペナルティを与えていることになります。

まあ、実戦で複数の駒が利いている局面は稀なので、そこで多少評価に誤差があっても…という意味はあります。

手番問題

相手の利きがある場合、自分の手番である場合とそうでない場合とでは話が違ってきます。

そこで、KKPEEテーブルにも手番を導入して(テーブルサイズは2倍になる)、KKPEET(TはTurn = 手番の意味)テーブルにしたほうが良いのですが、optimizerですべてのパラメーターを調整しなおす必要が出てきます。

私のほうでoptimizerで一つのパラメーターを求めるのに、AWS換算で3000円ぐらいのお金がかかっています。この連載記事、ここまでで、すでにAWS換算で20万円ほどかかっています。電竜戦の準備のためには1万円ほどしか使ってないのに、です。

そんなわけでして、KKPEETテーブルにすれば確実に強くなることはわかっているものの、本連載記事ではやりません。

ちなみに、このように無駄にお金を使い続けているやねうら王プロジェクトのための贈り物はいつでもお待ちしております。→ http://yaneuraou.yaneu.com/amazon%e3%82%a6%e3%82%a3%e3%83%83%e3%82%b7%e3%83%a5%e3%83%aa%e3%82%b9%e3%83%88/

評価関数の仕事と探索の仕事について

「次に駒が取られる」という状態を評価関数の側で頑張るのはあまり筋がよくないのです。何故なら、探索のほうで1手読めば済む話だからです。評価関数を重くして、1手先の評価が早くわかることにあまり価値はないのです。

評価関数の設計に慣れていない人は、より正確な評価を求めて、評価関数に何でもかんでも詰め込もうとして、「評価関数が2倍遅くなるけど、1手早く評価値がわかる」みたいな評価関数を作ってしまいます。

しかし、これは明らかに損なのです。探索で1手深く読むために2倍も時間がかからないので(たぶん現在の探索技術だと1手深く読むために必要な時間は1.3~1.8倍とかそんなもの)、1手読めばわかることを評価関数で正確に返すために評価関数が2倍遅くなるのは、全く割りに合わないのです。

では逆に評価関数は何をやってくれればいいかというと、ずっと先にならないとわからないような評価をして欲しいのです。例えば、囲いの堅さです。囲いが崩されるのは終盤なので、探索がいくら頑張っても序盤の局面で、終盤まで読めるわけはなく、囲いの堅さを評価するのは評価関数の仕事です。

それから、駒のpositionalな(位置の)評価です。これも、次の1手でその駒を動かすとは限らないので(最悪、そのまま何十手も動かさないこともある)、探索のほうで頑張っても不正確な価値となってしまいます。

このように評価関数は1手先の期待値を返すように努力するのではなく、探索に任せるべきところは探索に任せて、なるべく先の局面の期待値を返すように努力すべきなのです。

そういう意味からすると、例えば「角が歩で取られそう」みたいな局面は探索の側がその取り合いが終わった局面までは延長して調べてくれるでしょうから、「角が歩で取られそう」なことを対してそれをなるべく正確に評価しようと評価関数があまり頑張っても仕方ない意味はあります。

逆に「金が角で取られそう」というのは、取る側は駒損になりますから、探索でも見落とされがち(&すぐに取るとは限らない)なので、こういうのは評価関数で正しく評価したほうが良いです。(今回のKKPEEでは、これが評価できませんが。)

おい、たけわらべ、金銀が逆だぞ問題

たけわらべは、金冠によくやってしまいます。この連載で作ってきたソフトも、金冠にわりとしてしまいます。

金冠にした時の利きの価値を計算してみましょう。利きの価値は、王様からの距離に反比例するので(1つの升に複数あると少し価値が減りますが計算がややこしくなるので、それはいま考えないことにします)、以下のようになります。

・金冠の時

金の利きの価値(赤文字)に関しては、
1 + 1/2 × 2 + 1/3 × 3 = 3
です。

銀の利きの価値(緑文字)に関しては、
1/2×3 + 1/3×2 = 2 + 1/6

合計 ≒ 5.16

・銀冠の時

金の利きの価値
1 + 1/2×3 + 1/3×2 = 3 + 1/6

銀の利きの価値
1/2×2 + 1/3×3 = 2

合計 ≒ 5.16

なんと、同じなのです。

ここにさらに相手玉への脅威(相手玉に対する金と銀の利きの価値)を計算すると、金冠のほうが相手玉に近いところに利きをより多く発生させているので(金は横に利くので)、相手玉への脅威は、金冠のほうが上です。

総合すると金冠のほうが価値が高いことになってしまいます。そりゃ、たけわらべも好んで金冠にするのも無理はないですね。

これは、我々の利きの評価の仕方が何か間違っているのでしょうか?それとも何か欠けている特徴量があるのでしょうか?

金冠は何故悪形なのか?

金冠が何故悪形なのか考えてみましょう。将棋指し(有段者)ならば、金冠が悪形であることはその理由も含めて言えるはずです。

理由1) 銀に紐がついていない(王様以外の利きがない)

現状、利きの数は王様の利きも含めて計算していますが、理由1は、玉周辺の駒に関しては王様の利きを除いた数で計算する必要があることを示唆しています。

理由2) 王様の右下の升が空いているのに、ここに利きがない

右下の升には王様以外の利きがないで、終盤においてこの升から駒を放り込まれる手が常に見えています。このように玉の8近傍の升が空いていて、かつそこに王様以外の利きがない場合にはペナルティを課すべきだということを示唆しています。

他にもたくさん理由はありますが、とりあえず大きな理由はこの2つでしょう。

今回のソースコード

次回予告

次回「王様の右側にいる銀について、王様以外の利きがないからとペナルティを課したら弱くなったんですけど?」です。お楽しみに!

つづく

【連載】評価関数を作ってみよう!その8」への11件のフィードバック

  1. 評価関数の仕事と探索の仕事、とてもわかりやすい一節でした。
    金冠の考察もいい引きですね!

  2. > 相手玉への脅威は、金冠のほうが上です。
    > そりゃ、たけわらべも好んで金冠にするのも無理はないですね。

    ここで別のものを想像してしまってツボにはまったw

      • 互換性のありそうなものとして、液体○ヒとか○ナコー○とか?
        他にもアン○ルツとかℓ-メントールが含まれていそうなもの全般でw

        • ああ、虫刺されの「キンカン」ね。あれ、発売元が株式会社金冠堂なんだけど、将棋指しはあれ聞くと「なんか横から攻められたら弱そうな会社やなぁ」ぐらいの感想しか出てこない。

          • じゃああとそれと、それを右手に持って突き進むモーゼ様。
            それから、それ系の薬の容器で、先端のスポンジに含浸してる量が足りなくて肌に押し付けているけど、うまく弁が開かなくて仕方なくスポンジを指で押したら、中の薬液が一気に出てきて自分の玉付近に垂れ落ちた、というときに発生する事象もw

          • 他の記事とかツイート読んでないとわからんコメントをすると、あとからこの記事だけ読みに来た人が、わけわからんってなるのでほどほどに頼む。

  3. 金冠と銀冠が同じw
    ときどきソフトが早指し(ミリ秒単位)で
    elmo囲いの銀と金を逆にして囲うのも
    その辺りの評価に
    手が回らなかったということですかね

  4. 金冠等の上段金は斜めに動いた際に自囲いへの効きが弱くなるというのも悪形とされる理由になりそうでしょうか。
    | ・ ・v桂 ・
    | 歩 歩 ・ ・
    | ・ 金 桂 ・
    | ・ 玉 銀 ・
    こんな感じで攻められ斜めに逃げた場合、自陣への効きが減るので銀冠よりも価値が大きく下がるとも見れますかね?
    本稿の例でいえば、
    87金→76金(3-23/12=13/12)
    87銀→76銀(2-19/12=5/12)
    ただ「金が斜めに誘われた場合」を評価するのって評価関数より探索の領分じゃない?とも…

Ta(ry へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です