标题: Keras后端与Tensorflow在梯度计算上的差异

注意: keras.backend() 返回tensorflow。使用的是Python 3.5。

我在梯度计算中遇到一个错误。我已经在一个简单的Keras模型和Tensorflow模型中复制了这个错误,如下所示。

from keras.layers import Dense, Inputfrom keras.models import Modelfrom keras.optimizers import Adamimport kerasimport keras.backend as Kimport numpy as npimport tensorflow as tfclass KerasModel(object):    def __init__(self, seed, dim_size, optimizer, loss_func):        self.sess=tf.Session()        I = Input(                shape=[dim_size],                 name='i'                 )        O = Dense(                1,                activation='relu',                kernel_initializer=keras.initializers.glorot_uniform(seed=seed),                name='o'                 )(I)        self.model = Model(inputs=I,outputs=O)        self.model.compile(loss=loss_func, optimizer=optimizer)        self.action_grads = tf.gradients(self.model.output, self.model.input)          self.grad_func= K.function(self.model.inputs, self.action_grads)        self.sess.run(tf.global_variables_initializer())    def tf_grad(self, X):        return self.sess.run(self.action_grads, feed_dict={self.model.input: X,})[0]    def keras_grad(self, X):                return self.grad_func(X)[0]class TFModel(object):    def __init__(self, seed, dim_size, optimizer, loss_func):        self.graph= tf.Graph()        with self.graph.as_default():            glorot_uniform= tf.glorot_uniform_initializer(seed=seed)            O= {                    'weights': tf.Variable(glorot_uniform([dim_size, 1])),                    'bias': tf.Variable( tf.zeros(1) )                }            w_list= [                 O['weights'], O['bias']                    ]             w_list_placeholder= []            w_list_update= []            for i in range(0, len(w_list)):                w_list_placeholder.append( tf.placeholder(tf.float32) )                w_list_update.append( w_list[i].assign( w_list_placeholder[i] ) )            I= tf.placeholder(tf.float32, shape= (None, dim_size))            output= tf.nn.relu( tf.add( tf.matmul( I, O['weights']), O['bias'] ) )            gradient= tf.gradients(output, I)            y= tf.placeholder(tf.float32)            loss= tf.reduce_mean( loss_func(y, output) )            train = optimizer.minimize(loss)            self.tensors= {                'output': output, 'I': I, 'y': y, 'grad':gradient,                'loss': loss, 'train-op': train, 'w': w_list,                'w-placeholder': w_list_placeholder, 'w-update': w_list_update                          }            self.sess= tf.Session(graph=self.graph)            self.sess.run( tf.variables_initializer( self.graph.get_collection('variables') ) )    def train_on_batch(self, X, y):        _, l=self.sess.run(             [self.tensors['train-op'], self.tensors['loss']],            feed_dict={                 self.tensors['I']: X,                self.tensors['y']: y                       }                           )        return l    def predict(self, X):        return self.sess.run(self.tensors['output'], feed_dict={self.tensors['I']: X})    def get_weights(self):        return self.sess.run(self.tensors['w'])    def set_weights(self, new_weights):        self.sess.run(             self.tensors['w-update'],             feed_dict={ x:y for x,y in zip(self.tensors['w-placeholder'], new_weights) }                      )    def grad(self, X):        return self.sess.run(self.tensors['grad'], feed_dict={self.tensors['I']:X})[0]

这两个模型在层、初始化、优化器、损失函数、权重等方面是相同的。

我使用这两个模型从同一组输入计算梯度。对于Tensorflow模型,这是通过grad()函数完成的:

def grad(self, X):    return self.sess.run(self.tensors['grad'], feed_dict={self.tensors['I']:X})[0]

对于Keras模型,这是通过keras_grad()tf_grad()完成的。

self.action_grads = tf.gradients(self.model.output, self.model.input)self.grad_func= K.function(self.model.inputs, self.action_grads)def tf_grad(self, X):    return self.sess.run(self.action_grads, feed_dict={self.model.input: X,})[0]def keras_grad(self, X):            return self.grad_func(X)[0]

keras_grad()使用keras.backend.function()来完成,而tf_grad()使用tf.Session()来完成。

然后它们用另一组相同的输入进行训练。同样,这在下面显示:

seed=1dim_size=3learning_rate=0.01e=1e-8k_adam= KerasModel(    seed, dim_size, tf.train.AdamOptimizer(learning_rate=learning_rate,epsilon= e),    keras.losses.mean_squared_error                  )tf_model= TFModel(    seed, dim_size, tf.train.AdamOptimizer(learning_rate=learning_rate,epsilon= e),    keras.losses.mean_squared_error                  )X=np.array([[0.25175066, 0.53507285, 0.3210762 ]])#X= np.random.random([1,dim_size])y= np.random.random([1])print(k_adam.keras_grad([X]))print(k_adam.tf_grad(X))print(tf_model.grad(X))print()X= np.array([[0.47194079, 0.85071664, 0.25451934]])#X= np.random.random([1,dim_size])y= np.random.random([1])k_adam.model.train_on_batch(X,y)tf_model.train_on_batch(X,y)print(k_adam.keras_grad([X]))print(k_adam.tf_grad(X))print(tf_model.grad(X))print()X= np.random.random([1,dim_size])y= np.random.random([1])k_adam.model.train_on_batch(X,y)tf_model.train_on_batch(X,y)print(k_adam.keras_grad([X]))print(k_adam.tf_grad(X))print(tf_model.grad(X))

运行代码应该会给你以下输出:

[[-0.63922524  1.0297645  -1.1010152 ]][[-0.63922524  1.0297645  -1.1010152 ]][[-0.63922524  1.0297645  -1.1010152 ]][[-0.62922525  1.0397645  -1.0910152 ]][[-0.63922524  1.0297645  -1.1010152 ]][[-0.62922525  1.0397645  -1.0910152 ]][[ ... ]]....

以及其他一些结果。

对于第一组输出,我期望两个模型计算出的梯度数组是相同的,因为它们是相同的模型。这确实是正确的。

对于第二组输出,我用一组不同的相同输入训练了两个模型。因此,梯度数组应该与第一组输出不同,但它们应该在自己之间是相同的(第二组输出)。这在一定程度上是正确的。Tensorflow模型和keras_grad()的梯度数组在它们之间是相同的,但与第一组不同。

然而,tf_grad()的输出并没有从第一组输出中改变。

根据我自己的测试,我发现tf_grad()的输出在初始化后要么是0,要么是同一组数字。这种行为即使在用不同的批次训练时也会重复出现。

如前所述,tf_grad()keras_grad()的唯一区别是,tf_grad()使用tf.session()运行,而keras_grad()使用keras.backend.function()运行,这两个都是来自Keras模型的。

为什么一个能够相应地更新而另一个不能呢?


回答:

Related Posts

如何使用Google Protobuf解析、编辑和生成object_detection/pipeline.config文件

我在一个常见的集成学习范式中训练多个模型,目前我在处理…

我的GridSearchCV不起作用,我不知道为什么

大家好,我在使用GridSearchCV时遇到了问题,…

Keras: 两个同时进行的层,其中一个对前一层的输出进行卷积

我想实现这样的模型连接: 输入图像1 -> 卷积层1 …

如何将行数据转换为列数据而不使用独热编码

我有一个如下所示的数据集。 MonthDate Day…

使用 ML Kit 与 NNAPI

我正在尝试在运行 Android 9 的设备上使用新的…

Vowpal Wabbit 可能的哈希冲突

我在VW中生成了一个模型,并且在相同的数据上生成了两个…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注