尝试了解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()
),这似乎是很难,因为没有指定名称。仍然混淆为什么返回现有变量而不是零的新张量变量。
答案 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
方法中更新操作。