Instructions to use shirish9354/Criminal_Activity_Detector_UCFCrimeDataset with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use shirish9354/Criminal_Activity_Detector_UCFCrimeDataset with Keras:
# !pip install -U keras tensorflow huggingface_hub # Keras needs TensorFlow installed to read "hf://" paths, so the tensorflow backend is selected here; # "jax" and "torch" also work for computation once TensorFlow is installed. import os os.environ["KERAS_BACKEND"] = "tensorflow" import keras model = keras.saving.load_model("hf://shirish9354/Criminal_Activity_Detector_UCFCrimeDataset") - Notebooks
- Google Colab
- Kaggle
Overview
A video-based binary classifier that labels any clip as Normal or Suspicious. Trained end-to-end on the UCF-Crime dataset β 1,950 annotated surveillance videos across 13 crime categories (Abuse, Arrest, Arson, Assault, Burglary, Explosion, Fighting, Road Accidents, Robbery, Shooting, Shoplifting, Stealing, Vandalism) plus matched normal footage.
Model Usage Code on Google Colab can be found here.
Model Creation Code on Kaggle can be found here.
Architecture
Raw video
β
ResNet50 (frozen, ImageNet) β feature extractor, 25M params
β 16 frames Γ 2048-dim vectors
LayerNorm + Dense(256) + Dropout(0.4)
β
Bidirectional GRU (64 units) β temporal modelling
β
Temporal Attention β learned frame weighting
β
Dense(64) + Dropout(0.6)
β
Sigmoid β P(suspicious)
Head parameters: 660,738 (2.52 MB) Backbone: Frozen ResNet50 β features extracted once and cached, not retrained
Code Snippet 1
import requests
url = "https://shirish9354-ucf-crime.hf.space/predict"
with open(r"FILE_PATH", "rb") as f: res = requests.post(url, files={"file": f})
print(res.json())
Code Snippet 2
!pip install suspectiq
from suspectiq import SuspectIQ
detector = SuspectIQ()
result = detector.predict(r"FILE_PATH")
print(result)
Training Details
| Setting | Value |
|---|---|
| Framework | TensorFlow 2.19.0 / Keras 3 |
| GPU | 2Γ Tesla T4 (Kaggle) |
| Loss | Focal Loss (Ξ±=0.60, Ξ³=2.0) |
| Optimiser | Adam + gradient clipping (clipnorm=1.0) |
| LR schedule | ReduceLROnPlateau on val_AUC, min 1e-5 |
| Early stopping | Patience 6 on val_AUC, restore best weights |
| Epochs run | 19 (best at epoch 13) |
| Batch size | 32 |
| Sequence length | 16 frames per 2-second clip |
| Threshold | 0.325 (macro-F1 tuned on validation set) |
Dataset Splits
| Split | Clips | Normal | Suspicious |
|---|---|---|---|
| Train | 1,328 | 680 (51.2%) | 648 (48.8%) |
| Val | 332 | 170 (51.2%) | 162 (48.8%) |
| Test | 290 | 150 (51.7%) | 140 (48.3%) |
Splits are at video level β no frame-level leakage between train and val. Val is a stratified 20% carve-out of the training pool.
Results
| Metric | Value |
|---|---|
| Test accuracy | 90.3% |
| Test AUC-ROC | 0.930 |
| Macro F1 | 0.903 |
| Normal precision / recall | 89.6% / 92.0% |
| Suspicious precision / recall | 91.2% / 88.6% |
| False alarms (FP) | 12 / 150 normal clips |
| Misses (FN) | 16 / 140 suspicious clips |
Inference
Supports both recorded video and live streams (webcam, RTSP, RTMP) via a sliding window with configurable overlap:
model = tf.keras.models.load_model('best_model.keras')
# No custom_objects needed β @register_keras_serializable handles it
Latency: ~135 ms per 2-second window on T4 GPU (after tf.function warm-up) Overlap: 50% default β events spanning clip boundaries are always fully captured
Fixes Applied Across Versions
| Issue | Fix |
|---|---|
| Class weight collapse (v1) | Focal Loss Ξ±=0.60 |
| Backbone overfitting | ResNet50 frozen throughout |
| Slow extraction | Batched GPU extraction (~8Γ faster) |
| Threshold bias | Macro-F1 tuning instead of suspicious-only F1 |
| Custom class serialisation | @register_keras_serializable |
| Training resume after crash | Epoch history + weight checkpoint |
| Feature extraction resume | Incremental partial .npz checkpoint every 200 clips |
| Dataset path resolution | BFS auto-discovery + 5-layout fallback |
| Leakage | Video-level splits confirmed |
- Downloads last month
- 4