def get_image_classifier_kr(
    loss_name="categorical_crossentropy", loss_type="function_losses", from_logits=False, load_init=True
):
    """
    Standard Keras classifier for unit testing

    The weights and biases are identical to the TensorFlow model in get_classifier_tf().

    :param loss_name: The name of the loss function.
    :type loss_name: `str`
    :param loss_type: The type of loss function definitions: label (loss function defined by string of its name),
                      function_losses (loss function imported from keras.losses), function_backend (loss function
                      imported from keras.backend)
    :type loss_type: `str`
    :param from_logits: Flag if model should predict logits (True) or probabilities (False).
    :type from_logits: `bool`
    :param load_init: Load the initial weights if True.
    :type load_init: `bool`
    :return: KerasClassifier, tf.Session()
    """
    import tensorflow as tf

    tf_version = [int(v) for v in tf.__version__.split(".")]
    if tf_version[0] == 2 and tf_version[1] >= 3:
        is_tf23_keras24 = True
        tf.compat.v1.disable_eager_execution()
        from tensorflow import keras
        from tensorflow.keras.layers import Conv2D, Dense, Flatten, MaxPooling2D
        from tensorflow.keras.models import Sequential
    else:
        is_tf23_keras24 = False
        import keras
        from keras.models import Sequential
        from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D

    from art.estimators.classification.keras import KerasClassifier

    # Create simple CNN
    model = Sequential()

    if load_init:
        if is_tf23_keras24:
            model.add(
                Conv2D(
                    1,
                    kernel_size=(7, 7),
                    activation="relu",
                    input_shape=(28, 28, 1),
                    kernel_initializer=_tf_weights_loader("MNIST", "W", "CONV2D", 2),
                    bias_initializer=_tf_weights_loader("MNIST", "B", "CONV2D", 2),
                )
            )
        else:
            model.add(
                Conv2D(
                    1,
                    kernel_size=(7, 7),
                    activation="relu",
                    input_shape=(28, 28, 1),
                    kernel_initializer=_kr_weights_loader("MNIST", "W", "CONV2D"),
                    bias_initializer=_kr_weights_loader("MNIST", "B", "CONV2D"),
                )
            )
    else:
        model.add(Conv2D(1, kernel_size=(7, 7), activation="relu", input_shape=(28, 28, 1)))

    model.add(MaxPooling2D(pool_size=(4, 4)))
    model.add(Flatten())

    if from_logits:
        if load_init:
            if is_tf23_keras24:
                model.add(
                    Dense(
                        10,
                        activation="linear",
                        kernel_initializer=_tf_weights_loader("MNIST", "W", "DENSE", 2),
                        bias_initializer=_tf_weights_loader("MNIST", "B", "DENSE", 2),
                    )
                )
            else:
                model.add(
                    Dense(
                        10,
                        activation="linear",
                        kernel_initializer=_kr_weights_loader("MNIST", "W", "DENSE"),
                        bias_initializer=_kr_weights_loader("MNIST", "B", "DENSE"),
                    )
                )
        else:
            model.add(Dense(10, activation="linear"))
    else:
        if load_init:
            if is_tf23_keras24:
                model.add(
                    Dense(
                        10,
                        activation="softmax",
                        kernel_initializer=_tf_weights_loader("MNIST", "W", "DENSE", 2),
                        bias_initializer=_tf_weights_loader("MNIST", "B", "DENSE", 2),
                    )
                )
            else:
                model.add(
                    Dense(
                        10,
                        activation="softmax",
                        kernel_initializer=_kr_weights_loader("MNIST", "W", "DENSE"),
                        bias_initializer=_kr_weights_loader("MNIST", "B", "DENSE"),
                    )
                )
        else:
            model.add(Dense(10, activation="softmax"))

    loss = None

    if loss_name == "categorical_hinge":
        if loss_type == "label":
            raise AttributeError("This combination of loss function options is not supported.")
        elif loss_type == "function_losses":
            loss = keras.losses.categorical_hinge
    elif loss_name == "categorical_crossentropy":
        if loss_type == "label":
            if from_logits:
                raise AttributeError("This combination of loss function options is not supported.")
            else:
                loss = loss_name
        elif loss_type == "function_losses":
            if from_logits:
                if is_tf23_keras24:

                    def categorical_crossentropy(y_true, y_pred):
                        return keras.losses.categorical_crossentropy(y_true, y_pred, from_logits=True)

                    loss = categorical_crossentropy
                else:
                    raise NotImplementedError("This combination of loss function options is not supported.")
            else:
                loss = keras.losses.categorical_crossentropy
        elif loss_type == "function_backend":
            if from_logits:

                def categorical_crossentropy(y_true, y_pred):
                    return keras.backend.categorical_crossentropy(y_true, y_pred, from_logits=True)

                loss = categorical_crossentropy
            else:
                loss = keras.backend.categorical_crossentropy
    elif loss_name == "sparse_categorical_crossentropy":
        if loss_type == "label":
            if from_logits:
                raise AttributeError("This combination of loss function options is not supported.")
            else:
                loss = loss_name
        elif loss_type == "function_losses":
            if from_logits:
                if int(keras.__version__.split(".")[0]) == 2 and int(keras.__version__.split(".")[1]) >= 3:

                    def sparse_categorical_crossentropy(y_true, y_pred):
                        return keras.losses.sparse_categorical_crossentropy(y_true, y_pred, from_logits=True)

                    loss = sparse_categorical_crossentropy
                else:
                    raise AttributeError("This combination of loss function options is not supported.")
            else:
                loss = keras.losses.sparse_categorical_crossentropy
        elif loss_type == "function_backend":
            if from_logits:

                def sparse_categorical_crossentropy(y_true, y_pred):
                    return keras.backend.sparse_categorical_crossentropy(y_true, y_pred, from_logits=True)

                loss = sparse_categorical_crossentropy
            else:
                loss = keras.backend.sparse_categorical_crossentropy
    elif loss_name == "kullback_leibler_divergence":
        if loss_type == "label":
            raise AttributeError("This combination of loss function options is not supported.")
        elif loss_type == "function_losses":
            loss = keras.losses.kullback_leibler_divergence
        elif loss_type == "function_backend":
            raise AttributeError("This combination of loss function options is not supported.")
    elif loss_name == "cosine_similarity":
        if loss_type == "label":
            loss = loss_name
        elif loss_type == "function_losses":
            loss = keras.losses.cosine_similarity
        elif loss_type == "function_backend":
            loss = keras.backend.cosine_similarity

    else:
        raise ValueError("Loss name not recognised.")

    model.compile(loss=loss, optimizer=keras.optimizers.legacy.Adam(lr=0.01), metrics=["accuracy"])

    # Get classifier
    krc = KerasClassifier(model, clip_values=(0, 1), use_logits=from_logits)

    return krc

    Standard Keras classifier for unit testing

    The weights and biases are identical to the TensorFlow model in get_classifier_tf().

    :param loss_name: The name of the loss function.
    :type loss_name: `str`
    :param loss_type: The type of loss function definitions: label (loss function defined by string of its name),
                      function_losses (loss function imported from keras.losses), function_backend (loss function
                      imported from keras.backend)
    :type loss_type: `str`
    :param from_logits: Flag if model should predict logits (True) or probabilities (False).
    :type from_logits: `bool`
    :param load_init: Load the initial weights if True.
    :type load_init: `bool`
    :return: KerasClassifier, tf.Session()
    
tests/utils.py