DFP_code

Code Structure

  • common
    • util.py
    • tf_ops.py
    • defaults.py
  • Simulator
    • doom_simulator.py
    • multi_doom_simulator.py
  • Agent
    • agent.py
    • future_predictor_agent_basic.py
    • future_predictor_agent_advantage.py
    • future_predictor_agent_advantage_nonorm.py
  • target
    • future_target_maker.py
  • experience
    • multi_experience_memory.py
    • multi_experience.py

Common

util.py

make_objective_indices_and_coeffs(temporal_coeffs, meas_coeffs):

网络使用两个系数作为目标的系数作为最终决断的系数,一个是temporal_coeffs, 即时间尺度上的系数,分别对应不同时间段对目标值的贡献,meas_coeffs表示不同的measure对目标值的贡献。

make_array(shape=(1,), dtype=np.float32, shared=False, fill_val=None):

生成array,如果有array共享的话,从共享的区域中生成array

merge_two_dicts(x, y)

合并两个dict,用于defaults.py 中的参数和不同模型的参数合并

StackedBarPlot

用于画不同的预测值的直方图,并可以动态显示

tf_ops

msra_stddev(x, k_h, k_w)

参数初始化方差

mse_ignore_nans(preds, targs. **kwargs)

忽略Nan 求MSE

conv2d(input_, output_dim, k_h, k_w, d_h, d_w, msra_coeff, name)

构建卷积层的api

lrelu(x, leak, name)

构建lrelu层的api

linear(input_, output_size, name, msra_coeff)

线性函数api

conv_encoder(data, params, name, msra_coeff)

根据conv_params的参数构建连续的卷积层

fc_net(data, param, name, last_linear, return_layers, msra_coeff)

根据fc_params的参数构建连续的全连接层;根据return_layers的性质,确定最后一层的fc是否要接relu

flatten(data)

构建flatten层的api

defaults.py

default.py主要提供不同的默认参数dict,其中主要分为4类, target_maker, simulator, experiment(experiment, train_experiment, test_policy), agent。 给不同的文件提供不同的默认参数配置, 在具体使用的时候,该参数会被不同文件中的参数给覆盖。

target_maker_args

这里的min_num_targs, 表示目标target的最小数量, 对于那些target数量不足的样本,会用nan替换

simulator_args

frame_skip表示不使用连续的帧作为状态,使用间隔的帧作为状态。

experience_args

这里分为三个文件experience_args, train_experience_args, test_policy_experience_args

agent_args

存储所有关于网络的参数

Simulator

DoomSimulator

DoomSimulator类

init(self, args)

初始化程序配置,设置doom的各项参数,具体参考doom_doc
使用analyze_controls(self, config_file), 解析获得available_controls, continuous_controls, discrete_control,注意到这些都是index. 比如continuous_controls = [1,2,3], discrete_control = [4,5,6]

analyze_controls(self, config_file)

利用正则表达式解析available_controls, continuous_controls, discrete_control.

init_game, close_game, get_random_action, is_new_episode, next_map, new_episode

函数作用如名所示,注意doom的具体动作可以使用多个动作的组合,比如可控的动作是[1, 2], 那么实际可能的动作为[True, True] or [True, False] or [False, True] or [False, False]

step(self, action)

执行一步动作,返回img,measure, reward, terminal. 这里action是一个bool vector, 图像均为黑白(彩色会报错), img指doomSimulator返回的图像,meas指config文件中的指定的variable
,这里特指{AMMO2, HEALTH, USER2}(这里的user2指kill_count, 在wad文件里面使用). rwrd特指doomSimulator返回的reward,这个是doom内部自带的reward.

MultiDoomSimulator

多个doomSimulator的类,可以用来同时执行一个action的列表,同时返回imgs, meass, rwrds, terms(均为list)

Agent

agent.py

init(self, sess, args):

初始化各项参数
同时调用prepare_controls_and_actions(), 初始化所有的control和action

prepare_controls_and_actions(self)

注意到这里controls表示action的index,action用bool vector表示。其中controls分为两类,一类是由网络生成的discrete_controls_to_net, 一类是外部赋予的discrete_controls_manual. 同时net_discrete_actions是一个numpy array,表示list of vector(除掉了冲突的action), 这些vector可以用来直接执行动作。
另外,初始化了action_to_index的dict,用来查询不同的action的index, 初始化了onehot_dizhscrete_actions用一个one-hot向量表达不同的action,这里可以用作网络的输入。

preprocess_actiosn(self, acts)

这里的acts表示batch_size个动作,每个动作用一个bool vector(包含了net_action和manunal_action)表示,该函数的作用是把这些acts转化成对应的one-hot-vector输入到网络中去.

