tf.zeros()是否返回tf.get_variable()?

时间:2018-04-16 16:39:42

标签: python tensorflow machine-learning keras gradient-descent

尝试了解keras优化器中的SGD优化代码(source code)。在get_updates模块中,我们有:

# momentum
shapes = [K.int_shape(p) for p in params]
moments = [K.zeros(shape) for shape in shapes]
self.weights = [self.iterations] + moments
for p, g, m in zip(params, grads, moments):
    v = self.momentum * m - lr * g  # velocity
    self.updates.append(K.update(m, v))

其中K = keras.backend。现在,由于moments被设置为列表零​​张量,m是此列表的迭代,为什么m始终评估为行中的零张量v = self.momentum * m - lr * g

现在我查找了keras.backend.zeros代码的tensorflow(source code),keras.backend.zeros返回tf.zeros,显然会返回一个零的常数张量。 (编辑:或者,如果指定了形状,则返回使用tf.Variable初始化的tf.zeros。)

我的直觉是它会返回类似tf.get_variable()的东西,其初始值为零,因此每次都不会覆盖张量。相反,名为m的张量会不断更新K.update()

tf.zeros()实际上表现得像tf.get_variable(),初始化为零吗?还有其他我想念的东西吗?

编辑:因此,即使指定了形状,上面链接的源代码似乎仍然会返回一个新的张量变量,而不是重用现有的变量(即使用get_variable()),这似乎是很难,因为没有指定名称。仍然混淆为什么返回现有变量而不是零的新张量变量。

1 个答案:

答案 0 :(得分:2)

我认为你错过了正确的K.zeros功能。这是keras 2.1(keras/backend/tensorflow_backend.py)中的源代码:

def zeros(shape, dtype=None, name=None):
    """Instantiates an all-zeros variable and returns it.

    # Arguments
        shape: Tuple of integers, shape of returned Keras variable
        dtype: String, data type of returned Keras variable
        name: String, name of returned Keras variable

    # Returns
        A variable (including Keras metadata), filled with `0.0`.

    # Example
    ```python
        >>> from keras import backend as K
        >>> kvar = K.zeros((3,4))
        >>> K.eval(kvar)
        array([[ 0.,  0.,  0.,  0.],
               [ 0.,  0.,  0.,  0.],
               [ 0.,  0.,  0.,  0.]], dtype=float32)
    ```
    """
    if dtype is None:
        dtype = floatx()
    tf_dtype = tf.as_dtype(dtype)
    return variable(tf.constant_initializer(0., dtype=tf_dtype)(shape),
                    dtype, name)

如您所见,它实际上返回用零初始化的变量,而不是常量的零张量。 documentation表示相同:

  

实例化一个全零变量并将其返回。

修改:后续问题的答案。

这实际上是一个非常好的观察:你是对的,随后对Optimizer.get_updates(loss, params)的调用将创建新的变量,将 new 操作分配给{{1 }和权重到self.updates。从某种意义上说,self.weights方法是优化器构造函数的一部分。

但这是它的工作原理:这个方法每个模型实例被称为一次。它返回在不同批次的循环中多次应用的更新操作列表,但操作本身保持不变。以下是get_updates类(keras/engine/training.py)的相关代码:

Model

def _make_train_function(self): ... if self.train_function is None: ... with K.name_scope('training'): with K.name_scope(self.optimizer.__class__.__name__): training_updates = self.optimizer.get_updates( params=self._collected_trainable_weights, loss=self.total_loss) updates = self.updates + training_updates + self.metrics_updates # Gets loss and metrics. Updates weights at each call. self.train_function = K.function(inputs, [self.total_loss] + self.metrics_tensors, updates=updates, name='train_function', **self._function_kwargs) 只调用一次来构造self.optimizer.get_updates(...)

随意检查其他优化器并检查它们是否都准备好权重并在train_function方法中更新操作。