天天看點

訓練時第二個step loss特别大_RLlib訓練APIs

在高層RLlib提供了Trainer類,他keep一個policy用于和環境互動。通過trainer接口,policy可以訓練,儲存,或者用于動作的計算。在多智能體訓練中,trainer同時管理多個政策的查詢和優化。

訓練時第二個step loss特别大_RLlib訓練APIs

你能使用下述指令訓練一個DQN:

rllib train --run DQN --env CartPole-v0
           

結果會預設儲存到子目錄~/ray_results。這個子目錄包含檔案

params.json(用于儲存超參數),

{

"env": "CartPole-v0"

}

檔案result.json(包含了每個episode的訓練資料)

{"episode_reward_max": 49.0, "episode_reward_min": 8.0, "episode_reward_mean": 20.74736842105263, "episode_len_mean": 20.74736842105263, "episodes_this_iter": 190, "policy_reward_mean": {}, "custom_metrics": {}, "sampler_perf": {"mean_env_wait_ms": 0.06072526728229897, "mean_processing_ms": 0.15717214266133053, "mean_inference_ms": 0.7396685669186922}, "off_policy_estimator": {}, "info": {"num_steps_trained": 3968, "num_steps_sampled": 4000, "sample_time_ms": 2006.434, "load_time_ms": 46.28, "grad_time_ms": 1630.859, "update_time_ms": 476.545, "learner": {"default_policy": {"cur_kl_coeff": 0.20000000298023224, "cur_lr": 4.999999873689376e-05, "total_loss": 64.50533294677734, "policy_loss": -0.03904179856181145, "vf_loss": 64.53799438476562, "vf_explained_var": 0.042524512857198715, "kl": 0.03189465031027794, "entropy": 0.6628726124763489, "entropy_coeff": 0.0}}}, "timesteps_this_iter": 4000, "done": false, "timesteps_total": 4000, "episodes_total": 190, "training_iteration": 1, "experiment_id": "78133ebfb69b4d1590b42716371ad75d", "date": "2019-08-24_15-16-13", "timestamp": 1566630973, "time_this_iter_s": 4.203403949737549, "time_total_s": 4.203403949737549, "pid": 3569, "hostname": "yang-XPS-15-9570", "node_ip": "183.173.87.224", "config": {"monitor": false, "log_level": "INFO", "callbacks": {"on_episode_start": null, "on_episode_step": null, "on_episode_end": null, "on_sample_end": null, "on_train_result": null, "on_postprocess_traj": null}, "ignore_worker_failures": false, "log_sys_usage": true, "model": {"conv_filters": null, "conv_activation": "relu", "fcnet_activation": "tanh", "fcnet_hiddens": [256, 256], "free_log_std": false, "no_final_linear": false, "vf_share_layers": true, "use_lstm": false, "max_seq_len": 20, "lstm_cell_size": 256, "lstm_use_prev_action_reward": false, "state_shape": null, "framestack": true, "dim": 84, "grayscale": false, "zero_mean": true, "custom_preprocessor": null, "custom_model": null, "custom_options": {}}, "optimizer": {}, "gamma": 0.99, "horizon": null, "soft_horizon": false, "env_config": {}, "env": "CartPole-v0", "clip_rewards": null, "clip_actions": true, "preprocessor_pref": "deepmind", "lr": 5e-05, "evaluation_interval": null, "evaluation_num_episodes": 10, "evaluation_config": {}, "num_workers": 2, "num_gpus": 0, "num_cpus_per_worker": 1, "num_gpus_per_worker": 0, "custom_resources_per_worker": {}, "num_cpus_for_driver": 1, "num_envs_per_worker": 1, "sample_batch_size": 200, "train_batch_size": 4000, "batch_mode": "truncate_episodes", "sample_async": false, "observation_filter": "NoFilter", "synchronize_filters": true, "tf_session_args": {"intra_op_parallelism_threads": 2, "inter_op_parallelism_threads": 2, "gpu_options": {"allow_growth": true}, "log_device_placement": false, "device_count": {"CPU": 1}, "allow_soft_placement": true}, "local_tf_session_args": {"intra_op_parallelism_threads": 8, "inter_op_parallelism_threads": 8}, "compress_observations": false, "collect_metrics_timeout": 180, "metrics_smoothing_episodes": 100, "remote_worker_envs": false, "remote_env_batch_wait_ms": 0, "min_iter_time_s": 0, "timesteps_per_iteration": 0, "seed": null, "input": "sampler", "input_evaluation": ["is", "wis"], "postprocess_inputs": false, "shuffle_buffer_size": 0, "output": null, "output_compress_columns": ["obs", "new_obs"], "output_max_file_size": 67108864, "multiagent": {"policies": {}, "policy_mapping_fn": null, "policies_to_train": null}, "use_gae": true, "lambda": 1.0, "kl_coeff": 0.2, "sgd_minibatch_size": 128, "shuffle_sequences": true, "num_sgd_iter": 30, "lr_schedule": null, "vf_share_layers": false, "vf_loss_coeff": 1.0, "entropy_coeff": 0.0, "entropy_coeff_schedule": null, "clip_param": 0.3, "vf_clip_param": 10.0, "grad_clip": null, "kl_target": 0.01, "simple_optimizer": false}, "time_since_restore": 4.203403949737549, "timesteps_since_restore": 4000, "iterations_since_restore": 1, "num_healthy_workers": 2, "trial_id": "09c8ad76"}

