2021SC@SDUSC
本篇代码分析模块为:TrainGenerator.py
前面一篇博客中,我们分析了图生成器的定义过程,为了是模型达到更好的效果,我们下面来看一下作者是如何进行训练的。
一.训练图生成器
(1)一些初始化设置
# T = 10 max_gen_step = 10 candidate_set = ['C.4', 'N.5', 'O.2', 'F.1', 'I.7', 'Cl.7', 'Br.5']
'C.4'表明碳原子的度不超过4。
(2)梯度下降更新参数,训练模型
这里实际上涉及到了梯度下降的方法,我们首先来看看梯度下降的一个直观的解释。比如我们在一座大山上的某处位置,由于我们不知道怎么下山,于是决定走一步算一步,也就是在每走到一个位置的时候,求解当前位置的梯度,沿着梯度的负方向,也就是当前最陡峭的位置向下走一步,然后继续求解当前位置梯度,向这一步所在位置沿着最陡峭最易下山的位置走一步。这样一步步的走下去,一直走到觉得我们已经到了山脚。当然这样走下去,有可能我们不能走到山脚,而是到了某一个局部的山峰低处。
从上面的解释可以看出,梯度下降不一定能够找到全局的最优解,有可能是一个局部最优解。当然,如果损失函数是凸函数,梯度下降法得到的解就一定是全局最优解。
## 训练generator
def train_generator(c=0, max_nodes=5):
g.c = c
for i in range(max_gen_step):
optimizer.zero_grad()
G = copy.deepcopy(g.G)
p_start, a_start, p_end, a_end, G = g.forward(G)
Rt = g.calculate_reward(G)
loss = g.calculate_loss(Rt, p_start, a_start, p_end, a_end, G)
loss.backward()
optimizer.step()
if G['num_nodes'] > max_nodes:
g.reset_graph()
elif Rt > 0:
g.G = G
optimizer.zero_grad():意思是把梯度置零,也就是把loss关于weight的导数变成0。因为一个batch的loss关于weight的导数是所有sample的loss关于weight的导数的累加和。
copy.deepcopy():深拷贝,即我们通常理解的字面"复制"的意思。deepcopy的时候会将复杂对象的每一层复制一个单独的个体出来。
g.calculate_loss():算一下loss标量出来,确定优化的目标,才能进行反向传播。反向传播基于一个loss标量,loss从中获取grad。
loss.backward():