使用方法について - 詳細版 -

このセクションでは, ReNomRL を使用する前の事前知識としていくつか紹介する.

1- 引数 env の構造

env 変数について, もし size-2 の list( or tuple) が指定された場合, 環境を [training_env, test_env] の環境として認識する. A2C のようなマルチエージェントを要する学習モデルの場合は, training_env も list( or tuple) として適用することができるが, num_worker の数と一致しなければならない. 各々のオブジェクトは BaseEnv を継承しなければならい. もし, env BaseEnv を継承したオブジェクトの場合, num_worker に応じて deepcopy する. env で指定した環境は test_env になる.

Good Examples:

from renom_rl.discrete.a2c import A2C

custom_env = CartPole00()
test_custom_env = CartPole00()
custom_env_list = [CartPole00() for _ in range(8)]

_ = A2C(custom_env, q_network)

_ = A2C([custom_env, test_custom_env], q_network, num_worker=8)

_ = A2C([custom_env_list, test_custom_env], q_network, num_worker=8)

Bad Examples:

custom_env_list = [CartPole00() for _ in range(8)]

_ = A2C([custom_env_list, test_custom_env], q_network, num_worker=9)

2- ネットワーク 構造

各学習モデルに応じてネットワーク構造は異なる. 例えば, A2C の場合, actor, critic を出力とする構造を取らなければならない. 構造については各々の学習モデルのドキュメントを参照してください.

Example:

#For DQN
class DQN_Model(rm.Model):

    def __init__(self, a=2):
        self.d1 = rm.Dense(30)
        self.r1 = rm.Relu()
        self.d2 = rm.Dense(a)
        self.act = rm.Softmax()

    def forward(self, x):
        h = self.d1(x)
        h = self.r1(h)
        h = self.d2(h)
        act = self.act(h)

        return act

#For A2C
class A2C_Discrete(rm.Model):
    def __init__(self, m=2, v=1):
        self.d1 = rm.Dense(200)
        self.r1 = rm.Relu()
        self.d2 = rm.Dense(m)
        self.act = rm.Softmax()
        self.val = rm.Dense(v)

    def forward(self, x):
        h = self.d1(x)
        h = self.r1(h)
        h = self.d2(h)
        act = self.act(h)
        val = self.val(h)

        return act, val

3- ネットワークの初期化

initialize が False に設定されていない限り, init と fit 時に初期化は実行される.

初期化を阻止したい場合は, initialize を False にしてください.

Example:

from renom_rl.discrete.dqn import DQN

algorithm = DQN(custom_env, q_network, initialize = False)

4- ロガー

renom_rl.utility.logger を使用することで, データのロギングができる. 詳細についてはこちらの renom_rl.utility.logger.Logger を参照してください.

class Original(Logger):

    def __init__(self,log_key):
        super(Original,self).__init__(log_key,record_episode_base=False)
        self.reward_previous = 0
        self.reward = 0
        self.total_list = []
        self.state = 0
        self.total = 0

    def logger(self,**log):
        self.state = log["state"]
        self.reward = log["reward"]
        self.total += log["reward"]
        return "state----{}/reward---{}/total----{}".format(self.state, self.reward, self.total)


import renom as rm
from renom_rl.environ.openai import CartPole00
from renom_rl.discrete.dqn import DQN

network = rm.Sequential([rm.Dense(32),rm.Relu(),rm.Dense(32),rm.Relu(),rm.Dense(2)])

logger = Original(["reward"])

dqn=DQN(env=CartPole00(),q_network=network,logger=logger)

#result
# state----[-0.00528582  0.76312646 -0.00763515 -1.1157825 ]/reward---0/total-----39: 100%|██████████████████████████████████████| 500/500 [00:01<00:00, 438.39it/s]

5- Init と Fit の引数

__init__ fit は多くの引数が同じである. __init__ のみに依存する引数は, 環境, ネットワーク, ロガーに関する引数である. 強化学習を実施する上で最低限必要なオブジェクトだと我々は考えている.

../_images/02-image_of_rl.png

fit のみに依存する引数は, 学習時間(長さ)に依存する引数であり, 主に epoch, epoch_step 等である.

