ホーム » 強化学習

強化学習」カテゴリーアーカイブ

Acme : サンプル : チュートリアル

Acme : サンプル : チュートリアル (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/15/2020

* 本ページは、Acme の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

サンプル : チュートリアル

この colab は強化学習エージェントを作成するために Acme のモジュールがどのように一緒にスタックされるかの概要を提供します。それはどのようにネットワークを環境仕様に適合させるか、アクター、leaner、再生バッファ、データセット、adder そして完全なエージェントをどのように作成するかを示します。それはまた貴方自身の Acme ベースのエージェントを作成するためにどこで、あるモジュールをスワップアウトできるかも明らかにします。

 

インストール

最初の 2, 3 セルで総ての必要な依存性 (そして 2, 3 のオプションのもの) をインストールすることから始めます。

#@title Install necessary dependencies.

!sudo apt-get install -y xvfb ffmpeg
!pip install 'gym==0.10.11'
!pip install imageio
!pip install PILLOW
!pip install 'pyglet==1.3.2'
!pip install pyvirtualdisplay

!pip install dm-acme
!pip install dm-acme[reverb]
!pip install dm-acme[tf]
!pip install dm-acme[envs]

from IPython.display import clear_output
clear_output()

 

dm_control をインストールする

次のセルは貴方が institutional MuJoCo ライセンスを持つ場合 dm_control により提供される環境をインストールします。これは必要ではありませんが、これなしでは下の dm_cartpole 環境を利用することができません、そして代わりに gym 環境を利用してこの colab に従うことができます。それを行なうには次のセルを単純に展開し、貴方のライセンスファイルを貼り付けて、そしてセルを実行します。

代わりに、Colab は貴方のローカルマシン上の Jupyter カーネルの使用もサポートします、これはここのガイドラインに従うことにより成されます : https://research.google.com/colaboratory/local-runtimes.html 。これは https://github.com/deepmind/dm_control の手順に従い personal MuJoCo ライセンスを使用することにより dm_control をインストールすることを可能にします。

#@title Add your License
#@test {"skip": true}
mjkey = """
""".strip()

mujoco_dir = "$HOME/.mujoco"

# Install OpenGL dependencies
!apt-get update && apt-get install -y --no-install-recommends \
  libgl1-mesa-glx libosmesa6 libglew2.0

# Get MuJoCo binaries
!wget -q https://www.roboti.us/download/mujoco200_linux.zip -O mujoco.zip
!unzip -o -q mujoco.zip -d "$mujoco_dir"

# Copy over MuJoCo license
!echo "$mjkey" > "$mujoco_dir/mjkey.txt"

# Install dm_control
!pip install dm_control

# Configure dm_control to use the OSMesa rendering backend
%env MUJOCO_GL=osmesa

# Check that the installation succeeded
try:
  from dm_control import suite
  env = suite.load('cartpole', 'swingup')
  pixels = env.physics.render()
except Exception as e:
  raise e from RuntimeError(
      'Something went wrong during installation. Check the shell output above '
      'for more information.')
else:
  from IPython.display import clear_output
  clear_output()
  del suite, env, pixels

 

モジュールをインポートする

今は総ての関連モジュールをインポートできます。

#@title Import modules.
#python3

%%capture
import copy
import pyvirtualdisplay
import imageio 
import base64
import IPython


from acme import environment_loop
from acme.tf import networks
from acme.adders import reverb as adders
from acme.agents.tf import actors as actors
from acme.datasets import reverb as datasets
from acme.wrappers import gym_wrapper
from acme import specs
from acme import wrappers
from acme.agents.tf import d4pg
from acme.agents import agent
from acme.tf import utils as tf2_utils
from acme.utils import loggers

import gym 
import dm_env
import matplotlib.pyplot as plt
import numpy as np
import reverb
import sonnet as snt
import tensorflow as tf

# Import dm_control if it exists.
try:
  from dm_control import suite
except (ModuleNotFoundError, OSError):
  pass

# Set up a virtual display for rendering OpenAI gym environments.
display = pyvirtualdisplay.Display(visible=0, size=(1400, 900)).start()

 

環境をロードする

今は環境をロードできます。以後、環境から単一状態を生成して可視化するために環境を作成します。利用したい環境を単に選択してセルを実行します。

environment_name = 'dm_cartpole'  # @param ['dm_cartpole', 'gym_mountaincar']
# task_name = 'balance'  # @param ['swingup', 'balance']

def make_environment(domain_name='cartpole', task='balance'):
  env = suite.load(domain_name, task)
  env = wrappers.SinglePrecisionWrapper(env)
  return env

if 'dm_cartpole' in environment_name:
  environment = make_environment('cartpole')
  def render(env):
    return env._physics.render(camera_id=0)  #pylint: disable=protected-access

elif 'gym_mountaincar' in environment_name:
  environment = gym_wrapper.GymWrapper(gym.make('MountainCarContinuous-v0'))
  environment = wrappers.SinglePrecisionWrapper(environment)
  def render(env):
    return env.environment.render(mode='rgb_array')
else:
  raise ValueError('Unknown environment: {}.'.format(environment_name))

# Show the frame.
frame = render(environment)
plt.imshow(frame)
plt.axis('off')

 

環境仕様 (= Spec)

後で次の図に対応するループで環境と相互作用します :

しかしこの環境と相互作用するエージェントの構築を始める前に、最初に環境が返す (e.g. 観測) あるいは消費する (e.g. アクション) オブジェクトのタイプを見ましょう。environment_spec は環境が公開する観測、報酬と割引きの形式と取られるアクションの形式を貴方に示します、

environment_spec = specs.make_environment_spec(environment)

print('actions:\n', environment_spec.actions, '\n')
print('observations:\n', environment_spec.observations, '\n')
print('rewards:\n', environment_spec.rewards, '\n')
print('discounts:\n', environment_spec.discounts, '\n')

 

観測をアクションにマップするポリシー・ネットワークを構築する

潜在的に強化学習アルゴリズムの最も重要なパートは環境観測をアクションにマップするポリシーです。ポリシーを作成するために単純なニューラルネットワークを利用できます、この場合には層 norm を持つ単純な順伝播 MLP です。私達の TensorFlow エージェントについてはネットワークやもジュールを指定するために sonnet ライブラリを利用します ; それとともに作業するネットワークの総ては初期バッチ次元を持ちます、これはバッチ化された推論/学習を可能にします。

環境から返される観測は何らかの方法でネストされることが可能です : e.g. dm_control スーツからの環境はしばしば位置と速度エントリを含む辞書として返されます。私達のネットワークはこの辞書をアクションを生成するために恣意的にマップすることが許されます、しかしこの場合それを MLP を通して供給する前にこれらの観測を単純に結合します。ネストされた観測を各バッチのための単一次元に平坦化する Acme の batch_concat ユティリティを使用してそれを行なうことができます。観測が既にフラットであるならばこれは no-op となるでしょう。

同様に、MLP の出力はアクション spec が規定するものとは異なる値の範囲を持つかもしれません。このためには、アクションを spec に適合するように再スケールするため Acme の TanhToSpec を利用できます。

# Calculate how big the last layer should be based on total # of actions.
action_spec = environment_spec.actions
action_size = np.prod(action_spec.shape, dtype=int)
exploration_sigma = 0.3

# In order the following modules:
# 1. Flatten the observations to be [B, ...] where B is the batch dimension.
# 2. Define a simple MLP which is the guts of this policy.
# 3. Make sure the output action matches the spec of the actions.
policy_modules = [
    tf2_utils.batch_concat,
    networks.LayerNormMLP(layer_sizes=(300, 200, action_size)),
    networks.TanhToSpec(spec=environment_spec.actions)]

policy_network = snt.Sequential(policy_modules)

# We will also create a version of this policy that uses exploratory noise.
behavior_network = snt.Sequential(
    policy_modules + [networks.ClippedGaussian(exploration_sigma),
                      networks.ClipToSpec(action_spec)])

 

アクターを作成する

アクターは私達のフレームワークの一部でアクションを生成することにより環境と直接相互作用します。より詳細には先の図はこの相互作用がどのように起きるかを正確に示すために展開できます :

貴方自身のアクターを常に書ける一方で、Acme では幾つかの有用な事前作成されたバージョンも提供します。上で指定したネットワークについては FeedForwardActor を利用します、これは 単一の順伝播ネットワークをラップしてそして任意のバッチ次元を処理したり観測された遷移を記録するようなことをどのように行なうかを知っています。

actor = actors.FeedForwardActor(policy_network)

総てのアクターは次の公開メソッドと属性を持ちます :

[method_or_attr for method_or_attr in dir(actor)  # pylint: disable=expression-not-assigned
 if not method_or_attr.startswith('_')]

 

ランダムアクターのポリシーを評価する

ポリシーを持つアクターをインスタンス化しましたが、ポリシーはどのようなタスク報酬を獲得することもまだ学習していませんので、本質的には単にランダムに動作するだけです。けれどもこれはアクターと環境がどのように相互作用するかを見るために完全な機会です。下でフレームが与えられたときに動画を表示する単純なヘルパー関数を定義します、そして世界でアクションを取るアクターの 500 ステップを示します。

def display_video(frames, filename='temp.mp4'):
  """Save and display video."""
  # Write video
  with imageio.get_writer(filename, fps=60) as video:
    for frame in frames:
      video.append_data(frame)
  # Read video and display the video
  video = open(filename, 'rb').read()
  b64_video = base64.b64encode(video)
  video_tag = ('
# Run the actor in the environment for desired number of steps.
frames = []
num_steps = 500
timestep = environment.reset()

for _ in range(num_steps):
  frames.append(render(environment))
  action = actor.select_action(timestep.observation)
  timestep = environment.step(action)

# Save video of the behaviour.
display_video(np.array(frames))

 

再生バッファにアクター経験をストアする

多くの RL エージェントはアクターにより取られたアクションと一緒に環境からのデータ (e.g. 観測) をストアするために再生バッファのようなデータ構造を利用します。このデータはポリシーを更新するために後で学習プロセスに供給されます。このステップを含むために再度前の図を展開することができます :

これを可能にするため、Acme は Reverb を活用します、これは機械学習研究のために設計された効率的で利用が容易なデータストレージと輸送系です。下でそれと相互作用する前に再生バッファを作成します。

# Create a table with the following attributes:
# 1. when replay is full we remove the oldest entries first.
# 2. to sample from replay we will do so uniformly at random.
# 3. before allowing sampling to proceed we make sure there is at least
#    one sample in the replay table.
# 4. we use a default table name so we don't have to repeat it many times below;
#    if we left this off we'd need to feed it into adders/actors/etc. below.
replay_buffer = reverb.Table(
    name=adders.DEFAULT_PRIORITY_TABLE,
    max_size=1000000,
    remover=reverb.selectors.Fifo(),
    sampler=reverb.selectors.Uniform(),
    rate_limiter=reverb.rate_limiters.MinSize(min_size_to_sample=1))

# Get the server and address so we can give it to the modules such as our actor
# that will interact with the replay buffer.
replay_server = reverb.Server([replay_buffer], port=None)
replay_server_address = 'localhost:%d' % replay_server.port

データを再生 (バッファ) に追加するために Reverb と直接相互作用できるでしょう。けれども Acme ではこのデータストレージの上に追加の層を持ちます、これは挿入しているデータがどのような種類であろうとも同じインターフェイスを使用することを可能にします。

Acme のこの層は経験をデータテーブルに追加する Adder に相当します。私達はテーブルにストアされることが望まれる情報のタイプに基づいて異なる幾つかの adder を提供します、けれどもこの場合 NStepTransitionAdder を利用します、これは単純な遷移をストアするか (if N=1) 塊状の遷移を形成する N-ステップを蓄積します。

# Create a 5-step transition adder where in between those steps a discount of
# 0.99 is used (which should be the same discount used for learning).
adder = adders.NStepTransitionAdder(
    client=reverb.Client(replay_server_address),
    n_step=5,
    discount=0.99)

以下のように add() と add_first() メソッドを使用して遷移を再生バッファに直接追加するために adder を直接利用することもできます :

num_episodes = 2  #@param

for episode in range(num_episodes):
  timestep = environment.reset()
  adder.add_first(timestep)

  while not timestep.last():
    action = actor.select_action(timestep.observation)
    timestep = environment.step(action)
    adder.add(action=action, next_timestep=timestep)

これはデータを観測するために共通の十分な方法ですので、Acme のアクターは一般的に Adder インスタンスを取ります、これは observation メソッドを定義するために利用します。先に総てのアクターのように FeedForwardActor が observe と observe_first メソッドを定義することを見ました。アクターに Adder インスタンスを初期化時に与えれば、それは観測を作成するためにこの adder を利用します。

actor = actors.FeedForwardActor(policy_network=behavior_network, adder=adder)

下で同じプロセスを繰り返しますが、アクターとその observe メソッドを利用します。下でこられの微妙な変更に注意します。

num_episodes = 2  #@param

for episode in range(num_episodes):
  timestep = environment.reset()
  actor.observe_first(timestep)  # Note: observe_first.

  while not timestep.last():
    action = actor.select_action(timestep.observation)
    timestep = environment.step(action)
    actor.observe(action=action, next_timestep=timestep)  # Note: observe.

 

再生バッファの経験から学習する

Acme は複数の学習アルゴリズム/エージェントを提供します。ここではアクターにより収集されたデータから学習するために D4PG 学習アルゴリズムを使用します。そのため、make_dataset 関数を使用して Reverb テーブルから TensorFlow データセットを最初に作成します。

# This connects to the created reverb server; also note that we use a transition
# adder above so we'll tell the dataset function that so that it knows the type
# of data that's coming out.
dataset = datasets.make_dataset(
    client=reverb.TFClient(server_address=replay_server_address),
    batch_size=256,
    environment_spec=environment_spec,
    transition_adder=True)

以後、D4PG を利用します、actor-critic 学習アルゴリズムです。D4PG は幾分複雑なアルゴリズムですので、このメソッドの完全な説明は添付のペーパーに委ねます (ドキュメント参照)。

けれども、D4PG は actor-critic アルゴリズムですので、そのために critic (値関数) を指定しなければなりません。この場合 D4PG は更に分布 critic も使用します。D4PG はまたオンラインとターゲットネットワークも利用しますので、(前からの) policy_network と作成しようとしている新しい critic ネットワークの両者のコピーを作成する必要があります。

critic ネットワークを構築するため、multiplexer を利用します、これは単純にニューラルネットワーク・モジュールで複数の入力を取りそれらを結合して更に処理する前にそれらを異なる方法で処理します。Acme の CriticMultiplexer の場合、入力は観測とアクションで、それぞれ自身のネットワーク・トルソーを伴います。それから critic ネットワーク・もジュールがあります、これは観測ネットワークとアクションネットワークの出力を処理して tensor を出力します。

最後に、これらのネットワークを最適化するために learner は作成された変数を持つネットワークを受け取らなければなりません。Acme でこれを正確に扱うユティリティを持ちます、そして次のコードブロックの最後の行でそれを行ないます。

critic_network = snt.Sequential([
    networks.CriticMultiplexer(
        observation_network=tf2_utils.batch_concat,
        action_network=tf.identity,
        critic_network=networks.LayerNormMLP(
            layer_sizes=(400, 300),
            activate_final=True)),
    # Value-head gives a 51-atomed delta distribution over state-action values.
    networks.DiscreteValuedHead(vmin=-150., vmax=150., num_atoms=51)])

# Create the target networks
target_policy_network = copy.deepcopy(policy_network)
target_critic_network = copy.deepcopy(critic_network)

# We must create the variables in the networks before passing them to learner.
tf2_utils.create_variables(network=policy_network,
                           input_spec=[environment_spec.observations])
tf2_utils.create_variables(network=critic_network,
                           input_spec=[environment_spec.observations,
                                       environment_spec.actions])
tf2_utils.create_variables(network=target_policy_network,
                           input_spec=[environment_spec.observations])
tf2_utils.create_variables(network=target_critic_network,
                           input_spec=[environment_spec.observations,
                                       environment_spec.actions])

今はこれらのネットワークを使用する learner を作成できます。ここでは遷移 adder で使用されたのと同じ割引き因子を使用していることに注意してください。残りのパラメータは合理的なデフォルトです。

けれども通常の間隔で出力を端末にロギングしていることに注意してください。ネットワーク重みのチェックポイント (i.e. それらのセーブ) も無効にしています。これはデフォルトでは通常は使用されますが、対話的な colab セッションでは問題を引き起こす可能性がありおます。

learner = d4pg.D4PGLearner(policy_network=policy_network,
                           critic_network=critic_network,
                           target_policy_network=target_policy_network,
                           target_critic_network=target_critic_network,
                           dataset=dataset,
                           discount=0.99,
                           target_update_period=100,
                           policy_optimizer=snt.optimizers.Adam(1e-4),
                           critic_optimizer=snt.optimizers.Adam(1e-4),
                           # Log learner updates to console every 10 seconds.
                           logger=loggers.TerminalLogger(time_delta=10.),
                           checkpoint=False)

learner の公開メソッドを調べるとそれは主として変数を公開してそれらを更新するために存在することを見ます。つまりこれは教師あり学習に非常に類似しています。

[method_or_attr for method_or_attr in dir(learner)  # pylint: disable=expression-not-assigned
 if not method_or_attr.startswith('_')]

learner の step() メソッドはそれに与えられた再生データセットからデータのバッチをサンプリングして、そして optimizer を使用し、そこまでの損失メトリクスをログ記録しながら最適化を遂行します。Note: 再生データセットからサンプリングするためには、再生バッファに少なくとも 1000 要素がなければなりません (それはアクターの追加された経験から既に持つはずです)。

learner.step()

 

訓練ループ

最後に、ピースの総てをひとつにまとめて環境で幾つかの訓練ステップを実行できます、アクターの経験収集と learner の学習を交互に行ないます。

これは num_training_episodes エピソードの間実行する単純な訓練ループです、そこではアクターと learner は交代でそれぞれ (経験を) 生成して経験から学習します :

  • アクターは環境で動作し & min_actor_steps_per_iteration ステップの間経験を再生に追加します。
  • learner は再生データからサンプリングしてそれから num_learner_steps_per_iteration ステップの間学習します。

Note: learner とアクターはポリシーネットワークを共有しますので、learner 上で成された任意の学習は、自動的にアクターのポリシーに転送されます。

num_training_episodes =  10 # @param {type: "integer"}
min_actor_steps_before_learning = 1000  # @param {type: "integer"}
num_actor_steps_per_iteration =   100 # @param {type: "integer"}
num_learner_steps_per_iteration = 1  # @param {type: "integer"}

learner_steps_taken = 0
actor_steps_taken = 0
for episode in range(num_training_episodes):
  
  timestep = environment.reset()
  actor.observe_first(timestep)
  episode_return = 0

  while not timestep.last():
    # Get an action from the agent and step in the environment.
    action = actor.select_action(timestep.observation)
    next_timestep = environment.step(action)

    # Record the transition.
    actor.observe(action=action, next_timestep=next_timestep)

    # Book-keeping.
    episode_return += next_timestep.reward
    actor_steps_taken += 1
    timestep = next_timestep

    # See if we have some learning to do.
    if (actor_steps_taken >= min_actor_steps_before_learning and
        actor_steps_taken % num_actor_steps_per_iteration == 0):
      # Learn.
      for learner_step in range(num_learner_steps_per_iteration):
        learner.step()
      learner_steps_taken += num_learner_steps_per_iteration

  # Log quantities.
  print('Episode: %d | Return: %f | Learner steps: %d | Actor steps: %d'%(
      episode, episode_return, learner_steps_taken, actor_steps_taken))

 

ひとつにまとめる: Acme エージェント

ピースの総てを使用してそれらがどのように相互作用できるかを見た今、それらを一つにまとめられるもう一つの方法があります。Acme 設計スキームでは、エージェントは learner とアクター・コンポーネントの両者を持つ実在で、それらの相互作用を内部的にまとめます。エージェントは経験を再生バッファに追加するアクターと、それからサンプリングして学習し、交代で、重みをアクターと共有し戻す leaner の間のやり取りを処理します。

上のカスタム訓練ループで num_actor_steps_per_iteration と num_learner_steps_per_iteration パラメータをどのように使用したかに類似して、エージェント・パラメータ min_observations と observations_per_step はエージェントの訓練ループの構造を指定します。

  • min_observations は学習を開始するために幾つのアクター・ステップが起きる必要があるかを指定します。
  • observations_per_step は各 learner ステップの間内に幾つのアクター・ステップが発生するかを指定します。
d4pg_agent = agent.Agent(actor=actor,
                         learner=learner,
                         min_observations=1000,
                         observations_per_step=8.)

もちろん agents.D4PG エージェントを単に直接使用することもできました、これはこの総てを私達のために設定します。ちょうど作成したこのエージェントで続けますが、このチュートリアルで概説されるスキップの殆どは単に事前構築されたエージェントと環境ループを利用することによりスキップできます。

 

完全な (= full) エージェントを訓練する

経験を収集してストアすることを単純化するため、Acme の EnvironmentLoop を直接使用することもできます、これは指定された数のエピソードのために環境ループを実行します。各エピソードはそれ自身がループで、観測を得てからその観測を (アクションを取得するため) エージェントに与えるように環境と最初に相互作用します。エピソードの終了時、新しいエピソードが開始されます。エピソードの数が与えられない場合にはこれは環境と無限に相互作用します。

# This may be necessary if any of the episodes were cancelled above.
adder.reset()

# We also want to make sure the logger doesn't write to disk because that can
# cause issues in colab on occasion.
logger = loggers.TerminalLogger(time_delta=10.)
loop = environment_loop.EnvironmentLoop(environment, d4pg_agent, logger=logger)
loop.run(num_episodes=50)

 

D4PG エージェントを評価する

今はエージェントを評価できます。これは noisy behavior ポリシーを使用しますので、最適ではないことに注意してください。絶対的に精密であることを望んだ場合にはこれを noise-free ポリシーと容易に置き換えられたでしょう。最適なポリシーはこの環境でおよそ 1000 報酬を得られることに注意してください。D4PG は一般には 50-100 leaner ステップ内でそれに到達するはずです。このチュートリアルを単に単純化するためにそれを 50 でカットして behavior noise を破棄しません。

# Run the actor in the environment for desired number of steps.
frames = []
num_steps = 500
timestep = environment.reset()

for _ in range(num_steps):
  frames.append(render(environment))
  action = d4pg_agent.select_action(timestep.observation)
  timestep = environment.step(action)

# Save video of the behaviour.
display_video(np.array(frames))
 

以上






Acme : サンプル : クイックスタート

Acme : サンプル : クイックスタート (強化学習) (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/13/2020

* 本ページは、Acme の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

サンプル : クイックスタート

Acme をインストールして貴方の最初の D4PG エージェントを訓練するためのガイド

 

環境ライブラリを選択する

Note: dm_control は有効な Mujoco ライセンスを必要とします。

environment_library = 'gym'  # @param ['dm_control', 'gym']

 

Mujoco ライセンスをここで追加する

Note: dm_control のためだけに必要です。

mjkey = """
""".strip()

if not mjkey and environment_library == 'dm_control':
  raise ValueError(
      'A Mujoco license is required for `dm_control`, if you do not have on '
      'consider selecting `gym` from the dropdown menu in the cell above.')

 

インストール

Acme をインストールする

!pip install dm-acme
!pip install dm-acme[reverb]
!pip install dm-acme[tf]

 

環境ライブラリをインストールする

有効なライセンスなしでは dm_control 環境を利用することはできませんが、gym 環境を利用して依然としてこの colab に従うことができます。

personal Mujoco ライセンス (not an institutional one) を持つ場合、貴方のローカルマシンで Jupyter カーネルを実行するには https://research.google.com/colaboratory/local-runtimes.html の手順に従う必要があるかもしれません。これは https://github.com/deepmind/dm_control の手順に従い personal Mujoco ライセンスを使用することにより dm_control をインストールすることを可能にします。

#@test {"skip": true}
if environment_library == 'dm_control':
  mujoco_dir = "$HOME/.mujoco"

  # Install OpenGL dependencies
  !apt-get update && apt-get install -y --no-install-recommends \
    libgl1-mesa-glx libosmesa6 libglew2.0

  # Get MuJoCo binaries
  !wget -q https://www.roboti.us/download/mujoco200_linux.zip -O mujoco.zip
  !unzip -o -q mujoco.zip -d "$mujoco_dir"

  # Copy over MuJoCo license
  !echo "$mjkey" > "$mujoco_dir/mjkey.txt"

  # Install dm_control
  !pip install dm_control

  # Configure dm_control to use the OSMesa rendering backend
  %env MUJOCO_GL=osmesa

  # Check that the installation succeeded
  try:
    from dm_control import suite
    env = suite.load('cartpole', 'swingup')
    pixels = env.physics.render()
  except Exception as e:
    raise e from RuntimeError(
        'Something went wrong during installation. Check the shell output above '
        'for more information. If you do not have a valid Mujoco license, '
        'consider selecting `gym` in the dropdown menu at the top of this Colab.')
  else:
    del suite, env, pixels

elif environment_library == 'gym':
  !pip install gym

 

可視化パッケージをインストールする

!sudo apt-get install -y xvfb ffmpeg
!pip install imageio
!pip install PILLOW
!pip install pyvirtualdisplay

 

モジュールをインポートする

import IPython

from acme import environment_loop
from acme import specs
from acme import wrappers
from acme.agents.tf import d4pg
from acme.tf import networks
from acme.tf import utils as tf2_utils
from acme.utils import loggers
import numpy as np
import sonnet as snt

# Import the selected environment lib
if environment_library == 'dm_control':
  from dm_control import suite
elif environment_library == 'gym':
  import gym

# Imports required for visualization
import pyvirtualdisplay
import imageio
import base64

# Set up a virtual display for rendering.
display = pyvirtualdisplay.Display(visible=0, size=(1400, 900)).start()

 

環境をロードする

今では環境をロードできます。以下では環境を作成して環境の仕様を把握します。

if environment_library == 'dm_control':
  environment = suite.load('cartpole', 'balance')
  
elif environment_library == 'gym':
  environment = gym.make('MountainCarContinuous-v0')
  environment = wrappers.GymWrapper(environment)  # To dm_env interface.

else:
  raise ValueError(
      "Unknown environment library: {};".format(environment_name) +
      "choose among ['dm_control', 'gym'].")

# Make sure the environment outputs single-precision floats.
environment = wrappers.SinglePrecisionWrapper(environment)

# Grab the spec of the environment.
environment_spec = specs.make_environment_spec(environment)

 

D4PG エージェントを作成する

#@title Build agent networks

# Get total number of action dimensions from action spec.
num_dimensions = np.prod(environment_spec.actions.shape, dtype=int)

# Create the shared observation network; here simply a state-less operation.
observation_network = tf2_utils.batch_concat

# Create the deterministic policy network.
policy_network = snt.Sequential([
    networks.LayerNormMLP((256, 256, 256), activate_final=True),
    networks.NearZeroInitializedLinear(num_dimensions),
    networks.TanhToSpec(environment_spec.actions),
])

# Create the distributional critic network.
critic_network = snt.Sequential([
    # The multiplexer concatenates the observations/actions.
    networks.CriticMultiplexer(),
    networks.LayerNormMLP((512, 512, 256), activate_final=True),
    networks.DiscreteValuedHead(vmin=-150., vmax=150., num_atoms=51),
])
# Create a logger for the agent and environment loop.
agent_logger = loggers.TerminalLogger(label='agent', time_delta=10.)
env_loop_logger = loggers.TerminalLogger(label='env_loop', time_delta=10.)

# Create the D4PG agent.
agent = d4pg.D4PG(
    environment_spec=environment_spec,
    policy_network=policy_network,
    critic_network=critic_network,
    observation_network=observation_network,
    sigma=1.0,
    logger=agent_logger,
    checkpoint=False
)

# Create an loop connecting this agent to the environment created above.
env_loop = environment_loop.EnvironmentLoop(
    environment, agent, logger=env_loop_logger)

 

訓練ループを実行する

# Run a `num_episodes` training episodes.
# Rerun this cell until the agent has learned the given task.
env_loop.run(num_episodes=100)

 

評価ループを可視化する

レンダリングと可視化のためのヘルパー関数

# Create a simple helper function to render a frame from the current state of
# the environment.
if environment_library == 'dm_control':
  def render(env):
    return env.physics.render(camera_id=0)
elif environment_library == 'gym':
  def render(env):
    return env.environment.render(mode='rgb_array')
else:
  raise ValueError(
      "Unknown environment library: {};".format(environment_name) +
      "choose among ['dm_control', 'gym'].")

def display_video(frames, filename='temp.mp4'):
  """Save and display video."""

  # Write video
  with imageio.get_writer(filename, fps=60) as video:
    for frame in frames:
      video.append_data(frame)

  # Read video and display the video
  video = open(filename, 'rb').read()
  b64_video = base64.b64encode(video)
  video_tag = ('

 

エピソードのための環境でエージェントを実行して可視化する

timestep = environment.reset()
frames = [render(environment)]

while not timestep.last():
  # Simple environment loop.
  action = agent.select_action(timestep.observation)
  timestep = environment.step(action)

  # Render the scene and add it to the frame stack.
  frames.append(render(environment))

# Save and display a video of the behaviour.
display_video(np.array(frames))
 

以上






Acme : エージェント

Acme : エージェント (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/13/2020

* 本ページは、Acme の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

エージェント

Acme は下でリストされる幾つかの事前構築されたエージェントを含みます。これらは総てシングルプロセス・エージェントです。現在これらのエージェントの分散亜種をリリースする計画はありませんが、それらはこのレポジトリで利用可能な単一プロセスの対応物と正確に同じ learning と acting コードを共有します。

異なるユースケースに基づいて分けたセクションで下でエージェントをリストアップしました、これらの区別はしばしば微妙ですが。各実装のより多くの情報については関連するエージェント固有の README を見てください。

 

連続的制御

Acme は連続的な制御エージェントに長く焦点を当ててきています (i.e. アクション空間が連続空間から成る設定)。以下のエージェントはこの設定にフォーカスしています :

エージェント ペーパー コード
深層決定論的ポリシー勾配 (DDPG) Lillicrap et al., 2015
分散分布 (= Distributional) 深層 Determinist (D4PG) Barth-Maron et al., 2018
Maximum a posteriori ポリシー最適化 (MPO) Abdolmaleki et al., 2018
分布 Maximum a posteriori ポリシー最適化 (DMPO)

 

離散制御

離散アクション空間を念頭において構築された幾つかのエージェントも含みます。これらのエージェントとリストされた連続的エージェントの区別はある程度恣意的であることに注意してください。E.g. Impala は連続的アクション空間のためにも実装できるでしょうが、ここでは離散アクション亜種にフォーカスしています。

エージェント ペーパー コード
深層 Q-ネットワーク (DQN) Horgan et al., 2018  
Importance-Weighted Actor-Learner アーキテクチャ (IMPALA) Espeholt et al., 2018  
リカレント再生分散 DQN (R2D2) Kapturowski et al., 2019

 

バッチ RL

Acme の構造はまた (環境相互作用を伴わない) バッチ RL での利用のための “learner-only” アルゴリズムにも非常に素晴らしく適しています。実装されたアルゴリズムは以下を含みます :

エージェント ペーパー コード
Behavior Cloning (BC)

 

実演からの学習

Acme はまた実演 (デモ) からのデータと結合される active データ獲得も容易に可能にします。そのようなアルゴリズムは以下を含みます :

エージェント ペーパー コード
実演からの深層 Q-学習 (DQfD) Hester et al., 2017
実演からのリカレント再生分散 DQN (R2D3) Gulcehre et al., 2020

 

モデルベースの RL

最後に、Acme はまた MCTS の亜種も含みます、これは与えられたあるいは学習されたシミュレータを使用してモデルベースの RL のために利用できます。

エージェント ペーパー コード
モンテカルロ木探索 (MCTS) Silver et al., 2018

 

以上






Acme : コンポーネント

Acme : コンポーネント (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/13/2020

* 本ページは、Acme の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

コンポーネント

環境

Acme は dm_env 環境インターフェイス を実装する環境と動作するように設計されています。これはアクションを取り観測を受け取るために環境と相互作用するための一般的な API を提供します。この環境 API はまた environment.action_spec() のようなメソッドを通してその環境に関連する入力と出力空間を指定するための環境のための標準的な方法も提供します。Acme はまたこれらの spec type を acme.specs を通して直接公開することにも注意してください。けれどもまた、Acme エージェントが完全な環境 spec を要求することは普通のことです、これは acme.make_environment_spec(environment) を利用して得ることができます。

Acme はまた acme.wrappers の下で幾つかのクラスを公開しています、これは dm_env 環境をラップ and/or 公開します。総てのそのようなラッパーは次の形式です :

environment = Wrapper(raw_environment, ...)

ここで動作を制御するために追加パラメータがラッパーに渡されるかもしれません (より詳細については個々の実装を見てください)。直接公開されるラッパーは以下を含みます :

  • SinglePrecisionWrapper: 環境により返される任意の倍精度浮動小数点と整数コンポーネントを単精度に変換します。
  • AtariWrapper: “Human Level Control Through Deep Reinforcement Learning” 公開物で使用された変更に対応するラッパーのスタックを使用して標準的 ALE Atari 環境を変換します。

Acme はまた acme.wrappers.gym_wrapper モジュールを含みます、これは OpenAI Gym 環境と相互作用するために利用できます。これは一般的な GymWrapper クラスとともに AtariGymWrapper を含みます、これは AtariWrapper によりオプションで公開できる lives カウント観測を公開します。

 

ネットワーク

任意のエージェント実装のための重要なビルディングブロックはパラメータ化された関数あるいはネットワークから成ります、これはポリシー、値関数等を構築するために使用されます。Acme で実装されるエージェントは (その上で適用される) 環境にはできる限り不可知論であるとして構築されます。結果としてそれらは典型的にはネットワークを必要とします、これらは観測を消費するか、アクションを生成する、あるいは両者のために環境と直接相互作用するために使用されます。これらは典型的にはエージェントに初期化時に直接渡されます、e.g.

policy_network = ...
critic_network = ...
agent = MyActorCriticAgent(policy_network, critic_network, ...)

 

Tensorflow と Sonnet

TensorFlow エージェントについては、Acme のネットワークは典型的には Sonnet ニューラルネットワーク・ライブラリを使用して実装されています。これらのネットワーク・オブジェクトは Callable オブジェクトの形式を取ります、これは入力として (ネストされた) tf.Tensor オブジェクトのコレクションを取り (nested) tf.Tensor か tfp.Distribution オブジェクトのコレクションを出力します。以後、次のエイリアスを使用します。

import sonnet as snt
import tensorflow as tf
import tensorflow_probability as tfp

tfd = tfp.distributions

カスタム Sonnet モジュールが直接実装されて利用できる一方で、Acme はまた幾つかの有用なネットワーク・プリミティブを提供します、これは RL タスクに仕立てられています ; これらは acme.tf.networks からインポートできます、より詳細については ネットワーク を見てください。これらのプリミティブは状態を持つネットワークモジュールをスタックするとき snt.Sequential か snt.DeepRNN を使用して結合できます。

モジュールをスタックするとき、トルソー (= torso)、ヘッドそしてマルチプレクサ・ネットワークとしばしば呼ばれるものの間で識別することは、常にではありませんが、しばしば有用です。ネットワーク・アーキテクチャを議論するときこのカテゴリー分類は純粋に教育上のものですがそれにもかかわらず有用であることがわかることに注意してください。

トルソーは最初に入力 (観測、アクションか組み合わせ) を変換して深層学習文献では埋め込みベクトルとして一般に知られるものを生成します。これらのモジュールはスタックできます、その結果埋め込みはそれがヘッドに供給される前に複数回変換されます。

例えばそれを Atari ゲームで訓練するとき Impala エージェントで使用する単純なネットワークを考えましょう :

impala_network = snt.DeepRNN([
    # Torsos.
    networks.AtariTorso(),  # Default Atari ConvNet offered as convenience.
    snt.LSTM(256),  # Custom LSTM core.
    snt.Linear(512), # Custom perceptron layer before head.
    tf.nn.relu,  # Seemlessly stack Sonnet modules and TF ops as usual.
    # Head producing 18 action logits and a value estimate for the input
    # observation.
    networks.PolicyValueHead(num_actions=18),
])

ヘッドは望まれる出力 (アクション・ロジットや分布、値推定, etc) を生成するために埋め込みベクトルを消費するネットワークです。これらのモジュールもまたスタックできます、これは確率的ポリシーを扱うときに特に有用です。例えば、制御スーツで訓練される、MPO エージェントで使用される次の確率的ポリシーを考えます :

policy_layer_sizes: Sequence[int] = (256, 256, 256)

stochastic_policy_network = snt.Sequential([
    # MLP torso with initial layer normalization; activate the final layer since
    # it feeds into another module.
    networks.LayerNormMLP(policy_layer_sizes, activate_final=True),
    # Head producing a tfd.Distribution: in this case `num_dimensions`
    # independent normal distributions.
    networks.MultivariateNormalDiagHead(num_dimensions),
  ])

確率的ポリシーは対数確率と Kullback-Leibler (KL) ダイバージェンスを計算するために MPO アルゴリズムで内部的に使用されます。greedy アクションとして確率的ポリシーの平均を選択する追加のヘッドをスタックすることもできます :

greedy_policy_network = snt.Sequential([
    networks.LayerNormMLP(policy_layer_sizes, activate_final=True),
    networks.MultivariateNormalDiagHead(num_dimensions),
    networks.StochasticModeHead(),
  ])

連続的制御タスクのための actor-critic エージェントを設計するとき、一つの単純なモジュールが特に有用であることを見出しました : CriticMultiplexer です。この callable Sonnet モジュールは 2 つの入力、観測とアクションを取り、そして [observation|action]_network のいずれかか両者が渡された場合それらを多分変換した後、それらをバッチ次元を除いて総て一緒に結合します。例えば、次は D4PG 実験のために適応された C51 (Bellemare et al., 2017 参照) 分散 critic ネットワークです :

critic_layer_sizes: Sequence[int] = (512, 512, 256)

distributional_critic_network = snt.Sequential([
    # Flattens and concatenates inputs; see `tf2_utils.batch_concat` for more.
    networks.CriticMultiplexer(),
    networks.LayerNormMLP(critic_layer_sizes, activate_final=True),
    # Distributional head corresponding to the C51 network.
    networks.DiscreteValuedHead(vmin=-150., vmax=150., num_atoms=51),
])

最後に、actor-critic 制御エージェントはまたポリシーと critic により共有される観測ネットワークの仕様を許します。このネットワークは観測を一度埋め込み変換された入力を必要に応じてポリシーと critic の両者で利用します、これは特に変換が高価であるとき計算を節約します。これは例えばピクセルから学習するときです、そこでは観測ネットワークは大きい ResNet であり得ます。そのような場合、共有 visual ネットワークは単純に以下を定義して渡すことにより任意の DDPG, D4PG, MPO, DMPO に指定できます :

shared_resnet = networks.ResNetTorso()  # Default (deep) Impala network.

agent = dmpo.DMPO(
    # Networks defined above.
    policy_network=stochastic_policy_network,
    critic_network=distributional_critic_network,
    # New ResNet visual module, shared by both policy and critic.
    observation_network=shared_resnet,
    # ...
)

この場合、policy_ と critic_network は共有 visual トルソーの上のヘッドとして動作します。

 

内部コンポーネント

Acme はまた幾つかのコンポーネントとコンセプトを含みます、これらは典型的にはエージェントの実装の内側です。これらのコンポーネントはもし貴方が Acme エージェントを利用することにだけ関心がある場合、一般に無視できます。けれどもそれらは新規のエージェントを実装するとき、あるいは既存のエージェントを変更するときに有用であることがわかります。

 

損失

幾つかの良く利用される損失関数があります。一般に可能なところでは TFRL に従うことに注意してください、それがそのために TensorFlow 2 をサポートしない場合を除いて。

実装された RL-固有の損失は以下を含みます :

そして実装された (そして上で言及した損失内で有用な) ものは :

  • ロバスト回帰のための Huber 損失 (訳注: リンク切れ)。

 

Adders

Adder はデータを再生バッファに送るために一緒にパックして、そしてその過程でこのデータに何某かの削減/変換を行なう可能性があります。

総ての Acme Adder はそれらの add(), end_episode(), または add_async(), end_episode_async() と reset() メソッドを通して相互作用できます。

add() メソッドは形式 : (state_t, action_t, reward_t+1, discount_t+1, [extras_t]) のタプルを取ります。

エピソードの最後で、学習に利用可能な、形式 (state, (a, r, d…), *next_state*) のデータを持つという RL アルゴリズムの一般的な要請の結果、どのような新しいアクション、報酬 etc. を追加することなく最後の next_state を再生バッファに追加する必要があります。Adder の end_episode() メソッドはこれを貴方のために処理します、通常はタプルの他のパートを適切にパディングして最後の next_state を単純に追加することによって。

adder のサンプル使用方法は :

timestep = env.reset()
while not timestep.last():
  action = my_policy(timestep)
  new_timestep = env.step(action)
  # Adds a (s, a, r, d) tuple to the adder's internal buffer.
  adder.add(timestep.observation, action, new_timestep.reward,
            new_timestep.discount)
  timestep = new_timestep
# When the episode ends, tell the adder about the final arrival state.
adder.end_episode(new_timestep.observation)

 

ReverbAdder

Acme は RL 経験をストアするために再生バッファのようなデータ構造を作成するために Reverb を利用します。

便利のため、actor 経験を Reverb テーブルに追加するために Acme は幾つかの ReverbAdder を提供します。提供される ReverbAdder は以下を含みます :

  • NStepTransitionAdder は環境/エージェント・ループから単一ステップを取り、自動的にそれらを N-ステップ遷移に結合して、そして将来の再取得 (= retrieval) のために遷移を Reverb に追加します。ステップはバッファリングされてから N-ステップ遷移に結合されます、これは再生 (バッファ) にストアされてそこから返されます。

    N が 1 であるところでは、遷移は次の形式です :

    `(s_t, a_t, r_t, d_t, s_{t+1}, e_t)`
    

    1 より大きい N については、遷移は次の形式です :

    `(s_t, a_t, R_{t:t+n}, D_{t:t+n}, s_{t+n}, e_t)`,
    

    遷移はシークエンスかエピソードとしてストアできます。

  • EpisodeAdder、これはエピソード全体を次の形式の trajectories (軌道) として追加します :
    (s_0, a_0, r_0, d_0, e_0,
     s_1, a_1, r_1, d_1, e_1,
              .
              .
              .
     s_T, a_T, r_T, 0., e_T)
    
  • PaddedEpisodeAdder、これは max_sequence_length へのパディングを伴う EpisodeAdder と同じです。
  • SequenceAdder、これは次の形式の固定 sequence_length n のシークエンスを追加します :
      (s_0, a_0, r_0, d_0, e_0,
       s_1, a_1, r_1, d_1, e_1,
                .
                .
                .
       s_n, a_n, r_n, d_n, e_n)
    

    シークエンスは overlapping (if period パラメータ = sequence_length n) か non-overlapping (if period < sequence_length) であり得ます。

 

Loggers

Acme は、総て write() メソッドを持つ抽象 Logger クラスに基づいて、データを共通の場所に書き出すための幾つかの logger を含みます。

NOTE: デフォルトでは、logger を構築するとき logger 出力の間の秒数を表す、time_delta 引数のために非ゼロ値が与えられない限りは logger は write() を通して渡された総てのデータを直ちに出力します。

 

Terminal Logger

データを直接端末にログ出力します。

サンプル :

terminal_logger = loggers.TerminalLogger(label='TRAINING',time_delta=5)
terminal_logger.write({'step': 0, 'reward': 0.0})

>> TRAINING: step: 0, reward: 0.0

 

CSV Logger

指定された CSV ファイルにログ出力します。

サンプル :

csv_logger = loggers.CSVLogger(logdir='logged_data', label='my_csv_file')
csv_logger.write({'step': 0, 'reward': 0.0})

 

Tensorflow savers

訓練された TensorFlow モデルをセーブするため、それらをチェックポイントあるいはスナップショットを撮ることができます。

チェックポイントとスナップショットの両者は後で利用するためにモデル状態をセーブしてリストアする方法です。違いはチェックポイントをリストアするときに発生します。

チェックポイントでは、最初に正確なグラフを再構築してから、チェックポイントをリストアしなければなりません。それらは実験を実行している間、実験が中断/阻止されて実験状態を失うことなく実験実行を続けるためにリストアされなければならないケースで、持つことは有用です。

スナップショットはグラフを内部的に再構築しますので、貴方がしなければならないことの総てはスナップショットをリストアすることです。

Acme の Checkpointer クラスは望まれるモデル状態の異なるパートを (objects_to_save 引数を持つ) チェックポイントと (objects_to_snapshot 引数を持つ) スナップショットの両者を行なう機能を提供します。

 model = snt.Linear(10)
 checkpointer = utils.tf2_utils.Checkpointer(
     objects_to_save={'model': model},
     objects_to_snapshot={'model': model})
 for _ in range(100):
   # ...
   checkpointer.save()
 

以上






Acme : 概要 – DeepMind 強化学習ライブラリ

Acme : 概要 – DeepMind 強化学習ライブラリ (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/12/2020

* 本ページは、Acme の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

概要

Acme は強化学習 (RL) エージェントとエージェント・ビルディングブロックのライブラリです。Acme はポピュラーなアルゴリズムの参照実装としてそして強力なベースラインとして役立つような、単純で、効率的で可読なエージェントを公開するための努力をする一方で、新規の研究を行なうために十分な柔軟性を依然として提供しています。Acme の設計はまた複雑さの異なるレベルで RL 問題への複数のエントリポイントを提供することも試みています。

 

概要

Acme を使用して素早く始めることを単に望む場合、ライブラリについて知るべき主要なことは幾つかのエージェント実装と次のように利用できる EnvironmentLoop プリミティブを公開していることです :

loop = acme.EnvironmentLoop(environment, agent)
loop.run()

これは単純なループを実行します、そこでは与えられたエージェントは環境と相互作用してこの相互作用から学習します。これはエージェント・インスタンス (その実装は ここ で見つけられます) と環境インスタンスを仮定します、これは DeepMind Environment API を実装しています。個々のエージェントはまた実装をより詳細に説明する README.md ファイルを含みます。もちろん、これら 2 行のコードは描写を明確に単純化しています。実際に始めるために、examples サブディレクトリで見つかる詳細なワーキングコードサンプルを見てください、これらは幾つかのエージェントと環境をどのようにインスタンス化するかを示します。クイックスタート・ノートブック もまた含みます。

Acme はまた、エージェントアルゴリズムに深く潜る、あるいはそれらをより複雑な設定で利用する一方で、このレベルの単純性を維持しようとします。基礎的なコンポーネントのより詳細な説明とともに Acme の概要は ドキュメント を参照することにより見つけられます。そして典型的な Acme エージェントの裏の基礎的なコンポーネントそしてこれらが新規の実装を形成するためにどのように結合できるかをより詳細に説明する チュートリアルノートブック も含みます。

 

インストール

Python 3.6 と 3.7 上で acme をテストしました。

  1. オプション: バージョン衝突を避けるために依存性を管理するため Python 仮想環境を使用することを強く推奨します :
    python3 -m venv acme
    source acme/bin/activate
    pip install --upgrade pip setuptools
    
  2. (Reverb, ストレージ・バックエンドを含む) コアライブラリをインストールするには :
    pip install dm-acme
    pip install dm-acme[reverb]
    
  3. JAX or TensorFlow ベースのエージェントのための依存性をインストールするには :
    pip install dm-acme[tf]
    # and/or
    pip install dm-acme[jax]
    
  4. 最後に、環境 (gym, dm_control, bsuite) をインストールするには :
    pip install dm-acme[envs]
    

 

Citing Acme

(訳注: 必要な場合には 原文 を参照してください。)

 

docs/index.md

概要

Acme は強化学習 (RL) エージェントとエージェント・ビルディングブロックのライブラリです。Acme は全体として新規の実装を作成するために十分な柔軟性を依然として提供する一方で、単純で、効率的で可読なエージェントベースラインを公開する努力をしています。Acme の設計は複雑さの異なるレベルで RL 問題への複数のエントリポイントを提供することを試みています。最初のエントリポイント – そして始めるに最も容易な方法 – は最先端技術のベースライン・エージェントの一つを単に実行することによります。これは単純に環境ループを使用してエージェント (or アクター) インスタンスを環境に接続することにより成されます。これは RL に共通な環境との相互作用の標準モードをインスタンス化して次の図で示されます :

この設定はもちろん、任意の RL 実践者に見覚えがあるでしょう、そしてこれによって貴方は始めて 2, 3 行のコードで Acme エージェントを実行することができます。Acme により利用される環境は DeepMind Environment API に従うことが想定されます、これは環境をある初期状態にリセットすることと環境をステップさせて観測を生成することの両者への単純なメカニズムを提供します。

Acme のアクターは 3 つの主要なメソッドを公開します : select_action は取られるアクションを返します、observe は環境からの観測を記録します、そして update メソッドです。実際に、これらのメソッドを利用することにより、上で示された EnvironmentLoop は以下によりおおよそ近似できます :

while True:
  # Make an initial observation.
  step = environment.reset()
  actor.observe_first(step.observation)

  while not step.last():
    # Evaluate the policy and take a step in the environment.
    action = actor.select_action(step.observation)
    step = environment.step(action)

    # Make an observation and update the actor.
    actor.observe(action, next_step=step)
    actor.update()

NOTE : 現在 Acme では利用するデータを観測するためのデフォルトメソッドは observe/observe_last メソッドを利用しています (上の反対)。これは上のために段階的に廃止され、これらが間もなくデフォルトになるでしょう。

内部的には、Acme を使用して構築されるエージェントはモジュール acting と learning コンポーネントで書かれています。acting により経験を生成するために使用されるサブコンポーネントを参照して learning により適切なアクション選択モデル (典型的にはニューラルネットワーク) を訓練するプロセスを参照しています。エージェントのこの分解の図は下で与えられます :

表面的にはこれはマルチエージェントの間で同じ実験生成コードを共有することを可能にします。より重要なことに、この精神は分散エージェントがどのように構築されるかという方法を大きく単純化します。

分散エージェントはシングルプロセスの対応物と総て同じコンポーネントを使用して構築されますが、行動、学習、評価、再生等のためのコンポーネントが各々それら自身のプロセスで動作するように分割されます。この図は下で示されます、そしてここではそれが単に多くの異なるアクター/環境とともに、上と同じテンプレートに従うことを見れるでしょう :

これは新規のエージェントを設計して既存のエージェントをテストするプロセスを非常に単純化します、そこではスケールの違いは大雑把には無視できます。これはバッチや (そこではデータ生成プロセスはなく固定データセットだけの) オフライン設定への幅広いスケールダウンも可能にします :

最後に、Acme はまたエージェントコードを可読に保持し、そして次のエージェントを書くプロセスを遥かに容易にする幾つかの有用なユティリティも含みます。チェックポイントからスナップショット、ロギングの様々な形式、そして他の低位計算に渡るこれらのコンポーネントのための一般的なツールを提供します。上で説明された構造に加えてこれらのコンポーネントのより多くの情報については、Acme コンポーネント のより詳細な議論を見るか、様々な エージェント の完全な実装を見てください。

 

以上






Tensorforce : 基本 : モジュール仕様

Tensorforce 基本 : モジュール仕様 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/24/2020 (0.5.4)

* 本ページは、Tensorforce の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

基本 : モジュール仕様

下で表される仕様選択肢のいずれかにより、エージェントは Agent.create(agent=…) を通してインスタンス化されます (agent は type 引数として作用します)。2 番目の引数 environment としてアプリケーション Environment 実装を渡すことが推奨されます、これはエージェントの対応する states, actions と max_episode_timesteps 引数を自動的に抽出します。

 

モジュールをどのように指定するか

モジュール type と引数を持つ辞書

Agent.create(...
    policy=dict(network=dict(type='layered', layers=[dict(type='dense', size=32)])),
    memory=dict(type='replay', capacity=10000), ...
)

 

JSON 仕様ファイル (plus 追加引数)

Agent.create(...
    policy=dict(network='network.json'),
    memory=dict(type='memory.json', capacity=10000), ...
)

 

モジュールパス (plus 追加引数)

Agent.create(...
    policy=dict(network='my_module.TestNetwork'),
    memory=dict(type='tensorforce.core.memories.Replay', capacity=10000), ...
)

 

Callable or Type (plus 追加引数)

Agent.create(...
    policy=dict(network=TestNetwork),
    memory=dict(type=Replay, capacity=10000), ...
)

 

デフォルトモジュール: only arguments or first argument

Agent.create(...
    policy=dict(network=[dict(type='dense', size=32)]),
    memory=dict(capacity=10000), ...
)

 

静的 vs 動的ハイパーパラメータ

Tensorforce はエージェント/モジュール引数 (プリミティブ型: bool/int/long/float) の間を識別します、これは層サイズ、or アーキテクチャ内の値のような、学習率のような、 TensorFlow モデル・アーキテクチャのいずれかの部分を指定します。前者はエージェント初期化の一部として静的に定義されるところ、後者は後で動的に調整できます。これらの動的ハイパーパラメータはドキュメントのタイプ仕様の一部としてパラメータにより示され、そして例えば、減衰する学習率を指定するような定数値の代わりに パラメータモジュール が割り当てられます。

 

サンプル: 探求を指数関数的に減衰する

Agent.create(...
    exploration=dict(
        type='decaying', unit='timesteps', decay='exponential',
        initial_value=0.1, decay_steps=1000, decay_rate=0.5
    ), ...
)

 

サンプル: 線形に範囲 (= horizon) を増やす

Agent.create(...
    reward_estimation=dict(horizon=dict(
        type='decaying', dtype='long', unit='episodes', decay='polynomial',
        initial_value=10.0, decay_steps=1000, final_value=50.0, power=1.0
    ), ...
)
 

以上






Tensorforce : 基本 : イントロダクション & Getting Started

Tensorforce 基本 : イントロダクション & Getting Started (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/24/2020 (0.5.4)

* 本ページは、Tensorforce : Basics の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

基本 : イントロダクション& Getting Started

Tensorforce はオープンソースの深層強化学習フレームワークで、研究と実践におけるアプリケーションのためのモジュール化された柔軟なライブラリ設計と簡単な使い勝手を重視しています。Tensorforce は Google の TensorFlow フレームワーク version 2.0 (!) の上に構築されていて Python 3 と互換です (Python 2 サポートは version 0.5 でドロップされました)。

Tensorforce は高位設計選択のセットに従います、これは他の類似のライブラリから差別化します :

  • モジュール式コンポーネントベースの設計: とりわけ、特徴実装はできる限り一般的に適用可能で構成可能であることを目標にしています、紹介するペーパーの詳細を忠実に似せるためにある程度のコストを潜在的に払いながら。
  • RL アルゴリズムとアプリケーションの分離: アルゴリズムは入力 (状態/観測) と出力 (アクション/決定)、更にアプリケーション環境との相互作用のタイプと構造に不可知論者です。
  • Full-on TensorFlow モデル: アプリケーション・プログラミング言語とは無関係に可搬な計算グラフを可能にし、そしてモデルの配備を容易にするため、制御フローを含む、強化学習ロジック全体は TensorFlow で実装されています。

 

Getting started

環境を初期化する

Environment.create(…) インターフェイスを通して環境を初期化することが推奨されます。

from tensorforce.environments import Environment

例えば、OpenAI CartPole 環境は次のように初期化できます :

environment = Environment.create(
    environment='gym', level='CartPole', max_episode_timesteps=500
)

Gym の事前定義されたバージョンもまたアクセス可能です :

environment = Environment.create(environment='gym', level='CartPole-v1')

代わりに、環境は config ファイルとして指定できます :

{
    "environment": "gym",
    "level": "CartPole"
}

環境 config ファイルはそれらのファイルパスを渡すことによりロードできます :

environment = Environment.create(
    environment='environment.json', max_episode_timesteps=500
)

カスタム Gym 環境が同じ方法で利用できますが、それに応じてインポートされて登録される対応するクラスを必要とします。

最後に、Tensorforce の Environment インターフェイスを使用してカスタム環境を実装することが可能です :

class CustomEnvironment(Environment):

    def __init__(self):
        super().__init__()

    def states(self):
        return dict(type='float', shape=(8,))

    def actions(self):
        return dict(type='int', num_values=4)

    # Optional, should only be defined if environment has a natural maximum
    # episode length
    def max_episode_timesteps(self):
        return super().max_episode_timesteps()

    # Optional
    def close(self):
        super().close()

    def reset(self):
        state = np.random.random(size=(8,))
        return state

    def execute(self, actions):
        assert 0 <= actions.item() <= 3
        next_state = np.random.random(size=(8,))
        terminal = np.random.random() < 0.5
        reward = np.random.random()
        return next_state, terminal, reward

カスタム環境実装はそれらのモジュールパスを渡すことによりロードできます :

environment = Environment.create(
    environment='custom_env.CustomEnvironment', max_episode_timesteps=10
)

環境により指定されない限りは (or 評価のためでなければ) Environment.create(...) の max_episode_timesteps 引数を指定することが強く推奨されます、何故ならばそうでなければより多くのエージェント・パラメータが指定を必要とするかもしれないからです。

 

エージェントを初期化する

環境と同様に、Agent.create(...) インターフェイスを通してエージェントを初期化することが推奨されます。

from tensorforce.agents import Agent

例えば、一般的な Tensorforce エージェント は次のように初期化できます :

agent = Agent.create(
    agent='tensorforce', environment=environment, update=64,
    objective='policy_gradient', reward_estimation=dict(horizon=20)
)

他の事前定義エージェント・クラスも代わりに使用できます、例えば、Proximal Policy Optimization :

agent = Agent.create(
    agent='ppo', environment=environment, batch_size=10, learning_rate=1e-3
)

代わりに、エージェントは config ファイルとして定義できます :

{
    "agent": "tensorforce",
    "update": 64,
    "objective": "policy_gradient",
    "reward_estimation": {
        "horizon": 20
    }
}

エージェント config ファイルはそれらのファイルパスを渡すことによりロードできます :

agent = Agent.create(agent='agent.json', environment=environment)

Agent.create(...) の environment 引数として Environment.create(...) により返される environment オブジェクトを渡すことが推奨されます、その結果 states, actions and max_episode_timesteps 引数はそれに従って自動的に指定されます。

 

訓練と評価

訓練と評価のためには Runner ユティリティのような実行ユティリティを利用することが推奨されます、これはある範囲の configuration オプションを供給します :

from tensorforce.execution import Runner

訓練と続く評価から成る基本的な実験は数行のコードで書かれます :

runner = Runner(
    agent='agent.json',
    environment=dict(environment='gym', level='CartPole'),
    max_episode_timesteps=500
)

runner.run(num_episodes=200)

runner.run(num_episodes=100, evaluation=True)

runner.close()

実行ユティリティはエージェント-環境の相互作用を正しく処理する面倒を見ます、そして可能なところではこのように使用されるべきです。代わりに、エージェント-環境相互作用に渡るより詳細な制御が必要である場合には、単純な訓練と評価ループが次のように書けます :

# Create agent and environment
environment = Environment.create(
    environment='environment.json', max_episode_timesteps=500
)
agent = Agent.create(agent='agent.json', environment=environment)

# Train for 200 episodes
for _ in range(200):
    states = environment.reset()
    terminal = False
    while not terminal:
        actions = agent.act(states=states)
        states, terminal, reward = environment.execute(actions=actions)
        agent.observe(terminal=terminal, reward=reward)

# Evaluate for 100 episodes
sum_rewards = 0.0
for _ in range(100):
    states = environment.reset()
    internals = agent.initial_internals()
    terminal = False
    while not terminal:
        actions, internals = agent.act(states=states, internals=internals, evaluation=True)
        states, terminal, reward = environment.execute(actions=actions)
        sum_rewards += reward

print('Mean episode reward:', sum_rewards / 100)

# Close agent and environment
agent.close()
environment.close()
 

以上






TF-Agents 0.4 : Tutorials : DQN C51/Rainbow

TF-Agents 0.4 Tutorials : DQN C51/Rainbow (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/23/2020 (0.4)

* 本ページは、TF Agents の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

DQN C51/Rainbow

イントロダクション

このサンプルは TF-Agents ライブラリでカートポール環境上カテゴリカル DQN (C51) エージェントをどのように訓練するかを示します。

必要条件として DQN チュートリアル に目を通していることを確実にしてください。このチュートリアルは DQN チュートリアルに精通していることを仮定しています ; それは DQN と C51 の間の違いに主として焦点を当てます。

 

セットアップ

tf-agents をまだインストールしていないのであれば、以下を実行します :

!sudo apt-get install -y xvfb ffmpeg
!pip install 'gym==0.10.11'
!pip install 'imageio==2.4.0'
!pip install PILLOW
!pip install 'pyglet==1.3.2'
!pip install pyvirtualdisplay
!pip install --upgrade tensorflow-probability
!pip install tf-agents
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import base64
import imageio
import IPython
import matplotlib
import matplotlib.pyplot as plt
import PIL.Image
import pyvirtualdisplay

import tensorflow as tf

from tf_agents.agents.categorical_dqn import categorical_dqn_agent
from tf_agents.drivers import dynamic_step_driver
from tf_agents.environments import suite_gym
from tf_agents.environments import tf_py_environment
from tf_agents.eval import metric_utils
from tf_agents.metrics import tf_metrics
from tf_agents.networks import categorical_q_network
from tf_agents.policies import random_tf_policy
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.trajectories import trajectory
from tf_agents.utils import common

tf.compat.v1.enable_v2_behavior()


# Set up a virtual display for rendering OpenAI gym environments.
display = pyvirtualdisplay.Display(visible=0, size=(1400, 900)).start()

 

ハイパーパラメータ

env_name = "CartPole-v1" # @param {type:"string"}
num_iterations = 15000 # @param {type:"integer"}

initial_collect_steps = 1000  # @param {type:"integer"} 
collect_steps_per_iteration = 1  # @param {type:"integer"}
replay_buffer_capacity = 100000  # @param {type:"integer"}

fc_layer_params = (100,)

batch_size = 64  # @param {type:"integer"}
learning_rate = 1e-3  # @param {type:"number"}
gamma = 0.99
log_interval = 200  # @param {type:"integer"}

num_atoms = 51  # @param {type:"integer"}
min_q_value = -20  # @param {type:"integer"}
max_q_value = 20  # @param {type:"integer"}
n_step_update = 2  # @param {type:"integer"}

num_eval_episodes = 10  # @param {type:"integer"}
eval_interval = 1000  # @param {type:"integer"}

 

環境

前のように環境をロードします、一つは訓練のためそして一つは評価のためです。ここでは CartPole-v1 (vs. CartPole-v0 in DQN チュートリアル) を使用します、これは 200 よりも大きい 500 の大きな最大報酬を持ちます。

train_py_env = suite_gym.load(env_name)
eval_py_env = suite_gym.load(env_name)

train_env = tf_py_environment.TFPyEnvironment(train_py_env)
eval_env = tf_py_environment.TFPyEnvironment(eval_py_env)

 

エージェント

C51 は DQN に基づく Q-学習アルゴリズムです。DQN のように、それは離散アクション空間を持つ任意の環境上で利用できます。

C51 と DQN の間の主要な違いは各状態-アクションペアのための Q-値を単純に予測するのではなく、C51 は Q-値の確率分布のためのヒストグラム・モデルを予測します :

単純な期待値よりも分布を学習することにより、アルゴリズムは訓練の間よりステーブルのままでいることが可能で、改良された最終的なパフォーマンスに繋がります。これは特に二峰性分布の状況あるいは多峰性値分布でさえ特に真で、そこでは単一平均は正確な描写を提供しません。

値の上ではなく確率分布上で訓練するため、C51 はその損失関数を計算するためにある複雑な分布計算を遂行しなければなりません。しかし心配しないでください、これの総ては貴方のために TF-Agents でケアされます!

C51 エージェントを作成するため、最初に CategoricalQNetwork を作成する必要があります。CategoricalQNetwork の API は QNetwork のそれと同じです、追加引数 num_atoms があることを除いて。これは確率分布推定のサポート点の数を表します。(上の画像は 10 サポート点を含みます、各々は垂直の青色棒により表されます。) 名前から分かるように、アトムのデフォルト数は 51 です。

categorical_q_net = categorical_q_network.CategoricalQNetwork(
    train_env.observation_spec(),
    train_env.action_spec(),
    num_atoms=num_atoms,
    fc_layer_params=fc_layer_params)

ちょうど作成したネットワークを訓練するために optimizer、そしてネットワークが何回更新されたかを追跡するために train_step_counter 変数も必要です。

vanilla DqnAgent との一つの他の重要な違いは今は引数として min_q_value と max_q_value を指定する必要があることです。これらはサポートの最も極値を指定します (換言すれば、両側の 51 アトムの最も極値)。貴方の特定の環境のためにこれらを適切に選択することを確実にしてください。ここでは -20 と 20 を使用します。

optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate)

train_step_counter = tf.compat.v2.Variable(0)

agent = categorical_dqn_agent.CategoricalDqnAgent(
    train_env.time_step_spec(),
    train_env.action_spec(),
    categorical_q_network=categorical_q_net,
    optimizer=optimizer,
    min_q_value=min_q_value,
    max_q_value=max_q_value,
    n_step_update=n_step_update,
    td_errors_loss_fn=common.element_wise_squared_loss,
    gamma=gamma,
    train_step_counter=train_step_counter)
agent.initialize()

注意すべき一つの最後のことは $n$ = 2 で n-step 更新を使用するために引数も追加したことです。私達は (bellman 最適方程式に基づいて) 単一ステップのリターンを使用して現在の時間ステップと次の時間ステップの Q-値の間の誤差を計算するだけです。単一ステップのリターンは次のように定義されます :

$G_t = R_{t + 1} + \gamma V(s_{t + 1})$

ここで $V(s) = \max_a{Q(s, a)}$ を定義します。

N-ステップ更新は標準的な単一ステップの報酬関数を $n$ 回展開を伴います :

$G_t^n = R_{t + 1} + \gamma R_{t + 2} + \gamma^2 R_{t + 3} + \dots + \gamma^n V(s_{t + n})$

N-ステップ更新は更なる将来からブートストラップすることを可能にし、そして $n$ の正しい値で、これはしばしばより高速な学習に繋がります。

C51 と n-ステップ更新はしばしば Rainbow エージェントのコアを形成するために優先付けられた再生と結合されますが、私達は優先付けられた再生の実装から測定可能な改良は見ませんでした。その上、C51 エージェントを n-ステップ更新だけと結合するとき、エージェントはテストしたAtari 環境のサンプル上他の Rainbow エージェントと同じように上手く遂行します。

 

メトリクスと評価

ポリシーを評価するために使用される最も一般的なメトリックは平均リターンです。リターンはエピソードのために環境でポリシーを実行する間に得られた報酬の総計です、そして通常はこれを 2, 3 のエピソードに渡り平均します。平均リターンメトリックを次のように計算できます。

def compute_avg_return(environment, policy, num_episodes=10):

  total_return = 0.0
  for _ in range(num_episodes):

    time_step = environment.reset()
    episode_return = 0.0

    while not time_step.is_last():
      action_step = policy.action(time_step)
      time_step = environment.step(action_step.action)
      episode_return += time_step.reward
    total_return += episode_return

  avg_return = total_return / num_episodes
  return avg_return.numpy()[0]


random_policy = random_tf_policy.RandomTFPolicy(train_env.time_step_spec(),
                                                train_env.action_spec())

compute_avg_return(eval_env, random_policy, num_eval_episodes)

# Please also see the metrics module for standard implementations of different

 

データ収集

DQN チュートリアル内のように、再生バッファとランダムポリシーで初期データ収集をセットアップします。

#@test {"skip": true}
replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    data_spec=agent.collect_data_spec,
    batch_size=train_env.batch_size,
    max_length=replay_buffer_capacity)

def collect_step(environment, policy):
  time_step = environment.current_time_step()
  action_step = policy.action(time_step)
  next_time_step = environment.step(action_step.action)
  traj = trajectory.from_transition(time_step, action_step, next_time_step)

  # Add trajectory to the replay buffer
  replay_buffer.add_batch(traj)

for _ in range(initial_collect_steps):
  collect_step(train_env, random_policy)

# This loop is so common in RL, that we provide standard implementations of
# these. For more details see the drivers module.

# Dataset generates trajectories with shape [BxTx...] where
# T = n_step_update + 1.
dataset = replay_buffer.as_dataset(
    num_parallel_calls=3, sample_batch_size=batch_size,
    num_steps=n_step_update + 1).prefetch(3)

iterator = iter(dataset)

 

エージェントを訓練する

訓練ループは環境からデータを集めることとエージェントのネットワークを最適化することの両者を含みます。途中で、上手くやっているかを見るためにエージェントのポリシーを時々評価します。

以下は実行に ~7 分かかります。

#@test {"skip": true}
try:
  %%time
except:
  pass

# (Optional) Optimize by wrapping some of the code in a graph using TF function.
agent.train = common.function(agent.train)

# Reset the train step
agent.train_step_counter.assign(0)

# Evaluate the agent's policy once before training.
avg_return = compute_avg_return(eval_env, agent.policy, num_eval_episodes)
returns = [avg_return]

for _ in range(num_iterations):

  # Collect a few steps using collect_policy and save to the replay buffer.
  for _ in range(collect_steps_per_iteration):
    collect_step(train_env, agent.collect_policy)

  # Sample a batch of data from the buffer and update the agent's network.
  experience, unused_info = next(iterator)
  train_loss = agent.train(experience)

  step = agent.train_step_counter.numpy()

  if step % log_interval == 0:
    print('step = {0}: loss = {1}'.format(step, train_loss.loss))

  if step % eval_interval == 0:
    avg_return = compute_avg_return(eval_env, agent.policy, num_eval_episodes)
    print('step = {0}: Average Return = {1:.2f}'.format(step, avg_return))
    returns.append(avg_return)

 

可視化

プロット

エージェントのパフォーマンスを見るためにリターン vs グローバルステップをプロットすることができます。Cartpole-v1 では、ポールが直立し続ける総ての時間ステップのために環境は +1 の報酬を与え、そしてステップのあ最大数は 500 ですから、最大の可能なリターンもまた 500 です。

#@test {"skip": true}

steps = range(0, num_iterations + 1, eval_interval)
plt.plot(steps, returns)
plt.ylabel('Average Return')
plt.xlabel('Step')
plt.ylim(top=550)

 

ビデオ

各ステップで環境をレンダリングすることによりエージェントのパフォーマンスを可視化することは有用です。それを行なう前に、最初にビデオをこの colab に埋め込む関数を作成しましょう。

def embed_mp4(filename):
  """Embeds an mp4 file in the notebook."""
  video = open(filename,'rb').read()
  b64 = base64.b64encode(video)
  tag = '''
  '''.format(b64.decode())

  return IPython.display.HTML(tag)

以下のコードは 2,3 のエピソードのためにエージェントのポリシーを可視化します :

num_episodes = 3
video_filename = 'imageio.mp4'
with imageio.get_writer(video_filename, fps=60) as video:
  for _ in range(num_episodes):
    time_step = eval_env.reset()
    video.append_data(eval_py_env.render())
    while not time_step.is_last():
      action_step = agent.policy.action(time_step)
      time_step = eval_env.step(action_step.action)
      video.append_data(eval_py_env.render())

embed_mp4(video_filename)

C51 は CartPole-v1 上 DQN よりも僅かに良く行なう傾向がありますが、2 つのエージェントの間の違いはますます複雑な環境で更に更に重要になります。例えば、full Atari 2600 ベンチマーク上、C51 はランダムエージェントに関して正規化後 DQN を越えて 126 % の平均スコア改善を実演します。n-ステップ更新を含むことにより追加の改善が獲得できます。

For a deeper dive into the C51 algorithm, see A Distributional Perspective on Reinforcement Learning (2017).

 

以上






TF-Agents 0.4 : Tutorials : Checkpointer と PolicySaver

TF-Agents 0.4 Tutorials : Checkpointer と PolicySaver (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/23/2020 (0.4)

* 本ページは、TF Agents の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

Checkpointer と PolicySaver

イントロダクション

tf_agents.utils.common.Checkpointer は訓練状態、ポリシー状態と reply_buffer 状態をローカルストレージに/からセーブ/ロードするユティリティです。

tf_agents.policies.policy_saver.PolicySaver はポリシーだけをセーブ/ロードするツールで Checkpointer よりも軽いです。ポリシーを作成したコードのどのような知識なしでもモデルを配備するために PolicySaver を利用できます。

このチュートリアルでは、モデルを訓練するために DQN を使用てから、状態とモデルを対話的にどのようにストアしてロードできるかを示すために Checkpointer と PolicySaver を使用します。PolicySaver のために TF 2.0 の新しい saved_model ツールと形式を使用することに注意してください。

 

セットアップ

以下の依存性をインストールしていないのであれば、以下を実行します :

#@test {"skip": true}
!sudo apt-get install -y xvfb ffmpeg
!pip install 'gym==0.10.11'
!pip install 'imageio==2.4.0'
!pip install 'pyglet==1.3.2'
!pip install 'xvfbwrapper==0.2.9'
!pip install --upgrade tensorflow-probability
!pip install tf-agents
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import base64
import imageio
import io
import matplotlib
import matplotlib.pyplot as plt
import os
import shutil
import tempfile
import tensorflow as tf
import zipfile
import IPython

try:
  from google.colab import files
except ImportError:
  files = None
from tf_agents.agents.dqn import dqn_agent
from tf_agents.drivers import dynamic_step_driver
from tf_agents.environments import suite_gym
from tf_agents.environments import tf_py_environment
from tf_agents.eval import metric_utils
from tf_agents.metrics import tf_metrics
from tf_agents.networks import q_network
from tf_agents.policies import policy_saver
from tf_agents.policies import py_tf_eager_policy
from tf_agents.policies import random_tf_policy
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.trajectories import trajectory
from tf_agents.utils import common

tf.compat.v1.enable_v2_behavior()

tempdir = os.getenv("TEST_TMPDIR", tempfile.gettempdir())
#@test {"skip": true}
# Set up a virtual display for rendering OpenAI gym environments.
import xvfbwrapper
xvfbwrapper.Xvfb(1400, 900, 24).start()

 

DQN エージェント

ちょうど前の colab のように、DQN エージェントをセットアップしていきます。詳細はデフォルトでは隠されます、何故ならばこの colab の中核パートではないからです、しかし詳細を見るために ‘SHOW CODE’ 上をクリックできます。

 

ハイパーパラメータ

env_name = "CartPole-v1"

collect_steps_per_iteration = 100
replay_buffer_capacity = 100000

fc_layer_params = (100,)

batch_size = 64
learning_rate = 1e-3
log_interval = 5

num_eval_episodes = 10
eval_interval = 1000

 

環境

train_py_env = suite_gym.load(env_name)
eval_py_env = suite_gym.load(env_name)

train_env = tf_py_environment.TFPyEnvironment(train_py_env)
eval_env = tf_py_environment.TFPyEnvironment(eval_py_env)

 

エージェント

#@title
q_net = q_network.QNetwork(
    train_env.observation_spec(),
    train_env.action_spec(),
    fc_layer_params=fc_layer_params)

optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate)

global_step = tf.compat.v1.train.get_or_create_global_step()

agent = dqn_agent.DqnAgent(
    train_env.time_step_spec(),
    train_env.action_spec(),
    q_network=q_net,
    optimizer=optimizer,
    td_errors_loss_fn=common.element_wise_squared_loss,
    train_step_counter=global_step)
agent.initialize()

 

データ収集

#@title
replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    data_spec=agent.collect_data_spec,
    batch_size=train_env.batch_size,
    max_length=replay_buffer_capacity)

collect_driver = dynamic_step_driver.DynamicStepDriver(
    train_env,
    agent.collect_policy,
    observers=[replay_buffer.add_batch],
    num_steps=collect_steps_per_iteration)

# Initial data collection
collect_driver.run()

# Dataset generates trajectories with shape [BxTx...] where
# T = n_step_update + 1.
dataset = replay_buffer.as_dataset(
    num_parallel_calls=3, sample_batch_size=batch_size,
    num_steps=2).prefetch(3)

iterator = iter(dataset)

 

エージェントを訓練する

#@title
# (Optional) Optimize by wrapping some of the code in a graph using TF function.
agent.train = common.function(agent.train)

def train_one_iteration():

  # Collect a few steps using collect_policy and save to the replay buffer.
  for _ in range(collect_steps_per_iteration):
    collect_driver.run()

  # Sample a batch of data from the buffer and update the agent's network.
  experience, unused_info = next(iterator)
  train_loss = agent.train(experience)

  iteration = agent.train_step_counter.numpy()
  print ('iteration: {0} loss: {1}'.format(iteration, train_loss.loss))

 

ビデオ生成

#@title
def embed_gif(gif_buffer):
  """Embeds a gif file in the notebook."""
  tag = ''.format(base64.b64encode(gif_buffer).decode())
  return IPython.display.HTML(tag)

def run_episodes_and_create_video(policy, eval_tf_env, eval_py_env):
  num_episodes = 3
  frames = []
  for _ in range(num_episodes):
    time_step = eval_tf_env.reset()
    frames.append(eval_py_env.render())
    while not time_step.is_last():
      action_step = policy.action(time_step)
      time_step = eval_tf_env.step(action_step.action)
      frames.append(eval_py_env.render())
  gif_file = io.BytesIO()
  imageio.mimsave(gif_file, frames, format='gif', fps=60)
  IPython.display.display(embed_gif(gif_file.getvalue()))

 

ビデオを生成する

ビデオを生成することによりポリシーのパフォーマンスを確認する。

print ('global_step:')
print (global_step)
run_episodes_and_create_video(agent.policy, eval_env, eval_py_env)

 

Checkpointer と PolicySaver をセットアップする

今は Checkpointer と PolicySaver を使用する準備ができました。

 

Checkpointer

checkpoint_dir = os.path.join(tempdir, 'checkpoint')
train_checkpointer = common.Checkpointer(
    ckpt_dir=checkpoint_dir,
    max_to_keep=1,
    agent=agent,
    policy=agent.policy,
    replay_buffer=replay_buffer,
    global_step=global_step
)

 

Policy Saver

policy_dir = os.path.join(tempdir, 'policy')
tf_policy_saver = policy_saver.PolicySaver(agent.policy)

 

1 反復訓練する

#@test {"skip": true}
print('Training one iteration....')
train_one_iteration()

 

チェックポイントにセーブする

train_checkpointer.save(global_step)

 

チェックポイントをリストアする

これが動作するするためには、オブジェクトのセット全体がチェックポイントが作成されたときと同じ方法で再作成されるべきです。

train_checkpointer.initialize_or_restore()
global_step = tf.compat.v1.train.get_global_step()

ポリシーもセーブして位置にエクスポートします。

tf_policy_saver.save(policy_dir)

ポリシーは、それを作成するために何のエージェントやネットワークが使用されたかのどのような知識も持つことなくロードできます。これはポリシーの配備を遥かに容易にします。

セーブされたポリシーをロードしてそれがどのように遂行するか確認します。

saved_policy = tf.compat.v2.saved_model.load(policy_dir)
run_episodes_and_create_video(saved_policy, eval_env, eval_py_env)

 

Export と import

colab の残りは、後の時点で訓練をで続けてそして再度訓練しなければならないことなくモデルを配備できるように checkpointer とポリシー・ディレクトリを export / import するに役立つでしょう。

今は「1 反復を訓練する」に戻って後で差異を理解できるように更に 2, 3 回訓練することができます。僅かばかりより良い結果をひとたび見始めるのであれば、以下を続けてください。

#@title Create zip file and upload zip file (double-click to see the code)
def create_zip_file(dirname, base_filename):
  return shutil.make_archive(base_filename, 'zip', dirname)

def upload_and_unzip_file_to(dirname):
  if files is None:
    return
  uploaded = files.upload()
  for fn in uploaded.keys():
    print('User uploaded file "{name}" with length {length} bytes'.format(
        name=fn, length=len(uploaded[fn])))
    shutil.rmtree(dirname)
    zip_files = zipfile.ZipFile(io.BytesIO(uploaded[fn]), 'r')
    zip_files.extractall(dirname)
    zip_files.close()

チェックポイント・ディレクトリから zip されたファイルを作成します。

train_checkpointer.save(global_step)
checkpoint_zip_filename = create_zip_file(checkpoint_dir, os.path.join(tempdir, 'exported_cp'))

zip ファイルをダウンロードします。

#@test {"skip": true}
if files is not None:
  files.download(checkpoint_zip_filename) # try again if this fails: https://github.com/googlecolab/colabtools/issues/469

ある程度の時間 (10-15 回) の間訓練した後、チェックポイント zip ファイルをダウンロードして、そして訓練をリセットするために “Runtime > Restart and run all” に行き、そしてこのセルに戻ります。今はダウンロードされた zip ファイルをアップロードして訓練を続けることができます。

#@test {"skip": true}
upload_and_unzip_file_to(checkpoint_dir)
train_checkpointer.initialize_or_restore()
global_step = tf.compat.v1.train.get_global_step()

ひとたびチェックポイント・ディレクトリをアップロードしたら、訓練を続けるために「1 反復を訓練する」に戻るかロードされたポリシーのパフォーマンスを確認するために「ビデオを生成する」に戻ります。

代わりに、ポリシー (モデル) をセーブしてそれをリストアできます。checkpointer とは違い、訓練を続けることはできませんが、依然としてモデルを配備できます。ダウンロードされたファイルは checkpointer のそれよりも遥かに小さいことに注意してください。

tf_policy_saver.save(policy_dir)
policy_zip_filename = create_zip_file(policy_dir, os.path.join(tempdir, 'exported_policy'))
#@test {"skip": true}
if files is not None:
  files.download(policy_zip_filename) # try again if this fails: https://github.com/googlecolab/colabtools/issues/469

ダウンロードされたポリシー・ディレクトリ (exported_policy.zip) をアップロードしてセーブされたポリシーがどのように遂行するかを確認します。

#@test {"skip": true}
upload_and_unzip_file_to(policy_dir)
saved_policy = tf.compat.v2.saved_model.load(policy_dir)
run_episodes_and_create_video(saved_policy, eval_env, eval_py_env)

 

SavedModelPyTFEagerPolicy

TF ポリシーを使用することを望まない場合、py_tf_eager_policy.SavedModelPyTFEagerPolicy の利用を通して Python env で saved_model を直接使用することもできます。

これは eager mode が有効であるときに限り動作するだけであることに注意してください。

eager_py_policy = py_tf_eager_policy.SavedModelPyTFEagerPolicy(
    policy_dir, eval_py_env.time_step_spec(), eval_py_env.action_spec())

# Note that we're passing eval_py_env not eval_env.
run_episodes_and_create_video(eager_py_policy, eval_py_env, eval_py_env)
 

以上






TF-Agents 0.4 : Tutorials : ネットワーク

TF-Agents 0.4 Tutorials : ネットワーク (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/22/2020 (0.4)

* 本ページは、TF Agents の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

ネットワーク

イントロダクション

この colab では貴方のエージェントのためにどのようにカスタム・ネットワークを定義するかをカバーします。ネットワークはエージェントにより訓練されるモデルを定義することを手助けします。TF-Agents では幾つかの異なるタイプのネットワークを見つけるでしょう、これらはエージェントに渡り有用です :

 
主要ネットワーク

  • QNetwork: 離散アクションを持つ環境のために Qlearning で使用されます、このネットワークは観測を各々の可能なアクションのための値推定にマップします。
  • CriticNetworks: 文献では ValueNetworks としても参照されます、ある状態をポリシーの期待リターンのための推定にマップする価値 (Value) 関数のあるバージョンを推定するために学習します。これらのネットワークはエージェントが現在在る状態がどれほど良いかを推定します。
  • ActorNetworks: 観測からアクションへのマッピングを学習します。これらのネットワークは通常はアクションを生成するためにポリシーにより使用されます。
  • ActorDistributionNetworks: ActorNetworks に類似していますが、これらはポリシーがアクションを生成するためにサンプリングできる分布を生成します。

 
Helper ネットワーク

  • EncodingNetwork: ネットワークの入力に適用する前処理層のマッピングを容易に定義することをユーザに可能にします。
  • DynamicUnrollLayer:それが時間シークエンスに渡り適用されるときエピソード境界上でネットワークの状態を自動的にリセットします。
  • ProjectionNetwork: CategoricalProjectionNetwork or NormalProjectionNetwork のようなネットワークは入力を取りカテゴリカル or 正規分布を生成するために必要なパラメータを生成します。

TF-Agents の総てのサンプルは事前構成されたネットワークを装備しています。けれどもこれらのネットワークは複雑な観測を処理するためにセットアップされていません。

一つの観測/アクションより多くを公開する環境を持ちネットワークをカスタマイズする必要がある場合には、このチュートリアルは貴方のためです!

 

セットアップ

tf-agents をまだインストールしてないのであれば、以下を実行します :

!pip install --upgrade tensorflow_probability
!pip install tf-agents
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import abc
import tensorflow as tf
import numpy as np

from tf_agents.environments import random_py_environment
from tf_agents.environments import tf_py_environment
from tf_agents.networks import encoding_network
from tf_agents.networks import network
from tf_agents.networks import utils
from tf_agents.specs import array_spec
from tf_agents.utils import common as common_utils
from tf_agents.utils import nest_utils

tf.compat.v1.enable_v2_behavior()

 

ネットワークを定義する

Network API

TF-Agents では Keras ネットワーク からサブクラス化します。それで以下が可能です :

  • ターゲットネットワークを作成するとき必要な copy 演算を単純化する。
  • network.variables() を呼び出すとき自動変数作成を遂行する。
  • ネットワーク input_specs に基づいて入力を検証する。

 

EncodingNetwork

上で言及したように EncodingNetwork はあるエンコーディングを生成するためにネットワークの入力に適用する前処理層のマッピングを容易に定義することを可能にします。

EncodingNetwork は以下の殆どオプションの層から成ります :

  • 前処理層
  • 前処理 combiner
  • Conv2D
  • Flatten
  • Dense

encoding ネットワークの特別なことは入力前処理が適用されることです。入力前処理は preprocessing_layers と preprocessing_combiner 層を通して可能です。これらの各々はネストされた構造として指定できます。もし preprocessing_layers ネストが input_tensor_spec よりも浅い場合、層はサブネストを得ます。例えば、

if :
    input_tensor_spec = ([TensorSpec(3)] * 2, [TensorSpec(3)] * 5)
    preprocessing_layers = (Layer1(), Layer2())

then 前処理は次を呼び出します :
    preprocessed = [preprocessing_layers[0](observations[0]),
                preprocessing_layers[1](obsrevations[1])]

けれども if
    preprocessing_layers = ([Layer1() for _ in range(2)],
                        [Layer2() for _ in range(5)])

then 前処理は次を呼び出します :
    preprocessed = [
      layer(obs) for layer, obs in zip(flatten(preprocessing_layers),
                                    flatten(observations))
    ]

 

カスタムネットワーク

貴方自身のネットワークを作成するためには __init__ と call メソッドを override しなければならないだけです。画像とベクトルを含む観測を取る ActorNetwork を作成するため EncodingNetworks について学習したことを使用してカスタムネットワークを作成しましょう。

class ActorNetwork(network.Network):

  def __init__(self,
               observation_spec,
               action_spec,
               preprocessing_layers=None,
               preprocessing_combiner=None,
               conv_layer_params=None,
               fc_layer_params=(75, 40),
               dropout_layer_params=None,
               activation_fn=tf.keras.activations.relu,
               enable_last_layer_zero_initializer=False,
               name='ActorNetwork'):
    super(ActorNetwork, self).__init__(
        input_tensor_spec=observation_spec, state_spec=(), name=name)

    # For simplicity we will only support a single action float output.
    self._action_spec = action_spec
    flat_action_spec = tf.nest.flatten(action_spec)
    if len(flat_action_spec) > 1:
      raise ValueError('Only a single action is supported by this network')
    self._single_action_spec = flat_action_spec[0]
    if self._single_action_spec.dtype not in [tf.float32, tf.float64]:
      raise ValueError('Only float actions are supported by this network.')

    kernel_initializer = tf.keras.initializers.VarianceScaling(
        scale=1. / 3., mode='fan_in', distribution='uniform')
    self._encoder = encoding_network.EncodingNetwork(
        observation_spec,
        preprocessing_layers=preprocessing_layers,
        preprocessing_combiner=preprocessing_combiner,
        conv_layer_params=conv_layer_params,
        fc_layer_params=fc_layer_params,
        dropout_layer_params=dropout_layer_params,
        activation_fn=activation_fn,
        kernel_initializer=kernel_initializer,
        batch_squash=False)

    initializer = tf.keras.initializers.RandomUniform(
        minval=-0.003, maxval=0.003)

    self._action_projection_layer = tf.keras.layers.Dense(
        flat_action_spec[0].shape.num_elements(),
        activation=tf.keras.activations.tanh,
        kernel_initializer=initializer,
        name='action')

  def call(self, observations, step_type=(), network_state=()):
    outer_rank = nest_utils.get_outer_rank(observations, self.input_tensor_spec)
    # We use batch_squash here in case the observations have a time sequence
    # compoment.
    batch_squash = utils.BatchSquash(outer_rank)
    observations = tf.nest.map_structure(batch_squash.flatten, observations)

    state, network_state = self._encoder(
        observations, step_type=step_type, network_state=network_state)
    actions = self._action_projection_layer(state)
    actions = common_utils.scale_to_spec(actions, self._single_action_spec)
    actions = batch_squash.unflatten(actions)
    return tf.nest.pack_sequence_as(self._action_spec, [actions]), network_state

構造化観測を生成して実装を確認するために RandomPyEnvironment を作成しましょう。

action_spec = array_spec.BoundedArraySpec((3,), np.float32, minimum=0, maximum=10)
observation_spec =  {
    'image': array_spec.BoundedArraySpec((16, 16, 3), np.float32, minimum=0,
                                        maximum=255),
    'vector': array_spec.BoundedArraySpec((5,), np.float32, minimum=-100,
                                          maximum=100)}

random_env = random_py_environment.RandomPyEnvironment(observation_spec, action_spec=action_spec)

# Convert the environment to a TFEnv to generate tensors.
tf_env = tf_py_environment.TFPyEnvironment(random_env)

観測を辞書として定義しましたので、これらを処理するために前処理層を作成する必要があります。

preprocessing_layers = {
    'image': tf.keras.models.Sequential([tf.keras.layers.Conv2D(8, 4),
                                        tf.keras.layers.Flatten()]),
    'vector': tf.keras.layers.Dense(5)
    }
preprocessing_combiner = tf.keras.layers.Concatenate(axis=-1)
actor = ActorNetwork(tf_env.observation_spec(), 
                     tf_env.action_spec(),
                     preprocessing_layers=preprocessing_layers,
                     preprocessing_combiner=preprocessing_combiner)

actor ネットワークを持つ今、環境からの観測を処理できます。

time_step = tf_env.reset()
actor(time_step.observation, time_step.step_type)

エージェントに使用される任意の主要ネットワークをカスタマイズするために同じストラテジーが使用できます。前処理が何であろうと定義してそれをネットワークの残りに接続できます。貴方自身のカスタムを定義するときネットワークの出力層定義が適合することを確実にしてください。

 

以上






AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com