a model grouping layers into an object with traininginference features there are three ways to instantiate a model with the functional api you start from input you chain layer calls to specify the model s forward pass and finally you create your model from inputs and outputs python inputs keras inputshape37 x keras layers dense32 activationreluinputs outputs keras layers dense5 activationsoftmaxx model keras modelinputsinputs outputsoutputs note only dicts lists and tuples of input tensors are supported nested inputs are not supported e g lists of list or dicts of dict a new functional api model can also be using the intermediate tensors this enables you to quickly extract subcomponents of the model example python inputs keras inputshapenone none 3 processed keras layers randomcropwidth128 height128inputs conv keras layers conv2dfilters32 kernelsize3processed pooling keras layers globalaveragepooling2dconv feature keras layers dense10pooling fullmodel keras modelinputs feature backbone keras modelprocessed conv activations keras modelconv feature note that the backbone and activations models are not created with keras input objects but with the tensors that originate from keras input objects under the hood the layers and weights will be shared across these models so that user can train the fullmodel and use backbone or activations to do feature extraction the inputs and outputs of the model can be nested structures of tensors as well and the created models are standard functional api models that support all the existing apis by subclassing the model class in that case you should define your layers in init and you should implement the model s forward pass in call python class mymodelkeras model def initself super init self dense1 keras layers dense32 activationrelu self dense2 keras layers dense5 activationsoftmax def callself inputs x self dense1inputs return self dense2x model mymodel if you subclass model you can optionally have a training argument boolean in call which you can use to specify a different behavior in training and inference python class mymodelkeras model def initself super init self dense1 keras layers dense32 activationrelu self dense2 keras layers dense5 activationsoftmax self dropout keras layers dropout0 5 def callself inputs trainingfalse x self dense1inputs x self dropoutx trainingtraining return self dense2x model mymodel once the model is created you can config the model with losses and metrics with model compile train the model with model fit or use the model to do prediction with model predict with the sequential class in addition keras sequential is a special case of model where the model is purely a stack of singleinput singleoutput layers python model keras sequential keras inputshapenone none 3 keras layers conv2dfilters32 kernelsize3 signature detection for usage of model as a functional signature detection for usage of a model subclass as a functional subclass retrieves a layer based on either its name unique or index if name and index are both provided index will take precedence indices are based on order of horizontal graph traversal bottomup args name string name of layer index integer index of layer returns a layer instance prints a string summary of the network args linelength total length of printed lines e g set this to adapt the display to different terminal window sizes positions relative or absolute positions of log elements in each line if not provided becomes 0 3 0 6 0 70 1 defaults to none printfn print function to use by default prints to stdout if stdout doesn t work in your environment change to print it will be called on each line of the summary you can set it to a custom function in order to capture the string summary expandnested whether to expand the nested models defaults to false showtrainable whether to show if a layer is trainable defaults to false layerrange a list or tuple of 2 strings which is the starting layer name and ending layer name both inclusive indicating the range of layers to be printed in summary it also accepts regex patterns instead of exact name in such case start predicate will be the first element it matches to layerrange0 and the end predicate will be the last element it matches to layerrange1 by default none which considers all layers of model raises valueerror if summary is called before the model is built saves a model as a keras file args filepath str or pathlib path object path where to save the model must end in keras overwrite whether we should overwrite any existing model at the target location or instead ask the user via an interactive prompt saveformat the saveformat argument is deprecated in keras 3 format to use as a string only the keras format is supported at this time example python model keras sequential keras layers dense5 inputshape3 keras layers softmax model savemodel keras loadedmodel keras saving loadmodelmodel keras x keras random uniform10 3 assert np allclosemodel predictx loadedmodel predictx note that model save is an alias for keras saving savemodel the saved keras file contains the model s configuration architecture the model s weights the model s optimizer s state if any thus models can be reinstantiated in the exact same state saves all layer weights to a weights h5 file args filepath str or pathlib path object path where to save the model must end in weights h5 overwrite whether we should overwrite any existing model at the target location or instead ask the user via an interactive prompt load weights from a file saved via saveweights weights are loaded based on the network s topology this means the architecture should be the same as when the weights were saved note that layers that don t have weights are not taken into account in the topological ordering so adding or removing layers is fine as long as they don t have weights partial weight loading if you have modified your model for instance by adding a new layer with weights or by changing the shape of the weights of a layer you can choose to ignore errors and continue loading by setting skipmismatchtrue in this case any layer with mismatching weights will be skipped a warning will be displayed for each skipped layer args filepath string path to the weights file to load it can either be a weights h5 file or a legacy h5 weights file skipmismatch boolean whether to skip loading of layers where there is a mismatch in the number of weights or a mismatch in the shape of the weights case all inputs are in the first arg possibly nested case inputs were recorded as multiple keyword arguments returns a json string containing the network configuration to load a network from a json save file use keras models modelfromjsonjsonstring customobjects args kwargs additional keyword arguments to be passed to json dumps returns a json string tf backend only create a tf savedmodel artifact for inference e g via tfserving note this can currently only be used with the tf backend this method lets you export a model to a lightweight savedmodel artifact that contains the model s forward pass only its call method and can be served via e g tfserving the forward pass is registered under the name serve see example below the original code of the model including any custom layers you may have used is no longer necessary to reload the artifact it is entirely standalone args filepath str or pathlib path object path where to save the artifact example python create the artifact model exportpathtolocation later in a different process environment reloadedartifact tf savedmodel loadpathtolocation predictions reloadedartifact serveinputdata if you would like to customize your serving endpoints you can use the lowerlevel keras export exportarchive class the export method relies on exportarchive internally revive functional model but not functional subclasses with a custom init either the model has a custom init or the config does not contain all the information necessary to revive a functional model this happens when the user creates subclassed models where getconfig is returning insufficient information to be considered a functional model in this case we fall back to provide all config into the constructor of the class parses a json model configuration string and returns a model instance usage model keras sequential keras layers dense5 inputshape3 keras layers softmax config model tojson loadedmodel keras models modelfromjsonconfig args jsonstring json string encoding a model configuration customobjects optional dictionary mapping names strings to custom classes or functions to be considered during deserialization returns a keras model instance uncompiled inject functional into the hierarchy of this class if needed from keras models import functional if cls model return functional functional in case there is any multiple inheritance we stop injecting the class if keras model is not in its class hierarchy if cls object return object cls bases tuple injectfunctionalmodelclassbase for base in cls bases trigger any new class swapping that needed to happen on functional but did not because functional was not in the class hierarchy cls newcls return cls model fit doc basetrainer trainer fit doc model predict doc basetrainer trainer predict doc model evaluate doc basetrainer trainer evaluate doc model trainonbatch doc basetrainer trainer trainonbatch doc model testonbatch doc basetrainer trainer testonbatch doc model predictonbatch doc basetrainer trainer predictonbatch doc a model grouping layers into an object with training inference features there are three ways to instantiate a model with the functional api you start from input you chain layer calls to specify the model s forward pass and finally you create your model from inputs and outputs python inputs keras input shape 37 x keras layers dense 32 activation relu inputs outputs keras layers dense 5 activation softmax x model keras model inputs inputs outputs outputs note only dicts lists and tuples of input tensors are supported nested inputs are not supported e g lists of list or dicts of dict a new functional api model can also be using the intermediate tensors this enables you to quickly extract sub components of the model example python inputs keras input shape none none 3 processed keras layers randomcrop width 128 height 128 inputs conv keras layers conv2d filters 32 kernel_size 3 processed pooling keras layers globalaveragepooling2d conv feature keras layers dense 10 pooling full_model keras model inputs feature backbone keras model processed conv activations keras model conv feature note that the backbone and activations models are not created with keras input objects but with the tensors that originate from keras input objects under the hood the layers and weights will be shared across these models so that user can train the full_model and use backbone or activations to do feature extraction the inputs and outputs of the model can be nested structures of tensors as well and the created models are standard functional api models that support all the existing apis by subclassing the model class in that case you should define your layers in __init__ and you should implement the model s forward pass in call python class mymodel keras model def __init__ self super __init__ self dense1 keras layers dense 32 activation relu self dense2 keras layers dense 5 activation softmax def call self inputs x self dense1 inputs return self dense2 x model mymodel if you subclass model you can optionally have a training argument boolean in call which you can use to specify a different behavior in training and inference python class mymodel keras model def __init__ self super __init__ self dense1 keras layers dense 32 activation relu self dense2 keras layers dense 5 activation softmax self dropout keras layers dropout 0 5 def call self inputs training false x self dense1 inputs x self dropout x training training return self dense2 x model mymodel once the model is created you can config the model with losses and metrics with model compile train the model with model fit or use the model to do prediction with model predict with the sequential class in addition keras sequential is a special case of model where the model is purely a stack of single input single output layers python model keras sequential keras input shape none none 3 keras layers conv2d filters 32 kernel_size 3 signature detection for usage of model as a functional signature detection for usage of a model subclass as a functional subclass retrieves a layer based on either its name unique or index if name and index are both provided index will take precedence indices are based on order of horizontal graph traversal bottom up args name string name of layer index integer index of layer returns a layer instance prints a string summary of the network args line_length total length of printed lines e g set this to adapt the display to different terminal window sizes positions relative or absolute positions of log elements in each line if not provided becomes 0 3 0 6 0 70 1 defaults to none print_fn print function to use by default prints to stdout if stdout doesn t work in your environment change to print it will be called on each line of the summary you can set it to a custom function in order to capture the string summary expand_nested whether to expand the nested models defaults to false show_trainable whether to show if a layer is trainable defaults to false layer_range a list or tuple of 2 strings which is the starting layer name and ending layer name both inclusive indicating the range of layers to be printed in summary it also accepts regex patterns instead of exact name in such case start predicate will be the first element it matches to layer_range 0 and the end predicate will be the last element it matches to layer_range 1 by default none which considers all layers of model raises valueerror if summary is called before the model is built saves a model as a keras file args filepath str or pathlib path object path where to save the model must end in keras overwrite whether we should overwrite any existing model at the target location or instead ask the user via an interactive prompt save_format the save_format argument is deprecated in keras 3 format to use as a string only the keras format is supported at this time example python model keras sequential keras layers dense 5 input_shape 3 keras layers softmax model save model keras loaded_model keras saving load_model model keras x keras random uniform 10 3 assert np allclose model predict x loaded_model predict x note that model save is an alias for keras saving save_model the saved keras file contains the model s configuration architecture the model s weights the model s optimizer s state if any thus models can be reinstantiated in the exact same state saves all layer weights to a weights h5 file args filepath str or pathlib path object path where to save the model must end in weights h5 overwrite whether we should overwrite any existing model at the target location or instead ask the user via an interactive prompt load weights from a file saved via save_weights weights are loaded based on the network s topology this means the architecture should be the same as when the weights were saved note that layers that don t have weights are not taken into account in the topological ordering so adding or removing layers is fine as long as they don t have weights partial weight loading if you have modified your model for instance by adding a new layer with weights or by changing the shape of the weights of a layer you can choose to ignore errors and continue loading by setting skip_mismatch true in this case any layer with mismatching weights will be skipped a warning will be displayed for each skipped layer args filepath string path to the weights file to load it can either be a weights h5 file or a legacy h5 weights file skip_mismatch boolean whether to skip loading of layers where there is a mismatch in the number of weights or a mismatch in the shape of the weights case all inputs are in the first arg possibly nested case inputs were recorded as multiple keyword arguments returns a json string containing the network configuration to load a network from a json save file use keras models model_from_json json_string custom_objects args kwargs additional keyword arguments to be passed to json dumps returns a json string tf backend only create a tf savedmodel artifact for inference e g via tf serving note this can currently only be used with the tf backend this method lets you export a model to a lightweight savedmodel artifact that contains the model s forward pass only its call method and can be served via e g tf serving the forward pass is registered under the name serve see example below the original code of the model including any custom layers you may have used is no longer necessary to reload the artifact it is entirely standalone args filepath str or pathlib path object path where to save the artifact example python create the artifact model export path to location later in a different process environment reloaded_artifact tf saved_model load path to location predictions reloaded_artifact serve input_data if you would like to customize your serving endpoints you can use the lower level keras export exportarchive class the export method relies on exportarchive internally revive functional model but not functional subclasses with a custom __init__ either the model has a custom __init__ or the config does not contain all the information necessary to revive a functional model this happens when the user creates subclassed models where get_config is returning insufficient information to be considered a functional model in this case we fall back to provide all config into the constructor of the class parses a json model configuration string and returns a model instance usage model keras sequential keras layers dense 5 input_shape 3 keras layers softmax config model to_json loaded_model keras models model_from_json config args json_string json string encoding a model configuration custom_objects optional dictionary mapping names strings to custom classes or functions to be considered during deserialization returns a keras model instance uncompiled inject functional into the hierarchy of this class if needed in case there is any multiple inheritance we stop injecting the class if keras model is not in its class hierarchy trigger any __new__ class swapping that needed to happen on functional but did not because functional was not in the class hierarchy
import inspect
import json
import os
import warnings

