基础

这段代码,可以看到一个倒立摆在胡乱操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import gym

env_name = "CartPole-v0"
env = gym.make(env_name) # 导入环境

episodes = 10
for episode in range(1, episodes + 1):
state = env.reset()
done = False
score = 0

while not done:
env.render() # 渲染环境
action = env.action_space.sample() # 随机采样动作
n_state, reward, done, info = env.step(action) # 和环境交互,得到下一个状态,奖励等信息
score += reward # 计算分数
print("Episode : {}, Score : {}".format(episode, score))

env.close() # 关闭窗口

用Stable_baseline3来训练的强化学习模型,可以很好地控制这个环境:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from stable_baselines3 import DQN
from stable_baselines3.common.vec_env.dummy_vec_env import DummyVecEnv
from stable_baselines3.common.evaluation import evaluate_policy
import gym

env_name = "CartPole-v0"
env = gym.make(env_name)
# 把环境向量化,如果有多个环境写成列表传入DummyVecEnv中,可以用一个线程来执行多个环境,提高训练效率
env = DummyVecEnv([lambda : env])
# 定义一个DQN模型,设置其中的各个参数
model = DQN(
"MlpPolicy", # MlpPolicy定义策略网络为MLP网络
env=env,
learning_rate=5e-4,
batch_size=128,
buffer_size=50000,
learning_starts=0,
target_update_interval=250,
policy_kwargs={"net_arch" : [256, 256]}, # 这里代表隐藏层为2层256个节点数的网络
verbose=1, # verbose=1代表打印训练信息,如果是0为不打印,2为打印调试信息
tensorboard_log="./tensorboard/CartPole-v0/" # 训练数据保存目录,可以用tensorboard查看
)
# 开始训练
model.learn(total_timesteps=1e5)
# 策略评估,可以看到倒立摆在平稳运行了
mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=10, render=true)
#env.close()
print("mean_reward:",mean_reward,"std_reward:",std_reward)
# 保存模型到相应的目录
model.save("./model/CartPole.pkl")

自定义环境

需要继承gym.Env类,然后重新其中的方法,配置一定的参数即可,格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import gym
from gym import spaces

class CustomEnv(gym.Env):
"""Custom Environment that follows gym interface"""
metadata = {'render.modes': ['human']}

def __init__(self, arg1, arg2, ...):
super(CustomEnv, self).__init__()
# Define action and observation space
# They must be gym.spaces objects
# Example when using discrete actions:
self.action_space = spaces.Discrete(N_DISCRETE_ACTIONS)
# Example for using image as input (channel-first; channel-last also works):
self.observation_space = spaces.Box(low=0, high=255,
shape=(N_CHANNELS, HEIGHT, WIDTH), dtype=np.uint8)

def step(self, action):
...
return observation, reward, done, info
def reset(self):
...
return observation # reward, done, info can't be included
def render(self, mode='human'):
...
def close (self):
pass

主要三个函数需要实现:

reset() 在每个回合最开始时执行,返回当前的观测(observation)

step(action) 输入 action,智能体执行 action 与环境交互,返回获得的(新的观测、奖励、是否结束、其他)

