WEBVTT

00:00:00.000 --> 00:00:02.410 align:middle line:90%
[SQUEAKING]

00:00:02.410 --> 00:00:04.338 align:middle line:90%
[RUSTLING]

00:00:04.338 --> 00:00:06.748 align:middle line:90%
[CLICKING]

00:00:06.748 --> 00:00:09.262 align:middle line:90%


00:00:09.262 --> 00:00:11.220 align:middle line:84%
MICHAEL SCOTT ASATO
CUTHBERT: Hello, everybody.

00:00:11.220 --> 00:00:12.803 align:middle line:84%
We're going to be
looking today at how

00:00:12.803 --> 00:00:17.180 align:middle line:84%
we can use machine learning and
artificial intelligence in order

00:00:17.180 --> 00:00:22.970 align:middle line:84%
to learn more about musical
behavior and music theory

00:00:22.970 --> 00:00:25.400 align:middle line:90%
and just music in general.

00:00:25.400 --> 00:00:28.190 align:middle line:84%
Our first task is
going to be how do we

00:00:28.190 --> 00:00:32.610 align:middle line:84%
transform music into formats
that computers can learn from?

00:00:32.610 --> 00:00:36.680 align:middle line:84%
Because a score alone
is not something

00:00:36.680 --> 00:00:39.060 align:middle line:84%
that can be used for
artificial intelligence.

00:00:39.060 --> 00:00:42.710 align:middle line:84%
And so our first task is
going to be understanding

00:00:42.710 --> 00:00:47.270 align:middle line:84%
how feature extraction, the
conversion of musical scores

00:00:47.270 --> 00:00:53.930 align:middle line:84%
into intelligent numerical
data, how feature extraction is

00:00:53.930 --> 00:00:57.050 align:middle line:84%
able to make machine
learning possible.

00:00:57.050 --> 00:01:00.640 align:middle line:84%
So go ahead and load
up Jupyter Notebook

00:01:00.640 --> 00:01:04.810 align:middle line:84%
and follow along as we do
some work with music21,

00:01:04.810 --> 00:01:09.590 align:middle line:84%
first separate from the music21
machine learning toolkit,

00:01:09.590 --> 00:01:13.150 align:middle line:84%
and then with music21
features in order

00:01:13.150 --> 00:01:19.660 align:middle line:84%
to learn more about some genres
and other ways of classifying

00:01:19.660 --> 00:01:21.190 align:middle line:90%
music.

00:01:21.190 --> 00:01:24.890 align:middle line:84%
So go ahead and start
Jupyter Notebook.

00:01:24.890 --> 00:01:27.880 align:middle line:84%
And we're going to create
the first step, which

00:01:27.880 --> 00:01:31.060 align:middle line:84%
is to understand
what features are

00:01:31.060 --> 00:01:34.900 align:middle line:84%
and why we might
want to extract them.

00:01:34.900 --> 00:01:37.730 align:middle line:90%
So what is a feature?

00:01:37.730 --> 00:01:40.040 align:middle line:84%
That's the first thing
we're going to work on.

00:01:40.040 --> 00:01:43.340 align:middle line:84%
Feature is something really,
really, really basic.

00:01:43.340 --> 00:01:45.820 align:middle line:90%
Let's say that we have a piece.

00:01:45.820 --> 00:01:49.885 align:middle line:84%
We'll load from the music21
corpus, our favorite Bach

00:01:49.885 --> 00:01:50.900 align:middle line:90%
chorale.

00:01:50.900 --> 00:01:55.940 align:middle line:84%
So you don't even need to know
what comes up from this corpus.

00:01:55.940 --> 00:02:01.480 align:middle line:90%
Parse bach.bwv66.6.

00:02:01.480 --> 00:02:06.910 align:middle line:84%
And just to remind ourselves
how it goes, here's the Bach.

00:02:06.910 --> 00:02:07.970 align:middle line:90%
So great.

00:02:07.970 --> 00:02:14.840 align:middle line:84%
Let's go ahead and choose
a feature from this.

00:02:14.840 --> 00:02:16.930 align:middle line:90%
Let's do the parts feature.

00:02:16.930 --> 00:02:22.700 align:middle line:84%
And we'll call it
numParts equals 4.

00:02:22.700 --> 00:02:31.780 align:middle line:84%
And let's do the time signature
numerator feature equals 4.

00:02:31.780 --> 00:02:32.320 align:middle line:90%
There.

00:02:32.320 --> 00:02:41.740 align:middle line:84%
We've now extracted manually
two features from this chorale.

00:02:41.740 --> 00:02:46.000 align:middle line:84%
Feature extraction is the
conversion of musical elements,

00:02:46.000 --> 00:02:47.120 align:middle line:90%
or any elements.

00:02:47.120 --> 00:02:49.120 align:middle line:84%
But musical feature
extraction is the conversion

00:02:49.120 --> 00:02:53.410 align:middle line:84%
of musical elements into single
numbers or lists, arrays,

00:02:53.410 --> 00:02:56.640 align:middle line:90%
vectors of numbers.

00:02:56.640 --> 00:03:01.530 align:middle line:84%
It is thus the most
boring thing in the world,

00:03:01.530 --> 00:03:04.020 align:middle line:90%
as you've just seen.

00:03:04.020 --> 00:03:06.700 align:middle line:90%
It is just a bunch of numbers.

00:03:06.700 --> 00:03:11.860 align:middle line:84%
Feature extraction sucks
out the lifeblood of music.

00:03:11.860 --> 00:03:14.370 align:middle line:84%
It takes everything
that's beautiful in music

00:03:14.370 --> 00:03:16.660 align:middle line:84%
and turns it into
a bunch of numbers.

00:03:16.660 --> 00:03:18.610 align:middle line:90%
It is a life sucker.

00:03:18.610 --> 00:03:23.160 align:middle line:84%
It is the zombie of
the musical world.

00:03:23.160 --> 00:03:26.580 align:middle line:84%
But there are tons of
amazing machine learning

00:03:26.580 --> 00:03:28.740 align:middle line:84%
and artificial intelligence
and deep learning

00:03:28.740 --> 00:03:30.010 align:middle line:90%
algorithms in the world.

00:03:30.010 --> 00:03:33.010 align:middle line:84%
As far as I know, they all
have one thing in common.

00:03:33.010 --> 00:03:36.750 align:middle line:84%
They only work on collections
of single numbers or vectors

00:03:36.750 --> 00:03:38.670 align:middle line:90%
of numbers.

00:03:38.670 --> 00:03:40.720 align:middle line:84%
I'm not a machine
learning expert,

00:03:40.720 --> 00:03:43.410 align:middle line:84%
so maybe there are
algorithms that work on two

00:03:43.410 --> 00:03:45.250 align:middle line:84%
or multi-dimensional
arrays of numbers.

00:03:45.250 --> 00:03:48.930 align:middle line:84%
That would be amazing for
machine vision or what we do.

00:03:48.930 --> 00:03:52.950 align:middle line:84%
But nothing, as far as I know
in the artificial intelligence

00:03:52.950 --> 00:03:59.970 align:middle line:84%
world, works on things
like this notation, or--

00:03:59.970 --> 00:04:02.240 align:middle line:90%
[AUDIO PLAYBACK]

00:04:02.240 --> 00:04:04.010 align:middle line:90%
-

00:04:04.010 --> 00:04:06.230 align:middle line:90%


00:04:06.230 --> 00:04:07.340 align:middle line:90%
[END PLAYBACK]

00:04:07.340 --> 00:04:08.840 align:middle line:84%
MICHAEL SCOTT ASATO
CUTHBERT: Sound.

00:04:08.840 --> 00:04:11.570 align:middle line:84%
So if we're going to work on
doing artificial intelligence

00:04:11.570 --> 00:04:14.780 align:middle line:84%
or predictions or anything
super amazing on music

00:04:14.780 --> 00:04:17.540 align:middle line:84%
notation, at least
at present, we

00:04:17.540 --> 00:04:21.769 align:middle line:84%
need to convert
music to numbers.

00:04:21.769 --> 00:04:24.530 align:middle line:84%
So that's what
feature extraction is.

00:04:24.530 --> 00:04:29.330 align:middle line:84%
Basic feature extraction
is pretty simple.

00:04:29.330 --> 00:04:34.160 align:middle line:84%
So in this case, let's
just extract automatically

00:04:34.160 --> 00:04:36.570 align:middle line:90%
the meter from this piece.

00:04:36.570 --> 00:04:40.650 align:middle line:84%
So we'll write
something that does it.

00:04:40.650 --> 00:04:42.950 align:middle line:84%
We'll import from
the typing module

00:04:42.950 --> 00:04:45.450 align:middle line:84%
because we like to
do things like this.

00:04:45.450 --> 00:04:50.120 align:middle line:84%
Turn Python, which is a weakly
typed language, into slightly

00:04:50.120 --> 00:04:55.930 align:middle line:84%
stronger types so that we can
understand a little bit better

00:04:55.930 --> 00:04:57.680 align:middle line:90%
what's going to go on.

00:04:57.680 --> 00:04:59.980 align:middle line:84%
So we'll also import
from music21 the meter

00:04:59.980 --> 00:05:01.040 align:middle line:90%
and stream modules.

00:05:01.040 --> 00:05:05.320 align:middle line:84%
Now let's write
something called extract.

00:05:05.320 --> 00:05:10.480 align:middle line:84%
Extract meter, which takes
in a variable score, which is

00:05:10.480 --> 00:05:13.520 align:middle line:90%
a stream.Stream stream object.

00:05:13.520 --> 00:05:15.380 align:middle line:84%
Maybe it should be a
stream.Score object,

00:05:15.380 --> 00:05:17.860 align:middle line:90%
but let's keep it flexible.

00:05:17.860 --> 00:05:21.520 align:middle line:84%
And it returns a
tuple of two integers.

00:05:21.520 --> 00:05:28.870 align:middle line:84%
And we'll say here that returns
a 2-tuple of the numerator

00:05:28.870 --> 00:05:43.930 align:middle line:84%
and the denominator of the first
time signature found in a score.

00:05:43.930 --> 00:05:52.420 align:middle line:84%
Returns 0, comma, 0 if
the score has no meter.

00:05:52.420 --> 00:05:55.570 align:middle line:84%
Why do we return 0, comma,
0 if there's no meter?

00:05:55.570 --> 00:05:57.580 align:middle line:84%
In feature extraction,
it's generally

00:05:57.580 --> 00:05:59.980 align:middle line:84%
assumed that we
want to return out

00:05:59.980 --> 00:06:02.450 align:middle line:84%
of bound number rather
than raising exception

00:06:02.450 --> 00:06:04.060 align:middle line:90%
if there's a mistake.

00:06:04.060 --> 00:06:07.960 align:middle line:84%
And the reason is you'd hate
to be running extract meter

00:06:07.960 --> 00:06:09.920 align:middle line:84%
on hundreds or
thousands of pieces,

00:06:09.920 --> 00:06:13.150 align:middle line:84%
and you're always getting 4,
comma, 4, or 3, comma, 4 or 6,

00:06:13.150 --> 00:06:16.760 align:middle line:84%
comma 8, or even something
wacky like 11, comma, 32.

00:06:16.760 --> 00:06:18.970 align:middle line:84%
And it's all
working successfully

00:06:18.970 --> 00:06:21.350 align:middle line:84%
only to have your entire
feature extraction,

00:06:21.350 --> 00:06:23.930 align:middle line:84%
artificial intelligence
pipeline fail

00:06:23.930 --> 00:06:26.990 align:middle line:84%
if there's one piece that
doesn't have a time signature.

00:06:26.990 --> 00:06:29.500 align:middle line:84%
Like let's say it's
Gregorian chant or some kind

00:06:29.500 --> 00:06:31.900 align:middle line:90%
of trance meditation.

00:06:31.900 --> 00:06:36.640 align:middle line:84%
So that's why we're going
to be returning 0, comma, 0.

00:06:36.640 --> 00:06:39.430 align:middle line:84%
On the other hand, maybe
it's a bad assumption

00:06:39.430 --> 00:06:42.650 align:middle line:84%
and we should raise exceptions
when something's not right.

00:06:42.650 --> 00:06:45.795 align:middle line:84%
And then we should fix our
work rather than hiding errors.

00:06:45.795 --> 00:06:48.310 align:middle line:90%


00:06:48.310 --> 00:06:50.650 align:middle line:84%
But we'll get to
that in just a bit.

00:06:50.650 --> 00:06:52.300 align:middle line:90%
First meter.

00:06:52.300 --> 00:06:54.280 align:middle line:84%
But first, let's
see how we do this.

00:06:54.280 --> 00:06:57.420 align:middle line:84%
So let's just remind ourselves
we can take from anything

00:06:57.420 --> 00:07:01.140 align:middle line:84%
get elements by class,
meter.TimeSignature.

00:07:01.140 --> 00:07:03.690 align:middle line:90%


00:07:03.690 --> 00:07:07.950 align:middle line:84%
And if we do not have
any, the first meter

00:07:07.950 --> 00:07:13.980 align:middle line:84%
will return 0, comma,
0, and otherwise

00:07:13.980 --> 00:07:19.710 align:middle line:84%
will return the first meter's
numerator and the first meter's

00:07:19.710 --> 00:07:23.160 align:middle line:90%
denominator.

00:07:23.160 --> 00:07:26.670 align:middle line:84%
We're kind of hiding an
error in our encoding.

00:07:26.670 --> 00:07:28.120 align:middle line:90%
Is that the right thing to do?

00:07:28.120 --> 00:07:30.825 align:middle line:84%
And I think this
is something that,

00:07:30.825 --> 00:07:32.520 align:middle line:84%
when we're talking
about it-- and I

00:07:32.520 --> 00:07:36.120 align:middle line:84%
would love to talk to
anybody directly about ethics

00:07:36.120 --> 00:07:41.160 align:middle line:84%
and morality and who artificial
intelligence is working for,

00:07:41.160 --> 00:07:44.580 align:middle line:84%
because I think there are
often important considerations

00:07:44.580 --> 00:07:47.750 align:middle line:84%
of artificial intelligence with
moral and ethical consequences

00:07:47.750 --> 00:07:50.790 align:middle line:84%
when we hide things
that it can't do.

00:07:50.790 --> 00:07:52.850 align:middle line:90%
And so I want you--

00:07:52.850 --> 00:07:54.350 align:middle line:84%
if you're going to
be somebody who's

00:07:54.350 --> 00:07:56.570 align:middle line:84%
going to be working with
artificial intelligence

00:07:56.570 --> 00:07:58.550 align:middle line:84%
and the rest of your
life and technology

00:07:58.550 --> 00:08:00.680 align:middle line:84%
to think about such
things, maybe we

00:08:00.680 --> 00:08:04.250 align:middle line:84%
shouldn't be hiding
our errors so much.

00:08:04.250 --> 00:08:05.310 align:middle line:90%
OK.

00:08:05.310 --> 00:08:08.160 align:middle line:84%
So we have this extract
meter to get back to this.

00:08:08.160 --> 00:08:10.140 align:middle line:90%
Oops.

00:08:10.140 --> 00:08:13.100 align:middle line:84%
Doesn't matter if you put a
parentheses around a tuple

00:08:13.100 --> 00:08:14.160 align:middle line:90%
when you return it.

00:08:14.160 --> 00:08:16.620 align:middle line:84%
But if you start with one,
you have to do the other.

00:08:16.620 --> 00:08:19.190 align:middle line:84%
OK, so let's take this
Bach chorale and let's

00:08:19.190 --> 00:08:26.090 align:middle line:90%
run extract meter on the bach.

00:08:26.090 --> 00:08:27.540 align:middle line:90%
0, comma, 0.

00:08:27.540 --> 00:08:29.250 align:middle line:90%
Oh, I know why.

00:08:29.250 --> 00:08:33.845 align:middle line:90%
Because we forgot to do recurse.

00:08:33.845 --> 00:08:37.490 align:middle line:84%
Flat would do just as well, but
recurse is a little bit faster.

00:08:37.490 --> 00:08:40.070 align:middle line:84%
Oh, by the way, something
I didn't mention.

00:08:40.070 --> 00:08:43.640 align:middle line:84%
You might have seen
that we're sending

00:08:43.640 --> 00:08:46.640 align:middle line:84%
in the class, actual
class meter.TimeSignature.

00:08:46.640 --> 00:08:50.380 align:middle line:84%
We could also put in the
string time signature.

00:08:50.380 --> 00:08:53.680 align:middle line:90%
Doesn't matter either way there.

00:08:53.680 --> 00:08:57.260 align:middle line:84%
But this actually doesn't
get us the first meter.

00:08:57.260 --> 00:08:59.630 align:middle line:90%
This gets us all the meters.

00:08:59.630 --> 00:09:03.640 align:middle line:84%
And so if there
are no meters that

00:09:03.640 --> 00:09:05.180 align:middle line:84%
says if there's
not a single one,

00:09:05.180 --> 00:09:12.290 align:middle line:84%
return that, we'll call first
meter the first of all meters.

00:09:12.290 --> 00:09:15.460 align:middle line:90%
So of course, it's number zero.

00:09:15.460 --> 00:09:17.540 align:middle line:90%
Now that should be there.

00:09:17.540 --> 00:09:20.060 align:middle line:90%
Now extract_meter bach.

00:09:20.060 --> 00:09:20.620 align:middle line:90%
Fantastic.

