Difference between revisions of "MIR workshop 2011 day5 lab"

From CCRMA Wiki
Jump to: navigation, search
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
<h1>MIR Workshop 2011 Day 5 Lab</h1>
+
MIR Workshop 2011 Day 5 Lab on Music Recommendation<br>
<h2>Douglas Eck, Google</h2>
+
Douglas Eck, Google
  
  
<h2>Overview<h2>
+
<h2>Overview</h2>
 
This lab covers the construction of parts of a music recommender. Focus is placed on building a similarity matrix from data and querying that matrix based on cosine distance.  
 
This lab covers the construction of parts of a music recommender. Focus is placed on building a similarity matrix from data and querying that matrix based on cosine distance.  
 
Fast programmers should be able to accomplish considerably more.   
 
Fast programmers should be able to accomplish considerably more.   
Line 10: Line 10:
 
* The basics (some Python code available to help).
 
* The basics (some Python code available to help).
 
** Calculate acoustic features on CAL500 dataset (students should have already done this.)  
 
** Calculate acoustic features on CAL500 dataset (students should have already done this.)  
** Read in user tag annotations from same dataset provided by UCSD.
+
** Read in user tag annotations for the same dataset provided by UCSD.
** Build similarity matrix based on word vectors derived from these annotations.
+
** Build similarity matrix based on word vectors derived from these annotations. In my implementation the matrix is stored as a dictionary of vectors, but this is python-specific.
 
** Query similarity matrix with a track to get top hits based on cosine distance.
 
** Query similarity matrix with a track to get top hits based on cosine distance.
 
** Build second similarity matrix using acoustic features.  
 
** Build second similarity matrix using acoustic features.  
Line 20: Line 20:
 
** Use the CAL500 user annotations as ground truth and evaluate your audio features (ROC curve or some precision measure).  
 
** Use the CAL500 user annotations as ground truth and evaluate your audio features (ROC curve or some precision measure).  
 
** Compare a 2D visualization of acoustic features versus UCSD user annotations.
 
** Compare a 2D visualization of acoustic features versus UCSD user annotations.
 
+
** Train a classifier on CAL500.  Train / test splits will be generated this afternoon.
 
+
  
 
Lab code is found in /usr/ccrma/courses/mir20110/cal500_new.
 
Lab code is found in /usr/ccrma/courses/mir20110/cal500_new.
 
A previous version was uploaded at /usr/ccrma/courses/mir2011/cal500 but it was using filenames from my University of Montreal lab.  I renamed audio files to match those of UCSD Cal500
 
A previous version was uploaded at /usr/ccrma/courses/mir2011/cal500 but it was using filenames from my University of Montreal lab.  I renamed audio files to match those of UCSD Cal500
 +
 +
An example call for the code provided by me:
 +
 +
<pre>
 +
%python cal500_example.py norah_jones-dont_know_why
 +
1 Cosine distance=0.0000 Track=norah_jones-dont_know_why
 +
2 Cosine distance=0.1111 Track=carole_king-youve_got_a_friend
 +
3 Cosine distance=0.1365 Track=alicia_keys-fallin
 +
4 Cosine distance=0.1387 Track=dido-here_with_me
 +
5 Cosine distance=0.1610 Track=fiona_apple-love_ridden
 +
6 Cosine distance=0.1646 Track=barry_manilow-mandy
 +
7 Cosine distance=0.1661 Track=stan_getz-corcovado_quiet_nights_of_quiet_stars
 +
8 Cosine distance=0.1696 Track=aimee_mann-wise_up
 +
9 Cosine distance=0.1758 Track=marvelettes-please_mr._postman
 +
10 Cosine distance=0.1772 Track=ben_folds_five-brick
 +
11 Cosine distance=0.1795 Track=cranberries-linger
 +
12 Cosine distance=0.1833 Track=sade-smooth_operator
 +
13 Cosine distance=0.1860 Track=john_lennon-imagine
 +
14 Cosine distance=0.1864 Track=dionne_warwick-walk_on_by
 +
15 Cosine distance=0.1918 Track=5th_dimension-one_less_bell_to_answer
 +
16 Cosine distance=0.1923 Track=carpenters-rainy_days_and_mondays
 +
17 Cosine distance=0.1932 Track=diana_ross_and_the_supremes-where_did_our_love_go
 +
18 Cosine distance=0.1939 Track=smokey_robinson_and_the_miracles-ooo_baby_baby
 +
19 Cosine distance=0.1939 Track=fleetwood_mac-say_you_love_me
 +
20 Cosine distance=0.1970 Track=rufus_wainwright-cigarettes_and_chocolate_milk
 +
</pre>
 +
 +
 +
Functions provided by me in cal500_example.py.  Students can recode as they please in any language. They are free to use as much of my code as they want.
 +
 +
<pre>
 +
def RemapFilename(infile):
 +
  """Maps a filename from Doug name to real cal500 name."""
 +
 +
 +
def RenameCal500(dest_directory='high_bitrate'):
 +
  """Renames cal500 files from Doug naming scheme to standard one
 +
  and places them in dest_directory."""
 +
 +
 +
def MakeFilenameMap(infile = 'cal500_doug_filenames.txt',
 +
                      outfile = 'cal500_filename_map.txt'):
 +
  """Create text file mapping old (Doug) filenames to standard
 +
  Cal500 filenames."""
 +
 +
 +
def GetKeyFromAnnotationPath(annotation_path):
 +
  """Gets key from annnotation file path, stripping off
 +
  the number.
 +
  # Ex: norine_braun-spanish_banks_02.txt yields
 +
  # norine_braun-spanish_banks
 +
 +
 +
# Mapping from text values in CAL500 annotation files to (somewhat arbitrary) numeric values.
 +
ANNOTATION_MAP = {
 +
    'yes': 1.0,
 +
    'prominent': 1.0,
 +
    'present': 0.75,
 +
    'uncertain': 0.5,
 +
    'no': 0.0,
 +
    'none': 0.0,
 +
    '5': 5/5.0,
 +
    '4': 4/5.0,
 +
    '3': 3/5.0,
 +
    '2': 2/5.0,
 +
    '1': 1/5.0,
 +
    '0': 0.0
 +
    }
 +
 +
 +
def AddTagWeightsToDictFromAnnotationFile(annotation_path, tag_weights):
 +
  """Reads tag weights into a dictionary keyed by tag name
 +
  and adds them to the defaultdict tag_weights. Use key 'counter'
 +
  to track number of annotations."""
 +
 +
 +
def BuildTagDictionary(tag_directory='annotations'):
 +
  """Builds dictionary mapping cal500 key to a weighted tag vector.
 +
  Returns dictionary and our vocabulary of tags."""
 +
 +
 +
def BuildVectorDictionaryFromTagDictionary(tag_dict, vocabulary):
 +
  """Transforms tag dictionaries int tag vectors using vocabulary."""
 +
 +
 +
def CosineDistance(v1, v2):
 +
  """Calculates cosine distance using numpy."""
 +
 +
 +
def ScoreQuery(vector_dict, query):
 +
  """Finds nearest neigbors for query in vector_dict."""
 +
 +
 +
def PrintScoreDict(score_dict, query, k=20):
 +
  """Print score dictionary for a query."""
 +
 +
 +
# Here is the main function as called above.
 +
if __name__=='__main__':
 +
  if len(sys.argv)>1:
 +
    query = sys.argv[1]
 +
  else:
 +
    query = 'norah_jones-dont_know_why'
 +
 +
  # Build vectors from words.
 +
  tag_dict, vocabulary = BuildTagDictionary()
 +
  vector_dict = BuildVectorDictionaryFromTagDictionary(tag_dict, vocabulary)
 +
 +
  # Score a query.
 +
  score_dict = ScoreQuery(vector_dict, query)
 +
  PrintScoreDict(score_dict, query)
 +
 +
</pre>

Latest revision as of 09:04, 1 July 2011

MIR Workshop 2011 Day 5 Lab on Music Recommendation
Douglas Eck, Google


Overview

This lab covers the construction of parts of a music recommender. Focus is placed on building a similarity matrix from data and querying that matrix based on cosine distance. Fast programmers should be able to accomplish considerably more.


  • The basics (some Python code available to help).
    • Calculate acoustic features on CAL500 dataset (students should have already done this.)
    • Read in user tag annotations for the same dataset provided by UCSD.
    • Build similarity matrix based on word vectors derived from these annotations. In my implementation the matrix is stored as a dictionary of vectors, but this is python-specific.
    • Query similarity matrix with a track to get top hits based on cosine distance.
    • Build second similarity matrix using acoustic features.
    • Query this similarity matrix with track to get top hits based on cosine distance.
  • Extra (I didn't write code for this, but can help students find examples).
    • Query the EchoNest for additional acoustic features and compare to yours.
    • Use the CAL500 user annotations as ground truth and evaluate your audio features (ROC curve or some precision measure).
    • Compare a 2D visualization of acoustic features versus UCSD user annotations.
    • Train a classifier on CAL500. Train / test splits will be generated this afternoon.

Lab code is found in /usr/ccrma/courses/mir20110/cal500_new. A previous version was uploaded at /usr/ccrma/courses/mir2011/cal500 but it was using filenames from my University of Montreal lab. I renamed audio files to match those of UCSD Cal500

An example call for the code provided by me:

%python cal500_example.py norah_jones-dont_know_why
1 Cosine distance=0.0000 Track=norah_jones-dont_know_why
2 Cosine distance=0.1111 Track=carole_king-youve_got_a_friend
3 Cosine distance=0.1365 Track=alicia_keys-fallin
4 Cosine distance=0.1387 Track=dido-here_with_me
5 Cosine distance=0.1610 Track=fiona_apple-love_ridden
6 Cosine distance=0.1646 Track=barry_manilow-mandy
7 Cosine distance=0.1661 Track=stan_getz-corcovado_quiet_nights_of_quiet_stars
8 Cosine distance=0.1696 Track=aimee_mann-wise_up
9 Cosine distance=0.1758 Track=marvelettes-please_mr._postman
10 Cosine distance=0.1772 Track=ben_folds_five-brick
11 Cosine distance=0.1795 Track=cranberries-linger
12 Cosine distance=0.1833 Track=sade-smooth_operator
13 Cosine distance=0.1860 Track=john_lennon-imagine
14 Cosine distance=0.1864 Track=dionne_warwick-walk_on_by
15 Cosine distance=0.1918 Track=5th_dimension-one_less_bell_to_answer
16 Cosine distance=0.1923 Track=carpenters-rainy_days_and_mondays
17 Cosine distance=0.1932 Track=diana_ross_and_the_supremes-where_did_our_love_go
18 Cosine distance=0.1939 Track=smokey_robinson_and_the_miracles-ooo_baby_baby
19 Cosine distance=0.1939 Track=fleetwood_mac-say_you_love_me
20 Cosine distance=0.1970 Track=rufus_wainwright-cigarettes_and_chocolate_milk


Functions provided by me in cal500_example.py. Students can recode as they please in any language. They are free to use as much of my code as they want.

def RemapFilename(infile):
  """Maps a filename from Doug name to real cal500 name."""


def RenameCal500(dest_directory='high_bitrate'):
  """Renames cal500 files from Doug naming scheme to standard one
  and places them in dest_directory."""


def MakeFilenameMap(infile = 'cal500_doug_filenames.txt',
                      outfile = 'cal500_filename_map.txt'):
  """Create text file mapping old (Doug) filenames to standard
  Cal500 filenames."""


def GetKeyFromAnnotationPath(annotation_path):
  """Gets key from annnotation file path, stripping off
  the number.
  # Ex: norine_braun-spanish_banks_02.txt yields
  # norine_braun-spanish_banks


# Mapping from text values in CAL500 annotation files to (somewhat arbitrary) numeric values.
ANNOTATION_MAP = {
    'yes': 1.0,
    'prominent': 1.0,
    'present': 0.75,
    'uncertain': 0.5,
    'no': 0.0,
    'none': 0.0,
    '5': 5/5.0,
    '4': 4/5.0,
    '3': 3/5.0,
    '2': 2/5.0,
    '1': 1/5.0,
    '0': 0.0
    }


def AddTagWeightsToDictFromAnnotationFile(annotation_path, tag_weights):
  """Reads tag weights into a dictionary keyed by tag name
  and adds them to the defaultdict tag_weights. Use key 'counter'
  to track number of annotations."""


def BuildTagDictionary(tag_directory='annotations'):
  """Builds dictionary mapping cal500 key to a weighted tag vector.
  Returns dictionary and our vocabulary of tags."""


def BuildVectorDictionaryFromTagDictionary(tag_dict, vocabulary):
  """Transforms tag dictionaries int tag vectors using vocabulary."""


def CosineDistance(v1, v2):
  """Calculates cosine distance using numpy."""


def ScoreQuery(vector_dict, query):
  """Finds nearest neigbors for query in vector_dict."""


def PrintScoreDict(score_dict, query, k=20):
  """Print score dictionary for a query."""


# Here is the main function as called above.
if __name__=='__main__':
  if len(sys.argv)>1:
    query = sys.argv[1]
  else:
    query = 'norah_jones-dont_know_why'

  # Build vectors from words.
  tag_dict, vocabulary = BuildTagDictionary()
  vector_dict = BuildVectorDictionaryFromTagDictionary(tag_dict, vocabulary)

  # Score a query.
  score_dict = ScoreQuery(vector_dict, query)
  PrintScoreDict(score_dict, query)