Skip to main content
 首页 » 编程设计

python之Tensorflow 在反向传播期间不更新线性权重

2025年01月19日29qq78292959

问题

在我的循环模型(顺序二元分类器)中,在每个时间步 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)