tensorflow / tflite-support

TFLite Support is a toolkit that helps users to develop ML and deploy TFLite models onto mobile / ioT devices.
Apache License 2.0
373 stars 126 forks source link

TfLite Model is giving different output on Android app and in python for same inputs. Outputs using python are realistic but for java it remains same. Why the outputs are behaving this way in java file? #736

Closed ayush-raj8 closed 2 years ago

ayush-raj8 commented 2 years ago

So I'm building a very simple model using tensorflow that gives x+1 as output (prediction). I'll deploy this model on android application so I convert it to tflite format.

For building model :-

` import tensorflow as tf

x = [1,2,3,4,5,6,7,8,9,10] y = [2,3,4,5,6,7,8,9,10,11]

model = tf.keras.models.Sequential([tf.keras.layers.Dense(units=1, input_shape=[1])]) model.compile(optimizer='sgd', loss='mean_squared_error') model.fit(x, y, epochs=50)

path_file = 'saved_model/hello_world_tensorflow' tf.saved_model.save(model, path_file)

import pathlib

converter = tf.lite.TFLiteConverter.from_saved_model(path_file) tflite_model = converter.convert() tflite_model_file = pathlib.Path('model1.tflite') tflite_model_file.write_bytes(tflite_model)`

Using model in Python code for getting output

` import numpy as np import tensorflow as tf

interpreter = tf.lite.Interpreter(model_path="model1.tflite") interpreter.allocate_tensors()

input_details = interpreter.get_input_details() output_details = interpreter.get_output_details()

input_shape = input_details[0]['shape'] print(input_shape) input_data = np.array([[3]], dtype=np.float32) # 3 is the input here interpreter.set_tensor(input_details[0]['index'], input_data)

interpreter.invoke()

output_data = interpreter.get_tensor(output_details[0]['index']) print(output_data,input_data)`

Using model in Java Code (MainActivity.java File ) android

` package ar.labs.androidml;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast;

import org.tensorflow.lite.DataType; import org.tensorflow.lite.support.tensorbuffer.TensorBuffer;

import java.nio.ByteBuffer;

import ar.labs.androidml.ml.Model1;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btn= findViewById(R.id.button);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            try{
                EditText inputEditText;

                inputEditText = findViewById(R.id.editTextNumberDecimal);
                Float data= Float.valueOf(inputEditText.getText().toString());
                ByteBuffer byteBuffer= ByteBuffer.allocateDirect(1*4);
                byteBuffer.putFloat(data);

                Model1 model = Model1.newInstance(getApplicationContext());

                // Creates inputs for reference.
                TensorBuffer inputFeature0 = TensorBuffer.createFixedSize(new int[]{1, 1}, DataType.FLOAT32);
                inputFeature0.loadBuffer(byteBuffer);

                // Runs model inference and gets result.
                Model1.Outputs outputs = model.process(inputFeature0);
                TensorBuffer outputFeature0 = outputs.getOutputFeature0AsTensorBuffer();

                // Releases model resources if no longer used.
                TextView tv= findViewById(R.id.textView);
                float[] data1=outputFeature0.getFloatArray();

                tv.setText(outputFeature0.getDataType().toString());
                tv.setText(String.valueOf(data1[0]));

                model.close();

            }
            catch (Exception e)
            {
                Toast.makeText(getApplicationContext(),"Issue...",Toast.LENGTH_LONG).show();
            }
        }
    });
}

} `

The issue

Python code:

Java Code

Why are outputs from Python code and Java code are so different for same input? Why the outputs are behaving this way in java file like returning a constant value for most cases? Please help me fix.

ayush-raj8 commented 2 years ago

Solved ! Solved by myself! Add the new line so that the bytes are returned in LITTLE_ENDIAN. By default, the order of a ByteBuffer object is BIG_ENDIAN. Finally, the order method in is invoked to modify the byte order. The ByteOrder.nativeOrder() method returns the LITTLE_ENDIAN byte order. The order method creates a new buffer modifiedBuffer, and sets the byte order to LITTLE_ENDIAN.

ByteBuffer byteBuffer= ByteBuffer.allocateDirect(1*4);
byteBuffer.order(ByteOrder.nativeOrder()); // new line added
byteBuffer.putFloat(data);

Note : TfLite saved models only support Little Endian format by default.