-
Notifications
You must be signed in to change notification settings - Fork 454
Keras v3 Support #1116
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
base: main
Are you sure you want to change the base?
Keras v3 Support #1116
Conversation
This PR will be rebased after its prerequisites are merged to resolve the conflicts. |
if keras.__version__ > '3.0': | ||
layer_list, *_ = hls4ml.converters.parse_keras_v3_model(model) | ||
else: | ||
model_arch = json.loads(model.to_json()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if the case was used in practice, but the old logic allows model to be a dict, and only if it's not not a dict, only then model_arch = json.loads(model.to_json())
. Does the logic here work if model is a dict?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dict is a representation of a json. we work with a dict that was a json of a model whether made by us or, in the old days, by the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
model.get_config
has slightly different behavior, where objects may be passed as-is (not serialized). v2 converter assumes a dict of fully serialized model config, so serialize+deserialize is used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cosmetics mostly. run ruff on changed files before merging
docs/frontend/keras.rst
Outdated
|
||
The ``data_format='channels_first'`` parameter of Keras layers is supported, but not extensively tested. All HLS implementations in ``hls4ml`` are based on ``channels_last`` data format and need to be converted to that format before the HLS code can be emitted. We encourage users of ``channels_first`` to report their experiences to developers on GitHub. | ||
|
||
|
||
* `QKeras <https://github.com/fastmachinelearning/qkeras>`_ | ||
The equivalent QKeras API and its quantizers are also supported by ``hls4ml``. QKeras is not compatible with Keras v3. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mention the alternatives (from Marius, HGQ2, via quantizers lib etc)
docs/intro/setup.rst
Outdated
* `TensorFlow <https://pypi.org/project/tensorflow/>`_ (version 2.8 to 2.14) and `QKeras <https://pypi.org/project/qkeras/>`_ are required by the Keras converter. One may want to install newer versions of QKeras from GitHub. Newer versions of TensorFlow can be used, but QKeras and hl4ml do not currently support Keras v3. | ||
The ``hls4ml`` library requires python 3.10 or later, and depends on a number of Python packages and external tools for synthesis and simulation. Python dependencies are automatically managed by ``pip`` or ``conda``. | ||
|
||
The following Python packages are all optional and are only required if you intend to use the corresponding converter. Only install the packages you need. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the advice "only install packages you need" was already given above
hls4ml/converters/__init__.py
Outdated
@@ -9,6 +9,7 @@ | |||
from hls4ml.converters.keras_to_hls import get_supported_keras_layers # noqa: F401 | |||
from hls4ml.converters.keras_to_hls import parse_keras_model # noqa: F401 | |||
from hls4ml.converters.keras_to_hls import keras_to_hls, register_keras_layer_handler | |||
from hls4ml.converters.keras_v3_to_hls import parse_keras_v3_model # noqa: F401 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename keras_to_hls
to keras_v2_to_hls
# EinsumDense config | ||
params = default_params.copy() | ||
params['strategy'] = strategy | ||
params['n_free0'] = node.attributes.attributes['n_free0'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use either node.attributes[]
or node.get_attr()
static const unsigned strategy; | ||
static const unsigned reuse_factor; | ||
static const unsigned multiplier_limit; | ||
static const bool store_weights_in_bram = false; // NOT USED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove it then
@@ -0,0 +1,516 @@ | |||
import math |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep for now for internal testing (as it is not triggered by the CI), but will be abandoned in the future in favor of spread out tests
def get_io_tensors(layer: 'keras.Layer', node_whitelist: set[int] | None = None): | ||
'''Given a keras layer, return a list of tuples of input and output | ||
tensors. If the layer is called only once (i.e., no shared layers), | ||
the list will contain only one tuple. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add an example where this will happen
return None | ||
return handler(layer, inp_tensors, out_tensors) | ||
|
||
def v2_call( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a comment on the rough list of layers that use this feature as this is to be deprecated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't really think of useful layers not yet covered. Haven't seen the fallback warning for a while.
A# Description
Add keras v3 specific object-based parser and some layer handlers (no h5 or json loading supported). The current keras parser doesn't work with v3 functional models in general.
Type of change
Tests
test/pytest/test_keras_v3_api.py
Test Configuration:
Requires
keras>=3.0
. Skips the whole module if this requirement is not sufficed.Checklist
pre-commit
on the files I edited or added.