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

时间:2018-03-21 16:24:46

标签: python tensorflow machine-learning

问题

在每个时间步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]

我是通过在每个时间步xW + b[32 x 4]张量应用线性变换t来实现的。我工作的模型的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_weightself.linear_bias都可以训练,并在图表构建过程中初始化为tf.Variables。 Torch和TF模型都使用相同的训练数据集,超参数。火炬和TF模型的大小(参数的数量)也是一样的。毋庸置疑,Torch模型训练并在测试数据上显示出良好的结果,而TF模型根本不训练。

问题:

由于我是TF的新手,你能否给出一些提示TF模型可能有什么问题?我知道这是一个很长的镜头没有完整的代码,但也许我在这里缺少特定于TF的东西。

信息

您可能已经注意到,在Torch中,我们在时间步t每个线性操作有3个平均值,而在TF中我得到2个均值 - 一个来自线性,另一个来自偏差。如果不是linear()而是使用tf.layers.dense调用而没有name参数,那么每个密集调用实际上有3个均值。但在这种情况下,TF会为每个密集呼叫创建一个我们不想做的不同平均值。

这是TF代码的训练块,它应该执行所有前进/后退魔法,但它不会:

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())

Tensorboard

由于验证损失,模型在38个时期后停止训练后的Tensorboard屏幕截图不会再减少。我对结核病也不太熟悉,根据直方图,我只能说某些事情肯定是不对的。

# 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)

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

我似乎正在应用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)