Create personalized music by learning from simple ratings - no musical knowledge required
Listen to generated melodies and rate them
PLGL learns your musical taste from ratings
Create new compositions matching your preferences
The system uses a Variational Autoencoder (VAE) to learn a latent representation of music. This creates a continuous space where similar melodies are close together.
class MusicVAE(nn.Module):
def __init__(self, latent_dim: int = 256):
super().__init__()
self.latent_dim = latent_dim
# Encoder: Piano roll → Latent space
self.encoder = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=(12, 4), stride=(2, 2)),
nn.ReLU(),
nn.Conv2d(32, 64, kernel_size=(12, 4), stride=(2, 2)),
# ... compress to latent dimensions
)
# Decoder: Latent space → Piano roll
self.decoder = nn.Sequential(
nn.Linear(latent_dim, 512),
nn.ReLU(),
# ... expand back to piano roll
nn.Sigmoid() # Note probabilities 0-1
)
PLGL extracts interpretable musical features to understand what makes melodies appealing:
def extract_musical_features(self, melody: torch.Tensor) -> Dict[str, float]:
"""Extract interpretable musical features"""
features = {
'pitch_range': self._compute_pitch_range(piano_roll), # How wide
'note_density': self._compute_note_density(piano_roll), # How busy
'rhythmic_complexity': self._compute_rhythmic_complexity(), # Rhythm variety
'melodic_contour': self._compute_melodic_contour(), # Up/down movement
'harmonic_consistency': self._compute_harmonic_consistency() # Musical intervals
}
return features
A neural network learns to predict your ratings from musical features:
class MusicPreferenceLearner:
def __init__(self, music_vae: MusicVAE):
self.vae = music_vae
# Preference model: Piano roll → Rating (0-1)
self.preference_model = nn.Sequential(
nn.Linear(128 * 32, 512), # Flattened piano roll
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, 1),
nn.Sigmoid() # Output preference score
)
Navigate the latent space to find melodies with high preference scores:
def generate_personalized_melody(self, optimization_steps: int = 500):
# Start from random point in latent space
z = torch.randn(1, self.latent_dim, requires_grad=True)
optimizer = torch.optim.Adam([z], lr=0.01)
for step in range(optimization_steps):
# Generate melody from latent code
melody = self.vae.decode(z)
# Score with preference model
score = self.preference_model(melody.flatten())
# Optimize to maximize score
loss = -score
loss.backward()
optimizer.step()
# Add exploration noise
z += torch.randn_like(z) * 0.01
return self.generate_melody(z)
Create diverse playlists that still match your preferences:
def generate_playlist(self, n_songs: int = 10, diversity: float = 0.5):
playlist = []
for i in range(n_songs):
if i % 2 == 0:
# High-preference melody (exploitation)
melody = self.generate_personalized_melody()
else:
# Diverse but still good (exploration)
z = torch.randn(1, self.latent_dim)
# Ensure different from previous songs
if playlist:
distances = torch.norm(z - prev_latents, dim=1)
while distances.min() < diversity:
z = torch.randn(1, self.latent_dim)
playlist.append(melody)
return playlist
Generate infinite playlists that match your mood and taste, discovering new melodies you'll love.
Create dynamic soundtracks that adapt to player preferences in real-time.
Generate music that matches director preferences without describing technical requirements.
Like TikTok for music - swipe through generated melodies, no searching or prompting needed.
Ready to implement PLGL for music generation?