<p>I'd recommend quantizing your model. This would reduce the file size by about 1/4. You can try just weight quantization, or full quantization.</p>

<p>Using the Python API, for only weight quantization:</p>

<pre><code>import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_quant_model = converter.convert()
</code></pre>

<p>For full quantization, I'd recommend using a representative dataset to reduce the accuracy loss associated with quantization.</p>

<pre><code>import tensorflow as tf

def representative_dataset_gen():
  for _ in range(num_calibration_steps):
  # Get sample input data as a numpy array in a method of your choosing.
  yield [input]

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset_gen
tflite_quant_model = converter.convert()
</code></pre>

<p>You can also try mobilenet architectures. Quantized versions of these can be anywhere from &lt;1MB to ~5MB. You can easily find some Tensorflow implentations of mobilefacenets with a quick google search, but here's a link to the paper that started it:
<a href="https://arxiv.org/abs/1804.07573" rel="nofollow noreferrer">https://arxiv.org/abs/1804.07573</a></p>
How to Reduce size of Tflite model or Download and set it programmatically?
<p>Okay so in my app i am trying to implement face recognition using face net model which is converted to tflite averaging at about 93 MB approximately,
however this model eventually increases size of my apk.
so i am trying to find alternate ways to deal with this</p>

<p>Firstly i can think of is to compress it in some way and then uncompress when app is installed</p>

<p>Another way is that i should upload that model to server and after being downloaded get it loaded in my application.
However i do not seem know how to implement this:</p>

<p>By default face net allows implementation from assets folder</p>

<pre><code> var facenet = FaceNet(getAssets());
</code></pre>

<p>But in case i'm downloading that model how can i get it loaded in my application?</p>

<p>Here is my face net intilization code:</p>

<pre><code>  public FaceNet(AssetManager assetManager) throws IOException {
        tfliteModel = loadModelFile(assetManager);
        tflite = new Interpreter(tfliteModel, tfliteOptions);
        imgData = ByteBuffer.allocateDirect(
                BATCH_SIZE
                        * IMAGE_HEIGHT
                        * IMAGE_WIDTH
                        * NUM_CHANNELS
                        * NUM_BYTES_PER_CHANNEL);
        imgData.order(ByteOrder.nativeOrder());
    }   


private MappedByteBuffer loadModelFile(AssetManager assetManager) throws IOException {
            AssetFileDescriptor fileDescriptor = assetManager.openFd(MODEL_PATH);
            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);
        }
</code></pre>

<p>My FaceNet Class:</p>

<pre><code>public class FaceNet {
    private static final String MODEL_PATH = "facenet.tflite";

    private static final float IMAGE_MEAN = 127.5f;
    private static final float IMAGE_STD = 127.5f;

    private static final int BATCH_SIZE = 1;
    private static final int IMAGE_HEIGHT = 160;
    private static final int IMAGE_WIDTH = 160;
    private static final int NUM_CHANNELS = 3;
    private static final int NUM_BYTES_PER_CHANNEL = 4;
    private static final int EMBEDDING_SIZE = 512;

    private final int[] intValues = new int[IMAGE_HEIGHT * IMAGE_WIDTH];
    private ByteBuffer imgData;

    private MappedByteBuffer tfliteModel;
    private Interpreter tflite;
    private final Interpreter.Options tfliteOptions = new Interpreter.Options();

    public FaceNet(AssetManager assetManager) throws IOException {
        tfliteModel = loadModelFile(assetManager);
        tflite = new Interpreter(tfliteModel, tfliteOptions);
        imgData = ByteBuffer.allocateDirect(
                BATCH_SIZE
                        * IMAGE_HEIGHT
                        * IMAGE_WIDTH
                        * NUM_CHANNELS
                        * NUM_BYTES_PER_CHANNEL);
        imgData.order(ByteOrder.nativeOrder());
    }

    private MappedByteBuffer loadModelFile(AssetManager assetManager) throws IOException {
        AssetFileDescriptor fileDescriptor = assetManager.openFd(MODEL_PATH);
        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 void convertBitmapToByteBuffer(Bitmap bitmap) {
        if (imgData == null) {
            return;
        }
        imgData.rewind();
        bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
        // Convert the image to floating point.
        int pixel = 0;
        for (int i = 0; i &lt; IMAGE_HEIGHT; ++i) {
            for (int j = 0; j &lt; IMAGE_WIDTH; ++j) {
                final int val = intValues[pixel++];
                addPixelValue(val);
            }
        }
    }

    private void addPixelValue(int pixelValue){
        //imgData.putFloat((((pixelValue &gt;&gt; 16) &amp; 0xFF) - IMAGE_MEAN) / IMAGE_STD);
        //imgData.putFloat((((pixelValue &gt;&gt; 8) &amp; 0xFF) - IMAGE_MEAN) / IMAGE_STD);
        //imgData.putFloat(((pixelValue &amp; 0xFF) - IMAGE_MEAN) / IMAGE_STD);
        imgData.putFloat(((pixelValue &gt;&gt; 16) &amp; 0xFF) / 255.0f);
        imgData.putFloat(((pixelValue &gt;&gt; 8) &amp; 0xFF) / 255.0f);
        imgData.putFloat((pixelValue &amp; 0xFF) / 255.0f);
    }

    public void inspectModel(){
        String tag = "Model Inspection";
        Log.i(tag, "Number of input tensors: " + String.valueOf(tflite.getInputTensorCount()));
        Log.i(tag, "Number of output tensors: " + String.valueOf(tflite.getOutputTensorCount()));

        Log.i(tag, tflite.getInputTensor(0).toString());
        Log.i(tag, "Input tensor data type: " + tflite.getInputTensor(0).dataType());
        Log.i(tag, "Input tensor shape: " + Arrays.toString(tflite.getInputTensor(0).shape()));
        Log.i(tag, "Output tensor 0 shape: " + Arrays.toString(tflite.getOutputTensor(0).shape()));
    }

    private Bitmap resizedBitmap(Bitmap bitmap, int height, int width){
        return Bitmap.createScaledBitmap(bitmap, width, height, true);
    }

    private Bitmap croppedBitmap(Bitmap bitmap, int upperCornerX, int upperCornerY, int height, int width){
        return Bitmap.createBitmap(bitmap, upperCornerX, upperCornerY, width, height);
    }

    private float[][] run(Bitmap bitmap){
        bitmap = resizedBitmap(bitmap, IMAGE_HEIGHT, IMAGE_WIDTH);
        convertBitmapToByteBuffer(bitmap);

        float[][] embeddings = new float[1][512];
        tflite.run(imgData, embeddings);

        return embeddings;
    }

    public double getSimilarityScore(Bitmap face1, Bitmap face2){
        float[][] face1_embedding = run(face1);
        float[][] face2_embedding = run(face2);

        double distance = 0.0;
        for (int i = 0; i &lt; EMBEDDING_SIZE; i++){
            distance += (face1_embedding[0][i] - face2_embedding[0][i]) * (face1_embedding[0][i] - face2_embedding[0][i]);
        }
        distance = Math.sqrt(distance);

        return distance;
    }

    public void close(){
        if (tflite != null) {
            tflite.close();
            tflite = null;
        }
        tfliteModel = null;
    }

}
</code></pre>