可选render(method=’human’)` 渲染环境

Read more »

1
2
https://github.com/eleurent/highway-env
https://github.com/MCZhi/Driving-IRL-NGSIM/blob/main/NGSIM_env/envs/ngsim_env.py

1301,3725,511,1118847351400,20.428,717.996,6451628.438,1872868.223,11,4.5,2,31.39,-10.61,2,NA,NA,NA,NA,NA,NA,1289,1304,51.13,1.63,us-101

NGSIM数据集包含四个不同的场景:US-101、I-80、Lankershim与Peachtree。US-101与I-80记录了车辆在高速公路上的行驶轨迹,Lankershim与Peachtree记录了车辆在城市道路上的行驶轨迹

字段名 描述
Vehicle_Id 车辆识别号(根据进入该区域的时间升序),可重复利用。
Frame_Id 该条数据在某一时刻的帧(按开始时间升序),同一Vehicle_ID的帧号不会重复。
Total_Frame 该车出现在此数据集的总帧数。
Global_Time 时间戳(ms)。
Local_X 车辆前部中心的横向(X)坐标,以英尺为单位,相对于截面在行驶方向上的最左侧边缘。
Local_Y 车辆前部中心的纵向(Y)坐标,以英尺为单位,相对于截面在行驶方向上的相对于路段入口的纵向边缘。
Local_X,Local_Y 采集区域内的坐标,采集区域不同,坐标系不同,会有不同的零点。
Global_X, Global_Y 全局坐标,只有一个零点,可用作数据筛选(以英尺为单位)。
v_length 车辆长度(以英尺为单位)。
v_Width 车辆宽度(以英尺为单位)。
v_Class 车辆类型:1-摩托车,2-汽车,3-卡车。
v_Vel 车辆瞬时速度,以英尺/秒为单位。
v_Acc 车辆的瞬时加速度,以英尺/秒平方为单位。
Lane_ID 车辆的当前车道位置。 第1车道是最左边的车道,第5车道是最右边的车道。
O_Zone 车辆的起点区域,即车辆进入跟踪系统的位置。 研究区域有11个起源,编号从101到111。有关更多详细信息,请参阅数据分析报告。
D_Zone 车辆的目的地区域,即车辆离开跟踪系统的地方。 研究区域中有10个目的地,从201到211编号。起点102是单向出口,因此,没有关联的目标号码202。请参阅数据分析报告以获取更多详细信息。
Int_ID 车辆行驶的路口。 交叉点的编号为1到4,交叉点1位于最南端,交叉点4位于研究区域的最北端。 值为“ 0”表示该车辆不在交叉路口的附近,而是该车辆标识为Lankershim Boulevard的一段(下面的Section_ID)。请参阅数据分析报告以获取更多详细信息。
Section_ID 车辆行驶的路段。 Lankershim Blvd分为五个部分(路口1的南部;路口1和2、2和3、3和4之间;路口4的北部)。 值为0表示该车辆未识别出Lankershim Boulevard的一段,并且该车辆紧邻交叉路口(上述Int_ID)。 请参阅数据分析报告以获取更多详细信息。
Direction 车辆的行驶方向。 1-东行(EB),2-北行(NB),3-西行(WB),4-南行(SB)。
Movement 车辆的运动。 1-通过(TH),2-左转(LT),3-右转(RT)。
Preceding 同道前车的车辆编号。数值为0表示没有前面的车辆-发生在研究段的末尾和出匝道。
Following 在同一车道上跟随本车辆的车辆的车辆ID。 值0表示没有跟随的车辆-在研究部分的开头和匝道发生。
Space_Headway 间距提供了车辆的前中心到前一辆车辆的前中心之间的距离(英尺)。
Time_Headway 时间进度(以秒为单位)提供了从车辆的前中心(以车辆的速度)行进到前一辆车辆的前中心的时间。
Location 街道名称或高速公路名称。
    v_Vel  v_Acc  Lane_ID     x_prime    y_prime  v_Class  Space_Headway

id
10_436 43.82 -1.59 1 93.445584 -1.861718 2 0.00
12_443 35.26 4.49 1 77.581354 -1.745590 2 52.05
13_432 39.48 6.21 2 100.954027 -5.892089 2 98.13
14_515 36.66 -11.20 5 106.701336 -15.726461 3 0.00
18_291 41.14 0.15 5 78.375053 -15.703906 2 92.93
20_414 40.01 0.00 3 61.464749 -8.023250 2 123.13
21_439 43.55 7.14 4 85.675927 -11.882628 2 82.24
22_441 34.92 0.09 2 80.107841 -5.302910 2 68.39
23_438 37.55 0.00 1 61.004501 -1.665427 2 54.39
25_436 44.98 0.00 4 55.262678 -11.570208 2 99.78
26_438 34.99 0.00 2 65.094002 -4.779874 2 49.26
27_432 40.00 0.00 1 34.377782 -1.819046 2 87.36
2_437 44.99 0.00 2 130.865270 -5.408676 2 0.00
31_465 35.02 -0.23 5 60.066326 -15.641117 2 60.07
32_438 34.41 -1.74 2 50.624842 -4.710684 2 47.47
34_451 40.01 0.28 4 37.907366 -11.704015 2 56.94
35_280 31.20 -2.39 5 43.132858 -16.138246 2 55.56
39_450 41.50 0.02 1 21.973032 -0.281026 2 40.70
40_391 43.69 -10.63 4 20.277430 -12.428220 2 57.84
47_428 40.00 0.00 3 14.348765 -8.414309 2 154.58
48_507 35.08 -1.87 5 32.537400 -15.481097 2 34.76
5_452 38.55 0.00 4 129.526284 -12.498629 2 0.00
8_448 39.97 0.09 4 110.742070 -12.588850 2 61.63
9_409 45.88 -6.52 3 98.994163 -8.774887 2 0.00

image-20230314102459825

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def test_make_data_loader():
"""Tests data loader produces same results for same input in different formats."""
trajs = [
types.Trajectory(
obs=np.array([0, 1]),
acts=np.array([100]),
infos=None,
terminal=True,
),
types.Trajectory(
obs=np.array([4, 5, 6]),
acts=np.array([102, 103]),
infos=None,
terminal=True,
),
types.Trajectory(
obs=np.array([10, 11, 12, 13]),
acts=np.array([104, 105, 106]),
infos=None,
terminal=False,
),
]
trans = types.Transitions(
obs=np.array([0, 4, 5, 10, 11, 12]),
acts=np.array([100, 102, 103, 104, 105, 106]),
next_obs=np.array([1, 5, 6, 11, 12, 13]),
dones=np.array([True, False, True, False, False, False]),
infos=np.array([{}] * 6),
)
trans_mapping = [
{
"obs": np.array([0, 4]),
"acts": np.array([100, 102]),
"next_obs": np.array([1, 5]),
"dones": np.array([True, False]),
"infos": np.array([{}, {}]),
},
{
"obs": np.array([5, 10]),
"acts": np.array([103, 104]),
"next_obs": np.array([6, 11]),
"dones": np.array([True, False]),
"infos": np.array([{}, {}]),
},
{
"obs": np.array([11, 12]),
"acts": np.array([105, 106]),
"next_obs": np.array([12, 13]),
"dones": np.array([False]),
"infos": np.array([{}, {}]),
},
]

for data in [trajs, trans, trans_mapping]:
data_loader = base.make_data_loader(
data,
batch_size=2,
data_loader_kwargs=dict(shuffle=False, drop_last=False),
)
for batch, expected_batch in zip(data_loader, trans_mapping):
assert batch.keys() == expected_batch.keys()
for k in batch.keys():
v = batch[k]
if isinstance(v, th.Tensor):
v = v.numpy()
assert np.all(v == expected_batch[k])

  1. Of course you don’t have to generate the demonstrations. This is just done in the examples to make them more self-contained. You can pass your trajectories as a sequence of imitation.data.types.Trajectory to GAIL/AIRL.
Read more »

1
from a2c_ppo_acktr.algo import gail
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import copy
import glob
import os
import time
from collections import deque

import gym
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

from a2c_ppo_acktr import algo, utils
from a2c_ppo_acktr.algo import gail
from a2c_ppo_acktr.arguments import get_args
from a2c_ppo_acktr.envs import make_vec_envs
from a2c_ppo_acktr.model import Policy
from a2c_ppo_acktr.storage import RolloutStorage
from evaluation import evaluate


def main():
args = get_args()

torch.manual_seed(args.seed)
torch.cuda.manual_seed_all(args.seed)

if args.cuda and torch.cuda.is_available() and args.cuda_deterministic:
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True

log_dir = os.path.expanduser(args.log_dir)
eval_log_dir = log_dir + "_eval"
utils.cleanup_log_dir(log_dir)
utils.cleanup_log_dir(eval_log_dir)

torch.set_num_threads(1)
device = torch.device("cuda:0" if args.cuda else "cpu")

envs = make_vec_envs(args.env_name, args.seed, args.num_processes,
args.gamma, args.log_dir, device, False)

actor_critic = Policy(
envs.observation_space.shape,
envs.action_space,
base_kwargs={'recurrent': args.recurrent_policy})
actor_critic.to(device)

if args.algo == 'a2c':
agent = algo.A2C_ACKTR(
actor_critic,
args.value_loss_coef,
args.entropy_coef,
lr=args.lr,
eps=args.eps,
alpha=args.alpha,
max_grad_norm=args.max_grad_norm)
elif args.algo == 'ppo':
agent = algo.PPO(
actor_critic,
args.clip_param,
args.ppo_epoch,
args.num_mini_batch,
args.value_loss_coef,
args.entropy_coef,
lr=args.lr,
eps=args.eps,
max_grad_norm=args.max_grad_norm)
elif args.algo == 'acktr':
agent = algo.A2C_ACKTR(
actor_critic, args.value_loss_coef, args.entropy_coef, acktr=True)

if args.gail:
assert len(envs.observation_space.shape) == 1
discr = gail.Discriminator(
envs.observation_space.shape[0] + envs.action_space.shape[0], 100,
device)
file_name = os.path.join(
args.gail_experts_dir, "trajs_{}.pt".format(
args.env_name.split('-')[0].lower()))

expert_dataset = gail.ExpertDataset(
file_name, num_trajectories=4, subsample_frequency=20)
drop_last = len(expert_dataset) > args.gail_batch_size
gail_train_loader = torch.utils.data.DataLoader(
dataset=expert_dataset,
batch_size=args.gail_batch_size,
shuffle=True,
drop_last=drop_last)

rollouts = RolloutStorage(args.num_steps, args.num_processes,
envs.observation_space.shape, envs.action_space,
actor_critic.recurrent_hidden_state_size)

obs = envs.reset()
rollouts.obs[0].copy_(obs)
rollouts.to(device)

episode_rewards = deque(maxlen=10)

start = time.time()
num_updates = int(
args.num_env_steps) // args.num_steps // args.num_processes
for j in range(num_updates):

if args.use_linear_lr_decay:
# decrease learning rate linearly
utils.update_linear_schedule(
agent.optimizer, j, num_updates,
agent.optimizer.lr if args.algo == "acktr" else args.lr)

for step in range(args.num_steps):
# Sample actions
with torch.no_grad():
value, action, action_log_prob, recurrent_hidden_states = actor_critic.act(
rollouts.obs[step], rollouts.recurrent_hidden_states[step],
rollouts.masks[step])

# Obser reward and next obs
obs, reward, done, infos = envs.step(action)

for info in infos:
if 'episode' in info.keys():
episode_rewards.append(info['episode']['r'])

# If done then clean the history of observations.
masks = torch.FloatTensor(
[[0.0] if done_ else [1.0] for done_ in done])
bad_masks = torch.FloatTensor(
[[0.0] if 'bad_transition' in info.keys() else [1.0]
for info in infos])
rollouts.insert(obs, recurrent_hidden_states, action,
action_log_prob, value, reward, masks, bad_masks)

with torch.no_grad():
next_value = actor_critic.get_value(
rollouts.obs[-1], rollouts.recurrent_hidden_states[-1],
rollouts.masks[-1]).detach()

if args.gail:
if j >= 10:
envs.venv.eval()

gail_epoch = args.gail_epoch
if j < 10:
gail_epoch = 100 # Warm up
for _ in range(gail_epoch):
discr.update(gail_train_loader, rollouts,
utils.get_vec_normalize(envs)._obfilt)

for step in range(args.num_steps):
rollouts.rewards[step] = discr.predict_reward(
rollouts.obs[step], rollouts.actions[step], args.gamma,
rollouts.masks[step])

rollouts.compute_returns(next_value, args.use_gae, args.gamma,
args.gae_lambda, args.use_proper_time_limits)

value_loss, action_loss, dist_entropy = agent.update(rollouts)

rollouts.after_update()

# save for every interval-th episode or for the last epoch
if (j % args.save_interval == 0
or j == num_updates - 1) and args.save_dir != "":
save_path = os.path.join(args.save_dir, args.algo)
try:
os.makedirs(save_path)
except OSError:
pass

torch.save([
actor_critic,
getattr(utils.get_vec_normalize(envs), 'obs_rms', None)
], os.path.join(save_path, args.env_name + ".pt"))

if j % args.log_interval == 0 and len(episode_rewards) > 1:
total_num_steps = (j + 1) * args.num_processes * args.num_steps
end = time.time()
print(
"Updates {}, num timesteps {}, FPS {} \n Last {} training episodes: mean/median reward {:.1f}/{:.1f}, min/max reward {:.1f}/{:.1f}\n"
.format(j, total_num_steps,
int(total_num_steps / (end - start)),
len(episode_rewards), np.mean(episode_rewards),
np.median(episode_rewards), np.min(episode_rewards),
np.max(episode_rewards), dist_entropy, value_loss,
action_loss))

if (args.eval_interval is not None and len(episode_rewards) > 1
and j % args.eval_interval == 0):
obs_rms = utils.get_vec_normalize(envs).obs_rms
evaluate(actor_critic, obs_rms, args.env_name, args.seed,
args.num_processes, eval_log_dir, device)


if __name__ == "__main__":
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import h5py
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.data
from torch import autograd

from stable_baselines3.common.running_mean_std import RunningMeanStd

class Discriminator(nn.Module):
def __init__(self, input_dim, hidden_dim, device):
super(Discriminator, self).__init__()

self.device = device

self.trunk = nn.Sequential(
nn.Linear(input_dim, hidden_dim), nn.Tanh(),
nn.Linear(hidden_dim, hidden_dim), nn.Tanh(),
nn.Linear(hidden_dim, 1)).to(device)

self.trunk.train()

self.optimizer = torch.optim.Adam(self.trunk.parameters())

self.returns = None
self.ret_rms = RunningMeanStd(shape=())

def compute_grad_pen(self,
expert_state,
expert_action,
policy_state,
policy_action,
lambda_=10):
alpha = torch.rand(expert_state.size(0), 1)
expert_data = torch.cat([expert_state, expert_action], dim=1)
policy_data = torch.cat([policy_state, policy_action], dim=1)

alpha = alpha.expand_as(expert_data).to(expert_data.device)

mixup_data = alpha * expert_data + (1 - alpha) * policy_data
mixup_data.requires_grad = True

disc = self.trunk(mixup_data)
ones = torch.ones(disc.size()).to(disc.device)
grad = autograd.grad(
outputs=disc,
inputs=mixup_data,
grad_outputs=ones,
create_graph=True,
retain_graph=True,
only_inputs=True)[0]

grad_pen = lambda_ * (grad.norm(2, dim=1) - 1).pow(2).mean()
return grad_pen

def update(self, expert_loader, rollouts, obsfilt=None):
self.train()

policy_data_generator = rollouts.feed_forward_generator(
None, mini_batch_size=expert_loader.batch_size)

loss = 0
n = 0
for expert_batch, policy_batch in zip(expert_loader,
policy_data_generator):
policy_state, policy_action = policy_batch[0], policy_batch[2]
policy_d = self.trunk(
torch.cat([policy_state, policy_action], dim=1))

expert_state, expert_action = expert_batch
expert_state = obsfilt(expert_state.numpy(), update=False)
expert_state = torch.FloatTensor(expert_state).to(self.device)
expert_action = expert_action.to(self.device)
expert_d = self.trunk(
torch.cat([expert_state, expert_action], dim=1))

expert_loss = F.binary_cross_entropy_with_logits(
expert_d,
torch.ones(expert_d.size()).to(self.device))
policy_loss = F.binary_cross_entropy_with_logits(
policy_d,
torch.zeros(policy_d.size()).to(self.device))

gail_loss = expert_loss + policy_loss
grad_pen = self.compute_grad_pen(expert_state, expert_action,
policy_state, policy_action)

loss += (gail_loss + grad_pen).item()
n += 1

self.optimizer.zero_grad()
(gail_loss + grad_pen).backward()
self.optimizer.step()
return loss / n

def predict_reward(self, state, action, gamma, masks, update_rms=True):
with torch.no_grad():
self.eval()
d = self.trunk(torch.cat([state, action], dim=1))
s = torch.sigmoid(d)
reward = s.log() - (1 - s).log()
if self.returns is None:
self.returns = reward.clone()

if update_rms:
self.returns = self.returns * masks * gamma + reward
self.ret_rms.update(self.returns.cpu().numpy())

return reward / np.sqrt(self.ret_rms.var[0] + 1e-8)


class ExpertDataset(torch.utils.data.Dataset):
def __init__(self, file_name, num_trajectories=4, subsample_frequency=20):
all_trajectories = torch.load(file_name)

perm = torch.randperm(all_trajectories['states'].size(0))
idx = perm[:num_trajectories]

self.trajectories = {}

# See https://github.com/pytorch/pytorch/issues/14886
# .long() for fixing bug in torch v0.4.1
start_idx = torch.randint(
0, subsample_frequency, size=(num_trajectories, )).long()

for k, v in all_trajectories.items():
data = v[idx]

if k != 'lengths':
samples = []
for i in range(num_trajectories):
samples.append(data[i, start_idx[i]::subsample_frequency])
self.trajectories[k] = torch.stack(samples)
else:
self.trajectories[k] = data // subsample_frequency

self.i2traj_idx = {}
self.i2i = {}

self.length = self.trajectories['lengths'].sum().item()

traj_idx = 0
i = 0

self.get_idx = []

for j in range(self.length):

while self.trajectories['lengths'][traj_idx].item() <= i:
i -= self.trajectories['lengths'][traj_idx].item()
traj_idx += 1

self.get_idx.append((traj_idx, i))

i += 1


def __len__(self):
return self.length

def __getitem__(self, i):
traj_idx, i = self.get_idx[i]

return self.trajectories['states'][traj_idx][i], self.trajectories[
'actions'][traj_idx][i]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import numpy as np
import gym
from stable_baselines3 import PPO
from stable_baselines3.common.evaluation import evaluate_policy
from stable_baselines3.common.vec_env import DummyVecEnv
from stable_baselines3.ppo import MlpPolicy

from imitation.algorithms.adversarial.gail import GAIL
from imitation.data import rollout
from imitation.data.wrappers import RolloutInfoWrapper
from imitation.rewards.reward_nets import BasicRewardNet
from imitation.util.networks import RunningNorm
from imitation.util.util import make_vec_env

rng = np.random.default_rng(0)

env = gym.make("seals/CartPole-v0")
expert = PPO(policy=MlpPolicy, env=env, n_steps=64)
expert.learn(1000)

rollouts = rollout.rollout(
expert,
make_vec_env(
"seals/CartPole-v0",
n_envs=5,
post_wrappers=[lambda env, _: RolloutInfoWrapper(env)],
rng=rng,
),
rollout.make_sample_until(min_timesteps=None, min_episodes=60),
rng=rng,
)

venv = make_vec_env("seals/CartPole-v0", n_envs=8, rng=rng)
learner = PPO(env=venv, policy=MlpPolicy)
reward_net = BasicRewardNet(
venv.observation_space,
venv.action_space,
normalize_input_layer=RunningNorm,
)
gail_trainer = GAIL(
demonstrations=rollouts,
demo_batch_size=1024,
gen_replay_buffer_capacity=2048,
n_disc_updates_per_round=4,
venv=venv,
gen_algo=learner,
reward_net=reward_net,
)

gail_trainer.train(20000)
rewards, _ = evaluate_policy(learner, venv, 100, return_episode_rewards=True)
print("Rewards:", rewards)

TensorFlow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import argparse
import gym
import numpy as np
import tensorflow as tf
from network_models.policy_net import Policy_net
from network_models.discriminator import Discriminator
from algo.ppo import PPOTrain

def argparser():
parser = argparse.ArgumentParser()
parser.add_argument('--logdir', help='log directory', default='log/train/gail')
parser.add_argument('--savedir', help='save directory', default='trained_models/gail')
parser.add_argument('--gamma', default=0.95)
parser.add_argument('--iteration', default=int(1e4))
return parser.parse_args()


def main(args):
env = gym.make('CartPole-v0')
env.seed(0)
ob_space = env.observation_space
Policy = Policy_net('policy', env)
Old_Policy = Policy_net('old_policy', env)
PPO = PPOTrain(Policy, Old_Policy, gamma=args.gamma)
D = Discriminator(env)

# 得到专家的观测和行动
expert_observations = np.genfromtxt('trajectory/observations.csv')
expert_actions = np.genfromtxt('trajectory/actions.csv', dtype=np.int32)

saver = tf.train.Saver()

with tf.Session() as sess:
writer = tf.summary.FileWriter(args.logdir, sess.graph)
sess.run(tf.global_variables_initializer())

obs = env.reset()
success_num = 0

for iteration in range(args.iteration):
observations = []
actions = []
rewards = []
v_preds = []
run_policy_steps = 0

while True:
run_policy_steps += 1
obs = np.stack([obs]).astype(dtype=np.float32)
act, v_pred = Policy.act(obs = obs,stochastic = True)

act = np.asscalar(act)
v_pred = np.asscalar(v_pred)

next_obs,reward,done,info = env.step(act)

observations.append(obs)
actions.append(act)
rewards.append(reward)
v_preds.append(v_pred)

if done:
next_obs = np.stack([next_obs]).astype(dtype=np.float32) # prepare to feed placeholder Policy.obs
_, v_pred = Policy.act(obs=next_obs, stochastic=True)
v_preds_next = v_preds[1:] + [np.asscalar(v_pred)]
obs = env.reset()
break
else:
obs = next_obs

writer.add_summary(tf.Summary(value=[tf.Summary.Value(tag='episode_length', simple_value=run_policy_steps)])
, iteration)
writer.add_summary(tf.Summary(value=[tf.Summary.Value(tag='episode_reward', simple_value=sum(rewards))])
, iteration)

if sum(rewards) >= 195:
success_num += 1
if success_num >= 100:
saver.save(sess, args.savedir + '/model.ckpt')
print('Clear!! Model saved.')
break
else:
success_num = 0

observations = np.reshape(observations,newshape=[-1] + list(ob_space.shape))
actions = np.array(actions).astype(dtype = np.int32)

for i in range(2):
D.train(expert_s = expert_observations,
expert_a = expert_actions,
agent_s = observations,
agent_a = actions)


d_rewards = D.get_rewards(agent_s=observations,agent_a = actions)
d_rewards = np.reshape(d_rewards,newshape=[-1]).astype(dtype=np.float32)

gaes = PPO.get_gaes(rewards=d_rewards, v_preds=v_preds, v_preds_next=v_preds_next)
gaes = np.array(gaes).astype(dtype=np.float32)
# gaes = (gaes - gaes.mean()) / gaes.std()
v_preds_next = np.array(v_preds_next).astype(dtype=np.float32)

# train policy
inp = [observations, actions, gaes, d_rewards, v_preds_next]
PPO.assign_policy_parameters()
for epoch in range(6):
sample_indices = np.random.randint(low=0, high=observations.shape[0],
size=32) # indices are in [low, high)
sampled_inp = [np.take(a=a, indices=sample_indices, axis=0) for a in inp] # sample training data
PPO.train(obs=sampled_inp[0],
actions=sampled_inp[1],
gaes=sampled_inp[2],
rewards=sampled_inp[3],
v_preds_next=sampled_inp[4])

summary = PPO.get_summary(obs=inp[0],
actions=inp[1],
gaes=inp[2],
rewards=inp[3],
v_preds_next=inp[4])

writer.add_summary(summary, iteration)
writer.close()


if __name__ == '__main__':
args = argparser()
main(args)

1
traj = Trajectory(observations, actions, infos=None, terminal=True)

–pedestrians

Read more »

概念

Docker包括三个基本概念:

镜像(Image):Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

仓库(Repository):仓库(Repository)类似Git的远程仓库,集中存放镜像文件

三者关系可以用下图表示:

在这里插入图片描述

Docker的常用命令

服务

查看Docker版本信息

Read more »

背景

自动驾驶算法的调试和效果评测首先要在仿真环境中去做,因此,一个强大、灵活的仿真环境是开发、测试过程中必不可少的要素。我在查找可用的仿真工具时主要关注以下几个特性:

  • 开源,免费
  • 包含高速场景
  • 可以便捷的控制、切换场景的环境,场景、环境尽可能的丰富与真实
  • 可以便捷的控制、切换场景内移动物体(如车辆、行人等)的行为模式,行为模式尽可能的丰富与真实

CARLA是一个主要由英特尔实验室和巴塞罗那的计算机视觉中心开发的开源项目。包含了自动驾驶系统的3种方法:

  • 经典模块化方法,包含基于视觉的感知模块,基于规则的规划器,还有行为控制器。
  • 端到端的模仿学习方法。
  • 端到端的强化学习方法。

特点:

  • 针对3D的城市场景(urban driving),开源免费,支持感知、规划、控制。
  • 基于Unreal Engine 4,server-client结构。
  • 可安装于Linux和Windows。
  • Python API,没有C++ API。

架构

Carla 是一个开源的模拟器,可以模拟真实的交通环境,行人行为,汽车传感器信号等等。如下图所示,模拟器使用C++ 和虚幻 (Unreal) 引擎构成,使用者可以通过 Python API 使用 Python 脚本代码对模拟器的环境进行操作和控制。

在这里插入图片描述

Read more »

项目

虚幻引擎项目(Project) 保存着构成游戏所需的所有内容和代码。项目在你的电脑硬盘上由许多目录构成,例如蓝图和材质。你可以随时修改项目目录的名称和层级关系。

虚幻编辑器中的内容浏览器所展示的目录结构和你在硬盘上看到的项目目录结构相同。

每个项目都有一个与之对应的 .uproject 文件。.uproject 文件是你创建、打开或保存项目必须用到的文件。你可以创建任何数量的不同项目,并同时操作它们。

对象

在虚幻引擎中,最基本的类叫做 Object。换句话说,它就像最基本的构建单位,包含了资产的基本功能。虚幻引擎中的大多数类都继承自Object(或从中获取部分功能)。

在C++中,UObject 是所有Object的基类,包含各类功能,诸如垃圾回收、通过元数据(UProperty)将变量公开给编辑器,以及保存和加载时的序列化功能。

类(Class) 用于定义虚幻引擎中Actor或对象的行为和属性。类可以被继承,这意味着某个类可以从其父类(衍生或派生出该类的类)获得信息,然后再将信息传递给子类。类可用C++代码或蓝图创建。

蓝图

Read more »

SUMO ( Simulation of Urban Mobility) 是免费、开源的交通系统仿真软件,可以实现交通流的微观控制,即具体到道路上每一辆车的运行路线都可以单独规划。可模拟复杂环境中的交通流。

sumo中一个路网文件,分为路网net文件和交通需求(路径)route文件。net文件由node文件和edge文件组成。其中node表示节点,如一个交叉口。

在这里插入图片描述

  1. 节点文件 node file (.nod.xml)
  2. 连边文件 edge file (.edg.xml)
  3. 类型文件 edge type file (.type.xml)
  4. 基于上述三个文件创建路网文件 net file (.net.xml)
  5. 路由文件 route file (.rou.xml)

上述文件本质上都是 xml 文件,不过为了方便区分其作用,额外增加了一个后缀名。

假设我们要创建如下图所示的小型道路网络:

在这里插入图片描述

图中黑色节点对应交通路口,连边对应道路。每个路口所在位置坐标已给出。

node file

1
2
3
4
5
6
7
<nodes>
<node id="n1" x="-500" y="0" type="priority"/>
<node id="n2" x="-250" y="0" type="traffic_light"/>
<node id="n3" x="-150" y="200" type="traffic_light"/>
<node id="n4" x="0" y="0"/>
<node id="n5" x="150" y="200"/>
</nodes>
Read more »

Ray

Ray是一个用于并行和分布式 Python 的开源项目,当我们将应用程序迁移到分布式设置时,传统编程概念会发生变化。比如用于模型培训的 TensorFlow、用于数据处理和 SQL 的 Spark 以及用于流处理的 Flink。这些工具提供更高层次的抽象,如神经网络、数据集和流。但是,由于它们与串行编程所使用的抽象不同,因此必须重新编写应用程序以利用它们。

在这里插入图片描述

Ray占据了一个独特的中间地带。而不是引入新的概念。Ray 获取函数和类的现有概念,并将它们作为任务和参与者转换为分布式设置。这种 API 选择允许串行应用程序并行化,而不需要进行重大修改

Ray 可以用来在多个核心或机器上扩展 Python 应用。它有几个主要的优点,包括:

  • 简单性:你可以扩展你的 Python 应用,而不需要重写,同样的代码可以在一台机器或多台机器上运行。

  • 稳健性:应用程序可以优雅地处理机器故障和进程抢占。

  • 性能:任务以毫秒级的延迟运行,可扩展到数万个内核,并以最小的序列化开销处理数值数据。

在这里插入图片描述

作为分布式计算系统,Ray仍旧遵循了典型的Master-Slave的设计:Master负责全局协调和状态维护,Slave执行分布式计算任务。不过和传统的分布式计算系统不同的是,Ray使用了混合任务调度的思路。

  • GlobalScheduler:Master上启动了一个全局调度器,用于接收本地调度器提交的任务,并将任务分发给合适的本地任务调度器执行。
  • RedisServer:Master上启动了一到多个RedisServer用于保存分布式任务的状态信息(ControlState),包括对象机器的映射、任务描述、任务debug信息等。
  • LocalScheduler:每个Slave上启动了一个本地调度器,用于提交任务到全局调度器,以及分配任务给当前机器的Worker进程。
  • Worker:每个Slave上可以启动多个Worker进程执行分布式任务,并将计算结果存储到ObjectStore。
  • ObjectStore:每个Slave上启动了一个ObjectStore存储只读数据对象,Worker可以通过共享内存的方式访问这些对象数据,这样可以有效地减少内存拷贝和对象序列化成本。ObjectStore底层由Apache Arrow实现。
  • Plasma:每个Slave上的ObjectStore都由一个名为Plasma的对象管理器进行管理,它可以在Worker访问本地ObjectStore上不存在的远程数据对象时,主动拉取其它Slave上的对象数据到当前机器

Ray的任务也是通过类似SparkDriver的概念的方式进行提交的,有所不同的是:

Read more »

LeNet-5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
import torchvision
import torchvision.transforms as transforms
import time
import matplotlib.pyplot as plt
import os

os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"


# 导入FashionMNIST数据集
mnist_train = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST', train=True, download=True, transform=transforms.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST', train=False, download=True, transform=transforms.ToTensor())


# 处理数据集,把数据转换成张量,使数据可以输入下面我们搭建的网络
def load_data_fashion_mnist(mnist_train, mnist_test, batch_size):
if sys.platform.startswith('win'):
num_workers = 0
else:
num_workers = 4
train_data = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers)
test_data = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)
return train_data, test_data


class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5), # in_channels, out_channels, kernel_size
nn.LeakyReLU(0.1),
nn.MaxPool2d(2, 2), # kernel_size, stride
nn.Conv2d(6, 16, 5),
nn.LeakyReLU(0.1),
nn.MaxPool2d(2, 2)
)
self.fc = nn.Sequential(
nn.Linear(16*4*4, 120),
nn.LeakyReLU(0.1),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84, 10)
)

def forward(self, img):
feature = self.conv(img)
output = self.fc(feature.view(img.shape[0], -1))
return output

# 测试准确率计算
def evaluate_accuracy(data_iter, net, device=None):
if device is None and isinstance(net, torch.nn.Module):
# 如果没指定device就使用net的device
device = list(net.parameters())[0].device
acc_sum, n = 0.0, 0
with torch.no_grad():
for X, y in data_iter:
net.eval() # 评估模式, 这会关闭dropout
acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item()
net.train() # 改回训练模式
n += y.shape[0]
return acc_sum / n


# 训练函数
def train(net, train_data, test_data, batch_size, optimizer, device, num_epochs):
net = net.to(device)
print("training on ", device)
loss_function = torch.nn.CrossEntropyLoss() # 定义损失函数(交叉熵损失函数)
ax = [] # 保存等会更新的epoch,loss,train_acc,test_acc,用于绘制动态折线图
ay1 = []
ay2 = []
ay3 = []
plt.ion()
# 开始训练
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n, batch_count, start = 0.0, 0.0, 0, 0, time.time() # 初始化参数
for X, y in train_data:
X = X.to(device) # 把参数导入GPU训练
y = y.to(device)
y_hat = net(X)
l = loss_function(y_hat, y) # 使用损失函数计算loss
optimizer.zero_grad() # 把梯度置零,也就是把loss关于weight的导数变成0
l.backward() # 反向传播
optimizer.step()
train_l_sum += l.cpu().item()
train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
n += y.shape[0]
batch_count += 1
test_acc = evaluate_accuracy(test_data, net) # 测试当个epoch的训练的网络
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec'
% (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start))
# 绘制动态折线图(如果不想绘制,可以删掉)
plt.clf() # 清除刷新前的图表,防止数据量过大消耗内存
ax.append(epoch + 1) # 追加x坐标值
ay1.append(train_l_sum / batch_count) # 追加y坐标值
ay2.append(train_acc_sum / n)
ay3.append(test_acc)
plt.plot(ax, ay1, 'g-')
plt.plot(ax, ay2, 'r-')
plt.plot(ax, ay3, '-')
plt.ylabel("epoch")
plt.plot(ax, ay1, label="loss") # 在绘图函数添加一个属性label
plt.plot(ax, ay2, label="train_acc")
plt.plot(ax, ay3, label="test_acc")
plt.legend(loc=2) # 添加图例,loc为图例位置,1为右上角,2为左上角,3为左下角,4为右下角
plt.grid() # 添加网格
plt.pause(5) # 设置暂停时间,太快图表无法正常显示
plt.ioff() # 关闭画图的窗口,即关闭交互模式
plt.show() # 显示图片,防止闪退


if __name__ == '__main__':
batch_size = 256 # 批量数大小
train_data, test_data = load_data_fashion_mnist(mnist_train, mnist_test, batch_size)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 使用GPU,如果没有则使用CPU
net = LeNet() # 导入我们搭建好的网络
lr, num_epochs = 0.001, 10
optimizer = torch.optim.Adam(net.parameters(), lr=lr) # 优化函数
train(net, train_data, test_data, batch_size, optimizer, device, num_epochs)

AlexNet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 96, 11, 4), # in_channels, out_channels, kernel_size, stride, padding
nn.ReLU(),
nn.MaxPool2d(3, 2), # kernel_size, stride
# 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
nn.Conv2d(96, 256, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(3, 2),
# 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。
nn.Conv2d(256, 384, 3, 1, 1),
nn.ReLU(),
nn.Conv2d(384, 384, 3, 1, 1),
nn.ReLU(),
nn.Conv2d(384, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)
self.fc = nn.Sequential(
nn.Linear(256*5*5, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 10),
)

def forward(self, img):
feature = self.conv(img)
output = self.fc(feature.view(img.shape[0], -1))
return output

完整实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import time
import torch
from torch import nn, optim
import torchvision
import sys

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

def load_data_fashion_mnist(batch_size, resize=None, root='~/Datasets/FashionMNIST'):
if sys.platform.startswith('win'):
num_workers = 0
else:
num_workers = 4
trans = []
if resize:
trans.append(torchvision.transforms.Resize(size=resize))
trans.append(torchvision.transforms.ToTensor())

transform = torchvision.transforms.Compose(trans)
mnist_train = torchvision.datasets.FashionMNIST(root=root, train=True, download=True, transform=transform)
mnist_test = torchvision.datasets.FashionMNIST(root=root, train=False, download=True, transform=transform)

train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers)
test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)

return train_iter, test_iter

batch_size = 128
train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=224)

class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 96, 11, 4), # in_channels, out_channels, kernel_size, stride, padding
nn.ReLU(),
nn.MaxPool2d(3, 2), # kernel_size, stride
# 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
nn.Conv2d(96, 256, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(3, 2),
# 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。
nn.Conv2d(256, 384, 3, 1, 1),
nn.ReLU(),
nn.Conv2d(384, 384, 3, 1, 1),
nn.ReLU(),
nn.Conv2d(384, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)
self.fc = nn.Sequential(
nn.Linear(256*5*5, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 10),
)

def forward(self, img):
feature = self.conv(img)
output = self.fc(feature.view(img.shape[0], -1))
return output

net = AlexNet()

def evaluate_accuracy(data_iter, net, device=None):
if device is None and isinstance(net, torch.nn.Module):
# 如果没指定device就使用net的device
device = list(net.parameters())[0].device
acc_sum, n = 0.0, 0
with torch.no_grad():
for X, y in data_iter:
net.eval() # 评估模式, 这会关闭dropout
acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item()
net.train() # 改回训练模式
n += y.shape[0]
return acc_sum / n


def train(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):
net = net.to(device)
print("training on ", device)
loss = torch.nn.CrossEntropyLoss()
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n, batch_count, start = 0.0, 0.0, 0, 0, time.time()
for X, y in train_iter:
X = X.to(device)
y = y.to(device)
y_hat = net(X)
l = loss(y_hat, y)
optimizer.zero_grad()
l.backward()
optimizer.step()
train_l_sum += l.cpu().item()
train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
n += y.shape[0]
batch_count += 1
test_acc = evaluate_accuracy(test_iter, net)
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec'
% (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start))

lr, num_epochs = 0.001, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
train(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

Read more »

背景

GAIL算法存在的问题:

  • 模态崩塌问题:指生成模型产生的生成样本塌缩于真实样本分布的某一模态下的子分布,而无法覆盖全部真实样本分布。
  • 生成样本利用效率低:是GAIL假设策略为随机性策略并以无模型RL方法来学习策略。由于随机性策略采样动作的过程是不可微分的,因此反向传播的链式求导在策略模型万的动作节点处中断。在随机环境中,智能体的状态迁移过程是随机的。

InfoGAIL主要改进第一个问题,以自动驾驶为例,GAIL算法不能够很好处理不同驾驶风格的多专家数据场景。专家个体的不同,样本服从多个模态下的子分布,单一模态的假设不符合实际问题

InfoGAIL

核心思想:InfoGAIL假设专家数据具有多个模态的分布,从专家数据中同时学习多种有效的模态,比如快速驾驶模态与安全驾驶模态,增加辅助网络用来对样本所属的模态类别进行分类。InfoGAIL将信息论中的互信息概念运用到GAIL模型中,通过最大化互信息的原来,能增强策略产生的样本与模态隐变量之间的相关性,进而实现无监督的多模态学习。

互信息表示一个随机变量x在给定另一变量y后所减少的不确定性或信息量。通俗来说,互信息表示x与y之间的相关性,互信息越大,两者越相关。公式表示为:

在这里插入图片描述

InfoGAIL在GAIL的基础上考虑最大化待学习策略产生的状态-动作与模态隐变量之前的互信息:

在这里插入图片描述

Read more »