from keras import backend
from keras import utils
from keras.api_export import keras_export
from keras.layers.layer import Layer
from keras.models.variable_mapping import map_trackable_variables
from keras.saving import saving_api
from keras.saving import saving_lib
from keras.trainers import trainer as base_trainer
from keras.utils import io_utils
from keras.utils import summary_utils
from keras.utils import traceback_utils

if backend.backend() == "tensorflow":
    from keras.backend.tensorflow.trainer import TensorFlowTrainer as Trainer
elif backend.backend() == "jax":
    from keras.backend.jax.trainer import JAXTrainer as Trainer
elif backend.backend() == "torch":
    from keras.backend.torch.trainer import TorchTrainer as Trainer
elif backend.backend() == "numpy":
    from keras.backend.numpy.trainer import NumpyTrainer as Trainer
else:
    raise RuntimeError(
        f"Backend '{backend.backend()}' must implement the Trainer class."
    )


@keras_export(["keras.Model", "keras.models.Model"])
class Model(Trainer, Layer):
    

    def __new__(cls, *args, **kwargs):
        
        if functional_init_arguments(args, kwargs) and cls == Model:
            from keras.models import functional

            return functional.Functional(*args, **kwargs)
        return super().__new__(cls)

    def __init__(self, *args, **kwargs):
        Trainer.__init__(self)
        from keras.models import functional

        
        
        if functional_init_arguments(args, kwargs):
            inject_functional_model_class(self.__class__)
            functional.Functional.__init__(self, *args, **kwargs)
        else:
            Layer.__init__(self, *args, **kwargs)

    def call(self, *args, **kwargs):
        raise NotImplementedError(
            f"Model {self.__class__.__name__} does not have a `call()` "
            "method implemented."
        )

    @property
    def layers(self):
        return list(self._flatten_layers(include_self=False, recursive=False))

    @layers.setter
    def layers(self, _):
        raise AttributeError(
            "`Model.layers` attribute is reserved and should not be used. "
            "Please use another name."
        )

    @traceback_utils.filter_traceback
    def get_layer(self, name=None, index=None):
        
        if index is not None and name is not None:
            raise ValueError(
                "Provide only a layer name or a layer index. Received: "
                f"index={index}, name={name}."
            )
        if index is not None:
            if len(self.layers) <= index:
                raise ValueError(
                    f"Was asked to retrieve layer at index {index}"
                    f" but model only has {len(self.layers)}"
                    " layers."
                )
            else:
                return self.layers[index]

        if name is not None:
            for layer in self.layers:
                if layer.name == name:
                    return layer
            raise ValueError(
                f"No such layer: {name}. Existing layers are: "
                f"{list(layer.name for layer in self.layers)}."
            )
        raise ValueError(
            "Provide either a layer name or layer index at `get_layer`."
        )

    @traceback_utils.filter_traceback
    def summary(
        self,
        line_length=None,
        positions=None,
        print_fn=None,
        expand_nested=False,
        show_trainable=False,
        layer_range=None,
    ):
        
        summary_utils.print_summary(
            self,
            line_length=line_length,
            positions=positions,
            print_fn=print_fn,
            expand_nested=expand_nested,
            show_trainable=show_trainable,
            layer_range=layer_range,
        )

    @traceback_utils.filter_traceback
    def save(self, filepath, overwrite=True, **kwargs):
        
        return saving_api.save_model(self, filepath, overwrite, **kwargs)

    @traceback_utils.filter_traceback
    def save_weights(self, filepath, overwrite=True):
        
        if not str(filepath).endswith(".weights.h5"):
            raise ValueError(
                "The filename must end in `.weights.h5`. "
                f"Received: filepath={filepath}"
            )
        try:
            exists = os.path.exists(filepath)
        except TypeError:
            exists = False
        if exists and not overwrite:
            proceed = io_utils.ask_to_proceed_with_overwrite(filepath)
            if not proceed:
                return
        saving_lib.save_weights_only(self, filepath)

    @traceback_utils.filter_traceback
    def load_weights(self, filepath, skip_mismatch=False, **kwargs):
        
        saving_api.load_weights(
            self, filepath, skip_mismatch=skip_mismatch, **kwargs
        )

    def build_from_config(self, config):
        if not config:
            return
        if "input_shape" in config:
            
            if utils.is_default(self.build):
                status = self._build_by_run_for_single_pos_arg(
                    config["input_shape"]
                )
            else:
                try:
                    self.build(config["input_shape"])
                    status = True
                except:
                    status = False
            self._build_shapes_dict = config

        elif "shapes_dict" in config:
            
            if utils.is_default(self.build):
                status = self._build_by_run_for_kwargs(config["shapes_dict"])
            else:
                try:
                    self.build(**config["shapes_dict"])
                    status = True
                except:
                    status = False
            self._build_shapes_dict = config["shapes_dict"]

        if not status:
            warnings.warn(
                f"Model '{self.name}' had a build config, but the model "
                "cannot be built automatically in "
                "`build_from_config(config)`. "
                "You should implement "
                "`def build_from_config(self, config)`, "
                "and you might also want to implement the method "
                " that generates the config at saving time, "
                "`def get_build_config(self)`. "
                "The method `build_from_config()` is meant to "
                "create the state of the model (i.e. its variables) "
                "upon deserialization.",
                stacklevel=2,
            )

    def to_json(self, **kwargs):
        
        from keras.saving import serialization_lib

        model_config = serialization_lib.serialize_keras_object(self)
        return json.dumps(model_config, **kwargs)

    def export(self, filepath, format="tf_saved_model"):
        
        from keras.export import export_lib

        export_lib.export_model(self, filepath)

    @classmethod
    def from_config(cls, config, custom_objects=None):
        from keras.models.functional import Functional

        functional_config_keys = [
            "name",
            "layers",
            "input_layers",
            "output_layers",
        ]
        is_functional_config = all(
            key in config for key in functional_config_keys
        )
        argspec = inspect.getfullargspec(cls.__init__)
        functional_init_args = inspect.getfullargspec(Functional.__init__).args[
            1:
        ]
        revivable_as_functional = (
            cls in {Functional, Model}
            or argspec.args[1:] == functional_init_args
            or (argspec.varargs == "args" and argspec.varkw == "kwargs")
        )
        if is_functional_config and revivable_as_functional:
            
            
            from keras.models.functional import functional_from_config

            return functional_from_config(
                cls, config, custom_objects=custom_objects
            )

        
        
        
        
        
        
        
        try:
            return cls(**config)
        except TypeError as e:
            raise TypeError(
                "Unable to revive model from config. When overriding "
                "the `get_config()` method, make sure that the "
                "returned config contains all items used as arguments "
                f"in the  constructor to {cls}, "
                "which is the default behavior. "
                "You can override this default behavior by defining a "
                "`from_config(cls, config)` class method to specify "
                "how to create an "
                f"instance of {cls.__name__} from its config.\n\n"
                f"Received config={config}\n\n"
                f"Error encountered during deserialization: {e}"
            )

    def _get_variable_map(self):
        store = {}
        map_trackable_variables(self, store=store, visited_trackables=set())
        return store