postprocess_actions(self, acts_net, act_manual)

将acts_net和act_manual组合成一个正式的输出的动作,该函数的输入的acts_net是一个[batch_size]的输入,每个值均为action的index,act_manual是一个bool_vector。将act_nets, act_manual组合成一个正式的action,可以用做simulator的输入.

random_actions(self, num_samples)

获得随机的action

make_net, make_losses,act_nets, act_manual

这几个函数都没有执行,在装饰器文件如future_predictor_agent_basic等中执行

act(self, state_imgs, state_meas, objective_coeffs)

调用act_net得到net_action,调用act_manual得到munual_action,使用postprocess_actions函数将其组合成一个具体的动作

build_model(self)

该函数主要构建tf的模型,具体的模型参考论文

  • 需要输入的参数包括input_images, input_measurement, input_targets, input_actions, input_objective_coeffs
  • 如果提供了预处理的函数,则会根据预处理函数对输入进行预处理,预处理的方式参考论文
    • 将img的值放缩在[-1, 1]
    • 将mesurements的值放缩在[-1, 1]
    • 将三个target分别除以7.5, 30, 1
  • 调用make_net和make_loss构建网络
  • 构建训练节点,学习率衰减节点,summary节点

Actor

一个子类,用作实际操作action的一个接口
init(self, agent, objective_coeffs, random_prob, random_objective_coeffs)
初始化objective_coeffs, 如果使用随机的初始化策略,则调用reset_objective_coeffs(self, indices), 使用均匀分布来初始化,否则直接对objective_coeffs赋值
reset_objective_coeffs(self, indices)
使用均匀分布初始化objective_coeffs
act(self, state_imgs, state_meas)
$\epsilon$-greedy算法,以$\epsilon$的概率执行随机的动作,以1-$\epsilon$的概率调用agent.act()函数执行动作
act_with_multi_memory(slef, multi_memory)
执行和act一样的功能,但是针对mutil_memory,调用这个函数执行多个动作要比使用上面的函数高校,因为这样只会在需要的时候才会读取state。

get_actor(self, objective_coeffs, random_prob, random_objective_coeffs)

返回actor的子类

train_one_batch(self, experience)

  • 调用experience.get_random_batch函数得到state_imgs, state_meas, rwrds, terms, acts, targs, objs
  • forward网络一次
  • 在特定的步数打印错误,存储summary,或存储histogram
  • 步数+1

train(self, simulator, experience, num_steps, test_police_experience)

  • 如果可以的话,载入checkpoint
  • 初始化writer, 和actor接口
  • 调用experience.add_n_steps_with_actor填充训练的memory
  • 调用train_one_batch共num_steps次,一共训练num_steps个batch
  • 每隔固定的步数保存checkpoint或者测试test_policy,同时每隔一定的步数重新填充memory,注意到这里会衰减$\epsilon$

test_policy(self, simulator, experience, objective_coeffs, num_steps, random_prob, write_summary, write_prdiction)

测试一次policy, 注意到这里会调用experience.compute_avg_meas_and_rwrd去计算得到这一次的policy的平均reward和平均measure。
另外,为了保证每次测试不改变head_offset, 会暂时保存该值,并在测试完之后恢复

save, load, set_init_step

功能如其,set_init_step可以接着之前的step继续训练

future_predictoragent*.py

这里一共包含3个文件(future_predictor_agent_basic, future_predictor_agent_advantage, future_predictor_agent_advantage_nonorm), 都是作为agent类的子类,重写了agent类中的make_net, make_losses, act_nets的成员函数,用于对比实验

make_net(self, input_images, input_measurement, input_actions, input_objectives, reuse)

  • 根据卷积和全联接的参数调用tf_ops中的接口来搭建网络
    • future_predictor_agent_basic中没有使用分支结构
    • future_predictor_agent_advantage中是论文中的标准结构
    • future_predictor_agent_advantage_nonorm是论文中的标准结构但是去除了normalization的环节
  • 这里input_images, input_measurement, input_actions均为网络的输入,而input_actions(bool of vector)用来指出哪个所有的预测中与当前动作相关的预测。

make_losses(self, pred_relevant, targets_preprocessed, objective_indices, objective_coeffs)

构建loss的计算节点,并同时去除nan,构建summry节点

act_net(self, state_imgs, state_meas, objective_coeffs)

  • 更新prediction
  • 按照objective_coeffs求出使收益最大的动作。

target

future_target_maker.py

target_maker类,负责生成网络的学习目标

init(self, args)

