COLTON OGDEN: All right.
Hello world.
This is CS50 on Twitch,
and today we're joined
by CS50's Nick Wong, who's
been a teaching fellow here
for a couple of years.
And today he's going to teach-- oh,
what are you going to teach us today?
What are we going to talk about?
NICK WONG: So we're going to be
talking about binary classifiers
using TensorFlow and Keras.
And so TensorFlow was actually a project
that was developed and built by Google.
And Google has their
hands in everything,
but TensorFlow is really cool
because it basically took
the whole linear algebra-ness of machine
learning and made it very simple.
And then Keras is a wrapper
on top of TensorFlow
that actually made even that
simplification a little bit simpler.
COLTON OGDEN: Let's transition to your
awesome little screensaver back here.
Yeah, so like an introduction to machine
learning using some nice open source
libraries, some Google base-- is Keras
a Google open source library as well?
NICK WONG: I believe so, yeah.
COLTON OGDEN: OK.
TensorFlow-- I know everyone's heard
of TensorFlow, or at least a lot of us
have.
I know almost nothing
about machine learning,
so this will be a learning
experience for me as well,
but I'm super excited to talk about
binary classifiers and what they are.
NICK WONG: Awesome.
So yeah, I'll talk a little
bit about the theory first.
I won't talk too much on theory.
I know people aren't usually huge fans.
I like the theory, I
think it's really cool,
but we're going to just
talk about it a little bit
to motivate and contextualize
what I'm actually going to start
saying and coding in front of you.
Before I do that, I just wanted
to point out this screen saver
that I've got going on here.
I think it's super cool.
I'm a huge fan.
It's technically CMatrix.
That's the actual
program that's running.
But I put that through
another program called
lolcat, which is one of my
favorite "messing with people"
or troll programs.
If you're ever trying
to mess with someone,
you can display lolcat and
stuff through a screen.
COLTON OGDEN: We'll have a separate
stream on how to troll people,
how to hack into a--
NICK WONG: One of my favorite things.
COLTON OGDEN: And this
screensaver is in a shell, right?
NICK WONG: Right.
So this is in a shell.
If I press any key, then
I'm back in my shell,
and I can go back to coding and
doing all sorts of cool things.
But I like having it there.
It's entertaining.
It just drains power, so
you want to be plugged in.
COLTON OGDEN: We have a few
comments in the chat there.
MKLOPPENBURG says, "Hey everybody."
BELLA_KIRS says, "Hello."
WHIPSTREAK, BELLA, and I
can't read that last one.
NICK WONG: Yeah, it's hard to read.
COLTON OGDEN: It looks like ILYAS.
They all say, Hi, Nick.
NICK WONG: Oh, awesome.
Hello guys.
Appreciate it.
Very happy to be here.
COLTON OGDEN: We have a lively chat, so
we'll definitely read off the messages
as we get them in the chat.
NICK WONG: Sweet.
All right.
So machine learning.
It's one of my favorite buzzwords
that everyone throws around,
along with like blockchain, AI--
what are some other ones?
There are some really
good ones out there.
Bitcoin people that are out there.
COLTON OGDEN: Yeah, blockchain.
They've been massively--
yeah, those last couple years.
NICK WONG: Everyone keeps throwing
them out there, and they're all great.
And so I think one of the things
that I heard this last summer where
I was working, someone said that machine
learning is just fancy statistics
wrapped up in a computer.
And I was like, yeah, not really.
Like in concept, yes, but
not necessarily in what
they actually intended.
What they were meaning
is, like, you could just
use statistics to do the same thing.
And when I was walking through
our science center today,
I was looking at the old
punch card style computers.
And I was like, yeah, technically
I can run statistics on that too,
but it's different.
The game has changed a little bit
given our computing power, our memory,
and things like that.
COLTON OGDEN: Little bit
apples and oranges type deal.
NICK WONG: Yeah.
It's just like, yeah, you're not
wrong really, but you're pretty off.
And so machine learning is
just a very broad field.
It really means just
any way in which you
get a computer to figure things out.
And a lot of it's modeled
after how humans learn.
So we-- well, in concept.
It's modeled after the way
our brains are structured.
So a lot of things are called neurons.
So you hear a lot of just
jargon that gets thrown out.
You'll hear, like, tensors, neurons,
layers, models, things like that.
COLTON OGDEN: I've heard,
like, neural nets, for example.
NICK WONG: Right, neural network.
And those sorts of things
can be very intimidating,
but they generally have
very well grounded meanings.
So for example, a neural net, that
just means that, like our brain,
they took a bunch of individual nodes
and they linked them all together,
and that's all that it
really ends up meaning.
Now, there's some nuance to
that there's some complexity,
but in concept, it's actually
pretty straightforward.
So what we're going to
do is we are technically
going to build a neural network today.
COLTON OGDEN: That's cool.
NICK WONG: It is what is
required for-- or not required,
but it's what we're going to use
for the binary classification.
And that brings us to what
binary classifiers are,
which is if you have
a bunch of data, can I
tell you if it's in one of two groups?
So it's either going to
be group A or group B.
And that can mean all
sorts of things for us.
COLTON OGDEN: So if we're looking at
pictures of apples versus pictures
of oranges, what's an apple--
NICK WONG: Is it an apple or an orange?
COLTON OGDEN: --what's an orange?
By the way, DARKSLAYERX says,
"How often do you stream?"
So we typically stream, as
of the last couple of weeks,
this is a fairly new thing,
but usually four days a week,
so Monday, Tuesday, Wednesday, Friday.
Thursday is a little bit of a
busy day right now for CS50.
We're shooting CS50 seminars.
You're doing a seminar, right?
NICK WONG: Yep.
I will be also doing a seminar.
COLTON OGDEN: Do you
know what it is on yet?
NICK WONG: It'll be on web
development with Python and Django.
COLTON OGDEN: OK, awesome.
NICK WONG: It's a completely different--
COLTON OGDEN: Completely unrelated.
NICK WONG: They're not even related.
COLTON OGDEN: But yeah,
pretty frequently.
Our goal is to do this roughly
three to four times per week.
It looks like WHIPSTREAK also tossed
in that's it on the CS50 Facebook page.
Yes, it is on the CS50
Facebook page most definitely.
NICK WONG: The human equivalent
of check demand page.
COLTON OGDEN: Yeah, yeah.
Yeah, basically.
NICK WONG: One of my favorite responses.
That's awesome.
COLTON OGDEN:
MKLOPPENBURG-- Django rocks.
NICK WONG: Yes, I agree.
And we use I guess
Flask and-- what is it?
Flask, Jijnja2, and MySQL in
CS50, and I'm a huge fan of Django
which kind of wraps that all together.
But today, we'll be just
using Python and we're
going to talk about [INAUDIBLE] stuff.
COLTON OGDEN: Separate stream.
We'll do a separate
Django stream for it.
NICK WONG: Yeah, completely different.
Yeah, exactly.
COLTON OGDEN: By the way, you
will be doing another stream--
NICK WONG: Yes.
COLTON OGDEN: --coming
up on Linux commands.
So Nick will do-- if
anybody is curious on how
he got his awesome show
operating this way,
we'll dive into the basics of how that
works with the basic Linux commands.
NICK WONG: Yeah.
That's next Friday, right?
COLTON OGDEN: Yeah, next Friday.
NICK WONG: Sweet.
Yeah.
So feel free to tune into
that if you think this is cool
or if you want to
learn more about Linux.
All right.
So we have binary classifiers.
We're just separating
things into two categories.
And that sounds like an intuitive thing.
If I show you a picture of a
square and a picture of a triangle,
you'll know that one
is not like the other.
But for machines, that
can be really complex.
And actually, the theory underneath
that seems very difficult.
And so machines, early on, that
was one of the easiest problems
that they could try and tackle solving.
And it's still hard.
It's not an easy problem,
but it is one of the easiest.
COLTON OGDEN: Identifying basically
simple shapes, those sort of things?
NICK WONG: Right.
Can I just say, is this this or not?
So is it a shape or not?
Is it dark or not?
And so what we're going
to actually start with--
and for you guys, I actually
started a GitHub repository
that you guys are welcome to
kind of pull code from as we go--
COLTON OGDEN: Oh, do you want to--
NICK WONG: --which we might
want to bring that up.
COLTON OGDEN: --let me know what
that is and I'll type it into chat?
NICK WONG: Yeah.
So it's at
GitHub.com/powerhouseofthecell--
COLTON OGDEN: Let me get the--
Sorry, I can't read it too well.
Powerhouse.
Oh, you're right.
Yeah.
Literally--
NICK WONG: Literally powerhouse.
COLTON OGDEN: You changed your Twitch
handle a little bit from last time.
NICK WONG: Yeah, I had to
change that, unfortunately.
COLTON OGDEN: Is_it_real.
NICK WONG: Yeah, exactly.
So our eventual goal for today,
what we will get to by the end,
is given pictures of cartoon people
versus real pictures, like a portrait,
can we distinguish which one is real?
COLTON OGDEN: That's an interesting--
NICK WONG: Can I tell us-- is
something cartoon or is it not?
And the reason I thought
that was really cool
is there is no necessarily
apparent programmatic way
to distinguish the two.
You can't tell based on color.
You can't necessarily tell based
on orientation or type of shape.
Maybe for really bad approximations
in cartoon structure,
you could maybe guess at that, but
even then, that might not be true.
COLTON OGDEN: I was going to say, if
I were to take an initial stab at this
completely naively, I would probably
build the cartoon classifier and then
work my way up to real humans
because I feel like that's--
it's almost a simplification
or an abstraction of that.
NICK WONG: Right, exactly.
And so that's what my point was, is
that even given very limited tools--
we have basically no theory
that we've talked about.
We don't have to talk about likelihood
maximization or any sort of summation
notation, none of that.
We can still do that.
We can get really high accuracies
with pretty minimal tools.
And they're all open source.
They're all available
anywhere you want to go.
So I think that's really cool.
And I think when I was beginning CS,
that was super inspiring to me, so I
like sharing that with people.
COLTON OGDEN: Cool.
NICK WONG: We're also going to use
a third library I forgot to mention.
It's called OpenCV or
Open Computer Vision.
I think it was UC Irvine's project.
And I actually used
that my freshman year,
but I've used it ever
since because it is
one of the primary libraries
for reading images,
for just pulling them in and
doing something like that.
But the problem with OpenCV is they
update their documentation possibly
less consistently than
college kids go to sleep.
It's so all over the place.
It does say MIT license.
Sorry.
To respond with WHIPSTREAK's question,
which is, is it an MIT license?
I'm in my GitHub.
Why?
Isn't this Harvard?
MIT license is actually
kind of a broad license.
It's generally used for
personal projects or projects
that you want to be able
to share it with the world
but you do want them to acknowledge you
or just reference the fact that it's
not necessarily theirs.
It's one of my favorite
licenses to use on GitHub.
Another common one that you might
see is the GNU license as well as
the Apache license.
Those two or those three
are pretty well-known.
And then there's a bunch
of other license options
that I don't understand super well.
COLTON OGDEN: And then
FERNANDO also says, "Hi."
Hi, Fernando.
NICK WONG: Hey, Fernando.
COLTON OGDEN: Thanks
for joining us today.
NICK WONG: Awesome.
So we're going to get going a little bit
on our environment and what we're doing
and how we actually go.
So I'm in Bash.
This is my command prompt.
I just like the color blue a lot.
Ironically, I'm wearing
red, but that's OK.
And so this is my Bash prompt.
If you're not super familiar with
Bash or Linux shell, don't worry.
I might refer to with a couple of words
like terminal, console, Bash, shell.
They all mean the same thing.
I just mean here.
I can type stuff ls, which has
all sorts of stuff on there.
I'm a mess.
I can do ps to see what's
actually running-- very little.
There's a bunch of other commands,
and we'll go into them next Friday.
But what I'm going to do is I
actually have a technology called
Virtualenvwrapper,
and what that means is
I can basically create these
separate little Python modules,
Python environments for myself.
And so that means that if I have some
projects that uses Python 2.5 and then
my current project uses Python 3.7
because I'm not in the 20th century--
sorry, I like to jab
at the old Pythons--
then I can separate
everything out and not
worry about colliding dependencies
or colliding version numbers.
I can keep everything very clean.
COLTON OGDEN: Or even two
versions of the same library.
NICK WONG: Exactly, which
would be-- that is the worst.
I have done that many
times, and it's awful.
So we're going to call
that, this version.
Is_it_real.
It'll match with my GitHub, and
I'll try to be very consistent.
And you'll see that when
I run this mkvirtualenv,
but I'm not really
necessarily going to go into.
There are a lot of tutorials online
on how to install Virtualenvwrapper.
That is what I'm using, though.
And it takes a little bit to go,
but it creates all these ways for me
to actually interact with
Python in an isolated place.
And you'll notice that, over
here, it puts a little--
it prepends a part to
my prompt that says
that I'm in that virtual
environment at any one time.
So I can leave it by
just saying, deactivate,
just for those of you
that are gone, and then I
can work on it using this command.
Cool.
So I'm also going to
create a folder for this.
I normally would have done
some make directory or mkdir,
but I'm actually going to
just go into the one that I--
oops.
It's called is_it_real.
My apologies.
I'm going to go into one that I already
created just because already cloned
my GitHub repository.
If you cloned it, then you'll actually
end up being in a place like this,
and you'll have these
two files in there--
just the readme and the license.
We are literally creating
this from scratch.
COLTON OGDEN: That's
the best way to do it.
NICK WONG: So I apologize if
we have some syntax errors.
You'll get to see some
really live debugging.
COLTON OGDEN: We've had plenty of
that on the ones that I've done, so--
NICK WONG: That's good to hear, because
there's going to be plenty on my end.
All right, cool.
So we're in a Python
virtual environment,
and we need to pick up
a bunch of packages.
So we're going to do that live
too, which never goes well.
I've never had this code
correct on the first go.
So we're going to pick up some kind
of maybe not conventional ones,
or they aren't the names of the packages
that I said at the very beginning.
We're picking NumPy and SciPy.
And those are very common.
Machine learning, any
sort of numbers or data
analysis-- you're going
to usually see those.
NumPy or NumPy makes things
very fast generally speaking,
and it's going to give you a
bunch operations with numbers.
I'm going to actually let
this run while I talk.
Oh good, they're cached.
Thank god.
They're kind of large, so
they're kind of a pain.
And then SciPy is a bunch
of science-like tools.
So if you're analyzing
data, it's really useful.
COLTON OGDEN: It's
literally In the name--
SciPy.
NICK WONG: Yeah.
It's always like Python
is super intuitive.
It's meant to be user friendly.
The next thing that
we're going to grab--
and I always forget what it's called.
I think it's opencv-python.
Their package name is not super
intuitive because the package itself
when you import it-- thank god--
is called cv2.
However, we're using cv3.
And it's still called
cv2, so there's that.
And you download it as
opencv-python, which is absurd.
So I don't really like their
naming scheme, but that's OK.
COLTON OGDEN: WHIPSTREAK says, "Nick
and Colton are acting like best friends.
Are they?"
We're definitely good friends.
NICK WONG: We are very good friends.
COLTON OGDEN: We taught a
games course together actually,
so we do have a little
bit of history here.
NICK WONG: Yeah.
Colton's awesome.
I actually got to watch him
full powerhouse last year
teaching his course that he went
and did the whole nine yards on.
I was just there for the ride.
It was very cool.
COLTON OGDEN: We flipped the
situation around a little bit,
so now you are teaching
and I am observing.
NICK WONG: I appreciate it.
COLTON OGDEN: It's fun.
It all comes around.
TWITCHHELLOWORLD-- "I don't
see the Livestream video.
Is everyone seeing a Livestream video?"
The video should definitely be up.
I see it on my Twitch.
Definitely refresh the page
and see if that fixes it.
NICK WONG: Very possible.
COLTON OGDEN: Astly, who's
NUWANA333, says, "Hi everyone.
Yes TWITCHHELLOWORLD."
Good to see you, Astly.
But yeah, if you have any issues,
definitely refresh the page.
I'm seeing it live, and It
looks like everyone else
is seeing it live as well.
NICK WONG: Yeah, good luck.
Debugging browser stuff is one
of my least favorite tasks.
It's why I work in Python.
All right.
So let's see.
We've picked up NumPy, SciPy, opencv.
We also need Pillow, which is not an
intuitive package that you would want.
It's capitalized too, so just in case
you encounter some weird errors there.
And Pillow, it's the-- what is it?
Python image library.
So that translates to PIL.
They call it Pillow and it's
capitalized, but when you import it,
you don't.
You don't import Pillow anywhere really.
Some of these packages
are kind of absurd.
So then, we're also going
to install the stars
of our show, which are TensorFlow--
so shout out to Google for making
that accessible to everybody--
and Keras, which is a
wrapper on top of TensorFlow.
It makes it a little bit higher level.
It's a little bit
easier to interact with.
And that way, you're not dealing
with as much terminology,
so you're not sitting there
being like, what's a tensor?
What are the dimensions?
And all these things.
Keras takes care of that.
COLTON OGDEN: Shout out to also how easy
it is to install all these packages.
That's probably why
Python is so successful.
NICK WONG: Gotta love Python.
I am a huge fan of Python.
I think Colton is too.
Python is just very well done.
You're seeing maybe a different output
than you might see on your screen
because I have used these
packages pretty extensively,
so they're all cached on my machine.
It just means that
they've been saved before.
And you'll see some bars that go
across, and that should be correct.
Cool.
So we've downloaded all of our packages.
If we wanted to test that out,
we could go into the Python REPL
by just typing Python and say,
like, "import tenserflow,"
and that should not fail.
That would suck if it did it.
And maybe "from keras.models
import--" that might-- yeah,
I think that was probably
right. "import Model"
I'm also going to assume
a lot of Python syntax,
so if you have any questions,
feel free to post it in the chat
and we'll be happy to answer it.
And so yeah, we have both terrace--
sorry-- TensorFlow and Keras.
And then the last one that we want
to double check that we have is cv2.
COLTON OGDEN: It looks
like Keras even has
a implicit dependency on TensorFlow--
NICK WONG: Yes.
COLTON OGDEN: --it looks
like with that line there.
NICK WONG: Yeah, exactly.
So actually, Keras has this thing.
I think most people use
TensorFlow now underneath it.
It's kind of the back end for it.
But it can also use Theano or Theano,
which is a different machine learning
background or back end.
It's very cool, also very powerful.
I just happen to use TensorFlow.
So you can use either one.
We're going to just talk
about TensorFlow though.
Cool.
So we can exit out of
that with Control-D
or by typing in the word
"exit" and parentheses.
And now we're going to actually
start creating some code
or writing some code.
So what I'm going to do
is, generally speaking,
I like to separate things out and be
very modular and have good practices.
But when I first go through stuff,
I just want to get it working.
I just want things to
actually function correctly.
So we're going to write a
monolithic style for this,
meaning that, basically,
we're going to--
and actually, I'm going
to just touch this.
Oops.
I can't spell.
I can never spell live.
And we're going to just touch run.pi.
I like calling it run.py.
It indicates what I'm
going to do with it.
I'm going to run it.
And so that makes things a
little bit easier on ourselves,
and it'll be a little
bit easier to follow so
that we're not flipping between
files all over the place.
However, I also don't exactly
love typing in just Bash
and using nano for everything.
So we're going to use
Visual Studio Code.
It's one of my favorite IDEs.
A completely different
team was behind it.
I think mostly different team
was behind it at Microsoft
then the team behind Visual Studio.
So if you have any kind of
group with Visual Studio, one,
they've revamped it a lot, but
two, it's very different from VSC.
And VSC is super customizable.
It has a lot of nice plugins.
COLTON OGDEN: Big fan of it myself.
NICK WONG: Yeah, which is nice.
COLTON OGDEN: We have a
couple comments there.
Looks like WHIPSTREAK says, "What is the
machine learning program's objective?"
NICK WONG: Ah.
OK, right.
I didn't actually it.
I mentioned it to Colton right
beforehand and then didn't actually,
I think, say it.
So we're going to be going over--
basically, the end goal is to see if
we can distinguish, given an image,
if it's a cartoon image
or a real-life one.
And we're going to focus
on images of people
because that makes it a
little bit easier for us.
But that's going to be the end goal.
We're going to start
with a little bit easier
of a task, which is
distinguishing whether or not
an image is dark or
light, because I think
that that conceptually is a little
bit easier for us to understand.
There is a way for us
to figure that out.
I think you could, maybe upon
thinking about it for a little bit,
come up with a program that
does it deterministically.
It takes the average--
images are just data.
And it maybe takes the average overall
of the image's intensities and says,
if they're over some
threshold, it's light,
and if they're under that
threshold, it's dark.
And I think that that would be a
very nice programmatic way to do it.
You need to adjust a mic?
DAN COFFEY: [INAUDIBLE]
NICK WONG: Ah, yeah.
My apologies.
DAN COFFEY: Sorry about that.
NICK WONG: Thank you.
No, no worries.
COLTON OGDEN: Dan Coffey, everybody.
Shout out to Dan Coffey.
NICK WONG: Dan Coffey makes all
of this magic much more possible.
COLTON OGDEN: Oh, we got some--
NICK WONG: Awesome.
COLTON OGDEN: --other
comments there too.
NICK WONG: Oh, yeah.
COLTON OGDEN: CHITSUTOTE-- "Hi there!
What's the topic today?
Machine learning?"
Yeah, machine learning.
Going to be talking about TensorFlow
and cartoons, light and dark.
Oh, DAVIDJMALAN is in the chat.
NICK WONG: Wow.
That's awesome.
COLTON OGDEN: Everybody shout out to
DAVIDJMALAN giving vc code link there.
NICK WONG: Yes.
COLTON OGDEN: He's coming in the clutch.
NICK WONG: Very helpful.
COLTON OGDEN: Lots of
hellos for David there.
MAGGUS503.
NICK WONG: Nice.
Yeah, I love it.
Is that a unicorn?
COLTON OGDEN: I think so.
NICK WONG: Or maybe a pig.
COLTON OGDEN: I think
it's a Brony maybe.
NICK WONG: Oh, a Brony.
Nice.
COLTON OGDEN: I can't tell.
It's hard to tell.
NICK WONG: It's
something, and it's cool.
COLTON OGDEN: "If I login on a
desktop," says TWITCHHELLOWORLD,
"then is it maybe an option to
see the livestream video there?"
I would use Chrome.
Use Google Chrome because that's
the only web browser that I really
tested this extensively on.
It should work and Firefox,
should work and Safari,
should work on most major web browsers.
But the latest version of Chrome on
Twitch.tv/CS50TV should work just fine,
so give that a try.
NICK WONG: And best of luck.
COLTON OGDEN: I'm not too familiar
with any Twitch for desktop apps,
but presumably those would work as well.
But chrome is the only one that
I'm personally familiar with.
NICK WONG: Makes sense, yeah.
Yeah, actually the same.
I usually don't watch too
many Switch streams, actually.
COLTON OGDEN: Just star in them, really.
NICK WONG: Yeah.
I like to just host them.
All right, cool.
So we have this open.
If you're not super familiar
with an IDE, don't worry.
On the left, you just
have my file structure,
all the files that I have
access to in this directory.
At the bottom, I have a console,
so this is just Bash again.
You can just list things out
and do normal Bash things.
And then, in the main
bulk of the screen is
where we'll actually be writing code.
Hopefully, that's not
too small for everyone.
It should be big enough
that everyone can read it.
COLTON OGDEN: It's the
size I usually program on.
NICK WONG: OK, perfect.
COLTON OGDEN: If anybody
thinks it's too small,
definitely let us know in the chat.
NICK WONG: Yes.
And actually, I just moved
my files off the screen--
give us a little bit more real estate.
So what we're going to do is we're
going to setup all of our imports
and get this file built so that
we can actually run it and execute
things that are going on.
I know just ahead of time
I'm going to need os.
I'm going to use it for path joining
and checking directories and things
because we're going to have
pictures in a bunch of directories,
so I'm going to use os for that.
I also know that I'm probably going to
want argparse for later design stuff.
argparse is just a
really convenient library
for doing command line
arguments so I have
to do, like, if the length of argc--
or if argc is greater than 2,
than this, and then otherwise--
I just particularly like argparse.
It's built into Python.
And those are our two system
libraries or the built-ins for Python.
We're also going to
definitely need Keras.
But with Keras, you don't
usually indirectly import Keras.
We don't actually need Keras on its own.
So we're actually going to
say, "from keras.models import
Sequential," which is not exactly model.
It's actually, I think,
a subclass of model.
And Sequential has a bunch
of things preset for us
because we know that we're going to
be building some form of model where
we just add layers to it one at a time.
And actually, we may
not have known that.
I know that, and I'm
going to tell you that,
that that is how it's going to work.
And so, yeah, Sequential
model means that we're going
to just stack everything together.
It looks-- if you were
to view it in real life,
it would literally be a stack of layers.
And each of those layers represents
all sorts of different things,
and we'll talk about
those when we get there.
COLTON OGDEN: That's like
refinements possibly?
NICK WONG: Yeah, exactly.
They're ways of tinkering with
the data as it comes through.
I like to think of it as, like, if
you imagine them as a bunch of filters
and you're just pouring sand
through it, and at the end
you get something meaningful.
COLTON OGDEN: A ruby
or something, right?
NICK WONG: Hopefully sand you like.
Yeah, or a gem.
Cool.
So we're going to import Keras.
We're also going to import-- oops--
cv2.
And that is going to just let us open
images and do things, basically all
the image manipulation through that.
And I don't think we
necessarily need any other ones.
Oh, we actually do also want NumPy.
We're going to use it to reshape
arrays and images and things like that.
And so NumPy actually usually gets
imported as something usually.
The convention seems to
be "import numpy as np."
And so a lot of tutorials,
you'll see just "np."
blabbity-blah, and that
assumes that we'll use np.
Cool.
And then, I like to follow the
C paradigm of "if name--" oops.
Yeah, you're going to see me
in mistype constantly today.
Then we're going to run stuff.
And I'm going to put
"pass" there for now,
but we will generally
put something there.
And I like to use this space up
here to write out some functions
and help with debugging.
And then down here, we're going
to just call those functions.
So very C script mashup
is what we're seeing here.
However, I also like to use Control-C
to exit out of functionality as we go,
so I'm going to wrap this and
try an except KeyboardInterrupt,
and that'll let me just say, like,
oh, the user deliberately aborted.
I like to put preface that.
And that'll just make
it a little bit easier
for me to distinguish between me
Control-Cing and actual errors that
happened while we were running.
So this is one of my favorite
ways of setting up programs.
You're welcome to do your own.
Excuse me.
All right.
So before we actually even get to
the keras.model's import Sequential,
I'm going to let us have access
to command line arguments in case
we get to that later.
So I'm going to say, ap just
stands for argparse, is argparse.
I was doing this without a editor
earlier when I was testing things out,
and man, it's much harder.
This is great because I
just have autocomplete,
and I don't have to remember
the actual names of things.
COLTON OGDEN: IntelliSense.
NICK WONG: Right.
IntelliSense is-- what a
beautiful, beautifully built thing.
And then I'm going to just say
that this is ap.parse_args.
Sorry, I didn't really
narrate any of that.
In between this line 4 and line 6,
we can put it like ap.add_argument,
and those will be available
to us on the command line.
So that's just a really
convenient way of doing this.
And actually, even right now,
there are certain commands
that are now available to
us on the command line.
So we're going to look at that.
If I do run.py, it'll tell us
that we're using TensorFlow
and nothing will happen.
That's what we expect.
But then, from here, I can actually
do -h and we'll get a usage message,
and that's arg_parse doing its job.
And the reason that I do that before
TensorFlow or before importing Keras
is because Keras is
actually a very slow import,
so we're completely able
to ignore that if someone
didn't pass a necessary
command line argument
or they wanted to just get help.
It speeds things up just a little bit.
So maybe stylistically it
looks a little strange,
but it's definitely not too problematic.
COLTON OGDEN: I think old
WHIPSTREAK has a question for you.
NICK WONG: Oh, yes.
"In line 12 and line 13
necessary or-- sorry, 16 and 17."
I believe you're talking about this.
You can also use the actual
code that's in those lines
because lines will change and
we're a little bit delayed,
or you guys I guess are a little
bit delayed from what we perceive.
So also telling us which lines of
code you're talking about by name
COLTON OGDEN: I think he's asking
or he or she is asking whether the
"if name is main" is
necessary to run the script.
NICK WONG: Ah, OK.
I see.
No.
So if you're asking about the "if
name equals main, then we do stuff,"
it's totally not necessary.
Python is a fully capable
scripting language.
You can just run Python
scripts as you go.
I just like to follow a C style
paradigm where we have a main
and it actually gets
called and things go.
This also means what
also ends up happening
for us is that if I import
this whole file as a module,
then that stuff is not going
to get automatically run.
So I would have--
excuse me.
I would have access to the functions
that I might build earlier on or later
in this file, but I'm
not necessarily going
to have them all just run
without me telling them to.
So it serves a couple of purposes.
I think it's very convenient.
Cool.
So now we're going to
start building some stuff.
So you might say, OK, well,
the first intuitive thing
is that we're going to want
to be able to load data.
And that makes a lot of
sense, except I don't
know what my data looks like, I
don't know where we got it from,
there's no data that
exists at the moment,
and I have no file structure for it.
So loading data is
un-implementable at the moment.
And I like to walk through these and
motivate different parts of the problem
as we go, and we've not motivated
that we don't have any data.
To run a machine learning model without
data is, I think, a nonsense idea.
So we're going to get some data.
You're going to get a nice view of
just how messy everything is in my file
structure.
I'm going to use Finder
to just create some files.
If you will trust me on
faith, you can hopefully
believe that this is the same
directory that we're looking at here
and it's the same directory
we're in over here.
They're all the same.
And if you don't believe
me, then I apologize.
Nothing I can do on that.
I'm going to call this images
because our data type is images.
You can call it whatever you'd like.
And then, within img, I'm going
to actually have three folders.
So the first two are train and
test, or validate is another word
that you might use for that.
And this is pretty standard
in any sort of machine
learning setup, at least
for supervised learning
where we're trying to feed it answers
and get it to learn some pattern,
is we're going to say, take my data
and split it into two data sets.
I have a training data,
and I have a testing data
set that validates whether
or not that data's good.
And the reason that you
would split something
is in machine learning models, they
can sometimes over-learn things.
For example, humans do
this all the time too,
where I might tell a child that
after 1 comes 2, and after 2 comes 3,
and the child might then
go and say, OK, well then
after 3 comes 4, and then 4 comes 5.
And that's very reasonable.
That's something that's
totally what we might expect,
except I might have just fed
you the first couple of numbers
and a Fibonacci sequence, in which case
after 3 does not come 4 but rather 5,
and then 8 and then 13.
And so it's really important to us to be
able to give the machine learning model
data that it doesn't incorporate
into what it actually does,
and data that it can then just
see how well it actually is doing.
Basically, it's called over-fitting,
where a machine learning model learns
all of its training data by memorizing.
And so it just says,
this is what I know.
This is everything that I'm going to do.
An analogy for that is a child
saying, I know four colors
and I know them very well.
And then you hand them a new color,
and they have no clue what it is.
And that's something that real
humans could, in concept, do.
We tend to compensate for that,
but it's definitely very possible,
and machines do it all the time.
So we split this into training data to
give it something to actually learn on,
and then we see how
well it's actually doing
kind of in the real world on data it's
never seen before in the testing data.
And that data does not
getting incorporated back
into how the machine actually learns.
It's just used, literally, to test it.
And then, the third directory that we're
going to put in is a predict directory.
And I just like to structure
things really cleanly.
And so this directory is just
going to contain a bunch of images
that I want the machine to predict on.
I want the machine to tell me,
what do those images actually have?
Are they light?
Are they dark?
Are they cartoon?
Are they real?
Things like that.
COLTON OGDEN: Cool.
NICK WONG: Cool.
So in train and test,
we're going to want--
the way that Keras pulls
images from a directory
as it uses the directory name
as the label for that data.
So I'm going to create a new folder,
and we're going to call that light.
And I'm going to create a new
folder here and call that dark.
And so we'll want to
replicate these over to test.
And so these two folders, basically
what they do is inside of dark,
I'm going to put a
bunch of dark images--
not dark in the metaphysical sense,
but literally just darker images.
They're just blacker colored.
COLTON OGDEN: R-rated stream.
NICK WONG: Yeah.
We're going to keep everything
very nice and PG I hope.
And so everything here
will just be-- is it
literally just more black
pixels or more light pixels?
And a lot of times, people are like,
oh, I have to collect a bunch of data.
And I've actually been
very much an advocate
of collecting just smarter
data, not necessarily more.
So what I mean by that is, are you
covering all the cases, for example?
And in our case, we don't
really have that many.
There's just, like--
actually, I guess there's
a very large number of ways you can
make a dark image versus a light image.
But what I mean by that is
we can collect some things,
like maybe there's a
just pure black screen.
Well, that makes sense.
And that's dark, for sure.
But what about if you had a black
screen with some stars in it?
Well, then that might actually
be slightly different.
Or for example, this picture.
I'm literally going to just drag and
drop a bunch of pictures from Google.
This picture, I would
classify it as dark.
It's pretty black.
There's a little candle in there.
And so a machine might
not deterministically
be able to say, oh, well that's
dark, but machine learning
can probably figure that out.
And so I'm going to copy
a bunch of these images.
You'll notice a lot of them
are not exactly all black.
Most of them have some
sort of image in them.
And this one is pure black.
Love that.
This one is also quite
dark, but not black
really, not as black as the other ones.
COLTON OGDEN: An interesting
test case on that one, yeah.
NICK WONG: Right.
So I think that that's something
that would be really worth putting
in front of our computer.
And I'm deliberately ignoring an
image that I know is on the right
because it's a really good test example.
So I'm going to grab 10 of these.
Oh sorry, it's actually down here now.
So there's this image, and this
image I would classify as dark,
but it has a very bright center to it.
So if we can get our
machine learning model
to figure out whether or
not that's light or dark,
that'd be really interesting for us.
So we're going to put that
in our predict folder.
COLTON OGDEN: ZODI4KX says,
"Hey guys, I'm Wesly."
ZODI4CKX.
NICK WONG: Oh.
COLTON OGDEN: Good to have you, Wesly.
Thanks for joining us.
And then BHAVIK_KNIGHT, who's
a regular, is in the chat.
NICK WONG: Welcome back.
COLTON OGDEN: Says, "Hey guys.
Seems like I'm very late today."
No worries, BHAVIK, we're
just getting started.
And the code is on GitHub.
I'll try to post that URL again.
NICK WONG: And at basically every major
point, I will push all of the code
that we have so far to GitHub.
If you were around last week, they
actually did a whole stream on GitHub
and how oh this very powerful tool--
COLTON OGDEN: Oh yeah, with Kareem.
Yeah, on Twitch and on YouTube we
do have a Git and GitHub stream
with Kareem Zidane, Kareem the Dream.
NICK WONG: Kareem the Dream.
All right.
And then, I'm going to just
switch over to our testing folder
and put some other dark images in there.
This will let us get
a good gauge of just
whether or not we're
accurately measuring things.
I think in the previous
folder for training
I put about 10 images for testing data.
Oh, Black Mirror.
What a fitting, very
appropriate thing to test on.
I put about 5.
There's not really a hard number on
how many of anything you should have,
but I generally try to go
for nice numbers that I think
are really cool, like 5, 10, and 42.
I think the more data
you get, in general
you can do better, as long as
your data brings up new patterns.
So then we're going to just
bring in some more images.
Sorry, this part is not
particularly interesting.
I'm not writing any code.
COLTON OGDEN: Hey, it's from scratch.
The whole thing is from scratch.
NICK WONG: It is from scratch.
So you could literally
follow along click by click,
and you will technically do this.
COLTON OGDEN: And choose
their own images even.
NICK WONG: Yeah, you could
even pick your own images.
This is meant to be as
generalizable as I hope possible.
And so we're just picking
up very light colored--
oh, sorry.
I picked up a few too many.
I like to keep my data sets balanced.
So if I have 10 in dark, I'm
going to try and keep 10 in light.
I am a little--
weirdly enough, you wouldn't believe
this by looking at my desktop,
I do like to keep things
organized when I code.
I think when I organize my life,
not so much, but that's OK.
COLTON OGDEN: People have
different definitions of organized.
It's OK.
NICK WONG: Yeah.
It's a flexible definition.
So yeah, I'm very organized
when I write code.
I'm not necessarily so organized
when I do the rest of my life.
Cool.
So then I'm going to rename these.
I just think it's a little
bit cleaner to have this.
And then we're going to get
some light testing data.
Oh.
Actually, I think this is
just such a pretty picture.
COLTON OGDEN: Oh yeah,
that's a nice picture.
NICK WONG: It's very cool.
Oh, I thought it was a unicorn.
I was super excited for a second.
I thought it was a unicorn.
COLTON OGDEN: Can explain again the
difference between the test and the--
what was the other category?
NICK WONG: Yeah.
So we have test and training
data, and there's also a predict.
COLTON OGDEN: Predict, that's--
test and predict, what's the
difference between those two?
NICK WONG: All right.
So testing data is going
to be said-- at every step
that we run our machine learning model,
we'll see how it did on testing data.
That won't be incorporated into
the model, but it will tell us,
like, how are we actually doing?
Because on its training
data, it'll generally go up
as it starts to just memorize things.
So we want to see, on data
it's never seen before,
is it actually getting better?
Are we actually seeing some improvement,
or are we kind of at a loss here?
And so we'll see a little
bit clearer what exactly I'm
talking about when we actually
start to run some models.
But basically, the testing data
shows us, how are we actually doing?
The training data we
generally should improve at.
If you're staying at
just this flat 50/50,
you're probably doing
something wrong in your model.
In fact, there is an
error I discovered earlier
that I think would be really
good for me to show everyone
that I like to mess up.
Cool.
And then we have two
images-- oh, and predict.
Sorry, I didn't answer that part.
The predicting data is,
after we've trained our model
and we have it thinking and it thinks
it knows what it's talking about,
then we're going to test it
on data that it doesn't really
get thrown into any sort of framework.
This is really the
use case of our model.
So if I wanted to use it for
actively predicting things,
then we're going to say, hey, let's
take a look at how we might do that.
So it might not be in
the directory predict.
We might even pass it as
a command line argument,
and it just goes and finds it.
But I like to keep it
organized there for now
while we're going and developing.
COLTON OGDEN: Make sense.
NICK WONG: Cool.
So we have a bunch of images.
I guess for the sake of
copyright, they're not mine.
I literally pulled them off of Google.
You watched me do that.
They are in no way my images, and I
certainly do not take credit for them.
I only take credit for
knowing how to Google--
or barely.
And so we just went
found some random images.
And if you don't believe that
those are the same thing,
here are all of my same
directories that we just built.
I just use Finder because I think
it's a slightly easier interface.
Cool.
So we have all these images now.
Let's see if we can go find them.
So when we say load data,
that means that somehow, I
have to get the images
that I just put everywhere
and return them to me as
test and training data.
So we're going to go and
get some of that data.
I'm probably going to be given
an image directory or img_dir,
and I probably want to
go and maybe enumerate
what's in that image directory.
I happen to know that the
structure of this directory
is in a test and train split.
So what we might do is I
might say, OK, then my test--
or we'll start with train.
"train_images."
And we'll say "paths."
And so I will probably switch
these to abbreviated versions
because I think those are conventional.
So this is our training data, and
these are the image paths that we get.
I'm going to use a list comprehension
because it's convenient,
but if you are not
comfortable with those,
then I think it's somewhat easy
to flip this into a for loop--
hopefully not a problem.
If you have any questions on syntax and
things, then feel free to let me know.
If you spot any bugs, maybe
just chuckle to yourself
and you'll see me find it
later when I try to run it.
Cool.
So what we want to do is we're
going to do "os.path.join,"
which is a cool command.
It lets you just actually
join paths together
without really having to worry
about like slashes and things
and double slashes.
And I know that this is going
to be in my training directory.
And then I'm going to
just do "img_path."
And this is "for img_path in os."--
OK, this is possibly
very poorly styled code.
It's going to be a very long line.
We could've split this up.
"in os.listdir(os.path.join)."
Oh man, that maybe was
not the best planning.
That's OK.
COLTON OGDEN: The beauty of
list comprehensions right there.
NICK WONG: Gotta love
list comprehensions.
COLTON OGDEN: At least you can enter in
the middle of it, though, to break up,
which is nice.
NICK WONG: That is true.
Well actually, that's a very good point.
We might do that.
So technically what
we are doing is we're
taking the variable
train_imgs_paths, we're
setting it list equal to this list.
I've realized I'm
starting to skip words.
That's kind of cool.
And so what we're doing is we're saying
join the paths of the image director we
were handed, the training directory
which we know will exist--
we're hardcoding that for now--
and then the image path.
And the image path is given to us
by iterating through and assigning
as we go through image path to each
of the things or items in this list.
And this list is a list of the
directory which is given by, again,
joining our image directory and train.
So what that basically ends up meaning
is that we're going to go and collect
all the paths of things that we went and
put into our image training directory.
And then-- you really should
never copy and paste code. #CS51.
We're going to copy and paste code, and
we're going to change some variables.
Gotta love that.
And we're going to say, OK, here's
my test img_path, [INAUDIBLE] path,
and this is also in test.
Yeah, live coding will really test your
ability to be confident when you do it.
All right.
So I generally like to
iteratively debug things.
I don't like doing huge monolithic
swaths of what's going on.
So we're going to just
run this in our script.
So we're going to have
"load_data," and we're
going to say img is the data directory.
We might pass that in as a
command line argument later,
and that might trigger some bells.
But now we should be
able to run this, and it
should print out to me both of the
things that contain our image data.
So then, the thing that we have in here
is you'll notice that there's this .DS
Store.
Actually, that causes
some bugs sometimes.
It won't cause bugs in this case
because Keras ignores it when
it's flowing things from directory.
But if you try to load individual
images, that does mess with you.
So just keep that in the back,
very far back of your mind.
It is something to keep in mind.
All right.
So now we're going to get into--
oops-- the meat of Keras.
And unfortunately, I don't remember the
exact syntax off the top of my head,
but I'll tell you what
we're going to go do.
And then we're going to do what every
cs person should be very good at.
We're going to look
at some documentation
and we're going to
remember what that name is.
So I have these paths now.
I know exactly where all
of the images are named.
I actually don't necessarily
need each of their paths.
I really only need this
os.path.join of here.
That's the actual directory.
We're going to use that later.
But I like to have the image paths for
displaying which images we're actually
looking at later.
So it's just a future
thought focused thing.
But we're going to do what
Keras has beautifully built,
which is called a flow from directory.
And the reason that
we're going to do that
is because we don't
necessarily have a lot of data.
And our data is certainly incomplete.
There's plenty ways
make another dark image.
But the reason that I think a
flow from directory is brilliant
is because it allows us
to take our small data set
and make it into a very large one.
Because an image that
looks like this, if I
were to flip it around, to the
computer, that's a different image.
But to us, for our
purposes, it's identical.
It's still dark.
It didn't change anything about it.
So what's beautiful about
Keras's flow from directory
is it randomly does that.
It'll start flipping images.
It might cut them in half.
It can flip them around in
all sorts of directions.
It can shrink them.
It can resize them however we like.
And it allows us to create data
from just our existing data set.
We don't have to go and find anymore.
COLTON OGDEN: That's a cool [INAUDIBLE].
NICK WONG: So it's a very cool feature.
COLTON OGDEN: BHAVIK_KNIGHT says,
"We don't have a main, have we?"
NICK WONG: We kind of do.
So what Python actually ends
up doing, in a nutshell,
is if the Python script is run as
a script from the command line,
then it is going to have main.
But if it's run as a module,
it's imported as a module,
then its name, this variable that
we never really instantiated,
is not going to be main.
I actually don't know what it
is if you run it as a module.
But yeah, no worries there.
Let's see.
"Am I supposed to log in?"
TWITCHHELLOWORLD says, "Am I
supposed to log in to GitHub
to see the code at the URL?"
You don't need to log in it.
Is a public repository.
There is no code there currently.
After we load all of our data
in, I'll push that to GitHub
so that everyone can see
what's going on there.
Cool.
So we have Keras.
The documentation got
updated I say recently.
I mean within the past
five months or so,
which I'm really happy about
because for a little bit there
it was a little confusing.
And I know that down at the bottom
they do this whole thing talking
about image pre-processing.
And that's just a bunch of stuff that I
happen to know by reading through this.
I know that I'm going to want to
do some sort of actual generator.
But this is not the exact one I want.
This one is.
So this little bit of code that
is in the Keras documentation--
I take no credit for writing it--
is basically what we're looking for.
This gives us the ability to
do our data generators, which
are that whole applying random
operations to our data set.
And then we do these actual
generators, which are
going to be the flowing from directory.
It's going to pull all our data
in to some sort of directory--
or from the directories that we listed,
and it's going to do stuff with them.
We're going to do stuff with it.
So I'm going to literally
copy and paste this code.
Not necessarily the best model,
I think, for doing things, but--
COLTON OGDEN: This is true "from
scratch" programming today.
NICK WONG: This really is
"from scratch" programming.
I did actually walk through this
with myself a little bit last night,
but I deleted all of
that code so that you
would get a legitimate
version of this and you
would see that there is a
lot of effort and thought
and messiness that goes into this.
So we'll notice that in
VSC, Image Data Generator is
highlighted because it doesn't exist.
We'll deal with that in a second.
It's just an import that we need.
I'm not a huge fan of their style.
I prefer this one.
But that's OK.
So in this train_datagen, we
know that rescale basically--
sorry.
I keep saying "we know."
I apologize.
I mean just rescale is going to allow
us to reshape the image's just size.
It's literally taking the
image and just making it--
trimming it this way or that way.
Sheer range is not something
we're going to actually deal with,
though it would be totally valid.
And that takes an image and just--
you can think of it as--
just cuts off parts of it.
And that's definitely a useful
operation for us, but not necessarily
in this case.
I don't necessarily need zoom range.
I think there's one
called vertical flip.
And so vertical and horizontal flips
do exactly what they sound like.
They flip the data.
And we're going to use this for now.
So it allows you to
rescale stuff to grayscale
for this, allows you to do all sorts
of rescaling here as well as rescaling
the image size.
I should actually double
check on what rescale does.
That's OK.
We'll look at it in a second.
But then, horizontal flipping
and vertical flipping
allows us to create a bunch of new
data-- a little bit of new data,
where you can do a horizontal
flip, you can do a vertical flip,
or you can do both.
And those will create new
images for the computer.
And then this test_datagen is
going to just be our testing data.
So it's the same kind of
thing, but for the test
data that's going to be
used to validate our model.
And this one has only
the rescaling factor.
Cool.
So then we get into the generator.
And so this is where you see
this flow from directory.
It's one of my--
I think my favorite command
that Keras has because it allows
you to do this extra data creation.
We are actually-- this happens
to be for a binary classifier.
Cool.
So it's still going to
be a binary classifier.
And you'll notice that there's
this thing called target_size,
and then there's this data directory.
So we are going to
change those two things.
So I'm going to just copy a
little bit of what I had above.
And that's my training
directory, is just
os.path.join this, which is
our image directory that we
supplied via the
argument, and the testing
directory, which is just called test.
And we now have two directories which
hopefully have two folders within them
that have a bunch of images in them.
That's what Keras expects.
And then, this target size
is the size of the image.
It assumes that they're
of any dimensionality.
We rescaled them so that they
are only two-dimensional images.
Color images are actually
in three dimensions.
We have our width and our height,
and then we have our colors.
We have R, G, and B. If
you've been doing CS50 stuff,
you actually know exactly how
that works probably very well.
And so I'm going to change our target
size a little bit to be 500 by 500.
They don't have to be squares.
I just think it's kind of cool.
And it won't really matter for us.
A dark image that has been
reshaped and distorted
but is still all the same pixels is
identical to us for these purposes
as the image that's
in its original size.
And then, our batch size--
and this actually has a
few too few parameters.
I'm going to add a few.
Our batch size let's say is just
a nice, clean, round number.
And then we're-- so batch size, meaning
how many images does it pull for any
given step within the process?
And then, I don't think we need
anything else from this except knowing
where exactly that came from.
And if you look on their
documentation, they
do list all of the possible
ways in which you could
manipulate the data before it comes in.
There are some really cool ones.
Fill mode I think is
actually really nifty.
And that basically just
inputs some data for you
if you need it to fill out images
that aren't all the same size.
It allows you to--
instead of shrinking
them or expanding them,
it lets you just fill in the extra
space to the maximum image size.
This is the actual
split between the two,
so it reserves some fraction
of things for validation.
So if you just had training data,
then you could split some of them
to be only validation data.
And there's some other
stuff that goes into this.
But we have this
ImageDataGenerator class.
And you'll notice that it
seems to come from here.
That's the full module path.
So what we're going to do
is I'm going to copy that,
and we're going to paste that here.
"from keras.preprocessing.igame
import ImageDataGenerator."
And that's how I would convert
those full pads to, hopefully,
what actually does its job.
We'll see if that's true.
That's the intuition, at least.
And you'll notice this actually went
away because IntelliSense thinks
that I've at least done it correctly.
Hopefully, it's right.
And then the rest of this we're
going to leave on its own.
So we have our validation-- or our train
generator and our validation generator.
And those are going to be what our
model actually ends up getting fitted to
and trained on.
Trained on and fitted to are actually
pretty much synonyms in this sense.
So we have our train
generator, and I'm also
going to return the
validation generator.
Cool.
So we've loaded our data, and hopefully
we end up actually getting data.
I'm also going to now
excepts those arguments.
I'm going to call it train_data and
test_data to be consistent with myself
from the way that I
labeled my directories.
You're welcome to change
those variable names.
I think that would count as
some sort of consistency points.
And we're going to run this and
make sure that nothing happens.
That's literally what we want.
We want it to tell us the images
it found and do nothing else.
And that's exactly what it did.
And so I'm very glad
that that's what it did,
and also that is exactly what we
were expecting, where it found
20 images belonging to two classes.
So you might intuit--
oh, that was our training
data, which is good
because that was the one we ran
first, so I'm glad it came out first.
And then it found 10 images
also belonging to two classes.
We're still doing binary.
We've got two classes and 10 images.
We know that that was our testing data.
So everything seems to check out.
And hey, we're still using TensorFlow.
So I'm going to git at add.
I am in the habit of saying git add dot.
Not a great habit.
I'll git add img and
I'll git add run.py.
COLTON OGDEN: I'm in the
same bad habit as well.
NICK WONG: It's a terrible habit.
Someone in our CS61 class actually
committed the entire subversion tree
of--
it was some Unix command.
They accidentally pulled an entire
Unix subversion tree into it.
COLTON OGDEN: Probably not
what they intended to do.
NICK WONG: Was certainly not
what they intended to do.
They actually crashed
our grading server--
COLTON OGDEN: Oh, nice.
NICK WONG: --which was
really kind of cute.
Everyone was freaking out.
They were all like, oh no,
I can't get my grades in.
I'm going to fail.
The professors are like, we'll
just extend the deadline.
It's fine.
All right.
Cool.
So that has now been
pitched to the GitHub,
so if you would like to grab it,
you're welcome to pull that up.
Can anyone-- sorry.
Is that NEOKRES--
COLTON OGDEN: NEOKRES-- it's
hard to pronounce that name.
I'm not sure.
NICK WONG: I do not know
how to pronounce your name.
I'm so sorry.
But I'm going to call you NEO
for now, and if that offends you,
please let me know.
So NEO asked, "Can anyone tell me, is
there a link for C++ and JavaScript
Harvard video lectures/sections
if there are any?"
I don't necessarily know
from my other classes.
I know CS50 has some great
videos on JavaScript.
I don't believe we have any on C++.
COLTON OGDEN: Yeah.
CS50 doesn't do any--
hasn't done any C++.
We have done some JavaScript
videos in the past,
and Brian Yu's web course, I
believe, goes into some JavaScript
if you want to go to that URL
for some JavaScript stuff.
But yeah, no C++ yet.
We'll keep it in mind for maybe
some future stream videos.
NICK WONG: Yeah.
I think that'd be very
fun to go through.
C++ is a great language.
It does all sorts of cool things.
JavaScript I have a lot of beef
with, but it is technically
a very useful language.
I think it does a lot
of very strange things.
And actually, speaking of
JavaScript, TensorFlow,
which is the back end of
what we're doing here,
was recent-- well, recently
implemented in JavaScript by Google.
And so they released that, and they have
all sorts of really cool demonstrations
on using machine learning
on the web browser.
So that's actually what my winter
break will probably consist of,
and I'm super excited for.
COLTON OGDEN: That and the web assembly.
NICK WONG: Yes.
COLTON OGDEN: That's be huge.
NICK WONG: Web assembly I think is
a huge just advancement of browser
technology.
I'm super excited for that too.
COLTON OGDEN: It feels like
those two will go hand in hand.
NICK WONG: So many go.
I think so.
I think that that will
actually vastly improve
the abilities of what we see
browsers doing, which given
Spectre and Meltdown makes
me a little bit nervous.
I don't know if I want my browser to be
able to do a lot more than it already
can.
But I think it'll be cool
as we work out kinks.
All right.
So we have built our
loading data, and I'm
reasonably confident that
we have loaded it correctly.
You'll notice that when
I load the data here,
I actually don't use
either of these two.
I'm realizing that in my head I
had thought a little bit too far.
So these two are not necessarily useful.
I'll comment them out for us,
and we might revisit them later.
Hopefully, we will revisit them later.
All right.
That's actually one of my favorite
features of Visual Studio Code,
is being able to just collapse
the code of a function.
And there are a lot
of IDEs that do that.
I think a CS50 ID does not,
though, and it's really annoying.
Cool.
So we're going to-- oops.
I was going to say we're going to fit
the model, but we don't have a model.
My next thing would be, oh, OK,
let's train our model on things,
but we don't actually
have a model to train.
So let's build a model.
And this is, I think, one of the
coolest parts of what we get to do.
So building a model.
I'm going to create a
kind of "global" variable.
It is global, actually.
I don't know why I put
quotes around that.
And I'm going to call that Sequential.
Or sorry, I'm going to call it
m, and it is a Sequential model.
And that's going to be global
because all of our functions
are going to access it.
And you might be thinking
to yourself, oh, this
might fit really well in a class,
and you'd be absolutely right.
This is actually really well implemented
as a class that has certain methods.
But we're building it as
a script, and here we are.
So we're going to use build_model
to actually construct our model
and see what layers we can add
to it and things like that.
So the first thing that I
might want to do is m.add.
And that's going to be the way
that we add layers to our model.
They're going to be sequential
so that if we add a layer,
that's the last layer.
The last added layer is the last
layer that we are going to go through.
All of our data we'll go
through that layer at the end.
So the first layer that
we're going through
is the first one that we add, and we're
going to have that be-- oops, "Desne".
And Dense is just your standard, good
old-fashioned neural network layer.
It basically has a bunch of
nodes in it, and those nodes
are going to look like
that's the number of nodes,
roughly, that it has inside of it.
And that's pretty much
all you necessarily
need to know about what it does
as far as technical specs go.
But we're going to add
a bunch of parameters
to it because this is our first model.
Or sorry, our first layer.
And in our first layer,
we need to tell it
the input size that it should expect.
So this sort of thing
is always very annoying.
Dense requires a bunch of parameters.
I know input size is one of them, so
we're going to give it the input size.
And the input size is going
to be something like--
sorry, we specified 500, 500--
3?
Question mark?
That 3 goes either there
or on the other side.
I can't always remember.
It's close to that.
We're going to give it an activation.
And with binary classifiers,
they use a sigmoid activation.
And you might be wondering,
what is an activation?
Great question.
COLTON OGDEN: What's a sigmoid?
NICK WONG: What's a sigmoid,
also a great question.
And so basically, what
that means is activations
are the initializations of our layers.
So our layers, in reality,
they're just a bunch of numbers.
It's really just a weighting of numbers.
And then those numbers are
going to be modified as we go,
and then that weighting will change
to hopefully give us some answer.
And so those numbers, they
need an initial value.
You might default to 0, but that
actually, based on the math behind it,
doesn't necessarily give us
a whole lot to work with.
Sometimes that can actually cause
you to get stuck in one particularly
version of your model.
And so this activation is
an initialization to it.
It's a initial set of values.
And so sigmoid, you can think of it
as, like, if you were to plot it out,
it has that classic
curve structure to it.
And that's going to be what
you actually would imagine
if you were to plot out
all of the activation
or all of the individual
nodes' individual values
from an arbitrary left to right.
It's a little bit hard to describe
without the theory underneath,
but that's roughly what's going on.
We're setting a bunch of numbers
equal to a pattern, roughly speaking.
And all that means for us is
that a sigmoid response is
really good for binary classifiers
because binary classifiers have
one of two answers.
It's either up or down.
It's either 1 or 0.
And so a sigmoid response,
what that might look like,
if you know anything about
signals processing or filtering
of images or data, or even
music, then a sigmoid response
makes it really, really
hard to land in the middle.
It's very difficult for
me to be halfway between.
It's really easy for me to be 1 or 0.
And so that is basically
what we're looking for.
That's the behavior we're looking
for in this sort of model.
So we're going to stick with
sigmoid activations for most things.
We will see a bug that I introduced
to myself last night, where
if you choose the wrong
activation, we can actually
get totally random behavior from
our model, and that's kind of cool.
But we're going to stick
with sigmoids for now.
COLTON OGDEN: METAL_EAGLE
has a question for you
if you want to pick that one up.
NICK WONG: Oh, awesome.
So a METAL_EAGLE asked, "What
is the problem of 'git add.'?
Should you have a habit to
run git status beforehand
to make sure that running
git add will not break
anything you do not want to commit?"
I have broken all sorts of things
that I did not want to commit.
I have committed API keys.
I've committed my only
personal keys to things,
depending on what you're building.
So yes, you should definitely make sure.
Running git status is
another really good habit
that I do not have to make sure
what you're actually committing.
"git add."
is problematic, I
think, because let's say
that you have something
in your directory
that is not part of your project.
It just happened to be in there
because you were reusing some old code
or you wanted to look at
something for an example.
And I've certainly done that.
You probably don't want to
add that to your git project.
You don't want to put it in
the git repository history.
Because of the way git works--
it's a feature, not a bug--
you have access to all
the previous things.
So-- excuse me.
If you were to add some sort of API
key, for example, then using "git add."
means that that is now permanently
part of your git history.
GitHub has a really cool tool.
It's GitGuardians, actually.
They monitor perpetually for
API keys, and they'll email you
and they'll block your
repository for a little bit
until you get that sorted out.
And that's really cool.
COLTON OGDEN: That's a cool feature.
NICK WONG: They've
emailed me a couple times.
I occasionally am just really trying
to go, and I'm a little careless.
COLTON OGDEN: Do as Nick
says, not as he does.
NICK WONG: Right, exactly.
I've picked up some bad
habits along the way.
TWITCHHELLOWORLD says, "I couldn't
see the Livestream in the app
so I missed the start.
Are you in CS50 sandbox or
somewhere in TensorFlow?
NICK WONG: Yes.
So we're not-- sorry, we're
not in the CS50 sandbox.
We are using TensorFlow.
We are in Visual Studio Code on my
personal-- on my local environment.
So I'm just using this on my laptop,
and I will be pushing code in chunks
as we go to GitHub.
So basically, whenever I
get a chunk of code working,
then we'll actually
push that to you guys,
and you're welcome to copy it down and
see how it works on your own machine.
You will need TensorFlow.
You will need Keras.
You also need Pillow.
You will also need opencv.
Actually, I can make that really easy
because Python has the freeze feature.
So I can freeze, which basically means
take all of the current Python packages
you have and output them.
So if I just run "pip
freeze," then it'll
output all the packages that
I've downloaded and I use.
And there's a few more
than you might think.
I only downloaded Keras, but Keras,
for example, downloads three other--
or like three packages.
So this is actually a really
good way to transfer what
Python things you're using.
And in this command, I just piped all
of that output into a requirements.txt.
It's a very common feature on Python
packages and modules and things.
And if you wanted to
build from that, you
could do pip install
-r of requirements.txt,
and that'll pull all those
requirements in the correct versions,
or at least the version
I'm using, to you.
So I'll also push that to-- oops--
to GitHub.
So we'll git add-- oops.
And git commit.
COLTON OGDEN: Thanks
also to MKLOPPENBURG
for pitching in the React course
that Jordan Hayashi taught,
which did cover JavaScript,
and for mentioning
that we are using the VS code.
NICK WONG: Awesome.
Thank you.
All right.
So you should have a requirements.txt
file in the repository now,
and that should help if you're
trying to get everything set up.
Cool.
So we now want to continue
adding layers to our model,
and we can keep things
actually very simple.
So we add this dense layer.
I'm positive I'm missing a parameter.
I think it goes in the beginning there.
And we're going to figure that
out when it doesn't compile.
But this dense parameter
is just your input.
That's the first thing
that's available to us
whenever our data goes
through our model.
The next thing that we
want to be able to add is--
our models are images.
Images in general are displayed
as arrays of some sort of data.
And in our code, they're also arrays.
They're NumPy arrays, but
they are still arrays.
And we're going to need to
modify that a little bit.
We need to tinker around with
what exactly we're seeing.
So actually, we're going
to change this beginning
layer to be a convolutional layer.
Ah, that's what I was forgetting.
OK.
We're to use a convolutional
layer at the top.
It still uses basically
all the same parameters,
except it has an additional
parameter which is its filter size.
And we're going to use three by three.
That might be a name parameter.
I'm not entirely sure.
And so convolution is a operation
that you can do on signals data
from anything, from visual
signals to auditory signals
to electronic ones in general.
And a convolution, mathematically
speaking, is you take a signal
and you take a response,
and you loop the response
and pass it over the signal.
And if that sounds complex and
difficult to understand, it is.
I don't necessarily fully
understand it either.
COLTON OGDEN: Is it
like feedback almost?
NICK WONG: Yeah, exactly.
It's like your response to what's
going on in the signal or the way
that two signals might interact.
I would think of it maybe like that.
COLTON OGDEN: That makes sense.
NICK WONG: Yeah.
COLTON OGDEN: Almost like the messing
with the image data that we had too.
Feels similar.
NICK WONG: Right.
Yeah, exactly.
It's just a way for us to
manipulate the image data.
What convolution will do for us is it--
I believe in this case, if
I'm not losing my marbles,
it is convolving the image
with this three by three array.
And what that's going to do for us
is make our data little bit more--
not centralized, because that's actually
what our next layer is going to do--
but it makes our data more readable
and friendly to the machine.
So it gives it some features that
make our machine a little bit happier.
COLTON OGDEN: Massaging the data.
NICK WONG: Exactly.
That's exactly what it does.
All right.
COLTON OGDEN: BHAVIK_KNIGHT
says, "Why not pip3?"
Why are you using pip instead of pip3?
NICK WONG: Ah.
So actually, if you look at which pip
or pip --version, this actually is pip3.
I happen to use pip because
it's alias to the same command.
So pip3 would also work.
There's not necessarily a
difference between the two.
However, there is a
difference if you're on a Mac
and you use the installed version
of pip versus the system installed
version of pip.
And that is one of the most
annoying bugs you will ever
encounter, almost guaranteed.
COLTON OGDEN: CYLVTWITCH says,
"Will the videos be on YouTube
so I can watch them later?"
Yes, they will be.
If you just go to YouTube
and type CS50 on Twitch,
you should be able to see our playlist.
And it's also see CS50's YouTube
channel where David posts his lectures
and a bunch of other course videos.
NICK WONG: Awesome.
COLTON OGDEN: GHASSEN says,
"Hello, are there any interns open
in Silicon Valley?"
I would Google and see.
I'm sure there are
internships available,
but none that necessarily CS50
is directly affiliated with
or knows of at this moment.
But definitely do some
Googling and see, and I'm
sure there are links on those
websites that you could reach out
to get some more information on them.
NICK WONG: And BHAVIK_KNIGHT
actually pointed out
that convolution is output
going into the input again.
That is actually-- yeah, exactly.
That is what this convolution does.
So it's not the general
definition of convolution,
which is what I was I
guess stumbling through,
but it is the convolution
that happens here.
It convolves the image with itself.
Thank you.
That was something
that was very important
that I could not for the life of
me remember how to talk about.
Cool.
So now we're also--
COLTON OGDEN: You could say
it's a little convoluted.
NICK WONG: It's a little convoluted.
That's awesome.
COLTON OGDEN: Zing.
NICK WONG: Man, I love puns.
Puns are the light of my life.
All right.
So we can also add this MaxPooling2D
layer, which sounds very--
sorry.
I was reading the comments,
and it's kind of funny.
Sometimes you guys have just
these entertaining comments OK.
So we're adding a MaxPooling2D layer,
and that sounds kind of ridiculous,
but it's not.
Max pooling just means that we're
looking at the maximum of the values
in a given range or frame.
We're pooling all those
together, and that's
going to be representative
of that actual area.
So you could imagine it as taking a
5 by 5 array, and the maximum of that
is now representative of all
of that five by five array.
So it could be thought
of as like feature--
man, the word is escaping me.
Combining features or
feature combination.
And it basically just means that some of
the data in our image will get ignored,
but we're assuming that the maximum
part of our data is the important part.
There's also min pooling
and there's average pooling.
There's a bunch of other
ways that you can pool data.
There's all sorts of
things you can do with it.
And then, 2D means two dimensional.
You're using two-dimensional data.
So the parameters to MaxPooling2D
are something like filter_size.
And this is just that,
like how much of a--
like what's the size of
the pool we're using.
Activation is definitely one
of those parameters, I think.
OK.
I say "definitely," and
then I said, "I think."
That's self-contradicting.
I don't know if it takes anything else.
We'll find out.
This is generally something
where I don't necessarily
memorize it because I can
just go look at documentation.
And then, we're still working with
an image which is not super clean.
Or sorry, it's not super easy for our
machine to then put out a 1 or a 0.
So what we might do is
something like this--
model that add of a Flatten layer.
And that pretty much
does exactly as its name.
It just flattens the image
into a one-dimensional stream.
And so if you did CS50's resize
recover and you played around
with images a lot, you could think
of them as all having been flattened.
So they're no longer represented
in two-dimensional arrays.
They're represented
like a stream of data.
And there is some breakpoint
that's logical, but to a computer,
those breakpoints don't matter.
They're kind of irrelevant.
So we can actually then
flatten our images.
And now that we've done this max
pooling and convolution of the image,
we can flatten everything and then just
feed that into standard dense neural
network models.
And that should be
pretty reasonable for us.
And we're actually going
to do exactly that.
We're going to add a dense layer to
do some kind of minor computation.
I like to use powers of two.
That is certainly not a--
it's not a requirement,
but I like to use them.
And that's just the number of nodes
within our layer, roughly speaking.
It's not exactly correct,
but it's close enough.
And then we're going
to add our final layer.
And this one has a
specific set of parameters.
It has to have the number of
nodes within it be actually one.
And the reason for that is
we're using a binary classifier,
so we want it to output only
using one node or one number.
We don't want it to output a bunch of
nodes because then each of those nodes
might be weighted to something else.
They might represent non-existent
or imaginary classes.
So we don't want that.
Cool.
And then we're going to give that
one a sigmoid activation as well.
So now, running through
this in concept would work,
but you'll notice that in
IntelliSense, it actually
highlights all of these
things or all of the layers
that we just added because
they haven't been imported yet.
So what we're going
to do is import them.
And I believe it's "from keras.layers,"
hopefully, "import Dense,"
can't remember the name, "Conv2D,"
and we'll say MaxPooling.
Oh, I love IntelliSense.
It pulls things that I
don't even have up here yet.
"Flatten."
And I think that's it.
So those are all the layers
that we tried to use.
Oops, that's not what I want.
And now that we have everything going--
oh, I killed my virtual environment.
That's a bummer.
We should be able to
get this model built.
Now, the problem is that we haven't
necessarily linked them yet.
But I also think I'm
missing a parameter here.
I think I might have
not named it correctly.
But that's OK.
We'll be told that very
shortly by our Python run.py--
well, if we call build_model.
So build_model is a
little bit strange, and it
deviates from the
standard paradigm that I
like to use in that it has a side effect
and doesn't actually return anything
to us.
So build_model is kind
of like print, where
you just run it and things
happen, and you don't necessarily
know what's going on underneath.
I'm not a huge fan of that.
I prefer a functional style model where
you get a return given some input,
but that's OK.
We're using this more as a weird hybrid
between scripting and modular building.
So it's kind of halfway.
So we can go ahead and
run this, and it should
run without problems, minus the
fact that I think I have-- oh OK.
Well, I also can't spell.
No surprise there.
Now that I spelled that correctly,
this should run mostly correct.
Yes.
input_size size is not a keyword.
We're going to go and look
at some documentation.
You would think I would
know that part, though.
I believe it is.
Well, OK.
I'm obviously wrong.
It's not input_size.
But I know there is something in there.
Let's look at-- oh, right.
Sorry.
Convolutional layers.
That's what I was trying to look at.
Conv1D.
Conv2D.
There's all these things.
So we know that we need a filter.
This is the number of filters that
the convolution's going to have.
The kernel size.
So those are two positional arguments.
And I actually might have--
yeah, passed those correctly.
Cool.
I just forgot how to name it input or
tell it what kind of input it takes.
Ah, input_shape.
input_shape.
There we go.
So that's correct.
So what this actually does--
and you might be wondering-- oh,
it's probably filter shape as well.
Or size filter.
There's all sorts of
variations on these.
So what this does is--
we didn't actually
have to pass an input shape
to all of the other filters
because they can intuit
them from the previous one
or from the previous
layer that was being used.
And so that is a cool feature, and it's
certainly one of the benefits of Keras,
is you don't necessarily
need to keep track
of all of the individual things
that are going on in between.
You can just stick to adding
layers in a sequential order.
All right.
I apparently don't
know the name of that.
One of these days.
Let's see.
Where do they put their--
they might have called that Merge,
or Merge is their own layer.
I haven't seen that one before.
Add.
Subtract.
Concatenate.
Oh, well we can also use MaxPooling.
And this will bring up--
wow.
Or it won't.
Oh wait, there we go.
Cool.
MaxPooling2D.
It seems to take a second.
Ah, OK.
Here.
We'll look at that.
MaxPooling2D takes not--
oh, it's pool_size.
That makes sense.
That's kind of intuitive.
All right.
Cool.
So we have corrected our
syntax, and I believe that fixes
all the rest of our syntax errors.
And that should be able to--
or not.
Did I misspell that?
Yeah.
Doo-doo-doo.
Ah, it might not take an activation.
You're really seeing this live.
You quite actually--
COLTON OGDEN: It's part of
the fun, part of the charm.
NICK WONG: It is part of
the actual fun to this.
There we go.
It's literally just tinkering around
with what exactly I remember and what I
don't.
Cool.
So we have now added correctly a
convolutional two-dimensional layer,
a max pooling two-dimensional
layer, a flattening layer, and then
two dense layers, the last
of which is our output one.
And that's going to return to us
a number that is either 0 or 1.
Well, kind of.
It will return to us a number
that ranges from 0 to 1.
It won't necessarily be 0.
COLTON OGDEN: We have
a couple of comments
here if you want to read some of these.
NICK WONG: Cool, yeah.
COLTON OGDEN: OK.
So GHASSEN says, "Here in Tunisia
we study many, many technologies,
and access to Silicon
Valley is restricted.
I want a guaranteed choice because
that would be very useful."
I'm definitely not an expert on
the programs that Harvard offers.
I would probably just say Google for
"international transfer programs."
I know we definitely have Harvard
students from Tunisia who have
come here, but I can't speak on that.
I'm not an authority on that.
and I don't know anything
about anything related to
Silicon Valley directly
because just familiar with
what goes on here in Cambridge
at Harvard University, I'm afraid.
But definitely do dig
around a little bit,
see what the research or the
transfer programs look like.
Look up Silicon Valley companies.
See if they have any programs
related to international work.
I know that some companies probably
do have something related to that,
although I'm not going to say--
I can't speak on behalf of international
work related laws, so I'm not sure.
But again, I would defer to
Google on that, probably.
So afraid I can't give any
better information than that,
but I'm not an expert on that.
42FORCE says, "Thanks for doing this."
NICK WONG: Oh, thank you.
Yeah, thank you for
being here and watching.
We appreciate it.
"What structure is a Sequential?"
So Sequential is actually its own class.
It's given to us by
Keras's model's submodule.
And it does work like a set, and
very nice intuition on using--
it has the .add method.
But that actually is unrelated
to the facts of how a set works.
I believe they do use
an underlying structure.
It's not a set, but I believe
there is an underlying list
to keep track of which
layers you added when.
But that add method has
a bunch of other stuff
that goes on underneath
to verify your layer
and translate it
accordingly TensorFlow-wise.
So very nice intuition, but
it actually is Keras specific.
And thank you, NUWANDA, for pointing
out I did miss an s in Keras.
Same thing at BELLA_KIRS.
I did miss the s.
I did miss that.
COLTON OGDEN: Part of the
fun of the live coding.
NICK WONG: It is one of the great parts.
COLTON OGDEN: I feel 100%.
NICK WONG: Yeah.
Awesome.
Are there any other comments
that were Going on here
COLTON OGDEN: I think we
grabbed all the questions there.
NICK WONG: Awesome.
All right.
So I just pushed the build_model
part, so you should have
access to building the actual model.
We are going to revisit the way
this model works because it probably
won't work super well.
It's not very complex, but
it does work in concept.
So now we get to the exciting part
of fitting our model to our data.
We have a model.
It's been built. We now just
have to actually fit it or train.
So I'm actually going to use
the word train because that's
what I called our data sub directories.
But we're also going to use just this--
it's actually basically a one-liner.
It doesn't really return anything to us.
It just takes the model
and says, you know what?
Now here's a bunch of data.
Tell us what happens when
we shove it through you.
And we give you the
answers along the way.
So again, syntactically this
is going to be kind of fun.
Go figure.
Even after years of doing CS, and years
of working with the same modules too,
I'm still looking up
syntax occasionally.
It happens.
It's OK.
So we're going to-- in
our train model, we're
going to want to have both the
training data and the testing data.
We're going to use the testing data at
each step to validate what's going on.
The training data is
going to do exactly that.
It's going help us train our model.
So we're going to use m.fit_generator.
And that's the actual parameter.
It's very similar to m.fit, except
I'm not supplying manual data,
I'm supplying a generator-- it's
very similar in concept to Python
generators--
that just generates data as we go.
It'll never run out,
which is really cool.
And I remember approximately
zero of the syntax for this,
or at least the names of them.
They do change from time to time.
This actually used to be nb_epochs.
And epochs or epochs is
just the number of times
that we run through the
training set of steps.
So it's how many times do we
actually just try to train the model.
And so what this means is that,
if we run like 10 epochs--
epochs?
Whatever it is.
You'll know what I mean.
If it sounds funny, that's OK.
You can make fun of me.
So as we go through for 10, on the first
time, the model's just totally fresh
and not trained on anything.
But on the second, third, and
fourth times, and every time after,
it's going to have picked up
knowledge from all the previous times.
So it's basically it practicing.
I would think of it as just
practice rounds for the model.
So we're going to start with just 10.
And then we're going to
say batch_size equals 20--
COLTON OGDEN: Does it
save these iterations
of data collection, data gathering?
NICK WONG: No, it does not.
So it doesn't really save
them anywhere on file.
So when you get to the end, it
actually just tosses the model,
unless you save it yourself.
So we're actually not going to save
them until later when we actually have
some models that we are satisfied with.
But no, it doesn't actually
save them on each epoch.
You can-- Keras has these beautifully
built structures for things.
They have these callbacks
which, if you're familiar
JavaScript callbacks-- come
from the same terminology.
But what that lets you do is
at the end of every epoch,
you could actually save
that version of the model.
And if you're running like 1,000 epochs
and you have just these enormous batch
sizes and you really want to
make sure that at every stage
you could tell us something
about the model at that stage,
then you would want to do that.
And I don't think I'll
probably cover that here.
It is a little bit more
advanced and a little bit more--
I don't necessarily know
it off the top of my head.
But super cool, and Keras has
all sorts of powerful tools.
And as I said earlier
at the very beginning,
they actually just updated
some of the documentation,
and they have all sorts of cool
things that I haven't even seen yet.
So I'm really excited about that.
WHIPSTREAK also just asked,
"Are we only using Python?"
Yes.
I happen to particularly love Python,
although you could also code this
in C++.
I believe they have libraries for it.
I don't know if Java does.
I don't believe it does.
But C++ would also probably work.
It would be a little
bit faster, probably.
But we're going to stick to the Python
implementation of Keras and TensorFlow.
COLTON OGDEN: It's clear that this
is quite a rabbit hole to go into.
NICK WONG: Yeah, it
really just fans out.
There's all sorts of
things you could do.
There's just so many ways in which
you can change what's going on here.
We're going to switch back
to get on our fit parameters.
What do we actually need
as far as that goes?
COLTON OGDEN: BLUEBOOGER
asks, "Could you use R?"
And his name is actually
blue in our chat
too, which is all the more appropriate.
NICK WONG: That's awesome.
Yes, I believe R has a library.
Actually, BHAVIK_KNIGHT
just answered that.
I believe there is a library for it.
I am not super familiar with
it off the top of my head.
COLTON OGDEN: I wonder if
TensorFlow-- does TensorFlow have--
NICK WONG: Yeah, I
believe TensorFlow for R.
COLTON OGDEN: Interesting.
NICK WONG: Oh yeah, look at that.
COLTON OGDEN: Oh, that's cool.
Yeah, TensorFlow does have
an R binding, which is nice.
NICK WONG: Yeah, look at that.
COLTON OGDEN: Cool.
NICK WONG: Yeah, so TensorFlow
is really beautifully well done.
It's a Google project, and
I'm a little bit biased,
but I think they do a really good job.
It's very, very cool what they've
been able to put together for us.
Let's see if I can find
where fit generator is.
It might be under the Sequential model.
Oh, actually they throw it
in image pre-processing.
I do remember that.
So let's go see what they actually do.
We're going to just copy all these
parameters because we're original.
And I'm going to paste them all here.
They did a 50--
COLTON OGDEN: Copying and pasting is
a real developer technique, though.
NICK WONG: It really is.
It is a very, very valid
developer technique.
COLTON OGDEN: Stack
overflow. #StackOverflow.
NICK WONG: Exactly.
And so we're going to just change
these to our variable names.
Steps per epoch.
2,000 is quite a few.
Generally speaking, you would want to
actually run many, many steps on these,
but our data's pretty small, and we
can actually get really good results
with pretty low numbers of steps.
COLTON OGDEN: And
oftentimes, big companies
are using massive server
farms for this, aren't they?
NICK WONG: Yeah, they use enormous--
COLTON OGDEN: Not just like a MacBook--
NICK WONG: Just computational power.
COLTON OGDEN: --or MacBook Pro.
NICK WONG: Yeah.
Yeah, we're running
this on my local laptop.
This is my just personal student laptop.
But yeah, a lot of big
companies are running
these on just enormous clusters
of paralleled networks and things.
They have all sorts of network
capable computational sharing.
They have some just
supercomputers running it.
They have some really just-- they
have a lot of money going into this,
and there's a lot of
just people really trying
to get these things to work
for all sorts of crazy things.
I know there's a project at
Lifts that does something really
cool with simulating a bunch of
just real life data in real time,
and they just test random
machine learning models on it.
Or not random, but their
own personal projects on it.
And that's super cool.
I know Google has, I'm sure,
just millions of products
that we don't know about.
There's all sorts of really
cool things going on.
All right.
So we have done this train model, which
does call the actual fit generator
method.
And what that means is I'm
going to then call that in my--
the actual scripted part of this
and call train_data and test_data.
And in concept, this
should actually run.
This should get us pretty close.
Oh.
OK, I tried to git push.
I made the mistake of going up and
pressing Enter without even looking.
That was great.
Gotta love the habit.
COLTON OGDEN: It's a
hard habit to break.
NICK WONG: It really is.
Ah.
You must compile your
model before using it.
That's entirely reasonable, and
I completely forgot about it.
Technically, build_model is incomplete.
I forgot to compile the model.
So compiling it means
you're telling TensorFlow--
oh man, I cannot type--
that you are done adding
layers to the model.
You want it to be all
put together, assembled
into tensors in this beautiful pipeline.
And so that's what we basically
end up having going on there,
and that's all we're going to run here.
It also takes a couple of arguments.
For example, it takes an optimizer,
which is, mathematically, a tool
that makes things a little bit
better as far as how each layer
or how everything takes feedback.
So when it's told what
the actual answers were,
it optimizes for making sure that
we don't interpret that incorrectly.
I would think of it like that.
That's not exactly what it
does, but it is the right idea.
I'm going to use SGD, which is the--
man, I am forgetting
names left and right.
That is the name for something.
Actually, we can switch this
to Adam, which is-- again,
I don't remember the acronym, but
it is a version of an optimizer.
They just these slightly-- well, some
actually majorly different things.
And you'll notice some different
results, depending on what you're doing
and which optimizer you use.
We're going to also add metrics.
And this takes a list.
We're going to do binary_crossentropy,
which sounds really fancy,
and great party term if
you're at a party of nerds.
It's a really fun term
to throw out there.
There's also categorical_crossentropy.
I think that one's even cooler.
It's even longer.
And so what that basically just
means is every time we do--
I got distracted by a comment.
That's really funny.
COLTON OGDEN: Let me go back
up to WHIPSTREAKS there.
He says--
NICK WONG: Right, sorry.
Ah, OK.
So, "I was away, only came back now.
Do summary."
Yes.
I don't know exactly where you
left, but we are currently trying
to get our model learning on data.
And so what that means
for us is that we want
to be able to actually run this train of
the model or fit the model to the data.
And what we-- or what I
forgot about in the interim
was that I actually have
to compile the model, which
means giving it an optimizer and what
metrics to use for how well it's doing.
And that's, I think,
what will catch you up.
COLTON OGDEN: And the video
will be on Twitch as a VOD
to look at later and
also on YouTube tonight.
You'll be able to look back
on it if you missed anything.
NICK WONG: Awesome.
And then-- ah, we're checking
in on who BHAVIK_KNIGHT is.
That's kind of cool.
COLTON OGDEN: Part of
the Handmade Hero stream.
I've checked that out a
couple of times, actually.
NICK WONG: That's sweet.
COLTON OGDEN: It's nice.
It's a guy who makes a complete
game from scratch 100% in C, which
is pretty cool.
NICK WONG: Wow, that's crazy.
COLTON OGDEN: And he's got
like 1,000 videos up right now.
It's pretty ridiculous.
NICK WONG: Damn.
COLTON OGDEN: But I guess BHAVIK_KNIGHT
is not the same person that's
on the Handmade Hero stream.
NICK WONG: Wow, that's crazy.
COLTON OGDEN: Just happens to
be shared by-- another person
happens to have that handle.
NICK WONG: I didn't even
know that was possible.
COLTON OGDEN: And then
GHASSEN says, "I recommend
to have a live session
of parallel programming.
It's just a hard thing to understand."
NICK WONG: Yeah, we can do that.
COLTON OGDEN: We could take a look
into that at some point, yeah.
NICK WONG: Actually, it'll
come up a little bit here too.
COLTON OGDEN: Yeah, OK.
NICK WONG: We do you
use it a little bit.
But yeah, that'd actually
be a really fun one.
We could even parallel code it
and then see if it runs that way,
motivate it that way.
And actually, that's--
I can't read that name, but--
COLTON OGDEN: It's BLUEBOOGER.
NICK WONG: Oh, BLUEBOOGER.
Ah, my fave.
All right, so BLUEBOOGER then pointed
out that we are parallel programming
right now.
COLTON OGDEN: Except I'm
not actually programming.
NICK WONG: This is true.
COLTON OGDEN: I'm a
bystander in this right now.
NICK WONG: You're a waiting process.
COLTON OGDEN: I am.
NICK WONG: You are the parallel
equivalent of a waiting process.
COLTON OGDEN: I am.
NICK WONG: That's awesome.
COLTON OGDEN: An
infinitely waiting process.
NICK WONG: Yeah.
The "while true" process.
COLTON OGDEN: A demon thread.
NICK WONG: Yeah.
Oh, man.
I think if you don't appreciate
puns and jokes in life,
then it's just kind of sad.
It's just really depressing.
All right.
So we have an optimizer.
We have metrics.
There is a third thing
that I am missing,
and I can't remember what that is.
So we're going to go
find it in documentation.
COLTON OGDEN: This is part of
the live coding thrill, man.
NICK WONG: It really is.
We're looking left and
right at documentation.
COLTON OGDEN: It's a good
documentation consulting tutorial.
NICK WONG: It really is.
Keras, your documentation,
it is a lot better now.
I really appreciate what
you guys did on that.
Great job.
It's making my life a lot easier.
It used to be, I think,
a little bit of a mess,
but there have been a lot
of clean cleanups on it.
Things have been updated.
It's great.
I'm a huge fan of up
to date documentation.
If you can read documentation
and be like, wow, things work--
oh right, "loss."
There we go.
COLTON OGDEN: 42FORCE
says, "What you said,
Nick, is true about puns and such."
NICK WONG: I really appreciate that.
Yes.
That's one of my life philosophies.
Especially when you're
sitting up late at night
and just trying not to stay up until the
sun comes back up, puns keep you going.
All right.
So I actually misspoke
a little bit earlier.
I said the binary_crossentropy was a
way of metricizing what's going on.
Apparently, I'm losing my marbles.
That is actually a
categorization of loss.
It is, in a way, a way of looking
at how things are going wrong,
but loss is basically--
there's a whole lot
of theory behind that,
but you could think of
it as the way that--
kind of the loss in
accuracy that the model had.
So on that run, how poorly was it doing?
The higher it is, the worst it goes.
The metrics are what
we're actually using
to display in a human readable format.
Loss doesn't necessarily
mean anything to me.
It could be, like, a 42.
That might be meaningful, maybe.
They're more useful
as a relative metric.
But metrics on their own, like
accuracy, that's super meaningful to me.
It means what it says.
It's an accuracy, usually
given as a percentage.
I think mine in this case will be
displayed not as a percentage but as
a proportion of 1.
So you'll get like 0.55.
Not great.
0.5 means we're literally guessing.
0.45 means we're doing worse than
guessing, so we're anti-guessing.
We got it right, but
then flipped our logic.
And then 1 is ideal.
"Ideal" in concept.
Cool.
COLTON OGDEN: Astly-- NUWANDA3333,
who's Astley [INAUDIBLE],, says, "Agreed.
Hope you do more sessions, Nick."
NICK WONG: Awesome.
Thank you.
I really appreciate it.
COLTON OGDEN: Tune in next Friday--
NICK WONG: Yeah, we'll
be here next Friday.
COLTON OGDEN: --for a
LInux command tutorial.
NICK WONG: I very much enjoy that.
I appreciate it a lot.
And now we're going to see
if we can get this to run.
That's one of my favorite--
I say that to myself
when I'm coding things.
Hey look, it worked.
I'm always-- I'm not
actually surprised it worked.
I'm a little bit surprised it worked.
Cool.
So I'll tell you what's
going on here while it runs.
It's running exquisitely
slowly, which is awesome.
It wasn't running so slowly last
night, but we're Livestreaming.
COLTON OGDEN: Exquisitely slowly.
NICK WONG: So slowly.
Everything you Livestream, something
that ran in maybe one second
will take four hours.
If you had a download that took
a second, it's four hours now.
There's just no getting around that.
COLTON OGDEN: It feels like four hours.
NICK WONG: Yes, especially when
you're sitting there just waiting.
But there's a lot for
me to explain here,
so we're going to go
through what's going on.
So you see this bar
increasing on the left.
That's telling you your
progress through the number of--
I'll see if I can find it
in the code because that
would contextualize what's going on.
The number of steps.
So each one of the--
oh man, that was awful.
Each one of these little bars
that goes through on the bottom
here is going to be one step.
Each line is one-- or sorry,
is one epoch or epoch.
And that's going to be just-- we're
going to run through 10 of them,
as per our parameters.
But then, our steps per epoch
is how many steps do we actually
go through trying to train our data.
And that's going to be
20 in this case, and it's
going to count through each
one that we walk through.
And then it tells us an ETA.
Those are generally fairly accurate.
I've found them to be pretty reliable.
This is the loss that we mentioned
earlier-- not particularly meaningful.
You generally want it to go down.
That's pretty much all we really know.
COLTON OGDEN: Also, your
computer is whirring right now.
NICK WONG: It's really funny.
If you run these in
class and you're supposed
to be paying attention
to lecture, then people
will start to look at
you as your computer just
starts to get closer and
closer to just exploding.
And I think it freaks people out.
They're like, oh god, why
is your computer panicking?
And then we get to this accuracy metric,
which is what we mentioned before.
And you'll notice there's
actually two of them.
There's accuracy here, and
then there's val accuracy.
What that stands for is this is
the accuracy on the training data.
So that generally will
go up just regardless
as it starts to memorize things.
But the validation accuracy--
excuse me-- should give
us some reasonable metric
for how well we're actually doing.
And what we can do is, if
this validation accuracy
is substantially higher
than the training accuracy,
then you're doing a pretty good job.
You're literally predicting data
that you've never seen before better
than the data you have seen before.
And that's not something that
happens very often, if ever.
It's something that
would be pretty rare.
If the validation accuracy was at
100 and our training accuracy was at,
like, 1/2, then--
oh, sorry.
I forgot that we were on the screen.
Right.
Thank you, Colton.
COLTON OGDEN: There it is.
NICK WONG: I appreciate it.
You'll see it.
I can actually probably move it up
a little bit, and that might help.
COLTON OGDEN: Duck down just a touch.
NICK WONG: There we go.
Oh, well that-- it's close enough.
So yeah, that'll show up again
when this epoch finishes.
And so validation accuracy versus
accuracy are really good to compare.
If validation accuracy is
substantially lower than accuracy--
and unfortunately, that
happens kind of often--
that means you've probably
over-fitted your data.
Because when you're given
new data, you're just like,
oops, I don't know what's happening,
but given data that you've seen before,
you're pretty good at it.
However, what you might notice--
and it takes a little bit at the end
here-- you'll notice it freezes
on that last step in the epoch.
That's because it's running
all the validation steps,
and they take a little bit too.
You'll notice that our
accuracy is at 0.5,
and it's staying uniformly
there, which is not great.
That basically means
we're randomly guessing,
and we're randomly guessing really well.
We're just really random.
And what I mean by that is
even if I were to flip a coin,
I would probably hover around 50.
I'd have a mean of 50 and an expectation
of 50%, 50% heads or 50% tails,
but I wouldn't get exactly
50%, at least not usually.
So the fact that we are sticking
at 50% is a result of the fact
that our data's pretty well balanced,
but also we're just really random.
We're true randomness here.
We're literally guessing.
And so that's not ideal.
Probably not what we were looking for.
So that means that we now have
to debug the actual model.
And I guess we deliberately left this
here, where I made some of the mistakes
that I made last night, but I made
them again for everyone else to see.
And that's because they're really
common mistakes that show up
all the time in machine learning.
So it's really easy, usually, if you're
given some sort of Python code or C
code-- how do you debug it?
How do I go about fixing that code?
And the problem with machine
learning style things
is we don't necessarily know
where to go debugging-wise.
There's no real article on how to
debug a machine learning model.
There's a bunch of
really technical ones,
but there's none that are really
as approachable as this code seems
to imply it should be.
So we have a bunch of things to look at.
How do we build our model?
How are we getting our data?
How are we manipulating our data?
And what kind of optimizer are we using?
And what kind of activations do
we have within building our model?
So I'm going to let this keep running,
and we'll stay at 50, but that's OK.
It's cool to watch it go.
We can also make this a lot faster.
So there are some other
things going on here that
can make our lives a little bit better.
Let's go about making it faster first.
So this is use_multipleprocessing, which
is something that I think is correct.
And we're going to say false.
But I'm going to say
the number of workers
or the number of independent
threads you can spin up is 4.
And what this means is a lot
of machine learning stuff
can actually be done in parallel.
I don't have to do it all in
one thread on one processor.
I can spread it across as
many processors as I want,
limited by the number I have.
And so what I'm going to do is
I'm going to say, you know what?
You can actually use 4
workers or 4 threads.
And I turned off multi-processing.
If you use both at the same time, Keras
will give you some warning and be like,
yeah, don't do that.
And the reasoning for that
being, basically, you're
attempting to do two
versions of the same thing.
I say that, and I'm sure
someone somewhere just cringed.
They're not actually the
same thing, but it would
accomplish a lot of the same goals.
So we're going to just use
one instead of the other.
And I'm going to rerun this now.
It should run a little bit faster,
which would be ideal for us.
COLTON OGDEN: Machine
learning takes a long time.
NICK WONG: Machine learning can be
very problematic as far as timing goes.
[INAUDIBLE]
COLTON OGDEN: Learning in real life
takes a long time, so it makes sense.
NICK WONG: Yeah, exactly.
And we have one of the most powerful
computers in the known universe,
actually, which is crazy.
So it is going very marginally faster,
but not necessarily a whole lot.
All right.
So now we need to look
at, well, what are we
doing that might be breaking
our machine learning model?
Why is it not learning
in the way we want it to?
So some things-- and this is where
we get into a guess and check
sort of thing, and the
programmatic part is
where you're looking, where
you're guessing and checking.
So the first place I might look
is in the way I built my model.
Is there something
inherently that jumps out
that tells me, yeah, this is incorrect,
like something here just doesn't work?
So I noticed that my activation
here is sigmoid, which is right.
That's what I want for a binary
classifier because of the same reasons
that we mentioned earlier.
My activation in all intermediate
steps is also sigmoid,
but I could change that.
I could make it relu.
I don't actually know
what that stands for.
I did at one point.
I don't anymore.
Or something like tanh.
And both would be reasonable.
There's no real reason to pick--
there is a real reason to
pick one versus the other,
but we don't necessarily need to care.
But I'm going to leave
that actually as sigmoid.
I'm going to look at the original
activation, which is also sigmoid.
And that might be kind of problematic.
It might not necessarily be
the source of our bug exactly,
but it might also be
something to reconsider,
in that we said that a
sigmoid activation creates it
so that you're in a binary state.
It's either down or up.
And we don't necessarily-- thank you.
MAGGUS503 just pointed out that
relu is rectified linear unit.
Thank you.
COLTON OGDEN: And GHASSEN said,
"Can I work with you guys?
I need a Skype interview
with a company in America."
So CS50, to the best of my
knowledge, is not currently hiring.
When we do hire, we
accept all applications.
Normally, they're posted on
our website, cs50.harvard.edu.
But like I said, I don't believe we have
any job openings currently available.
In terms of getting a Skype interview
with a company in America, that's
also something that we probably won't
be able to assist with, but definitely
reach out to companies you're
interested in working with.
Most companies have links on
their website for applications.
Definitely build a portfolio of
projects on GitHub or the like
so that you have more
code to share with people.
And keep the search going,
but I'm sorry that we're
unable to provide any
more than that currently.
NICK WONG: But best of luck.
COLTON OGDEN: Yeah,
definitely best of luck--
NICK WONG: Very good luck.
COLTON OGDEN: --in finding something.
There's tons of openings, I'm sure.
NICK WONG: Yeah.
All sorts of companies want people
who know anything about coding
or are looking for just people to,
I guess, put in effort and work.
I think-- we'll go on a
short aside, like for four
seconds, that I think that
don't ever lose motivation
on these sorts of things.
As someone-- I sent out I think
like 104 job applications last year.
COLTON OGDEN: That's dedication.
NICK WONG: I got rejected
from most of them.
You're really trying to
get a job, and for me it's
like, well, I want to be doing
something with my life over the summer.
I want to actually be contributing.
So just don't give up.
Just keep going, keep pushing through.
Rejection-- people very clichedly will
say, like, rejection makes you grow,
or rejection teaches you stuff.
But I learned a lot from
my rejections, and I think
that they actually do help you a lot.
So [INAUDIBLE].
COLTON OGDEN: Yeah, there's
a phrase that I like that's--
who came up with it?
"Be so good they can't ignore you."
NICK WONG: Oh, right.
COLTON OGDEN: Steve Martin, I believe.
NICK WONG: Yeah, I think so.
COLTON OGDEN: That's a good phrase.
Keep working hard, and if you're really,
really, really good at what you do,
you just won't help but be able to get
something somewhere. that you want.
NICK WONG: I think Lang Lang, the
pianist, has a phrase or a story
in his book where there's someone who
hates him and is a judge for his piano
competition, and even they
can't deny how good he is.
I think that that's
really just super cool.
I think that's super inspiring.
All right.
So we did change some stuff about
what was going on in our model.
I rectified, so to speak, the
activation of our input layer.
I changed it from sigmoid to
rectified linear unit or relu.
Relu.
And that actually caused our model to
start doing some interesting things.
It's still very slow, and
we added some extra workers,
but it's not necessarily
going that much faster.
But if we look down
at our metrics here--
and I believe Colton might
be in one of the metrics,
but we can just raise it up.
COLTON OGDEN: Oh, I'm sorry.
NICK WONG: Oh no, you're all good.
We can just do this.
COLTON OGDEN: Cut off there.
NICK WONG: I think it's above you now.
COLTON OGDEN: I'm trying to go this way.
NICK WONG: There we go.
I think you're good.
I think you're good.
COLTON OGDEN: Cool.
NICK WONG: All right.
So what we can look at
here is in this first line,
in that first epoch, what
we see is our loss is--
whatever.
It's some set of numbers.
But our accuracies, our accuracy
and validation accuracy,
are not 50-- or 0.5.
Sorry.
I'll probably refer to
them as percentages,
but they are technically
fractions between 0 and 1.
So they're actually 70 on our training
data and 100% on our testing data,
on our validation done.
And if you recall or maybe you're
currently watching in the future-- huh,
weird--
then you might recall that I
said it's pretty rare that you
have your validation accuracy go
higher than your actual accuracy
or your accuracy and your training
data because you generally
learn you're training data lot
better than your validation data.
But in this case, we are using
something that's fairly simple,
and we are technically solving a
problem that isn't too terrible.
So we actually see that
our validation accuracy,
in now two epochs out of
three so far, has been higher
than our training accuracy.
And we do happen to have just more
variance within our training data set.
It's bigger.
It's double the size.
So it makes sense that
we might see something
like this for a pretty simple problem.
So we're going to let that keep running.
It's still very slow.
And something that-- the
reason I keep pointing that out
is to motivate the rest of-- or the
next part that I'm going to talk about.
But it would be really cool if I could
speed that up and not lose accuracy
because that would be-- that's
the ideal, if I can make machine
learning model run really quickly,
really cheaply, and not lose accuracy.
COLTON OGDEN: Millionaire.
Future millionaire.
NICK WONG: That'd be awesome.
You could you make a
start right there on that.
And that's a gross
oversimplification of the problem
and certainly not
something that we can do,
but there is something that we can
do to fix what's going on here.
Because I've mentioned
earlier that these images,
the size doesn't really
matter that much as long
as we keep most of the important
data or most of the features.
We're using some pretty large images.
They're sized 500 by 500.
And so if we're running through,
what, 20, 40 images, and we have 500
by 500 for each, well, 500 squared,
we're on the order of 10,000,
or I guess 25,000 actual pixels
or data points, times 40.
So we're at, at the very least,
what is that, 2 million or 200,000?
I'm not very good at math.
And that's OK.
I think we're on the order
of a couple 100,000 things
and calculations that have to go through
all the time, and that's terrible.
It's definitely not what we're
looking for and I guess not
what we really need.
So I would go through and
change all of these 500s
to then maybe something like 150,
a very common version of that.
The problem is, I wrote
it in a bunch of places,
and it's going to just
change in one way.
I'm going to use pretty
much square images forever.
So this is a pretty good place
to switch to some variable.
So im_dim or image dimensionality--
oh actually, that's not
a great variable name.
It means something else.
We'll say image-- we'll
call this one width.
It actually doesn't matter
which one we define as width
and which one we define as height
as long as we're self-consistent.
So I'm going to say image height
and image width are in that order,
and I'm going to replace
all of our 500s with those,
which should, if we don't
screw up missing one of them,
should help us out a little bit.
And then, similar to how
we defined model up here,
we're going to also
define each of those.
And we're going to bring that
down to about 150 by 150.
Let's make sure that I
didn't leave any spare 500s.
Cool.
And now we know that we can control
the image height and width by just
changing a configuration variable.
And in my previous project or in
the talk that I gave last year,
the code that I used for that actually
has just a configuration module,
and you can just change config
variables and it will change everything
about how it works.
And so I think that, generally,
moving those out of the actual code
so that you can think of the code in
terms of abstractly what it's doing
can clean up a lot of your
actual debugging and processing.
So we're going to stop this, the
currently running training session.
And it says, "User aborted!"
And that's great.
We're going to run it again
but with our smaller sizes,
and we're going to see if that
changes the speed at which we go.
And I say that like I didn't know.
COLTON OGDEN: Visibly it looks like
it's definitely moving a lot faster.
NICK WONG: Yeah, it's so much faster.
And you'll notice our
accuracy has not gone down.
We're still interpreting these
images pretty accurately.
And you can think of this in a
human context is if I handed you
a really small image
versus an enormous poster,
you could tell me pretty quickly
whether either one is dark or light.
You could look at the smaller version
and be like, yeah, that's dark.
And you look have at
the big poster board.
Yeah, that's light.
And that's pretty
immediately doable for us.
So this is basically what we're seeing.
We're seeing the machine
equivalent of that.
And right now, you could argue
that we've over-fit our data.
That's probably true.
But our validation accuracy
is still also true.
The problem is that that might
lead you to think, oh, well then we
can now use this model and predict
on our prediction data, which
is definitely our next step.
But that's not entirely the case.
You'll notice that loss
parameter actually has
continued to go down from row to row.
And that tells us something about
what we're doing to our data.
It's one of the only times that I'm
going to point at loss as something
that we really want to consider.
As that continues going down, it
means we're getting closer and closer
to just getting it right.
But that's problematic
on our training data
because it means that
we're over-fitting.
We're going to just hyper-fit
ourselves to this data set,
and we're going to put on our
blinders and say, this is all I know,
and this is all I can ever deal with.
That's really problematic for images,
where even one pixel difference means
that you have a different
image technically.
So we want to prevent that.
And luckily, right before
we go into prediction,
we actually have a layer that does that.
So we're going to add that layer in
between, sandwiched between two Denses.
And that layer is called Dropout.
And I know we are running a little
bit low on time, but that's OK.
I think we are actually
going to run perfectly into--
COLTON OGDEN: We can go--
NICK WONG: Finish this.
COLTON OGDEN: --a few over if you
need to take a few minutes to--
NICK WONG: All right.
COLTON OGDEN: Fairly
flexible format on Twitch.
NICK WONG: Right.
That is a good point.
That's actually one of the
beautiful aspects of this.
All right.
So what we've done here is we've added
Dropout, which means everyone once
in a while, we're going to
just randomly drop out data.
We're going to just ignore
it for that training session.
And that's really cool.
It means that we can actually
counterbalance the over-fitting
that we might do.
I said 0.2, but I'm going to
make it really aggressive.
The term "aggressive dropout" is
something that I think is really funny.
It makes me think of a college
kid who just drops out of college
and is extremely aggressive about it.
But yeah, we have this
aggressive dropout,
which means that we're dropping out a
pretty high number of things or data
points at each point.
And that's going to help us prevent
ourselves from over-fitting.
I'm also going to, now that we have this
whole thing working on up to training,
I'm going to add that to GitHub.
oops.
"Added model training."
And then we can git push.
And so now what we have left to do is--
can we actually try
and predict on the data
that we have in our
prediction directory?
So that's going to be our last step, and
we're going to say that our predict--
our predict on, and we'll say
image as well because that's
where our prediction data lives.
So then, in here I'm going
to say define predict,
and it's going to take
an img_dir, and all
we have to do is let's recall what
the actual structure of predict is.
So under Image, under
Predict, it's just images.
And what I might say is, OK, then
let's actually just take those images,
and we're going to save their paths.
I need to be able to
save their actual paths.
And that's actually what I
had intended to do over here.
I just conflated the two in my head.
And we now have this
lovely line of code.
There is no actual need to do
any of this os path joining.
If you'll recall, we're
just using listdir
to tell us what images are in that.
And then we're going to img_dir
predict of what's going on in there.
And this should give us
access to all of the images
that we actually want to use.
Let me actually think through that
before I tell you that that's the case.
Ah. os.listdir.
I actually do need the os.path.join.
Oop, not "jin." "join."
That's one of the features
I don't like of VSC.
And "predict."
So now we have access
to all of the images
that we want to have prediction on.
And I'm just going to call
these im paths or img_paths.
And the reason that I'm
going to keep track of those
is so that I can tell which image I'm
actually making a prediction on later.
And so I have to now
load in these images.
And this is where we actually use cv2.
So let's say images is equal to--
and I'm going to use, again,
list comprehensions. cv2.imread
of img for img in img_paths.
And this will allow us to actually
read in each of the images.
And then I'm going to again do images
is cv2.reshape, I believe, of the img.
And we're going to
reshape it to our height.
Oops, I called that im_height.
im_height, im_width-- god I
love the auto-complete-- by 3.
And this is, again, for img in images.
Cool.
And what this basically does--
and I'm abbreviating the steps
and cutting down a little bit on
my narration-- but cv2.imread means
read the image into
what we're dealing with.
It reads it in as a NumPy array.
And then this cv2.reshape
of the img actually puts it
into the right shape for us, I believe.
I think that's a necessary step.
I might be conflating it
with the NumPy version.
And there's also-- yeah, I have a
feeling I mixed these two together.
We're going to actually
comment that one out for now.
I think I'm talking about the NumBy one.
We have numpy.reshape, and
that sounds much more correct,
so I'm actually going to just
copy the line I had above.
And this basically just takes
the images, like dimensionality,
and reformats them a little bit
so that we can actually feed them
into our machine learning model.
Our pre-processing step before up
at the top when we load in the data
actually did that for us.
We just didn't really realize it.
Cool.
So this should be all
of our actual images.
And then we're going
to say predictions--
actually, we can just return from there.
We can return again a list
comprehension of m.predict_classes.
I don't know if it's plural.
We'll find out.
Gotta love the just
random guessing sometimes.
On img for img in images.
And this will tell us, what
does it think each thing is?
However, that's going to return to
us something that's a little weird.
And we can actually printed it.
Printed it out?
Who knows?
We can look at what those
predictions might look like.
And since we're debugging this and
not actually the number of epochs--
or sorry, not the actual
model, we just want
to see what it would look like later--
we can actually reduce this to
two steps per epoch and one epoch.
And that's going to be really fast.
It's going to just skim through.
Oops.
I just did git push again.
There we go.
Cool.
I have invalid syntax,
and that makes sense.
I forgot the word "in" on line 81.
Doo-doo-doo-doo.
That's one of those things where
if you're watching someone code,
you see that immediately,
and you're like, no!
How did you forget that?
But then when you're coding
it live, you're just like, eh.
All right.
Cool.
Cannot reshape an array of size
150804 into shape 150, 150, 3.
I'm going to actually
cat a piece of code
I wrote a long time ago
to see what that was just
so I can verify what that resize was.
Ah, cv2.resize.
OK, so there was actually a step there.
Sorry.
I'm peeking at some
code I wrote earlier.
It's code from a different project,
but it does do the right thing.
COLTON OGDEN: Code reuse
is an important thing.
NICK WONG: Code reuse.
So OK, we have cv2 resizing the image
to the right dimensionality for us,
and then we have NumPy reshaping
it into the proper array for what
we're actually looking for.
And that should actually be correct.
The rest of this is roughly true.
And I'm going to stop looking
at my previous code now.
Cool.
So then, let's go ahead
and print these out
and see what that looks like for us.
42FORCE points out, "Code
reuse works all the time."
Yes.
I am generally a big fan.
All right, so we get these
just random looking arrays.
They don't look particularly meaningful.
This is a NumPy data structure
where you have an array
and it has a super listed in number.
It's 1.
The other one could be 0, but
it's actually they're both 1.
And then our dtype is a 32-bit integer.
So that's not super meaningful to
us, but if we actually just access
the 0th element of the 0th
element of each of those arrays,
we'll just get the numbers back.
And then what we can do is--
I'm actually going to
also print out which
image path that's associated with.
So I'm going to say that img_paths
at i, i in enumerate of images.
COLTON OGDEN: MKLOPPENBURG says,
"Will have to finish this later on.
It's been a joy.
Thanks Colton, Nick for doing this."
NICK WONG: Awesome.
COLTON OGDEN: It's been a good time.
NICK WONG: Thank you.
We appreciate it.
COLTON OGDEN: GHASSEN says, "Can I guys
send you my CV so that you take a look?
I built a great resume."
Again, I don't believe CS50 is currently
hiring or looking at CVs or resumes.
Normally, when we do, we send out--
we have an apply link setup
which is currently not accepting.
But particularly if you're interested
in working for a Silicon Valley company,
I would do research into
companies in that region.
Check out their website.
Check out their job applications.
And then submit your CV there.
You'll probably have much
better luck doing so.
But thank you for the--
thank you for offering to us.
And if we are hiring in the
future, definitely submit it.
And then BHAKIV_KNIGHT says, "0, 0 in
brackets would do as well for NumPy."
NICK WONG: Yes, that is true.
I think it also works for Python.
I'm just generally a fan
of the old-fashioned way.
I'm not that old, but I am
certainly an old-fashioned user.
All right.
So I am still copying things to
speed things along a little bit.
And then, I will tell
us what's going on.
All right.
So we can actually then go from here.
All right.
So we want to be able to map between
the numbers and the actual classes
that we're talking about, like
light, dark, things like that.
So what we're going to say--
nice.
All right.
Colton got called out for
his great people skills.
That's true.
He does have fantastic people skills.
I wanted to make sure that he didn't
end up reading his own compliment.
COLTON OGDEN: Thanks, Astley.
Appreciate that.
NICK WONG: He does a
great job with people.
All right.
So we're going to define invert mapping.
It's something that I
think is just useful.
Given a dictionary, which
I'm going to call d,
we're going to have inverted,
which is the inverted version
of that dictionary.
And I can say, "for key in d."
And actually, you could say
"key, value in d.items."
This might make it a
little bit easier on us.
Then we can say inverted at
the value is equal to the key.
And this assumes a lot about
your dictionary and how it works,
but that's OK.
We can actually prove that
those assumptions are valid
because of how Keras defines
the class indices dictionary.
But that basically allows
us to switch it from--
it gives you the index name or
the label name with the number,
and I want the number with
the label name mapped to it.
So I just invert the dictionary for us.
There might actually even be a Python
function that already exists for that.
I just don't happen to know it.
COLTON OGDEN: BHAVIK_KNIGHT has a
dictionary comprehension just there
in the chat.
NICK WONG: Ah.
Yeah, that's perfect.
If you look in the chat, BHAVIK_KNIGHT's
version of the dictionary inversion
is exactly what I just wrote out, but
in one line and certainly very readable.
So very nice.
Cool.
So now that we have this kind of
mapping, we can then just go through.
And for our prediction---
or actually, we're going to say the
I think value is what I called it,
value and im_name in predictions.
We can actually now print out
what each of those things was.
So "We think that im_name is val."
Oops.
Sorry, not val but
rather mapping at val.
Cool.
And if we run this through--
oh, that's not what I wanted.
That's what I wanted.
If we run this through really
quickly, then this will not actually
build our model correctly.
It's certainly not the
right version of the model.
It's not going to get things right.
But what we are going to
have is at the very end,
it'll print predictions on any image
that's in our predict directory.
And that's what we see at the
very bottom here, is that it says,
we think that the dark_1.jpeg is light,
and we think that light_1.jpeg is also
light.
So it got one of them right
and not the other one,
which is not super great for us.
COLTON OGDEN: 50%
NICK WONG: 50%.
But we know that if we train
things a little bit longer,
we can actually do a lot better.
COLTON OGDEN: FORSUNLIGHT
says, "Nick, old is gold."
NICK WONG: I'm a huge fan.
I also love that the old way
of labeling global variables
used to be by prepending a g to them.
COLTON OGDEN: Oh yeah.
NICK WONG: So that's actually--
I don't know if you intended
that, but it is certainly
the greatest pun on that.
All right.
So what I promised at the beginning--
I can, I guess-- hopefully
you'll take on faith
that if we increase the number
of times that we train this
and allow it to run its full course,
we could actually get this to a point
where it is correctly predicting
on light and dark images.
However, I promised that we could
do cartoon versus real images,
and so let's actually set up that data.
And we'll find that it's
actually really easy.
The way that we set up this
structure, all we have to do
is replace the image directory and
then re-run our script, and that's it.
And so what we're going to do is
I'm going to call this img.old.
And then I'm going to just
copy it and create a new one.
Oh, I can't paste it
into it's own location.
Bummer.
That's OK.
And we're going to now
create this new image which
still has predict, test, and train.
It's going to have two
different jpegs in there.
And in test, instead of
having dark and light,
it actually has cartoon and real.
COLTON OGDEN: GHASSEN
says, "Like swift 3.
Very interesting.
We spoke about SQL last session.
I hope that we can
build a common platform
and start talking programming."
Yeah, Swift is a good idea.
I'll maybe see around if anybody
knows how to program in Swift
and wants to maybe make a
simple application on stream.
If you want to maybe read
TWITCH's last comment there.
NICK WONG: Ah.
All right.
So TWITCHHELLOWORLD says, "Thank you.
This is so interesting.
I heard that the later AI that triumphed
over the initial program, which
won over the human at go, had
not been trained by humans,
rather simply given the rule's
games, then left to train itself."
Yes.
That's reinforcement
learning at its best.
"Is that a type of coding that is called
AI as opposed to machine learning?
How is it similar or different
in terms of the coding?
Thanks."
So yeah, fantastic
question, and something that
is one of the greater confusions
with how AI and machine learning
are related.
A lot of times, AI
utilizes machine learning
practices in order to generate
what looks like intelligence.
And the goal is actually to
simulate human intelligence.
That is the benchmark, give or take.
And so what TWITCHHELLOWORLD
points out there,
which is that the AI, or AlphaGo,
that beat a human being at go
was not actually trained by humans
and was just handed the rules
and figured it out.
That's really crazy.
It's one of the most powerful
versions of machine learning,
or artificial intelligence I
think is actually much more close
to what you're actually going at there.
And it's super cool that
it was able to do that.
That is a completely different.
COLTON OGDEN: Just played a ton of
games against itself, basically--
NICK WONG: Pretty much.
COLTON OGDEN: --and figured
out what led to a victory?
NICK WONG: It kind of simulated
it in its head and figured it out,
and that's nuts.
That's insane.
Actually, there's this really cool
version of that type of learning.
It's similar.
It's the reinforcement
unsupervised learning
challenge bu I think Microsoft.
And they use Minecraft for it.
So you actually build a Minecraft agent
and have it compete with other agents
to survive.
And that's something that is also on
my list of projects for winter break,
is to build my own Minecraft agent
and see how I can do on that.
COLTON OGDEN: See if you
beat out everyone else.
Battle royale.
NICK WONG: Battle royale.
I'm a huge fan of building
agents for online video games
like PUBG, things like that.
Also, we're going to just start
dragging cartoon portraits of people--
COLTON OGDEN: Oh, nice.
NICK WONG: --onto our data list.
Now, generally speaking, you
want to be really careful
when you're picking up human data
because there are a lot of racist AIs
out there.
And that basically just
means they were trained
on data sets that weren't complete.
These data sets did not have
representations of all kinds of people,
and that's really important.
It's something I actually
feel very strongly about--
making sure that people realize that
you're just doing bad science if you
don't have a complete data set.
So even in the worst case,
where I can't, I guess,
help you from being racist,
you should certainly
be able to recognize
that it's bad science
to not have a complete data set.
And in the best case, you realize
that being racist is not ideal,
and so you are also trying to
obtain the real goal of being
representative and inclusive
of everyone that could possibly
be using your device.
COLTON OGDEN: Well said.
PUPPYLIONHD says, "Halfway
in this CS50 course,
should I be able to
understand all of that?
Because I don't, and it's
kind of frustrating."
NICK WONG: I would argue certainly not.
I think even if you were working on--
if you were all the way
through CS50, I would
argue that you shouldn't necessarily
be able to just understand
this right off the bat.
And actually, yeah, I think it
should be a little bit frustrating.
It certainly was for me when I began.
And I know for a lot of people it
is constantly very frustrating.
So I think what I would advise,
or my general advice for that
is, yes, it's very frustrating
at the beginning and throughout,
but looking back at what you
can do now is a really good way
to alleviate that frustration.
So for me, when I went into CS50,
that was my first time I'd ever coded.
That was two years ago.
We're I guess getting on three.
COLTON OGDEN: Are you a junior now?
NICK WONG: I am a junior, yeah.
And so I actually took CS50
as my first ever CS class.
I had never really coded before then.
I had built computers
and things, and so there
were some we'll say routes
for doing some computer stuff,
but I had never actually
written a line of code.
And so I was very lost.
And I give a lot of credit to
my TF at the time, actually,
for helping me with how CS
could be a big part of my life.
COLTON OGDEN: Who was your TF?
NICK WONG: His name was Vik Jayaram.
COLTON OGDEN: Oh, yes.
NICK WONG: So if you're watching, then--
COLTON OGDEN: Shout out to Vik.
NICK WONG: Yeah, shout out to Vik.
COLTON OGDEN: I know Jik--
Vic personally.
I can't talk.
NICK WONG: He's a great guy.
COLTON OGDEN: Yeah, he's super cool.
NICK WONG: I still remember the
sections that I was in with him.
And he also was super willing
to be like, yeah it's hard,
but you can do it.
He was very encouraging in that sense.
And I give him a lot
of credit for making
me feel like I could actually go
through and accomplish a lot in CS.
I've been teaching the class
that he taught for two years now.
So that's very cool.
And I was really excited about that.
And I like to tell it
to a lot of my students,
is that I started out not that
far from where you are now.
I really wasn't all that different.
And I think that that
can be really helpful,
especially if you're sitting
there and you're like,
wow, this seems very
complex or it seems absurd,
it seems basically impossible
for me to accomplish.
That is certainly not the case.
And it's not the case that I hope
any CS people or any CS staff
ever propagate that opinion.
I think that it is very
important for people
to realize that CS can be for
anyone that wants to be in it.
I think that it rewards people
who have natural talent.
That's true.
Almost any field does.
But it particularly will really
reward people for putting in effort.
And a lot of fields are
like that too, where
you will actually get a lot of rewards
out of it for putting in real effort.
COLTON OGDEN: Yeah, and all these
streams, they take a long time,
and it's just a small
fraction of the amount of time
that it actually does take
to do all of this stuff.
NICK WONG: That's true.
COLTON OGDEN: It's time
consuming, but if you
enjoy it and you put in the
work, it's very rewarding.
NICK WONG: Exactly.
COLTON OGDEN: And it's fun.
It can be fun.
NICK WONG: I could not agree more.
COLTON OGDEN: "Nick is
not racist and loves puns.
Great addition to the channel."
Yes, I very much agree.
NICK WONG: Thank you.
I appreciate it.
COLTON OGDEN: "What is the difference
between React and Angular?"
NICK WONG: Oh, that's a good question.
COLTON OGDEN: So unrelated to
machine learning, but in a nutshell,
they are both front end
frameworks for web development.
They abstract what it means
to do for an end development
and make it a bit more modular
and are more high level.
Tomorrow, we're actually going be
talking about React with Brian Yu--
NICK WONG: Hey, Brian.
COLTON OGDEN: --where we can maybe
do a deeper dive into the differences
and nuances between the two.
But React is certainly the
more popular presently,
although Angular has
been around for longer
and has also had a lot of
fame associated with it.
"Is it safe to study the same
sort of coding and courses
as machine learning to eventually
execute unsupervised learning?"
NICK WONG: So let's see.
Yes and no.
Yes in the sense that you need the
basic background and other information--
oh, sorry.
Ignore my desktop, it's a mess.
You do need a lot of the same background
and basic information and practices
that you see in this supervised rigorous
learning that we're doing right now.
But you also would be exposed
to a lot of new techniques
that people realize
they could use when they
didn't have to actually watch or give
answers to their AI or their machine.
There's also a lot of different
best practices in play,
like I'm not really
necessarily collecting data.
I might be, as was pointed out
earlier, I might be pointing out rules.
I might be looking for patterns
that are a little bit broader
than the actual data
that we're looking at.
And that can be really
important, especially
if you're creating these agents.
Then you give them a set of rules,
and then you see what they do.
Or you might give them a set of rules,
see what they do for a little bit,
feed them some information as
a response to what they did,
and then let them go again.
So there might be interactions.
Actually, I think a
lot of the time there
are interactions between
this unsupervised learning
and the supervised learning.
So yes, you definitely would want--
I think this is easier to start with.
It's a little bit easier
for us to contextualize.
Excuse me.
But you will learn a lot
more in that field as well.
There is a lot to that on its own.
I think this is a good
place to start, though.
There are a bunch of questions.
COLTON OGDEN: "What is the
best technology that fits
for certain and guaranteed hiring?"
Honestly, that's a hard question to
answer just because every industry is
a little different.
Every niche in every industry
is a little bit different.
I would say figure out what you
want to do in computer science
or whatever field you're interested in.
Do a deep dive on it.
Learn a lot.
Spend a lot of time figuring
out whether you enjoy it or not.
And make some projects.
Flesh out your GitHub a bit.
Reach out to people.
Get some smaller jobs.
See if their work
experience is fulfilling.
And build upon it from there.
But it's hard to frame it as there being
any sort of magic bullet or magic trick
because at the end of the day,
it's going to be a lot of hard work
ultimately, because if it was easy
and free, everybody would do it
and everybody would have a
very well-paying job in tech.
NICK WONG: That's true.
COLTON OGDEN: So the reality is you're
going to have to spend a lot of time
figuring that out for yourself
and doing research and getting
good at various technologies,
and ultimately probably finding
a specialization or a given
strength in a particular field.
But good question.
NICK WONG: Very, very good question.
COLTON OGDEN: FORSUNLIGHT says,
"This is the real power of teaching.
Connection fuels commitment.
I guess daily live streams will
increase the commitment of students."
I think so too, and I honestly hope that
this channel helps inspire other people
to dig into more projects
of their own and we
get to build some really
cool stuff on stream.
I know today's has been really cool.
It's been very unique, all the ones
we've had so far, and very technical,
which is nice.
The deeper we can go into this stuff,
I think it shows a little bit more
of the reality of actually
getting into the nuts
and bolts of this kind of stuff.
NICK WONG: Yeah.
I'm super excited that Colton
asked me to come and join and be
able to present with all you guys.
But also, I think Colton's
idea for just having
a Twitch Livestream, that's fantastic.
I think that's super awesome
for what you guys get to do.
And you get to have just
new topics all the time.
It's so cool
COLTON OGDEN: I get to come in and
not even have to prepare anything.
It's great.
I can mess up live on
stream and everyone sees
what it's like to be a real programmer.
How about that?
NICK WONG: Actually, that's a
really important part of this.
And Colton told me
about it last week when
I was thinking about what to do for
this, is that being able to mess
up live on camera, that's great.
I think it shows a lot of people
just the ridiculousness of the belief
that people just are monolithic
coders, that they just come in
and they just go boom, boom, boom.
Those coders, I guess, do exist,
but they aren't necessarily--
they're usually a product
of having done it a lot.
They've sat down and
really fleshed this out.
So having I guess the
live version of that,
going online and having that in
front of you, that's really cool,
and it's something that I wish
you saw more in other fields too.
COLTON OGDEN: Yeah.
A big trend is making an
app in 10 or 15 minutes.
But the reality is it's very unlikely
that any actual app or project you make
is going to take 15 minutes.
And those videos are
cool for introducing
at least the concepts behind
a lot of those ideas things,
like building the games and such.
GHASSEN says, "Thank you, Colton.
Hope to be friends on Facebook."
Yep.
Send me a friend request.
I'll accept it.
"Shout out to Colton.
Livestream is cool.
I like to see people get
frustrated and break code
like I do in psets,
practice, et cetera."
Yeah, that's going to happen.
NICK WONG: It certainly happens.
COLTON OGDEN: That's
absolutely going to happen.
BHAVIK, thank you for that.
NICK WONG: All right.
So as promised, a little bit behind
schedule, but definitely as promised,
I've edited a little bit of our code.
I added a command line argument so
that we could modify things as we go.
But we have just changed the
entirety of what we're doing.
We're no longer classifying
between light and dark.
We are classifying between real
and cartoon pictures of people.
And all we had to do was find
new data sets and label them.
That was it.
And the code will work
entirely fine on those.
You'll notice things are
a little bit harder here,
where we still are validating things--
oh, nice.
David through your Facebook in there.
COLTON OGDEN: Shout out to David for
throwing my Facebook in the chat there.
"Prof is here!"
Welcome, David sir.
NICK WONG: Yep.
Welcome back, David.
And so this validation
accuracy is not necessarily
going straight to 100 anymore.
It is a little bit difficult
to classify, really,
between cartoon images
and real life ones.
But you'll notice we're doing
way better than just guessing.
We are not at 50/50.
We're at some 80% and 80%,
which means we're roughly--
oops-- not too terrible on this.
Ah, that's the same bug I had last time.
Let me get rid of that
and let it run again.
rm img/predict/.DS.
There we are.
So annoying.
I told you at the very beginning of the
Livestream that was going to come up,
and then I forgot about it.
COLTON OGDEN: It's like
we've come full circle.
NICK WONG: Yeah.
We've come all the way back to
what we had at the very beginning,
where there's a small bug,
we fixed it, and now we
are doing what we
promised at the beginning.
We are classifying between
cartoon images of people
and real images of people.
And what that means is--
in concept, you could train this a lot
better with way more comprehensive data
and doing all sorts of cool things.
But even with very limited data sets
in roughly two minute training times
and in and hour and a
half, two hours of coding,
we were able to get to a
model that works pretty well
on what's going on here.
There's actually quite a few concepts
that we demonstrate in this model.
There's a lot of things going
on underneath the hood, which
is one of David's actual
favorite phrases, I think.
What's the record?
40-something?
COLTON OGDEN: I think someone cut
a video on our production staff
of how many times David said
"under the hood," and it was a lot.
NICK WONG: It was pretty funny.
COLTON OGDEN: It was a good number.
A good number of it.
NICK WONG: So yeah, there's
all sorts of things going on
in this even simple project.
And I think that there's a lot of
places for it to grow and expand.
So you're welcome to take the code.
It's all yours.
There's no need to credit me with it.
And the images are not mine
except for the pictures of me.
There is a picture of my face.
I use it as the profile picture.
And you'll notice, even here, we
didn't do a great job of predicting.
We guessed that they were both cartoons.
One of them is certainly not a cartoon.
I'm a real person, I swear.
COLTON OGDEN: It's debatable.
NICK WONG: Debatable.
I'm certainly, not a cartoon
version of myself, I think.
But yes, we basically were
able to get from beginning
to end in about two hours.
And we have a machine learning model
that allows you to predict on things.
There's plenty of room to modify this
to make it a little bit more general,
to make it usable from the
command line or as an app.
But this is certainly a--
I think if you were able to get
through this even without fully
understanding everything, even if you
were just sitting there and being like,
oh, this is kind of
cool, that's fantastic.
COLTON OGDEN: Even I'll admit,
I don't know every detail
of what we talked about,
but it's been fascinating
and actually inspiring to go
and dive a little bit deeper
into these technologies--
NICK WONG: That's awesome.
COLTON OGDEN: --into machine learning.
So I think if that's even what
some people take away from this,
they're like things, different fields,
different niches of CS or other fields
can be interesting or inspiring you
without knowing all the details, that's
great.
That's how seeds are planted
for future exploration.
NICK WONG: Yeah.
I thoroughly agree with that.
Couldn't be better said.
COLTON OGDEN: "Thank you
very much," says DKBUXBOM.
"It has been instructive
and very inspiring.
Special thanks for the encouragement."
Absolutely.
It's been a great session.
NICK WONG: Yeah, of course.
Thank you.
We appreciate having you guys
sitting here talking with us.
It's really cool.
COLTON OGDEN: Yeah, the back and forth
is what really makes this a ton of fun.
42FORCE-- "Many thanks for the effort
Colton and Nick along with rest
of CS50 team!
This is something to be thankful for
by being here in the 20th century.
Education is now a free resource."
Absolutely.
No, and it changes every day.
And a special thanks to our production
team for setting this up for us too.
This is only possible because of
their hard work and for David--
NICK WONG: Snaps for
the production team.
COLTON OGDEN: --being in
support of the vision as well.
So shout outs to David
and the production team.
Maybe want to read off TWITCH--
NICK WONG: Sure, yeah.
So TWITCHHELLOWORLD.
Nice.
You went for two
smaller ones, and then--
COLTON OGDEN: Giving you.
NICK WONG: I appreciate it.
No, it's cool.
So TWITCHHELLOWORLD says, "Is
the distinction between, say,
a PhD in AI for instance, those
who develop the new techniques
and.or develop TensorFlow itself as
opposed to the MS/BS degree holders
and self-trained as those that execute
these techniques in various settings?
I hear sometimes PhDs are
overqualified for some openings,
though it seems some companies prefer
advanced degrees for their AI research.
Thank you so much for this."
So of course, you're welcome.
We appreciate it.
But also, that's a great question on
the difference between PhD MS versus BS.
And actually, a lot of
that can vary by country.
I know that in certain countries it's
actually really common to get a BS,
then an MS, then a PhD.
In the United States, a lot of
times you jump from BS to PhD.
There's maybe some years
of research in between,
but you actually just go
straight from one to the other.
And so that's a really good
question for asking, maybe,
what are companies looking for?
And a lot of companies, especially
the big five, you're looking at them
and you might say, OK, well
I might want to go work
for like DeepMind, Google DeepMind.
They tend to look for a lot of PhDs.
I don't know of too many
people who are undergrads
who are going to work on DeepMind.
That's very cool.
It's super technical work.
And they tend to do a lot more theory
before they put it into practice.
But I think differentiating between
people who are purely theoretical
and people who are purely practical
is kind of a false dichotomy.
There are people who are
very theoretical who can do
a lot of really cool practical stuff.
They can build apps out of nowhere.
And there are people who
are super practical who
also happen to know a lot of theory.
And so I think that
they go hand-in-hand.
The more theory you know, I think
it makes it a little bit easier
to do things practically.
There are some classic
counterexamples to this,
but I think in general, that's true.
And the more practical things you
do, it motivates a lot of the theory.
Why am I curious about how this
actually works underneath the hood
until I've done it?
And then I see where things break.
Now, maybe when I
understand how things work,
I might say, oh, that
makes a lot of sense.
I can actually fix this now.
And so it influences both directions.
COLTON OGDEN: We can answer
questions like, what's a sigmoid?
NICK WONG: Right.
Right, exactly.
COLTON OGDEN: "What if
we live in a cartoon?"
says MAGGUS.
NICK WONG: That would be really cool.
Actually, there is a friend of mine
who posed a really cool thought
experiment on that, which
was-- could you ever
believe that we would
be living in a matrix?
I'm going to just
absolutely bungle this.
But he said it really
eloquently, which was
like, if you could believe
that we could ever be a matrix,
then it's probably pretty
possible that we're
in one, because if you think that AI
could ever be representative of a human
being, then the fact that
that could already exist
would make us exactly where we are now.
It would be on not identifiable.
And I think there's a very
famous discussion or set
of quotations between
Elon Musk and Stephen
Hawking and talking about the
probability that we live inside
of a simulation.
And they say that it's really high.
The probability that we don't
live in a simulation is very low.
And based on what we know,
that's true, at least
based on that topic and my
readings of the articles on that.
However, a counter to
that example is, let's say
that I have a soccer team
A and a soccer team B,
and I say, what's the
probability that soccer team
A wins when they play together?
And you would pretty reasonably,
hopefully, say it's about 50%.
And that's true.
That's the current probability
given what you know.
However, if I tell you that soccer team
A is Harvard's varsity boys soccer team
and soccer team B is my
kindergarten soccer team,
you now know that the probability that
soccer team A wins is roughly 100.
I would argue actually 100.
I hope it's 100.
So that changes--
COLTON OGDEN: Shout out to
the Harvard soccer team.
NICK WONG: Yeah, go Harvard.
So that's a crazy shift in
what our probability is.
It went from something that is
literally probabilistic to something
that is quite hopefully deterministic.
And that, I think, points to a
lot of these questions about--
are we a cartoon?
Are we in a matrix?
Are we in these sort of things?
There are people who
are very smart and very
relevant to this sort of discussion, and
they have a lot of cool opinions on it,
but it's good to also
temper those opinions
with the reality of the
probability that we know very much
about our world and our universe even.
Pretty minimal.
We don't even really know
what's in the oceans.
So to say that we might understand
something about the universe
is pretty limited to
what we can actually
say given that the amount of information
we know, the total breadth of knowledge
of humanity-- pretty small if you
imagine that the breadth of knowledge
that actually exists is infinitely
larger, or almost infinitely larger.
COLTON OGDEN: We're into
metaphysical conversations here on--
NICK WONG: Yeah, very
metaphysical, very philosophical.
COLTON OGDEN: --CS50.
Twitch.TV/CS50TV.
Let's see, make sure we
didn't miss anything.
NICK WONG: Right.
COLTON OGDEN: "Colton,
Nick, you're amazing.
Thank you for the great
work you're doing."
NICK WONG: Thank you very much.
COLTON OGDEN: Thanks so much, BELLA.
Appreciate you coming
in time and time again.
I think I've seen you on every
stream so far, so thanks so much.
NICK WONG: Wow, that's awesome.
COLTON OGDEN: "Thanks for the
live stream," says BHAVIK.
"I really enjoy being here."
Glad to have you, BHAVIK.
Also a regular.
David's heading out.
Thanks, David--
NICK WONG: Thank you, David.
COLTON OGDEN: --for
joing us on the chat.
We got some thank yous for
David there in the chat.
"Which IDE are you
using?" says MARLINDO71.
NICK WONG: Visual Studio Code.
And I think BHAVIK_KNIGHT actually
answered that right below.
COLTON OGDEN: Oh yes.
NICK WONG: But yeah, I'm using VSC.
It's one of my favorite IDEs.
I also sometimes switch to Adam
if I'm feeling kind of fun.
But yeah, whatever works for you.
COLTON OGDEN: "How to
choose the best partition
after preparing a Gini or Shannon tree?
How to identify the
prediction exceptions?"
I can't say I know.
NICK WONG: OK.
So I don't know super well
what exactly Gini and Shannon
trees are, though I would imagine
that it's related to forest decision
problems in machine learning.
And I can explain a little bit of that.
It's basically you pass a set
of data into a set of-- they're
called trees that make decisions.
And at first, they're
random, and then they
start to really successfully
choose based on decisions.
And this goes iteratively
all the way through.
That's a very rough, leaving
out a lot [INAUDIBLE]..
COLTON OGDEN: It's like a
decision tree pipeline almost?
NICK WONG: Yeah.
I would think of it like
that, and there's some nuance
that I'm pretty much omitting.
And I believe if you're talking
about something along those lines,
then it's very similar in the decision
to choose a rectified linear unit
versus a sigmoid versus
different activations
then what we saw here
in our linear models.
And that's roughly
what you end up seeing.
But because I don't actually know
what a Gini or Shannon tree is or are,
I can't necessarily speak to how you
would actually identify the prediction
exceptions on those.
COLTON OGDEN: Cool.
Cool.
"Thank you," says TWITCHHELLOWORLD.
Astley says, "If we lived in a
cartoon, we could run in the air
until we looked down."
NICK WONG: Possibly, yeah.
COLTON OGDEN: That's one of my
biggest desires right there.
"VSCode.
If you are looking for an IDE to do
Python stuff, PyCharm is very good.
I use PyCharm for Python."
I haven't used it myself--
NICK WONG: [INAUDIBLE].
COLTON OGDEN: --but I've
heard the same thing, yeah.
People tend to really enjoy it.
Patrick Schmidt tends to
really like that a lot.
NICK WONG: Oh, that's awesome.
COLTON OGDEN: "Love Professor Margot
Seltzer's phrase, if you do good,
you will do well."
Yeah.
Do good, do well.
That's one phrase that
actually definitely says.
It's very true, very true.
"Also relevant."
We have a Reddit post here.
I'm going to pull it up on my computer.
NICK WONG: Yeah, I was going
to say, that's a dangerous--
COLTON OGDEN: DRUNKBEAR--
"What is happening here?"
OK, the number one data--
maybe if you want to
pull it up, it looks OK.
NICK WONG: Oh, all right.
COLTON OGDEN: Pull it up
on your web browser there.
NICK WONG: Let's see.
Twitch.tv.
COLTON OGDEN: Oh,
actually-- oh, yeah, yeah.
You have to go to the chat, I guess.
NICK WONG: CS50TV.
COLTON OGDEN: Yeah.
And then I'll paste it in there
again when you're in the chat.
NICK WONG: Beautiful.
Gotta love the Wi-Fi.
Anytime you are actively observing the
Wi-Fi, it's millions of times slower.
But then if I look away, it's gone.
Look at that.
Cool.
Oh, this is going to be pretty meta.
You're going to be watching the stream.
Oh, well you get an ad.
I was going to say, you're going
to be watching the stream--
COLTON OGDEN: Watching the
stream within a stream kind of.
NICK WONG: --while it's streaming.
Yeah, kind of.
COLTON OGDEN: Kind of.
I think the chat is--
I think you have to
expand that a little bit.
NICK WONG: I'm going to
expand this a little bit.
There we go.
COLTON OGDEN: And there.
You should be there.
So let's paste that
bad boy right in there.
NICK WONG: Beautiful.
All right.
So we get this beautiful gem.
It almost looks like an XKCD comic.
All right.
So "The number one data scientist
excuse for legitimately slacking off."
COLTON OGDEN: Yeah.
That's like the old "my code's
compiling" joke from back when--
NICK WONG: That's my favorite.
COLTON OGDEN: --back when programs
took 30 minutes to an hour.
NICK WONG: My build.
COLTON OGDEN: Some probably
still do take that long.
NICK WONG: I believe so.
COLTON OGDEN: Probably
much longer than that.
Things like-- I don't know
about Chrome, but maybe
Microsoft products like Word and Excel.
NICK WONG: Yeah.
They're known for taking forever.
COLTON OGDEN: Those
probably take ages, right?
"What is happening here?"
DRUNKBEAR.
We are just recapping the conclusion
to our machine learning stream here
with Nick Wong, but it's
going to be on YouTube.
The VOD should be up on Twitch.
We built a simple binary classifier.
And then I guess this is a perfect way
to close it off too with having the--
NICK WONG: Yeah, I figure we can
loop all the way back around.
COLTON OGDEN: --the visual of Nick's
custom little shell screensaver here,
which is really cool.
I don't know if maybe you want to link
to how you got that if it's simple.
NICK WONG: Yeah.
Actually, I can link to what that is.
COLTON OGDEN: Because
that's really cool.
NICK WONG: I can post that here.
Well, let me log into Twitch.
COLTON OGDEN: "Yeah, you're genius guys.
Gini and Shannons are algorithms
to identify the best fitting model
to adopt so you can build a classifier."
Yeah it sounds like
what you were saying.
NICK WONG: OK, I can't log in.
I can tell you what it is.
It's CMatrix is the
program that actually runs.
I piped CMatrix into lolcat.
So I can actually show
you what that looks like.
COLTON OGDEN: "Atom is
a bit slow to start.
I like Vim's key binding very much, so
I use it inside the IDE," says BHAVIK.
Yea, Atom is a bit slow.
Try VSCode out, see if
that's a little bit faster.
I know it uses less
memory than Atom does.
But the two are, I believe,
both built on Electron,
so they both do use a bit
more memory than they need to.
Well, not than they
need to, but than is--
compared to other--
NICK WONG: Than standard-- yeah.
COLTON OGDEN: --IDEs
or other text editors.
PUPPYLIONHD-- "When is the next stream?"
The next stream is tomorrow, so we'll
have CS50's Bryan Yu, our head teaching
fellow, who'll be up here.
NICK WONG: Yeah, Brian Yu.
COLTON OGDEN: Shout out to Brian.
He'll be teaching us how to
React, the basics of React.
And his web course is--
I think I pasted it earlier,
but just to do it one more time.
He taught that course,
a web course, so if you
want to maybe glance over some
of the course materials there.
I don't recall offhand if he
taught React in that class.
I know that Jordan's class
did teach React or React
Native, which part of that was React.
"Recently installed VSCode."
Oh sorry, did you put the thing in the--
NICK WONG: I did.
Sorry.
I put the command up here.
It's this command is
technically how to run.
Or I guess this is the actual command.
COLTON OGDEN: OK.
So they need to install a CMatrix and
a lolcat, and then once they have that,
they can alias that
in their Bash profile,
and then they're all set to go.
NICK WONG: Yeah.
And I like to call it rest because
it's what I do when I'm resting
and I'm not actually
teaching anything actively.
COLTON OGDEN: Nice.
Love it.
I love it.
It's nice.
NICK WONG: Cool.
COLTON OGDEN: We'll keep that
on there for just a second.
NICK WONG: All right.
Sounds good.
COLTON OGDEN: But yeah,
this was Nick Wong
building a binary classifier, a humble
introduction to machine learning.
I didn't absorb probably more than 50%
or 60% of it, but it's very inspiring.
NICK WONG: We went through it very fast.
Thank you, I appreciate it.
COLTON OGDEN: It looks
like a deep rabbit hole.
Looks like a--
NICK WONG: Yeah, it just goes.
COLTON OGDEN: --lot of very interesting
stuff, a lot of fancy terminology
that I would love to understand
that the theoretical meaning of.
But machine learning powers
so much of the modern world,
so it's nice to get a
glimpse into how it works.
NICK WONG: Thank you
for having me, Colton.
I really appreciate it.
It's been awesome.
COLTON OGDEN: Yeah.
No, it was a terrific--
NICK WONG: Looking forward to all
of the future talks we get to do.
COLTON OGDEN: Terrific stream.
And join us again next week.
On next Friday, we'll have Nick talking
to us about some of this fancy terminal
stuff.
He'll be showing us--
NICK WONG: Terminal tricks.
COLTON OGDEN: --basic Linux commands.
So a bit more of an entry level stream,
some how do we use the command line?
What are some common commands?
Things like ls, cd, and maybe
some other things like piping,
or however much time we have.
NICK WONG: Yeah.
I think we'll go for a little while.
COLTON OGDEN: Which
is a great foundation
upon which we can build other
streams and get people more fluent
in using the command line.
NICK WONG: Yeah.
COLTON OGDEN: "What password
managers do you guys use?
I keep forgetting to ask that.
David Sir talked about it
in cyber security lecture,
but I'd like some
recommendations to try."
We use 1Password for CS50,
so take a look at 1Password.
I don't know if you use--
NICK WONG: I use
LastPass, but all very--
COLTON OGDEN: They're all
probably more or less--
NICK WONG: They're pretty
much the same, yeah.
COLTON OGDEN: --identical
or feature compatible.
But yeah, using a password
manager is a very handy tool.
NICK WONG: I just got a
student discount for LastPass.
COLTON OGDEN: Oh, nice.
OK, a little bit of a interest there.
All right.
Well, thanks so much everybody.
This has been CS50 on Twitch, our
seventh episode, Binary Classifier
with TensorFlow, Keras, and Python.
Thanks for everybody who's tuning in.
As always, if you have suggestions,
definitely let us know.
We'll be joined again by Nick next week.
And this week, we'll be joined
by Brian tomorrow for some React.
And then on Friday, we'll
take a look at some Unity.
We'll make 3D Pong.
NICK WONG: Nice.
That's awesome.
COLTON OGDEN: So yeah, that'll be it.
Any last things you'd
like bring up or mention?
NICK WONG: No.
Thank you, guys.
Really appreciate it.
I'll see you guys next Friday.
COLTON OGDEN: Cool.
See you, everybody.
Thanks so much again.
Looking forward to the next stream.
NICK WONG: Awesome.