@keras_export("keras.models.model_from_json")
def model_from_json(json_string, custom_objects=None):
    
    from keras.saving import serialization_lib

    model_config = json.loads(json_string)
    return serialization_lib.deserialize_keras_object(
        model_config, custom_objects=custom_objects
    )


def functional_init_arguments(args, kwargs):
    return (
        (len(args) == 2)
        or (len(args) == 1 and "outputs" in kwargs)
        or ("inputs" in kwargs and "outputs" in kwargs)
    )


def inject_functional_model_class(cls):
    
    from keras.models import functional

    if cls == Model:
        return functional.Functional
    
    
    if cls == object:
        return object

    cls.__bases__ = tuple(
        inject_functional_model_class(base) for base in cls.__bases__
    )
    
    
    cls.__new__(cls)

    return cls


Model.fit.__doc__ = base_trainer.Trainer.fit.__doc__
Model.predict.__doc__ = base_trainer.Trainer.predict.__doc__
Model.evaluate.__doc__ = base_trainer.Trainer.evaluate.__doc__
Model.train_on_batch.__doc__ = base_trainer.Trainer.train_on_batch.__doc__
Model.test_on_batch.__doc__ = base_trainer.Trainer.test_on_batch.__doc__
Model.predict_on_batch.__doc__ = base_trainer.Trainer.predict_on_batch.__doc__