构造函数,注意几点

  • min_num_targs: target的最小数量,对于某些靠近end of episode的样本,其可能的target数量少于min_num_targs,所以这些样本无效,会用nan替代
  • 根据不同的gamma值,对不同的future step对reward进行指数衰减。在具体的实验中,由于并没有用到simulator中的reward值,因此gamma值为空
  • 每个时刻需要预测的target的维度包括两个部分: 1, 不同gamma衰减下的reward;2,不同的measure。 所以num_targets = len(self.meas_to_predict) + self.num_reward_targets。注意num_targets的长度必须与agent中的objective_coeffs_meas的长度相同,因为objective_coeffs_meas就是用来衡量不同的target对最终结果的加权系数
  • 总的target的维度为self.num_targets * len(self.future_steps). 注意self.future_steps的长度必须与agent中的objective_coeffs_temporal的长度相同
  • 根据min_num_targs,确定min_future_frames,将来用来确定该帧与之后的min_future_frames处的帧是否处于同一个episode来判断当前帧是否有效.

make_targets(self, indices, meas, rwrds, n_episode, meas_mean, meas_std)

生成对应indices处的targets
该函数主要是在multi_experience_memory处调用,所以提供的meas,rwards都是一个大的memory, indices负责指示想要生成batch的样本所在memory处的位置.

  • capacity指memory的大小
  • target分为两个部分,一个是measurement, 一个是reward
  • 对于measurement,如果有meas_mean或者meas_std的话,会进行normalization的处理,不在一个epsisode的样本的measurement会用最近的measurement进行替换。
  • 对于reward,target是对一个时间窗口(self.future_steps)内的rwrd进行指数衰减下的加权求和。

experience

multi_experience_memory.py

MultiExperienceMemory类

init(self, args, multi_simulator, target_maker)

初始化空的memory,这里包含两个假设:1,观测都是连续的,在每一个episode内都有一个停止的状态;2,每一个episode都比memory的长度要短。
调用reset函数,初始化各项私有变量

reset(self)

  • self._curr_indices设置成不同memory的indices
  • self._episode_counts用来设置不同memory的eposide值,用来区分不同frame在memory中的位置

add(self, imgs, meass, rwrds, terms, acts, objs, preds)

  • 更新images, measurements, rewards, terminals, actions,n_episode, objectives, predictions
  • 在term处的measurements使用上一个状态measurements,同时对于term处,对measurement进行一定的衰减
  • 为了防止出现两个term状态,在出现第二个term时,将第二个term状态的measurements置零
  • 更新episode_counts, curr_indices和terminals

add_step(self, multi_simulator, acts, objs, preds)

调用multi_simulator执行一次acts, 并将其结果加入memory

add_n_steps_with_actor(self, multi_simulator, num_steps, actor, verbose, write_prediction, write_logs, global_step)

  • log中会写入具体的episode, step, time, accu_reward, prev_meas, avg_meas
  • 如果有prediction的话,会写入prediction
  • 调用add_steps共num_steps次,使用actor类的接口加入memory

get_states(self, indices)

根据indices从memory中选择state_imgs, state_meas。注意到这里的的state_imgs包含history_step个历史,且每个历史之间相差不同的history_len
而state_meas仅仅包含当前indices处的measurements

get_current_state(self)

获得当前最近的观测值

get_last_indices(self)

返回最近的indices

get_target(self, indices)

使用target_maker.make_targets类返回indices处的targets.
这里使用了一个hack,对不同的memory处使用了一12345678 * self._n_head的数值,用来区分不同的head处的episode值

has_valid_history(self, index)

判断index处是否有足够的history进行训练

has_valid_target(self, index)

判断index处是否有足够的target进行训练

is_valid_target(self, index)

判断index处的状态是否有效,即是否有足够的history和target

get_observations(self, indices)

得到indices处的所有信息包括
state_imgs, state_meas, rwrds, terms, acts, targs, objs

get_random_batch(self, batch_size)

从memory中随机采用batch_size个有效的样本

compute_avg_meas_and_rwrd(self, start_idx, end_idx)

统计从start_idx,end_idx中所有的episode中的平均measurements和rewards

show(self, start_idx, end_idx, display, write_imgs, write_video, preprocess_targets, show_predictions, net_discrete_actions)

show的接口,提供display, write_imgs, write_vedio, show_prediction的选项

multi_experiement.py

init(self, target_maker_args, simulator_args, train_experience_args, test_policy_experience_args, agent_args, experiment_args)

将默认的参数和给定的参数进行合并,得到具体的参数.
部分参数在此处求解,比如各种shape的参数

run(self, mode)

  • show模式,将训练的head_offset和测试的head_offset错开。测试policy,并show_memory中的结果
  • train模式,训练网络, 更新参数.
Donate comment here