我正在创建自定义DeMorgan's laws,类似于gym environment或this trading one。正在设置自定义环境,以使用this soccer one来训练PPO强化学习模型。
我的问题是,批量更新之间的时间(逐步通过环境和收集奖励所花费的时间)花费的时间越来越长,并且每次更新线性扩展大约1-5秒。刚开始时,这是有道理的,因为未经训练的特工很快就会“死亡”(done=True
,所以这一集结束了)。随着特工训练,它应该生存更长的时间,直到它开始生存整个情节,并且两次更新之间的时间应该达到稳定。但是,即使经过数百次更新(数百集,环境中成千上万个连续步骤),两次更新之间的时间仍在增加。我已经监视了培训,可以看到该代理在大约50次更新中幸存下来。
起初,我认为环境中的某些变量可能会持续存在并且在两次更新之间变得非常大,从而减慢了计算时间。但是,当我在训练期间监视内存使用情况时,它在整个过程中保持不变。考虑到环境应该重置每个情节(并将所有列表变量初始化为空),从理论上讲,增加变量的大小不是问题。
已经说过,也许我没有将数据正确地传递到MyCustomEnv
中。当我将整个训练数据集读入内存(1e6
个样本)时,我希望每次发作只将一批stable-baselines传递给环境,但是我可能是错的(我已经设定了n_steps=1024
,这是批次/情节中的步骤数)。下面是一个最小的代码示例。
# myenv.py
import gym
from gym import spaces
import numpy as np
from sklearn.preprocessing import MinMaxScaler
class MyCustomEnv(gym.Env):
def __init__(self, data):
super().__init__()
self.data = data # numpy array, shape = (1e6, 5)
self.observation_space = spaces.Box(low=0., high=1., shape=(1, self.data.shape[1]), dtype=np.float32)
self.action_space = spaces.Discrete(4) # 4 actions - see ACTION_LOOKUP below
def _take_action(self, action):
my_action = ACTION_LOOKUP[action]
tmp = do_action(my_action) # this is a simple function not shown, it returns a float
self.my_list.append(tmp)
def _done(self):
if current_step = self.data.shape[1] - 1:
return True
if died(): # another simple function not shown that just checks a running variable
return True
return False
def _next_observation(self):
obs = MinMaxScaler().fit_transform(self.data)[-1] # last row of numpy array data, scaled
return obs
def _reward(self):
reward = get_reward(self.my_list)
return reward
def step(self, action):
self._take_action(action)
self.current_step += 1
obs = self._next_observation()
reward = self._reward()
done = self._done()
return obs, reward, done, {}
def reset(self):
self.current_step = 0
self.my_list = []
ACTION_LOOKUP = {
0 : "LEFT"
1 : "RIGHT"
2 : "UP"
3 : "DOWN"
}
然后在我的main
脚本中实例化环境时
# main.py
import pandas as pd
from stable_baselines.common.vec_env import DummyVecEnv
from stable_baselines.common.policies import MlpLstmPolicy
from stable_baselines import PPO2
from myenv import MyCustomEnv
if __name__ == "__main__":
data = pd.read_csv("my_data.csv").values # numpy array
train_env = DummyVecEnv([lambda: MyCustomEnv(data)])
model = PPO2(MlpLstmPolicy, train_env, verbose=1)
model.learn(total_timesteps=int(1e6))
我在这里做错什么会导致两次更新之间的时间永远增加吗?自定义n_steps
环境似乎不会将数据传递到该环境中,因此也许有一种更好的方法可以让代理逐步通过静态训练数据环境。