Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v0.6.0 #39

Merged
merged 54 commits into from
May 22, 2021
Merged

Release v0.6.0 #39

merged 54 commits into from
May 22, 2021

Conversation

keisen
Copy link
Owner

@keisen keisen commented Dec 3, 2020

  • Support mixed-precision of Tensorflow 2.4+, (i.e., NOT support experimental API).
  • Change a terminology that Loss to Score
  • Refactoring Testcases, ActivationMaximization and some utilities
  • Some bugfixes
  • Write docstrings
  • Update example notebook
  • README.md
  • Add tests
  • Update setup.py
  • Write Release note

Closes #24, #43 , #45, #47 and #51

@keisen keisen added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request labels Dec 3, 2020
@keisen keisen self-assigned this Dec 3, 2020
@keisen keisen marked this pull request as ready for review January 31, 2021 09:02
@bersbersbers
Copy link

As the author of #43 and #45, I was interested in testing this using
pip install git+https://github.com/keisen/tf-keras-vis.git@refs/pull/39/merge
First thing I noticed, you are importing packaging now, but it did not auto-install using the above command. Do you maybe need to add it as a dependency?

@bersbersbers
Copy link

bersbersbers commented Feb 19, 2021

Then, this test code does not run. It runs fine without set_policy:

import tensorflow as tf
from tf_keras_vis.activation_maximization import ActivationMaximization

policy = tf.keras.mixed_precision.experimental.Policy("mixed_float16")
tf.keras.mixed_precision.experimental.set_policy(policy)
model = tf.keras.applications.MobileNet()

ActivationMaximization(model)(lambda x: x, tf.zeros(model.input.shape[1:]))
print("Done")

Output is

