Examples taken/adapted from "Feature Extraction and Machine Learning of Symbolic Music Using the music21 Toolkit" Get original code here.
from music21 import converter, features
import numpy as npHandel's Messiah, movement 3-05
Feature extracted: Direction of Motion
url = 'http://www.musedata.org/cgi-bin/mddata?composer=handel' \
      '&edition=chry&genre=&work=messiah&format=kern&movement=3-05'
handel = converter.parse(url)"The features implemented in features.jSymbolic are based on those found
in jSymbolic and defined in Cory McKay’s MA Thesis, 'Automatic Genre
Classification of MIDI Recordings.' The LGPL jSymbolic system can be found
here."
"DirectionOfMotionFeature returns the fraction of melodic intervals that
are rising rather than falling. Unisons are omitted."
fe = features.jSymbolic.DirectionOfMotionFeature(handel)Extracts the DirectionOfMotionFeature from handel.
feature = fe.extract()Features are extracted as vectors, thus the need for the index to report a
feature as a single value rather than a list (or array):
Percentage of melodic motion that is ascending: 0.55
print('Percentage of melodic motion that is ascending:',
      feature.vector[0])Two movements from Handel's Messiah
Feature extracted: Triple meter (1 = True, 0 = False)
Handel's Messiah, movement 3-04
handel2 = converter.parse("http://www.musedata.org/cgi-bin/mddata?" \
                          "composer=handel&edition=chry&genre=&work=" \
                          "messiah&format=kern&movement=3-04")
fe = features.jSymbolic.TripleMeterFeature(handel2)Movement 3-04 is in triple meter:
Triple Meter Feature Vector for Handel movement 3-04: 1
print('Triple Meter Feature Vector for Handel movement 3-04:',
      fe.extract().vector[0])Handel's Messiah, movement 3-05
handel = converter.parse('http://www.musedata.org/cgi-bin/mddata?' \
                         'composer=handel&edition=chry&genre=&work=' \
                         'messiah&format=kern&movement=3-05')
fe = features.jSymbolic.TripleMeterFeature(handel)Movement 3-05 is not in triple meter:
Triple Meter Feature Vector for Handel movement 3-05: 0
print('Triple Meter Feature Vector for Handel movement 3-05:',
      fe.extract().vector[0])Feature extraction by ID
M10 Chromatic Motion: Fraction of melodic intervals that correspond
to a semitone.
M12 Melodic Thirds: Fraction of melodic intervals that are major or
minor thirds.
M13 Melodic Fifths: Fraction of melodic intervals that are perfect fifths.
fes = features.extractorsById(['M10','M12','M13'])fes is a list of music21.features.jSymbolic subclasses:
<class 'music21.features.jSymbolic.ChromaticMotionFeature'>
<class 'music21.features.jSymbolic.MelodicThirdsFeature'>
<class 'music21.features.jSymbolic.MelodicFifthsFeature'>
for feature in fes:
    print(feature)Using music21's DataSet class, which combines a set of features and a collection of data from which to extract the features. See the documentation for details.
Create a new DataSet. classLabel is string describing the labels for
data added to the dataset.
ds = features.DataSet(classLabel='Composer')
fes = features.extractorsById(['M10','M12','M13'])
ds.addFeatureExtractors(fes)Add streams to the dataset using the addData method.
Bach, Art of Fugue 7, mm. 1 - 50
art_of_fugue_7 = 'http://www.musedata.org/cgi-bin/mddata?composer=' \
                 'bach&edition=bg&genre=canon&work=1080&format=' \
                 'kern&movement=07'
b1 = converter.parse(art_of_fugue_7).measures(0, 50)Add stream with classValue 1 (for Bach) and id Art of Fugue
ds.addData(b1, classValue=1, id='Art of Fugue')Add stream with classValue 1 and id BWV 66.6
ds.addData('bwv66.6.xml', classValue=1, id='BWV 66.6')Handel, Messiah, movement 3-5
url = 'http://www.musedata.org/cgi-bin/mddata?composer=handel&' \
      'edition=chry&genre=&work=messiah&format=kern&movement=3-05'
handel_messiah_3_05 = converter.parse(url)Add stream with classValue 2 (for Handel) and id Messiah
ds.addData(handel_messiah_3_05, classValue=2, id='Messiah')Add stream with classValue 2 and id mystery Handel
url = 'http://www.midiworld.com/midis/other/handel/gfh-jm01.mid'
handel_mystery = converter.parse(url)
ds.addData(handel_mystery, classValue=2, id='mystery Handel')The process method processes "all Data with all FeatureExtractors."
ds.process()getAttributeLabels returns a list of attribute labels:
Attribue labels: ['Identifier', 'Chromatic_Motion', 'Melodic_Thirds', 'Melodic_Fifths', 'Composer']
print('Attribue labels:', ds.getAttributeLabels(), "\n")getFeaturesAsList returns a list of attribute values for all streams added
to the DataSet:
Features for work: ['Art_of_Fugue', 0.33980582524271846, 0.049352750809061485, 0.040453074433656956, 1]
Features for work: ['bwv66.6.xml', 0.22012578616352202, 0.11320754716981132, 0.05660377358490566, 1]
Features for work: ['Messiah', 0.06896551724137931, 0.1724137931034483, 0.0, 2]
Features for work: ['mystery_Handel', 0.18497576736672053, 0.1583198707592892, 0.03877221324717286, 2]
for work in ds.getFeaturesAsList():
    print('Features for work:', work)
    print()Access identifiers, features values, and labels with the appropriate indices
for getFeaturesAsList:  
dataset = np.array(ds.getFeaturesAsList())>>> identifiers
array(['Art_of_Fugue', 'bwv66.6.xml', 'Messiah', 'mystery_Handel'],
dtype='<U20')  
identifiers = dataset[:, 0]>>> data
array([['0.33980582524271846', '0.049352750809061485',
'0.040453074433656956'],
['0.22012578616352202', '0.11320754716981132', '0.05660377358490566'],
['0.06896551724137931', '0.1724137931034483', '0.0'],
['0.18497576736672053', '0.1583198707592892', '0.03877221324717286']],
dtype='<U20')
data = dataset[:, 1:4]>>> targets
array(['1', '1', '2', '2'],
dtype='<U20')
targets = dataset[:, 4]