이 페이지는 Cloud Translation API를 통해 번역되었습니다.
Switch to English

SAC 미니어처

저작권 2018 TF- 에이전트 저자.

TensorFlow.org에서보기 Google Colab에서 실행 GitHub에서 소스보기 노트북 다운로드

소개

이 예는 TF-Agents 라이브러리를 사용하여 Minitaur 환경에서 Soft Actor Critic 에이전트를 훈련시키는 방법을 보여줍니다.

DQN Colab을 통해 작업했다면 매우 친숙 할 것입니다. 주목할만한 변경 사항은 다음과 같습니다.

  • 에이전트를 DQN에서 SAC로 변경
  • CartPole보다 훨씬 복잡한 환경 인 Minitaur에 대한 교육 Minitaur 환경은 앞으로 나아갈 수 있도록 사중 로봇을 훈련시키는 것을 목표로합니다.
  • 초기 데이터 수집을 수행하기 위해 임의의 정책을 사용하지 않습니다.

다음 종속성을 설치하지 않은 경우 다음을 실행하십시오.

sudo apt-get install -y xvfb ffmpeg
pip install -q 'gym==0.10.11'
pip install -q 'imageio==2.4.0'
pip install -q matplotlib
pip install -q PILLOW
pip install -q --pre tf-agents[reverb]
pip install -q 'pybullet==2.4.2'



ffmpeg is already the newest version (7:3.4.8-0ubuntu0.2).
xvfb is already the newest version (2:1.19.6-1ubuntu4.4).
The following packages were automatically installed and are no longer required:
  dconf-gsettings-backend dconf-service dkms freeglut3 freeglut3-dev
  glib-networking glib-networking-common glib-networking-services
  gsettings-desktop-schemas libcairo-gobject2 libcolord2 libdconf1
  libegl1-mesa libepoxy0 libglu1-mesa libglu1-mesa-dev libgtk-3-0
  libgtk-3-common libice-dev libjansson4 libjson-glib-1.0-0
  libjson-glib-1.0-common libproxy1v5 librest-0.7-0 libsm-dev
  libsoup-gnome2.4-1 libsoup2.4-1 libxi-dev libxmu-dev libxmu-headers
  libxnvctrl0 libxt-dev linux-gcp-headers-5.0.0-1026
  linux-headers-5.0.0-1026-gcp linux-image-5.0.0-1026-gcp
  linux-modules-5.0.0-1026-gcp pkg-config policykit-1-gnome python3-xkit
  screen-resolution-extra xserver-xorg-core-hwe-18.04
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 90 not upgraded.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.

설정

먼저 필요한 다른 도구를 가져오고 Colab 전체의 Eager 모드에서 더 쉽게 반복 할 수 있으므로 TF-V2 동작을 활성화해야합니다.

 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 tensorflow as tf
tf.compat.v1.enable_v2_behavior()

from tf_agents.agents.ddpg import critic_network
from tf_agents.agents.sac import sac_agent
from tf_agents.drivers import dynamic_step_driver
from tf_agents.environments import suite_pybullet
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 actor_distribution_network
from tf_agents.networks import normal_projection_network
from tf_agents.policies import greedy_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

 

하이퍼 파라미터

 env_name = "MinitaurBulletEnv-v0" # @param {type:"string"}

# use "num_iterations = 1e6" for better results,
# 1e5 is just so this doesn't take too long. 
num_iterations = 100000 # @param {type:"integer"}

initial_collect_steps = 10000 # @param {type:"integer"} 
collect_steps_per_iteration = 1 # @param {type:"integer"}
replay_buffer_capacity = 1000000 # @param {type:"integer"}

batch_size = 256 # @param {type:"integer"}

critic_learning_rate = 3e-4 # @param {type:"number"}
actor_learning_rate = 3e-4 # @param {type:"number"}
alpha_learning_rate = 3e-4 # @param {type:"number"}
target_update_tau = 0.005 # @param {type:"number"}
target_update_period = 1 # @param {type:"number"}
gamma = 0.99 # @param {type:"number"}
reward_scale_factor = 1.0 # @param {type:"number"}
gradient_clipping = None # @param