以及一個用于可視化訓練過程的TensorBoard檔案。

rllib train指令有許多選項,可自行檢視

rllib train --help
           

最重要的選項是使用--env選擇環境(任何gym的環境以及使用者自定義gym環境),以及使用--run選擇算法(可用選項包括SAC,PPO,PG,A2C,A3C,IMPALA,ES,DDPG,DQN,MARWIL,APEX,APEX_DDPG)。

評估訓練政策

為了儲存checkpoints,當運作rilib train時設定--checkpoint-freq(兩次儲存之間的訓練疊代次數)

評估以前訓練得到的DQN政策:

rllib rollout 
    ~/ray_results/default/DQN_CartPole-vo_0upjmdgr0/checkpoint_1/checkpoint-1 
    --run DQN --env CartPole-vo --steps 10000
           

rollout.py将從位于~/ray_results/default/DQN_CartPole-vo_0upjmdgr0/checkpoint_1/checkpoint-1的政策重建DQN網絡并渲染。

配置

指定參數

除了一堆common超參,每個算法都有特定的超參數,可以通過--config來設定。

如下我們指定A2C使用8個worker,

rllib train --env=PongDeterministic-v4 --run=A2C --config '{"num_workers": 8}'
           

指定資源

對大多數算法,可通過設定num_workers來指定并行程度。gpu資源可通過num_gpus選項設定。同樣配置設定到worker的資源可通過num_cpus_per_worker,num_gpus_per_worker和custom_resources_per_worker來設定。GPU的數量可以是小數以配置設定GPU的一部分。

訓練時第二個step loss特别大_RLlib訓練APIs

Common參數

