π΅ Music LSTM β Symbolic Piano Generation
A Stacked LSTM + Attention model for symbolic piano music generation, trained on 46 million musical events from ~12,000 MIDI files.
Built from scratch as part of the CodeAlpha AI Internship (Task 3) β no pre-trained model, no external API, just raw deep learning on MIDI data.
Model Description
The model treats music generation as a next-token prediction problem β the same principle behind language models like GPT, applied to piano music.
Each musical event is encoded as a single token representing three attributes simultaneously:
- Pitch β MIDI note value (0β127)
- Duration β discretized into 10 musical buckets (thirty-second β whole note)
- Velocity β discretized into 8 classical nuance buckets (ppp β fff)
The model learns to predict the next token given a sequence of 64 past tokens, then generates music autoregressively.
Architecture
Token sequence (64 tokens)
β
βΌ
Embedding (vocab_size=6543, dim=256)
β
βΌ
LSTM Layer 1 (hidden=1024) β local patterns: intervals, rhythm
β
βΌ
LSTM Layer 2 (hidden=1024) β higher-level patterns: phrases, motifs
β
βΌ
Attention (additive, Bahdanau-style)
β
βΌ
Linear β Softmax (6543 classes)
β
βΌ
Next token prediction
| Parameter | Value |
|---|---|
| Total parameters | 22,030,480 |
| Vocabulary size | 6,543 tokens |
| Sequence length | 64 tokens |
| Hidden size | 1,024 |
| LSTM layers | 2 |
| Embedding dim | 256 |
| Dropout | 0.3 |
Training Data
| Dataset | Files | Events |
|---|---|---|
| Maestro v3.0.0 | 1,276 | ~6M |
| GiantMIDI-Piano v1.21 | 10,841 | ~41M |
| Total | 12,109 | ~46M |
Both datasets consist of professional and semi-professional solo piano recordings in classical style, ensuring a consistent musical domain.
Preprocessing used symusic (C++ MIDI parser) for fast extraction of pitch, duration, and velocity attributes from raw MIDI files.
Training
Trained on Kaggle 2ΓT4 GPUs (30GB VRAM total) using torch.nn.DataParallel.
| Hyperparameter | Value |
|---|---|
| Optimizer | Adam (lr=0.001) |
| Scheduler | ReduceLROnPlateau (factor=0.5, patience=2) |
| Batch size | 256 |
| Gradient clipping | 5.0 |
| Early stopping patience | 5 |
Results
| Epoch | Train Loss | Val Loss |
|---|---|---|
| 1 | 6.834 | 6.407 |
| 4 | 5.906 | 5.900 |
| 8 | 5.505 | 5.806 β best |
| 13 | 5.041 | 5.857 β early stop |
Best checkpoint: epoch 8, val_loss = 5.805
Random baseline: ln(6543) β 8.78 β the model significantly outperforms random prediction.
Usage
Quick start
git clone https://github.com/Tahsine/CodeAlpha_Music_Generation
cd CodeAlpha_Music_Generation
pip install -r requirements.txt
The model weights are downloaded automatically from this repo on first run:
# Generate MIDI (256 notes, temperature=0.9)
python generate.py
# Full options
python generate.py \
--n_tokens 512 \
--temperature 0.9 \
--bpm 120 \
--output artifacts/my_music.mid \
--device cpu
Generate MIDI + WAV
# Install FluidSynth
sudo apt-get install fluidsynth # Linux
brew install fluidsynth # macOS
# Generate audio β soundfont (~30MB) downloads automatically
python generate.py --n_tokens 512 --temperature 0.9 --audio
Temperature guide
| Temperature | Effect |
|---|---|
0.7 |
Conservative β coherent but repetitive |
0.9 |
Balanced β musical and varied (recommended) |
1.1 |
Creative β surprising but less coherent |
Load model directly in Python
import torch
from huggingface_hub import hf_hub_download
# Download weights
model_path = hf_hub_download(
repo_id="KalineZephyr/music-lstm-midi-codealpha",
filename="best_model.pt",
)
# Load checkpoint
ckpt = torch.load(model_path, map_location="cpu")
print(f"Best epoch : {ckpt['epoch']}")
print(f"Val loss : {ckpt['val_loss']:.4f}")
print(f"Config : {ckpt['config']}")
Limitations
- Short-range coherence only β LSTM memory is limited to ~50β100 tokens. The model generates locally coherent phrases but lacks long-range structure (no recurring themes, no global form).
- Piano only β trained exclusively on solo piano data. Other instruments will produce poor results.
- Classical/romantic style β dataset bias toward Western classical music.
- No rhythm quantization β generated durations are discretized into 10 buckets, which may sound mechanical compared to human performance.
These limitations are inherent to LSTM-based sequence models. A Transformer architecture with full self-attention would address the long-range coherence issue.
Repository
GitHub: Tahsine/CodeAlpha_Music_Generation
License
MIT