Music Recommendation Workshop

RythmHacks 2025

Loading...
Artist
Genre
Tempo 120 BPM
Energy 80 %
Dance 75 %
Valence 70 %

Why This Song?

Feature Comparison

How It Works

This app uses content-based filtering to recommend songs based on their musical features. Each song is represented as a point in a 4-dimensional space using:

  • Tempo: Speed in BPM, normalized to 0-1 (dividing by 200)
  • Energy: Intensity and activity level (0-1)
  • Danceability: How suitable for dancing (0-1)
  • Valence: Musical positivity/happiness (0-1)

The algorithm follows three steps:

  • Step 1: Learn your preferences - Learns from all your ratings: 3★ is neutral, >3★ pulls toward a song's features, <3★ pushes away. Tempo is normalized by /200.
  • Step 2: Score candidates - Calculates similarity between your preferences and each unrated song using weighted features
  • Step 3: Recommend best match - Picks the highest-scoring song, with a genre bonus if it matches your favorite genre

Weights control how important each feature is (always sum to 1). Genre bonus adds extra points when the song's genre matches your most-rated genre. You can toggle between abs-diff (absolute difference) and cosine similarity methods.

Workshop Guide: What to Do

Your mission: teach the recommender what you like by rating songs, then experiment with the controls to see how the algorithm changes what it recommends.

Step-by-step

  1. Rate songs with 1–5 stars. No skipping—every rating teaches the model.
  2. After a few ratings, read Why This Song? and the Feature Comparison bars to understand the match.
  3. Tune the weights: drag one feature high and others low. What kinds of songs appear? Then reset weights and try a different emphasis.
  4. Switch similarity (Abs-Diff vs Cosine). Does the recommended song change? Why might these two methods disagree?
  5. Toggle the Genre Bonus. Does your top genre influence the pick? Predict first, then check the result.
  6. Keep rating until you notice a pattern in your preferences (energy, tempo, danceability, valence).

Challenges

  • 90% Club: Achieve a ≥90% match on a song you genuinely like. What settings helped you get there?
  • 5th Dimension: Reduce the dataset to a few songs only. Add a 5th dimension to the songs such as "loudness" in [0,1]. Update the similarity calculations to include this new feature, and see how it affects recommendations. Hint you'll need to update computeUserPreferences(), scoreSong(), and renderBars() to handle the new feature.
  • Moods are Clusters: Similar music tends to group into clusters (e.g., high-energy dance tracks vs. low-energy ballads). Can you add the ability to play music for a certain mood by identifying clusters in the feature space? For example, you could play a workout playlist or one for focusing.

The Math Behind Similarity

We compare your preferences p = [tempoN, energy, danceability, valence] with a song's features s using one of two functions (current mode: abs-diff):

  • Abs-Diff (weighted absolute difference):
    score = Σ w_i · (1 − |p_i − s_i|)
    Each feature is in [0,1] (tempo is normalized by /200). The best possible per-feature term is 1 when they match exactly.
  • Cosine (weighted cosine similarity):
    Scale each component by √w_i, then compute sim = (p·s) / (||p||·||s||), where p and s are the scaled vectors.
    We convert this into a score in [0,1].

Genre bonus: If a song's genre matches your most-rated genre, we add a bonus: score += genreBonus.

Match %: match = round(100 · score / (Σw + bonus_if_applicable)), clamped to [0,100]. Here Σw is the sum of feature weights (1 by default), and the denominator includes the genre bonus only when it applies.

Keyboard Shortcuts: 1-5 Rate | D Debug | W Reset Weights | S Toggle Similarity | G Toggle Genre Bonus

Controls

Similarity Function

Feature Weights

Tempo 0.20
Energy 0.30
Danceability 0.30
Valence 0.20

Genre Bonus

Bonus 0.20

Your Ratings

Debug Info