COMMON_CONFIG = {
    # === 用于調試 ===
    # 是否向log檔案夾寫入episode狀态和視訊
    "monitor": False,

    # 為agnet和workers設定ray.rllib.*的log等級
    # 應該為DEBUG,INFO,WARN,ERROR其中之一。 DEBUG 等級将會
    # 定期列印内部資料流的相關資訊 (這也是INFO等級在一開始會列印的).
    "log_level": "INFO",

    # 訓練不同階段的回調函數。這些函數将會把單一的info作為參數,對于episode回調,我們可更新
    # episode對象的自定義度量字典,進而将自定義的度量名額能夠附加在episode上,你還能改變回
    # 調中傳入的批處理資料
    "callbacks": {
        "on_episode_start": None,     # arg: {"env": .., "episode": ...}
        "on_episode_step": None,      # arg: {"env": .., "episode": ...}
        "on_episode_end": None,       # arg: {"env": .., "episode": ...}
        "on_sample_end": None,        # arg: {"samples": .., "worker": ...}
        "on_train_result": None,      # arg: {"trainer": ..., "result": ...}
        "on_postprocess_traj": None,  # arg: {
                                      #   "agent_id": ..., "episode": ...,
                                      #   "pre_batch": (before processing),
                                      #   "post_batch": (after processing),
                                      #   "all_pre_batches": (other agent ids),
                                      # }
    },

    # 如果一個worker失敗,是否繼續
    "ignore_worker_failures": False,

    # log系統資源利情況
    "log_sys_usage": True,

    # 開啟TF eager
    "eager": False,

    # === 政策 ===
    # 傳入模型的參數,model/catalog.py中說明了全部參數
    "model": MODEL_DEFAULTS,

    # 傳入優化器的參數. 随優化器而邊
    "optimizer": {},

    # === 環境 ===
    # MDP折扣因子
    "gamma": 0.99,

    # 一個episode的最大步數。預設為gym環境的env.spec.max_episode_steps。
    "horizon": None,

    # 計算reward但是當步數達到horizon的時候不reset環境,這使得我們可以做value estimation
    # 而且可以将RNN狀态在多個episode之間擴充。這個參數當horizon不為無窮時才有用。
    "soft_horizon": False,

    # 在episode結束的時候不設定done. 注意如果soft_horizon=True,你還是要設定done的,除非
    # 你的環境可以持續運作而不用重設
    "no_done_at_end": False,

    # 傳給env creator的參數
    "env_config": {},

    # 環境的名字
    "env": None,

    # 是否在後處理時進行reward截斷,設定為None則隻對Atari環境做reward clip
    "clip_rewards": None,

    # 是否将動作截斷在定義的動作空間高低區間上
    "clip_actions": True,

    # 是否預設使用rllib或者deepmind的預處理
    "preprocessor_pref": "deepmind",

    # 預設的學習率
    "lr": 0.0001,

    # === 評估 ===
    # 每 `evaluation_interval` 個訓練疊代次數進行評估。
    # 評估的資訊包含在“evaluation”度量鍵中
    # 目前評估不支援并行
    # Apex的度量隻對其中一個worker進行。
    "evaluation_interval": None,

    # 每次評估運作的episode數量
    "evaluation_num_episodes": 10,

    # 要傳給評估worker的其他參數
    # 典型的用法是傳入用于評估的env creator的參數
    # 以及通過計算确定性動作關閉探索
    # TODO(kismuz): implement determ. actions and include relevant keys hints
    "evaluation_config": {},

    # === 資源 ===
    # 用于并行的actor個數
    "num_workers": 2,

    # 配置設定給訓練過程的GPU資源. 不是所有算法都能利用GPU的,可以是小數(如0.3)
    "num_gpus": 0,

    # 配置設定給每個worker的CPU數量
    "num_cpus_per_worker": 1,

    # 配置設定給每個worker的GPU數量
    "num_gpus_per_worker": 0,

    # 配置設定給每個worker的自定義資源
    "custom_resources_per_worker": {},

    # 配置設定給trainer的CPU數量。注意:隻有大那該在Tune中運作時才有效
    "num_cpus_for_driver": 1,

    # === 記憶體配額 ===
    # 可通過設定這些配額來告訴ray為你的訓練保留這些記憶體,這保證了順利的運作,
    # 代價是如果你的工作負荷超過配額就會失敗

    # 為訓練程序保留的堆記憶體(0代表無限)
    # 這可以很大如果你用大的batch,replay buffer等
    "memory": 0,

    # 為訓練程序保留的對象存儲空間. Being large
    # 足夠容納幾份模型權重的拷貝即可
    # 預設開啟,因為模型一般都很小.
    "object_store_memory": 0,

    # 為每個worker保留的堆記憶體
    # 一般來說小一點就好,除非你的環境很占記憶體
    "memory_per_worker": 0,

    # 為每個worker保留的對象存儲空間
    # 大到一次容納幾個sample batch就足夠
    # 預設開啟,因為一般超不過200M
    "object_store_memory_per_worker": 0,

    # === 執行 ===
    # 每個worker的環境數量
    "num_envs_per_worker": 1,

    # 預設sample batch大小. 這樣大小的batch不斷從workers收集
    # 直到滿足train_batch_size,如果一個worker用多個環境
    # 需要乘一個num_envs_per_worker
    "sample_batch_size": 200,

    # 用于訓練的batch size, 應該 >= sample_batch_size.
    # Samples batches将會級聯成這個大小用于訓練
    "train_batch_size": 200,

    # 是否展開 "complete_episodes" or "truncate_episodes"
    "batch_mode": "truncate_episodes",

    # 使用背景線程用于采樣 (因為不同步,輕微off-policy, 不建議打開
    # 除非你的環境要求)
    "sample_async": False,

    # 逐元素的observation過濾器, "NoFilter" 或者 "MeanStdFilter"
    "observation_filter": "NoFilter",

    # 是否同步remote過濾器的資料.
    "synchronize_filters": True,

    # 預設配置單程序tf op
    "tf_session_args": {
        # note: overriden by `local_tf_session_args`
        "intra_op_parallelism_threads": 2,
        "inter_op_parallelism_threads": 2,
        "gpu_options": {
            "allow_growth": True,
        },
        "log_device_placement": False,
        "device_count": {
            "CPU": 1
        },
        "allow_soft_placement": True,  # required by PPO multi-gpu
    },

    # 過載local worker的tf session參數
    "local_tf_session_args": {
        # 預設允許更高程度的并行,但是有限制
        # 因為那會造成多個并發dirver的沖突
        "intra_op_parallelism_threads": 8,
        "inter_op_parallelism_threads": 8,
    },

    # 是否用LZ4壓縮單個observation
    "compress_observations": False,

    # 等待metric batches的最大時間(s). 沒有按時傳回的資料将在下一輪疊代中收集
    "collect_metrics_timeout": 180,

    # 在這樣數量的episode下做度量平滑
    "metrics_smoothing_episodes": 100,

    # 如果num_envs_per_worker > 1, 是否在remote程序中建立這些env而不是在worker中
    # 這增加了通信開支, 但如果你的環境用很多時間step/reset(如星際争霸),這就很合理
    # 謹慎使用,overheads很重要
    "remote_worker_envs": False,

    # 和環境互動擷取batch時remote worker的等待時間
    # 0 (當至少一個環境準備好後繼續) 是一個合理的選擇,
    # 但最優值需要測量環境的step/reset,以及model推斷時間獲得
    "remote_env_batch_wait_ms": 0,

    # 每次疊代的最少時間
    "min_iter_time_s": 0,

    # 每次train call最小的環境的步數
    # 這個值不影響訓練效果,隻影響每次疊代的長度
    "timesteps_per_iteration": 0,

    # 這個參數和 worker_index, 用來設定每個worker的随機種子
    # 這樣相同的配置下就會有相同的結果
    # 這使得實驗可以複現
    "seed": None,

    # === 離線資料集 ===
    # 用于指定如何産生經驗:
    #  - "sampler": 通過線上仿真産生經驗 (預設)
    #  - 一個局部路徑或者全局檔案表達形式 (如, "/tmp/*.json")
    #  - 檔案路徑或url的清單 (如, ["/tmp/1.json", "s3://bucket/2.json"])
    #  - 一個使用字元串為鍵和采樣機率為值的字典 (如,
    #    {"sampler": 0.4, "/tmp/*.json": 0.4, "s3://bucket/expert.json": 0.2}).
    #  - 一個傳回rllib.offline.InputReader的函數
    "input": "sampler",

    # 用于指定如何評估目前政策. 僅當讀取離線經驗時有效
    # 可用選項:
    #  - "wis": 權重重要性采樣估計.
    #  - "is": 重要性采樣估計.
    #  - "simulation": 背景運作環境,但僅用于評估不用于學習
    "input_evaluation": ["is", "wis"],

    # 是否在離線輸入的軌迹片段上運作後處理trajectory()
    # 注意後處理将用目前政策而不是行為政策,對于on-policy算法這是不行的
    "postprocess_inputs": False,

    # 如果設定為正數, 将會通過一個這樣數量batch的滑窗buffer将輸入batch打亂
    # 如果輸入資料順序不夠随機,就使用這個選項
    # 直到這個buffer填滿,才會進行輸入
    "shuffle_buffer_size": 0,

    # 指定經驗儲存的地方:
    #  - None: 不儲存任何經驗
    #  - "logdir":儲存在agent的log目錄下
    #  - 或者自定義任何路徑/url (如, "s3://bucket/")
    #  - 一個傳回rllib.offline.OutputWriter的函數
    "output": None,

    # 指定壓縮為LZ4的sample batch columns
    "output_compress_columns": ["obs", "new_obs"],

    # 最大輸出檔案大小
    "output_max_file_size": 64 * 1024 * 1024,

    # === 多智能體 ===
    "multiagent": {
        # 從政策id到元祖 (policy_cls, obs_space,
        # act_space, config)的映射. See rollout_worker.py for more info.
        "policies": {},
        # 從agent id到policy id
        "policy_mapping_fn": None,
        # 有選擇的選擇要訓練的政策
        "policies_to_train": None,
    },
}
           