actor_fc_layer_params = (256, 256)
critic_joint_fc_layer_params = (256, 256)

log_interval = 5000 # @param {type:"integer"}

num_eval_episodes = 30 # @param {type:"integer"}
eval_interval = 10000 # @param {type:"integer"}
 

환경

RL의 환경은 우리가 해결하려는 작업 또는 문제를 나타냅니다. suites 사용하여 TF-Agent에서 표준 환경을 쉽게 작성할 수 있습니다. 우리는 문자열 환경 이름이 주어지면 OpenAI Gym, Atari, DM Control 등과 같은 소스에서 환경을로드하기위한 다른 suites 을 가지고 있습니다.

이제 Pybullet Suite에서 Minituar 환경을로드하겠습니다.

 env = suite_pybullet.load(env_name)
env.reset()
PIL.Image.fromarray(env.render())
 
current_dir=/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/pybullet_envs/bullet
urdf_root=/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/pybullet_data
options= 

/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/gym/logger.py:30: UserWarning: WARN: gym.spaces.Box autodetected dtype as <class 'numpy.float32'>. Please provide explicit dtype.
  warnings.warn(colorize('%s: %s'%('WARN', msg % args), 'yellow'))

png

이 환경의 목표는 에이전트가 Minitaur 로봇을 제어하고 가능한 빨리 진행하도록하는 정책을 교육하는 것입니다. 에피소드는 지난 1000 단계이며, 수익은 에피소드 전체의 보상의 합입니다.

정책이 actions 를 생성하는 데 사용할 observation 정보로 환경이 제공하는 정보를 살펴 보자.

 print('Observation Spec:')
print(env.time_step_spec().observation)
print('Action Spec:')
print(env.action_spec())
 
Observation Spec:
BoundedArraySpec(shape=(28,), dtype=dtype('float32'), name='observation', minimum=[  -3.1515927   -3.1515927   -3.1515927   -3.1515927   -3.1515927
   -3.1515927   -3.1515927   -3.1515927 -167.72488   -167.72488
 -167.72488   -167.72488   -167.72488   -167.72488   -167.72488
 -167.72488     -5.71        -5.71        -5.71        -5.71
   -5.71        -5.71        -5.71        -5.71        -1.01
   -1.01        -1.01        -1.01     ], maximum=[  3.1515927   3.1515927   3.1515927   3.1515927   3.1515927   3.1515927
   3.1515927   3.1515927 167.72488   167.72488   167.72488   167.72488
 167.72488   167.72488   167.72488   167.72488     5.71        5.71
   5.71        5.71        5.71        5.71        5.71        5.71
   1.01        1.01        1.01        1.01     ])
Action Spec:
BoundedArraySpec(shape=(8,), dtype=dtype('float32'), name='action', minimum=-1.0, maximum=1.0)

우리가 볼 수 있듯이 관측은 상당히 복잡합니다. 모든 모터의 각도, 속도 및 토크를 나타내는 28 개의 값을받습니다. 그 대가로 환경은 [-1, 1] 사이의 동작에 대해 8 개의 값을 예상합니다. 원하는 모터 각도입니다.

일반적으로 교육용 환경과 평가 환경의 두 가지 환경을 만듭니다. 대부분의 환경은 순수한 파이썬으로 작성되었지만 TFPyEnvironment 랩퍼를 사용하여 TensorFlow로 쉽게 변환 할 수 있습니다. 원래 환경의 API는 NumPy와 배열을 사용의 TFPyEnvironment 에서 / 이러한 변환 Tensors TensorFlow 정책 및 에이전트와 더 쉽게 상호 작용하는 당신을 위해.

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

train_env = tf_py_environment.TFPyEnvironment(train_py_env)
eval_env = tf_py_environment.TFPyEnvironment(eval_py_env)
 
urdf_root=/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/pybullet_data
options= 
urdf_root=/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/pybullet_data
options= 

에이전트

SAC 에이전트를 만들려면 먼저 훈련 할 네트워크를 만들어야합니다. SAC는 행위자 비평가 에이전트이므로 두 개의 네트워크가 필요합니다.

