在我的循环模型(顺序二进制分类器)中,每个时间步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中执行相同操作时,平均值保持不变或在每个时期稍微更新:
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模型都使用相同的训练数据集,超参数。火炬和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())
由于验证损失,模型在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)
似乎我正在应用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)