问题
在我的循环模型(顺序二元分类器)中,在每个时间步 t,我需要执行以下输入转换:
[32 x 4] --> [32 x 100]
所以,如果我的序列长度是 3,我应该:
[32 x 4] --> [32 x 100]
[32 x 4] --> [32 x 100]
[32 x 4] --> [32 x 100]
我通过在每个时间步 t 上对 [32 x 4] 张量应用线性变换 xW + b 来实现。我的模型的工作 Torch 实现显示了每个时期线性权重变化的平均值:
Epoch #1
0.0012639100896195
0.0012639100896195
0.0012639100896195
Epoch #2
0.0039414558559656
0.0039414558559656
0.0039414558559656
Epoch #3
-0.0099147083237767
-0.0099147083237767
-0.0099147083237767
向后传递更新权重,一切正常。 然而,当我尝试在 Tensorflow 中做同样的事情时,mean 在每个时期保持不变或更新非常小:
Epoch: 1
> lr update: 0.0497500005
#################### DEBUGGING ####################
0.051794354 Model/input_layer2/linear_weigth:0
0.06118914 Model/input_layer2_bias/linear_bias:0
Epoch: 2
> lr update: 0.049500001
#################### DEBUGGING ####################
0.051794227 Model/input_layer2/linear_weigth:0
0.06118797 Model/input_layer2_bias/linear_bias:0
Epoch: 3
> lr update: 0.0492500015
#################### DEBUGGING ####################
0.051794235 Model/input_layer2/linear_weigth:0
0.06118701 Model/input_layer2_bias/linear_bias:0
Tensorflow 线性实现非常简单:
def linear(input)
return tf.add(tf.matmul(input, self.linear_weight), self.linear_bias)
expanded = [linear(batch_seq) for batch_seq in unstacked_input]
self.linear_weight 和 self.linear_bias 都是可训练的,并且在图构建过程中被初始化为 tf.Variables。 Torch 和 TF 模型都使用相同的训练数据集、超参数。 Torch 和 TF 模型大小(参数数量)也相同。不用说,Torch 模型训练并在测试数据上显示出良好的结果,而 TF 模型根本没有训练。
问题:
由于我是 TF 的新手,您能否提供一些提示,说明 TF 模型可能存在哪些问题?我知道如果没有完整的代码,这是一个很长的镜头,但也许我在这里遗漏了一些特定于 TF 的东西。
信息
您可能已经注意到,在 Torch 中,我们在时间步 t 的每个线性操作中有 3 个平均值,而在 TF 中,我有 2 个平均值——一个来自线性,另一个来自偏差。如果不是 linear() 我使用 tf.layers.dense 调用而不使用 name 参数,我实际上每个密集调用有 3 个平均值。但在那种情况下,TF 会为每个密集调用创建不同的平均值,这是我们不想做的。
这是 TF 代码的训练 block ,它应该执行所有前向/后向魔术,但它没有:
if self.training:
self.lr = tf.Variable(0.0, trainable=False)
tvars = tf.trainable_variables()
# clip the gradient by norm
grads, _ = tf.clip_by_global_norm(tf.gradients(self.cost, tvars), config.grad_clip)
# update variables (weights, biases, embeddings...)
with tf.name_scope("optimizer"):
optimizer = tf.train.AdamOptimizer(self.lr)
# compute grads/vars for tensorboard
self.grads_and_vars = optimizer.compute_gradients(loss)
# debugging only, this is how I get the weights and grads
for g, v in self.grads_and_vars:
self.param_vals[v.name] = v
self.param_grads[v.name+'_grads'] = g
self.train_op = optimizer.apply_gradients(zip(grads, tvars),
global_step=tf.train.get_or_create_global_step())
张量板
由于验证损失,模型在 38 个 epoch 后停止训练后的 Tensorboard 屏幕截图不再减少。我对TB也不是很熟悉,我只能根据直方图来判断肯定是不对的。
# collecting data for tb
tf.summary.scalar("Training loss", model_train.cost)
tf.summary.scalar("Learning rate", model_train.lr)
tf.summary.histogram("Training loss", model_train.cost)
for g, v in model_train.grads_and_vars:
tf.summary.histogram(v.name, v)
tf.summary.histogram(v.name + '_grad', g)
请您参考如下方法:
看来我正在应用 loss = tf.sigmoid(logits)(与原始 Torch 模型中一样),然后将 loss 提供给 tf.losses。 sigmoid_cross_entropy。这使梯度几乎为零,并且权重没有正确更新。当我删除 tf.sigmoid 函数时,梯度增加,权重开始移动。
logits = tf.nn.xw_plus_b(last_layer, self.output_w, self.output_b)
floss = tf.losses.sigmoid_cross_entropy
#floss = tf.nn.sigmoid_cross_entropy_with_logits
loss = floss(self.targets_input, logits, weights=1.0, label_smoothing=0,
scope="sigmoid_cross_entropy", loss_collection=tf.GraphKeys.LOSSES)