00:09:20.620 --> 00:09:23.770 align:middle line:90%
Returns 4, comma, 4.

00:09:23.770 --> 00:09:29.260 align:middle line:84%
So why would we want to extract
the meter as two numbers as part

00:09:29.260 --> 00:09:31.000 align:middle line:90%
of feature extraction?

00:09:31.000 --> 00:09:35.270 align:middle line:84%
We might do it as part
of a series of features

00:09:35.270 --> 00:09:37.820 align:middle line:84%
in order to make a
prediction about a piece.

00:09:37.820 --> 00:09:41.230 align:middle line:84%
Let's say we wanted to predict
if a piece of music is a waltz

00:09:41.230 --> 00:09:42.430 align:middle line:90%
or not.

00:09:42.430 --> 00:09:46.359 align:middle line:84%
So we might first
think, is this a waltz?

00:09:46.359 --> 00:09:48.854 align:middle line:90%
[MUSIC PLAYING]

00:09:48.854 --> 00:09:53.350 align:middle line:90%


00:09:53.350 --> 00:09:55.833 align:middle line:90%
Or is this a waltz?

00:09:55.833 --> 00:10:06.190 align:middle line:84%
[JOHN-PHILIP SOUSA, "STARS AND
STRIPES FOREVER"]

00:10:06.190 --> 00:10:08.180 align:middle line:90%
Is this a waltz?

00:10:08.180 --> 00:10:10.620 align:middle line:90%
[MUSIC PLAYING]

00:10:10.620 --> 00:10:21.850 align:middle line:90%


00:10:21.850 --> 00:10:23.942 align:middle line:90%
So what makes something a waltz?

00:10:23.942 --> 00:10:26.150 align:middle line:84%
Well, it probably has
something to do with the meter.

00:10:26.150 --> 00:10:29.170 align:middle line:84%
We fortunately already
have a meter extraction

00:10:29.170 --> 00:10:31.310 align:middle line:84%
from our time signature
for the piece,

00:10:31.310 --> 00:10:35.680 align:middle line:84%
and now we can use this
to try to figure out

00:10:35.680 --> 00:10:38.150 align:middle line:90%
if something is a waltz or not.

00:10:38.150 --> 00:10:41.650 align:middle line:84%
So we would assume that
the prevailing time

00:10:41.650 --> 00:10:44.050 align:middle line:84%
signature in a piece
and the opening time

00:10:44.050 --> 00:10:47.710 align:middle line:84%
signature in a piece, if
it's a waltz, would be 3, 4.

00:10:47.710 --> 00:10:52.270 align:middle line:84%
And therefore, our extraction
should be 3, comma, 4.

00:10:52.270 --> 00:10:55.730 align:middle line:84%
That is the worst
assumption ever.

00:10:55.730 --> 00:10:57.980 align:middle line:84%
The most famous
waltz of all time,

00:10:57.980 --> 00:11:02.230 align:middle line:84%
Johann Strauss' "Blue Danube"
waltz, which you just heard,

00:11:02.230 --> 00:11:03.560 align:middle line:90%
doesn't start in 3, 4.

00:11:03.560 --> 00:11:07.163 align:middle line:84%
It starts with a slow
introduction in 6, 8 time.

00:11:07.163 --> 00:11:10.600 align:middle line:90%


00:11:10.600 --> 00:11:13.730 align:middle line:84%
I happen to have a random
waltz on my computer.

00:11:13.730 --> 00:11:17.770 align:middle line:84%
It's Johann Strauss' waltz
called on the "Blue Danube."

00:11:17.770 --> 00:11:20.590 align:middle line:84%
It's not in the music21
corpus, but it's instead

00:11:20.590 --> 00:11:23.000 align:middle line:90%
on my hard drive on my desktop.

00:11:23.000 --> 00:11:28.270 align:middle line:84%
So I'll need to import the
converter module from music21.

00:11:28.270 --> 00:11:32.060 align:middle line:84%
I mean, it's just a wrapper
around loading things and stuff.

00:11:32.060 --> 00:11:35.600 align:middle line:84%
And now instead of
using corpus.parse,

00:11:35.600 --> 00:11:37.430 align:middle line:90%
I'll use converter.parse.

00:11:37.430 --> 00:11:41.270 align:middle line:90%
I'll give the full filename to--

00:11:41.270 --> 00:11:46.010 align:middle line:90%
file path to my waltz.

00:11:46.010 --> 00:11:48.343 align:middle line:90%
It's a music XML file.

00:11:48.343 --> 00:11:52.070 align:middle line:90%


00:11:52.070 --> 00:11:52.890 align:middle line:90%
Oh, great.

00:11:52.890 --> 00:11:57.210 align:middle line:84%
So the guy who's making this
recording just goes online,

00:11:57.210 --> 00:12:00.770 align:middle line:84%
grabs a random music XML
copy of the "Blue Danube"

00:12:00.770 --> 00:12:05.450 align:middle line:84%
from the internet, and this
version skips the introduction

00:12:05.450 --> 00:12:06.450 align:middle line:90%
completely.

00:12:06.450 --> 00:12:10.740 align:middle line:84%
So it has 3, 4 when it
should have gotten 6, 8.

00:12:10.740 --> 00:12:12.870 align:middle line:84%
So it's going to get
the right answer,

00:12:12.870 --> 00:12:15.020 align:middle line:90%
but for all the wrong reasons.

00:12:15.020 --> 00:12:17.840 align:middle line:84%
Have you ever heard
the expression GIGO?

00:12:17.840 --> 00:12:22.070 align:middle line:90%
Garbage in equals garbage out.

00:12:22.070 --> 00:12:25.730 align:middle line:84%
Let's not do that in
our own work, what we're

00:12:25.730 --> 00:12:28.440 align:middle line:90%
learning from in this tutorial.

00:12:28.440 --> 00:12:31.670 align:middle line:84%
Let's instead make the world of
artificial intelligence a better

00:12:31.670 --> 00:12:36.420 align:middle line:84%
place and always check whether
our training data is correct,

00:12:36.420 --> 00:12:39.090 align:middle line:84%
whether this is actually a
score of the "Blue Danube,"

00:12:39.090 --> 00:12:41.430 align:middle line:84%
rather than just the
main theme of it.

00:12:41.430 --> 00:12:47.000 align:middle line:84%
Let's check things like
this before we use it.

00:12:47.000 --> 00:12:48.260 align:middle line:90%
Great.

00:12:48.260 --> 00:12:51.210 align:middle line:90%
So it's in 3, 4.

00:12:51.210 --> 00:12:54.840 align:middle line:84%
So our extract_meter function
is going to return 3, 4.

00:12:54.840 --> 00:12:55.600 align:middle line:90%
Let's try that.

00:12:55.600 --> 00:13:01.070 align:middle line:90%


00:13:01.070 --> 00:13:01.880 align:middle line:90%
Sorry.

00:13:01.880 --> 00:13:03.060 align:middle line:90%
Don't get the answer.

00:13:03.060 --> 00:13:04.560 align:middle line:90%
Give the question.

00:13:04.560 --> 00:13:05.550 align:middle line:90%
There we go.

00:13:05.550 --> 00:13:07.130 align:middle line:84%
So now we have our
first feature that

00:13:07.130 --> 00:13:09.000 align:middle line:90%
might help identify a waltz.

00:13:09.000 --> 00:13:11.480 align:middle line:90%
Its time signature.

00:13:11.480 --> 00:13:14.255 align:middle line:84%
Now let's do something a
little bit more advanced.

00:13:14.255 --> 00:13:16.250 align:middle line:84%
Let's look at this
piece and see,

00:13:16.250 --> 00:13:19.530 align:middle line:84%
hm, is there anything that
seems to happen pretty often?

00:13:19.530 --> 00:13:24.170 align:middle line:84%
Well, it looks like the last
beat, beat three of the piece

00:13:24.170 --> 00:13:29.610 align:middle line:84%
or offset two is more often
higher than offset one.

00:13:29.610 --> 00:13:31.640 align:middle line:84%
I don't know if
that's true, but that

00:13:31.640 --> 00:13:33.870 align:middle line:84%
looks like something
that's a possibility.

00:13:33.870 --> 00:13:39.080 align:middle line:84%
So we'll create a more
sophisticated feature extractor

00:13:39.080 --> 00:13:45.220 align:middle line:84%
which returns the proportion
of all the measures where

00:13:45.220 --> 00:13:48.350 align:middle line:90%
beat three is above beat one.

00:13:48.350 --> 00:13:50.500 align:middle line:84%
First, we'll make
the assumption that

00:13:50.500 --> 00:13:52.400 align:middle line:84%
beat one is always
at offset zero

00:13:52.400 --> 00:13:53.960 align:middle line:90%
and beat three is at offset two.

00:13:53.960 --> 00:13:56.510 align:middle line:84%
These aren't very
good assumptions,

00:13:56.510 --> 00:13:58.760 align:middle line:84%
but maybe together with
searching for meter,

00:13:58.760 --> 00:14:00.790 align:middle line:84%
they'll two will
make a good case for

00:14:00.790 --> 00:14:02.540 align:middle line:84%
whether something
is a waltz or not.

00:14:02.540 --> 00:14:04.750 align:middle line:90%
So here we go.

00:14:04.750 --> 00:14:09.700 align:middle line:84%
We're going to eventually
write something-- proportion

00:14:09.700 --> 00:14:19.300 align:middle line:84%
proportion_beat3_above_beat1,
which is going to take a score.

00:14:19.300 --> 00:14:21.020 align:middle line:90%
Stream.Stream.

00:14:21.020 --> 00:14:24.320 align:middle line:84%
It's going to return a float
because it's a proportion.

00:14:24.320 --> 00:14:28.000 align:middle line:84%
And I'll just say pass
now, because in order

00:14:28.000 --> 00:14:29.860 align:middle line:84%
to do write this,
of course, we're

00:14:29.860 --> 00:14:32.380 align:middle line:84%
going to need something that
figures out for any given

00:14:32.380 --> 00:14:42.270 align:middle line:84%
measure if beat three is above
beat one for a single measure,

00:14:42.270 --> 00:14:43.630 align:middle line:90%
for one measure.

00:14:43.630 --> 00:14:47.200 align:middle line:84%
So we'll take an m, which
will be a stream.Measure,

00:14:47.200 --> 00:14:50.040 align:middle line:84%
and this is going to
return true or false.

00:14:50.040 --> 00:14:50.910 align:middle line:90%
Oops.

00:14:50.910 --> 00:14:54.100 align:middle line:84%
It's going to return
true or false.

00:14:54.100 --> 00:14:56.280 align:middle line:84%
Someday we have an
incredible production crew

00:14:56.280 --> 00:14:58.180 align:middle line:84%
that's going to edit
out all these mistakes,

00:14:58.180 --> 00:14:59.320 align:middle line:90%
but I don't have that yet.

00:14:59.320 --> 00:15:02.550 align:middle line:84%
So we'll just say
that measures notes

00:15:02.550 --> 00:15:06.600 align:middle line:84%
get all the elements
by class note,

00:15:06.600 --> 00:15:09.310 align:middle line:84%
and that returns
this stream iterator.

00:15:09.310 --> 00:15:12.420 align:middle line:84%
For now, I'm going to
say recast that stream

00:15:12.420 --> 00:15:14.430 align:middle line:90%
iterator as another stream.

00:15:14.430 --> 00:15:17.040 align:middle line:84%
You can do this with
any of the get something

00:15:17.040 --> 00:15:19.930 align:middle line:90%
by something classes in music21.

00:15:19.930 --> 00:15:20.430 align:middle line:90%
Great.

00:15:20.430 --> 00:15:24.820 align:middle line:84%
So within, this is now a stream
of just nothing but notes.

00:15:24.820 --> 00:15:30.270 align:middle line:84%
And so I can say the first
notes are those notes that

00:15:30.270 --> 00:15:35.150 align:middle line:90%
appear on offset zero.

00:15:35.150 --> 00:15:41.180 align:middle line:84%
And if there's no note
there, return false.

00:15:41.180 --> 00:15:41.840 align:middle line:90%
Great.

00:15:41.840 --> 00:15:49.970 align:middle line:84%
Now we'll check beat_3_notes
are those notes that

00:15:49.970 --> 00:15:56.250 align:middle line:84%
are at offset two and
that began at offset two.

00:15:56.250 --> 00:15:57.930 align:middle line:90%
So that should work pretty well.

00:15:57.930 --> 00:16:05.090 align:middle line:84%
And if there's no note that
satisfies that condition,

00:16:05.090 --> 00:16:08.270 align:middle line:84%
we're going to
return false again.

00:16:08.270 --> 00:16:12.920 align:middle line:84%
But what if there is
more than one note

00:16:12.920 --> 00:16:20.240 align:middle line:84%
at the beginning of the
measure or at beat three?

00:16:20.240 --> 00:16:23.690 align:middle line:84%
So we have to make sure
that the first note is

00:16:23.690 --> 00:16:27.290 align:middle line:84%
the first of the
beat three notes

00:16:27.290 --> 00:16:33.800 align:middle line:84%
and the beat_3_note is the
first of the beat_3_notes.

00:16:33.800 --> 00:16:35.250 align:middle line:90%
The third-- the first.

00:16:35.250 --> 00:16:39.860 align:middle line:84%
Now we'll go ahead and say if
the first note's pitch is lower,

00:16:39.860 --> 00:16:42.830 align:middle line:84%
then we're going to measure the
pitch by pitch space or midi

00:16:42.830 --> 00:16:47.600 align:middle line:84%
number is less than
the beat three notes,

00:16:47.600 --> 00:16:50.550 align:middle line:90%
pitch space will return false.

00:16:50.550 --> 00:16:54.680 align:middle line:84%
Otherwise, we're
going to return true.

00:16:54.680 --> 00:16:56.090 align:middle line:90%
Great.

00:16:56.090 --> 00:16:58.170 align:middle line:90%
Well, let's be good.

00:16:58.170 --> 00:17:00.090 align:middle line:90%
We'll make this a second thing.

00:17:00.090 --> 00:17:04.079 align:middle line:90%
We'll cut and paste that there.

00:17:04.079 --> 00:17:06.349 align:middle line:90%
Meanwhile we're going to--

00:17:06.349 --> 00:17:09.000 align:middle line:84%
let's write a
little test on this.

00:17:09.000 --> 00:17:11.450 align:middle line:90%
So we have blue.

00:17:11.450 --> 00:17:14.099 align:middle line:90%
Let's get measure zero.

00:17:14.099 --> 00:17:17.390 align:middle line:90%
So m0.

00:17:17.390 --> 00:17:19.020 align:middle line:90%
Actually, let's measure one.

00:17:19.020 --> 00:17:22.280 align:middle line:90%
So blue.measure 1.

00:17:22.280 --> 00:17:29.660 align:middle line:84%
And we'll see,
is_beat_3_above_beat_1.

00:17:29.660 --> 00:17:30.160 align:middle line:90%
Oops.

00:17:30.160 --> 00:17:34.390 align:middle line:90%


00:17:34.390 --> 00:17:36.080 align:middle line:90%
[AUDIO SPED UP]

00:17:36.080 --> 00:17:43.720 align:middle line:90%


00:17:43.720 --> 00:17:45.260 align:middle line:90%
This is why we test things.

00:17:45.260 --> 00:17:46.180 align:middle line:90%
Great.

00:17:46.180 --> 00:17:51.400 align:middle line:84%
Is_beat_3_above_beat_1
in measure one?

00:17:51.400 --> 00:17:52.850 align:middle line:90%
Actually, it is.

00:17:52.850 --> 00:17:54.820 align:middle line:90%
Ah.

00:17:54.820 --> 00:17:56.180 align:middle line:90%
Oh, I know what it is.

00:17:56.180 --> 00:17:58.880 align:middle line:90%
We have a reverse of a sign.

00:17:58.880 --> 00:18:03.980 align:middle line:84%
If this pitch is greater than
or equal, then we return false.

00:18:03.980 --> 00:18:06.400 align:middle line:90%
Actually, if it's-- yeah.

00:18:06.400 --> 00:18:07.810 align:middle line:90%
The equal sign there.

00:18:07.810 --> 00:18:10.280 align:middle line:90%
And now that's working.

00:18:10.280 --> 00:18:12.560 align:middle line:90%
Measure two should be true.

00:18:12.560 --> 00:18:14.960 align:middle line:84%
Also measure three
should be false.

00:18:14.960 --> 00:18:17.350 align:middle line:90%
Let's make sure that works.

00:18:17.350 --> 00:18:18.490 align:middle line:90%
Yep.

00:18:18.490 --> 00:18:19.670 align:middle line:90%
And false.

00:18:19.670 --> 00:18:20.170 align:middle line:90%
Great.

00:18:20.170 --> 00:18:22.840 align:middle line:90%
So that seems to be working.

00:18:22.840 --> 00:18:25.550 align:middle line:90%
Here's the irony, actually.

00:18:25.550 --> 00:18:29.190 align:middle line:84%
Except for the fact that our
label would be completely wrong,

00:18:29.190 --> 00:18:32.220 align:middle line:84%
having every single thing that
should be false be true and true

00:18:32.220 --> 00:18:35.710 align:middle line:84%
be false probably wouldn't
change our answers very much.

00:18:35.710 --> 00:18:36.760 align:middle line:90%
But who knows.

00:18:36.760 --> 00:18:39.240 align:middle line:84%
We call this,
is_beat_3_above_beat_1

00:18:39.240 --> 00:18:41.070 align:middle line:90%
in one measure?

00:18:41.070 --> 00:18:42.470 align:middle line:90%
It better do what it says.

00:18:42.470 --> 00:18:42.970 align:middle line:90%
OK, great.

00:18:42.970 --> 00:18:45.150 align:middle line:84%
Now we're going to get
the proportion that

00:18:45.150 --> 00:18:48.150 align:middle line:84%
is the proportion of
measures in this piece where

00:18:48.150 --> 00:18:49.510 align:middle line:90%
beat three is above beat one.

00:18:49.510 --> 00:18:53.760 align:middle line:84%
So we'll keep track of the
total number of measures

00:18:53.760 --> 00:18:55.470 align:middle line:90%
equals zero, the total--

00:18:55.470 --> 00:18:58.480 align:middle line:84%
we'll call them
waltz-like measures.

00:18:58.480 --> 00:19:00.910 align:middle line:84%
Those where beat three
is above beat one.

00:19:00.910 --> 00:19:02.190 align:middle line:90%
We'll call it zero.

00:19:02.190 --> 00:19:07.560 align:middle line:84%
For every measure in
the score, recurse

00:19:07.560 --> 00:19:10.820 align:middle line:90%
getElementsByClass measure.

00:19:10.820 --> 00:19:13.650 align:middle line:90%


00:19:13.650 --> 00:19:16.620 align:middle line:84%
There's a reason why we'll
use getElementsByClass measure

00:19:16.620 --> 00:19:19.950 align:middle line:84%
instead of measure
zero, one, two, three.

00:19:19.950 --> 00:19:23.430 align:middle line:84%
Mostly to do with the fact that
sometimes there's two measure

00:19:23.430 --> 00:19:26.660 align:middle line:84%
threes or they're missing
measure 11 or something like

00:19:26.660 --> 00:19:30.680 align:middle line:84%
that, where there's measure 5A
and 5B if there's a first ending

00:19:30.680 --> 00:19:31.710 align:middle line:90%
or something like that.

00:19:31.710 --> 00:19:33.290 align:middle line:90%
Anyhow.

00:19:33.290 --> 00:19:35.960 align:middle line:84%
For every measure, we increment
the total number of measures

00:19:35.960 --> 00:19:36.660 align:middle line:90%
by one.

00:19:36.660 --> 00:19:41.750 align:middle line:90%
And now we look at one measure.

00:19:41.750 --> 00:19:48.230 align:middle line:84%
And we say if that's true, then
the total waltz-like measures

00:19:48.230 --> 00:19:50.450 align:middle line:90%
plus equals one.

00:19:50.450 --> 00:19:56.540 align:middle line:84%
And we're going to return
the total waltz-like measures

00:19:56.540 --> 00:19:59.930 align:middle line:90%
divided by the total measures.

00:19:59.930 --> 00:20:05.030 align:middle line:84%
We're coding pretty fast, so
we'll just put as a to-do later.

00:20:05.030 --> 00:20:09.200 align:middle line:84%
What if there are
no total measures?

00:20:09.200 --> 00:20:13.000 align:middle line:84%
I always make sure that we don't
do a division by zero measure

00:20:13.000 --> 00:20:13.500 align:middle line:90%
error.

00:20:13.500 --> 00:20:16.170 align:middle line:90%
But that can be a later thing.

00:20:16.170 --> 00:20:24.920 align:middle line:84%
So let's check this proportion
of beat three above beat one

00:20:24.920 --> 00:20:25.820 align:middle line:90%
on the "Blue Danube."

00:20:25.820 --> 00:20:30.230 align:middle line:90%


00:20:30.230 --> 00:20:32.870 align:middle line:90%
26%.

00:20:32.870 --> 00:20:34.327 align:middle line:90%
Is that really true?

00:20:34.327 --> 00:20:35.410 align:middle line:90%
It seems a little bit low.

00:20:35.410 --> 00:20:38.270 align:middle line:90%


00:20:38.270 --> 00:20:41.270 align:middle line:90%
One, two down.

00:20:41.270 --> 00:20:43.080 align:middle line:90%
Well, we'll check that later.

00:20:43.080 --> 00:20:44.970 align:middle line:90%
Turns out it's not that bad.

00:20:44.970 --> 00:20:47.760 align:middle line:90%
And bwv-- sorry.

00:20:47.760 --> 00:20:48.830 align:middle line:90%
Bach.

00:20:48.830 --> 00:20:50.300 align:middle line:90%
Call it this time.

00:20:50.300 --> 00:20:52.040 align:middle line:84%
It's actually even
a little bit more.

00:20:52.040 --> 00:20:53.130 align:middle line:90%
Interesting.

00:20:53.130 --> 00:20:53.990 align:middle line:90%
OK.

00:20:53.990 --> 00:20:56.790 align:middle line:84%
So in any case, this is a
feature we've just defined.

00:20:56.790 --> 00:20:59.360 align:middle line:84%
This particular feature
figures out how often

00:20:59.360 --> 00:21:01.790 align:middle line:90%
beat three is above beat one.

00:21:01.790 --> 00:21:02.990 align:middle line:90%
Great.

00:21:02.990 --> 00:21:08.730 align:middle line:84%
What we can do now is these
are individual features.

00:21:08.730 --> 00:21:12.920 align:middle line:84%
Let's create something that does
change a whole bunch of features

00:21:12.920 --> 00:21:13.560 align:middle line:90%
together.

00:21:13.560 --> 00:21:14.487 align:middle line:90%
Well, not this one.

00:21:14.487 --> 00:21:15.570 align:middle line:90%
A whole bunch of features.

00:21:15.570 --> 00:21:18.870 align:middle line:90%
We'll get four features.

00:21:18.870 --> 00:21:28.030 align:middle line:84%
So we'll say our feature
extractor will take in a score,

00:21:28.030 --> 00:21:33.520 align:middle line:84%
and it's going to return a tuple
of a string, an int, an int,

00:21:33.520 --> 00:21:37.900 align:middle line:90%
a float, and a Boolean.

00:21:37.900 --> 00:21:38.950 align:middle line:90%
OK.

00:21:38.950 --> 00:21:39.763 align:middle line:90%
What the heck?

00:21:39.763 --> 00:21:41.180 align:middle line:84%
What are these
things going to be?

00:21:41.180 --> 00:21:45.040 align:middle line:84%
So first, what we're going to do
is we're going to take in score

00:21:45.040 --> 00:21:48.460 align:middle line:90%
and we're going to--

00:21:48.460 --> 00:21:52.600 align:middle line:84%
well, we're going to say
the filename of the score

00:21:52.600 --> 00:21:54.550 align:middle line:84%
is going to be
that first string.

00:21:54.550 --> 00:21:59.080 align:middle line:84%
And you can get the filename
from any music21 score

00:21:59.080 --> 00:22:01.820 align:middle line:84%
by getting this filePath,
which is a path lib,

00:22:01.820 --> 00:22:03.730 align:middle line:84%
and getting the name,
which gets rid of all

00:22:03.730 --> 00:22:04.880 align:middle line:90%
the directories and stuff.

00:22:04.880 --> 00:22:05.380 align:middle line:90%
Great.

00:22:05.380 --> 00:22:09.310 align:middle line:84%
So we'll get the filename of
something and we'll get the--

00:22:09.310 --> 00:22:12.797 align:middle line:84%
next thing we're going to
get these two ints, which

00:22:12.797 --> 00:22:13.880 align:middle line:90%
are going to be the meter.

00:22:13.880 --> 00:22:18.040 align:middle line:84%
So we'll say the
meter feature is

00:22:18.040 --> 00:22:20.730 align:middle line:90%
where I get that from extract.

00:22:20.730 --> 00:22:24.720 align:middle line:90%
Extract_meter on that score.

00:22:24.720 --> 00:22:27.570 align:middle line:84%
Next we're going to get
this float, which is

00:22:27.570 --> 00:22:30.780 align:middle line:90%
going to be the beat3_feature.

00:22:30.780 --> 00:22:37.590 align:middle line:84%
So we'll get the beat3_feature
is the proportion--

00:22:37.590 --> 00:22:39.960 align:middle line:90%
why do I keep doing this?

00:22:39.960 --> 00:22:44.140 align:middle line:84%
Beat_3_above_beat_1
for that score.

00:22:44.140 --> 00:22:44.640 align:middle line:90%
Great.

00:22:44.640 --> 00:22:45.430 align:middle line:90%
Super.

00:22:45.430 --> 00:22:45.960 align:middle line:90%
Oops.

00:22:45.960 --> 00:22:48.690 align:middle line:90%
I didn't hit Shift-Enter.

00:22:48.690 --> 00:22:53.350 align:middle line:90%
Then we want to get the Boolean.

00:22:53.350 --> 00:22:56.290 align:middle line:84%
What we're going to do is if
we're training a data set,

00:22:56.290 --> 00:23:00.150 align:middle line:84%
we're going to know whether
or not something is a waltz.

00:23:00.150 --> 00:23:02.520 align:middle line:84%
So we'll say that
Boolean is going

00:23:02.520 --> 00:23:05.380 align:middle line:84%
to be true or false on
whether something is a waltz.

00:23:05.380 --> 00:23:12.130 align:middle line:84%
And so we could say
is_waltz equals if true

00:23:12.130 --> 00:23:18.060 align:middle line:84%
if Waltz is in the filename,
or if lowercase waltz

00:23:18.060 --> 00:23:21.210 align:middle line:90%
is in the filename.

00:23:21.210 --> 00:23:23.250 align:middle line:90%
Filename.

00:23:23.250 --> 00:23:31.020 align:middle line:84%
So then we know the filename,
numerator and denominator, float

00:23:31.020 --> 00:23:33.945 align:middle line:84%
of the proportion beat three,
and whether or not filename

00:23:33.945 --> 00:23:34.960 align:middle line:90%
is waltz.

00:23:34.960 --> 00:23:38.605 align:middle line:84%
This last particular thing,
we'll sometimes call this,

00:23:38.605 --> 00:23:40.230 align:middle line:84%
instead of is_waltz,
we're saying we'll

00:23:40.230 --> 00:23:42.940 align:middle line:90%
use generic term ground_truth.

00:23:42.940 --> 00:23:45.970 align:middle line:84%
We'll also see it
called the class.

00:23:45.970 --> 00:23:49.720 align:middle line:84%
So whether it a belongs
to the waltz class or not.

00:23:49.720 --> 00:23:52.510 align:middle line:84%
So we can call it waltz or
non-waltz or true/false.

00:23:52.510 --> 00:23:53.710 align:middle line:90%
Something like that.

00:23:53.710 --> 00:23:56.650 align:middle line:84%
Now we want to return all
these things as a tuple.

00:23:56.650 --> 00:24:01.660 align:middle line:84%
So tuples are created with a
comma or with a parentheses.

00:24:01.660 --> 00:24:03.220 align:middle line:90%
So we'll use the parentheses.

00:24:03.220 --> 00:24:07.810 align:middle line:84%
The filename, the
meter_feature's first argument,

00:24:07.810 --> 00:24:11.710 align:middle line:84%
which is the numerator,
meter_feature's second argument,

00:24:11.710 --> 00:24:15.570 align:middle line:84%
which is the denominator,
the beat3_feature,

00:24:15.570 --> 00:24:19.430 align:middle line:90%
and the ground_truth.

00:24:19.430 --> 00:24:21.750 align:middle line:90%
So let's see.

00:24:21.750 --> 00:24:25.370 align:middle line:90%
We'll run this feature--

00:24:25.370 --> 00:24:27.440 align:middle line:90%
let's call extractor.

00:24:27.440 --> 00:24:31.340 align:middle line:90%
Let's call snippet properly.

00:24:31.340 --> 00:24:32.965 align:middle line:84%
Feature extractor on
the "Blue Danube."

00:24:32.965 --> 00:24:36.410 align:middle line:90%


00:24:36.410 --> 00:24:38.100 align:middle line:90%
I still didn't spell it right.

00:24:38.100 --> 00:24:41.510 align:middle line:90%
Why do I copy and paste?

00:24:41.510 --> 00:24:43.430 align:middle line:90%
There we go.

00:24:43.430 --> 00:24:48.890 align:middle line:84%
Oh, we can see "Blue
Danube" waltz is in 3, 4.

00:24:48.890 --> 00:24:52.080 align:middle line:90%
26% has this beat proportion.

00:24:52.080 --> 00:24:53.070 align:middle line:90%
And true.

00:24:53.070 --> 00:24:54.860 align:middle line:90%
It is a waltz.

00:24:54.860 --> 00:25:04.910 align:middle line:84%
Let's run our
feature_extractor on bach.

00:25:04.910 --> 00:25:08.580 align:middle line:90%
We'll see filename 4, 4, 35.

00:25:08.580 --> 00:25:09.080 align:middle line:90%
False.

00:25:09.080 --> 00:25:10.820 align:middle line:90%
Great.

00:25:10.820 --> 00:25:14.840 align:middle line:84%
So eventually we would want
to have a computer system that

00:25:14.840 --> 00:25:20.890 align:middle line:84%
can distinguish between a
waltz and not by learning

00:25:20.890 --> 00:25:22.990 align:middle line:90%
all this information.

00:25:22.990 --> 00:25:26.530 align:middle line:84%
Unfortunately, I don't
have enough waltzes

00:25:26.530 --> 00:25:28.460 align:middle line:90%
in my data set to do this.

00:25:28.460 --> 00:25:31.340 align:middle line:84%
So we're going to move
to the next best thing.

00:25:31.340 --> 00:25:33.920 align:middle line:90%
We're going to get a jig.

00:25:33.920 --> 00:25:38.960 align:middle line:84%
So let's go ahead and
grab a particular jig.

00:25:38.960 --> 00:25:45.010 align:middle line:84%
We have all of these jigs in
this data set, which is really

00:25:45.010 --> 00:25:46.550 align:middle line:90%
useful for people to know.

00:25:46.550 --> 00:25:51.374 align:middle line:84%
It's called Ryan's
Mammoth Collection.

00:25:51.374 --> 00:25:53.920 align:middle line:90%


00:25:53.920 --> 00:25:55.160 align:middle line:90%
It's a 19th century thing.

00:25:55.160 --> 00:25:55.952 align:middle line:90%
You can look it up.

00:25:55.952 --> 00:25:57.200 align:middle line:90%
It's very famous.

00:25:57.200 --> 00:25:57.700 align:middle line:90%
Hi.

00:25:57.700 --> 00:26:01.390 align:middle line:84%
I wanted to jump in for a
second and say something

00:26:01.390 --> 00:26:02.510 align:middle line:90%
about this collection.

00:26:02.510 --> 00:26:06.410 align:middle line:84%
I'm planning on not
using again soon.

00:26:06.410 --> 00:26:09.520 align:middle line:84%
Since I made this
video, I've realized

00:26:09.520 --> 00:26:12.020 align:middle line:84%
that within Ryan's
Mammoth Collection,

00:26:12.020 --> 00:26:14.740 align:middle line:84%
there is a lot of what
are called minstrel songs.

00:26:14.740 --> 00:26:17.640 align:middle line:84%
That is, songs
that were performed

00:26:17.640 --> 00:26:24.010 align:middle line:84%
in the style of Negro melodies,
but by white performers,

00:26:24.010 --> 00:26:27.390 align:middle line:84%
often in blackface
and with texts

00:26:27.390 --> 00:26:30.280 align:middle line:84%
which are not included in this
collection, thank goodness,

00:26:30.280 --> 00:26:33.690 align:middle line:84%
but with texts that
denigrated Black

00:26:33.690 --> 00:26:36.070 align:middle line:90%
Americans and Black experience.

00:26:36.070 --> 00:26:39.630 align:middle line:84%
So I'm going to try to change
this example as soon as I

00:26:39.630 --> 00:26:45.280 align:middle line:84%
can, and my apologies for
what I didn't know then

00:26:45.280 --> 00:26:50.490 align:middle line:84%
and what I know now and what I
plan to continue to do to make

00:26:50.490 --> 00:26:55.110 align:middle line:84%
computational musicology
a more welcoming place.

00:26:55.110 --> 00:26:57.650 align:middle line:84%
So if we're going to be looking
at the BloomingMeadowsJig.

00:26:57.650 --> 00:27:00.510 align:middle line:90%


00:27:00.510 --> 00:27:09.060 align:middle line:84%
We'll load that blooming equals
corpus.parse BloomingMeadowJig.

00:27:09.060 --> 00:27:11.040 align:middle line:90%
Don't need the abc.

00:27:11.040 --> 00:27:12.960 align:middle line:84%
You can leave it in
however you want.

00:27:12.960 --> 00:27:15.870 align:middle line:90%
Let's look at this.

00:27:15.870 --> 00:27:19.240 align:middle line:84%
In case you haven't
seen a jig in a while,

00:27:19.240 --> 00:27:23.790 align:middle line:84%
it's kind of helpful for
understanding the jig.

00:27:23.790 --> 00:27:25.570 align:middle line:90%
Generally speaking, 6, 8.

00:27:25.570 --> 00:27:28.360 align:middle line:84%
We've got these
violin bow marks.

00:27:28.360 --> 00:27:30.490 align:middle line:84%
We could use that as
a feature extractor.

00:27:30.490 --> 00:27:33.580 align:middle line:84%
If it has violin markings,
it's more likely to be a jig.

00:27:33.580 --> 00:27:35.380 align:middle line:90%
If it doesn't, it's less likely.

00:27:35.380 --> 00:27:38.770 align:middle line:84%
Lots of Bach pieces
have violin bow marks.

00:27:38.770 --> 00:27:42.840 align:middle line:84%
The Bach Violin Partitas,
they're not all jigs.

00:27:42.840 --> 00:27:46.120 align:middle line:84%
So it's not going to be perfect,
but all these things kind help.

00:27:46.120 --> 00:27:48.750 align:middle line:84%
But maybe that
meter extractor 6,

00:27:48.750 --> 00:27:51.330 align:middle line:84%
8 is going to be a
little bit helpful.

00:27:51.330 --> 00:27:54.530 align:middle line:84%
So I happen to know that
this little piece is a jig.

00:27:54.530 --> 00:27:56.280 align:middle line:84%
It's kind of nice short
piece, but there's

00:27:56.280 --> 00:27:57.280 align:middle line:90%
a whole bunch of things.

00:27:57.280 --> 00:27:59.590 align:middle line:84%
So we're going to get from
Ryan's Mammoth Collection.

00:27:59.590 --> 00:28:02.640 align:middle line:84%
And we'll use a different
thing that we've used before.

00:28:02.640 --> 00:28:04.140 align:middle line:84%
Instead of corpus-parse,
we're going

00:28:04.140 --> 00:28:07.320 align:middle line:90%
to search everything for Ryan.

00:28:07.320 --> 00:28:11.270 align:middle line:84%
I think everything in there is
as part of this Ryan's Mammoth

00:28:11.270 --> 00:28:11.940 align:middle line:90%
Collection.

00:28:11.940 --> 00:28:14.210 align:middle line:84%
And we'll see that
within Ryan, there's

00:28:14.210 --> 00:28:16.920 align:middle line:84%
going to be quite
a number of pieces.

00:28:16.920 --> 00:28:18.710 align:middle line:90%
1,063.

00:28:18.710 --> 00:28:22.880 align:middle line:84%
You'll see the first time
you use corpus search,

00:28:22.880 --> 00:28:27.510 align:middle line:84%
it takes some time,
but you can use--

00:28:27.510 --> 00:28:31.520 align:middle line:84%
after you do it once, it's
often quite a bit faster.

00:28:31.520 --> 00:28:33.020 align:middle line:90%
Super fast.

00:28:33.020 --> 00:28:33.830 align:middle line:90%
Yeah.

00:28:33.830 --> 00:28:34.530 align:middle line:90%
There we go.

00:28:34.530 --> 00:28:35.304 align:middle line:90%
OK.

00:28:35.304 --> 00:28:40.770 align:middle line:84%
So we're going to have
used that beat3_feature.

00:28:40.770 --> 00:28:41.990 align:middle line:90%
Why not?

00:28:41.990 --> 00:28:43.407 align:middle line:84%
I mean, we already
have a feature.

00:28:43.407 --> 00:28:45.157 align:middle line:84%
And we're going to use
the meters feature.

00:28:45.157 --> 00:28:46.470 align:middle line:90%
But let's use one more thing.

00:28:46.470 --> 00:28:48.650 align:middle line:84%
I've heard that
jigs tend to come

00:28:48.650 --> 00:28:54.320 align:middle line:84%
in a few keys, a
few key signatures.

00:28:54.320 --> 00:28:56.250 align:middle line:90%
Maybe one flat, one sharp.

00:28:56.250 --> 00:28:58.260 align:middle line:84%
They don't tend to
come in five flats.

00:28:58.260 --> 00:29:00.810 align:middle line:84%
That's kind of a hard
thing for violins.

00:29:00.810 --> 00:29:06.840 align:middle line:84%
So let's go ahead and
create a sharp extractor.

00:29:06.840 --> 00:29:08.390 align:middle line:90%
So we'll call it--

00:29:08.390 --> 00:29:13.120 align:middle line:84%
let's call it get_sharps,
because we'll just

00:29:13.120 --> 00:29:16.090 align:middle line:84%
remind ourselves that a
feature extractor is nothing

00:29:16.090 --> 00:29:21.280 align:middle line:84%
more than something that takes
in a score or some other piece

00:29:21.280 --> 00:29:23.240 align:middle line:90%
of data and returns numbers--

00:29:23.240 --> 00:29:24.820 align:middle line:90%
in this case, an integer.

00:29:24.820 --> 00:29:27.560 align:middle line:90%
We'll just put a try thing.

00:29:27.560 --> 00:29:29.210 align:middle line:90%
We'll return the score.

00:29:29.210 --> 00:29:37.330 align:middle line:84%
We're going to go through it,
recurse, get all the elements--

00:29:37.330 --> 00:29:41.680 align:middle line:84%
use plural this time--
by class, key signature.

00:29:41.680 --> 00:29:45.440 align:middle line:84%
Get the first one and
return the number of sharps.

00:29:45.440 --> 00:29:49.430 align:middle line:84%
Remember, if it's two flats,
sharps will be negative 2.

00:29:49.430 --> 00:29:55.150 align:middle line:84%
And in case we can't find it,
it might be an index error

00:29:55.150 --> 00:29:59.140 align:middle line:90%
because there's zero.

00:29:59.140 --> 00:30:02.830 align:middle line:84%
You can always, in your own
code that you don't turn in

00:30:02.830 --> 00:30:04.310 align:middle line:84%
and you don't put
something there,

00:30:04.310 --> 00:30:07.690 align:middle line:84%
you can just say
accept all errors.

00:30:07.690 --> 00:30:09.220 align:middle line:90%
Return 0.

00:30:09.220 --> 00:30:12.430 align:middle line:90%
Let's double check this.

00:30:12.430 --> 00:30:15.250 align:middle line:90%
Do we call it-- yeah, blooming.

00:30:15.250 --> 00:30:20.320 align:middle line:90%
Sharps blooming.

00:30:20.320 --> 00:30:21.490 align:middle line:90%
That's one.

00:30:21.490 --> 00:30:22.720 align:middle line:90%
Let's remind ourselves.

00:30:22.720 --> 00:30:24.480 align:middle line:84%
"Blue Danube"
should also be one.

00:30:24.480 --> 00:30:28.630 align:middle line:90%


00:30:28.630 --> 00:30:29.320 align:middle line:90%
Great.

00:30:29.320 --> 00:30:32.850 align:middle line:84%
And that Bach piece
should be three.

00:30:32.850 --> 00:30:38.080 align:middle line:90%


00:30:38.080 --> 00:30:38.860 align:middle line:90%
Super.

00:30:38.860 --> 00:30:39.800 align:middle line:90%
OK.

00:30:39.800 --> 00:30:41.480 align:middle line:84%
So that seems to
work a little bit.

00:30:41.480 --> 00:30:43.620 align:middle line:84%
Now let's write our
feature extractor.

00:30:43.620 --> 00:30:47.950 align:middle line:90%


00:30:47.950 --> 00:30:50.210 align:middle line:90%
Or our multi feature extractor.

00:30:50.210 --> 00:30:53.463 align:middle line:84%
Never really sure
if feature extractor

00:30:53.463 --> 00:30:54.880 align:middle line:84%
just refers to
something that gets

00:30:54.880 --> 00:30:57.318 align:middle line:84%
one feature, like
get_sharps or something that

00:30:57.318 --> 00:30:58.610 align:middle line:90%
gets a whole bunch of features.

00:30:58.610 --> 00:31:00.530 align:middle line:84%
People aren't really
clear on that.

00:31:00.530 --> 00:31:02.480 align:middle line:84%
So we're going to return,
again, the string.

00:31:02.480 --> 00:31:04.360 align:middle line:84%
It's going to be
the filename, two

00:31:04.360 --> 00:31:07.090 align:middle line:84%
integers for the metered
numerator and denominator.

00:31:07.090 --> 00:31:08.010 align:middle line:90%
Pretty important.

00:31:08.010 --> 00:31:11.980 align:middle line:84%
Float for that kind of
silly beat three thing.

00:31:11.980 --> 00:31:18.420 align:middle line:84%
But we'll add one more
integer on whether or not--

00:31:18.420 --> 00:31:20.380 align:middle line:90%
yeah, on the number of sharps.

00:31:20.380 --> 00:31:22.570 align:middle line:84%
And instead of returning
a Boolean at the end,

00:31:22.570 --> 00:31:25.110 align:middle line:84%
we're going to switch
this last little thing

00:31:25.110 --> 00:31:27.930 align:middle line:84%
to returning an integer
for whether or not

00:31:27.930 --> 00:31:29.320 align:middle line:90%
something is a jig.

00:31:29.320 --> 00:31:30.370 align:middle line:90%
The ground truth.

00:31:30.370 --> 00:31:37.980 align:middle line:84%
And it's because most of the
machine learning toolkits really

00:31:37.980 --> 00:31:42.600 align:middle line:84%
like working with numbers,
so might as well make

00:31:42.600 --> 00:31:44.400 align:middle line:90%
our ground truth a number.

00:31:44.400 --> 00:31:47.430 align:middle line:84%
Make a filename,
the filePath.name.

00:31:47.430 --> 00:31:48.430 align:middle line:90%
Again, as before.

00:31:48.430 --> 00:31:49.510 align:middle line:84%
You don't really
need that there,

00:31:49.510 --> 00:31:51.180 align:middle line:84%
but it's going to be really
helpful for figuring out

00:31:51.180 --> 00:31:53.580 align:middle line:84%
why something's working or
what particular pieces are

00:31:53.580 --> 00:31:54.630 align:middle line:90%
wrong or right.

00:31:54.630 --> 00:31:58.080 align:middle line:84%
I'm hoping I still had
proportion somewhere

00:31:58.080 --> 00:31:59.987 align:middle line:90%
in my clipboard, but OK.

00:31:59.987 --> 00:32:01.320 align:middle line:90%
So proportion_beat3_above_beat1.

00:32:01.320 --> 00:32:02.778 align:middle line:84%
I always hit
Shift-Enter too early.

00:32:02.778 --> 00:32:05.780 align:middle line:84%
Sharps feature is going to
be get_sharps from score.

00:32:05.780 --> 00:32:07.260 align:middle line:90%
And our ground_truth.

00:32:07.260 --> 00:32:09.343 align:middle line:84%
In this case, we said it's
going to be an integer.

00:32:09.343 --> 00:32:14.420 align:middle line:84%
So we'll say int jig in
filename or jig in filename.

00:32:14.420 --> 00:32:15.780 align:middle line:90%
Two things to note.

00:32:15.780 --> 00:32:19.370 align:middle line:90%
One, Python int on true--

00:32:19.370 --> 00:32:22.770 align:middle line:84%
int on true returns one,
int on false returns zero.

00:32:22.770 --> 00:32:27.170 align:middle line:84%
In fact, in earlier versions
of Python, true and false

00:32:27.170 --> 00:32:29.760 align:middle line:84%
were just kind of
aliases for one and zero.

00:32:29.760 --> 00:32:31.590 align:middle line:84%
Thankfully, that's
a little bit better.

00:32:31.590 --> 00:32:36.090 align:middle line:84%
The other thing is, again,
we've learned about garbage in,

00:32:36.090 --> 00:32:36.810 align:middle line:90%
garbage out.

00:32:36.810 --> 00:32:42.170 align:middle line:84%
I don't actually know if every
single thing in this collection

00:32:42.170 --> 00:32:46.140 align:middle line:84%
that has the word jig
in its title is a jig,

00:32:46.140 --> 00:32:48.860 align:middle line:84%
and I definitely don't
know that there's

00:32:48.860 --> 00:32:52.520 align:middle line:84%
every piece in this
collection that isn't a jig

00:32:52.520 --> 00:32:55.903 align:middle line:84%
or that is a jig has jig in
the title or that-- yeah.

00:32:55.903 --> 00:32:58.320 align:middle line:84%
That there might be jigs that
don't have jig in the title,

00:32:58.320 --> 00:33:03.400 align:middle line:84%
just as most rags in and
ragtime and Scott Joplin

00:33:03.400 --> 00:33:07.430 align:middle line:84%
have rag in their title,
Maple Leaf Rag and so on.

00:33:07.430 --> 00:33:08.900 align:middle line:90%
But some of them don't.

00:33:08.900 --> 00:33:10.400 align:middle line:90%
The entertainer is the rag.

00:33:10.400 --> 00:33:12.550 align:middle line:84%
It doesn't have
rag in his title.

00:33:12.550 --> 00:33:16.540 align:middle line:84%
So our ground_truth
isn't exactly

00:33:16.540 --> 00:33:18.830 align:middle line:90%
the world's gospel truth.

00:33:18.830 --> 00:33:22.630 align:middle line:84%
This is something that
people neglect all the time

00:33:22.630 --> 00:33:23.870 align:middle line:90%
in machine learning.

00:33:23.870 --> 00:33:28.900 align:middle line:84%
They keep training the
computer to replicate truths

00:33:28.900 --> 00:33:31.690 align:middle line:90%
that aren't necessarily true.

00:33:31.690 --> 00:33:33.950 align:middle line:84%
And you'll see this
all over the place.

00:33:33.950 --> 00:33:37.390 align:middle line:84%
I was just working with a
master's student on a project

00:33:37.390 --> 00:33:39.370 align:middle line:84%
where we were trying
to train optical music

00:33:39.370 --> 00:33:43.270 align:middle line:84%
recognition to produce the
exact ground truth that we

00:33:43.270 --> 00:33:45.280 align:middle line:90%
had found encoded.

00:33:45.280 --> 00:33:48.620 align:middle line:84%
The thing is, the ground
truth had lots of errors too.

00:33:48.620 --> 00:33:50.570 align:middle line:90%
So that's something to know.

00:33:50.570 --> 00:33:53.480 align:middle line:84%
Anyhow, getting back to
what are we going to return.

00:33:53.480 --> 00:33:55.550 align:middle line:84%
Take a second and see if
you can figure this out

00:33:55.550 --> 00:33:58.780 align:middle line:84%
based on what we've
said the return value is

00:33:58.780 --> 00:34:00.980 align:middle line:90%
and what we've defined here.

00:34:00.980 --> 00:34:01.480 align:middle line:90%
Great.

00:34:01.480 --> 00:34:08.120 align:middle line:84%
So we're going to return the
filename, meter_feature 0,

00:34:08.120 --> 00:34:15.820 align:middle line:84%
meter_feature 1,
beat3_feature, sharps_feature,

00:34:15.820 --> 00:34:18.639 align:middle line:90%
and the ground_truth.

00:34:18.639 --> 00:34:20.920 align:middle line:90%
Great.

00:34:20.920 --> 00:34:23.690 align:middle line:84%
OK, so now we just need to
iterate over everything.

00:34:23.690 --> 00:34:25.100 align:middle line:90%
I want to show something.

00:34:25.100 --> 00:34:28.280 align:middle line:84%
When you iterate over
a corpus search object,

00:34:28.280 --> 00:34:30.290 align:middle line:84%
there's this thing
called a metadata bundle.

00:34:30.290 --> 00:34:34.370 align:middle line:84%
That is to say, you haven't
actually parsed 1,063 pieces.

00:34:34.370 --> 00:34:38.120 align:middle line:84%
It just knows about the
existence of 1,063 pieces.

00:34:38.120 --> 00:34:47.080 align:middle line:84%
So when we say for bundle in
Ryan, we can print the bundle

00:34:47.080 --> 00:34:53.260 align:middle line:84%
and we can see that we have
all of these different entries

00:34:53.260 --> 00:34:54.639 align:middle line:90%
for pieces.

00:34:54.639 --> 00:34:59.610 align:middle line:84%
So what we'll go ahead and
do is instead of getting--

00:34:59.610 --> 00:35:00.910 align:middle line:90%
but not actual pieces.

00:35:00.910 --> 00:35:07.210 align:middle line:84%
So to get the pieces, we can
say piece_parsed equals bundle.

00:35:07.210 --> 00:35:11.745 align:middle line:84%
Actually, we call it-- instead
of bundle, say metadata entry.

00:35:11.745 --> 00:35:12.960 align:middle line:90%
Since outputs end there.

00:35:12.960 --> 00:35:17.220 align:middle line:90%
Metadata_entry in Ryan entry.

00:35:17.220 --> 00:35:20.620 align:middle line:84%
Piece_parsed is the
metadata_entry.parse.

00:35:20.620 --> 00:35:23.340 align:middle line:90%
That's going to take some time.

00:35:23.340 --> 00:35:27.960 align:middle line:84%
Then we're going to print
out the feature_extraction

00:35:27.960 --> 00:35:32.190 align:middle line:90%
on the piece_parsed.

00:35:32.190 --> 00:35:35.940 align:middle line:84%
You're going to learn to
use this little button

00:35:35.940 --> 00:35:39.480 align:middle line:84%
in a second, the Stop button,
because this is going to take

00:35:39.480 --> 00:35:41.500 align:middle line:90%
some time if you hit Run.

00:35:41.500 --> 00:35:43.780 align:middle line:84%
But you're going to have
to do it in a little bit.

00:35:43.780 --> 00:35:44.280 align:middle line:90%
Oops.

00:35:44.280 --> 00:35:46.050 align:middle line:90%
Feature_extractor.

00:35:46.050 --> 00:35:48.120 align:middle line:84%
Used to call it
feature_extraction.

00:35:48.120 --> 00:35:53.680 align:middle line:90%
That and exact_meter.

00:35:53.680 --> 00:35:54.970 align:middle line:90%
Extract_meter.

00:35:54.970 --> 00:35:55.750 align:middle line:90%
Here we go.

00:35:55.750 --> 00:35:58.370 align:middle line:84%
So we're going to
put this back here.

00:35:58.370 --> 00:36:02.360 align:middle line:90%
And let's go ahead and run this.

00:36:02.360 --> 00:36:04.460 align:middle line:90%
Oops.

00:36:04.460 --> 00:36:05.660 align:middle line:90%
Oh my goodness.

00:36:05.660 --> 00:36:08.310 align:middle line:90%
I cannot spell anything today.

00:36:08.310 --> 00:36:08.810 align:middle line:90%
OK.

00:36:08.810 --> 00:36:09.870 align:middle line:90%
Here we go.

00:36:09.870 --> 00:36:11.700 align:middle line:90%
Let's go ahead and running this.

00:36:11.700 --> 00:36:15.260 align:middle line:84%
It shows that
AdmiralsHornpipe is--

00:36:15.260 --> 00:36:18.440 align:middle line:84%
I don't know this
piece, but it's in 2/2.

00:36:18.440 --> 00:36:23.930 align:middle line:84%
Really seldom beat
three was offset

00:36:23.930 --> 00:36:26.490 align:middle line:90%
to higher than offset one.

00:36:26.490 --> 00:36:26.990 align:middle line:90%
Wow.

00:36:26.990 --> 00:36:29.220 align:middle line:90%
That is really, really low.

00:36:29.220 --> 00:36:32.610 align:middle line:90%
And it's in one sharp.

00:36:32.610 --> 00:36:33.300 align:middle line:90%
Oh, good.

00:36:33.300 --> 00:36:34.430 align:middle line:90%
Flats do work.

00:36:34.430 --> 00:36:35.940 align:middle line:90%
And it is zero.

00:36:35.940 --> 00:36:37.620 align:middle line:90%
It is not a jig.

00:36:37.620 --> 00:36:39.260 align:middle line:90%
It is a hornpipe.

00:36:39.260 --> 00:36:42.410 align:middle line:84%
I know we all know these
differences between reels

00:36:42.410 --> 00:36:45.260 align:middle line:84%
and hornpipes and jigs
and all these things.

00:36:45.260 --> 00:36:47.670 align:middle line:84%
Well, maybe some of
us got our pirates in.

00:36:47.670 --> 00:36:51.470 align:middle line:84%
OK, we can see here
BannocksOBarleyMealJig,

00:36:51.470 --> 00:36:53.780 align:middle line:90%
which is in 6/8.

00:36:53.780 --> 00:36:55.430 align:middle line:90%
It has this feature.

00:36:55.430 --> 00:36:59.870 align:middle line:84%
It's in two sharps and there's
a one here, so it is a jig.

00:36:59.870 --> 00:37:01.287 align:middle line:90%
So that works pretty well.

00:37:01.287 --> 00:37:02.870 align:middle line:84%
And we can scroll
all the way through.

00:37:02.870 --> 00:37:04.078 align:middle line:90%
Wow, there's a lot of pieces.

00:37:04.078 --> 00:37:05.120 align:middle line:90%
OK, great.

00:37:05.120 --> 00:37:06.620 align:middle line:90%
And some of them are jigs.

00:37:06.620 --> 00:37:07.545 align:middle line:90%
Some of them are not.

00:37:07.545 --> 00:37:10.420 align:middle line:90%


00:37:10.420 --> 00:37:11.304 align:middle line:90%
OK.

00:37:11.304 --> 00:37:15.050 align:middle line:84%
So now we've extracted
all this data.

00:37:15.050 --> 00:37:19.390 align:middle line:84%
If we put all of this into
some sort of file somewhere,

00:37:19.390 --> 00:37:21.620 align:middle line:90%
we will have it all done.

00:37:21.620 --> 00:37:23.500 align:middle line:84%
So I'm going to take
a two second break

00:37:23.500 --> 00:37:28.210 align:middle line:84%
and show how we move
from feature extraction

00:37:28.210 --> 00:37:30.700 align:middle line:90%
to machine learning.

00:37:30.700 --> 00:37:32.290 align:middle line:84%
OK, one of the most
important things

00:37:32.290 --> 00:37:35.440 align:middle line:84%
we're going to be thinking about
when we think about machine

00:37:35.440 --> 00:37:38.620 align:middle line:84%
learning is that
we're going to be

00:37:38.620 --> 00:37:42.530 align:middle line:84%
training the computer on
a certain set of data,

00:37:42.530 --> 00:37:45.580 align:middle line:84%
training our algorithms,
training our neural networks

00:37:45.580 --> 00:37:48.520 align:middle line:84%
or whatever, artificial
intelligence and machine

00:37:48.520 --> 00:37:52.100 align:middle line:84%
learning algorithm we choose to
use on some portion of the data.

00:37:52.100 --> 00:37:55.400 align:middle line:84%
And then we want to see, how
good is the computer doing?

00:37:55.400 --> 00:37:58.990 align:middle line:84%
So we're going to hold out
some portion of the data

00:37:58.990 --> 00:38:00.070 align:middle line:90%
to be our test.

00:38:00.070 --> 00:38:04.390 align:middle line:84%
To see, well, if the training
data is somewhat like the test

00:38:04.390 --> 00:38:06.700 align:middle line:84%
data, but the computer's
seen the training data

00:38:06.700 --> 00:38:08.480 align:middle line:84%
and it hasn't seen
the test data,

00:38:08.480 --> 00:38:13.570 align:middle line:84%
how well does it learn
from the training data

00:38:13.570 --> 00:38:18.080 align:middle line:84%
in order to make identifications
in the test data?

00:38:18.080 --> 00:38:21.800 align:middle line:84%
And there are lots of
different ways of doing this.

00:38:21.800 --> 00:38:24.410 align:middle line:84%
Please take a machine
learning class.

00:38:24.410 --> 00:38:27.590 align:middle line:84%
Take an artificial intelligence
class so you can learn about one

00:38:27.590 --> 00:38:31.960 align:middle line:84%
hold out cross-validation
or 1/10 hold out.

00:38:31.960 --> 00:38:34.433 align:middle line:84%
Lots of different ways
that we can do this better

00:38:34.433 --> 00:38:35.600 align:middle line:90%
than what we're going to do.

00:38:35.600 --> 00:38:40.210 align:middle line:84%
But instead, for now, to
make things very simple,

00:38:40.210 --> 00:38:42.730 align:middle line:84%
for whom this is going to
be your first introduction

00:38:42.730 --> 00:38:45.790 align:middle line:84%
to artificial intelligence and
machine learning, what we're

00:38:45.790 --> 00:38:49.060 align:middle line:84%
going to do is we're going to
divide all of our training data

00:38:49.060 --> 00:38:52.260 align:middle line:84%
into two parts, all of
our data into half of it

00:38:52.260 --> 00:38:55.300 align:middle line:84%
as the test data and half
of it as the training data.

00:38:55.300 --> 00:38:58.800 align:middle line:84%
And I'm just going to go through
and almost always do everything

00:38:58.800 --> 00:39:02.130 align:middle line:84%
in, this one to test, this
one training, this one

00:39:02.130 --> 00:39:03.610 align:middle line:90%
test, this one training.

00:39:03.610 --> 00:39:06.150 align:middle line:84%
It's just going to
make things easier.

00:39:06.150 --> 00:39:09.600 align:middle line:84%
But there are better
ways to do it.

00:39:09.600 --> 00:39:10.450 align:middle line:90%
Enough for now.

00:39:10.450 --> 00:39:14.070 align:middle line:84%
Let's get to some artificial
intelligence and machine

00:39:14.070 --> 00:39:16.440 align:middle line:90%
learning.

00:39:16.440 --> 00:39:17.010 align:middle line:90%
OK.

00:39:17.010 --> 00:39:20.950 align:middle line:84%
Let's go ahead and open
up two files for writing.

00:39:20.950 --> 00:39:24.210 align:middle line:90%
I'm going to call them--

00:39:24.210 --> 00:39:25.240 align:middle line:90%
they're on my desktop.

00:39:25.240 --> 00:39:29.130 align:middle line:84%
Oh, now you know my
secret, secret path.

00:39:29.130 --> 00:39:32.358 align:middle line:90%
We'll call it train_data.tab.

00:39:32.358 --> 00:39:33.900 align:middle line:84%
We're going to open
this for writing,

00:39:33.900 --> 00:39:37.320 align:middle line:90%
and we'll call it as training.

00:39:37.320 --> 00:39:40.710 align:middle line:84%
If you're not familiar
with Python file

00:39:40.710 --> 00:39:44.610 align:middle line:84%
handles, please take a
second to look this up

00:39:44.610 --> 00:39:47.950 align:middle line:84%
because otherwise this
won't make much sense.

00:39:47.950 --> 00:39:53.210 align:middle line:84%
But essentially we're going
to have two files so we're

00:39:53.210 --> 00:39:56.690 align:middle line:84%
going to be able to write
to, going back and forth,

00:39:56.690 --> 00:39:57.990 align:middle line:90%
one versus the other.

00:39:57.990 --> 00:40:00.930 align:middle line:84%
There's going to be
better ways of doing this,

00:40:00.930 --> 00:40:03.630 align:middle line:84%
but this is how we're
going to do it first.

00:40:03.630 --> 00:40:04.170 align:middle line:90%
OK.

00:40:04.170 --> 00:40:06.470 align:middle line:90%
We're going to need to say--

00:40:06.470 --> 00:40:09.650 align:middle line:84%
for a lot of various
algorithms, we're

00:40:09.650 --> 00:40:13.110 align:middle line:84%
going to need to be able to
say what our column names are.

00:40:13.110 --> 00:40:15.590 align:middle line:84%
So we'll say our
columns are going

00:40:15.590 --> 00:40:18.900 align:middle line:84%
to be a series of
tab separated values.

00:40:18.900 --> 00:40:21.680 align:middle line:84%
That's what these dot tab
files are going to be.

00:40:21.680 --> 00:40:27.240 align:middle line:84%
A series of tab separated
values that join these titles,

00:40:27.240 --> 00:40:32.600 align:middle line:84%
filename, numerator-- doesn't
matter what these are called--

00:40:32.600 --> 00:40:37.220 align:middle line:90%
denominator beat3 proportion.

00:40:37.220 --> 00:40:40.080 align:middle line:84%
I'm not going to make
myself type that again.

00:40:40.080 --> 00:40:44.940 align:middle line:84%
And we'll say is_jig at
the end for a ground truth.

00:40:44.940 --> 00:40:46.040 align:middle line:90%
Fantastic.

00:40:46.040 --> 00:40:46.950 align:middle line:90%
OK.

00:40:46.950 --> 00:40:48.480 align:middle line:90%
Those are columns.

00:40:48.480 --> 00:40:50.270 align:middle line:84%
And first I'm going
to do is write

00:40:50.270 --> 00:40:57.110 align:middle line:84%
to each of our different files,
write our columns with a line

00:40:57.110 --> 00:41:00.020 align:middle line:90%
break at the end.

00:41:00.020 --> 00:41:02.720 align:middle line:84%
Our testing is going
to write columns

00:41:02.720 --> 00:41:05.390 align:middle line:90%
with a line break at the end.

00:41:05.390 --> 00:41:06.120 align:middle line:90%
Great.

00:41:06.120 --> 00:41:08.720 align:middle line:84%
Now we want to describe what
kind of value, what kind

00:41:08.720 --> 00:41:11.660 align:middle line:84%
of value will a machine
learning toolkit

00:41:11.660 --> 00:41:16.340 align:middle line:84%
expect to get from filename,
string, numerator, integer,

00:41:16.340 --> 00:41:18.570 align:middle line:90%
beat3, float.

00:41:18.570 --> 00:41:19.830 align:middle line:90%
Things like that.

00:41:19.830 --> 00:41:24.290 align:middle line:84%
So we'll say our descriptions
are going to be--

00:41:24.290 --> 00:41:28.200 align:middle line:84%
and these are pretty standard
formats but they're not Python.

00:41:28.200 --> 00:41:29.610 align:middle line:90%
So look at this.

00:41:29.610 --> 00:41:30.500 align:middle line:90%
It's not str.

00:41:30.500 --> 00:41:31.860 align:middle line:90%
It's string.

00:41:31.860 --> 00:41:36.750 align:middle line:84%
And we'll say that our integers
are discrete data with an i.

00:41:36.750 --> 00:41:40.670 align:middle line:90%
Not discreet like indiscreet.

00:41:40.670 --> 00:41:41.910 align:middle line:90%
OK, I won't make a joke.

00:41:41.910 --> 00:41:44.930 align:middle line:84%
But discrete like
integer values.

00:41:44.930 --> 00:41:48.440 align:middle line:84%
But beat3 data
can be continuous.

00:41:48.440 --> 00:41:51.590 align:middle line:90%
It can be 1.2, 1.21, so on.

00:41:51.590 --> 00:41:55.250 align:middle line:84%
And then another discrete
data for the number of sharps.

00:41:55.250 --> 00:41:59.060 align:middle line:84%
And then for is_jib,
it's also at 0, 1,

00:41:59.060 --> 00:42:00.950 align:middle line:84%
so it's going to
be discrete data.

00:42:00.950 --> 00:42:02.320 align:middle line:90%
Fantastic.

00:42:02.320 --> 00:42:07.750 align:middle line:84%
We're going to write thees to
these files, the descriptions

00:42:07.750 --> 00:42:08.650 align:middle line:90%
also.

00:42:08.650 --> 00:42:09.250 align:middle line:90%
Boom.

00:42:09.250 --> 00:42:10.510 align:middle line:90%
OK.

00:42:10.510 --> 00:42:11.010 align:middle line:90%
Great.

00:42:11.010 --> 00:42:14.290 align:middle line:90%


00:42:14.290 --> 00:42:18.110 align:middle line:84%
We also tend to put
these meta variables in,

00:42:18.110 --> 00:42:22.010 align:middle line:84%
and they say, if
anything is special,

00:42:22.010 --> 00:42:23.660 align:middle line:90%
if anything is unlike the rest.

00:42:23.660 --> 00:42:27.380 align:middle line:84%
Well, the ones that are
special is the first thing.

00:42:27.380 --> 00:42:29.960 align:middle line:90%
String is just a metadata.

00:42:29.960 --> 00:42:34.210 align:middle line:84%
That is to say, it
just means something

00:42:34.210 --> 00:42:37.900 align:middle line:84%
so that we can more easily
diagnose problems and look

00:42:37.900 --> 00:42:38.600 align:middle line:90%
things up later.

00:42:38.600 --> 00:42:39.950 align:middle line:90%
We don't actually need it.

00:42:39.950 --> 00:42:43.180 align:middle line:84%
We're not going to
study the filename.

00:42:43.180 --> 00:42:46.750 align:middle line:84%
And then these are
just normal things.

00:42:46.750 --> 00:42:50.260 align:middle line:84%
Numerator, denominator,
beat3, number of sharps.

00:42:50.260 --> 00:42:54.370 align:middle line:84%
And then at the very end,
the final thing is our class.

00:42:54.370 --> 00:42:56.640 align:middle line:84%
The thing that we're
trying to learn.

00:42:56.640 --> 00:43:04.320 align:middle line:84%
We're trying to learn, does
this information, 98.11112,

00:43:04.320 --> 00:43:07.350 align:middle line:90%
describe a jig or not?

00:43:07.350 --> 00:43:10.180 align:middle line:84%
The class of objects
that is a jig.

00:43:10.180 --> 00:43:10.680 align:middle line:90%
Great.

00:43:10.680 --> 00:43:12.520 align:middle line:90%
So these are our meta variables.

00:43:12.520 --> 00:43:18.905 align:middle line:84%
And we're going to write
them to, again, our--

00:43:18.905 --> 00:43:19.780 align:middle line:90%
do I still have that?

00:43:19.780 --> 00:43:21.900 align:middle line:90%
No.

00:43:21.900 --> 00:43:27.990 align:middle line:84%
I'm going to write that to our
training and to our testing.

00:43:27.990 --> 00:43:30.490 align:middle line:90%
Great.

00:43:30.490 --> 00:43:30.990 align:middle line:90%
Here.

00:43:30.990 --> 00:43:33.520 align:middle line:90%
I can do this anyhow.

00:43:33.520 --> 00:43:38.881 align:middle line:90%
We can cat that file.

00:43:38.881 --> 00:43:42.090 align:middle line:84%
These magic things are stuff
you can do in Jupyter that you

00:43:42.090 --> 00:43:44.180 align:middle line:90%
can't do in normal Python.

00:43:44.180 --> 00:43:49.770 align:middle line:90%
But it'll see train_data tab.

00:43:49.770 --> 00:43:50.270 align:middle line:90%
Yep.

00:43:50.270 --> 00:43:52.920 align:middle line:84%
We can see what we've
written out there.

00:43:52.920 --> 00:43:54.000 align:middle line:90%
OK, great.

00:43:54.000 --> 00:43:55.730 align:middle line:84%
Now we're going to
take this and we're

00:43:55.730 --> 00:43:57.540 align:middle line:84%
going to write
more things to it.

00:43:57.540 --> 00:44:04.520 align:middle line:84%
We're going to write into
these two files information

00:44:04.520 --> 00:44:07.020 align:middle line:84%
about from our
feature extraction.

00:44:07.020 --> 00:44:13.640 align:middle line:84%
So we're going to go back
for each piece in Ryan.

00:44:13.640 --> 00:44:17.090 align:middle line:90%
Enumerate Ryan.

00:44:17.090 --> 00:44:20.930 align:middle line:84%
And enumerate says our
first thing goes into piece

00:44:20.930 --> 00:44:21.953 align:middle line:90%
and we'll call it i.

00:44:21.953 --> 00:44:23.370 align:middle line:84%
Actually, We'll
not call it piece.

00:44:23.370 --> 00:44:26.310 align:middle line:90%
We'll call it metadata_entry.

00:44:26.310 --> 00:44:27.860 align:middle line:90%
Great.

00:44:27.860 --> 00:44:32.540 align:middle line:84%
And we'll say piece_parsed
is our metadata_entry.parse.

00:44:32.540 --> 00:44:35.840 align:middle line:90%


00:44:35.840 --> 00:44:36.500 align:middle line:90%
Great.

00:44:36.500 --> 00:44:43.230 align:middle line:84%
And our features are
for feature_extractor

00:44:43.230 --> 00:44:47.480 align:middle line:90%
on piece_parsed.

00:44:47.480 --> 00:44:48.510 align:middle line:90%
Piece_parsed.

00:44:48.510 --> 00:44:53.430 align:middle line:84%
And now we're going to make
a string out of that feature.

00:44:53.430 --> 00:44:57.140 align:middle line:84%
String equals tab
separated version

00:44:57.140 --> 00:45:02.240 align:middle line:84%
of the string value
of each element

00:45:02.240 --> 00:45:05.280 align:middle line:90%
for the element in features.

00:45:05.280 --> 00:45:06.052 align:middle line:90%
OK.

00:45:06.052 --> 00:45:09.080 align:middle line:90%
And we should call it f.

00:45:09.080 --> 00:45:11.510 align:middle line:90%
Fantastic.

00:45:11.510 --> 00:45:15.860 align:middle line:90%
And if i is even.

00:45:15.860 --> 00:45:19.310 align:middle line:84%
No, if i is odd, we'll
write it to the training

00:45:19.310 --> 00:45:25.910 align:middle line:90%
data with a new line.

00:45:25.910 --> 00:45:29.540 align:middle line:84%
And otherwise we'll
write it to the testing

00:45:29.540 --> 00:45:35.180 align:middle line:90%
data with a new line.

00:45:35.180 --> 00:45:36.020 align:middle line:90%
Great.

00:45:36.020 --> 00:45:38.015 align:middle line:84%
Hopefully I didn't
type anything wrong.

00:45:38.015 --> 00:45:39.140 align:middle line:90%
We'll find out in a second.

00:45:39.140 --> 00:45:42.220 align:middle line:90%


00:45:42.220 --> 00:45:43.090 align:middle line:90%
Great.

00:45:43.090 --> 00:45:44.660 align:middle line:90%
It seems to be working.

00:45:44.660 --> 00:45:46.922 align:middle line:90%
It's slow.

00:45:46.922 --> 00:45:48.880 align:middle line:84%
One of the things I'm
going to eventually learn

00:45:48.880 --> 00:45:52.340 align:middle line:84%
is that everything's slower
when I'm screen recording.

00:45:52.340 --> 00:45:56.740 align:middle line:84%
So we could see
that, yep, there's

00:45:56.740 --> 00:45:58.670 align:middle line:90%
a bunch of things in here.

00:45:58.670 --> 00:46:00.680 align:middle line:84%
Most important one,
can we get a jig?

00:46:00.680 --> 00:46:04.630 align:middle line:84%
It has a one at the end if
it's a jig, zero at the end

00:46:04.630 --> 00:46:07.750 align:middle line:90%
if it's something else.

00:46:07.750 --> 00:46:08.990 align:middle line:90%
These jigs are 6/8.

00:46:08.990 --> 00:46:10.660 align:middle line:90%
Oh, look, there's a jig.

00:46:10.660 --> 00:46:12.140 align:middle line:90%
It begins at 9/8.

00:46:12.140 --> 00:46:14.448 align:middle line:84%
So maybe it's 8
that's more important.

00:46:14.448 --> 00:46:14.990 align:middle line:90%
I don't know.

00:46:14.990 --> 00:46:17.180 align:middle line:84%
We'll see if the computer
can figure this out.

00:46:17.180 --> 00:46:19.880 align:middle line:84%
We don't need to look
at all 1,000 entries.

00:46:19.880 --> 00:46:24.590 align:middle line:84%
Jupyter does a nice way of
not putting that all together.

00:46:24.590 --> 00:46:25.910 align:middle line:90%
OK, great.

00:46:25.910 --> 00:46:28.960 align:middle line:84%
So now we have
something that we can

00:46:28.960 --> 00:46:32.410 align:middle line:84%
feed into an artificial
intelligence classification

00:46:32.410 --> 00:46:33.230 align:middle line:90%
program.

00:46:33.230 --> 00:46:36.350 align:middle line:84%
So we don't have one so we're
going to write one of our own.

00:46:36.350 --> 00:46:39.930 align:middle line:84%
So we're going to
say neural network.

00:46:39.930 --> 00:46:41.020 align:middle line:90%
Just kidding.

00:46:41.020 --> 00:46:42.910 align:middle line:84%
No, that's not what
this class is about.

00:46:42.910 --> 00:46:44.110 align:middle line:90%
That's other classes.

00:46:44.110 --> 00:46:45.370 align:middle line:90%
We're going to install one.

00:46:45.370 --> 00:46:51.930 align:middle line:84%
So go ahead and install orange3,
which is a really great package.

00:46:51.930 --> 00:46:53.850 align:middle line:84%
Oh, hey, I already
have it installed.

00:46:53.850 --> 00:46:56.110 align:middle line:84%
Yours probably takes a
little bit longer than that.

00:46:56.110 --> 00:46:56.730 align:middle line:90%
Great.

00:46:56.730 --> 00:46:58.710 align:middle line:90%
Super.

00:46:58.710 --> 00:47:00.810 align:middle line:90%
So now I have orange3.

00:47:00.810 --> 00:47:05.490 align:middle line:84%
Orange3 names its
stuff kind of funny.

00:47:05.490 --> 00:47:09.100 align:middle line:84%
So I always-- because I've
been using it for a long time,

00:47:09.100 --> 00:47:11.560 align:middle line:90%
I just import it.

00:47:11.560 --> 00:47:12.970 align:middle line:90%
It's not orange3.

00:47:12.970 --> 00:47:14.050 align:middle line:90%
I just call it orange.

00:47:14.050 --> 00:47:14.682 align:middle line:90%
Great.

00:47:14.682 --> 00:47:16.140 align:middle line:84%
Now what we're
going to do is we're

00:47:16.140 --> 00:47:20.490 align:middle line:84%
going to load in
our training data

00:47:20.490 --> 00:47:26.046 align:middle line:84%
from an orange data table
based on that information.

00:47:26.046 --> 00:47:28.830 align:middle line:90%


00:47:28.830 --> 00:47:31.232 align:middle line:90%
So a train_data.tab.

00:47:31.232 --> 00:47:35.540 align:middle line:90%


00:47:35.540 --> 00:47:39.560 align:middle line:84%
I reverted myself to
using camelcase things.

00:47:39.560 --> 00:47:41.270 align:middle line:84%
I probably shouldn't,
but I'm not

00:47:41.270 --> 00:47:44.900 align:middle line:90%
going to rewrite everything now.

00:47:44.900 --> 00:47:48.330 align:middle line:84%
So it doesn't look like much,
but I have a lot in my sleeve.

00:47:48.330 --> 00:47:48.900 align:middle line:90%
OK.

00:47:48.900 --> 00:47:51.390 align:middle line:84%
So we're going to
load those two.

00:47:51.390 --> 00:47:52.310 align:middle line:90%
Great.

00:47:52.310 --> 00:47:55.110 align:middle line:84%
We can look at
train_data little bit.

00:47:55.110 --> 00:47:55.610 align:middle line:90%
Yep.

00:47:55.610 --> 00:47:57.380 align:middle line:90%
Whole bunch of stuff.

00:47:57.380 --> 00:48:02.790 align:middle line:84%
These are, I think,
matplotlib-ish type things.

00:48:02.790 --> 00:48:03.690 align:middle line:90%
OK, great.

00:48:03.690 --> 00:48:08.000 align:middle line:84%
So what we want to
do is create a bunch

00:48:08.000 --> 00:48:13.190 align:middle line:84%
of learners, things that
can classify and understand

00:48:13.190 --> 00:48:15.810 align:middle line:84%
data and try to make
guesses about things.

00:48:15.810 --> 00:48:20.400 align:middle line:84%
Our first learner is kind of
like the placebo of learners.

00:48:20.400 --> 00:48:23.120 align:middle line:84%
It's called the
majority learner.

00:48:23.120 --> 00:48:27.060 align:middle line:84%
And there's other ways of doing
this, but we'll use this one.

00:48:27.060 --> 00:48:33.570 align:middle line:84%
And the majority
learner is pretty cool.

00:48:33.570 --> 00:48:35.820 align:middle line:90%
It just looks at the data.

00:48:35.820 --> 00:48:41.840 align:middle line:84%
It looks at what we put in
the training data and it says,

00:48:41.840 --> 00:48:43.050 align:middle line:90%
you know what?

00:48:43.050 --> 00:48:47.390 align:middle line:84%
There's about three times as
many things that are not jigs

00:48:47.390 --> 00:48:49.110 align:middle line:90%
as there are jigs.

00:48:49.110 --> 00:48:52.760 align:middle line:84%
So I can get 3 out
of 4 right if I just

00:48:52.760 --> 00:48:54.930 align:middle line:84%
learn to always vote
with the majority.

00:48:54.930 --> 00:48:58.655 align:middle line:84%
I don't know anything about
music, but I'll just say--

00:48:58.655 --> 00:49:00.510 align:middle line:84%
I'll always say
that's not a jig.

00:49:00.510 --> 00:49:01.260 align:middle line:90%
And you know what?

00:49:01.260 --> 00:49:03.530 align:middle line:90%
I'll usually be right.

00:49:03.530 --> 00:49:06.650 align:middle line:84%
So never classify
things according to,

00:49:06.650 --> 00:49:09.350 align:middle line:90%
hey, is this right or wrong?

00:49:09.350 --> 00:49:11.190 align:middle line:84%
Did it get it right
more than half the time?

00:49:11.190 --> 00:49:11.690 align:middle line:90%
No.

00:49:11.690 --> 00:49:15.090 align:middle line:84%
Classify how you're
doing against,

00:49:15.090 --> 00:49:17.100 align:middle line:84%
did it do better than
the majority learner?

00:49:17.100 --> 00:49:19.920 align:middle line:90%


00:49:19.920 --> 00:49:22.070 align:middle line:84%
You're going to
now, if you don't

00:49:22.070 --> 00:49:24.350 align:middle line:84%
know what this is,
we're going to learn

00:49:24.350 --> 00:49:31.210 align:middle line:84%
what a k nearest
neighbors is, knnLearner.

00:49:31.210 --> 00:49:33.280 align:middle line:90%
Classification.

00:49:33.280 --> 00:49:34.840 align:middle line:90%
Classification.

00:49:34.840 --> 00:49:37.870 align:middle line:90%
KnnLearner.

00:49:37.870 --> 00:49:41.320 align:middle line:84%
And this is a pretty standard
artificial intelligence

00:49:41.320 --> 00:49:44.380 align:middle line:84%
learning algorithm
and so I'm not

00:49:44.380 --> 00:49:45.980 align:middle line:84%
going to say too
much about that.

00:49:45.980 --> 00:49:48.700 align:middle line:84%
So we create a kind
of learner thing,

00:49:48.700 --> 00:49:52.030 align:middle line:84%
and our classifier
is a learner that's

00:49:52.030 --> 00:49:58.330 align:middle line:84%
going to work on a particular
set of data, our training data.

00:49:58.330 --> 00:49:59.240 align:middle line:90%
OK, good.

00:49:59.240 --> 00:50:01.970 align:middle line:84%
So we create a learner,
create a classifier.

00:50:01.970 --> 00:50:03.520 align:middle line:84%
Hasn't actually
learned anything yet,

00:50:03.520 --> 00:50:07.250 align:middle line:84%
but it's going to be
ready for doing that.

00:50:07.250 --> 00:50:09.836 align:middle line:90%
OK.

00:50:09.836 --> 00:50:12.190 align:middle line:84%
Now we're going to
check how often does

00:50:12.190 --> 00:50:14.240 align:middle line:84%
the majority
learner get things--

00:50:14.240 --> 00:50:16.870 align:middle line:84%
how many times does
it get it correct

00:50:16.870 --> 00:50:22.840 align:middle line:84%
and how many times does the
k nearest neighbor's learner

00:50:22.840 --> 00:50:24.730 align:middle line:90%
get things correct?

00:50:24.730 --> 00:50:30.870 align:middle line:84%
And how many total
things are there?

00:50:30.870 --> 00:50:34.150 align:middle line:90%
We get that as a float.

00:50:34.150 --> 00:50:39.300 align:middle line:84%
Still thinking too much how
to think like Python too.

00:50:39.300 --> 00:50:43.590 align:middle line:90%
So how many test data there are.

00:50:43.590 --> 00:50:44.610 align:middle line:90%
Go and see.

00:50:44.610 --> 00:50:47.330 align:middle line:90%
OK, 532 in the test data.

00:50:47.330 --> 00:50:50.790 align:middle line:90%


00:50:50.790 --> 00:50:52.980 align:middle line:84%
The training data
does not need to be

00:50:52.980 --> 00:50:55.170 align:middle line:84%
exactly the same
size, or even close

00:50:55.170 --> 00:50:57.300 align:middle line:84%
to the same size
as the test data.

00:50:57.300 --> 00:50:58.470 align:middle line:90%
But in this case, they are.

00:50:58.470 --> 00:50:59.050 align:middle line:90%
Great.

00:50:59.050 --> 00:51:01.650 align:middle line:84%
So now we're going to
iterate through each

00:51:01.650 --> 00:51:12.600 align:middle line:84%
of the rows of our test
data not our training data.

00:51:12.600 --> 00:51:16.140 align:middle line:84%
So we're going to know what
row number we are on, i,

00:51:16.140 --> 00:51:17.530 align:middle line:90%
and then test row.

00:51:17.530 --> 00:51:19.620 align:middle line:84%
And then the majority
learner is going

00:51:19.620 --> 00:51:24.490 align:middle line:84%
to make a guess based on
the data in the test row.

00:51:24.490 --> 00:51:26.740 align:middle line:84%
However, the majority
learner is really stupid,

00:51:26.740 --> 00:51:31.350 align:middle line:84%
so it's guess is always
going to be, it's not a jig.

00:51:31.350 --> 00:51:34.270 align:middle line:84%
Then k nearest neighbor
is going to make a guess.

00:51:34.270 --> 00:51:36.450 align:middle line:84%
We hope that k
nearest neighbor is

00:51:36.450 --> 00:51:40.480 align:middle line:84%
making a guess based on some
intelligence that it has,

00:51:40.480 --> 00:51:42.790 align:middle line:90%
or fake intelligence.

00:51:42.790 --> 00:51:45.340 align:middle line:84%
I mean, it's called artificial
intelligence for a reason.

00:51:45.340 --> 00:51:51.880 align:middle line:84%
And then we get to see in this
case what the actual answer is,

00:51:51.880 --> 00:51:52.720 align:middle line:90%
what the class--

00:51:52.720 --> 00:51:53.920 align:middle line:90%
whether it's a jig or not.

00:51:53.920 --> 00:51:56.160 align:middle line:90%
So that's our real answer.

00:51:56.160 --> 00:51:58.470 align:middle line:84%
So we know this but
k nearest neighbor

00:51:58.470 --> 00:52:00.660 align:middle line:90%
is not allowed to look at this.

00:52:00.660 --> 00:52:03.730 align:middle line:84%
We really hope the
computer's not peeking,

00:52:03.730 --> 00:52:07.390 align:middle line:84%
otherwise all artificial
intelligence is kind of screwed.

00:52:07.390 --> 00:52:07.950 align:middle line:90%
OK.

00:52:07.950 --> 00:52:10.440 align:middle line:84%
We'll just print
out some test data

00:52:10.440 --> 00:52:22.330 align:middle line:84%
that the row i is a little bit
of information about our set.

00:52:22.330 --> 00:52:23.770 align:middle line:90%
That should be good.

00:52:23.770 --> 00:52:24.270 align:middle line:90%
Great.

00:52:24.270 --> 00:52:38.293 align:middle line:84%
We'll print out that the answer
to row i is jig, if realAnswer.

00:52:38.293 --> 00:52:40.850 align:middle line:90%


00:52:40.850 --> 00:52:42.770 align:middle line:90%
I think that works.

00:52:42.770 --> 00:52:44.320 align:middle line:90%
Else not jig.

00:52:44.320 --> 00:52:50.510 align:middle line:90%


00:52:50.510 --> 00:52:52.410 align:middle line:90%
And then we'll put a tab.

00:52:52.410 --> 00:52:56.450 align:middle line:84%
We'll say k nearest neighbor
got it right or wrong.

00:52:56.450 --> 00:53:00.140 align:middle line:84%
Right if knn's-- if the k
nearest neighbors guess is

00:53:00.140 --> 00:53:05.480 align:middle line:84%
the same as the
realAnswer, else wrong.

00:53:05.480 --> 00:53:06.530 align:middle line:90%
Whew.

00:53:06.530 --> 00:53:09.200 align:middle line:90%
That's some pretty tough stuff.

00:53:09.200 --> 00:53:11.310 align:middle line:84%
Our thing can't
even get that right.

00:53:11.310 --> 00:53:11.853 align:middle line:90%
Good.

00:53:11.853 --> 00:53:12.353 align:middle line:90%
OK.

00:53:12.353 --> 00:53:14.960 align:middle line:90%


00:53:14.960 --> 00:53:16.945 align:middle line:84%
We'll print a blank
line after that.

00:53:16.945 --> 00:53:19.730 align:middle line:90%


00:53:19.730 --> 00:53:24.550 align:middle line:84%
If the majority guessed
right, then the majority

00:53:24.550 --> 00:53:29.140 align:middle line:90%
correct increment.

00:53:29.140 --> 00:53:35.920 align:middle line:84%
If k nearest neighbors
guess is right--

00:53:35.920 --> 00:53:40.180 align:middle line:84%
so we're just checking at
this point how good is this.

00:53:40.180 --> 00:53:44.260 align:middle line:84%
k nearest neighbor's correct,
it is going to be one bigger.

00:53:44.260 --> 00:53:45.940 align:middle line:90%
Great.

00:53:45.940 --> 00:53:49.150 align:middle line:84%
So we'll go ahead
and let that run.

00:53:49.150 --> 00:53:51.430 align:middle line:90%
Oops.

00:53:51.430 --> 00:53:53.450 align:middle line:90%
Colons are very nice.

00:53:53.450 --> 00:53:54.490 align:middle line:90%
Oops.

00:53:54.490 --> 00:53:55.530 align:middle line:90%
I screwed something up.

00:53:55.530 --> 00:53:59.440 align:middle line:90%


00:53:59.440 --> 00:54:00.580 align:middle line:90%
Oops.

00:54:00.580 --> 00:54:02.350 align:middle line:90%
There we go.

00:54:02.350 --> 00:54:06.010 align:middle line:84%
I have to cast this
as a list because--

00:54:06.010 --> 00:54:06.860 align:middle line:90%
where is it?

00:54:06.860 --> 00:54:10.150 align:middle line:84%
This data can't be
sliced, but lists can.

00:54:10.150 --> 00:54:10.760 align:middle line:90%
OK.

00:54:10.760 --> 00:54:12.450 align:middle line:90%
Is that going on?

00:54:12.450 --> 00:54:14.930 align:middle line:84%
I probably need
to reset my data,

00:54:14.930 --> 00:54:16.820 align:middle line:90%
so let's go ahead and do that.

00:54:16.820 --> 00:54:18.350 align:middle line:90%
It's going to be printing.

00:54:18.350 --> 00:54:19.180 align:middle line:90%
Cool.

00:54:19.180 --> 00:54:20.500 align:middle line:90%
Not jig.

00:54:20.500 --> 00:54:22.740 align:middle line:84%
k nearest neighbors
got it wrong.

00:54:22.740 --> 00:54:23.895 align:middle line:90%
Not jig.

00:54:23.895 --> 00:54:25.270 align:middle line:84%
k nearest neighbors
got it right.

00:54:25.270 --> 00:54:26.250 align:middle line:90%
Good.

00:54:26.250 --> 00:54:28.840 align:middle line:84%
So, hey, we see a
lot of got it right.

00:54:28.840 --> 00:54:29.410 align:middle line:90%
I like that.

00:54:29.410 --> 00:54:30.250 align:middle line:90%
I like that.

00:54:30.250 --> 00:54:31.000 align:middle line:90%
OK.

00:54:31.000 --> 00:54:33.810 align:middle line:90%
Here's the moment of truth.

00:54:33.810 --> 00:54:39.790 align:middle line:84%
Without machine learning,
there's a majority learner.

00:54:39.790 --> 00:54:42.030 align:middle line:90%
Majority correct.

00:54:42.030 --> 00:54:48.430 align:middle line:84%
Always put things into
print percentages.

00:54:48.430 --> 00:54:52.000 align:middle line:84%
Always round your percentages
to something reasonable.

00:54:52.000 --> 00:54:55.170 align:middle line:84%
Nobody wants to see all
those dangling digits.

00:54:55.170 --> 00:54:55.870 align:middle line:90%
OK.

00:54:55.870 --> 00:54:58.060 align:middle line:90%
So it got that number right.

00:54:58.060 --> 00:55:06.430 align:middle line:84%
And we'll say with
knn machine learning,

00:55:06.430 --> 00:55:10.240 align:middle line:90%
we got the knn correct.

00:55:10.240 --> 00:55:12.450 align:middle line:90%
How well do we do?

00:55:12.450 --> 00:55:15.660 align:middle line:84%
Without machine learning,
got it 77% right.

00:55:15.660 --> 00:55:20.560 align:middle line:84%
k nearest neighbors
got it 95% right.

00:55:20.560 --> 00:55:22.200 align:middle line:90%
Wow.

00:55:22.200 --> 00:55:23.560 align:middle line:90%
OK, that's pretty awesome.

00:55:23.560 --> 00:55:25.530 align:middle line:84%
That's a lot better
than I thought

00:55:25.530 --> 00:55:30.030 align:middle line:90%
when I thought I would do this.

00:55:30.030 --> 00:55:31.995 align:middle line:84%
By the way, one of
the things we can do.

00:55:31.995 --> 00:55:38.830 align:middle line:84%
You probably want to keep track
of your data and don't do this,

00:55:38.830 --> 00:55:40.630 align:middle line:84%
but we'll just go
ahead and check.

00:55:40.630 --> 00:55:43.920 align:middle line:84%
Does it make a difference if we
swap the training and the test

00:55:43.920 --> 00:55:44.420 align:middle line:90%
data?

00:55:44.420 --> 00:55:47.880 align:middle line:90%


00:55:47.880 --> 00:55:48.930 align:middle line:90%
Oops.

00:55:48.930 --> 00:55:50.020 align:middle line:90%
Not training data.

00:55:50.020 --> 00:55:51.190 align:middle line:90%
Train_data.

00:55:51.190 --> 00:55:55.200 align:middle line:90%


00:55:55.200 --> 00:55:57.810 align:middle line:90%
Do we get a fluke?

00:55:57.810 --> 00:56:01.230 align:middle line:90%
And we can go ahead and run.

00:56:01.230 --> 00:56:02.710 align:middle line:90%
72 and 94.

00:56:02.710 --> 00:56:04.810 align:middle line:90%
So yeah, still pretty good.

00:56:04.810 --> 00:56:06.430 align:middle line:90%
Doesn't matter which one we do.

00:56:06.430 --> 00:56:11.010 align:middle line:84%
I'm going to switch that
back because I will totally

00:56:11.010 --> 00:56:12.130 align:middle line:90%
make that mistake.

00:56:12.130 --> 00:56:13.240 align:middle line:90%
But yeah.

00:56:13.240 --> 00:56:16.210 align:middle line:84%
So we're doing really
well with this.

00:56:16.210 --> 00:56:18.810 align:middle line:84%
So this is how you can do
artificial intelligence

00:56:18.810 --> 00:56:19.885 align:middle line:90%
with machine learning.

00:56:19.885 --> 00:56:23.300 align:middle line:90%


00:56:23.300 --> 00:56:25.740 align:middle line:84%
But that's been a
little bit hard.

00:56:25.740 --> 00:56:30.770 align:middle line:84%
So fortunately,
music21 has some tools

00:56:30.770 --> 00:56:34.230 align:middle line:84%
to make a lot of these
things even easier here.

00:56:34.230 --> 00:56:37.460 align:middle line:84%
So music21 feature extraction
will be the last topic

00:56:37.460 --> 00:56:40.340 align:middle line:84%
that I'm going to
talk about today.

00:56:40.340 --> 00:56:43.700 align:middle line:84%
So we can go ahead and
import from music21

00:56:43.700 --> 00:56:45.063 align:middle line:90%
the features module.

00:56:45.063 --> 00:56:49.560 align:middle line:90%


00:56:49.560 --> 00:56:50.060 align:middle line:90%
Great.

00:56:50.060 --> 00:56:52.820 align:middle line:84%
So within the
features module, there

00:56:52.820 --> 00:56:55.050 align:middle line:90%
are things called DataSets.

00:56:55.050 --> 00:56:59.420 align:middle line:84%
So let's create
training_set, which

00:56:59.420 --> 00:57:05.990 align:middle line:84%
will be a DataSet with
a class label of is_jig.

00:57:05.990 --> 00:57:07.620 align:middle line:84%
We call it ground
truth or whatever.

00:57:07.620 --> 00:57:13.190 align:middle line:84%
And we'll create an identical
one for our test set.

00:57:13.190 --> 00:57:14.490 align:middle line:90%
Testing_set.

00:57:14.490 --> 00:57:15.050 align:middle line:90%
Great.

00:57:15.050 --> 00:57:17.650 align:middle line:84%
So these are just
things that are

00:57:17.650 --> 00:57:22.060 align:middle line:84%
ready to add two
important things.

00:57:22.060 --> 00:57:26.710 align:middle line:84%
A set of data that is streamed,
so a whole bunch of streams

00:57:26.710 --> 00:57:29.810 align:middle line:84%
will be added to both the
training and the test set,

00:57:29.810 --> 00:57:35.110 align:middle line:84%
and also a set of
feature extractors.

00:57:35.110 --> 00:57:39.070 align:middle line:84%
I'm not going to explain
today how to write new feature

00:57:39.070 --> 00:57:42.560 align:middle line:84%
extractors in the way
music 21 expects them,

00:57:42.560 --> 00:57:45.220 align:middle line:84%
but they're basically pretty
similar to what we've just

00:57:45.220 --> 00:57:47.230 align:middle line:84%
been writing with
functions, except they're

00:57:47.230 --> 00:57:50.380 align:middle line:90%
kind of expected to be classes.

00:57:50.380 --> 00:57:54.130 align:middle line:84%
But we don't really
have to because music21

00:57:54.130 --> 00:57:57.730 align:middle line:84%
has a whole bunch of
feature extractors.

00:57:57.730 --> 00:58:01.150 align:middle line:84%
Some of them come from
this amazing toolkit called

00:58:01.150 --> 00:58:03.850 align:middle line:84%
jSymbolic, or they're
re-interpretations

00:58:03.850 --> 00:58:08.810 align:middle line:84%
of Corey McKay's jSymbolic
toolkit, which is in Java,

00:58:08.810 --> 00:58:14.230 align:middle line:84%
and they have numbers like D1
is the overall dynamic range

00:58:14.230 --> 00:58:14.840 align:middle line:90%
features.

00:58:14.840 --> 00:58:17.460 align:middle line:84%
Not all of them have
been implemented

00:58:17.460 --> 00:58:20.410 align:middle line:90%
I's are instrument features.

00:58:20.410 --> 00:58:24.360 align:middle line:84%
You can probably see that the
percentage of all notes being

00:58:24.360 --> 00:58:28.480 align:middle line:84%
played by electric guitars, if
you know something about jigs,

00:58:28.480 --> 00:58:34.200 align:middle line:84%
is probably not going to be
very helpful to classifying

00:58:34.200 --> 00:58:36.400 align:middle line:84%
whether or not
something is a jig.

00:58:36.400 --> 00:58:39.600 align:middle line:84%
But maybe the average
melodic interval

00:58:39.600 --> 00:58:42.330 align:middle line:84%
will tell you something like
that, or how often there

00:58:42.330 --> 00:58:44.940 align:middle line:84%
are melodic thirds
or melodic fifths,

00:58:44.940 --> 00:58:47.620 align:middle line:84%
or maybe other things
might tell signs.

00:58:47.620 --> 00:58:52.530 align:middle line:84%
So these are melody features,
pitch features, and so on.

00:58:52.530 --> 00:58:53.806 align:middle line:90%
There's rhythm features.

00:58:53.806 --> 00:58:55.306 align:middle line:84%
That's going to be
pretty important.

00:58:55.306 --> 00:58:58.380 align:middle line:90%


00:58:58.380 --> 00:59:01.330 align:middle line:84%
R31, initial time
signature feature.

00:59:01.330 --> 00:59:07.030 align:middle line:84%
R32, compound or simple
meter features, and so on.

00:59:07.030 --> 00:59:10.800 align:middle line:84%
So we could add a bunch
of these features in,

00:59:10.800 --> 00:59:13.140 align:middle line:90%
and we remember the names.

00:59:13.140 --> 00:59:15.670 align:middle line:84%
Within the music21
documentation,

00:59:15.670 --> 00:59:18.030 align:middle line:84%
there will be
certain things that

00:59:18.030 --> 00:59:21.030 align:middle line:84%
will tell you
TripleMeterFeature set

00:59:21.030 --> 00:59:23.790 align:middle line:84%
to 1 if the numerator of
the initial time signature

00:59:23.790 --> 00:59:26.200 align:middle line:90%
is 3 or 0 otherwise.

00:59:26.200 --> 00:59:30.420 align:middle line:84%
And this shows you
how it can work.

00:59:30.420 --> 00:59:34.710 align:middle line:84%
So we can give a particular
piece and it will tell us that

00:59:34.710 --> 00:59:39.460 align:middle line:84%
bwv66.6 is 0, not
in triple meter.

00:59:39.460 --> 00:59:41.160 align:middle line:90%
OK.

00:59:41.160 --> 00:59:46.020 align:middle line:84%
We've already done something
really, really great.

00:59:46.020 --> 00:59:49.620 align:middle line:84%
And so I will tell you that if
we use this very similar feature

00:59:49.620 --> 00:59:51.580 align:middle line:84%
extractors to the
ones we did before,

00:59:51.580 --> 00:59:55.390 align:middle line:84%
we're going to get
the same results.

00:59:55.390 --> 00:59:57.030 align:middle line:84%
But one of the other
things we can do

00:59:57.030 --> 01:00:00.910 align:middle line:84%
is we can just use a whole
bunch of pretty random ones.

01:00:00.910 --> 01:00:07.170 align:middle line:84%
So we'll get these
features by ID.

01:00:07.170 --> 01:00:10.320 align:middle line:84%
And these are a bunch
of features that I used

01:00:10.320 --> 01:00:15.350 align:middle line:90%
to classify various pieces of--

01:00:15.350 --> 01:00:17.460 align:middle line:90%
I think it was 16th--

01:00:17.460 --> 01:00:18.590 align:middle line:90%
15th century music.

01:00:18.590 --> 01:00:20.340 align:middle line:90%
No, 16th century music.

01:00:20.340 --> 01:00:23.540 align:middle line:84%
So they're not
exactly super tuned

01:00:23.540 --> 01:00:26.420 align:middle line:90%
for what we're going to do.

01:00:26.420 --> 01:00:30.980 align:middle line:84%
A lot of them are melodic
features and so on.

01:00:30.980 --> 01:00:31.820 align:middle line:90%
Let me see.

01:00:31.820 --> 01:00:36.810 align:middle line:84%
Scroll over, see which ones
haven't done pitch features.

01:00:36.810 --> 01:00:44.940 align:middle line:84%
Pitch feature 8, 10,
rhythm feature 15.

01:00:44.940 --> 01:00:45.440 align:middle line:90%
Great.

01:00:45.440 --> 01:00:48.470 align:middle line:90%
And we can see what they are.

01:00:48.470 --> 01:00:50.780 align:middle line:84%
I'm already going to
tell you, no surprise,

01:00:50.780 --> 01:00:52.160 align:middle line:84%
these aren't going
to work nearly

01:00:52.160 --> 01:00:55.220 align:middle line:84%
as well as the
ones we just made.

01:00:55.220 --> 01:00:57.818 align:middle line:84%
Note density feature isn't
going to help us very much.

01:00:57.818 --> 01:00:59.360 align:middle line:84%
I would have thought
range might have

01:00:59.360 --> 01:01:02.330 align:middle line:84%
told us something about a
jig, but maybe it's not.

01:01:02.330 --> 01:01:04.610 align:middle line:84%
Some people will
tell you, hey, just

01:01:04.610 --> 01:01:07.970 align:middle line:84%
throw lots of feature
extractors in.

01:01:07.970 --> 01:01:09.330 align:middle line:90%
It can't hurt.

01:01:09.330 --> 01:01:10.590 align:middle line:90%
It kind of can.

01:01:10.590 --> 01:01:14.080 align:middle line:84%
But because we often don't
have enough data to make

01:01:14.080 --> 01:01:16.450 align:middle line:90%
use of all these features.

01:01:16.450 --> 01:01:17.900 align:middle line:90%
But let's give it a shot.

01:01:17.900 --> 01:01:25.150 align:middle line:84%
We're going to add these feature
extractors to our training set

01:01:25.150 --> 01:01:28.635 align:middle line:90%
and to our testing set.

01:01:28.635 --> 01:01:31.960 align:middle line:90%


01:01:31.960 --> 01:01:34.090 align:middle line:84%
OK, so our training
set and testing

01:01:34.090 --> 01:01:39.020 align:middle line:84%
set is now ready to go where
any stream we add to these sets,

01:01:39.020 --> 01:01:42.550 align:middle line:84%
we're going to have these
feature extractors added

01:01:42.550 --> 01:01:43.250 align:middle line:90%
to them.

01:01:43.250 --> 01:01:48.970 align:middle line:84%
So we'll say is for
i, add metadata_entry

01:01:48.970 --> 01:01:54.970 align:middle line:90%
in enumerate Ryan, again.

01:01:54.970 --> 01:01:58.960 align:middle line:84%
Piece_parsed equals
metadata_entry.parse.

01:01:58.960 --> 01:02:02.650 align:middle line:90%


01:02:02.650 --> 01:02:10.960 align:middle line:84%
If i is odd, then
training or test will be--

01:02:10.960 --> 01:02:12.780 align:middle line:84%
so we only have to
write things once,

01:02:12.780 --> 01:02:14.530 align:middle line:84%
we'll set our training
or test set will be

01:02:14.530 --> 01:02:16.310 align:middle line:90%
the training set in this case.

01:02:16.310 --> 01:02:22.570 align:middle line:84%
Otherwise our training or
test will be our testing set.

01:02:22.570 --> 01:02:24.010 align:middle line:90%
Great.

01:02:24.010 --> 01:02:24.970 align:middle line:90%
Filename.

01:02:24.970 --> 01:02:27.560 align:middle line:90%
Is the piece parsed?

01:02:27.560 --> 01:02:30.610 align:middle line:90%
FilePath.name.

01:02:30.610 --> 01:02:31.790 align:middle line:90%
Is_jig.

01:02:31.790 --> 01:02:34.870 align:middle line:90%
Same thing we're doing before.

01:02:34.870 --> 01:02:36.730 align:middle line:90%
Here we're not going to--

01:02:36.730 --> 01:02:38.300 align:middle line:90%
music21 smart enough.

01:02:38.300 --> 01:02:40.940 align:middle line:84%
It doesn't need us to
cast this to an integer.

01:02:40.940 --> 01:02:43.160 align:middle line:84%
It'll figure out
what to do itself.

01:02:43.160 --> 01:02:45.580 align:middle line:90%
OK.

01:02:45.580 --> 01:02:48.340 align:middle line:84%
I'm going to say what row
are we, is this a jig,

01:02:48.340 --> 01:02:49.970 align:middle line:90%
and what's its filename.

01:02:49.970 --> 01:02:51.200 align:middle line:90%
That's easy part.

01:02:51.200 --> 01:02:54.280 align:middle line:84%
And then whatever data
set we're working with,

01:02:54.280 --> 01:02:59.070 align:middle line:84%
training or test, we're
going to add the data from--

01:02:59.070 --> 01:03:01.430 align:middle line:90%
here's our stream, our score.

01:03:01.430 --> 01:03:02.450 align:middle line:90%
What did we call it?

01:03:02.450 --> 01:03:03.590 align:middle line:90%
ClassValue.

01:03:03.590 --> 01:03:05.930 align:middle line:90%
What is the right answer?

01:03:05.930 --> 01:03:08.620 align:middle line:84%
It's whether or
not this is a jig.

01:03:08.620 --> 01:03:13.290 align:middle line:84%
And then the identification
for this will be the filename.

01:03:13.290 --> 01:03:14.260 align:middle line:90%
Boom.

01:03:14.260 --> 01:03:15.550 align:middle line:90%
It's going to go through.

01:03:15.550 --> 01:03:20.460 align:middle line:84%
It has 1,000 of these to run,
so I'm not going to wait for all

01:03:20.460 --> 01:03:23.140 align:middle line:90%
of it to happen.

01:03:23.140 --> 01:03:27.690 align:middle line:84%
I'm going to stop for a
second because we don't have

01:03:27.690 --> 01:03:29.610 align:middle line:90%
all that time in the world.

01:03:29.610 --> 01:03:31.230 align:middle line:84%
That's part of the
reason why we also

01:03:31.230 --> 01:03:33.330 align:middle line:90%
don't want to do everything.

01:03:33.330 --> 01:03:36.460 align:middle line:84%
But that small training
set, we're going to process,

01:03:36.460 --> 01:03:39.360 align:middle line:84%
and we're going to
take that training set

01:03:39.360 --> 01:03:44.280 align:middle line:90%
and write it out to train2.tab.

01:03:44.280 --> 01:03:45.240 align:middle line:90%
No, we're not.

01:03:45.240 --> 01:03:48.040 align:middle line:84%
You should do that because
you have time to wait.

01:03:48.040 --> 01:03:50.230 align:middle line:90%
But nobody wants to do that.

01:03:50.230 --> 01:03:53.130 align:middle line:84%
We'll do the same thing
with the testing_set.process

01:03:53.130 --> 01:03:55.830 align:middle line:90%
and the testing_set.

01:03:55.830 --> 01:04:00.100 align:middle line:84%
We're going to write
that to test2.tab.

01:04:00.100 --> 01:04:02.430 align:middle line:84%
I'm not doing that
right now because they

01:04:02.430 --> 01:04:07.010 align:middle line:84%
do in those old cooking shows,
I've already done all this

01:04:07.010 --> 01:04:11.730 align:middle line:84%
and I'm going to load it
from what I've already done.

01:04:11.730 --> 01:04:15.320 align:middle line:90%
So you know what I mean.

01:04:15.320 --> 01:04:16.820 align:middle line:84%
The old cooking
shows where they put

01:04:16.820 --> 01:04:20.460 align:middle line:84%
they put the raw
turkey in the oven,

01:04:20.460 --> 01:04:24.290 align:middle line:84%
and then they just immediately
go to the other oven

01:04:24.290 --> 01:04:25.610 align:middle line:90%
and the turkey--

01:04:25.610 --> 01:04:26.160 align:middle line:90%
sorry.

01:04:26.160 --> 01:04:29.160 align:middle line:84%
I you all can read
my mind, right?

01:04:29.160 --> 01:04:32.070 align:middle line:90%


01:04:32.070 --> 01:04:35.370 align:middle line:84%
That's what you pay me to
do, make you read my mind,

01:04:35.370 --> 01:04:38.060 align:middle line:90%
not actually teach.

01:04:38.060 --> 01:04:39.740 align:middle line:90%
That's fantastic.

01:04:39.740 --> 01:04:40.990 align:middle line:90%
OK.

01:04:40.990 --> 01:04:41.490 align:middle line:90%
Yeah.

01:04:41.490 --> 01:04:42.180 align:middle line:90%
Anal enough.

01:04:42.180 --> 01:04:48.650 align:middle line:84%
I'll make this line up so
I don't make any typos.

01:04:48.650 --> 01:04:50.930 align:middle line:90%
It's on my desktop.

01:04:50.930 --> 01:04:53.070 align:middle line:90%
Test2.tab.

01:04:53.070 --> 01:04:54.260 align:middle line:90%
That's why it broke.

01:04:54.260 --> 01:04:55.200 align:middle line:90%
OK.

01:04:55.200 --> 01:04:58.610 align:middle line:84%
So again, we're going to
do everything as before.

01:04:58.610 --> 01:05:04.960 align:middle line:84%
Why do everything as before when
you can just copy and paste.

01:05:04.960 --> 01:05:09.940 align:middle line:84%
Because now we've already
written everything out for--

01:05:09.940 --> 01:05:12.820 align:middle line:84%
yeah, this whole
process and write thing

01:05:12.820 --> 01:05:16.936 align:middle line:84%
takes care of everything
we did before where we--

01:05:16.936 --> 01:05:18.070 align:middle line:90%
where is that?

01:05:18.070 --> 01:05:19.810 align:middle line:90%
Where we had to define--

01:05:19.810 --> 01:05:23.600 align:middle line:84%
we had to open our datas, we
had to define our columns,

01:05:23.600 --> 01:05:26.120 align:middle line:84%
we had to write that out,
define our descriptions,

01:05:26.120 --> 01:05:29.980 align:middle line:84%
write out all our meta things,
extract what our feature

01:05:29.980 --> 01:05:35.290 align:middle line:84%
extractors do, all that stuff
of these little process,

01:05:35.290 --> 01:05:38.390 align:middle line:84%
and then write did
all that for us.

01:05:38.390 --> 01:05:47.010 align:middle line:84%
So now we're actually back onto
feature extraction is done.

01:05:47.010 --> 01:05:49.570 align:middle line:90%


01:05:49.570 --> 01:05:53.800 align:middle line:90%
Let's do machine learning.

01:05:53.800 --> 01:05:56.260 align:middle line:84%
Anybody who tells you that
the machine learning is

01:05:56.260 --> 01:05:59.830 align:middle line:84%
the only hard part and
that feature extraction is

01:05:59.830 --> 01:06:04.150 align:middle line:84%
easy stuff is lying to you
or doesn't know what they're

01:06:04.150 --> 01:06:09.160 align:middle line:84%
talking about or whatever
because feature extraction

01:06:09.160 --> 01:06:12.555 align:middle line:84%
and doing it right is
really, really hard.

01:06:12.555 --> 01:06:16.300 align:middle line:84%
So we're going to basically
copy and paste everything

01:06:16.300 --> 01:06:21.130 align:middle line:90%
that we did before.

01:06:21.130 --> 01:06:22.030 align:middle line:90%
Totals.

01:06:22.030 --> 01:06:24.850 align:middle line:90%
Something like that.

01:06:24.850 --> 01:06:25.540 align:middle line:90%
Great.

01:06:25.540 --> 01:06:30.070 align:middle line:84%
We're going to run
this again and then

01:06:30.070 --> 01:06:37.540 align:middle line:84%
we're going to print
everything afterwards.

01:06:37.540 --> 01:06:38.380 align:middle line:90%
Great.

01:06:38.380 --> 01:06:42.400 align:middle line:84%
And that's going to
go through and it's

01:06:42.400 --> 01:06:44.740 align:middle line:90%
going to print a couple things.

01:06:44.740 --> 01:06:45.450 align:middle line:90%
How are we doing?

01:06:45.450 --> 01:06:49.250 align:middle line:90%


01:06:49.250 --> 01:06:53.510 align:middle line:84%
We've given it a lot more things
to train on, so a lot more data.

01:06:53.510 --> 01:06:55.180 align:middle line:84%
These are much
bigger files because

01:06:55.180 --> 01:06:58.580 align:middle line:84%
of all the different feature
extractors, so it takes a while.

01:06:58.580 --> 01:07:04.980 align:middle line:84%
You can see in all this
time, it's just done one row.

01:07:04.980 --> 01:07:05.800 align:middle line:90%
Two rows.

01:07:05.800 --> 01:07:07.023 align:middle line:90%
Are we going to wait for--

01:07:07.023 --> 01:07:09.750 align:middle line:90%


01:07:09.750 --> 01:07:13.320 align:middle line:84%
I think it's, like,
an hour and a half.

01:07:13.320 --> 01:07:15.130 align:middle line:84%
I ran this at 2:00
in the morning.

01:07:15.130 --> 01:07:17.640 align:middle line:84%
Are we going to wait
an hour and a half?

01:07:17.640 --> 01:07:18.520 align:middle line:90%
We can all do that.

01:07:18.520 --> 01:07:19.053 align:middle line:90%
No.

01:07:19.053 --> 01:07:21.220 align:middle line:84%
I'm going to hit Stop for
a second on the recording,

01:07:21.220 --> 01:07:24.990 align:middle line:84%
and then I'm going to
load up our results.

01:07:24.990 --> 01:07:25.690 align:middle line:90%
OK.

01:07:25.690 --> 01:07:28.500 align:middle line:90%
Here are the results I got.

01:07:28.500 --> 01:07:31.810 align:middle line:84%
Again, our majority
learner got 77% right.

01:07:31.810 --> 01:07:35.970 align:middle line:84%
And our k nearest neighbors
super intelligent artificial

01:07:35.970 --> 01:07:40.235 align:middle line:90%
intelligence only got 4% better.

01:07:40.235 --> 01:07:41.610 align:middle line:84%
I mean, I don't
even know if that

01:07:41.610 --> 01:07:44.950 align:middle line:84%
meets the margin of error in
a political poll or something.

01:07:44.950 --> 01:07:49.990 align:middle line:84%
So all that extra time didn't
actually improve anything.

01:07:49.990 --> 01:07:54.330 align:middle line:84%
What's important is
always to choose your--

01:07:54.330 --> 01:07:57.940 align:middle line:84%
choose your feature
extractors well.

01:07:57.940 --> 01:08:03.560 align:middle line:84%
The fact that I didn't include
that one simple extractor

01:08:03.560 --> 01:08:07.620 align:middle line:84%
about the time signature made
all the difference in the world,

01:08:07.620 --> 01:08:09.350 align:middle line:90%
I think.

01:08:09.350 --> 01:08:10.070 align:middle line:90%
OK.

01:08:10.070 --> 01:08:14.870 align:middle line:84%
I just want to show
that you can print

01:08:14.870 --> 01:08:18.260 align:middle line:84%
all of the different features
onto various charts and zoom in

01:08:18.260 --> 01:08:21.029 align:middle line:84%
and stuff like that if
people want to do that.

01:08:21.029 --> 01:08:24.140 align:middle line:84%
But that'll be something
for another time.

01:08:24.140 --> 01:08:27.859 align:middle line:84%
This is what is
available to you now.

01:08:27.859 --> 01:08:30.450 align:middle line:84%
Maybe not this kind
of low level one,

01:08:30.450 --> 01:08:35.810 align:middle line:84%
but using these feature
extractors, simple ones

01:08:35.810 --> 01:08:39.229 align:middle line:90%
like sharps and meter and--

01:08:39.229 --> 01:08:39.830 align:middle line:90%
what was that?

01:08:39.830 --> 01:08:43.649 align:middle line:84%
Percentage of compound
time, range features,

01:08:43.649 --> 01:08:47.359 align:middle line:84%
things like that, in
order to classify pieces

01:08:47.359 --> 01:08:49.800 align:middle line:90%
is incredibly powerful.

01:08:49.800 --> 01:08:53.090 align:middle line:84%
And when put together
with the right machine

01:08:53.090 --> 01:08:56.370 align:middle line:84%
learning and artificial
intelligence algorithm,

01:08:56.370 --> 01:08:59.109 align:middle line:84%
there's a lot of
possibilities for the future

01:08:59.109 --> 01:09:03.970 align:middle line:90%
of computational music analysis.

01:09:03.970 --> 01:09:07.279 align:middle line:84%
This lecture has run
pretty darn long,

01:09:07.279 --> 01:09:12.933 align:middle line:84%
so I'm going to say for a
second little supplement on what

01:09:12.933 --> 01:09:14.350 align:middle line:84%
are some of the
things that I have

01:09:14.350 --> 01:09:18.700 align:middle line:84%
learned through using
computational artificial

01:09:18.700 --> 01:09:19.760 align:middle line:90%
intelligence?

01:09:19.760 --> 01:09:23.020 align:middle line:84%
What are some of the projects
other people have done,

01:09:23.020 --> 01:09:29.060 align:middle line:84%
and why the world state of the
art black box deep learning

01:09:29.060 --> 01:09:31.870 align:middle line:84%
or other sophisticated
algorithms

01:09:31.870 --> 01:09:34.960 align:middle line:84%
might not always be the
best ones that we want

01:09:34.960 --> 01:09:37.960 align:middle line:84%
to use when we're doing
artificial intelligence

01:09:37.960 --> 01:09:42.800 align:middle line:84%
and machine learning
techniques on musical scores.

01:09:42.800 --> 01:09:44.720 align:middle line:84%
But we'll leave that
for another time.

01:09:44.720 --> 01:09:46.760 align:middle line:90%
Thank you so much for listening.

01:09:46.760 --> 01:09:49.819 align:middle line:84%
Go ahead and play around
with some data sets.

01:09:49.819 --> 01:09:52.420 align:middle line:84%
You've learned how to
use corpus search to be

01:09:52.420 --> 01:09:55.240 align:middle line:90%
able to find various pieces.

01:09:55.240 --> 01:10:00.580 align:middle line:84%
there's a music21, I
think user's guide chapter

01:10:00.580 --> 01:10:04.130 align:middle line:84%
and tutorial on how to do more
interesting things with that.

01:10:04.130 --> 01:10:08.020 align:middle line:84%
There's the paper written with
Chris Ariza and Lisa Friedland

01:10:08.020 --> 01:10:11.540 align:middle line:84%
on using feature
extractors with music21.

01:10:11.540 --> 01:10:16.870 align:middle line:84%
And there's also some other
music21 feature extractor papers

01:10:16.870 --> 01:10:20.770 align:middle line:84%
that were written with MIT
undergraduate UROPs on how

01:10:20.770 --> 01:10:24.340 align:middle line:84%
we can use feature extraction
to go beyond what we can do

01:10:24.340 --> 01:10:28.540 align:middle line:84%
with midi, to really look at
the nuance of musical scores

01:10:28.540 --> 01:10:30.080 align:middle line:90%
in feature extraction.

01:10:30.080 --> 01:10:31.880 align:middle line:84%
I'll be sending
all those around.

01:10:31.880 --> 01:10:36.370 align:middle line:84%
The meantime, please go back
through the most interesting

01:10:36.370 --> 01:10:40.540 align:middle line:84%
parts of this lecture to you,
hit pause, and play around

01:10:40.540 --> 01:10:42.850 align:middle line:90%
with your own data sets.

01:10:42.850 --> 01:10:48.270 align:middle line:84%
Good luck in applying
this to future projects.

01:10:48.270 --> 01:10:54.000 align:middle line:90%