Args: input_tensors ([tf.Tensor]) Returns: output tensors of this tower, evaluated with the input tensors.
(self, *input_tensors)
| 41 | self.cached_model = None |
| 42 | |
| 43 | def __call__(self, *input_tensors): |
| 44 | """ |
| 45 | Args: |
| 46 | input_tensors ([tf.Tensor]) |
| 47 | Returns: |
| 48 | output tensors of this tower, evaluated with the input tensors. |
| 49 | """ |
| 50 | reuse = tf.get_variable_scope().reuse |
| 51 | |
| 52 | old_trainable_names = {x.name for x in tf.trainable_variables()} |
| 53 | trainable_backup = backup_collection([tf.GraphKeys.TRAINABLE_VARIABLES]) |
| 54 | update_ops_backup = backup_collection([tf.GraphKeys.UPDATE_OPS]) |
| 55 | |
| 56 | def post_process_model(model): |
| 57 | added_trainable_names = {x.name for x in tf.trainable_variables()} |
| 58 | restore_collection(trainable_backup) |
| 59 | |
| 60 | for v in model.weights: |
| 61 | # In Keras, the collection is not respected and could contain non-trainable vars. |
| 62 | # We put M.weights into the collection instead. |
| 63 | if v.name not in old_trainable_names and v.name in added_trainable_names: |
| 64 | tf.add_to_collection(tf.GraphKeys.TRAINABLE_VARIABLES, v) |
| 65 | new_trainable_names = {x.name for x in tf.trainable_variables()} |
| 66 | |
| 67 | for n in added_trainable_names: |
| 68 | if n not in new_trainable_names: |
| 69 | logger.warn("Keras created trainable variable '{}' which is actually not trainable. " |
| 70 | "This was automatically corrected.".format(n)) |
| 71 | |
| 72 | # Keras models might not use this collection at all (in some versions). |
| 73 | # This is a BC-breaking change of tf.keras: https://github.com/tensorflow/tensorflow/issues/19643 |
| 74 | restore_collection(update_ops_backup) |
| 75 | for op in model.updates: |
| 76 | tf.add_to_collection(tf.GraphKeys.UPDATE_OPS, op) |
| 77 | |
| 78 | if self.cached_model is None: |
| 79 | assert not reuse |
| 80 | |
| 81 | # starting from some versions, tf.keras starts to prepend name scope to variable names .. |
| 82 | @contextmanager |
| 83 | def clear_tower0_name_scope(): |
| 84 | ns = tf.get_default_graph().get_name_scope() |
| 85 | if ns == 'tower0': |
| 86 | with tf.name_scope('/'): |
| 87 | yield |
| 88 | else: |
| 89 | yield |
| 90 | |
| 91 | with clear_tower0_name_scope(): |
| 92 | model = self.cached_model = self.get_model(*input_tensors) |
| 93 | assert isinstance(model, keras.Model), \ |
| 94 | "Your get_model function should return a `tf.keras.Model`!" |
| 95 | outputs = model.outputs |
| 96 | elif reuse: |
| 97 | # use the cached Keras model to mimic reuse |
| 98 | # NOTE: ctx.is_training won't be useful inside model, |
| 99 | # because inference will always use the cached Keras model |
| 100 | model = self.cached_model |
nothing calls this directly
no test coverage detected