비평가는 우리에게 Q(s,a) 대한 가치 추정치를 제공 할 것입니다. 즉, 그것은 관찰과 행동을 입력으로받을 것이며, 주어진 상태에 대해 그 행동이 얼마나 좋은지를 추정 할 것입니다.

 observation_spec = train_env.observation_spec()
action_spec = train_env.action_spec()
critic_net = critic_network.CriticNetwork(
    (observation_spec, action_spec),
    observation_fc_layer_params=None,
    action_fc_layer_params=None,
    joint_fc_layer_params=critic_joint_fc_layer_params)
 

우리는이 비평가를 사용하여 actor 네트워크를 훈련시켜 관찰 한 액션을 생성 할 수 있습니다.

ActorNetwork 는 정규 분포에 대한 ActorNetwork 를 예측합니다. 그런 다음이 분포는 동작을 생성해야 할 때마다 현재 관측치에 따라 샘플링됩니다.

 def normal_projection_net(action_spec,init_means_output_factor=0.1):
  return normal_projection_network.NormalProjectionNetwork(
      action_spec,
      mean_transform=None,
      state_dependent_std=True,
      init_means_output_factor=init_means_output_factor,
      std_transform=sac_agent.std_clip_transform,
      scale_distribution=True)


actor_net = actor_distribution_network.ActorDistributionNetwork(
    observation_spec,
    action_spec,
    fc_layer_params=actor_fc_layer_params,
    continuous_projection_net=normal_projection_net)
 

이러한 네트워크를 통해 에이전트를 인스턴스화 할 수 있습니다.

 global_step = tf.compat.v1.train.get_or_create_global_step()
tf_agent = sac_agent.SacAgent(
    train_env.time_step_spec(),
    action_spec,
    actor_network=actor_net,
    critic_network=critic_net,
    actor_optimizer=tf.compat.v1.train.AdamOptimizer(
        learning_rate=actor_learning_rate),
    critic_optimizer=tf.compat.v1.train.AdamOptimizer(
        learning_rate=critic_learning_rate),
    alpha_optimizer=tf.compat.v1.train.AdamOptimizer(
        learning_rate=alpha_learning_rate),
    target_update_tau=target_update_tau,
    target_update_period=target_update_period,
    td_errors_loss_fn=tf.compat.v1.losses.mean_squared_error,
    gamma=gamma,
    reward_scale_factor=reward_scale_factor,
    gradient_clipping=gradient_clipping,
    train_step_counter=global_step)
tf_agent.initialize()
 

정책

TF-에이전트에서 정책 RL에 정책의 기본 개념을 나타냅니다 : 주어진 time_step 동작이나 행동에 걸쳐 분포를 생산하고 있습니다. 주요 방법은 policy_step = policy.step(time_step) 여기서 policy_step 은 명명 된 튜플 PolicyStep(action, state, info) 입니다. policy_step.action 은 환경에 적용되는 action 이며, state 는 상태 저장 (RNN) 정책에 대한 state 나타내며 info 는 조치의 로그 확률과 같은 보조 정보를 포함 할 수 있습니다.

에이전트에는 기본 정책 (agent.policy)과 데이터 수집에 사용되는 동작 정책 (agent.collect_policy)의 두 가지 정책이 있습니다. 평가 / 배포를 위해 기본 정책을 GreedyPolicy ()로 래핑하여 평균 조치를 취합니다.

 eval_policy = greedy_policy.GreedyPolicy(tf_agent.policy)
collect_policy = tf_agent.collect_policy
 

측정 항목 및 평가

정책을 평가하는 데 사용되는 가장 일반적인 지표는 평균 수익입니다. 수익률은 에피소드 환경에서 정책을 실행하는 동안 얻은 보상의 합계이며 일반적으로 몇 에피소드에서 평균을냅니다. 다음과 같이 평균 수익 측정 항목을 계산할 수 있습니다.

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

  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]


compute_avg_return(eval_env, eval_policy, num_eval_episodes)

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

재생 버퍼

