[TFLite C++] Signature calculating CategoricalCrossentropy loss produces wrong result
Hi @peratrepic,

Can you either provide your data + python training code to reproduce the tflite model file or just the tflite model itself. Also it is preferable if you do not redact your input data & labels for now, I can try to reproduce w/o it but it would be helpful to understand the full context.

Thanks! Hi @pkgoogle, sure!

Here is the python code I am using to create the model and convert it to tflite format:
<details><summary>Click to expand!</summary>

```
import numpy as np
import os
import tensorflow as tf

IMG_SIZE = 28

class Model(tf.Module):
    def __init__(self):
        self.model = tf.keras.Sequential([
            tf.keras.layers.Flatten(input_shape=(IMG_SIZE, IMG_SIZE), name='flatten'),
            tf.keras.layers.Dense(
                units=10,
                kernel_initializer=tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.05),
                bias_initializer=tf.keras.initializers.Ones(),
                name='dense'
            ),
        ])

        opt = tf.keras.optimizers.SGD(learning_rate=0.1)
        loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
        self.model.compile(optimizer=opt, loss=loss_fn, metrics=['accuracy'])

    # The `train` function takes a batch of input images and labels.
    @tf.function(input_signature=[
        tf.TensorSpec([32, IMG_SIZE, IMG_SIZE], tf.float32),
        tf.TensorSpec([32, 10], tf.float32),
    ])
    def train(self, x, y):
        with tf.GradientTape() as tape:
            prediction = self.model(x)
            loss = self.model.loss(y, prediction)
        gradients = tape.gradient(loss, self.model.trainable_variables)
        self.model.optimizer.apply_gradients(
            zip(gradients, self.model.trainable_variables))
        result = {"loss": loss}
        return result

    @tf.function(input_signature=[
        tf.TensorSpec([1, IMG_SIZE, IMG_SIZE], tf.float32),
    ])
    def infer(self, x):
        logits = self.model(x)
        probabilities = tf.nn.softmax(logits, axis=-1)
        return {
            "output": probabilities,
            "logits": logits
        }

m = Model()

def save_model():
    model_path = R"<insert your path>"

    tf.saved_model.save(
        m,
        model_path,
        signatures={
            'train':
                m.train.get_concrete_function(),
            'infer':
                m.infer.get_concrete_function(),
        })

    # Convert the model
    converter = tf.lite.TFLiteConverter.from_saved_model(model_path)
    converter.target_spec.supported_ops = [
        tf.lite.OpsSet.TFLITE_BUILTINS,  # enable TensorFlow Lite ops.
        tf.lite.OpsSet.SELECT_TF_OPS  # enable TensorFlow ops.
    ]
    converter.experimental_enable_resource_variables = True
    tflite_model = converter.convert()

    with open(os.path.join(model_path, "trained_model.tflite"), 'wb') as model_writer:
        model_writer.write(tflite_model)

save_model()
```

</details>

As you can see model is not being trained in python, I am just creating it and saving it to tflite format, with the goal to train it on another device using tflite C++ API. Here is the unredacted code for doing so:
<details><summary>Click to expand!</summary>

