This project investigates whether a compact neural network can learn an entire video as a fully autonomous nonlinear dynamical system that unrolls temporally in a low-dimensional latent space from a single initial condition.
The benchmark video is the complete Bad Apple!! PV: 6,573 frames at 384×512 resolution (30 FPS, ~3m 39s).
This experiment was inspired by the work on memorizing Bad Apple into a 3MB SIREN MLP (GitHub: SlothScript/BadAppleOnANeuralNetwork), which mapped coordinate queries
Instead of querying a spatial-temporal coordinate function with an explicit time index
Can a tiny recurrent transition network learn the continuous temporal flow of the video, such that evaluating
autonomously generates all 6,573 frames without ever supplying the time index at inference time?
At Inference (Zero Timestamp Input):
┌──────────────┐ (h_t, c_t) ┌──────────────────────┐ (h_{t+1}, c_{t+1})
│ Initial State│───────────────>│ Recurrent Transition │──────────────────────> ...
│ (h0, c0) │ │ Function (CTF) │
└──────────────┘ └──────────────────────┘
│
h_t
▼
┌──────────────────────┐
│ Frame Decoder │───> Frame_t (384×512)
└──────────────────────┘
During inference, the learned table embeddings and optimizer states are completely discarded. The standalone inference package consists strictly of:
-
Initial Latent Vectors:
( floats). -
Custom Transition Function (
ctf): 4-gate LSTM-style recurrence (parameters). -
Frame Decoder (
fd): 4-stage bilinear upsampling with depthwise-separable convolutions (parameters).
| Component | Layer Description | Parameters | Memory (FP32) |
|---|---|---|---|
Transition Function (ctf) |
Recurrent gates ( |
16,640 | 65.00 KB |
Frame Decoder (fd) |
Latent projection ( |
399,360 | 1,560.00 KB |
| Conv Block 1 ( |
232 | 0.91 KB | |
| Conv Block 2 ( |
448 | 1.75 KB | |
| Conv Block 3 ( |
312 | 1.22 KB | |
| Output Conv ( |
9 | 0.04 KB | |
| Initial Latents ( |
64-dim initial hidden and cell vectors | 128 | 0.50 KB |
| Total Inference Model | 417,129 | 1.60 MB |
- Model Weights in VRAM: 1.60 MB
- Peak Active VRAM (per frame decode): 17.22 MB
- Inference Throughput: >200 FPS (on RTX 4080)
- Standalone Package File:
exports/models/bad_apple_inference_only.pt(1.60 MB)
(Note: The source MP4 is ~19.5 MB. This project is an investigation into neural memorization and nonlinear dynamical systems rather than a replacement for standardized entropy-coded video compression algorithms like H.264/AV1).
Training Setup:
┌────────────────────────────────────────────────────────┐
│ TrainingTableEmbeddings (Learned Anchor Scaffolding)│
│ h_table: [6573, 64] c_table: [6573, 64] │
└────────────────────────────────────────────────────────┘
│ ▲
t_start │ │ Supervision:
▼ │ L_dyn_h, L_dyn_c, L_smooth
(h_t, c_t) + Noise │
│ │
▼ │
┌───────────────────────────┐ │
│CustomTransitionFunction │─┘
│(Orthogonal Init + Gating) │
└───────────────────────────┘
│
│ h_t, h_{t+1}, ..., h_{t+K}
▼
┌───────────────────────────┐
│FrameDecoder (Chunked = 32)│───> L_recon vs Ground Truth Frames
└───────────────────────────┘
-
Two-State Recurrence (
): The decoder only receives . The second state serves as an internal memory manifold, allowing the system to disambiguate identical video frames that occur at different timestamps. -
Learned Temporal Scaffolding (
TrainingTableEmbeddings): Backpropagating end-to-end through 6,573 steps from epoch 1 is computationally intractable and suffers from severe gradient vanishing/exploding. Learned latent tables provide local initializationsat arbitrary timestamps, allowing parallel randomized segment training. -
Hybrid Optimization (AdamW + Muon):
-
AdamW (
) optimizes the frame decoder and embedding tables. -
Muon (
) optimizes the recurrent gate matrices using matrix orthogonalization.
-
AdamW (
The primary obstacle in autonomous rollout is compounding error: microscopic transition errors at step
Curriculum Horizon (K=2 → 512)
├── Optimizer Momentum Attenuation (×0.2 every 10 epochs)
├── State Perturbation Injection (σ = 0.005)
├── Second-Difference Temporal Smoothness (Acceleration Regularization)
└── Chunked Decoding (Chunk Size = 32)
Training begins with short local steps (
Every curriculum transition introduces a predictable jump in loss as the recurrent model is forced to maintain stability over larger unrolls before adapting.
To prevent the model from learning a brittle 1D trajectory that fails when slightly perturbed, Gaussian noise (
The loss is computed between clean predicted states and ground-truth table states. This trains the transition function
Directly penalizing velocity (
This enforces a smooth trajectory across latent space without constraining speed.
When the curriculum doubles the rollout horizon
-
Training Loss vs. Autonomous Rollout:
Selecting checkpoints based solely on the lowest training loss is misleading because training loss is measured with teacher-table anchors over finite horizons
. Model checkpoints were selected by evaluating full unrolls from . -
Checkpoint Optimizer-State Handling:
In early runs prior to epoch ~300, optimizer states were not retained across manual pauses. This caused accidental optimizer resets during some stage transitions. Once identified, intentional soft momentum attenuation (
) was implemented cleanly.
(Additional analytics dashboards—including stage-by-stage convergence grids, cosine self-similarity recurrence matrices, step velocities, and a standalone interactive Three.js 3D point cloud visualizer—are available in exports/plots/ and exports/interactive/).
├── exports/
│ ├── export_pipeline.py # Generates packaged models, CSV/JSON tables, and plots
│ ├── load_and_rollout.py # Self-contained video synthesis and evaluation engine
│ ├── models/
│ │ ├── bad_apple_inference_only.pt # Standalone 1.60 MB inference package
│ │ └── bad_apple_complete_training.pt # Complete checkpoint with optimizer states
│ ├── plots/ # High-resolution analytics dashboards
│ ├── tables/ # CSV/JSON training metrics and parameter statistics
│ └── interactive/ # Standalone WebGL 3D latent point cloud visualizer
├── extract_frames.py # FFmpeg frame extraction utility
├── visualize_tables.py # Latent manifold, PCA, recurrence, and gating visualizers
├── logs.txt # Full 650-epoch training log
└── README.md
git clone https://github.com/SEBADA321/BadAppleRNN.git
cd BadAppleRNN
python -m venv .venv
source .venv/bin/activate
pip install torch torchvision numpy opencv-python matplotlibGenerate a side-by-side video comparing ground truth against autonomous unroll with real-time MSE and timestamp overlays:
python exports/load_and_rollout.py(Outputs exports/rollout_side_by_side.mp4)
# Tri-Panel: Ground Truth | Table Reconstruction | Autonomous Rollout
python exports/load_and_rollout.py --mode tri-panel
# Clean Single-Stream Autonomous Video (512x384)
python exports/load_and_rollout.py --mode single
# Direct Table Reconstruction Comparison
python exports/load_and_rollout.py --mode tableTo package checkpoints, parse logs, generate tables, and re-create publication dashboards:
python exports/export_pipeline.py- Bad Apple on a Neural Network (SIREN INR by SlothScript)
- Sitzmann et al., "Implicit Neural Representations with Periodic Activation Functions", NeurIPS 2020.
- Jordan et al., "Muon: An optimizer for hidden layers in neural networks", 2024.