On device machine learning in android

Hello Everyone, i am Ashok. i am student i am working on a digits mnist classification project in the part of my internship. i would like to create on device machine learning training in android app.

reference:

i trained the model and i am facing this warning:
WARNING:absl:Importing a function (__inference_internal_grad_fn_368181) with ops with unsaved custom gradients. Will likely fail if a gradient is requested.

later, i converted it into tensorflow lite model.

i got stuck while creating the application. the error i am facing is:

java.lang.IllegalArgumentException: Cannot copy to a TensorFlowLite tensor (train_y:0) with 40 bytes from a Java Buffer with 8 byte

please help me. i am new to python and machine learning. I truly appreciate your help. thank you.

Java code

public class MainActivity extends AppCompatActivity {

    private ImageView imageView;
    private TextView textView;
    private Button selectImageButton, ProcessImage;
    private Button trainModelButton, Updateweights;
    private Button predictButton;
    private Bitmap image;

    private static final int NUM_EPOCHS = 100;
    private static final int BATCH_SIZE = 10;
    private static final int IMG_HEIGHT = 28;
    private static final int IMG_WIDTH = 28;
    private static final int NUM_TRAININGS = 60000;
    private static final int NUM_BATCHES = NUM_TRAININGS / BATCH_SIZE;
    private static final int NUM_IMAGES = 1;
    private static final int REQUEST_CODE_GALLERY = 1;
    private List<Bitmap> selectedImages;
    private List<FloatBuffer> trainImageBatches;
    private List<FloatBuffer> trainLabelBatches;

    private Button SelectImagesBtn, TrainModelBtn;
//    ByteBuffer modelBuffer;
    Interpreter modelBuffer;
    Bitmap bitmap;


    private static final int IMAGE_PICK_REQUEST_CODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.selected_image_view);
        textView = findViewById(R.id.improved_learning_rate_text_view);
        selectImageButton = findViewById(R.id.select_image_button);
        trainModelButton = findViewById(R.id.train_model_button);
        predictButton = findViewById(R.id.predict_number_button);
        ProcessImage = findViewById(R.id.process_image_button);


        try {
            modelBuffer = new Interpreter(loadModelFile());
        } catch (Exception e) {
            Log.e("MainActivity", "Error loading TFLite model", e);
        }


        selectImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectImagesFromGallery();
            }
        });

        trainModelButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                trainModel();
                Toast.makeText(getApplicationContext()," Train button is clicked",Toast.LENGTH_SHORT).show();
            }
        });

        predictButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                LoadOndevicetrainedmodel();
