Add guide for exporting Keras models to LiteRT#2260
Add guide for exporting Keras models to LiteRT#2260pctablet505 wants to merge 2 commits intokeras-team:masterfrom
Conversation
Introduces comprehensive documentation and code examples for exporting Keras models to TensorFlow Lite (LiteRT) format. Includes guides in Jupyter notebook, Python script, and Markdown formats, covering basic export, different model architectures, quantization, dynamic shapes, custom signatures, model validation, and advanced export options. Updates autogen scripts to support the new guide.
Summary of ChangesHello @pctablet505, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the documentation by introducing a detailed guide on exporting Keras models to TensorFlow Lite (LiteRT) format. This new resource provides developers with essential information and practical examples for deploying Keras models efficiently on mobile and edge devices, covering various model types, optimization strategies like quantization, and advanced configuration options. Additionally, it includes a minor update to a Keras project version reference in the autogeneration scripts. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive guide for exporting Keras models to LiteRT, covering various model types, quantization, dynamic shapes, and validation. The guide is well-structured and provides clear examples. The autogen.py and guides_master.py updates correctly integrate the new guide and adjust the Keras project version reference.
guides/litert_export.py
Outdated
| try: | ||
| from ai_edge_litert.interpreter import Interpreter | ||
|
|
||
| print("Using ai_edge_litert for inference") | ||
| litert_available = True | ||
| except ImportError: | ||
| try: | ||
| from tensorflow.lite import Interpreter | ||
|
|
||
| print("Using tensorflow.lite for inference") | ||
| litert_available = True | ||
| except ImportError: | ||
| try: | ||
| import tensorflow as tf | ||
|
|
||
| Interpreter = tf.lite.Interpreter | ||
|
|
||
| print("Using tf.lite.Interpreter for inference") | ||
| litert_available = True | ||
| except (ImportError, AttributeError): | ||
| print("LiteRT interpreter not available. Skipping inference test.") | ||
| print( | ||
| "To test inference, install ai_edge_litert: pip install ai-edge-litert" | ||
| ) |
There was a problem hiding this comment.
The logic for importing the LiteRT interpreter is repeated here and in the validate_tflite_model function. Encapsulating this logic into a helper function would improve code readability and maintainability, adhering to the DRY (Don't Repeat Yourself) principle. This also makes it easier to update the import strategy in the future if needed.
def _get_litert_interpreter_and_status():
"""Attempts to import a LiteRT interpreter and returns its status."""
litert_available = False
Interpreter_class = None
try:
from ai_edge_litert.interpreter import Interpreter as Interpreter_class
print("Using ai_edge_litert for inference")
litert_available = True
except ImportError:
try:
from tensorflow.lite import Interpreter as Interpreter_class
print("Using tensorflow.lite for inference")
litert_available = True
except ImportError:
try:
import tensorflow as tf
Interpreter_class = tf.lite.Interpreter
print("Using tf.lite.Interpreter for inference")
litert_available = True
except (ImportError, AttributeError):
print("LiteRT interpreter not available. Skipping inference test.")
print("To test inference, install ai_edge_litert: pip install ai-edge-litert")
return Interpreter_class, litert_available
Interpreter, litert_available = _get_litert_interpreter_and_status()
divyashreepathihalli
left a comment
There was a problem hiding this comment.
Thank you for the PR! Left some comments!
guides/litert_export.py
Outdated
| """ | ||
| ## Introduction | ||
|
|
||
| TensorFlow Lite (LiteRT) is TensorFlow's solution for running machine learning models |
There was a problem hiding this comment.
This may make it sound like it is a tensorflow solution.
Maybe reword it to - "LiteRT is a solution for running machine learning models..."
|
|
||
| # Generate dummy data for demonstration | ||
| X_train = np.random.random((1000, 28, 28)) | ||
| y_train = np.random.randint(0, 10, 1000) |
There was a problem hiding this comment.
Keep the names consistent
X_train> x_train
guides/litert_export.py
Outdated
|
|
||
| # Load and test the exported model | ||
| litert_available = False | ||
| try: |
There was a problem hiding this comment.
This is a demo colab - you should assume the environment will support the interpreter instead of this nested try except blocks. please remove.
guides/litert_export.py
Outdated
| output = interpreter.get_tensor(output_details[0]["index"]) | ||
|
|
||
| print(f"\nInference successful! Output shape: {output.shape}") | ||
| else: |
There was a problem hiding this comment.
remove the if else block
and let the block throw an error
guides/litert_export.py
Outdated
| """ | ||
|
|
||
| keras_hub_available = False | ||
| try: |
There was a problem hiding this comment.
remove the try except blocks!
Please add relevant install instructions in the beginning of the Colab - for what is needed to run this guide.
guides/litert_export.py
Outdated
| print("keras-hub not available. Skipping Keras-Hub example.") | ||
| print("To run this example, install keras-hub: pip install keras-hub") | ||
|
|
||
| if keras_hub_available: |
There was a problem hiding this comment.
remove the if and try blocks - if there is an error let it throw the error
guides/litert_export.py
Outdated
| vision_model.export("resnet.tflite", format="litert") | ||
|
|
||
| print("Exported Keras-Hub vision model") | ||
| except Exception as e: |
There was a problem hiding this comment.
remove the try and except!
guides/litert_export.py
Outdated
| - **Memory issues**: Reduce model size with quantization | ||
| - **Accuracy drops**: Start with float16 instead of full int8 quantization | ||
|
|
||
| ## Next Steps |
There was a problem hiding this comment.
are these next steps guide available? - if not - lets remove
|
@gemini-code-assist review |
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive guide on exporting Keras models to LiteRT (TensorFlow Lite) format. The guide is provided in Jupyter Notebook, Python script, and Markdown formats. The changes also include adding the new guide to the site's master list and updating a Keras version reference in an autogeneration script.
My review focuses on improving the code examples in the new guide to follow Keras best practices, such as using keras.Input for defining model input shapes. I've also suggested a minor improvement for character encoding to ensure cross-platform compatibility. The changes to the build scripts look good.
| "# Create a simple MNIST classifier\n", | ||
| "model = keras.Sequential(\n", | ||
| " [\n", | ||
| " keras.layers.Flatten(input_shape=(28, 28)),\n", |
There was a problem hiding this comment.
While using input_shape in the first layer works, the recommended best practice for Sequential models is to use a keras.Input object as the first layer. This makes the model's inputs and their shapes more explicit.
Here's how you could refactor the model definition:
model = keras.Sequential(
[
keras.Input(shape=(28, 28)),
keras.layers.Flatten(),
keras.layers.Dense(128, activation="relu"),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation="softmax"),
]
)| "# Create a model for quantization\n", | ||
| "quantization_model = keras.Sequential(\n", | ||
| " [\n", | ||
| " keras.layers.Dense(64, activation=\"relu\", input_shape=(784,)),\n", |
There was a problem hiding this comment.
For clarity and consistency with best practices, it's better to define the input shape of a Sequential model using a keras.Input layer instead of the input_shape argument in the first layer.
Here's how you could refactor it:
quantization_model = keras.Sequential(
[
keras.Input(shape=(784,)),
keras.layers.Dense(64, activation="relu"),
keras.layers.Dense(32, activation="relu"),
keras.layers.Dense(10, activation="softmax"),
]
)| "dynamic_model = keras.Sequential(\n", | ||
| " [\n", | ||
| " keras.layers.Dense(64, activation=\"relu\"),\n", | ||
| " keras.layers.Dense(10, activation=\"softmax\"),\n", | ||
| " ]\n", | ||
| ")\n", | ||
| "\n", | ||
| "# Use None for dynamic dimensions\n", | ||
| "dynamic_model.build((None, 784)) # None = dynamic batch size\n", |
There was a problem hiding this comment.
Instead of defining an empty Sequential model and then calling .build(), you can define the input shape directly using a keras.Input layer. This makes the model definition more self-contained and readable. Using batch_size=None in keras.Input explicitly declares a dynamic batch size.
Here's a suggested refactoring:
dynamic_model = keras.Sequential(
[
keras.Input(shape=(784,), batch_size=None), # None = dynamic batch size
keras.layers.Dense(64, activation="relu"),
keras.layers.Dense(10, activation="softmax"),
]
)| # Create a simple MNIST classifier | ||
| model = keras.Sequential( | ||
| [ | ||
| keras.layers.Flatten(input_shape=(28, 28)), |
There was a problem hiding this comment.
While using input_shape in the first layer works, the recommended best practice for Sequential models is to use a keras.Input object as the first layer. This makes the model's inputs and their shapes more explicit.
Here's how you could refactor the model definition:
model = keras.Sequential(
[
keras.Input(shape=(28, 28)),
keras.layers.Flatten(),
keras.layers.Dense(128, activation="relu"),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation="softmax"),
]
)| # Create a model for quantization | ||
| quantization_model = keras.Sequential( | ||
| [ | ||
| keras.layers.Dense(64, activation="relu", input_shape=(784,)), |
There was a problem hiding this comment.
For clarity and consistency with best practices, it's better to define the input shape of a Sequential model using a keras.Input layer instead of the input_shape argument in the first layer.
Here's how you could refactor it:
quantization_model = keras.Sequential(
[
keras.Input(shape=(784,)),
keras.layers.Dense(64, activation="relu"),
keras.layers.Dense(32, activation="relu"),
keras.layers.Dense(10, activation="softmax"),
]
)|
|
||
| # Compare outputs | ||
| np.testing.assert_allclose(keras_output.numpy(), tflite_output, atol=1e-5) | ||
| print("✓ Model validation passed!") |
There was a problem hiding this comment.
| # Create a simple MNIST classifier | ||
| model = keras.Sequential( | ||
| [ | ||
| keras.layers.Flatten(input_shape=(28, 28)), |
There was a problem hiding this comment.
While using input_shape in the first layer works, the recommended best practice for Sequential models is to use a keras.Input object as the first layer. This makes the model's inputs and their shapes more explicit.
Here's how you could refactor the model definition:
model = keras.Sequential(
[
keras.Input(shape=(28, 28)),
keras.layers.Flatten(),
keras.layers.Dense(128, activation="relu"),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation="softmax"),
]
)| # Create a model for quantization | ||
| quantization_model = keras.Sequential( | ||
| [ | ||
| keras.layers.Dense(64, activation="relu", input_shape=(784,)), |
There was a problem hiding this comment.
For clarity and consistency with best practices, it's better to define the input shape of a Sequential model using a keras.Input layer instead of the input_shape argument in the first layer.
Here's how you could refactor it:
quantization_model = keras.Sequential(
[
keras.Input(shape=(784,)),
keras.layers.Dense(64, activation="relu"),
keras.layers.Dense(32, activation="relu"),
keras.layers.Dense(10, activation="softmax"),
]
)| # Create model with dynamic batch size | ||
| dynamic_model = keras.Sequential( | ||
| [ | ||
| keras.layers.Dense(64, activation="relu"), | ||
| keras.layers.Dense(10, activation="softmax"), | ||
| ] | ||
| ) | ||
|
|
||
| # Use None for dynamic dimensions | ||
| dynamic_model.build((None, 784)) # None = dynamic batch size |
There was a problem hiding this comment.
Instead of defining an empty Sequential model and then calling .build(), you can define the input shape directly using a keras.Input layer. This makes the model definition more self-contained and readable. Using batch_size=None in keras.Input explicitly declares a dynamic batch size.
Here's a suggested refactoring:
# Create model with dynamic batch size
dynamic_model = keras.Sequential(
[
keras.Input(shape=(784,), batch_size=None), # None = dynamic batch size
keras.layers.Dense(64, activation="relu"),
keras.layers.Dense(10, activation="softmax"),
]
)|
|
||
| # Compare outputs | ||
| np.testing.assert_allclose(keras_output.numpy(), tflite_output, atol=1e-5) | ||
| print("✓ Model validation passed!") |
There was a problem hiding this comment.
This pull request introduces a new guide to the guides list and updates the Keras project version reference in the
autogen.pyscript. The main changes are as follows:Guides update:
litert_exportand the title "Exporting Keras models to LiteRT" to the guides configuration inguides_master.py.Version reference update:
PROJECT_URLdictionary inautogen.pyto reference versionv3.13.0instead ofv3.13.1.Introduces comprehensive documentation and code examples for exporting Keras models to TensorFlow Lite (LiteRT) format. Includes guides in Jupyter notebook, Python script, and Markdown formats, covering basic export, different model architectures, quantization, dynamic shapes, custom signatures, model validation, and advanced export options. Updates autogen scripts to support the new guide.