C.W.K.
Stream
Lesson 05 of 05 · published

Practical: Full TFLite Conversion Pipeline

~13 min · practical, mobilenet, deployment

Level 0Level 0
0 XP0/78 lessons0/17 achievements
0/100 XP to next level100 XP to go0% complete

The pipeline you'll actually ship

Here's a complete production-ready TFLite workflow — train a transfer-learning classifier, convert to multiple TFLite variants, verify accuracy on each.

The pattern: train at full float32 precision, save as SavedModel, then produce three TFLite variants (baseline / dynamic-range / int8). Pick the smallest variant that still meets your accuracy bar in the target deployment.

Why this matters for product: a quantized MobileNetV2 classifier goes from ~14MB (float32) to ~3.5MB (int8) while running 3× faster on CPU. For mobile apps, the smaller binary means faster download, less storage usage, and the difference between requiring WiFi or shipping over cellular. These aren't academic numbers — they're real business constraints.

Code

Full pipeline — train, convert, compare·python
import tensorflow as tf
import numpy as np

# 1. Build a transfer-learning classifier
IMG_SIZE = 224
base = tf.keras.applications.MobileNetV2(
    input_shape=(IMG_SIZE, IMG_SIZE, 3),
    include_top=False, weights='imagenet')
base.trainable = False

model = tf.keras.Sequential([
    base,
    tf.keras.layers.GlobalAveragePooling2D(),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(5, activation='softmax'),
])
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
# ... model.fit(train_ds, validation_data=val_ds, epochs=10)
model.save('flower_model/saved_model/')

# 2. Convert to three TFLite variants
def representative_dataset():
    for _ in range(200):
        yield [np.random.rand(1, 224, 224, 3).astype(np.float32)]

variants = {}

c = tf.lite.TFLiteConverter.from_saved_model('flower_model/saved_model/')
variants['baseline'] = c.convert()

c = tf.lite.TFLiteConverter.from_saved_model('flower_model/saved_model/')
c.optimizations = [tf.lite.Optimize.DEFAULT]
variants['dynamic'] = c.convert()

c = tf.lite.TFLiteConverter.from_saved_model('flower_model/saved_model/')
c.optimizations = [tf.lite.Optimize.DEFAULT]
c.representative_dataset = representative_dataset
variants['int8'] = c.convert()

# Compare sizes
for name, model_bytes in variants.items():
    print(f"{name:12s}: {len(model_bytes) / 1024:.1f} KB")
Verify accuracy on each variant·python
import tensorflow as tf
import numpy as np

def run_tflite(model_bytes, test_images):
    interpreter = tf.lite.Interpreter(model_content=model_bytes)
    interpreter.allocate_tensors()
    input_idx  = interpreter.get_input_details()[0]['index']
    output_idx = interpreter.get_output_details()[0]['index']

    results = []
    for img in test_images:
        interpreter.set_tensor(input_idx, img[None].astype(np.float32))
        interpreter.invoke()
        results.append(interpreter.get_tensor(output_idx)[0])
    return np.array(results)

# Compare baseline vs quantized — accuracy drop should be small
baseline_preds = run_tflite(variants['baseline'], test_images)
int8_preds     = run_tflite(variants['int8'],      test_images)
agreement = np.mean(np.argmax(baseline_preds, 1) == np.argmax(int8_preds, 1))
print(f"baseline vs int8 agreement: {agreement*100:.2f}%")

Exercise

Take any classification model you've trained and produce three TFLite variants (baseline, dynamic-range, full int8). Measure file sizes and report how much accuracy each tier sacrifices on your test set. The right tradeoff for your project is whichever tier first drops below your accuracy floor.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.