//                predictNumber();
                Toast.makeText(getApplicationContext()," predict button is clicked",Toast.LENGTH_SHORT).show();
            }
        });

        ProcessImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                prepareTrainingBatches();
                Toast.makeText(getApplicationContext()," process button is clicked",Toast.LENGTH_SHORT).show();
            }
        });


    }





        // Method to select images from the gallery
    private void selectImagesFromGallery() {
        // Use an Intent to pick images from the gallery
        Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Images"), REQUEST_CODE_GALLERY);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_GALLERY && resultCode == RESULT_OK) {
            ClipData clipData = data.getClipData();
            if (clipData != null) {
                selectedImages = new ArrayList<>();
                int count = clipData.getItemCount();
                count = Math.min(count, NUM_IMAGES);
                for (int i = 0; i < count; i++) {
                    Uri imageUri = clipData.getItemAt(i).getUri();
                    try {
                         bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
//                        selectedImages.add(bitmap);
                        imageView.setImageBitmap(bitmap);
                        bitmap = resizeImage(bitmap);
                        Toast.makeText(getApplicationContext(),"image converted to bitmap",Toast.LENGTH_LONG).show();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }




        // Method to prepare training batches using the selected images
    private void prepareTrainingBatches() {
        try {
            trainImageBatches = new ArrayList<>(NUM_BATCHES);
            trainLabelBatches = new ArrayList<>(NUM_BATCHES);

            // Iterate over the selected images
            for (int i = 0; i < NUM_IMAGES; i++) {
                // Allocate a direct buffer to store the image data
//            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(IMG_HEIGHT * IMG_WIDTH * BATCH_SIZE).order(ByteOrder.nativeOrder());
                FloatBuffer trainImages = convertBitmapToFloatBuffer(bitmap);


                // Convert the resized image to grayscale
                Bitmap grayscaleImage = toGrayscale(bitmap);

                // Convert the grayscale image to a float buffer
                FloatBuffer floatBuffer = convertBitmapToFloatBuffer(grayscaleImage);

// Add the float buffer to trainImageBatches
                trainImageBatches.add(floatBuffer);




                // Allocate a direct buffer to store the label data
                ByteBuffer labelBuffer = ByteBuffer.allocateDirect(10 * BATCH_SIZE).order(ByteOrder.nativeOrder());
                FloatBuffer trainLabels = labelBuffer.asFloatBuffer();

                // Fill the image and label data for the current batch
//                trainImageBatches.add((FloatBuffer) trainImages.rewind());
                trainLabelBatches.add((FloatBuffer) trainLabels.rewind());

                Toast.makeText(getApplicationContext(), "prepareTrainingBatches is done", Toast.LENGTH_LONG).show();

            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "Error :"+ e, Toast.LENGTH_LONG).show();
        }
    }






        public void trainModel(){
        try  {

            // Run training for a few steps.
            float[] losses = new float[NUM_EPOCHS];
            for (int epoch = 0; epoch < NUM_EPOCHS; ++epoch) {
                for (int batchIdx = 0; batchIdx < NUM_BATCHES; ++batchIdx) {
                    Map<String, Object> inputs = new HashMap<>();
                    inputs.put("x", trainImageBatches.get(batchIdx));
                    inputs.put("y", trainLabelBatches.get(batchIdx));

                    Map<String, Object> outputs = new HashMap<>();

                    FloatBuffer loss = FloatBuffer.allocate(1);
                    outputs.put("loss", loss);

                    modelBuffer.runSignature(inputs, outputs, "train");

                    // Record the last loss.
                    if (batchIdx == NUM_BATCHES - 1) losses[epoch] = loss.get(0);
                }

                // Print the loss output for every 10 epochs.
                if ((epoch + 1) % 10 == 0) {
                    System.out.println(
                            "Finished " + (epoch + 1) + " epochs, current loss: " + losses[epoch]);
                    textView.setText("Finished " + (epoch + 1) + " epochs, current loss: " + losses[epoch]);
                }
            }

            // ...
            File outputFile = new File(getFilesDir(), "checkpoint.ckpt");
            Map<String, Object> inputs = new HashMap<>();
            inputs.put("checkpoint_path", outputFile.getAbsolutePath());
            Map<String, Object> outputs = new HashMap<>();
            modelBuffer.runSignature(inputs, outputs, "save");
        }
        catch (Exception e){
            e.printStackTrace();
            Log.d("TRAIN MODEL:", String.valueOf(e));
            Toast.makeText(getApplicationContext(),"Error:"+e,Toast.LENGTH_LONG).show();
        }

    }


        private MappedByteBuffer loadModelFile() throws IOException {
        // Load the TensorFlow Lite model from a file
        AssetFileDescriptor fileDescriptor = getAssets().openFd("model.tflite");
        FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
        FileChannel fileChannel = inputStream.getChannel();
        long startOffset = fileDescriptor.getStartOffset();
        long declaredLength = fileDescriptor.getDeclaredLength();
        return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
    }


    private Bitmap resizeImage(Bitmap originalImage){
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        int newWidth = 28;
        int newHeight = 28;

        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;

        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);

//        Bitmap resizedImage = Bitmap.createBitmap(originalImage, 0, 0, width, height, matrix, false);
       Bitmap resizedImage = Bitmap.createScaledBitmap(originalImage,newWidth,newHeight,true);
        return resizedImage;
    }















// The toGrayscale() and convertBitmapToFloatBuffer() methods are defined as follows:

    public static Bitmap toGrayscale(Bitmap bmpOriginal) {
        int width, height;
        height = bmpOriginal.getHeight();
        width = bmpOriginal.getWidth();

        Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmpGrayscale);
        Paint paint = new Paint();
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
        paint.setColorFilter(f);
        c.drawBitmap(bmpOriginal, 0, 0, paint);
        return bmpGrayscale;
    }

    public static FloatBuffer convertBitmapToFloatBuffer(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        float[] floatValues = new float[width * height];

        for (int i = 0; i < height; ++i) {
            for (int j = 0; j < width; ++j) {
                int pixelValue = bitmap.getPixel(j, i);
                floatValues[i * width + j] = (float)(pixelValue & 0xff) / 255.0f;
            }
        }

        FloatBuffer floatBuffer = FloatBuffer.wrap(floatValues);
        return floatBuffer;
    }


Hi @SouL_Gaming

The model is expecting 40 bytes and you are feeding it with 8. Check again the convertBitmapToFloatBuffer and/or toGrayScale functions.

Regards

Hello @George_Soloupis ,

Sorry for the late response,

i changed the code for the first error

 ByteBuffer labelBuffer = ByteBuffer.allocateDirect(1 * BATCH_SIZE * 4).order(ByteOrder.nativeOrder());
                FloatBuffer trainLabels = labelBuffer.asFloatBuffer();

i got new error now that is :

2023-02-14 23:02:36.287 4498-4498/com.application.finaltask W/System.err: java.lang.IllegalStateException: Internal error: Failed to run on the given Interpreter: Select TensorFlow op(s), included in the given model, is(are) not supported by this interpreter. Make sure you apply/link the Flex delegate before inference. For the Android, it can be resolved by adding "org.tensorflow:tensorflow-lite-select-tf-ops" dependency. See instructions: https://www.tensorflow.org/lite/guide/ops_select

after adding this dependency , i am getting new error.

org.tensorflow:tensorflow-lite-select-tf-ops

is there any on device training android application project , that would be helpful for me to take reference. i am searching whole internet for this solution(on-device training) but couldn’t find any.

from the tensorflow official page:

https://www.tensorflow.org/lite/examples/on_device_training/overview

they mentioned an demo app, but when i click on it, i am getting “Page not found”

please let me know if there is any source that would helpful for me. i am looking forward to hear from you. thank you.

So, what is the next error you are getting?

Check this android app examples/lite/examples/model_personalization/android at master · tensorflow/examples · GitHub

Hello @George_Soloupis ,

thank you for the android app ,Thank God finally i finded the Transfer_learning folder in the tensorflow github by by your help. I am specifically want to create transfer learning machine learning model for digits recognition with mnist data. can i know what changes i need to do in this code:

# Copyright 2021 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""CLI wrapper for tflite_transfer_converter.

Converts a TF model to a TFLite transfer learning model.
"""

import os

import numpy as np
import tensorflow as tf

IMG_SIZE = 224
NUM_FEATURES = 7 * 7 * 1280
NUM_CLASSES = 4


class TransferLearningModel(tf.Module):
  """TF Transfer Learning model class."""

  def __init__(self, learning_rate=0.001):
    """Initializes a transfer learning model instance.

    Args:
      learning_rate: A learning rate for the optimzer.
    """
    self.num_features = NUM_FEATURES
    self.num_classes = NUM_CLASSES

    # trainable weights and bias for softmax
    self.ws = tf.Variable(
        tf.zeros((self.num_features, self.num_classes)),
        name='ws',
        trainable=True)
    self.bs = tf.Variable(
        tf.zeros((1, self.num_classes)), name='bs', trainable=True)

    # base model
    self.base = tf.keras.applications.MobileNetV2(
        input_shape=(IMG_SIZE, IMG_SIZE, 3),
        alpha=1.0,
        include_top=False,
        weights='imagenet')
    # loss function and optimizer
    self.loss_fn = tf.keras.losses.CategoricalCrossentropy()
    self.optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)

  @tf.function(input_signature=[
      tf.TensorSpec([None, IMG_SIZE, IMG_SIZE, 3], tf.float32),
  ])
  def load(self, feature):
    """Generates and loads bottleneck features from the given image batch.

    Args:
      feature: A tensor of image feature batch to generate the bottleneck from.

    Returns:
      Map of the bottleneck.
    """
    x = tf.keras.applications.mobilenet_v2.preprocess_input(
        tf.multiply(feature, 255))
    bottleneck = tf.reshape(
        self.base(x, training=False), (-1, self.num_features))
    return {'bottleneck': bottleneck}

  @tf.function(input_signature=[
      tf.TensorSpec([None, NUM_FEATURES], tf.float32),
      tf.TensorSpec([None, NUM_CLASSES], tf.float32),
  ])
  def train(self, bottleneck, label):
    """Runs one training step with the given bottleneck features and labels.

    Args:
      bottleneck: A tensor of bottleneck features generated from the base model.
      label: A tensor of class labels for the given batch.

    Returns:
      Map of the training loss.
    """
    with tf.GradientTape() as tape:
      logits = tf.matmul(bottleneck, self.ws) + self.bs
      prediction = tf.nn.softmax(logits)
      loss = self.loss_fn(prediction, label)
    gradients = tape.gradient(loss, [self.ws, self.bs])
    self.optimizer.apply_gradients(zip(gradients, [self.ws, self.bs]))
    result = {'loss': loss}
    for grad in gradients:
      result[grad.name] = grad
    return result

  @tf.function(input_signature=[
      tf.TensorSpec([None, IMG_SIZE, IMG_SIZE, 3], tf.float32)
  ])
  def infer(self, feature):
    """Invokes an inference on the given feature.

    Args:
      feature: A tensor of image feature batch to invoke an inference on.

    Returns:
      Map of the softmax output.
    """
    x = tf.keras.applications.mobilenet_v2.preprocess_input(
        tf.multiply(feature, 255))
    bottleneck = tf.reshape(
        self.base(x, training=False), (-1, self.num_features))
    logits = tf.matmul(bottleneck, self.ws) + self.bs
    return {'output': tf.nn.softmax(logits)}

  @tf.function(input_signature=[tf.TensorSpec(shape=[], dtype=tf.string)])
  def save(self, checkpoint_path):
    """Saves the trainable weights to the given checkpoint file.

    Args:
      checkpoint_path: A file path to save the model.

    Returns:
      Map of the checkpoint file path.
    """
    tensor_names = [self.ws.name, self.bs.name]
    tensors_to_save = [self.ws.read_value(), self.bs.read_value()]
    tf.raw_ops.Save(
        filename=checkpoint_path,
        tensor_names=tensor_names,
        data=tensors_to_save,
        name='save')
    return {'checkpoint_path': checkpoint_path}

  @tf.function(input_signature=[tf.TensorSpec(shape=[], dtype=tf.string)])
  def restore(self, checkpoint_path):
    """Restores the serialized trainable weights from the given checkpoint file.

    Args:
      checkpoint_path: A path to a saved checkpoint file.

    Returns:
      Map of restored weight and bias.
    """
    restored_tensors = {}
    restored = tf.raw_ops.Restore(
        file_pattern=checkpoint_path,
        tensor_name=self.ws.name,
        dt=np.float32,
        name='restore')
    self.ws.assign(restored)
    restored_tensors['ws'] = restored
    restored = tf.raw_ops.Restore(
        file_pattern=checkpoint_path,
        tensor_name=self.bs.name,
        dt=np.float32,
        name='restore')
    self.bs.assign(restored)
    restored_tensors['bs'] = restored
    return restored_tensors

  @tf.function(input_signature=[])
  def initialize_weights(self):
    """Initializes the weights and bias of the head model.

    Returns:
      Map of initialized weight and bias.
    """
    self.ws.assign(tf.random.uniform((self.num_features, self.num_classes)))
    self.bs.assign(tf.random.uniform((1, self.num_classes)))
    return {'ws': self.ws, 'bs': self.bs}


def convert_and_save(saved_model_dir='saved_model'):
  """Converts and saves the TFLite Transfer Learning model.

  Args:
    saved_model_dir: A directory path to save a converted model.
  """
  model = TransferLearningModel()

  tf.saved_model.save(
      model,
      saved_model_dir,
      signatures={
          'load': model.load.get_concrete_function(),
          'train': model.train.get_concrete_function(),
          'infer': model.infer.get_concrete_function(),
          'save': model.save.get_concrete_function(),
          'restore': model.restore.get_concrete_function(),
          'initialize': model.initialize_weights.get_concrete_function(),
      })

  # Convert the model
  converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
  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()

  model_file_path = os.path.join('model.tflite')
  with open(model_file_path, 'wb') as model_file:
    model_file.write(tflite_model)


if __name__ == '__main__':
  convert_and_save()

This is the new error i am getting after adding the dependencies:

2023-02-15 19:56:32.294 21937-21937/com.application.finaltask E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.application.finaltask, PID: 21937
    java.lang.UnsatisfiedLinkError: dlopen failed: library "libtensorflowlite_flex_jni.so" not found
        at java.lang.Runtime.loadLibrary0(Runtime.java:1077)
        at java.lang.Runtime.loadLibrary0(Runtime.java:998)
        at java.lang.System.loadLibrary(System.java:1661)
        at org.tensorflow.lite.flex.FlexDelegate.<clinit>(FlexDelegate.java:61)
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:454)
        at java.lang.Class.forName(Class.java:379)
        at org.tensorflow.lite.NativeInterpreterWrapper.maybeCreateFlexDelegate(NativeInterpreterWrapper.java:544)
        at org.tensorflow.lite.NativeInterpreterWrapper.addDelegates(NativeInterpreterWrapper.java:484)
        at org.tensorflow.lite.NativeInterpreterWrapper.init(NativeInterpreterWrapper.java:96)
        at org.tensorflow.lite.NativeInterpreterWrapper.<init>(NativeInterpreterWrapper.java:73)
        at org.tensorflow.lite.NativeInterpreterWrapperExperimental.<init>(NativeInterpreterWrapperExperimental.java:36)
        at org.tensorflow.lite.Interpreter.<init>(Interpreter.java:227)
        at org.tensorflow.lite.Interpreter.<init>(Interpreter.java:211)
        at com.application.finaltask.MainActivity.onCreate(MainActivity.java:84)
        at android.app.Activity.performCreate(Activity.java:8163)
        at android.app.Activity.performCreate(Activity.java:8130)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3753)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3947)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:106)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2325)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:210)
        at android.os.Looper.loop(Looper.java:299)
        at android.app.ActivityThread.main(ActivityThread.java:8280)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1073)

Hello @George_Soloupis ,

I followed the android app, and added my tensorflow lite model into asset folder. but i am facing an error in the app and its crashing the app. how to resolve it ?

If the error s like the above with the ‘libtensorflowlite_flex_jni.so’ then it seems you have not added the
org.tensorflow:tensorflow-lite-select-tf-ops correctly?
Have you followed this

yes your right , i didnt added this dependency correctly. i added this dependency two times

    implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'

but after adding this dependency implementation 'org.tensorflow:tensorflow-lite-select-tf-ops:0.0.0-nightly-SNAPSHOT' i got this error :


02/15 22:18:59: Launching 'app' on Xiaomi M2004J19C.
Install successfully finished in 17 s 806 ms.
$ adb shell am start -n "com.application.finaltask/com.application.finaltask.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 19788 on device 'xiaomi-m2004j19c-adb-a07a68850409-roTNTo._adb-tls-connect._tcp'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
D/CompatibilityChangeReporter: Compat change id reported: 171979766; UID 10344; state: ENABLED
D/AppScoutStateMachine: 19788-ScoutStateMachinecreated
W/ziparchive: Unable to open '/data/app/~~QBNTdn3WsqmRIIcpwwuYUw==/com.application.finaltask-C4kMJ7ns3LcW4gdqCPaYnA==/base.dm': No such file or directory
W/ziparchive: Unable to open '/data/app/~~QBNTdn3WsqmRIIcpwwuYUw==/com.application.finaltask-C4kMJ7ns3LcW4gdqCPaYnA==/base.dm': No such file or directory
D/nativeloader: Configuring classloader-namespace for other apk /data/app/~~QBNTdn3WsqmRIIcpwwuYUw==/com.application.finaltask-C4kMJ7ns3LcW4gdqCPaYnA==/base.apk. target_sdk_version=33, uses_libraries=, library_path=/data/app/~~QBNTdn3WsqmRIIcpwwuYUw==/com.application.finaltask-C4kMJ7ns3LcW4gdqCPaYnA==/lib/arm64:/data/app/~~QBNTdn3WsqmRIIcpwwuYUw==/com.application.finaltask-C4kMJ7ns3LcW4gdqCPaYnA==/base.apk!/lib/arm64-v8a, permitted_path=/data:/mnt/expand:/data/user/0/com.application.finaltask
V/GraphicsEnvironment: ANGLE Developer option for 'com.application.finaltask' set to: 'default'
V/GraphicsEnvironment: Neither updatable production driver nor prerelease driver is supported.
I/ForceDarkHelperStubImpl: initialize for com.application.finaltask , ForceDarkOrigin
D/OpenGLRenderer: JNI_OnLoad success
I/MiuiForceDarkConfig: setConfig density:2.750000, mainRule:0, secondaryRule:0, tertiaryRule:0
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/libMEOW: meow new tls: 0xb40000747549c080
D/libMEOW: meow reload base cfg path: na
D/libMEOW: meow reload overlay cfg path: na
D/AppCompatDelegate: Checking for metadata for AppLocalesMetadataHolderService : Service not found
E/QT: [QT]file does not exist
D/libMEOW: applied 1 plugins for [com.application.finaltask]:
D/libMEOW:   plugin 1: [libMEOW_gift.so]:
D/libMEOW: meow delete tls: 0xb40000747549c080
D/ViewScrollStubImpl: the value of mScrollFrictionRes is: 0.015
D/MiuiMultiWindowUtils: freeform resolution args raw data:{  "zizhan":{    "freeform_args": {      "inner":{        "vertical_portrait":{"aspect_ratio":0.626, "original_ratio":0.5643,"original_scale":0.74,"top_margin":0.168,"left_margin":0.484},        "horizontal_portrait":{"aspect_ratio":0.626, "original_ratio":0.5643,"original_scale":0.74,"top_margin":0.1222,"left_margin":0.59745},        "vertical_landscape":{"aspect_ratio":1.6, "original_ratio":1,"original_scale":0.604,"top_margin":0.2596,"left_margin":0.2624},        "horizontal_landscape":{"aspect_ratio":1.6, "original_ratio":1,"original_scale":0.604,"top_margin":0.213,"left_margin":0.3758}      },      "outer":{        "vertical_portrait":{"aspect_ratio":0.626, "original_ratio":1,"original_scale":0.74,"top_margin":0.0753,"left_margin":-1},        "horizontal_portrait":{"aspect_ratio":0.626, "original_ratio":1,"original_scale":0.5756,"top_margin":-1,"left_margin":0.0753},        "vertical_landscape":{"aspect_ratio":1.6, "original_ratio":0.6847,"original_scale":0.587,"top_margin":0.0753,"left_margin":-1},        "horizontal_landscape":{"aspect_ratio":1.6, "original_ratio":0.6847,"original_scale":0.587,"top_margin":-1,"left_margin":0.0753}}    },    "mini_freeform_args":{      "inner":{        "vertical_portrait":{"aspect_ratio":0.626, "original_ratio":0.147},        "horizontal_portrait":{"aspect_ratio":0.626, "original_ratio":0.147},        "vertical_landscape":{"aspect_ratio":1.6, "original_ratio":0.165},        "horizontal_landscape":{"aspect_ratio":1.6, "original_ratio":0.165}      },      "outer":{        "vertical_portrait":{"aspect_ratio":0.626, "original_ratio":0.26},        "horizontal_portrait":{"aspect_ratio":0.626, "original_ratio":0.26},        "vertical_landscape":{"aspect_ratio":1.6, "original_ratio":0.293},        "horizontal_landscape":{"aspect_ratio":1.6, "original_ratio":0.293}}    }  },  "wide_default":{    "freeform_args": {        "vertical_portrait":{"aspect_ratio":0.625, "original_ratio":0.58,"original_scale":0.7574,"top_margin":0.125,"left_margin":-1},        "horizontal_portrait":{"aspect_ratio":0.625, "original_ratio":0.58,"original_scale":0.7574,"top_margin":-1,"left_margin":0.0714},        "vertical_landscape":{"aspect_ratio":1.6, "original_ratio":1,"original_scale":0.5153,"top_margin":0.125,"left_margin":-1},        "horizontal_landscape":{"aspect_ratio":1.6, "original_ratio":1,"original_scale":0.5153,"top_margin":-1,"left_margin":0.0714}    },    "mini_freeform_args":{        "vertical_portrait":{"aspect_ratio":0.5625, "original_ratio":0.144},        "horizontal_portrait":{"aspect_ratio":0.5625, "original_ratio":0.144},        "vertical_landscape":{"aspect_ratio":-1, "original_ratio":0.144},        "horizontal_landscape":{"aspect_ratio":-1, "original_ratio":0.144}    }  },  "narrow_default": {    "freeform_args": {        "vertical_portrait":{"aspect_ratio":0.5625, "original_ratio":1,"original_scale":0.7182,"top_margin":0.142,"left_margin":-1},        "horizontal_portrait":{"aspect_ratio":0.8, "original_ratio":1,"original_scale":0.7182,"top_margin":-1,"left_margin":0.05},        "vertical_landscape":{"aspect_ratio":1.6, "original_ratio":0.6545,"original_scale":0.4473,"top_margin":0.142,"left_margin":-1},        "horizontal_landscape":{"aspect_ratio":1.6, "original_ratio":0.6545,"original_scale":0.4473,"top_margin":-1,"left_margin":0.05}    },    "mini_freeform_args":{        "vertical_portrait":{"aspect_ratio":0.5625, "original_ratio":0.3},        "horizontal_portrait":{"aspect_ratio":0.5625, "original_ratio":0.3},        "vertical_landscape":{"aspect_ratio":1.7778, "original_ratio":0.3},        "horizontal_landscape":{"aspect_ratio":1.7778, "original_ratio":0.3}    }  },  "regular_default": {    "freeform_args": {      "vertical_portrait":{"aspect_ratio":0.625, "original_ratio":1,"original_scale":0.7,"top_margin":0.109,"left_margin":-1},      "horizontal_portrait":{"aspect_ratio":0.6667, "original_ratio":1,"original_scale":0.6102,"top_margin":-1,"left_margin":0.026},      "vertical_landscape":{"aspect_ratio
W/System.err: org.json.JSONException: No value for lancelot
W/System.err:     at org.json.JSONObject.get(JSONObject.java:398)
W/System.err:     at org.json.JSONObject.getJSONObject(JSONObject.java:618)
W/System.err:     at android.util.MiuiMultiWindowUtils.initFreeFormResolutionArgsOfDevice(MiuiMultiWindowUtils.java:1433)
W/System.err:     at android.util.MiuiMultiWindowUtils.initFreeFormResolutionArgs(MiuiMultiWindowUtils.java:1427)
W/System.err:     at android.util.MiuiMultiWindowUtils.<clinit>(MiuiMultiWindowUtils.java:209)
W/System.err:     at android.util.MiuiMultiWindowUtils.isSupportMultiSwitchFeature(MiuiMultiWindowUtils.java:3337)
W/System.err:     at com.android.internal.policy.DecorViewMultiWinStubImpl.<init>(DecorViewMultiWinStubImpl.java:19)
W/System.err:     at com.android.internal.policy.DecorViewMultiWinStubImpl$Provider.provideNewInstance(DecorViewMultiWinStubImpl$Provider.java:14)
W/System.err:     at com.android.internal.policy.DecorViewMultiWinStubImpl$Provider.provideNewInstance(DecorViewMultiWinStubImpl$Provider.java:8)
W/System.err:     at com.miui.base.MiuiStubRegistry.get(MiuiStubRegistry.java:129)
W/System.err:     at com.miui.base.MiuiStubUtil.newInstance(MiuiStubUtil.java:77)
W/System.err:     at com.android.internal.policy.DecorViewMultiWinStub.newInstance(DecorViewMultiWinStub.java:11)
W/System.err:     at com.android.internal.policy.DecorView.<init>(DecorView.java:335)
W/System.err:     at com.android.internal.policy.PhoneWindow.generateDecor(PhoneWindow.java:2380)
W/System.err:     at com.android.internal.policy.PhoneWindow.installDecor(PhoneWindow.java:2760)
W/System.err:     at com.android.internal.policy.PhoneWindow.getDecorView(PhoneWindow.java:2140)
W/System.err:     at androidx.appcompat.app.AppCompatActivity.initViewTreeOwners(AppCompatActivity.java:221)
W/System.err:     at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:196)
W/System.err:     at com.application.finaltask.MainActivity.onCreate(MainActivity.java:73)
W/System.err:     at android.app.Activity.performCreate(Activity.java:8163)
W/System.err:     at android.app.Activity.performCreate(Activity.java:8130)
W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3753)
W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3947)
W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:106)
W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2325)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
W/System.err:     at android.os.Looper.loopOnce(Looper.java:210)
W/System.err:     at android.os.Looper.loop(Looper.java:299)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:8280)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1073)
D/IS_CTS_MODE: false
D/MULTI_WINDOW_SWITCH_ENABLED: false
D/IS_CTS_MODE: false
D/MULTI_WINDOW_SWITCH_ENABLED: false
D/DecorView[]: getWindowModeFromSystem  windowmode is 1
W/ation.finaltas: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (unsupported, reflection, allowed)
W/ation.finaltas: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (unsupported, reflection, allowed)
I/InterpreterApi: Loaded native library: tensorflowlite_jni
I/InterpreterApi: Didn't load native library: tensorflowlite_jni_gms_client
I/tflite: Initialized TensorFlow Lite runtime.
I/tflite: Created TensorFlow Lite delegate for select TF ops.
    
    --------- beginning of crash
A/libc: Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x7475b71028 in tid 19788 (ation.finaltask), pid 19788 (ation.finaltask)
W/MIUIScout App: Enter APP_SCOUT_WARNING State
W/MIUIScout App:  (Current message: duration=2503ms seq=4 late=346ms h=android.app.ActivityThread$H w=159)
W/MIUIScout App: Event:APP_SCOUT_WARNING Thread:main backtrace:
        at org.tensorflow.lite.NativeInterpreterWrapper.createInterpreter(Native Method)
        at org.tensorflow.lite.NativeInterpreterWrapper.init(NativeInterpreterWrapper.java:106)
        at org.tensorflow.lite.NativeInterpreterWrapper.<init>(NativeInterpreterWrapper.java:73)
        at org.tensorflow.lite.NativeInterpreterWrapperExperimental.<init>(NativeInterpreterWrapperExperimental.java:36)
        at org.tensorflow.lite.Interpreter.<init>(Interpreter.java:227)
        at org.tensorflow.lite.Interpreter.<init>(Interpreter.java:211)
        at com.application.finaltask.MainActivity.onCreate(MainActivity.java:84)
        at android.app.Activity.performCreate(Activity.java:8163)
        at android.app.Activity.performCreate(Activity.java:8130)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3753)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3947)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:106)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2325)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:210)
        at android.os.Looper.loop(Looper.java:299)
        at android.app.ActivityThread.main(ActivityThread.java:8280)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1073)
I/ation.finaltas: Thread[6,tid=19825,WaitingInMainSignalCatcherLoop,Thread*=0xb400007474c39000,peer=0x13042c40,"Signal Catcher"]: reacting to signal 3
I/ation.finaltas: 

I think i didnt implemented correctly. I can’t figure out how to do this.

Probably, you can change the versions of
implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'
implementation 'org.tensorflow:tensorflow-lite-select-tf-ops:0.0.0-nightly'
with
implementation 'org.tensorflow:tensorflow-lite:2.11.0'
implementation 'org.tensorflow:tensorflow-lite-select-tf-ops:2.11.0'
clean, build project and check again. Try also with version 2.9.2.
Check the available versions here.

Hello @George_Soloupis ,

I am sorry to ask this but did you know or have any on-device training tensorflow application fully working. i would like to read the code to see how they implemented. By seeing a running application and its code. i think i can understand on-device training much better. So, that would help me to implement my on-device training digits recognition app too. I truly appreciate your help. thank you.

Hi

This is the only app that I am aware of right now

Hello @George_Soloupis ,

Thanks for your Help. The mistake is on my Side, instead of using the model Personalization from the demo branch I tried to use it from the master.

The on-device Training demo app working Fine. But I noticed it is not saving training and Predictions I have done before. When I again open the App its starts from the beginning.

How do I make that model save the previous training, predictions, and accuracy? and also it consisting of large codeset. i dont understand where i have to start changes. Can you explain me how the code is working.

Link: https://github.com/tensorflow/examples/tree/demo/lite/examples/model_personalization

And Also how would I apply on-device training for digit mnist recognition? I truly appreciate your help in this.

Thank you, Looking forward to your response.

Regards
Ashok

Is there a way to do On device MLOp in android?

I am also interested in on device model personalization and android library works with tensorflow lite api, which can help track a custom model performance and detect data drift at model inference for android ? Something like tfx for android on device.

I would like to do transfer learning retrain, performance measurement, model selection, drift detection with tensorflow lite in the close loop on android device, is this possible without making a library for it by myself?

hello @George_Soloupis i have a question about the TensorFlow Lite Example On-device Model Personalization. Is it possible to implement a project that extends the TensorFlow Lite Example On-device Model Personalization to include object detection capabilities, enabling the model to be trained directly on an Android device but not with a classifier but with an object detection model?

Start working on this and I can assist you as you are proceeding!

It seems like you’re encountering an issue with copying data to a TensorFlowLite tensor in your Android app. The error message suggests a mismatch in the size of the data you’re trying to copy to the tensor.

This could be due to several reasons:

  1. Data type mismatch: Make sure the data type of the Java buffer you’re trying to copy matches the expected data type of the TensorFlowLite tensor.
  2. Shape mismatch: Ensure that the shape of the tensor you’re trying to copy data into matches the shape of the input data.
  3. Size mismatch: Verify that the size of the data buffer matches the expected size of the TensorFlowLite tensor.

Without seeing your specific code, it’s a bit challenging to pinpoint the exact issue. However, here’s a general approach to copying data to a TensorFlowLite tensor in Java:

java

Copy code

// Assuming you have a ByteBuffer containing your input data
ByteBuffer buffer = ...; // Initialize your buffer with data

// Get the TensorFlowLite input tensor
Tensor inputTensor = tflite.getInputTensor(0); // Assuming 0 is the index of your input tensor

// Prepare the input data
Object input = ...; // Depending on the type of your input tensor, it could be an array, ByteBuffer, etc.
// Make sure the input data matches the expected shape and data type of the tensor

// Copy the input data to the TensorFlowLite tensor
inputTensor.copyFromBuffer(buffer);

// Perform inference with your TensorFlowLite model
tflite.run(input, output); // Assuming output is an array to store the model output

Make sure to replace the ellipses (…) with your actual data and variables. Also, ensure that the input data is prepared correctly according to the requirements of your TensorFlowLite model. Modified by moderator