Saturday, July 11, 2009

Weighted Song Playing Script

Note that this post has superseded by a new, smart playlist based approach. You can check it out here, where it's available for download.

I have been working on a music weighting script that performs two functions:

1) Determines a rating based on the song's skip and play count information, using proper statistics to account for the uncertainty from small sample sizes. It will also call attention to songs whose ratings are at odds with their actual play history so they can be reevaluated manually if desired (it will automatically do this, but it will take longer). Generating ratings is quite useful for large libraries where sorting music by hand is time consuming. Existing ratings and play and skip data are all taken into account during this process.

2) Determines a play order that gives preference to a song based on its play and skip history as well as the amount of time it's been since it's been played or skipped. It does so in a properly randomized fashion to prevent similarly rated songs from clumping together and to account for uncertainty in the data. This mode is compatible with custom playlists as it will simply pay attention the weighting for the songs contained in the list. It also adjusts the level of advantage popular songs have over unpopular ones to maintain a user defined level of songs successfully being played.

The program is written in Applescript and runs on Macs via iTunes. It adjusts the last played date of each song which allows iPods and iTunes to sort based on that simple parameter. The script can easily be set up to run automatically every few days. Note that almost all music players do not keep play and skip count information and would therefore be incompatible with my script, so it's pretty much Apple devices only. I've tested this script quite extensively, and if anyone is interested in giving it a try leave a comment and I'll write up documentation for it. Since proper docs are a lot of work I'll hold off until there is a request. If requested, I could make a version that only generated song ratings from the play / skip info. The working assumptions are different for a one time examination than a continuous process, but I've already worked out the algorithmic differences.

Theory:

The script is built around the binomial distribution defined by each song's play and skip count information. The distribution is used as the basis for a non-uniform random number generator to compute a weight, which is then multiplied by the amount of time since the song was last attempted (ie played or skipped). While the math for the cumulative binomial distribution is known, the inverse has not been solved explicitly, so a binary search is used to generate the random values.

To control the global success rate when playing songs, the weight generated by the non-uniform random number generator is raised to a power. Since all the weights are in the range from zero to one, the resulting value is also in that range, and values closer to one will decrease less in size. This gives, on average, and advantage to more popular songs. As an example:

The mean ratio for a one star song is 0.1, and the mean for a five star song is 0.9.

This means that normally a five star song will play .9/.1 = 9 times more frequently.

If the results are raised to a power of 1.5, one gets: (.9^1.5) / (.1^1.5) = 27 times more frequently.

The greater the exponent becomes, the larger the advantage higher rated songs will have. In theory, as a lot of data is collected on how popular each song is such a system shouldn't be required, but it can take quite some time for that to occur. It's important not to raise the exponent too high, or else lower rated songs and those simply lacking any information will very rarely be played. The user can set the desired range. The script waits until at least 50 songs have been played or skipped and then uses the ratio of success to guess what the exponent should be adjusted to. The last several runs are averaged together to prevent sharp changes in the output.

To determine the song's rating the binomial distribution formed by the song's play and skip count history is used to determine a rating that is greater than at least 5% of the distribution's total area (this threshold is user controllable). If a manual rating has been set, the script will slowly move the rating away from that value as the data shows it is unlikely. If no rating is provided, a neutral rating of 0.5 is assumed.

The rating doesn't actually effect the weighting algorithm, since the binomial distribution formed by the play and skip counts is used. To incorporate a user's manual rating, therefore, virtual plays and skips are added to the song's actual ones to change the distribution. The relative weight of the rating can be set, and a separate weight is used for computed ratings (iTunes shows hollow stars if a song's album has been rated but the song itself has no rating). The virtual counts are maintained separately so they can be discarded if the real data shows the user's rating to be flawed. If the user changes the rating to one incompatible with the existing data, the data is cleared and the song tested from scratch. The assumption is that the user has observed the data and disagrees with the conclusion for some reason (perhaps someone else had been using their iPod!).

One idea for improvement I'm considering is having the script generate album ratings based on data collected on that album's (or maybe even just artist's) songs. In theory this could allow songs to converge more quickly. It wouldn't count for as much as a manual user rating, but it doesn't require any extra effort. The best system would be for Genius to generate projected ratings, much as Netflix does, but Apple's lousy Genius paradigm is the subject for another post.

7 comments:

  1. I just came to say u look great.

    ReplyDelete
  2. Aw, you're the nicest spambot ever!

    ReplyDelete
  3. Hi Maxim - how are things coming along with this Applescript?

    ReplyDelete
  4. Maxim,

    I tinker endlessly with custom playlists in itunes to get just the right mix of new music, old music, unrated music, etc. I am very interested in your script. Alas, I run itunes on a PC. Is there any hope for me?

    Best,

    Laura F.

    ReplyDelete
  5. Are you still tweaking on this program as it sounds quite fascinating? I have been rating my songs by hand for well over a year now and it is quite daunting. My library is well over 33,000 songs though and some of them I've never even heard before. How will this affect your rating system?

    Thanks,
    Ford

    ReplyDelete
  6. For anyone checking on this, iTunes 10 appears to have broken scripting in Windows (intermittent failures), and I am not optimistic about Apple fixing it in the near future. As a result, I'm experimenting with using smart playlists exclusively to achieve my aims. Not as advanced, but faster and more reliable. Performing pretty well so far, but long term testing is needed to make sure.

    ReplyDelete
  7. The system now has a website and extensive documentation. It works well, but any suggestions for improvement are welcome. You can find it here:

    WSP Music System

    ReplyDelete