```
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/logger.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/signature_runner.h"

const int BATCH_SIZE = 32;
const int NUM_LABELS = 10;
const int IMG_SIZE = 28 * 28;

float run_test(tflite::Interpreter* interpreter)
{
    tflite::SignatureRunner* inference_runner = interpreter->GetSignatureRunner("infer");

    TfLiteTensor* input_tensor = inference_runner->input_tensor(inference_runner->input_names()[0]);
    float* input = input_tensor->data.f;

    int total = 0;
    int correct = 0;

    std::ifstream test_data("test_set.txt");
    std::string line;
    while (std::getline(test_data, line))
    {
        std::istringstream ss(line);
        int label;
        ss >> label;
        for (std::size_t i = 0; i < IMG_SIZE; ++i)
        {
            ss >> input[i];
        }

        if (inference_runner->Invoke() != kTfLiteOk)
        {
            std::cout << "Error invoking inference interpreter signature" << std::endl;
            return 0.f;
        }

        const TfLiteTensor* output_tensor = inference_runner->output_tensor(inference_runner->output_names()[0]);
        float* output = output_tensor->data.f;

        int predicted = 0;
        for (int i = 1; i < NUM_LABELS; ++i)
        {
            if (output[i] > output[predicted])
            {
                predicted = i;
            }
        }

        ++total;
        if (label == predicted)
        {
            ++correct;
        }
    }

    float accuracy = correct * 100.f / total;

    return accuracy;
}

void run_training(tflite::Interpreter* interpreter)
{
    std::cout << "Test acc before training: " << run_test(interpreter) << std::endl << std::endl;

    tflite::SignatureRunner* train_runner = interpreter->GetSignatureRunner("train");

    TfLiteTensor* input_data_tensor = train_runner->input_tensor(train_runner->input_names()[0]);
    float* input_data = input_data_tensor->data.f;
    TfLiteTensor* input_labels_tensor = train_runner->input_tensor(train_runner->input_names()[1]);
    float* input_labels = input_labels_tensor->data.f;

    int data_idx = 0;
    int num_batches = 0;
    std::vector<float> test_accs;

    std::ifstream train_data("train_set.txt");
    std::string line;
    while (std::getline(train_data, line))
    {
        std::istringstream ss(line);
        int label;
        ss >> label;
        for (int lbl_idx = 0; lbl_idx < NUM_LABELS; ++lbl_idx)
        {
            input_labels[data_idx * NUM_LABELS + lbl_idx] = (label == lbl_idx ? 1.f : 0.f);
        }
        for (int i = 0; i < IMG_SIZE; ++i)
        {
            ss >> input_data[data_idx * IMG_SIZE + i];
        }
        ++data_idx;

        if (data_idx == BATCH_SIZE)
        {
            data_idx = 0;

            if (train_runner->Invoke() != kTfLiteOk)
            {
                std::cout << "Error invoking train interpreter signature" << std::endl;
                return;
            }

            ++num_batches;
            const TfLiteTensor* output_tensor = train_runner->output_tensor(train_runner->output_names()[0]);
            float* output = output_tensor->data.f;
            std::cout << "Training of batch " << num_batches << " finished with loss: " << output[0] << std::endl;

            if (num_batches == 100)
            {
                break;
            }
        }
    }

    std::cout << std::endl << "Test acc after training: " << run_test(interpreter) << std::endl;
}

void train_model()
{
    tflite::LoggerOptions::SetMinimumLogSeverity(tflite::TFLITE_LOG_WARNING);

    std::unique_ptr<tflite::FlatBufferModel> model =
        tflite::FlatBufferModel::BuildFromFile("<insert your tflite model path>");
    if (model == nullptr)
    {
        std::cout << "Failed to load model" << std::endl;
        return;
    }

    tflite::ops::builtin::BuiltinOpResolver resolver;
    tflite::InterpreterBuilder builder(*model, resolver);
    std::unique_ptr<tflite::Interpreter> interpreter;
    builder(&interpreter);
    if (interpreter == nullptr)
    {
        std::cout << "Failed to create interpreter" << std::endl;
        return;
    }

    if (interpreter->AllocateTensors() != kTfLiteOk)
    {
        std::cout << "Failed to alocate interpreter tensors" << std::endl;
        return;
    }

    run_training(interpreter.get());
}

int main()
{
    train_model();

    return 0;
}
```

</details>