共通した引数については, 学習(fit)時に指定した値を優先的に使用する. 下図は学習時にどの引数が使用されるかの図を示す.

../_images/02-fit_value_ref.png

テスト時も上記と同様である.

Example:

# loss: use Default Value, gamma: specified at init, ActionFilter: Changed at fit
from renom_rl.utility.filter import EpsilonCFilter
dqn=DQN(custom_env, q_network, gamma=0.99)

print("---before---")
info=dqn.info_init()
print("loss(id):",id(info["loss_func"]),\
      "\ngamma(id):",info["gamma"],\
      "\nActionFilter(id):",id(info["action_filter"]))
print()
dqn.fit(random_step=0,epoch=1,epoch_step=10,action_filter=EpsilonCFilter(epsilon=0.1))
print()
print("---after---")
info=dqn.info_fit()
print("loss(id):",id(info["loss_func"]),\
      "\ngamma(id):",info["gamma"],\
      "\nActionFilter(id):",id(info["action_filter"]))

### The result will show as follows:
###
###    ---before---
###    loss(id): 112130625152
###    gamma(id): 0.99
###    ActionFilter(id): 112130625040
###
###    Run random 0 step for storing experiences
###
###    ---after---
###    loss(id): 112130625152
###    gamma(id): 0.99
###    ActionFilter(id): 112130625264

6- フィルタ

Filter は環境に対して行動を入力するときにネットワークから出力した値を処理するオブジェクトである. Filter には様々なオブジェクトがあり, 学習モデルに応じて, 使用できる・できないものがある.

下図では どのような Filter オブジェクトがどこで処理しているかを示す.

../_images/05-filter.png

DQN では node_selector , action_filter の引数がある. DQN の node_selector では, renom_rl.utility.DiscreteNodeChooser のオブジェクトを, action_filter では, renom_rl.utility.EpsilonGreedyFilter のオブジェクトを指定することができる. node_selector MaxNodeChooser() , action_filter EpsilonSLFilter() がデフォルトとして設定されている. node_selector では ProbNodeChooser() を指定することができる(ただし, ProbNodeChooser() は 0~1の値を基準に選定する). action_filter についても同クラスであれば, 同様に変えることができる.

他の学習モデルについても同様にフィルタをしている. 詳細については各学習モデルのドキュメントを参照していください.

7- BaseEnv 関数

start() ~ close() 関数

renom_rl.environ.env.BaseEnv では start() ~ close() 関数がある.

これらの関数は training 時と test 時に実行し, 下図のタイミングで実行される.

../_images/03-env_start_close.png

terminate() ~ stop_epoch() 関数

renom_rl.environ.env.BaseEnv では terminate() , terminate_epoch() , stop_epoch() 関数がある.

これらの関数は training と testing を停止する関数である. 各々の関数は下記の処理を停止する.

../_images/04-terminate.png

注意: stop_epoch() (または teminate_epoch() ) は各エポックごとに実行される. そのため, 各エポックの初期時に False を返すような処理をしない限り, 各エポックは常時停止する. 各エポックの初期時に stop_epoch() (または teminate_epoch() ) が False を返すようにしてください.

詳細については, renom_rl.environ.env.BaseEnv を参照してください.

Example:

class CartPole(CartPole00):
    def __init__(self):
        self.i = 0
        self.t = 0

        CartPole00.__init__(self)

    # overriding start, epoch, epoch_step, test_epoch_step, terminal_epoch
    def start(self):
        self.i = 0
        self.t = 0

    def epoch(self):
        self.i=0

    def epoch_step(self):
        self.i +=1

    def test_epoch_step(self):
        """if not overridden, epoch_step will run"""
        pass

    def terminate_epoch(self):
        if not self.i < 5:
            self.t += 1
        return False if self.i < 5 else True

    def result(self):
        print("epoch_step counts: ",self.i)
        print("terminate counts: ",self.t)

env=CartPole()

dqn=DQN(env,model)
dqn.fit(random_step=0, epoch=2, epoch_step=1000)
env.result()


## Results:
## epoch_step counts:  5
## terminate counts: 2