$$ \def\bra#1{\mathinner{\left\langle{#1}\right|}} \def\ket#1{\mathinner{\left|{#1}\right\rangle}} \def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}} $$

◇◇UTTT005:教師あり学習編④:supervised_learningエージェントの作成◇◇


前回学習させたモデルを使って、supervised_learningエージェントを実装した。

ランダムエージェントと実際に試合させてみたところ、大体1/3~半分くらい勝つ印象だった。ランダムエージェントに負け越すとは相当弱いと思うかもしれないが、一概にそうとはいえない。今回はネットワークで推論した手をそのままゲームエンジンに返していたが、ゲームエンジン側では合法手以外が帰ってきた場合即座に負けになるようにしてある(当然だが)。つまり、たまに非合法手を指していた。

逆に言えば、確認した数十戦のなかではsupervised_learningエージェント側の負けはすべて非合法手を指したことによるもので、最後まで指しきった試合ではすべて勝っていた。

しかし、ネットワークの推論結果をそのまま返すのをやめて合法手の中でのmaxを返すようにしたら勝つだろうと思ってやってみたら、Randomとほとんど変わらない強さになってしまった。どうやらそう簡単な話ではないらしい。

ここで、あれ?と思った。合法手じゃないものを無理やり合法手に変えた手が弱いというのは納得できるが、もともと十数回に一回しか非合法手を指さないのに、それだけでRandom並に弱くなるものだろうか?実はこれには思い当たる節がある。棋譜を作成する際に対戦相手をRandomにしていたのは、様々な盤面の棋譜を集めたいという考えがあったからだ。MCTSエージェント同士の対戦しかしないと同じような棋譜ばかりになってしまうのではないかと思ったのだった。

ここで問題になるのは、MCTSエージェントはRandomにほとんど負けないということだ。おそらく棋譜はMCTS側の勝ち試合ばかりだろう。つまり、その棋譜で学習したエージェントは不利局面を知らないのではないだろうか?序盤や有利局面ではRandomより強くても、もともと推論の精度は高くないからRandom相手に不利になることもある。そうなったら、学習した棋譜には類似盤面がないからランダムに近い手になり、負けるのではないだろうか。非合法手が出るのはそういうときだろうから、「最後まで指しきった試合はすべて勝つ」のではなく、「勝てる試合しか最後まで指しきれない」と考えると辻褄が合う。

ランダムとばかり対戦させるのではなく、自分と同等だったり自分より強いエージェントと対局した場合の棋譜を集めることも必要になりそうだ。

                
class SupervisedLearningAgent(AgentBase):

def request_move(self, board, legal, player_num):
    normal_board = board if player_num == 1 else [[0, 2, 1][mark] for mark in board]
    board_data = convert_board(normal_board, legal)
    inputs = torch.Tensor(board_data)
    outputs = self.model(inputs)
    _, move = torch.max(outputs.data, 0)
    if move not in legal:
        print("illegal move!")
    return move

def game_end(self, board, player_num, result):
    pass

def __init__(self, model_path):
    self.model = make_network()
    self.model.load_state_dict(torch.load(model_path))
    self.model.eval()
                
            

戻る