TensorFlow MobileNet in Practice
MobileNetV2 is the most practical pre-trained model for real-world projects. It is small enough to run on a smartphone, fast enough for real-time video, accurate enough for production use, and available with ImageNet weights in TensorFlow in one line. This topic builds a complete, production-quality image classifier using MobileNetV2 — from raw images to a deployed, prediction-ready model.
Why MobileNetV2
MobileNetV2 design principles: 1. Inverted residuals: expand channels, depthwise conv, compress back 2. Linear bottlenecks: no activation at bottleneck to preserve information 3. Depthwise separable convolutions: 8–9× fewer params than standard Conv Result: Parameters: 3.4 million (VGG16 has 138M — 40× more) Size on disk: 14 MB (VGG16 is 528 MB) Inference: 25ms on CPU (VGG16 takes ~150ms) Accuracy: 71.8% on ImageNet (VGG16: 71.3%) MobileNetV2 is as accurate as VGG16 at 1/40th the size.
Complete Project: Plant Disease Classifier
You will classify plant leaf images into three categories: healthy, bacterial infection, and fungal infection. This type of classifier has real agricultural value — farmers can photograph leaves and get instant disease diagnosis.
Step 1 — Set Up the Data Pipeline
import tensorflow as tf
IMG_SIZE = (224, 224)
BATCH_SIZE = 32
AUTOTUNE = tf.data.AUTOTUNE
CLASS_NAMES = ['bacterial', 'fungal', 'healthy']
def build_dataset(directory, training=True):
ds = tf.keras.utils.image_dataset_from_directory(
directory,
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
shuffle=training,
seed=42
)
if training:
ds = ds.map(augment, num_parallel_calls=AUTOTUNE)
return ds.prefetch(AUTOTUNE)
def augment(image, label):
image = tf.image.random_flip_left_right(image)
image = tf.image.random_brightness(image, max_delta=0.2)
image = tf.image.random_contrast(image, lower=0.8, upper=1.2)
return image, label
train_ds = build_dataset('data/train/', training=True)
val_ds = build_dataset('data/val/', training=False)
Step 2 — Build MobileNetV2 Transfer Learning Model
import tensorflow as tf
def build_model(num_classes=3):
# Load base model
base = tf.keras.applications.MobileNetV2(
input_shape=(224, 224, 3),
include_top=False,
weights='imagenet'
)
base.trainable = False
# Build full model
inputs = tf.keras.Input(shape=(224, 224, 3))
# MobileNetV2-specific preprocessing: scales to [-1, 1]
x = tf.keras.applications.mobilenet_v2.preprocess_input(inputs)
x = base(x, training=False)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dense(128, activation='relu')(x)
x = tf.keras.layers.Dropout(0.3)(x)
outputs = tf.keras.layers.Dense(num_classes, activation='softmax')(x)
model = tf.keras.Model(inputs, outputs)
return model, base
model, base = build_model(num_classes=3)
model.summary()
Step 3 — Phase 1 Training
model.compile(
optimizer=tf.keras.optimizers.Adam(0.001),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history_phase1 = model.fit(
train_ds,
epochs=15,
validation_data=val_ds,
callbacks=[
tf.keras.callbacks.ModelCheckpoint(
'best_phase1.keras',
monitor='val_accuracy',
save_best_only=True
)
]
)
print(f"Phase 1 best val_accuracy: {max(history_phase1.history['val_accuracy']):.2%}")
Step 4 — Phase 2 Fine-Tuning
# Unfreeze last 30 layers of MobileNetV2
base.trainable = True
for layer in base.layers[:-30]:
layer.trainable = False
# Recompile with lower learning rate
model.compile(
optimizer=tf.keras.optimizers.Adam(1e-5),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history_phase2 = model.fit(
train_ds,
epochs=10,
validation_data=val_ds,
callbacks=[
tf.keras.callbacks.EarlyStopping(
monitor='val_accuracy', patience=4,
restore_best_weights=True
),
tf.keras.callbacks.ModelCheckpoint(
'best_final.keras',
monitor='val_accuracy',
save_best_only=True
)
]
)
print(f"Phase 2 best val_accuracy: {max(history_phase2.history['val_accuracy']):.2%}")
Step 5 — Evaluate and Predict
# Load best model
best_model = tf.keras.models.load_model('best_final.keras')
# Evaluate
loss, acc = best_model.evaluate(val_ds)
print(f"Final accuracy: {acc:.2%}")
# Predict a single leaf image
def classify_leaf(model, image_path):
img = tf.keras.utils.load_img(image_path, target_size=(224, 224))
img_array = tf.keras.utils.img_to_array(img)
img_array = tf.expand_dims(img_array, 0)
predictions = model.predict(img_array, verbose=0)
predicted_class = CLASS_NAMES[tf.argmax(predictions[0]).numpy()]
confidence = tf.reduce_max(predictions[0]).numpy()
print(f"Diagnosis: {predicted_class} ({confidence:.1%} confidence)")
for name, prob in zip(CLASS_NAMES, predictions[0]):
bar = '█' * int(prob * 20)
print(f" {name:12s}: {prob:.1%} {bar}")
classify_leaf(best_model, 'test_leaf.jpg')
Step 6 — Export for Mobile Deployment
# Convert to TFLite for mobile deployment
converter = tf.lite.TFLiteConverter.from_keras_model(best_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT] # Apply quantization
tflite_model = converter.convert()
with open('plant_classifier.tflite', 'wb') as f:
f.write(tflite_model)
print(f"TFLite model size: {len(tflite_model) / 1024:.0f} KB")
# Typically ~4–6 MB after quantization (down from 14 MB)
MobileNetV2 Architecture Highlights
Input: (224, 224, 3)
│
▼ First Conv (32 filters, stride 2) → (112, 112, 32)
▼ Bottleneck blocks (×17, expansion 6) → various sizes
▼ Last Conv (1280 filters, 1×1) → (7, 7, 1280)
▼ GlobalAveragePooling → (1280,)
▼ [include_top=True] Dense(1000) → (1000,) ImageNet classes
[include_top=False] output here → (7, 7, 1280) for transfer learning
Performance Targets for Production
Use case Target latency Model variant ────────────────────────────────────────────────────────── Server API (batch) <100ms/image MobileNetV2 or EfficientNetB0 Mobile app (real-time) <50ms/frame MobileNetV2 TFLite quantized Edge camera <30ms/frame MobileNetV3Small TFLite Browser (TF.js) <200ms/image MobileNetV2 JS converted ──────────────────────────────────────────────────────────
MobileNetV2 with transfer learning and fine-tuning is one of the most powerful and practical tools in the TensorFlow ecosystem. It achieves production-level accuracy with minimal data, trains in minutes rather than days, and deploys to any platform. The skills you practiced here — two-phase training, quantized export, single-image prediction — apply to every future computer vision project you build. The advanced section now covers training techniques that push model quality and efficiency even further.
