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!