Skip to content

Conversation

KMChris
Copy link
Contributor

@KMChris KMChris commented Sep 13, 2025

Summary

Modernizes visualkeras for Keras 3/TF >=2.16, removes deprecated APIs, adds robust shape helpers, applies a local patch for nested-model tuple issues, and refines graph_view layout. All tests pass.

Key changes

  • Introduced .gitignore to exclude common Python artifacts and build files.
  • Updated graph_view and layered_view functions to improve compatibility with Keras 2 and 3.
  • Added helper functions to retrieve layer input and output shapes robustly.
  • Applied a patch to ensure single-item outputs are unwrapped correctly in Keras models.

Testing

  • Full suite passes (46 passed, ~20 warnings)
  • Minor, intentional visual diffs in graph_view dimensions

- Introduced .gitignore to exclude common Python artifacts and build files.
- Updated `graph_view` and `layered_view` functions to improve compatibility with Keras 2 and 3.
- Added helper functions to retrieve layer input and output shapes robustly.
- Applied a patch to ensure single-item outputs are unwrapped correctly in Keras models.
@Soontosh
Copy link
Collaborator

Thanks so much for the PR! I'll run the tests on my machine first to see if they pass and then merge.

@Soontosh
Copy link
Collaborator

Thanks again for the PR, but I observed one issue.

from .layer_utils import *
ensure_singleton_sequence_unwrap_patched()

Importing visualkeras now runs ensure_singleton_sequence_unwrap_patches which changes how all keras.Model objects behave (see above code snippet from graph.py). That helper rewrites Model.__call__:

# visualkeras/layer_utils.py
def ensure_singleton_sequence_unwrap_patched():
    import keras
    _orig_call = keras.models.Model.__call__
    def _vk_model_call(self, *args, **kwargs):
        out = _orig_call(self, *args, **kwargs)
        if isinstance(out, (list, tuple)) and len(out) == 1:
            return out[0]
        return out
    keras.models.Model.__call__ = _vk_model_call

After this reassignment, model.__call__ no longer carries certain attributes, so operations like tf.saved_model.save(model) or any code requesting model.__call__.get_concrete_function(...) will fail with AttributeError

Since this happens at import time, anybody who just does import visualkeras would suddenly lose the usual list/tuple output from their own models.

This should be fixed. Do you have any ideas? Maybe something like functools.wraps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants