Building a crappy personalized song recommender

Note: if you wanna skip straight to the repository, it’s here.

This semester I learned about utilizing APIs and Oauth2 to get data from web services. Time to put this into the test and do something cool - build a crappy song recommender. Here are the steps I followed after some brainstorming. Shoutout to Spotify for having nice data about each song.

  • Ask for several artists that you vibe to
  • Via Spotify, get a few related artists for each artist that the user input
  • Get all albums for each artist as well as their songs
  • get song features for each song (valence/musical positiveness, tempo, danceability, speechiness, energy)
  • Via Genius’s API, search for that song and artist combo for each song and get the song’s lyrics
  • calculate the sentiment of those lyrics
  • store it all in two database tables, one for songs and one for artists

Now that I have the data, how should I go about recommending songs? I decided to do something a bit naive and request the user to rank the song features that they find most important (do they care about danceability more than anything else? What about the sentiment of the lyrics and the valence?). I give each feature a weight based on the ranking. Then I make a weighted sum of those features for all of the songs in the database. I then query the tables to get all songs from the original artists the user specified and take the average of those weighted sums. This is essentially treated as a “desired sum” by the user by taking into account the artists they wanted me to use as a basis. Then, I order the tables by how close they are to the ‘desired_sum’ and spit out the top 20 songs that aren’t from any of the original artists. As mentioned before, this is definitely naive as a user can put in two artists whose songs features are ‘opposite’ of one another. So it’s not necessarily the case that the average of their weighted sums is meaningful to the user (they may not want something ‘in the middle’ but want something related to the first artist, and something related to the second artist). But it was pretty fun nonetheless.

There are definitely plenty of ways to improve this. Like I mentioned in the previous paragraph, what should you do if I give you two completely opposite artists in terms of their musicality? How do I get the optimal weights based on the ranking. Should the user have to rank all 6 or can they just rank one or two features and leave the rest with 0 weights?

I can see my friends using this to help create playlists for specific events/moods encountered in the future. Need a playlist for a party? Specify several artists you can vibe to and give high rankings to danceability, tempo, and energy? I think this is a way to get more data from the user directly. For example, I only enjoy 2 or 3 songs from the playlists Spotify creates for me based on the songs I listen to. If they somehow knew that I really listened to those songs because they were dance-able and didnt give a hoot about the lyrics or the genre, I might receive more songs that I’d enjoy. Maybe Spotify can try to include a ‘let’s get to know you better’ sorta thing when users first sign up. Or if they see a user is playing a playlist they created exclusively, ask them to fill out a brief ranking or survey so they can help improve or extend their playlist. There are many other ways to try and get this implemented. Maybe Spotify should give me a summer to try and work something out with them? :D

I enjoyed this project and would love to extend it if I had the time. I’m interested in Flask development and so I read up on some things and tried to make a Flask app for the user to interact with. It’s not pretty at all. Just the bare minimum such that it works. It was mainly to see if I would actually want to learn more about Flask (answer: yes). You can find everything in this repository.

P.S. There is another part of the flask app that lets you choose an artist, pick some albums from that artist, the choose two features from the song features (valence/musical positiveness, tempo, danceability, speechiness, energy) plus the song duration in minutes and the number of unique words in the song. Then it plots it for you to see using bokeh. You can use it for example to look at mumble rappers and see how the number of unique words in their songs is usually extremely low despite how low the song is (ie it’s mostly just the chorus and the beat).