Add update op(s), potentially dependent on layer inputs. Weight updates (for instance, the updates of the moving mean and variance in a BatchNormalization layer) may be dependent on the inputs passed when calling a layer. Hence, when reusing the same layer on different inputs `a` an
(self, updates, inputs=None)
| 1244 | 'inputs') |
| 1245 | @doc_controls.for_subclass_implementers |
| 1246 | def add_update(self, updates, inputs=None): |
| 1247 | """Add update op(s), potentially dependent on layer inputs. |
| 1248 | |
| 1249 | Weight updates (for instance, the updates of the moving mean and variance |
| 1250 | in a BatchNormalization layer) may be dependent on the inputs passed |
| 1251 | when calling a layer. Hence, when reusing the same layer on |
| 1252 | different inputs `a` and `b`, some entries in `layer.updates` may be |
| 1253 | dependent on `a` and some on `b`. This method automatically keeps track |
| 1254 | of dependencies. |
| 1255 | |
| 1256 | The `get_updates_for` method allows to retrieve the updates relevant to a |
| 1257 | specific set of inputs. |
| 1258 | |
| 1259 | This call is ignored when eager execution is enabled (in that case, variable |
| 1260 | updates are run on the fly and thus do not need to be tracked for later |
| 1261 | execution). |
| 1262 | |
| 1263 | Arguments: |
| 1264 | updates: Update op, or list/tuple of update ops, or zero-arg callable |
| 1265 | that returns an update op. A zero-arg callable should be passed in |
| 1266 | order to disable running the updates by setting `trainable=False` |
| 1267 | on this Layer, when executing in Eager mode. |
| 1268 | inputs: Deprecated, will be automatically inferred. |
| 1269 | """ |
| 1270 | if ds_context.has_strategy() and ds_context.in_cross_replica_context(): |
| 1271 | # Updates don't need to be run in a cross-replica context. |
| 1272 | if (ops.executing_eagerly_outside_functions() and |
| 1273 | not base_layer_utils.is_in_keras_graph()): |
| 1274 | raise RuntimeError( # pylint: disable=g-doc-exception |
| 1275 | '`add_update` was called in a cross-replica context. This is not ' |
| 1276 | 'expected. If you require this feature, please file an issue.') |
| 1277 | return |
| 1278 | |
| 1279 | updates = generic_utils.to_list(updates) |
| 1280 | call_context = base_layer_utils.call_context() |
| 1281 | |
| 1282 | # All updates can be run immediately in Eager or in a tf.function. |
| 1283 | if base_layer_utils.is_in_eager_or_tf_function(): |
| 1284 | if not call_context.frozen: |
| 1285 | for update in updates: |
| 1286 | if callable(update): |
| 1287 | update() |
| 1288 | return |
| 1289 | |
| 1290 | if call_context.in_call: |
| 1291 | relevant_inputs = call_context.inputs |
| 1292 | else: |
| 1293 | inbound_nodes = getattr(self, '_inbound_nodes', []) |
| 1294 | relevant_inputs = [node.input_tensors for node in inbound_nodes] |
| 1295 | |
| 1296 | def process_update(x): |
| 1297 | """Standardize update ops. |
| 1298 | |
| 1299 | Arguments: |
| 1300 | x: Tensor, op, or callable. |
| 1301 | |
| 1302 | Returns: |
| 1303 | An update op. |