Desant Phishing Detector β MobileNetV2 INT8 for Google Coral Edge TPU
A fully quantized (INT8) MobileNetV2 model for real-time phishing screenshot detection on Google Coral Edge TPU devices.
Distilled from the Desant CLIP-based phishing classifier by Desant.ai for ultra-low-latency edge deployment.
Feed any web page screenshot and the model classifies it as SAFE (class 0) or MALICIOUS / Phishing (class 1) β entirely on-device, with no cloud round-trip.
Model Details
| Property | Value |
|---|---|
| Architecture | MobileNetV2 (ImageNet backbone) + custom dense classifier head |
| Base model | MobileNetV2 1.0 224 via tf.keras.applications |
| Teacher model | Desant CLIP ViT-B/32 Phishing Classifier |
| Task | Binary image classification (safe vs. phishing) |
| Input | Web page screenshot β [1, 224, 224, 3] uint8 |
| Output | [1, 2] uint8 softmax probabilities [safe, malicious] |
| Quantization | Full INT8 post-training quantization (300 representative samples) |
| Edge TPU ops mapped | 100% (68/68 operators) β fully compiled for Coral |
| Edge TPU Compiler | v16.0.384591198 |
| Model size | 2.93 MB (Edge TPU) Β· 2.75 MB (CPU int8 fallback) |
| Framework | TensorFlow / TFLite |
| Target hardware | Google Coral USB Accelerator Β· Coral Dev Board Β· Raspberry Pi + Coral |
| License | CC-BY-4.0 |
Architecture
Input Image (web page screenshot)
β
βΌ Aspect-ratio-preserving resize + CLIP-mean padding β 224Γ224
ββββββββββββββββββββββββββββββββ
β MobileNetV2 1.0 β β ImageNet-pretrained, fine-tuned
β Depthwise Separable Convs β
β Input: 224Γ224Γ3 (uint8) β
β Inverted Residual Blocks β
ββββββββββββ¬ββββββββββββββββββββ
β 1280-dim feature map
βΌ
ββββββββββββββββββββββββββββββββ
β GlobalAveragePooling2D β
β Dropout(0.3) β
β Dense(128, ReLU) β
β Dropout(0.2) β
β Dense(2, Softmax) β β [safe, malicious] probabilities
ββββββββββββ¬ββββββββββββββββββββ
β
βΌ
uint8 output β dequantize β prediction
Edge TPU Operator Mapping (100% on-chip)
All operators execute on the Edge TPU β zero fallback to CPU:
| Operator | Count |
|---|---|
| CONV_2D | 35 |
| DEPTHWISE_CONV_2D | 17 |
| ADD | 10 |
| FULLY_CONNECTED | 2 |
| QUANTIZE | 2 |
| MEAN | 1 |
| SOFTMAX | 1 |
| Total | 68 |
Quantization Details
| Property | Input Tensor | Output Tensor |
|---|---|---|
| Name | serving_default_image:0 |
StatefulPartitionedCall_1:0 |
| Shape | [1, 224, 224, 3] |
[1, 2] |
| Dtype | uint8 | uint8 |
| Scale | 0.00784314 | 0.00390625 |
| Zero point | 127 | 0 |
Performance
Evaluated on a held-out stratified validation set (20% of dataset, 570 images):
| Metric | Score |
|---|---|
| Validation Accuracy | 88.95% |
| Validation Loss | 0.287 |
Note: This is a distilled edge model optimized for speed and size. For maximum accuracy, use the CLIP-based teacher model (92β96% accuracy, ~335 MB).
Training
Knowledge Distillation Pipeline
This model was trained as a student in a knowledge distillation pipeline:
- Teacher: CLIP ViT-B/32 fine-tuned phishing classifier (~335 MB, 92β96% accuracy)
- Student: MobileNetV2 trained on the same labeled dataset with class-weighted loss
- Export: Full INT8 post-training quantization with representative calibration dataset
- Compile: Edge TPU compiler maps all operations to the Coral accelerator
Data
| Property | Value |
|---|---|
| Total images | 2,846 |
| Train set | 2,276 (1,138 safe + 1,138 malicious) |
| Validation set | 570 (285 safe + 285 malicious) |
| Class balance | Perfectly balanced (50/50) |
- Malicious class (1): Real phishing login page screenshots from PhishTank, OpenPhish, URLhaus, AlienVault OTX
- Safe class (0): Legitimate web pages β real login pages (Google, Microsoft, banks), search engines, normal web pages
Training Configuration
| Parameter | Phase 1 (Frozen Backbone) | Phase 2 (Fine-tuning) |
|---|---|---|
| Optimizer | Adam (lr=1e-3) | Adam (lr=1e-5) |
| Epochs | Up to 20 | Up to 5 |
| Backbone | Frozen | Last 30 layers unfrozen |
| Loss | SparseCategoricalCrossentropy | SparseCategoricalCrossentropy |
| Class balancing | Inverse-frequency class weights | Inverse-frequency class weights |
| Scheduler | ReduceLROnPlateau (patience=2, factor=0.5) | ReduceLROnPlateau |
| Early stopping | patience=6 on val_loss | patience=6 on val_loss |
| Batch size | 32 | 32 |
Preprocessing Pipeline
# 1. Load screenshot (any resolution)
# 2. Aspect-ratio-preserving resize to 224Γ224
# 3. Pad with CLIP-mean color: (123, 117, 104)
# 4. MobileNetV2 normalization: [0, 255] β [-1.0, 1.0]
# 5. INT8 quantization: scale=0.00784314, zero_point=127
Augmentation (training only)
- Random horizontal flip (50%)
- Brightness jitter Γ0.85β1.15 (80%)
- Contrast jitter Γ0.85β1.15 (80%)
- Color/saturation jitter Γ0.85β1.15 (50%)
Usage
Files in this Repository
| File | Description |
|---|---|
student_best_int8_edgetpu_edgetpu.tflite |
Edge TPU compiled model (use with Coral devices) |
student_best_int8_edgetpu.tflite |
CPU-compatible INT8 TFLite (fallback, no Coral needed) |
labels.txt |
Class labels (SAFE, MALICIOUS) |
metadata.json |
Training metadata and hyperparameters |
training_history.csv |
Epoch-by-epoch training curves |
Quick Start β Edge TPU Inference (Python)
import numpy as np
from PIL import Image
from pycoral.adapters import classify, common
from pycoral.utils.edgetpu import make_interpreter
CLIP_MEAN_PAD = (123, 117, 104)
def preprocess(image_path, size=224):
"""Aspect-ratio-preserving resize with CLIP-mean padding."""
img = Image.open(image_path).convert("RGB")
w, h = img.size
scale = min(size / w, size / h)
new_w, new_h = int(w * scale), int(h * scale)
img = img.resize((new_w, new_h), Image.LANCZOS)
canvas = Image.new("RGB", (size, size), CLIP_MEAN_PAD)
canvas.paste(img, ((size - new_w) // 2, (size - new_h) // 2))
return np.array(canvas, dtype=np.uint8)
# Load Edge TPU model
interpreter = make_interpreter("student_best_int8_edgetpu_edgetpu.tflite")
interpreter.allocate_tensors()
# Preprocess and run inference
image = preprocess("screenshot.png")
common.set_input(interpreter, image)
interpreter.invoke()
# Get results
output = common.output_tensor(interpreter, 0)
safe_score = output[0]
malicious_score = output[1]
label = "MALICIOUS" if malicious_score > safe_score else "SAFE"
print(f"{label} β safe: {safe_score}, malicious: {malicious_score}")
CPU-only Inference (no Coral hardware)
import numpy as np
from PIL import Image
import tflite_runtime.interpreter as tflite
CLIP_MEAN_PAD = (123, 117, 104)
def preprocess(image_path, size=224):
img = Image.open(image_path).convert("RGB")
w, h = img.size
scale = min(size / w, size / h)
new_w, new_h = int(w * scale), int(h * scale)
img = img.resize((new_w, new_h), Image.LANCZOS)
canvas = Image.new("RGB", (size, size), CLIP_MEAN_PAD)
canvas.paste(img, ((size - new_w) // 2, (size - new_h) // 2))
return np.expand_dims(np.array(canvas, dtype=np.uint8), axis=0)
interpreter = tflite.Interpreter(model_path="student_best_int8_edgetpu.tflite")
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
image = preprocess("screenshot.png")
interpreter.set_tensor(input_details[0]["index"], image)
interpreter.invoke()
output = interpreter.get_tensor(output_details[0]["index"])[0]
scale = output_details[0]["quantization_parameters"]["scales"][0]
zero_point = output_details[0]["quantization_parameters"]["zero_points"][0]
probs = (output.astype(np.float32) - zero_point) * scale
label = "MALICIOUS" if probs[1] > probs[0] else "SAFE"
print(f"{label} β safe: {probs[0]:.4f}, malicious: {probs[1]:.4f}")
Raspberry Pi 5 + Coral USB Setup
# Install Coral runtime
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" \
| sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt update && sudo apt install libedgetpu1-std python3-pycoral
# Run inference
python3 inference.py --model student_best_int8_edgetpu_edgetpu.tflite --image screenshot.png
Model Family
| Model | Size | Accuracy | Hardware | Use Case |
|---|---|---|---|---|
| desant-phishing-inference | ~335 MB | 92β96% | GPU / CPU | Cloud inference, maximum accuracy |
| desant-phishing-detector-google-coral-int8 (this) | 2.93 MB | 88.95% | Edge TPU / CPU | On-device, real-time edge deployment |
Intended Use
- Primary use: Real-time on-device phishing detection on edge hardware (Coral USB, Raspberry Pi)
- Input: Screenshots of web pages, especially login pages
- Users: IoT security appliances, edge gateways, browser-integrated hardware, SOC edge nodes, security researchers
Limitations
- Trained primarily on English-language phishing pages; reduced accuracy on non-Latin scripts
- Optimized for login form detection β non-login phishing (e.g. fake download pages) may have lower recall
- Accuracy is lower than the CLIP teacher model due to the distillation/quantization tradeoff (~89% vs ~95%)
- Very low-resolution or heavily compressed screenshots may reduce accuracy
- Detects visual similarity to known phishing patterns; novel zero-day designs may evade detection
Ethical Considerations
This model is designed for defensive cybersecurity β protecting users from phishing attacks. It should not be used to:
- Create or improve phishing pages
- Bypass security systems
- Conduct adversarial attacks against phishing detection
Citation
@misc{desant2026phishing_edgetpu,
title={Desant Phishing Detector: MobileNetV2 INT8 for Google Coral Edge TPU},
author={Desant.ai},
year={2026},
url={https://huggingface.co/desant-ai/desant-phishing-detector-google-coral-int8}
}
Contact
- Company: Desant.ai
- Teacher model: desant-phishing-inference
- Demo: Hugging Face Space
- Downloads last month
- 1
Model tree for desant-ai/desant-phishing-detector-google-coral-int8
Base model
google/mobilenet_v2_1.0_224Evaluation results
- Validation Accuracyself-reported0.889