Tuned例子

rllib train -f /path/to/tuned/example.yaml
           

Python API

python api提供了必要的靈活性,他可以用來自定義環境,預處理器,以及模型。

基本例子

import 
           
注意:建議使用Tune運作rllib trainer,這樣可以使得實驗管理更簡單,并且可以可視化訓練過程。 隻需要在實驗config中設定"run": ALG_NAME, "env": ENV_NAME

所有RLlib trainer都和Tune API相容,如下的代碼展示了一個簡單的ppo超參數sweep。

import ray
from ray import tune

ray.init()
tune.run(
    "PPO",
    stop={"episode_reward_mean": 200},
    config={
        "env": "CartPole-v0",
        "num_gpus": 0,
        "num_workers": 1,
        "lr": tune.grid_search([0.01, 0.001, 0.0001]),
        "eager": False,
    },
)
           

Tune将會并行的在叢集上訓練.

== Status ==

Using FIFO scheduling algorithm.

Resources requested: 2/12 CPUs, 0/1 GPUs

Memory usage on this node: 5.1/33.3 GB

Result logdir: /home/yang/ray_results/PPO

Number of trials: 3 ({'TERMINATED': 2, 'RUNNING': 1})

RUNNING trials:

- PPO_CartPole-v0_1_lr=0.001: RUNNING, [2 CPUs, 0 GPUs], [pid=4478], 173 s, 39 iter, 156000 ts, 194 rew