Model is being trained on MNIST dataset, I've just reformated it from binary files to txt files: one line per data sample, numbers separated by spaces, first number in line represents label and rest of the numbers represent features. I am attaching first 320 samples of train set in `train_set.txt`, and first 960 samples of test set in `test_set.txt`, since I can only upload limited file size here.
[test_set.txt](https://github.com/tensorflow/tensorflow/files/11630576/test_set.txt)
[train_set.txt](https://github.com/tensorflow/tensorflow/files/11630577/train_set.txt)
 Hi @peratrepic,

I tried running your code but I actually run into a seg fault:
```
~/60718_clean/build$ ./main
Test acc before training: 11.3542

Training of batch 1 finished with loss: 263.954
Segmentation fault
```

Here's my setup
[60718.tar.gz](https://github.com/tensorflow/tensorflow/files/11727464/60718.tar.gz)

unzip it to the same directory that has your tensorflow source then:
```
tar -xzf 60718.tar.gz
cd 60718_clean
python test.py
cd build
cmake ..
make
./main
```
Is your environment similar? or are you just linking a built .so file? Any additional information about your setup will be helpful. This issue is stale because it has been open for 7 days with no activity. It will be closed if no further activity occurs. Thank you. Hey @pkgoogle , sorry for delayed response I am on vacation atm. I cannot run your setup until I return, but from your results it seems that you are already getting abnormal loss after training of first batch (`Training of batch 1 finished with loss: 263.954`), even before you hit the segfault. Shouldn't that be enough for you to debug?

For the reference, training of first batch in Python (by calling the "train" signature) gives loss around ~2.5.

Regarding segfault, I was also getting segfault with tflite binaries built from branch r2.10 while accessing the input tensors, but didn't get them with binaries from later branches (r2.12 and r2.13). I think that is also something which should be investigated on your end, because my code is just using snippets of code taken from tflite examples and documentation, it isn't doing anything unusual.

And regarding my setup, I am building and running this on Windows. I am building TFLite from stable tf branches using bazel and linking the built lib/dll in the project which trains the model using tflite C++ API. Hi @peratrepic, Thanks for the information it definitely helps, Can you tell me your exact bazel commands and how you're linking the built lib/dll in the project? Are you using these steps? https://www.tensorflow.org/install/source_windows or something else. Are you utilizing WSL at all? Many people have different set ups so its hard to tell exactly what you are doing. In my view, that datapoint is not enough to debug at the moment, we are also dealing with many other issues so let's figure out how to reproduce this correctly first. This issue is stale because it has been open for 7 days with no activity. It will be closed if no further activity occurs. Thank you. Hi @pkgoogle, I've now setup a Linux VM (_Ubuntu 22.04.2 AMD64_) in order to confirm that the issue is not platform dependent. I've confirmed that the issue is still happening and I've also encountered the same segmentation fault as you.

The reason that segmentation fault is happening is the same as one I was having with TF 2.10 (but not with TF 2.12 and 2.13) on Windows: reference to the input tensor changes after signature is invoked. I am not sure if that is expected behaviour since it is happening only with certain versions of TF with certain platforms, but anyways, here is a working version of the code without segmentation faults:
<details><summary>Click to expand!</summary>

```cpp
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/logger.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/signature_runner.h"

const int BATCH_SIZE = 32;
const int NUM_LABELS = 10;
const int IMG_SIZE = 28 * 28;

float run_test(tflite::Interpreter* interpreter)
{
    tflite::SignatureRunner* inference_runner = interpreter->GetSignatureRunner("infer");

    TfLiteTensor* input_tensor = inference_runner->input_tensor(inference_runner->input_names()[0]);
    float* input = input_tensor->data.f;

    int total = 0;
    int correct = 0;

    std::ifstream test_data("test_set.txt");
    std::string line;
    while (std::getline(test_data, line))
    {
        std::istringstream ss(line);
        int label;
        ss >> label;
        for (std::size_t i = 0; i < IMG_SIZE; ++i)
        {
            ss >> input[i];
        }

        if (inference_runner->Invoke() != kTfLiteOk)
        {
            std::cout << "Error invoking inference interpreter signature" << std::endl;
            return 0.f;
        }

        const TfLiteTensor* output_tensor = inference_runner->output_tensor(inference_runner->output_names()[0]);
        float* output = output_tensor->data.f;

        int predicted = 0;
        for (int i = 1; i < NUM_LABELS; ++i)
        {
            if (output[i] > output[predicted])
            {
                predicted = i;
            }
        }

        ++total;
        if (label == predicted)
        {
            ++correct;
        }
    }

    float accuracy = correct * 100.f / total;

    return accuracy;
}

void run_training(tflite::Interpreter* interpreter)
{
    std::cout << "Test acc before training: " << run_test(interpreter) << std::endl << std::endl;

    tflite::SignatureRunner* train_runner = interpreter->GetSignatureRunner("train");

    TfLiteTensor* input_data_tensor = train_runner->input_tensor(train_runner->input_names()[0]);
    TfLiteTensor* input_labels_tensor = train_runner->input_tensor(train_runner->input_names()[1]);

    int data_idx = 0;
    int num_batches = 0;
    std::vector<float> test_accs;

    std::ifstream train_data("train_set.txt");
    std::string line;
    while (std::getline(train_data, line))
    {
        std::istringstream ss(line);
        int label;
        ss >> label;
        float* input_labels = input_labels_tensor->data.f;
        float* input_data = input_data_tensor->data.f;
        for (int lbl_idx = 0; lbl_idx < NUM_LABELS; ++lbl_idx)
        {
            input_labels[data_idx * NUM_LABELS + lbl_idx] = (label == lbl_idx ? 1.f : 0.f);
        }
        for (int i = 0; i < IMG_SIZE; ++i)
        {
            ss >> input_data[data_idx * IMG_SIZE + i];
        }
        ++data_idx;

        if (data_idx == BATCH_SIZE)
        {
            data_idx = 0;

            if (train_runner->Invoke() != kTfLiteOk)
            {
                std::cout << "Error invoking train interpreter signature" << std::endl;
                return;
            }

            ++num_batches;
            const TfLiteTensor* output_tensor = train_runner->output_tensor(train_runner->output_names()[0]);
            float* output = output_tensor->data.f;
            std::cout << "Training of batch " << num_batches << " finished with loss: " << output[0] << std::endl;

            if (num_batches == 10)
            {
                break;
            }
        }
    }

    std::cout << std::endl << "Test acc after training: " << run_test(interpreter) << std::endl;
}

void train_model()
{
    tflite::LoggerOptions::SetMinimumLogSeverity(tflite::TFLITE_LOG_WARNING);

    std::unique_ptr<tflite::FlatBufferModel> model =
        tflite::FlatBufferModel::BuildFromFile("<INSERT YOUR MODEL PATH HERE>");
    if (model == nullptr)
    {
        std::cout << "Failed to load model" << std::endl;
        return;
    }

    tflite::ops::builtin::BuiltinOpResolver resolver;
    tflite::InterpreterBuilder builder(*model, resolver);
    std::unique_ptr<tflite::Interpreter> interpreter;
    builder(&interpreter);
    if (interpreter == nullptr)
    {
        std::cout << "Failed to create interpreter" << std::endl;
        return;
    }

    if (interpreter->AllocateTensors() != kTfLiteOk)
    {
        std::cout << "Failed to alocate interpreter tensors" << std::endl;
        return;
    }

    run_training(interpreter.get());
}

int main()
{
    train_model();

    return 0;
}
```

</details>

Here are the results that I am getting:
```
Test acc before training: 13.4375

Training of batch 1 finished with loss: 125.153
Training of batch 2 finished with loss: 19491.5
Training of batch 3 finished with loss: 37853.6
Training of batch 4 finished with loss: 42998.3
Training of batch 5 finished with loss: 30509.9
Training of batch 6 finished with loss: 29040.6
Training of batch 7 finished with loss: 41205.7
Training of batch 8 finished with loss: 23286.3
Training of batch 9 finished with loss: 14237.5
Training of batch 10 finished with loss: 11451.6

Test acc after training: 55.625
```

Here is the model that I am using, so you don't have to create it again: [trained_model.tflite.zip](https://github.com/tensorflow/tensorflow/files/11901036/trained_model.tflite.zip)

As for the setup, I am building `libtensorflowlite.so` from TF [r2.13 branch](https://github.com/tensorflow/tensorflow/tree/r2.13) using this bazel command: `bazel build -c dbg //tensorflow/lite:libtensorflowlite.so`. Bazel configuration is configured for CPU (no CUDA). Then I am linking the built .so to the cpp project (one cpp file, code given above). Here is the CMakeLists.txt I am using:
<details><summary>Click to expand!</summary>

```cmake
cmake_minimum_required(VERSION 3.17)
project(TFLiteCpp)

set(CMAKE_CXX_STANDARD 14)

# include has 2 subdirectories: tensorflow and flatbuffers
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include/)

# lib has 1 file: libtensorflowlite.so
ADD_LIBRARY(tensorflowlite SHARED IMPORTED)
set_property(TARGET tensorflowlite PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libs/libtensorflowlite.so)

add_executable(TFLiteCpp main.cpp)
target_link_libraries(TFLiteCpp tensorflowlite)
```

</details> Hi @peratrepic, I was able to reproduce your results, so currently I do not view this as a "wrong" result, loss calculations are not necessarily monotonically decreasing with training if your dataset is variable enough. We also see that batch 7 through 10 we have decreasing loss. This makes sense to me as usually a NN needs some amount of warm-up and as the data changes the loss can increase as the training in the previous batches makes it better at predicting those data, not necessarily the next batch. Usually there is some pattern in the labels and feature set which makes it able to predict the next batch better but it's not guaranteed to be true. Though in the long run and with enough data that is the pattern you will see. The batch sizes here are also relatively small (32 images which are only 28 x 28 pixels large), so it'll take some time to learn. Let me know if you are satisfied with this answer, and if so please feel free to close the issue if you have no more open items. Hi @pkgoogle,

As I've stated before:
- When you run the **SAME** model, the **SAME** signature ("train"), on the **SAME** dataset, with python tf api, the loss starts from around 2.5, jumps up and down a little bit, and then goes steadily down. When you run the same with tflite c++ api, the loss explodes into thousands, which is insanely high for any ML model training. It is just a coincidence in the limited output from above that loss is decreasing in batches 8-10, I've run it for hundreds of batches and it goes erratically up and down by thousands. The numbers themselves are not even important here, the main point here is that the **results with c++ api differ from the results with python api under the same training conditions**.
- The test accuracy is rising batch after batch, up to 80%, which proves that model is being actually trained, it is **NOT** diverging, it is just the reported loss that is faulty. To me that indicates that you are writing some garbage value into the output tensor, otherwise if loss that you were using internally to calculate the gradients was wrong - the model wouldn't be training at all.

Could you please investigate? Hi @peratrepic, do you have the code that shows that 
>with python tf api, the loss starts from around 2.5, jumps up and down a little bit, and then goes steadily down

The above code only shows construction and conversion in python.

So the models are not necessarily exactly the same, conversion actually performs some optimizations and changes (such as op fuses). Additionally are you testing them side by side? (I'm guessing yes but I have to make sure) or are you testing/training the python model, converting, then testing/training the C++ model? It's hard to say w/o more context whether the ML model having a loss of thousands is necessarily incorrect. The type of model, the type of loss, the size of the data, the range of the data, number of classes (and probably more) all have an impact.

> I've run it for hundreds of batches and it goes erratically up and down by thousands.

This is probably better evidence as after hundreds of batches it should stabilize more... but with a batch size of 32 of 28x28 pixels it could potentially still be due to natural variability. If you can show me the data I can take a look.

```
Training of batch 1 finished with loss: 172.813
Training of batch 2 finished with loss: 30406.2
Training of batch 3 finished with loss: 35372.7
Training of batch 4 finished with loss: 30955.9
Training of batch 5 finished with loss: 30645.5
Training of batch 6 finished with loss: 39069.4
Training of batch 7 finished with loss: 25181.5
Training of batch 8 finished with loss: 28106.7
Training of batch 9 finished with loss: 12969.1
Training of batch 10 finished with loss: 3079.69
Training of batch 11 finished with loss: 3693.12
Training of batch 12 finished with loss: 3314.77
Training of batch 13 finished with loss: 4591.12
Training of batch 14 finished with loss: 5880.76
Training of batch 15 finished with loss: 5654.75
Training of batch 16 finished with loss: 10133.1
Training of batch 17 finished with loss: 9301.94
Training of batch 18 finished with loss: 11654.5
Training of batch 19 finished with loss: 11827.8
Training of batch 20 finished with loss: 22028.1
Training of batch 21 finished with loss: 8553.58
```

The natural trend here is still downwards... 21 batches (of size 32 28x28 pixels) is still fairly early so the amount of variability is somewhat expected. Because the accuracy IS increasing stably, tells me that the variability of the loss is still likely due to natural variability rather than a bug.

Lower loss is correlated with accuracy, but not deterministically as you generally do a softmax and pick the most probable class. Then compare the classes... this is not the same calculation as the log difference in predicted and actual probabilities. So that's why they can diverge a bit. Is the accuracy you are quoting overall accuracy or specific batch accuracy? If the loss is not going down long term especially if you increase the batch size (so that the natural variability evens out) then that might be an issue, but I need to see that data first. > It's hard to say w/o more context whether the ML model having a loss of thousands is necessarily incorrect

Do you even know how cross entropy loss is calculated, the math behind? Are you aware how big mistakes model should make to get a loss into thousands, how much the model should diverge instead of giving 87% accuracy on the whole test set? Have you seen a loss larger than two digits in successfull training of any ML model known to mankind?
![ce loss values](https://github.com/tensorflow/tensorflow/assets/134813523/81551d91-6caf-4271-839f-fdd7ca906106)

That aside, you don't find it suspicious that loss is so much smaller just in the first batch?

> The type of model, the type of loss, the size of the data, the range of the data, number of classes (and probably more) all have an impact.

Have you heard of MNIST dataset? Are you just ignoring the fact that this is classic MNIST dataset and not some random dataset, that the model is a simple one layer neural network used in all of tensorflow examples with pretty much known expected loss/accuracy results? I've purposely used the simplest model here for the ease of demonstration, but you constantly pretend like we are talking about training GPT... You say "It's hard to say w/o more context" when I've given you literally all the context possible, but you still talk in hypotheticals.

> Is the accuracy you are quoting overall accuracy or specific batch accuracy?

Accuracy on a whole separate dataset used for testing (MNIST test set). Can you explain how the model can achieve 87% accuracy on a test set but have four digits loss on a training set?

> Additionally are you testing them side by side? (I'm guessing yes but I have to make sure) or are you testing/training the python model, converting, then testing/training the C++ model?

I am creating empty model, converting it to tflite, and then I am training it separately side by side in both python and c++, on the same dataset, calling same signature functions. Of course, I am training python model with python and tflite model with c++ tflite api, because how would I otherwise do it - you can't train tflite model in python, and I know you will now say "got ya, those are different models!", but more on that below.

> So the models are not necessarily exactly the same, conversion actually performs some optimizations and changes (such as op fuses).

Yes I am aware of that, I've worked on a couple of ML tools implementations, and I know it should not give exactly the same results, but they should be close to same not differing 1000x times for Christ's sake. I still cannot believe what I am reading, how can someone so confidently ignore the obvious... You gotta be just waiting for me to give up so you can close this issue. The scale of difference in loss values between python and c++ tflite doesn't bother you at all? How do you even test the c++ tflite implementation, what are you comparing it with if not python tensorflow results? When I opened this issue I've hoped to get at least one of these things:
- Getting this bug in tflite c++ api fixed.
- Advice on how to better use tflite c++ api, or how to properly use it if I did something incorrectly, because the documentation on these things is almost nonexistent.
- Information about what features and ops are currently available in tflite for backward propagation, this is not documented anywhere.

Instead, I am getting dragged in circles and being given some trivial ML 101 statements which are not applicable at all in this case. I believe that I've spent more than enough time to convince you that you have a bug, I don't want to spend anymore after this message. At this point it would have been more efficient to me to debug tflite code and fix it myself. Now I think I should better explore some alternative sdks like PyTorch mobile if this is the absolute state of support from TF engineers. Hi @peratrepic, apologies for the frustration, we have to check the easy cases and usual failure modes first to make sure it's not a problem elsewhere, that's the reason for all the questions and making sure things are reproducible. We aren't trying to drag you in circles, just trying to get a better understanding of the issue.

While Categorical Cross entropy is technically unbounded, it is highly unlikely to be that high with just 10 output neurons, we'll look deeper into this issue.

Hi @JunyoungLim, can you please take a look? Thanks. @peratrepic  -         try this approach-  
 const TfLiteTensor* output = train_runner->output_tensor("loss");
 float* loss = output->data.f;
cout <<"Loss : "<<loss[0]<<endl;
 @peratrepic can you share code for inference using c++? and do you know any method to merge model.ckpt and model.tflite? 
<details><summary>Click to expand!</summary> 
 
 ### Issue Type

Bug

### Have you reproduced the bug with TF nightly?

Yes

### Source

source

### Tensorflow Version

2.13

### Custom Code

Yes

### OS Platform and Distribution

Windows 10

### Mobile device

_No response_

### Python version

_No response_

### Bazel version

5.3.0

### GCC/Compiler version

_No response_

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current Behaviour?

I've created a simple model in Python (TF version 2.10) and converted it for tflite. The model has two signatures, one for inference and other for training. When I run those signatures in Python, everything works correctly, I get good inference result and good training loss. When I load the converted tflite model with the C++ TFLite API (built from source, from branch r2.13) and run those signatures: inference works as intended, training works as intended (the accuracy on the test set is steadily rising), but the reported loss is totally random. At first I thought that loss might be accumulated since it is rising to five digits, but that is not the case since it rises and falls in a random fashion. It seems like there is some bug in the ops used for CategoricalCrossentropy C++ TFLite implementation.

I've tried building tensorflow from r2.12 and r2.13 and I get the same behavior. I've tried r2.10 also but then I couldn't even run the signatures with C++ TFLite API, I was getting bunch of segmentation faults. I couldn't find anywhere the documentation on what ops for backward prop are available in C++ TFLite API, maybe some of those which are used in CategoricalCrossentropy loss calculation are not yet available, or there is a bug in their implementation.

### Standalone code to reproduce the issue

Here is a Python code I am using to create model with signatures:
```
IMG_SIZE = 28

class Model(tf.Module):
    def __init__(self):
        self.model = tf.keras.Sequential([
            tf.keras.layers.Flatten(input_shape=(IMG_SIZE, IMG_SIZE), name='flatten'),
            tf.keras.layers.Dense(
                units=10,
                kernel_initializer=tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.05),
                bias_initializer=tf.keras.initializers.Ones(),
                name='dense'
            ),
        ])

        opt = tf.keras.optimizers.SGD(learning_rate=0.1)
        loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
        self.model.compile(optimizer=opt, loss=loss_fn, metrics=['accuracy'])

    # The `train` function takes a batch of input images and labels.
    @tf.function(input_signature=[
        tf.TensorSpec([32, IMG_SIZE, IMG_SIZE], tf.float32),
        tf.TensorSpec([32, 10], tf.float32),
    ])
    def train(self, x, y):
        with tf.GradientTape() as tape:
            prediction = self.model(x)
            loss = self.model.loss(y, prediction)
        gradients = tape.gradient(loss, self.model.trainable_variables)
        self.model.optimizer.apply_gradients(
            zip(gradients, self.model.trainable_variables))
        result = {"loss": loss}
        return result

    @tf.function(input_signature=[
        tf.TensorSpec([1, IMG_SIZE, IMG_SIZE], tf.float32),
    ])
    def infer(self, x):
        logits = self.model(x)
        probabilities = tf.nn.softmax(logits, axis=-1)
        return {
            "output": probabilities,
            "logits": logits
        }
```

And here is the C++ code I am using to run the tflite model:
```
std::unique_ptr<tflite::FlatBufferModel> model =
    tflite::FlatBufferModel::BuildFromFile(tflite_model_path);
if (model == nullptr)
{
    std::cout << "Failed to load model" << std::endl;
    return;
}

tflite::ops::builtin::BuiltinOpResolver resolver;
tflite::InterpreterBuilder builder(*model, resolver);
std::unique_ptr<tflite::Interpreter> interpreter;
builder(&interpreter);
if (interpreter == nullptr)
{
    std::cout << "Failed to create interpreter" << std::endl;
    return;
}

if (interpreter->AllocateTensors() != kTfLiteOk)
{
    std::cout << "Failed to alocate interpreter tensors" << std::endl;
    return;
}

tflite::SignatureRunner* train_runner = interpreter->GetSignatureRunner("train");

TfLiteTensor* input_data_tensor = train_runner->input_tensor(train_runner->input_names()[0]);
float* input_data = input_data_tensor->data.f;
TfLiteTensor* input_labels_tensor = train_runner->input_tensor(train_runner->input_names()[1]);
float* input_labels = input_labels_tensor->data.f;

// Here I fill in the input data and labels, code redacted for brevity.

if (train_runner->Invoke() != kTfLiteOk)
{
    std::cout << "Error invoking train interpreter signature" << std::endl;
    return;
}

const TfLiteTensor* output_tensor = train_runner->output_tensor(train_runner->output_names()[0]);
float* output = output_tensor->data.f;
std::cout << "Training finished with loss: " << output[0] << std::endl;
```

Please let me know if you need more details, or full source code.


### Relevant log output

Here are the losses from batch to batch, as you can see they are too high and pretty much random. I repeat: the model is training correctly which I can see because the accuracy on the test set is steadily rising, so these loss values do not make sense.
```
Training of batch 1 finished with loss: 172.813
Training of batch 2 finished with loss: 30406.2
Training of batch 3 finished with loss: 35372.7
Training of batch 4 finished with loss: 30955.9
Training of batch 5 finished with loss: 30645.5
Training of batch 6 finished with loss: 39069.4
Training of batch 7 finished with loss: 25181.5
Training of batch 8 finished with loss: 28106.7
Training of batch 9 finished with loss: 12969.1
Training of batch 10 finished with loss: 3079.69
Training of batch 11 finished with loss: 3693.12
Training of batch 12 finished with loss: 3314.77
Training of batch 13 finished with loss: 4591.12
Training of batch 14 finished with loss: 5880.76
Training of batch 15 finished with loss: 5654.75
Training of batch 16 finished with loss: 10133.1
Training of batch 17 finished with loss: 9301.94
Training of batch 18 finished with loss: 11654.5
Training of batch 19 finished with loss: 11827.8
Training of batch 20 finished with loss: 22028.1
Training of batch 21 finished with loss: 8553.58
```

</details>