LoginSignup
26
27

More than 5 years have passed since last update.

Open AI gymでオセロの強化学習環境を作成してみた

Last updated at Posted at 2017-09-05

はじめに

OpenAI gymでオセロを強化学習するための環境を作ってみました。
今後、強化学習の環境を作ってみたい人向けに参考になればと思います。
学習アルゴリズムは未実装です。これから勉強してみます。
コードはこちら
https://github.com/pigooosuke/gym_reversi

gym/envsには、デフォルトで様々な学習環境が入っています。
ちなみに、ボードゲーム系では、囲碁とhexがあります。
今回は、これらのコードを参考にして作成しました。

作成手順

  1. gym/envs/ 以下にオリジナルの学習環境を作成する
  2. gym/envs/__init__.py に作成した環境をデフォルト値と一緒に登録する といった流れになります。

作成したEnvは、以下のように呼び出せるようになります。

import gym
env = gym.make('Reversi8x8-v0')

Envファイル

クラス説明

class ReversiEnv を作成しました
基本的にEnvには、5つのmethodを中心にコードを記述していく必要があります。
_step
ステップ数を1回分進める
(playerの差し手とopponentの差し手を出力し、ゲームが終わっていないかを確認)

_reset
Envの初期設定を読み込み
(ボードの読み込み、先行後攻など)

_render
EnvのStatusを図示する(画像、RGB、テキストがセットされている)
(ボードの石の状況を表示)

_close
Envの情報をすべて破棄する
(今回は未使用)

_seed
random seedによりactionを決定するのに利用
(設定)

classのinit

初期値には、
player_color: プレイヤーの石の色(黒が先)
opponent: opponentの戦略(今回はランダム)
observation_type: State encoding (不要な設定?消してもいいかも。numpy3cでstatusを管理していますという宣言。一応残している)
illegal_place_mode: ミスプレイをしたときの罰則(負けなど)
board_size: ボードのサイズ(今回は8)

を設定しています。

action

actionはEnvに対して、どの行動をとるかを決めます。
8x8のボードなので、0-63が打ち手の位置、64が投了、65がpassを設定しました。
actionの部分に強化学習の出力を導入するイメージです

done

step処理の後半にこのstepの結果、ゲームが終了しているか確認する必要があります。
- 石を置く場所がない。
- どちらかのプレイヤーの石一色になってしまった。
という条件に合致した場合、
ゲーム終了とともに、rewardを返します。

reward

評価方法は勝ち負けの1,-1を設定しています。

ゲーム終了確認

def game_finished(board):
    # Returns 1 if player 1 wins, -1 if player 2 wins and 0 otherwise
    d = board.shape[-1]

    player_score_x, player_score_y = np.where(board[0, :, :] == 1)
    player_score = len(player_score_x)
    opponent_score_x, opponent_score_y = np.where(board[1, :, :] == 1)
    opponent_score = len(opponent_score_x)
    if player_score == 0:
        return -1
    elif opponent_score == 0:
        return 1
    else:
        free_x, free_y = np.where(board[2, :, :] == 1)
        if free_x.size == 0:
            if player_score > (d**2)/2:
                return 1
            elif player_score == (d**2)/2:
                return 1
            else:
                return -1
        else:
            return 0
    return 0

失敗ネタ

最初ルールを全く設定せず、どのステータスでもactionで0-63を取れる(どこにでも石を置ける)という設定をし、ルール自体を学習させようとしましたが、開始1,2手の学習で収束してしまい上手く学習できず、actionの値に制限を付けています。

石を置ける候補を確認する

def get_enable_to_actions(board, player_color):
    actions=[]
    d = board.shape[-1]
    opponent_color = 1 - player_color
    for pos_x in range(d):
        for pos_y in range(d):
            if (board[2, pos_x, pos_y]==0):
                continue
            for dx in [-1, 0, 1]:
                for dy in [-1, 0, 1]:
                    if(dx == 0 and dy == 0):
                        continue
                    nx = pos_x + dx
                    ny = pos_y + dy
                    n = 0
                    if (nx not in range(d) or ny not in range(d)):
                        continue
                    while(board[opponent_color, nx, ny] == 1):
                        tmp_nx = nx + dx
                        tmp_ny = ny + dy
                        if (tmp_nx not in range(d) or tmp_ny not in range(d)):
                            break
                        n += 1
                        nx += dx
                        ny += dy
                    if(n > 0 and board[player_color, nx, ny] == 1):
                        actions.append(pos_x*8+pos_y)
    if len(actions)==0:
        actions = [d**2 + 1]
    return actions
26
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
27