TERMINATED trials:

- PPO_CartPole-v0_0_lr=0.01: TERMINATED, [2 CPUs, 0 GPUs], [pid=4482], 120 s, 24 iter, 96000 ts, 200 rew

- PPO_CartPole-v0_2_lr=0.0001: TERMINATED, [2 CPUs, 0 GPUs], [pid=4476], 70 s, 13 iter, 52000 ts, 200 rew

自定義訓練工作流

預設的,Tune會在每一次疊代調用trainer上的train()并且報告新的訓練結果。但有時我們需要自定義訓練流。Tune也支援自定義訓練函數,主要有兩個API,一個python類API,一個python函數API。對更加細化的訓練控制,就可以直接用RLlib的底層API(如policy,optimizer,evaluator等)來寫。

"""Example of a custom training workflow. Run this for a demo.
This example shows:
  - using Tune trainable functions to implement custom training workflows
You can visualize experiment results in ~/ray_results using TensorBoard.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import ray
from ray import tune
from ray.rllib.agents.ppo import PPOTrainer


def my_train_fn(config, reporter):
    # Train for 100 iterations with high LR
    agent1 = PPOTrainer(env="CartPole-v0", config=config)
    for _ in range(10):
        result = agent1.train()
        result["phase"] = 1
        reporter(**result)
        phase1_time = result["timesteps_total"]
    state = agent1.save()
    agent1.stop()

    # Train for 100 iterations with low LR
    config["lr"] = 0.0001
    agent2 = PPOTrainer(env="CartPole-v0", config=config)
    agent2.restore(state)
    for _ in range(10):
        result = agent2.train()
        result["phase"] = 2
        result["timesteps_total"] += phase1_time  # keep time moving forward
        reporter(**result)
    agent2.stop()


if __name__ == "__main__":
    ray.init()
    config = {
        "lr": 0.01,
        "num_workers": 0,
    }
    resources = PPOTrainer.default_resource_request(config).to_json()
    tune.run(my_train_fn, resources_per_trial=resources, config=config)
           

擷取Policy狀态

我們一般需要擷取trainer的内部狀态,如需要設定或擷取内部權重。在RLlib中,trainer的state是在rollout workers之間複制存在的。你可以在調用train()方法的中間通過調用trainer.workers.foreach_worker()或者trainer.workers.foreach_worker_with_index()來擷取和更新這些狀态。這些方法的參數是一個用于worker的lambda函數,這個函數可以傳回值,最後将以清單的形式傳回。

也可以不用拿每個worker的狀态而隻擷取其中一個主要的copy,trainer.get_policy()或者trainer.workers.local_worker()。

# 擷取本地policy權重
trainer.get_policy().get_weights()

# 同上
trainer.workers.local_worker().policy_map["default_policy"].get_weights()

# 擷取每個worker的權重,包括remote的replicas
trainer.workers.foreach_worker(lambda ev: ev.get_policy().get_weights())

# 同上
trainer.workers.foreach_worker_with_index(lambda ev, i: ev.get_policy().get_weights())
           

全局統籌

有時需要協調不同程序中的代碼,比如我們有時需要維持一個變量的全局平均,或者集中控制一個policy的超參數。Ray通過named actor這個東西來實作。舉個例子,比如我們現在需要維持一個全局計數器,這個計數器通過環境遞增,并定期從驅動程式中讀取。

from ray.experimental import named_actors

@ray.remote
class Counter:
   def __init__(self):
      self.count = 0
   def inc(self, n):
      self.count += n
   def get(self):
      return self.count

# on the driver
counter = Counter.remote()
named_actors.register_actor("global_counter", counter)
print(ray.get(counter.get.remote()))  # get the latest count

# in your envs
counter = named_actors.get_actor("global_counter")
counter.inc.remote(1)  # async call to increment the global count
           

Ray的actor有着很強的靈活性,它能夠實作如ps和allreduce這樣的通信模式。

回調和自定義度量

可以自定義用于policy evaluation過程的回調函數。這些回調函數将目前episode的狀态的字典作為參數。自定義的狀态量可以存儲在info["episode"].user_data字典中,自定義的整數度量可以存儲在info["episode"].custom_metrics字典中。這些自定義的度量将會作為訓練結果的一部分。下列代碼從環境中log了自定義的度量。

def on_episode_start(info):
    print(info.keys())  # -> "env", 'episode"
    episode = info["episode"]
    print("episode {} started".format(episode.episode_id))
    episode.user_data["pole_angles"] = []

def on_episode_step(info):
    episode = info["episode"]
    pole_angle = abs(episode.last_observation_for()[2])
    episode.user_data["pole_angles"].append(pole_angle)

def on_episode_end(info):
    episode = info["episode"]
    pole_angle = np.mean(episode.user_data["pole_angles"])
    print("episode {} ended with length {} and pole angles {}".format(
        episode.episode_id, episode.length, pole_angle))
    episode.custom_metrics["pole_angle"] = pole_angle

def on_train_result(info):
    print("trainer.train() result: {} -> {} episodes".format(
        info["trainer"].__name__, info["result"]["episodes_this_iter"]))

ray.init()
analysis = tune.run(
    "PG",
    config={
        "env": "CartPole-v0",
        "callbacks": {
            "on_episode_start": tune.function(on_episode_start),
            "on_episode_step": tune.function(on_episode_step),
            "on_episode_end": tune.function(on_episode_end),
            "on_train_result": tune.function(on_train_result),
        },
    },
)
           

自定義的度量同樣可以在tensorboard中可視化

訓練時第二個step loss特别大_RLlib訓練APIs

例子:課程學習

來看使用上述API實作課程學習的兩種方式。在課程學習中,agent的任務随着學習過程不斷調整,假設我們的環境類中有set_phase()方法,其可以随時間調節任務難度。

方法一:使用Trainer API在train()之間更新環境,以下例子展示了trainer在Tune函數中的運作。

import ray
from ray import tune
from ray.rllib.agents.ppo import PPOTrainer

def train(config, reporter):
    trainer = PPOTrainer(config=config, env=YourEnv)
    while True:
        result = trainer.train()
        reporter(**result)
        if result["episode_reward_mean"] > 200:
            phase = 2
        elif result["episode_reward_mean"] > 100:
            phase = 1
        else:
            phase = 0
        trainer.workers.foreach_worker(
            lambda ev: ev.foreach_env(
                lambda env: env.set_phase(phase)))

ray.init()
tune.run(
    train,
    config={
        "num_gpus": 0,
        "num_workers": 2,
    },
    resources_per_trial={
        "cpu": 1,
        "gpu": lambda spec: spec.config.num_gpus,
        "extra_cpu": lambda spec: spec.config.num_workers,
    },
)
           

方法二,使用回調函數

import ray
from ray import tune

def on_train_result(info):
    result = info["result"]
    if result["episode_reward_mean"] > 200:
        phase = 2
    elif result["episode_reward_mean"] > 100:
        phase = 1
    else:
        phase = 0
    trainer = info["trainer"]
    trainer.workers.foreach_worker(
        lambda ev: ev.foreach_env(
            lambda env: env.set_phase(phase)))

ray.init()
tune.run(
    "PPO",
    config={
        "env": YourEnv,
        "callbacks": {
            "on_train_result": tune.function(on_train_result),
        },
    },
)
           

調試

Gym Monitor

rllib train --env=PongDeterministic-v4 
    --run=A2C --config '{"num_workers": 2, "monitor": true}'

# videos will be saved in the ~/ray_results/<experiment> dir, for example
openaigym.video.0.31401.video000000.meta.json
openaigym.video.0.31401.video000000.mp4
openaigym.video.0.31403.video000000.meta.json
openaigym.video.0.31403.video000000.mp4
           

Tensorflow eager

使用build_tf_policy建構的政策可以通過設定"eager": True或者使用rllib train --eager使用eager模式運作。

Eager模式更友善調試,因為可以使用print來列印出tensor的值。

Episode Traces

可通過資料輸出API儲存episode資訊用于調試,如下代碼會将episode資訊存入/tmp/debug

rllib train --run=PPO --env=CartPole-v0 
    --config='{"output": "/tmp/debug", "output_compress_columns": []}'

# episode traces will be saved in /tmp/debug, for example
output-2019-02-23_12-02-03_worker-2_0.json
output-2019-02-23_12-02-04_worker-1_0.json
           

Log verbosity

可以通過"log_level"控制訓練log記錄等級。 有INFO DEBUG WARN ERROR幾種選擇,

rllib train --env=PongDeterministic-v4 
    --run=A2C --config '{"num_workers": 2, "log_level": "DEBUG"}'
           

REST API

在有些情況下(如與一個外部simulator或者生産環境互動時),不适合用RLlib包裹這個simulator,而要通過RLlib的外部agent接口。

訓練時第二個step loss特别大_RLlib訓練APIs
訓練時第二個step loss特别大_RLlib訓練APIs

例子

>>> class CartpoleServing(ExternalEnv):
       def __init__(self):
           ExternalEnv.__init__(
               self, spaces.Discrete(2),
               spaces.Box(
                   low=-10,
                   high=10,
                   shape=(4,),
                   dtype=np.float32))
       def run(self):
           server = PolicyServer(self, "localhost", 8900)
           server.serve_forever()
>>> register_env("srv", lambda _: CartpoleServing())
>>> pg = PGTrainer(env="srv", config={"num_workers": 0})
>>> while True:
        pg.train()
           
>>> client = PolicyClient("localhost:8900")
>>> eps_id = client.start_episode()
>>> action = client.get_action(eps_id, obs)
>>> ...
>>> client.log_returns(eps_id, reward)
>>> ...
>>> client.log_returns(eps_id, reward)
           

完整client例子

完整server例子