환경에서 수집 된 데이터를 추적하기 위해 TFUniformReplayBuffer를 사용합니다. 이 재생 버퍼는 저장 될 텐서를 설명하는 스펙을 사용하여 구성되며, tf_agent.collect_data_spec 사용하여 에이전트에서 얻을 수 있습니다.

 replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    data_spec=tf_agent.collect_data_spec,
    batch_size=train_env.batch_size,
    max_length=replay_buffer_capacity)
 

대부분의 에이전트에서 collect_data_spec 은 관찰, 동작, 보상 등을 포함하는 tuple이라는 Trajectory .

데이터 수집

이제 재생 버퍼를 시드 할 경험을 수집하는 드라이버를 만듭니다. 드라이버 collecter의 간단한 방법으로 우리를 제공하는 n 특정 정책을 사용하는 환경에서 단계 또는 에피소드.

 initial_collect_driver = dynamic_step_driver.DynamicStepDriver(
        train_env,
        collect_policy,
        observers=[replay_buffer.add_batch],
        num_steps=initial_collect_steps)
initial_collect_driver.run()
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tf_agents/drivers/dynamic_step_driver.py:203: calling while_loop_v2 (from tensorflow.python.ops.control_flow_ops) with back_prop=False is deprecated and will be removed in a future version.
Instructions for updating:
back_prop=False is deprecated. Consider using tf.stop_gradient instead.
Instead of:
results = tf.while_loop(c, b, vars, back_prop=False)
Use:
results = tf.nest.map_structure(tf.stop_gradient, tf.while_loop(c, b, vars))

(TimeStep(step_type=<tf.Tensor: shape=(1,), dtype=int32, numpy=array([1], dtype=int32)>, reward=<tf.Tensor: shape=(1,), dtype=float32, numpy=array([0.00101085], dtype=float32)>, discount=<tf.Tensor: shape=(1,), dtype=float32, numpy=array([1.], dtype=float32)>, observation=<tf.Tensor: shape=(1, 28), dtype=float32, numpy=
 array([[  1.308478  ,   2.166422  ,   1.5081352 ,   2.0260656 ,
           2.1123457 ,   1.114552  ,   1.5866141 ,   1.524472  ,
           6.9441314 ,   6.6945276 ,  -7.403659  , -20.185253  ,
          -4.8489103 ,  -1.2003611 , -19.449749  , -16.223652  ,
           4.2634044 ,   0.371617  ,  -0.92654324,  -3.8810008 ,
          -5.7       ,   3.10348   ,  -2.9569836 ,   3.916052  ,
           0.0551226 ,   0.10631521,  -0.09753982,   0.9880003 ]],
       dtype=float32)>),
 ())

재생 버퍼에서 데이터를 샘플링하기 위해 나중에 훈련을 위해 에이전트에 공급할 수있는 tf.data 파이프 라인을 만듭니다. sample_batch_size 를 지정하여 재생 버퍼에서 샘플링 된 항목 수를 구성 할 수 있습니다. 병렬 호출과 프리 페치를 사용하여 데이터 파이프 라인을 최적화 할 수도 있습니다.

공간을 절약하기 위해 현재 관측 값을 재생 버퍼의 각 행에만 저장합니다. 그러나 SAC 에이전트는 손실을 계산하기 위해 현재 및 다음 관측치가 모두 필요하므로 num_steps=2 를 설정하여 배치의 각 항목에 대해 두 개의 인접한 행을 항상 샘플링합니다.

 # Dataset generates trajectories with shape [Bx2x...]
dataset = replay_buffer.as_dataset(
    num_parallel_calls=3, sample_batch_size=batch_size, num_steps=2).prefetch(3)

