TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

書籍のpython-dlshogi2のバグについて

書籍「強い将棋ソフトの創りかた」の第5章のpython-dlshogi2に精度に影響のあるバグがあったので報告します。

誤り箇所

p.109 リスト5.2のfeatures.pyのmake_move_labelの移動方向を判定する処理は、以下のように定義されています。
python-dlshogi2/features.py at 4a1b227d8dfdd32cc2a77f151341dacfc904776b · TadaoYamaoka/python-dlshogi2 · GitHub

        # 移動方向
        to_y, to_x = divmod(to_sq, 9)
        from_y, from_x = divmod(from_sq, 9)
        dir_x = to_x - from_x
        dir_y = to_y - from_y
        if dir_y < 0:
            if dir_x == 0:
                move_direction = UP
            elif dir_x < 0:
                move_direction = UP_LEFT
            else:  # dir_x > 0
                move_direction = UP_RIGHT
        elif dir_y == 0:
            if dir_x < 0:
                move_direction = LEFT
            else:  # dir_x > 0
                move_direction = RIGHT
        elif dir_y > 0:
            if dir_x == 0:
                move_direction = DOWN
            elif dir_x < 0:
                move_direction = DOWN_LEFT
            else:  # dir_x > 0
                move_direction = DOWN_RIGHT
        else:  # dir_y == -2
            if dir_x == -1:
                move_direction = UP2_LEFT
            else:  # dir_x == 1
                move_direction = UP2_RIGHT

正しい内容

座標系の扱いの誤り

to_sqと、from_sqは、図5.13で説明しているように1一を0、1九を8、9九を80とする縦方向に採番した数値になっているため、divmodの結果を格納している変数のto_xとto_ yおよびfrom_xとfrom_yは、それぞれ逆になり、

        to_x, to_y = divmod(to_sq, 9)
        from_x, from_y = divmod(from_sq, 9)

とするのが正しいです。
前著は将棋ライブラリにpython-shogiを使用していたため、そのコードを流用していたため誤っていました。

LEFTとRIGHTが逆

x < 0のときにLEFTとしていましたが、将棋盤の右上から採番しているため、RIGHTが正しいです。

桂馬の動きが判定されない

最後のelseは、上にy < 0があるため通らない処理になっていました。
また、x, yが逆になっているため、elseの問題がなくても、桂馬の動きが判定されてないようになっていました。

修正後コード

以上を修正した後のコードは以下のようになります。

make_move_labelの移動方向を判定する処理
        # 移動方向
        to_x, to_y = divmod(to_sq, 9)
        from_x, from_y = divmod(from_sq, 9)
        dir_x = to_x - from_x
        dir_y = to_y - from_y
        if dir_y < 0:
            if dir_x == 0:
                move_direction = UP
            elif dir_y == -2 and dir_x == -1:
                move_direction = UP2_RIGHT
            elif dir_y == -2 and dir_x == 1:
                move_direction = UP2_LEFT
            elif dir_x < 0:
                move_direction = UP_RIGHT
            else:  # dir_x > 0
                move_direction = UP_LEFT
        elif dir_y == 0:
            if dir_x < 0:
                move_direction = RIGHT
            else:  # dir_x > 0
                move_direction = LEFT
        else:  # dir_y > 0
            if dir_x == 0:
                move_direction = DOWN
            elif dir_x < 0:
                move_direction = DOWN_RIGHT
            else:  # dir_x > 0
                move_direction = DOWN_LEFT

なお、この修正で、出力ラベルはdlshogiライブラリと完全一致するようになります。

学習済みチェックポイントへの影響

修正を行うと、以前のコードで学習したチェックポイントと互換性がなくなります。
一から再学習が必要です。
桂馬の動きが正しく学習できるようになるため、学習し直すと以前よりも強くなるはずです。

正誤表

非公式の正誤表に掲載しました。
正誤表 · TadaoYamaoka/ShogiAIBook2 Wiki · GitHub

出版社の公式のサポートページには後日掲載してもらいます。

GitHubのコードとチェックポイントの修正

チェックポイントを再学習してから、コードとチェックポイントの更新を行う予定です。
第7章のデータを使ったチェックポイント(checkpoint.pth)の再学習に時間がかかるため、明日になる予定です。
更新が完了したら、この記事に追記します。

お詫び

書籍を購入して、すでにpython-dlshogi2でモデルの学習を試された方は、申し訳ありません。

なお、この修正は、第7章、8章のdlshogiライブラリを使用した学習には影響はありません。
影響範囲は、第5章のpython-dlshogi2で学習したチェックポイントのみになります。