Exception has occurred: AttributeError       (note: full exception trace is shown but execution is paused at: _run_module_as_main)
'tensorflow.python.framework.ops.EagerTensor' object has no attribute '_in_graph_mode'
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py", line 1366, in _var_key
    if var._in_graph_mode:
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py", line 826, in add_slot
    var_key = _var_key(var)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/rmsprop.py", line 155, in _create_slots
    self.add_slot(var, "rms")
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py", line 783, in _create_all_weights
    self._create_slots(var_list)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py", line 604, in apply_gradients
    self._create_all_weights(var_list)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/mixed_precision/loss_scale_optimizer.py", line 787, in _apply_gradients
    return self._optimizer.apply_gradients(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py", line 3417, in _call_for_each_replica
    return fn(*args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py", line 2730, in call_for_each_replica
    return self._call_for_each_replica(fn, args, kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/mixed_precision/loss_scale_optimizer.py", line 761, in apply_fn
    return distribution.extended.call_for_each_replica(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/framework/smart_cond.py", line 54, in smart_cond
    return true_fn()
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/mixed_precision/loss_scale_optimizer.py", line 776, in _apply_gradients_cross_replica
    maybe_apply_op = smart_cond.smart_cond(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/autograph/impl/api.py", line 572, in wrapper
    return func(*args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py", line 2948, in _merge_call
    return merge_fn(self._strategy, *args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py", line 2941, in merge_call
    return self._merge_call(merge_fn, args, kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/mixed_precision/loss_scale_optimizer.py", line 739, in apply_gradients
    return distribution_strategy_context.get_replica_context().merge_call(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tf_keras_vis/activation_maximization/__init__.py", line 149, in __call__
    optimizer.apply_gradients(zip(grads, seed_inputs))
  File "/home/bers/cia/cia/cnn/bug.py", line 8, in <module>
    ActivationMaximization(model)(lambda x: x, tf.zeros(model.input.shape[1:]))
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 265, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 194, in _run_module_as_main (Current frame)
    return _run_code(code, main_globals, None,

@bersbersbers
Copy link

bersbersbers commented Feb 19, 2021

Then, you seem to rely a lot on the compute policy being set, but that is not actually ensured. Look at this example (run twice to see the error). You might instead rely on model.compute_dtype.

import sys
from pathlib import Path

import tensorflow as tf
from tf_keras_vis.activation_maximization import ActivationMaximization

model_file = Path("bug.tf")

if not model_file.exists():
    policy = tf.keras.mixed_precision.experimental.Policy("mixed_float16")
    tf.keras.mixed_precision.experimental.set_policy(policy)
    model = tf.keras.applications.MobileNet()
    model.save(model_file)
    sys.exit()

model = tf.keras.models.load_model(model_file)
ActivationMaximization(model)(lambda x: x, tf.zeros(model.input.shape[1:]))
print("Done")

Error is

Exception has occurred: ValueError       (note: full exception trace is shown but execution is paused at: _run_module_as_main)
Incompatible type conversion requested to type 'float32' for AutoCastVariable which is casted to type 'float16'
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/mixed_precision/autocast_variable.py", line 132, in _dense_var_to_tensor
    raise ValueError(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/framework/ops.py", line 1540, in convert_to_tensor
    ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/profiler/trace.py", line 163, in wrapped
    return func(*args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/eager/execute.py", line 273, in args_to_matching_eager
    tensor = ops.convert_to_tensor(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/ops/gen_nn_ops.py", line 1019, in conv2d_eager_fallback
    _attr_T, _inputs_T = _execute.args_to_matching_eager([input, filter], ctx, [_dtypes.half, _dtypes.bfloat16, _dtypes.float32, _dtypes.float64, _dtypes.int32, ])
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/ops/gen_nn_ops.py", line 936, in conv2d
    return conv2d_eager_fallback(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/ops/nn_ops.py", line 2597, in _conv2d_expanded_batch
    return gen_nn_ops.conv2d(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/ops/nn_ops.py", line 1143, in convolution_internal
    return op(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/ops/nn_ops.py", line 1013, in convolution_v2
    return convolution_internal(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/util/dispatch.py", line 201, in wrapper
    return target(*args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/layers/convolutional.py", line 248, in call
    outputs = self._convolution_op(inputs, self.kernel)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer.py", line 1012, in __call__
    outputs = call_fn(inputs, *args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/engine/functional.py", line 560, in _run_internal_graph
    outputs = node.layer(*args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/engine/functional.py", line 424, in call
    return self._run_internal_graph(
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer.py", line 1012, in __call__
    outputs = call_fn(inputs, *args, **kwargs)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/site-packages/tf_keras_vis/activation_maximization/__init__.py", line 122, in __call__
    outputs = self.model(seed_inputs, training=training)
  File "/home/bers/cia/cia/cnn/bug.py", line 17, in <module>
    ActivationMaximization(model)(lambda x: x, tf.zeros(model.input.shape[1:]))
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 265, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/data2/bers/opt/pyenv/versions/3.8.7/lib/python3.8/runpy.py", line 194, in _run_module_as_main (Current frame)
    return _run_code(code, main_globals, None,

@keisen
Copy link
Owner Author

keisen commented May 7, 2021

@bersbersbers , Thank you for your code-snippet.
On the second thought, I will put this problem on hold for now.
The design of ActivationMaximization related to regularizes has a known issue (that multiple I/O model is NOT considered fully), for now, I can't think of the way to fix problem concisely.

Thanks!

@bersbersbers
Copy link

bersbersbers commented May 7, 2021

On the second thought, I will put this problem on hold for now.
The design of ActivationMaximization related to regularizes has a known issue (that multiple I/O model is NOT considered fully), for now, I can't think of the way to fix problem concisely.

You're the boss, but do know that I disagree:

  • Unless I am mistaken, the mixed-precision issue has nothing to do the multiple-I/O model. I find ignoring the fixed-precision issue while still allowing full-precision models to use a method that you know has difficulties somewhat questionable. Similarly, why not fix the mixed-precision issue and thereby allow mixed-precision models with single I/O to compute activation maximizations at least?

  • I also don't see the problem you have with the code snipped I posted. The mixed-precision issue is that two numbers (derived from different stages of the network, I guess) cannot be added without casting, so we cast them. Is there anything wrong with this approach?

@keisen
Copy link
Owner Author

keisen commented May 7, 2021

You're the boss, but do know that I disagree:

@bersbersbers , Here is a open source project, so we only have fun and contribute it as possible as we can.

As I said before, unfortunately, I don't have a time enough to do all.
So I decided , at least, v0.6.0 won't support that.
I would do it in v0.7.0 or higher If I could find the time.

Or

@bersbersbers , If you can, please submit a PR that fix this issue.

As I said begore, because here is a open source, you can open and submit a PullRequest.
I may include it to v0.6.0 if the PR merged soon.

Either way, I want to release v0.6.0 soon.
Additionally, I want to keep tf-keras-vis's code clearly and concisely as possible as we can even if it were hard work to support mixed-precision.

Thanks!

@bersbersbers
Copy link

bersbersbers commented May 7, 2021

@bersbersbers , Here is a open source project, so we only have fun and contribute it as possible as we can.

Sure - I did not want to criticize anyone personally, just add my perspective on the issue.

@bersbersbers , If you can, please submit a PR that fix this issue.

I can easily submit #39 (comment) as a PR, if that is your intention. I have tested it locally and it solves the issue.

If you are looking for something else, please let me know what you are looking for. To my first solution, you replied it wasn't "intuitive"; to my second solution, you reacted with a "confused" emoji; and that was all I got as a reply. Really, I am happy to contribute, but after declining two of my solutions you need to give me some additional criteria regarding what you think defines an acceptable solution.

@bersbersbers
Copy link

bersbersbers commented May 20, 2021

@keisen would you mind explaining what you think the bug in TensorFlow is?

@pytest.mark.skip(reson="Because can't avoid error. It may be any bug in Tensorflow.")

I'd like to help isolate and report it upstream, but I don't see where TensorFlow is misbehaving.

Edit: as I see it, the problem is when you add score_values and regularizations, which are of different dtype. score_values is float32, while regularizations is float16. So what is the bug in your opinion?

  1. The fact that score_values is float32? That is due to the model having float32 outputs, by definition of the model, right?
  2. The fact that regularizations is float16? This is due to seed_inputs being float32 (which tf-keras-vis does itself).
  3. The fact that you cannot add float16 to float32? I believe this is expected.

In summary, I don't see where you think the TF bug is.

@bersbersbers
Copy link

bersbersbers commented May 20, 2021

Here's another basic idea to fix this issue.

diff --git a/tf_keras_vis/activation_maximization/__init__.py b/tf_keras_vis/activation_maximization/__init__.py
index 134c52d..d8c31c5 100644
--- a/tf_keras_vis/activation_maximization/__init__.py
+++ b/tf_keras_vis/activation_maximization/__init__.py
@@ -118,6 +118,7 @@ class ActivationMaximization(ModelVisualization):
                 for modifier in input_modifiers[name]:
                     seed_inputs[j] = modifier(seed_inputs[j])
 
+            regularizer_seed_inputs = seed_inputs
             if mixed_precision_enabled:
                 seed_inputs = (tf.cast(X, dtype=lower_precision_dtype(self.model))
                                for X in seed_inputs)
@@ -130,7 +131,7 @@ class ActivationMaximization(ModelVisualization):
                 outputs = listify(outputs)
                 score_values = self._calculate_scores(outputs, scores)
                 # Calculate regularization values
-                regularizations = [(regularizer.name, regularizer(seed_inputs))
+                regularizations = [(regularizer.name, regularizer(regularizer_seed_inputs))
                                    for regularizer in regularizers]
                 regularized_score_values = [
                     (-1. * score_value) + sum([v for _, v in regularizations])

Why does this work? You save the original (float32) input for use with the regularizer, so it's not changed when you cast it to float16 later in case of mixed_precision. That gives you all the expected dtypes everywhere.

If you think it's more maintainable, you can also introduce lower_precision_seed_inputs and leave the original at float32.

@keisen
Copy link
Owner Author

keisen commented May 20, 2021

@bersbersbers I'm sorry for the late reply!

If you are looking for something else, please let me know what you are looking for.

I believe that even if we fixed the error, some problems are still remain. Regularization values may be NaN. Many users may be confused because the results are different for ActivationMaximization with float32-precision and one with mixed-precision.

The reason of my reactions (emoji) are just because those ways can't fix the problem above. I can't decide whether to support mixed-precsion in ActivationMaximization is good or not. So I have no strong motivation to fully support mixed-precision in ActivationMaximization for now.

Thanks your contributions!

@bersbersbers
Copy link

I believe that even if we fixed the error, some problems are still remain.

That is true always and everywhere.

Regularization values may be NaN.

Is that specific to mixed_precision? That's as good an argument as the one with multi-I/O.

Many users may be confused because the results are different for ActivationMaximization with float32-precision and one with mixed-precision.

Well, for one, that is expected - these are different networks. Who would expect different networks to produce the same result?

Second, are users less confused when tf-keras-vis works with float32 and not with mixed-precision? Or when the maintainer references some TensorFlow bug that, frankly, I don't think exists?

Anyway, I will apply the changes mentioned above locally and be happy with them. Thanks and good luck!

@keisen
Copy link
Owner Author

keisen commented May 20, 2021

Here's another basic idea to fix this issue.

It looks good. Is there any impact on calculation result by the patch?

@bersbersbers
Copy link

Here's another basic idea to fix this issue.

It looks good. Is there any impact on calculation result by the patch?

I cannot say really: I don't have any comparison as the code without this patch does not run for my saved mixed-precision models, so this is the only result that I have. And my models take so long to train that I cannot re-train them with full precision now.

I can say that the results I get are somewhat expected, but I was hoping that your testing pipeline could shed more light on the immediate comparison between full/mixed precision

@keisen keisen merged commit 380dacb into master May 22, 2021
@keisen keisen deleted the release/v0.6.0 branch May 22, 2021 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
3 participants