iterator = iter(dataset)
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/autograph/operators/control_flow.py:1004: ReplayBuffer.get_next (from tf_agents.replay_buffers.replay_buffer) is deprecated and will be removed in a future version.
Instructions for updating:
Use `as_dataset(..., single_deterministic_pass=False) instead.

에이전트 훈련

교육 과정에는 환경에서 데이터를 수집하고 에이전트의 네트워크를 최적화하는 것이 포함됩니다. 그 과정에서 에이전트의 정책을 평가하여 상황을 파악할 수 있습니다.

 collect_driver = dynamic_step_driver.DynamicStepDriver(
    train_env,
    collect_policy,
    observers=[replay_buffer.add_batch],
    num_steps=collect_steps_per_iteration)
 
 
try:
  %%time
except:
  pass

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

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

# Evaluate the agent's policy once before training.
avg_return = compute_avg_return(eval_env, eval_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.
  collect_driver.run()

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

  step = tf_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, eval_policy, num_eval_episodes)
    print('step = {0}: Average Return = {1}'.format(step, avg_return))
    returns.append(avg_return)
 
WARNING:absl:Need to use a loss function that computes losses per sample, ex: replace losses.mean_squared_error with tf.math.squared_difference. Invalid value passed for `per_example_loss`. Expected a tensor tensor with at least rank 1, received: Tensor("critic_loss/add_1:0", shape=(), dtype=float32)
WARNING:absl:Need to use a loss function that computes losses per sample, ex: replace losses.mean_squared_error with tf.math.squared_difference. Invalid value passed for `per_example_loss`. Expected a tensor tensor with at least rank 1, received: Tensor("critic_loss/add_1:0", shape=(), dtype=float32)

step = 5000: loss = -63.16588592529297
step = 10000: loss = -61.471351623535156
step = 10000: Average Return = 0.07441557198762894
step = 15000: loss = -31.185678482055664
step = 20000: loss = -18.064279556274414
step = 20000: Average Return = -0.12959735095500946
step = 25000: loss = -15.05502986907959
step = 30000: loss = -12.023421287536621
step = 30000: Average Return = -1.4209648370742798
step = 35000: loss = -5.994253635406494
step = 40000: loss = -3.944823741912842
step = 40000: Average Return = -0.6664859652519226
step = 45000: loss = 0.3637888431549072
step = 50000: loss = -3.2982077598571777
step = 50000: Average Return = 0.0521695651113987
step = 55000: loss = -2.7744715213775635
step = 60000: loss = 1.7074693441390991
step = 60000: Average Return = -0.3222312033176422
step = 65000: loss = -1.8334136009216309
step = 70000: loss = -1.4784929752349854
step = 70000: Average Return = 0.6373701095581055
step = 75000: loss = 0.48983949422836304
step = 80000: loss = 1.5974589586257935
step = 80000: Average Return = 0.1859637051820755
step = 85000: loss = -5.309885501861572
step = 90000: loss = 0.42465153336524963
step = 90000: Average Return = 0.8508636951446533
step = 95000: loss = -6.7512335777282715
step = 100000: loss = 1.8088481426239014
step = 100000: Average Return = 0.24124357104301453

심상

줄거리

상담원의 성과를 확인하기 위해 평균 수익 대 글로벌 단계를 플로팅 할 수 있습니다. Minitaur 에서 보상 기능은 미니 타우 어가 1000 걸음으로 얼마나 멀리 걸으며 에너지 소비에 불이익을 주는지를 기준으로합니다.

 

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

png

비디오

각 단계에서 환경을 렌더링하여 에이전트의 성능을 시각화하는 것이 도움이됩니다. 이를 수행하기 전에 먼저이 Colab에 비디오를 포함하는 함수를 작성하겠습니다.

 def embed_mp4(filename):
  """Embeds an mp4 file in the notebook."""
  video = open(filename,'rb').read()
  b64 = base64.b64encode(video)
  tag = '''
  <video width="640" height="480" controls>
    <source src="data:video/mp4;base64,{0}" type="video/mp4">
  Your browser does not support the video tag.
  </video>'''.format(b64.decode())

  return IPython.display.HTML(tag)
 

다음 코드는 몇 가지 에피소드에 대한 에이전트 정책을 시각화합니다.

 num_episodes = 3
video_filename = 'sac_minitaur.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 = tf_agent.policy.action(time_step)
      time_step = eval_env.step(action_step.action)
      video.append_data(eval_py_env.render())

embed_mp4(video_filename)