Skip to content

Download Reinforcement Learning Course Subtitles | Machine Learning Tutorial Captions

Reinforcement Learning Course - Full Machine Learning Tutorial

Reinforcement Learning Course - Full Machine Learning Tutorial

freeCodeCamp.org

5966 segments EN
Save subtitles to LunaNotes

SRT - Most compatible format for video players (VLC, media players, video editors)

VTT - Web Video Text Tracks for HTML5 video and browsers

TXT - Plain text with timestamps for easy reading and editing

Subtitle preview

Scroll to view all subtitles

[00:00]

welcome to the reinforcement learning

[00:01]

jump start series i'm your host phil

[00:04]

tabor if you don't know me i'm a

[00:05]

physicist and former semiconductor

[00:07]

engineer turned machine learning

[00:08]

practitioner

[00:09]

in this series of tutorials you're going

[00:10]

to learn everything you need to know to

[00:12]

get started with reinforcement learning

[00:14]

you don't need any prior exposure all

[00:16]

you really need is some basic

[00:18]

familiarity with python

[00:20]

as far as requirements for this course

[00:21]

they are pretty light you will need the

[00:23]

open ai gym because we're going to be

[00:24]

taking advantage of that rather

[00:25]

extensively you'll also need the atari

[00:28]

extension for that so we can play games

[00:29]

like breakout space invaders you'll also

[00:32]

need the box 2d extension so we can do

[00:34]

the new lander environment

[00:36]

and beyond that you will need the

[00:38]

tensorflow library as well as pytorch

[00:41]

and i'm going to have tutorials in both

[00:43]

tensorflow and pi torch with a bit of a

[00:45]

stronger emphasis on tensorflow

[00:48]

i'm going to teach the course in

[00:49]

somewhat of a top-down fashion meaning

[00:51]

we're going to get to the really

[00:52]

important and exciting new stuff like

[00:54]

deep q learning and policy gradient

[00:56]

methods first

[00:57]

after that we'll kind of back up and

[00:59]

take a look at things like sarsa double

[01:02]

q learning and we'll even get into how

[01:04]

to make your own reinforcement learning

[01:05]

environments when we code up our own

[01:07]

grid world and then solve it with

[01:09]

regular q learning

[01:10]

if you missed something in the code

[01:12]

don't worry i keep all this code on my

[01:14]

github which i will link in the

[01:16]

pin comment down below i'll also link

[01:18]

the relevant timestamps for all the

[01:20]

material in case you want to jump around

[01:22]

because maybe some topics interest you

[01:23]

more or you want to get some additional

[01:25]

background information from the

[01:26]

explainer videos

[01:28]

questions comments leave them down below

[01:29]

i will address all of them let's get to

[01:31]

it

[01:33]

in this video you're going to learn

[01:35]

everything you need to know to implement

[01:37]

q-learning from scratch

[01:39]

you don't need any prior exposure to

[01:40]

q-learning you don't even really need

[01:42]

much familiarity with reinforcement

[01:44]

learning you get everything you need in

[01:46]

this video

[01:48]

if you're new here i'm phil and i'm here

[01:50]

to help you get started with machine

[01:51]

learning i upload three videos a week so

[01:54]

make sure to subscribe so you don't miss

[01:56]

out

[01:57]

imagine you've just gotten the

[01:58]

recognition you deserve in the form of

[02:00]

offers for a machine learning

[02:01]

engineering position from google

[02:04]

facebook and amazon

[02:06]

all three are offering you a boatload of

[02:08]

money and your dreams are big balling or

[02:10]

interrupted by the realization that

[02:12]

starting salary is just well the

[02:14]

starting salary you've got friends at

[02:16]

each of the three companies so you reach

[02:17]

out to find out about the promotion

[02:19]

schedules with each

[02:20]

facebook offers two hundred fifty

[02:22]

thousand dollars to start with a ten

[02:24]

percent raise after three years but with

[02:26]

a forty percent probability that you'll

[02:28]

quit

[02:30]

google offers two hundred thousand

[02:31]

dollars to start with the twenty percent

[02:33]

raise after three years but with only a

[02:35]

25 probability that you'll quit

[02:38]

amazon offers 350 000 to start with a

[02:41]

five percent raise after five years with

[02:43]

a sixty percent chance that you'll end

[02:45]

up washing out

[02:47]

so what should you take

[02:48]

all three of our big money but future

[02:51]

raises are far from certain

[02:53]

this is the sort of problem

[02:55]

reinforcement learning is designed to

[02:56]

solve

[02:57]

how can an agent maximize long-term

[02:59]

rewards in environments with

[03:01]

uncertainties

[03:03]

learning is a powerful solution because

[03:05]

it lets agents learn from the

[03:06]

environment in real time and quickly

[03:09]

learn novel strategies for mastering the

[03:11]

task at hand

[03:12]

q learning works by mapping pairs of

[03:14]

states and actions to the future rewards

[03:16]

the agent expects to receive

[03:19]

it decides which actions to take based

[03:21]

on a strategy called epsilon greedy

[03:23]

action selection

[03:24]

basically the agent spends some time

[03:26]

taking random actions to explore the

[03:28]

environment and the remainder of the

[03:29]

time selecting actions with the highest

[03:31]

known expected feature rewards

[03:34]

epsilon refers to the fraction of the

[03:35]

time the agent spends exploring and it's

[03:37]

a model hyperparameter between 0 and 1.

[03:40]

you can gradually decrease epsilon over

[03:42]

time to some finite value so that your

[03:45]

agent eventually converges on a mostly

[03:47]

greedy strategy

[03:49]

you probably don't want to set epsilon

[03:50]

at zero exactly since it's important to

[03:52]

always be testing the agent's model of

[03:54]

the environment after selecting and

[03:56]

taking some action the agent gets its

[03:58]

reward from the environment

[04:00]

what sets q-learning apart from many

[04:02]

reinforcement learning algorithms is

[04:03]

that it performs its learning operation

[04:05]

after each time step instead of at the

[04:08]

end of each episode as is the case with

[04:10]

policy gradient methods at this point

[04:12]

it's important to make a distinction

[04:14]

traditional q learning works by

[04:16]

literally keeping a table of state and

[04:18]

action pairs

[04:19]

if you're implementing this in python

[04:21]

you could use a dictionary with state

[04:22]

and action tuples as keys

[04:25]

this is only feasible in environments

[04:27]

with a limited number of discrete states

[04:28]

and actions

[04:30]

here the agent doesn't need to keep

[04:32]

track of its history since it can just

[04:34]

update the table in place as it plays

[04:36]

for the game the way the agent updates

[04:38]

his memories by taking the difference in

[04:39]

expected returns

[04:41]

between the actions it took with the

[04:42]

action that had the highest possible

[04:44]

future returns this ends up biasing the

[04:46]

agent's estimates over time towards the

[04:48]

actions that end up producing the best

[04:50]

possible outcomes when we're dealing

[04:52]

with environments that have a huge

[04:53]

number of states or state space that is

[04:55]

continuous then we really can't use a

[04:58]

table

[04:58]

in that case we have to use deep neural

[05:00]

networks to take these observations of

[05:02]

the environment and turn them into

[05:03]

discrete outputs that correspond to the

[05:06]

value of each action this is called deep

[05:08]

q learning the reason we have to use

[05:10]

neural networks is that they are

[05:11]

universal function approximators

[05:14]

it turns out the deep neural nets can

[05:16]

approximate any continuous function

[05:18]

which is precisely what we have the

[05:21]

relationship between states actions and

[05:23]

feature returns is a function that the

[05:25]

agent wants to learn so it can maximize

[05:27]

its future rewards deepq learning agents

[05:30]

have a memory of the states they saw the

[05:32]

actions they took and the rewards they

[05:34]

received

[05:35]

during each learning step the agent

[05:37]

samples a subset of this memory to feed

[05:39]

these states through its neural network

[05:41]

and compute the values of the actions it

[05:43]

took just like with regular q learning

[05:45]

the agent also computes the values for

[05:47]

the maximal actions and uses the

[05:49]

difference between the two as its loss

[05:51]

function to update the weights of the

[05:53]

neural network

[05:54]

so let's talk implementation

[05:56]

in practice we end up with two deep

[05:58]

neural networks

[06:00]

one network called the evaluation

[06:01]

network is to evaluate the current state

[06:04]

and see which action to take and another

[06:06]

network called the target network that

[06:08]

is used to calculate the value of

[06:09]

maximal actions during the learning step

[06:12]

the reasoning for why you need two

[06:14]

networks is a little complicated but

[06:16]

basically it boils down to eliminating

[06:18]

bias in the estimates of the values of

[06:20]

the actions

[06:21]

the weight of the target network are

[06:23]

periodically updated with the weights of

[06:25]

the evaluation network so that the

[06:27]

estimates of the maximal actions can get

[06:28]

more accurate over time if you're

[06:31]

dealing with an environment that gives

[06:32]

pixel images just like in the atari

[06:34]

library from the openai gym then you

[06:36]

will need to use a convolutional neural

[06:38]

network to perform feature extraction on

[06:40]

the images

[06:41]

the output from the convolutional

[06:42]

network is flattened and then fed into a

[06:45]

dense neural network to approximate the

[06:47]

values of each action for your agent if

[06:49]

the environment has movement as most do

[06:52]

then you have an additional problem to

[06:53]

solve

[06:54]

if you take a look at this image can you

[06:56]

tell which way the ball or paddle is

[06:58]

moving

[06:59]

it's pretty much impossible for you to

[07:00]

get a sense of motion from just a single

[07:02]

image and this limitation applies to the

[07:05]

deep q learning agent as well

[07:07]

this means you'll need a way of stacking

[07:10]

frames to give the agent a sense of

[07:11]

motion

[07:12]

so to be clear this means that the

[07:14]

convolutional neural network takes in

[07:16]

the batch of stacked images as input

[07:19]

rather than a single image

[07:21]

choosing an action is reasonably

[07:23]

straightforward generate a random number

[07:25]

and if it's less than the epsilon

[07:27]

parameter pick an action at random

[07:29]

if it's greater than the agent's epsilon

[07:31]

then feed the set of stacked frames

[07:33]

through the evaluation network to get

[07:35]

the values for all the actions in the

[07:37]

current state

[07:39]

find the maximal action and take it once

[07:41]

you get the new state back from the

[07:43]

environment add it to the end of your

[07:44]

stacked frames and store the stacked

[07:46]

frames actions and rewards in the

[07:49]

agent's memory then perform the learning

[07:51]

operation by sampling the agent's memory

[07:54]

it's really important to get a

[07:56]

non-sequential random sampling of the

[07:58]

memory so that you avoid getting trapped

[08:00]

in one little corner of parameter space

[08:03]

as long as you keep track of the state

[08:05]

transitions actions and rewards in the

[08:07]

same way you should be pretty safe

[08:10]

feed that random batch of data through

[08:11]

the evaluation and target networks and

[08:13]

the compute the loss function to perform

[08:15]

your loss minimization step for the

[08:18]

neural network that's really all there

[08:20]

is to deep cue learning a couple neural

[08:22]

networks a memory to keep track of

[08:24]

states and lots of gpu horsepower to

[08:26]

handle the training

[08:28]

speaking of which of course you'll need

[08:30]

to pick a framework preferably one that

[08:32]

lets you use a gpu for the learning

[08:35]

pytorch and tensorflow are both great

[08:37]

choices and both support model

[08:39]

checkpointing

[08:40]

this will be critical if you have other

[08:42]

stuff to do and can't dedicate a day or

[08:44]

so for model training

[08:46]

that's it for now make sure to share the

[08:48]

video if you found it helpful and

[08:50]

subscribe so you don't miss any future

[08:52]

reinforcement learning content i'll see

[08:54]

you in the next video

[08:56]

in this tutorial you're going to learn

[08:57]

how to use deep q learning to teach an

[08:59]

agent to play breakout in the tensorflow

[09:01]

framework you don't need to know

[09:02]

anything about deep q learning you don't

[09:04]

even need to know anything about

[09:05]

tensorflow you just have to follow along

[09:07]

let's get started

[09:08]

if you're new to the channel i'm phil a

[09:10]

physicist and former semiconductor

[09:12]

engineer turned machine learning

[09:13]

practitioner here at machine learning

[09:14]

with phil we do deep reinforcement

[09:16]

learning and artificial intelligence

[09:17]

tutorials three times a week so if

[09:19]

you're into that kind of thing hit that

[09:20]

subscribe button let's get to the video

[09:23]

so if you're not familiar with deep q

[09:24]

learning the basic idea is that the

[09:26]

agent uses a convolutional neural

[09:28]

network to turn the set of images from

[09:30]

the game into a set of feature vectors

[09:32]

those are fed into a fully connected

[09:34]

layer to determine the value of each of

[09:36]

the actions given some set of states in

[09:39]

this case a set of states is just going

[09:40]

to be a stack of frames because we want

[09:42]

the agent to have a sense of motion so

[09:44]

as we go along we'll be stacking up

[09:45]

frames passing them into our network and

[09:47]

asking the network hey what is the value

[09:48]

of either of the actions move left move

[09:50]

right or fire a ball we're going to

[09:52]

split this into two classes one of which

[09:54]

will house the deep q networks and the

[09:56]

other will house the agent and in the

[09:58]

agent class we're going to have other

[09:59]

stuff that we'll get to later

[10:01]

let's go ahead and start with our

[10:02]

imports we'll need os to handle model

[10:05]

saving

[10:09]

we'll need numpy to handle some basic

[10:10]

random functions

[10:12]

and of course tensorflow to build our

[10:14]

agent

[10:15]

so we'll start with our deepq network

[10:23]

the initializer is pretty

[10:24]

straightforward we're going to take the

[10:26]

learning rate number of actions

[10:29]

the

[10:30]

name of the network that is important

[10:31]

because we're gonna have two networks

[10:33]

one to select an action one to tell us

[10:34]

the value of an action

[10:37]

more on that later

[10:39]

the number of dimensions in the first

[10:40]

fully connected layer

[10:42]

the input dimensions of our environment

[10:44]

so

[10:45]

for the atari gym

[10:47]

sorry the atari library of the open ai

[10:49]

gym all of the images have 210 by 160

[10:51]

resolution and we're going to pass in a

[10:53]

set of frames to give the agent a sense

[10:55]

of motion we're going to pass in four

[10:56]

frames in particular so it's going to be

[10:58]

210 by default 210 160 by 4. we're going

[11:02]

to do some cropping later on we'll get

[11:03]

to that in a minute

[11:06]

we also need a directory to save our

[11:08]

model

[11:30]

so the next thing we need is the

[11:31]

tensorflow session this is what

[11:33]

instantiates everything into the graph

[11:36]

and each network wants to have its own

[11:40]

then we'll call the build network

[11:41]

function to add everything to the graph

[11:43]

once you've added everything to the

[11:44]

graph you have to initialize it very

[11:46]

important tensorflow will complain if

[11:47]

you don't do that so best to do that now

[11:51]

and the way you do that is by calling

[11:53]

the tf global variables initializer

[11:59]

function

[12:03]

other thing we need is a way of saving

[12:05]

our models as we go along and this is

[12:08]

critical because this deep queue network

[12:10]

takes forever to train i let it train

[12:12]

for about 10 hours and it averages a

[12:14]

score of two to three points

[12:15]

per set of uh whatever number of lies it

[12:17]

gets so

[12:19]

it's going to have to train for quite

[12:20]

some time so we're going to want to be

[12:21]

able to save it as we go along because

[12:22]

we have other stuff to do right

[12:33]

and of course you want a way of saving

[12:35]

your checkpoint files

[12:37]

next thing we need is a way of keeping

[12:38]

track of the parameters for each

[12:40]

particular network

[12:42]

and you do that like this

[12:53]

so what this will do is tell tensorflow

[12:55]

that we want to keep track of all of the

[12:57]

trainable variables for the network that

[12:59]

corresponds to whatever the name of this

[13:01]

particular network is we use this later

[13:03]

when we copy one network to another

[13:06]

next let's build our network

[13:11]

so we're gonna encase everything in a

[13:13]

scope that is based on the the network's

[13:15]

name

[13:20]

we're going to have placeholder

[13:21]

variables that tell us the inputs to our

[13:23]

model we're going to want to input the

[13:24]

stack of images from the

[13:26]

atari game we want to input the actions

[13:29]

that the agent took as well as the

[13:31]

target value for the q network we'll get

[13:33]

to that in a minute

[13:53]

and this convention of naming

[13:55]

naming placeholders and

[13:57]

layers you're going to see repeated

[13:59]

throughout the tensorflow library the

[14:02]

reason is that it it makes debugging

[14:04]

easier if you get an error it will tell

[14:05]

you the variable or layer that caused

[14:07]

the error very handy

[14:19]

and so you can probably tell by the

[14:24]

shape here that we are going to do a one

[14:26]

hot encoding of the actions

[14:38]

and the same thing for the q target so

[14:42]

the

[14:43]

convention of using none as the first

[14:44]

parameter in the shape

[14:46]

allows you to train a batch of stuff and

[14:48]

that's important because in virtually

[14:50]

every deep learning application you want

[14:52]

to pass in a batch of information right

[14:54]

in this case we're going to be passing

[14:55]

in batches of stacked frames

[14:59]

so we'll get to that in a moment next

[15:00]

thing we have to do is start to build

[15:02]

our

[15:03]

scroll down a little bit and start

[15:04]

building our convolutional neural

[15:06]

network so let's start building our

[15:07]

layers

[15:13]

the first one will have 32 filters

[15:16]

kernel size of 8x8

[15:21]

strides of 4 and a name of conf 1.

[15:25]

the other thing we need is an

[15:27]

initializer

[15:29]

now

[15:31]

we are going to use the initializer that

[15:33]

the deepmind team used in their paper

[15:36]

reason is that we want to learn from the

[15:38]

experts and may as well do what they do

[15:40]

if it's going to make our life

[15:41]

significantly easier

[15:44]

and that's going to be a variance

[15:45]

scaling initializer the scale of 2.

[15:53]

and then we want to activate that with a

[15:54]

relu function

[16:01]

that's right it's con1 activated

[16:03]

so our next layer is

[16:06]

pretty similar

[16:09]

it'll take the activated output of the

[16:12]

first layer

[16:13]

as input

[16:16]

that'll take 64 filters

[16:18]

if you're not familiar with what a

[16:19]

filter is you can check out my video on

[16:21]

convolutional neural networks

[16:24]

a kernel size of in this case four by

[16:27]

four

[16:28]

strides of two

[16:30]

name of conf two

[16:32]

and the

[16:33]

we can go ahead and

[16:36]

copy that initializer

[16:40]

why not

[16:48]

so that is our second convolutional

[16:49]

layer and we're gonna do something

[16:50]

similar for the third of course

[16:56]

and that will take

[16:58]

conf2 activated

[17:02]

128 filters

[17:08]

two by sorry a three by three kernel

[17:12]

good grief a stride of one and a name of

[17:16]

conf 3

[17:20]

and the same initializer

[17:29]

and of course we want to activate it as

[17:30]

well so the next step is once we have

[17:34]

the outputs of our convolutional net

[17:35]

neural network we want to flatten all of

[17:37]

them and pass them through a dense

[17:38]

network to get our q values or the

[17:40]

values of each state action pair let's

[17:42]

do that now

[17:55]

that's where our fc1 dimms come in

[18:02]

and

[18:03]

we need a

[18:05]

value activation

[18:08]

and oops we will do

[18:11]

the same initializer for the dense layer

[18:16]

so next up we need to determine the q

[18:19]

values

[18:21]

q and q learning just refers to the

[18:23]

value of a state action pair

[18:25]

it's just the nomenclature

[18:31]

and this will be the output of our

[18:32]

neural network

[18:34]

and of course we want to have one output

[18:36]

for each action

[18:38]

and this gets the same initializer

[18:43]

now we're not activating that yet uh we

[18:46]

want to

[18:48]

just get the linear values sorry the

[18:50]

linear activation of the output of our

[18:53]

network

[18:54]

so the next thing we need is the actual

[18:57]

value

[18:58]

of q

[19:00]

for each action

[19:05]

and remember actions is a placeholder

[19:08]

and next thing we need for every neural

[19:10]

network is a loss function

[19:12]

so we just want to have the squared

[19:14]

difference between

[19:16]

the

[19:18]

q value of the network outputs and

[19:20]

something called the q target the q

[19:23]

target let's get to that now so the

[19:25]

the way q learning works is that at each

[19:28]

time step it's a form of temporal

[19:29]

difference learning so every time step

[19:30]

it learns and it says hey i took some

[19:32]

action what was the maximal action i

[19:34]

could have taken and then it takes the

[19:35]

delta between whatever action it took

[19:37]

and the maximal action and uses that to

[19:40]

update the

[19:42]

the neural network as its loss function

[19:45]

so our training operation

[19:50]

is just a form of gradient descent uh

[19:53]

atom optimizer in this case

[19:56]

uh learning rate and you want to

[19:57]

minimize that loss function

[20:02]

let's give this more room

[20:09]

so that is almost it so that is our

[20:11]

network so the next thing we need is a

[20:13]

way of saving files right

[20:16]

and save and loading them as well

[20:18]

the reason we want this is as we said

[20:20]

these models take a notoriously long

[20:22]

time to train

[20:26]

and so we may want to start and stop as

[20:28]

we go along

[20:36]

and what this will do is it will look in

[20:38]

the checkpoint file and load up the

[20:40]

graph from that file

[20:42]

and save it

[20:43]

and load it into the graph of the

[20:45]

current session

[20:53]

and we're going to save frequently as we

[20:56]

train something like every 10 games

[21:04]

and all this function does is it takes

[21:05]

the current session and opposite to a

[21:08]

file

[21:09]

pretty handy so that is our deep q

[21:12]

network what this does again is it takes

[21:15]

a batch of images from the environment

[21:17]

in this case breakout passes it through

[21:19]

convolutional neural network to do the

[21:21]

feature selection that passes it through

[21:23]

a fully connected layer to determine the

[21:25]

value of each given action and then uses

[21:28]

the the maximum value of the next action

[21:30]

to determine its loss function and

[21:33]

perform training on that network network

[21:35]

via back propagation

[21:37]

next up we need an agent that includes

[21:38]

everything else all of the learnings all

[21:40]

the memories all that good stuff

[21:45]

so it's going to take something called

[21:46]

alpha that is the learning rate

[21:48]

gamma that's a discount factor a hyper

[21:50]

parameter of our model

[21:51]

the memory size number of actions and

[21:54]

epsilon that determines how often it

[21:56]

takes a random action

[21:59]

a batch size

[22:02]

a

[22:04]

parameter that tells us how often we

[22:05]

want to replace our target network

[22:08]

set of input dimms

[22:10]

we use the same as before 210 160 by

[22:12]

four

[22:16]

one moment my cat is whining we need the

[22:18]

directory to save the q next network

[22:23]

and we will need a directory to save the

[22:26]

q evaluation

[22:29]

and what this

[22:31]

as i said we'll have two networks one

[22:32]

that tells us the action to take the one

[22:34]

that tells us the value of that action

[22:39]

so let's go ahead and start our

[22:42]

initializer

[22:44]

so when we take random actions

[22:46]

we will need to know the action space

[22:47]

which is just the set of all possible

[22:49]

actions

[22:57]

and we need to know the number of

[22:59]

actions

[23:02]

we need our discount factor gamma this

[23:04]

tells the agent how much it wants to

[23:06]

discount future rewards

[23:11]

the memory size which tells us how many

[23:13]

transitions to store in memory

[23:16]

of course our epsilon

[23:18]

and epsilon greedy

[23:34]

and then we need our network to tell the

[23:36]

agent the value of the next action

[23:43]

so we'll pass in the alpha learning rate

[23:45]

number of actions

[23:48]

input dimms

[23:52]

the

[23:53]

name

[23:56]

and the checkpoint directory

[24:20]

okay so now we have our two networks the

[24:22]

next thing we need is a memory

[24:24]

so q learning works by saving the state

[24:27]

action reward and new state

[24:30]

transitions in its memory we're also

[24:32]

going to save the terminal flags that

[24:33]

tell the agent whether or not the game

[24:35]

is done

[24:36]

that'll go into the calculation of our

[24:37]

reward when we do the learning function

[24:39]

so we need a state memory

[24:44]

just a numpy array of zeros

[24:47]

we shape mem size and input dimms

[24:51]

and so this will save a

[24:53]

set of

[24:55]

four transitions four frames stacked

[24:57]

four frames by number of memories

[25:12]

and we also need an action memory

[25:21]

and this will handle the one this will

[25:22]

store the one hot encoding of our

[25:25]

actions

[25:36]

now

[25:37]

that is just one dimensional

[25:41]

this will just store the agent's memory

[25:42]

of the rewards

[25:44]

and then we need the terminal memory

[25:47]

so this just saves

[25:49]

the memory of the

[25:52]

done flex

[25:54]

and to save ram

[25:57]

we'll save that one as int8

[25:59]

and you know what we can do the same

[26:01]

thing with the

[26:03]

actions

[26:07]

and this is important because we're

[26:08]

going to be saving 25 000 or so

[26:10]

transitions on my pc this consumes about

[26:13]

47 gigabytes 48 gigabytes of ram i have

[26:16]

96 so it fits

[26:18]

uh if you have less you're gonna need a

[26:19]

significantly smaller memory size just

[26:21]

something to keep in mind

[26:25]

so next thing we need to do is to store

[26:27]

those transitions in memory

[26:30]

and this is of course pretty stateful

[26:32]

straightforward so we need the old state

[26:35]

the action the reward the new state

[26:38]

let's just call that state underscore

[26:41]

and a terminal flag so that'll just be

[26:43]

an integer zero or one

[26:46]

so the agent has some fixed memory signs

[26:48]

we want to fill up to that memory and

[26:50]

then when we exceed it we just want to

[26:52]

go back to the beginning and start

[26:53]

overriding it so the index

[26:55]

is just going to be mem counter which is

[26:58]

the

[26:59]

something i forgot let's put that up

[27:01]

here

[27:04]

so that will be the

[27:07]

counter that keeps track of the

[27:09]

number of memories that it has stored

[27:13]

so

[27:19]

for our actions we need to do the one

[27:20]

hot encoding

[27:27]

and when we pass in the action it'll

[27:28]

just be an integer

[27:30]

so making an array of zeros and setting

[27:32]

the index of the action you took to one

[27:33]

is a one hot encoding

[27:57]

and of course you want to increment the

[27:59]

memory counter

[28:02]

so the next thing we need is a way of

[28:04]

choosing actions so deep q learning

[28:06]

relies on what is called epsilon greedy

[28:09]

so epsilon is a parameter that tells it

[28:11]

how often to choose a random action

[28:13]

we're going to dk epsilon over time the

[28:15]

agent will start out acting purely

[28:16]

randomly for many many hundreds of games

[28:19]

and eventually the random factor will

[28:21]

start decreasing over time and the agent

[28:23]

will take more and more greedy actions

[28:25]

the greedy action is choosing the action

[28:27]

that has the highest value of the next

[28:28]

state

[28:33]

so this takes the state as input

[28:37]

we need a random number from the numpy

[28:40]

random number generator

[28:52]

and then we'll select an action at

[28:53]

random from the agent's action space

[28:56]

if we are going to take a greedy action

[28:58]

then we need to actually find out what

[29:01]

our next highest lead highest valued

[29:04]

action is

[29:05]

so we need to use our evaluation network

[29:07]

to run the

[29:10]

q eval

[29:11]

dot q values

[29:14]

tensor

[29:15]

using a feed dict of the

[29:20]

sorry the

[29:23]

i can't talk and type at the same time

[29:24]

of the current state as the q evaluation

[29:27]

network input

[29:29]

and then of course if you want the

[29:31]

maximum action you just need

[29:33]

numpy.arcmax of actions

[29:36]

and when you're done just return the

[29:38]

action

[29:41]

so now we come to the meat of the

[29:43]

problem we have to handle the learning

[29:44]

so learning has many parts to it the

[29:46]

basic idea is first thing we're going to

[29:48]

do is check to see if we want to update

[29:50]

the value of our target network and if

[29:52]

it's time to do that we're going to go

[29:53]

ahead and do that

[29:55]

the next thing we're going to do is

[29:56]

select a batch of random memories the

[29:58]

most important thing here is that these

[29:59]

memories are non-sequential if you

[30:01]

choose sequential memories then the

[30:03]

agent will get trapped in some little

[30:05]

nook and cranny a parameter space

[30:07]

and what you'll get is oscillations and

[30:09]

performance over time to actually have

[30:11]

robust learning you want to select

[30:13]

different transitions over the entirety

[30:15]

of the memory so

[30:18]

that's how you handle memory batching

[30:20]

and sampling and then you have to

[30:21]

calculate the

[30:23]

value of the

[30:25]

current action as well as the next

[30:26]

maximum action and then you plug that

[30:29]

into the bellman equation for the q

[30:31]

learning algorithm and run your update

[30:34]

function on your loss so let's go ahead

[30:36]

and do that

[30:42]

so

[30:44]

first thing we want to do is see if it's

[30:45]

time to replace our

[30:48]

network target network

[30:51]

if it is

[30:53]

go ahead and do that and we'll write the

[30:55]

update graph function momentarily

[30:58]

next thing we want to do is find out

[31:00]

where our memory ends

[31:07]

less than

[31:09]

mem size

[31:10]

else

[31:12]

this will allow us to randomly sample a

[31:14]

subset of the memory

[31:24]

and this will give us a

[31:27]

random choice in the range maximum

[31:30]

of size batch size

[31:32]

so next we need our state batches

[31:37]

these are just sorry these are just the

[31:41]

state transitions

[31:44]

we will need the

[31:48]

actions we took and remember we store

[31:50]

these as a one-hot encoding so we need

[31:52]

to go back to a

[31:55]

we need to go back to a

[31:57]

integer encoding so

[32:00]

we need to handle that

[32:02]

and the simplest way to do that is just

[32:03]

to do a numpy dot operation to just

[32:06]

multiply two vectors together

[32:33]

so next we need to calculate the values

[32:36]

of the

[32:37]

current set of states as well as these

[32:39]

set of next states

[32:43]

sorry sorry with qe valve

[33:04]

and the next so this will take the set

[33:07]

of next states the transit the

[33:09]

transitions

[33:29]

the next thing we want to do is

[33:31]

copy the qeval network

[33:34]

because we want the loss for all of the

[33:37]

non-optimal actions to be zero

[33:39]

next thing we need to do is calculate

[33:41]

the

[33:42]

value of q target

[33:44]

so for all of these states in the batch

[33:48]

for the actions we actually took

[33:51]

uh plus this quantity here

[33:58]

so the

[33:59]

maximum value of the next state

[34:03]

multiplied by this quantity terminal

[34:05]

batch so the reason is that if we if the

[34:08]

next state is the end of the episode you

[34:10]

just want to have the reward whereas if

[34:13]

it is not a terminal state the next

[34:15]

state then you want to actually take

[34:17]

into account the

[34:18]

discounted future rewards

[34:23]

so next we need to feed all of this

[34:25]

through our neural network

[34:32]

through our training operation

[34:49]

we need the

[34:51]

actions which is the action we actually

[34:53]

took

[34:55]

and we also need the target values

[35:00]

which we just calculated

[35:04]

so the next thing we need to do is to

[35:06]

handle the prospect of decreasing

[35:08]

epsilon over time remember epsilon is

[35:10]

the random factor that tells the agent

[35:12]

how often to take a random action the

[35:14]

goal of learning is to eventually take

[35:15]

the best possible actions so you want to

[35:17]

decrease that epsilon over time so we

[35:19]

handle that by allowing the agent to

[35:21]

play

[35:22]

some number of

[35:24]

moves randomly so we'll say 100 000

[35:26]

moves randomly

[35:30]

and we want to dictate some minimum

[35:32]

value because you never wanted to do

[35:33]

purely greedy actions because you never

[35:36]

know if your estimates are off so you

[35:38]

always want to be exploring to make sure

[35:39]

estimates are not off

[35:44]

and

[35:45]

you can decrease epsilon over time any

[35:47]

number of ways you can do it linearly

[35:49]

that's what deepmind did you can use

[35:50]

square roots you can use any number of

[35:52]

things i'm just going to do

[35:54]

this we're going to multiply it by some

[35:56]

fraction of one

[35:58]

a bunch of nines that'll give you a

[35:59]

really slow decrease of epsilon over

[36:01]

time so the agent takes a lot of random

[36:02]

actions and does a lot of exploration

[36:20]

sorry i flipped my sign there

[36:23]

i thought that didn't look right so yeah

[36:25]

if it tries to drop below 0.01 we're

[36:28]

going to go ahead and set it there

[36:30]

okay so that is the learning function

[36:33]

next up we have to handle the functions

[36:35]

to save the models

[36:37]

and this will just call the save

[36:40]

checkpoint

[36:41]

function

[36:43]

for the

[36:46]

respective networks

[37:05]

next function we need is a way of

[37:07]

updating our graph so what we want to do

[37:08]

is we want to copy the

[37:11]

evaluation network to the target network

[37:16]

and this is actually a little bit tricky

[37:18]

so what you want are the target

[37:20]

parameters

[37:23]

this is why we saved them earlier

[37:28]

and you want to perform a copy operation

[37:32]

on them

[37:35]

now

[37:37]

the reason this is non-trivial is

[37:39]

because you have to pass in a session

[37:41]

and the decision of which session to use

[37:42]

is non-trivial so you have to use the

[37:45]

session for the values that you're

[37:46]

trying to copy from not copy 2. so if

[37:50]

you had q next you would get

[37:52]

an error

[37:55]

which took me a little bit to figure out

[37:57]

so that is our agent class next up we

[37:59]

have to code a

[38:01]

a

[38:02]

main function so of course we have to

[38:05]

start again with our imports

[38:07]

i'm going to import jim

[38:09]

and we want to import a network

[38:16]

we will also need numpy to handle the

[38:18]

reshaping of the observation we're going

[38:20]

to truncate it to make the workload on

[38:23]

the neural the gpu a little bit lower so

[38:26]

import numpy

[38:27]

as np

[38:30]

if you want to save the

[38:33]

the uh games you can actually

[38:36]

use that with uh you can do that with

[38:38]

the wrappers so i won't put that in here

[38:40]

but i will put that in my github version

[38:42]

so you can just do a git pull on this

[38:44]

and you will have the way of

[38:46]

saving the games

[38:48]

so first thing we have to do is

[38:50]

pre-process our observations

[38:53]

and the reason you want to do this is

[38:54]

because you don't need all of the image

[38:56]

we don't need the score and we also

[38:58]

don't need color we just need one

[39:00]

channel

[39:05]

so i've already figured it out if you

[39:07]

take row 30 onward and all the columns

[39:11]

then you will get

[39:12]

a good image

[39:15]

and you want to reshape it like so the

[39:17]

next thing you have to handle

[39:19]

is a way of stacking the frames this is

[39:22]

because the agent can't get a sense of

[39:24]

motion by looking at only one picture

[39:26]

right nobody can get a sense of motion

[39:27]

from looking at one picture worse yet

[39:30]

the openai

[39:31]

atari library returns a sequence of

[39:33]

frames

[39:35]

where it could be a random number

[39:36]

between two three or four so to get a

[39:38]

sense of motion we have to actually

[39:40]

stack a set of frames and we're going to

[39:42]

handle that with this function

[39:44]

so we'll just keep a running stack of

[39:46]

frames the current frame to save

[39:49]

and the buffer size which just tells you

[39:51]

how many frames to save so at the top of

[39:54]

the episode you're not going to have

[39:55]

anything to save right there will be no

[39:57]

stacked frames

[40:00]

so you want to initialize it

[40:04]

so it'll be the buffer size by the shape

[40:06]

of each

[40:08]

individual frame

[40:10]

next you want to iterate over that

[40:18]

and say

[40:19]

each row which corresponds to each image

[40:22]

in your stack gets assigned to a frame

[40:27]

so otherwise it's not the beginning of

[40:29]

the episode and you want to

[40:32]

pop off the bottom observation

[40:34]

shift the set of frames down and append

[40:36]

the new observation to the end so

[40:39]

instead of one two three four it'll be

[40:40]

two three four and then frame five so

[40:43]

let's do that

[40:47]

equals

[40:48]

sorry zero two buffer size minus one

[40:58]

so this will shift everything down

[41:04]

and this will append the current frame

[41:06]

to the

[41:07]

end of the stack

[41:10]

next we have to do a reshape

[41:16]

and this is basically to make everything

[41:17]

play nicely with the neural network

[41:31]

all right now we're ready for our main

[41:33]

function

[41:34]

let's go ahead and save

[41:36]

scroll down

[41:42]

good grief

[41:59]

breakout v0 is the name of the

[42:01]

environment

[42:04]

this is just a flag to determine if we

[42:05]

want to load a checkpoint

[42:17]

sorry so yeah epsilon starts out at 1.0

[42:20]

so the agent takes purely random actions

[42:24]

our learning rate alpha

[42:26]

will be something small like zero zero

[42:28]

zero two five

[42:31]

and we've reshaped our input so it needs

[42:32]

to be 180 instead of 210

[42:35]

180 by 160 by four because we're going

[42:38]

to stack four frames

[42:40]

the breakout library sorry the breakout

[42:42]

game has

[42:43]

three actions

[42:45]

and a memory size of 25 000 which as i

[42:48]

said takes about 48 gigabytes of ram so

[42:50]

go ahead and scale that based on however

[42:52]

much you have if you have 16 gigs go

[42:54]

ahead and reduce it by down to something

[42:56]

like six or seven thousand

[42:59]

so the batch size tells us how many

[43:01]

batches of memories to include for our

[43:03]

training we'll use 32.

[43:08]

if low checkpoint is true then we want

[43:11]

to load the models

[43:16]

next thing we need is a way of keeping

[43:18]

track of the scores

[43:21]

we will need a

[43:25]

parameter for the number of games

[43:27]

stick with 200 to start with a stack

[43:29]

size of four

[43:32]

and an initial score of zero

[43:35]

so

[43:37]

the memory is originally initialized

[43:39]

with a bunch of zeros

[43:42]

that is perfectly acceptable but another

[43:44]

option something else we can do is we

[43:46]

can overwrite those zeros with actual

[43:47]

gameplay sampled from the environment so

[43:49]

why don't we do that so

[43:53]

and the actions are just chosen randomly

[43:54]

right it's just to give the agent some

[43:56]

idea of what is going on in the

[43:58]

environment

[44:01]

so you want to

[44:03]

reset at the top of every episode

[44:09]

you want to pre-process that observation

[44:14]

you want to

[44:16]

go ahead and stack the frames

[44:25]

and then player episode

[44:33]

so there's a bit of a

[44:34]

quirk here the

[44:37]

the agent saves its actions as zero one

[44:40]

or two but the actions in the

[44:41]

environment are actually one two and

[44:43]

three so we have to sample from that

[44:45]

interval and then

[44:47]

add one take the action subtract one and

[44:49]

then save the the transition in the

[44:51]

memory just a bit of a kluge

[44:53]

not a big problem

[45:01]

so then we want to

[45:04]

add that to our stack

[45:21]

go ahead and subtract off one from the

[45:23]

action

[45:24]

and store that transition in memory

[45:38]

and then finally set the old observation

[45:40]

to be the new one

[45:48]

let's go ahead and use a string print

[45:50]

statement

[45:59]

okay

[46:00]

now that we've loaded up our agent with

[46:02]

random memories

[46:03]

we can actually go ahead and play the

[46:05]

game

[46:20]

one thing i like to do is print out the

[46:21]

running average of the last 10 games so

[46:23]

that we get an idea of if the agent is

[46:25]

learning over not over time or not you

[46:28]

do it like this

[46:41]

and then just print that out

[47:01]

and i also like to know if epsilon is

[47:04]

still

[47:05]

one or if it has actually started to

[47:08]

decrease over time

[47:16]

and we also want to save the models

[47:17]

every 10 games

[47:19]

and if on any other game we just want to

[47:22]

print out the episode number

[47:27]

and the score

[47:32]

so we can actually scroll up here

[47:37]

copy this

[47:41]

so we're not done

[47:44]

whoops

[47:46]

there we go

[47:47]

so instead of a random choice it is

[47:50]

agent dot choose action

[47:52]

and that takes in the observation

[47:55]

oh but we did forget to do the same

[47:58]

thing here

[48:00]

grab those

[48:02]

and

[48:03]

put them there so the top of every

[48:05]

episode we reset the environment

[48:07]

pre-process the observation and stack

[48:09]

the frames quite critical

[48:11]

so

[48:12]

we still have to do the same thing with

[48:14]

adding and subtracting one we want to

[48:16]

save the transitions and the only other

[48:18]

difference is that we want to learn at

[48:20]

every step

[48:23]

at the end of the episode

[48:26]

we want to

[48:28]

go ahead and append our score so that

[48:31]

way we can keep track of our average

[48:34]

and if you want to get fancy you can go

[48:36]

ahead and add in a plotting function so

[48:38]

that when this is done learning you can

[48:39]

plot the learning over time and you

[48:41]

should see an upward slope over time and

[48:43]

if you want to plot the epsilons you

[48:44]

should see a gradual downward slope as

[48:46]

well so i'm gonna leave it here because

[48:48]

the model is still training on my

[48:50]

computer it's run about three thousand

[48:51]

iterations three thousand games that is

[48:53]

and it at best it gets two to three

[48:55]

points per set of five lives so it's

[48:58]

really going to need a couple days of

[48:59]

training to get up to anything

[49:00]

resembling competitive gameplay but once

[49:02]

it's done i'll upload another video that

[49:04]

explains how q learning works in depth

[49:06]

and in detail and i'll include the

[49:08]

performance from this particular model

[49:09]

in that video so you can check it out

[49:11]

then feel free to run this yourself when

[49:14]

i finish the model i will go ahead and

[49:16]

upload the trained version to my github

[49:17]

so you are free to download it if you

[49:18]

don't have

[49:19]

any hard any decent gpus to train this

[49:22]

with go ahead leave a comment down below

[49:24]

subscribe i will see you all in the next

[49:27]

video

[52:19]

welcome back everybody in this series of

[52:21]

videos we're going to code up a deep q

[52:23]

network in pytorch to play space

[52:25]

invaders from the atari open ai gym

[52:27]

library in this first video we're going

[52:29]

to code the convolutional neural network

[52:31]

class in the second video we'll code at

[52:32]

the aging class itself and in the third

[52:34]

we'll get to coding the main loop and

[52:36]

seeing how it all performs let's get to

[52:38]

it

[52:44]

so if you're not familiar with the deep

[52:46]

q network i would advise you to check

[52:47]

out my earlier video bite size machine

[52:49]

learning what is a deep q network it's a

[52:50]

quick little explainer video that gives

[52:52]

you the gist of it within about four and

[52:54]

a half minutes uh if you already know

[52:56]

then great we're ready to rock and roll

[52:58]

but if you don't

[52:59]

i'll give you the brief too long didn't

[53:01]

read so basic idea is that we want to

[53:04]

reduce some rather large state space

[53:05]

into something more manageable so we're

[53:07]

going to use a convolutional neural

[53:08]

network

[53:10]

to reduce the representation of our

[53:12]

estate space into something more

[53:13]

manageable and that'll be fed into a

[53:15]

fully connected neural network to

[53:17]

compute the q values in other words the

[53:18]

action values

[53:20]

for any particular given state

[53:24]

we're going to leverage two different

[53:25]

networks a network that is going to tell

[53:27]

us the value of the current state as

[53:29]

well as a network to tell us the value

[53:31]

of the successor states this is going to

[53:33]

be used to calculate the values of the

[53:35]

target and which is the purely greedy

[53:37]

action as well as the behavioral network

[53:40]

which is the current predicted state and

[53:42]

the difference between those two is used

[53:43]

in the loss function for our stochastic

[53:46]

gradient descent or root mean squared

[53:47]

propagator

[53:50]

so let's go ahead and get started um

[53:53]

we're going to start as usual

[53:55]

by doing our imports

[53:59]

and

[54:00]

there are quite a few

[54:02]

in pi torch

[54:04]

great library

[54:09]

one thing i really like about it is that

[54:11]

it's highly expressive you don't have a

[54:12]

whole lot of boilerplate code as you do

[54:14]

in something like tensorflow tensorflow

[54:16]

is enormously powerful uh and if you

[54:18]

wanna do

[54:19]

um

[54:20]

cross app type of software then that's

[54:23]

going to be really your only choice

[54:25]

for our purposes this is going to be

[54:28]

precise you want to use

[54:32]

and of course numpy

[54:34]

so

[54:36]

we're going to define a class for our

[54:37]

deep q network and that'll derive from

[54:40]

an end module

[54:42]

this is kind of how

[54:43]

uh

[54:44]

pytorch handles everything you want to

[54:46]

derive your class from the module

[54:48]

uh the base module uh so that way you

[54:50]

get access to all of the goodies

[54:53]

and we'll pass in our learning rate

[54:55]

alpha for our

[54:57]

stochastic gradient descent algorithm

[55:06]

all right so

[55:08]

the network is comprised of three

[55:10]

convolutional layers and two fully

[55:12]

connected layers

[55:13]

so the first one is just going to be a

[55:16]

two-dimensional convolution that's going

[55:18]

to take one input channel the reason is

[55:21]

that the

[55:23]

agent doesn't really care about color so

[55:25]

we're going to go ahead and make things

[55:26]

easier reduce our computational

[55:27]

requirements by going to a grayscale

[55:29]

representation

[55:31]

we'll take

[55:33]

32 filters with an 8 by 8 kernel

[55:36]

a stride of 4 and a padding of

[55:40]

1.

[55:43]

second layer

[55:44]

is going to be pretty similar

[55:47]

this one of course will take 32 channels

[55:49]

in give 64 channels out

[55:51]

and do a 4x4 kernel with a stride of two

[55:56]

and our third convolutional layer is

[55:59]

going to be of course two-dimensional as

[56:01]

well takes in 64

[56:03]

outputs 128 with a 3x3

[56:06]

kernel

[56:08]

uh that's it for the convolutions hey if

[56:10]

you don't know how convolutional neural

[56:11]

network works i'm going to go ahead and

[56:13]

link a video here that will give you the

[56:16]

uh

[56:17]

the the basic idea of of how those work

[56:20]

and if you would rather see how uh how

[56:22]

this stuff works in text form i don't

[56:23]

know if i mentioned this earlier but

[56:24]

there is an associated blog article my

[56:26]

website neuronet dot ai yeah i bought

[56:28]

that domain i'll link it in the

[56:30]

description go ahead and check it out

[56:32]

please

[56:34]

so our fully connected layer is the

[56:36]

following

[56:38]

and we're going to have to do a little

[56:40]

bit of magic here so

[56:43]

after running this stuff a bunch of

[56:44]

times

[56:45]

uh i know the dimensionality of the

[56:48]

images we're going to of the

[56:49]

convolutions we're going to get out and

[56:51]

what we want to know is

[56:55]

we're going to be taking a

[56:57]

set of filters uh you know convolved

[56:59]

images that have had filters applied to

[57:01]

them 128 to be exact and we want to

[57:04]

unroll them into a single flattened

[57:06]

image right to feed into our neural

[57:08]

network so that's going to be 128

[57:10]

channels that are 19 by 8 in size and

[57:13]

that's a magic number i got from just by

[57:16]

running the code in trial and error

[57:20]

and then our output layer is going to

[57:22]

take in those 512

[57:25]

units and output 6 y6 that's because we

[57:28]

have a total of 6 actions in the

[57:31]

game of space invaders you have a total

[57:32]

of 6 actions which are the subset of the

[57:35]

full 20 available in the atari library

[57:37]

basically the agent can do nothing it

[57:39]

can move left it can move right it can

[57:40]

shoot while standing still and it can

[57:41]

move left and right and shoot

[57:44]

when we get to the main video i'll go

[57:45]

ahead and show all those actions

[57:48]

we also need an optimizer

[57:52]

equals optim

[57:54]

rms prop

[57:56]

and we want to tell it to take the

[57:58]

parameters of our object for the weights

[58:02]

and our learning rate is going to be

[58:04]

alpha that we've passed in

[58:06]

our loss function is going to be a mean

[58:09]

square error loss

[58:13]

and the components of that will be the

[58:14]

target and the current predicted q

[58:17]

functions and of course the target is

[58:19]

just the greedy value right because q

[58:20]

learning is an off policy method that

[58:22]

uses

[58:23]

a

[58:24]

epsilon greedy behavioral policy to

[58:26]

update the purely greedy target policy

[58:31]

another thing we have to do in

[58:34]

pi torch is tell it which device we're

[58:36]

using so t.device

[58:39]

and that'll be cuda zero

[58:41]

if t dot cuda is

[58:44]

available

[58:46]

else

[58:47]

cpu

[58:48]

and what this is telling it is that if

[58:50]

the gpu is available go ahead and use it

[58:52]

which is of course always preferable

[58:54]

otherwise just use the cpu

[58:56]

and we

[58:57]

also have to tell it

[58:59]

to actually

[59:00]

send the network to the device

[59:03]

um maybe i'm using 0.4 i don't know if

[59:06]

in 1.0 that's actually required but as

[59:09]

of the time i'm coding this up it's

[59:11]

required so

[59:12]

uh something we have to live with

[59:15]

okay so this is the sum and the whole of

[59:18]

our network

[59:19]

only thing where that remains to do is

[59:21]

to feed forward our observation

[59:27]

and that will take

[59:29]

the

[59:30]

opposite no not observation observation

[59:33]

not only can i not type i cannot speak

[59:35]

as well

[59:36]

i suck at life

[59:38]

i don't know why you guys listen to me

[59:41]

so what we want to do is

[59:43]

the observation vector uh is the

[59:48]

we're going to use a sequence of frames

[59:50]

and those frames are the reduced images

[59:53]

from the screen so when we get to the

[59:54]

third video on

[59:56]

um

[59:57]

[Music]

[59:58]

on actually playing the game you'll see

[59:59]

that you don't need the full frame to

[60:00]

actually figure out what's going on you

[60:02]

can actually truncate it to get a really

[60:03]

good idea

[60:04]

in particular the agent can only move

[60:06]

left and right a certain

[60:08]

amount so we go ahead and truncate the

[60:09]

sides uh you don't need the score at the

[60:11]

top because we're keeping track of the

[60:12]

score ourselves you don't need some of

[60:14]

the bottom so you can actually truncate

[60:15]

the image a little bit to reduce your

[60:16]

memory requirements and we're going to

[60:18]

convert it into a grayscale so we get

[60:20]

rid of two we're just going to average

[60:22]

the three channels to make them into one

[60:25]

and we also have to pass in a sequence

[60:27]

of frames right because if i only show

[60:30]

you one frame of video game you can't

[60:31]

tell what's going on you don't get a

[60:33]

sense of motion from a single frame

[60:34]

right you need at least two to get a

[60:36]

sense of motion uh we'll be using three

[60:38]

i believe in the original implementation

[60:40]

of this algorithm for um

[60:43]

for deepmind they used four we're going

[60:45]

to go ahead and use three just to be

[60:46]

different

[60:47]

um

[60:48]

i haven't i suspect that's a

[60:49]

hyperparameter it's not something i've

[60:51]

played with i encourage you to do that

[60:52]

oh another thing is that

[60:55]

we must train this on a gpu if you try

[60:57]

to do it on your cpu it's going to take

[60:59]

7 000 years so

[61:00]

uh if you do not have access to a gpu go

[61:03]

ahead and leave a comment below and i

[61:05]

will find a way to get my pre-trained

[61:06]

model to you so you can go ahead and

[61:08]

play around with this

[61:10]

i have a 1080 ti and not not top of line

[61:13]

anymore but it's still quite good for

[61:14]

this particular apps application

[61:18]

so

[61:19]

back to the topic we have to

[61:21]

convert our sequence of frames our obser

[61:24]

observation to a tensor and we

[61:28]

also want to send that to the device uh

[61:30]

this is a peculiarity of pi torch as far

[61:32]

as i'm aware i'm not the world's leading

[61:34]

expert but as far as i understand it you

[61:36]

have to tell it to send the network as

[61:38]

well as the variables to the device as

[61:40]

well

[61:41]

not a big deal just something to be

[61:42]

aware of

[61:45]

next thing we have to do is resize it so

[61:47]

when you are given a sequence of frames

[61:50]

in the open ai gym and really any other

[61:53]

format of image is going to be

[61:56]

height and width by channels whereas if

[62:00]

you look up here

[62:01]

this actually expects the channels to

[62:03]

come first

[62:05]

and so we have to reshape the array to

[62:07]

to accommodate that

[62:09]

so

[62:10]

pytorch's built-in function for that is

[62:12]

view

[62:13]

we want a minus one to handle any number

[62:15]

of stacked frames

[62:17]

one channel in the beginning and we're

[62:19]

going to pass in 185 by 195 image

[62:23]

[Music]

[62:29]

that doesn't seem right actually sorry

[62:31]

it's not 195 i'm like the original image

[62:34]

is 210 by 160 it can't be 180 595

[62:38]

total brain fart there it's 185 by 95

[62:42]

okay so we have

[62:44]

taken in our sequence of frames we've

[62:46]

converted it into a tensor and flat and

[62:50]

converted it into the proper proper

[62:52]

shape for our network the next thing we

[62:54]

want to do is

[62:57]

activate it and feed it forward so

[63:00]

we call the first convolutional layer on

[63:02]

our observation

[63:03]

and we use the value function to

[63:06]

activate it

[63:07]

and we

[63:08]

store that in the new variable

[63:10]

observation

[63:11]

and then

[63:13]

we learn how to type and then we do the

[63:15]

same thing with that output

[63:18]

pass it through the second convolutional

[63:20]

layer

[63:22]

and then we do the same thing again we

[63:25]

pass it to the third convolutional layer

[63:30]

um

[63:31]

and we're almost home free so the next

[63:33]

thing we have to do

[63:34]

is

[63:35]

we are outputting a 128 by 19 by eight

[63:40]

oh

[63:41]

set of arrays

[63:51]

the next thing we have to do is

[63:54]

oh by the way that noise is my pomodoro

[63:56]

timer if you're not using the pomodoro

[63:58]

technique i highly recommend it

[63:59]

it's an enormous productivity hack but

[64:01]

anyway

[64:02]

next thing we have to do is

[64:05]

take our sequence of

[64:07]

convolved images and flatten them to

[64:09]

feed into our

[64:11]

fully connected neural network so we

[64:13]

again use the view function

[64:18]

uh to do that not minus one for whatever

[64:20]

number of frames we pass in

[64:23]

19 by eight is what we get out and i

[64:24]

found that out through experimentation

[64:27]

and we know it's 128 channels because we

[64:29]

dictate that

[64:31]

here right here 128 output channels

[64:34]

so boom we've flattened it and the only

[64:37]

thing that remains is to feed it forward

[64:40]

and we'll use a value activation

[64:41]

function there

[64:43]

fc1

[64:44]

fully connected layer one

[64:46]

and then

[64:47]

it's not observation but it's actions

[64:50]

self dot

[64:51]

fc2 observation so we'll feed it through

[64:54]

the final

[64:56]

fully convolved layer and store that as

[64:58]

a variable called actions and go ahead

[65:00]

and

[65:01]

return it

[65:02]

and the reason we're doing that is

[65:04]

because

[65:07]

what we're getting out is a q value for

[65:10]

each of our actions and we want to pass

[65:11]

that back now keep in mind that we're

[65:13]

passing in a sequence of frames and so

[65:15]

we're going to get back is a

[65:17]

matrix it's not going to be a single

[65:19]

array of six values it's going to be six

[65:22]

values times whatever number of rows of

[65:24]

images you pass in so if we pass in

[65:26]

three images it's going to have three

[65:28]

rows and six columns and that'll be

[65:30]

important later when we actually get to

[65:31]

choosing the actions

[65:33]

speaking of which i'm going to cut it

[65:35]

short here we've already i've already

[65:36]

rambled for about 12-13 minutes uh in

[65:39]

part two we're going to take a look at

[65:40]

coding of the agent class i have

[65:42]

structured it this way because the agent

[65:44]

actually has two networks so it made

[65:46]

sense to kind of stick the network in

[65:47]

its own class

[65:49]

we'll get to coding up the agent's init

[65:51]

function how to handle its memory how to

[65:53]

store transitions how to choose actions

[65:56]

and how to actually implement the

[65:57]

learning function that's a much longer

[65:59]

project so we'll stick that in its own

[66:00]

video and then in part three we're going

[66:02]

to get to actually coding up the main

[66:03]

loop and seeing how it performs hey if

[66:05]

you liked the video make sure to like

[66:07]

the video hey if you don't like it go

[66:08]

ahead the thumbs down i don't really

[66:10]

care let me know what you think

[66:11]

questions comments leave them down below

[66:13]

if you made it this far please consider

[66:15]

subscribing i look forward to seeing all

[66:17]

of you in the next video

[66:21]

welcome back everybody in the previous

[66:23]

video we got to coding the convolutional

[66:24]

neural network class for our deep q

[66:26]

learning agent that's going to play

[66:28]

space invaders if you haven't seen that

[66:30]

yet go ahead and click the link to go

[66:31]

ahead and watch that first otherwise you

[66:33]

probably won't know what's going on

[66:35]

if you're if you're the type of person

[66:37]

that would prefer to have a

[66:39]

written set of instructions go ahead and

[66:40]

click the link down below i'll link to

[66:42]

the associated blog article for this

[66:44]

particular tutorial series

[66:46]

when we last left off we just finished

[66:49]

returning the set of actions which is

[66:50]

the set of q values for our sequence of

[66:53]

frames

[66:54]

so of course in this video we're going

[66:55]

to go ahead and get started

[66:57]

coding up the agent class which is where

[67:00]

all the magic is going to happen

[67:01]

uh oh and of course as always i have

[67:04]

left the code for this in my github

[67:06]

under the youtube directory it gets its

[67:08]

own directory because there's a few

[67:09]

different files here

[67:11]

i'll link that below as well and if you

[67:12]

aren't following me on github you

[67:14]

probably should because that's where i

[67:15]

post all of my stuff

[67:18]

okay next up we have the

[67:21]

agent class right

[67:23]

and this is just going to derive from

[67:25]

the base object class nothing fancy here

[67:28]

we need a basic init function

[67:31]

and this is going to take gamma which is

[67:32]

our

[67:33]

discount factor so the agent

[67:36]

has a choice of how to value future

[67:38]

rewards

[67:39]

in general gets discounted by some value

[67:41]

because a reward now is worth more than

[67:43]

a reward in the future

[67:45]

just like with us we need epsilon for

[67:47]

epsilon greedy action selection

[67:49]

the alpha for the learning rate

[67:52]

the max memory size

[67:55]

a

[67:56]

variable to keep track of how low we

[67:58]

want epsilon to go

[68:00]

something to keep track of how long we

[68:02]

replace of how often we're going to

[68:04]

replace our target network i'll get to

[68:06]

that in a moment

[68:07]

for in a few minutes

[68:09]

and the action space and that's just a

[68:11]

list

[68:13]

of variables from zero through five

[68:15]

those correspond to all the possible

[68:17]

actions for our agent

[68:22]

and you just set these

[68:25]

to the appropriate variables

[68:27]

uh

[68:30]

being careful not to turn on your caps

[68:31]

lock key

[68:34]

so what these all are are just hyper

[68:36]

parameters for our agent we don't need

[68:38]

to store alpha because we're just going

[68:39]

to pass it into the network

[68:42]

and then never touch it again

[68:45]

storing the action space allows us to

[68:47]

accommodate the epsilon greedy action

[68:49]

selection later

[68:51]

the mems size

[68:53]

is

[68:55]

used for

[68:57]

efficiency purposes so we're going to

[68:58]

keep track of state action reward

[69:00]

transitions you don't want to store an

[69:02]

infinite number of them you only want to

[69:04]

store a subset

[69:06]

you don't need to store all of them

[69:07]

anyway there's no real practical benefit

[69:09]

since we're just sampling a subset

[69:10]

anyway so

[69:12]

we just use some rather large

[69:14]

memory um to keep track of all of the

[69:17]

state transitions

[69:18]

that we care about

[69:20]

keep track of how many steps

[69:22]

and the learn step counter

[69:26]

that is

[69:27]

to keep track of how many times the

[69:29]

agent has called the learn function that

[69:31]

is used for target network replacement

[69:34]

if you're not familiar with it target

[69:35]

network replacement is when you swap the

[69:37]

parameters from the evaluation network

[69:40]

to the

[69:41]

target network

[69:43]

my experience has been that it doesn't

[69:45]

actually help things so i'm not going to

[69:46]

do it i'm going to code it in because

[69:48]

it's

[69:49]

an important part of the topic but in

[69:51]

this particular case i haven't found it

[69:52]

to be helpful

[69:55]

but i haven't played with it too much i

[69:57]

saw that it does quite well without it

[69:58]

so why break it

[70:00]

so i'm going to store the memory as a

[70:02]

list and the reason i'll use a list

[70:05]

instead of

[70:06]

a numpy array is because the

[70:09]

associated cost of stacking numpy rays

[70:12]

is really really high so it's much much

[70:14]

faster to store a list of lists and then

[70:17]

convert to a numpy array when you learn

[70:20]

and that's much faster than keeping

[70:22]

track of a set of numpy arrays and just

[70:23]

stacking them the stack operation is

[70:25]

incredibly computationally prohibitive

[70:27]

so

[70:28]

for something like this that's already

[70:30]

computationally expensive doesn't make

[70:31]

any sense

[70:32]

[Music]

[70:34]

and keep track of the total number of

[70:37]

memory stored so that way you don't

[70:38]

overwrite the array

[70:41]

we want to keep track of how often we

[70:43]

want to replace the target network

[70:46]

and then we need our two networks qe val

[70:52]

and that is just

[70:55]

passing the alpha that is just the

[70:58]

agent's estimate of the current set of

[71:00]

states

[71:02]

and q next is the agent's estimate of

[71:05]

the successor set of states so recall in

[71:08]

deep q learning

[71:10]

we calculate the value the max value of

[71:13]

the successor state as our greedy action

[71:16]

that's our our actual target policy and

[71:19]

our behavior policy that we used to

[71:20]

generate data is epsilon greedy

[71:22]

that's it for our constructor

[71:25]

the next thing we have to worry about is

[71:29]

storing memory transitions

[71:32]

so

[71:33]

transition

[71:36]

so we are interested in the current

[71:39]

state

[71:40]

the action taken

[71:41]

the reward received

[71:44]

and the resulting state

[71:46]

because those are the things that that

[71:49]

allow the agent to learn so

[71:51]

we have to make sure that we

[71:54]

aren't over our memory so if the

[71:57]

mem

[71:58]

counters less than self.mem size

[72:01]

then just go ahead and append that

[72:07]

as a list

[72:12]

and again we're doing this because

[72:16]

it is much cheaper computationally to

[72:18]

append a list than it is to actually

[72:20]

stack a numpy array

[72:22]

if we have

[72:23]

filled up our memory then we want to

[72:26]

uh overwrite the position in memory that

[72:29]

is uh determined by the modulus

[72:35]

dot mem size so this will guarantee we

[72:37]

are bounded by zero all the way up to

[72:39]

our mem size

[72:45]

and of course this is a list of lists

[72:47]

it's just an action reward state

[72:50]

underscore

[72:52]

and we want to increment the memory

[72:54]

counter

[72:55]

pretty simple huh pretty straightforward

[72:59]

next up we have the

[73:01]

function to choose an action and this

[73:04]

will take the observation

[73:07]

and again just to remind you as we

[73:08]

discussed in the first video we're

[73:10]

passing in a sequence of observations

[73:12]

because we want to capture some

[73:13]

information about the temporal

[73:15]

dependence of what's going on again with

[73:17]

one frame you can't tell if the aliens

[73:19]

are moving left or right and so you

[73:21]

don't know if you should move left or

[73:22]

right

[73:23]

um of course you know which way your

[73:24]

bullets go you know which way there is

[73:26]

go but

[73:28]

as far as movement is concerned you need

[73:29]

at least one frame

[73:31]

so

[73:32]

as always

[73:33]

we're going to be using

[73:36]

numpy to calculate a random number for

[73:38]

us to our epsilon greedy action

[73:41]

selection

[73:42]

and you want to get the

[73:45]

value

[73:46]

of all of the actions for the current

[73:48]

set of states itself

[73:50]

q eval dot forward

[73:54]

so what we're doing now is forward

[73:55]

propagating that stack of frames through

[73:58]

the neural network the convolutional

[73:59]

neural network and the fully connected

[74:01]

layer to get the value

[74:03]

of each of each of the actions given

[74:05]

that you're in some set of states

[74:06]

denoted by the observation

[74:10]

so if rain is less than one minus

[74:13]

epsilon

[74:16]

then

[74:17]

you want to take the

[74:18]

arg max write the maximum action

[74:21]

and recall that we have stored the

[74:25]

actions as a matrix they're returned as

[74:27]

a matrix because you have

[74:30]

the number of rows that correspond to

[74:31]

the number of frames you pass in and

[74:34]

each of the columns correspond to each

[74:36]

of the six actions

[74:37]

so you want to take the

[74:40]

first

[74:41]

first axis

[74:45]

and if you're taking a random action

[74:49]

then you just choose something at random

[74:51]

from the action space list

[74:55]

and

[74:57]

go ahead and increment your steps

[75:00]

and return the action that you've chosen

[75:03]

the way i the reason i use one minus

[75:05]

epsilon is um

[75:06]

[Music]

[75:08]

you can use the probability epsilon

[75:10]

you can use probability one minus

[75:11]

epsilon this is really more of a soft uh

[75:14]

soft epsilon kind of strategy

[75:17]

rather than purely greedy but it doesn't

[75:19]

really matter this is going to give you

[75:21]

the probability of choosing the maximum

[75:23]

action

[75:24]

of epsilon plus epsilon over six because

[75:27]

they're

[75:28]

of course the greedy action is the

[75:30]

subset of all actions so there's a one

[75:32]

over six probability that when you take

[75:34]

the

[75:36]

quote-unquote non-greedy action you'll

[75:37]

actually end up getting the greedy

[75:39]

action

[75:41]

all right

[75:44]

next thing we have to worry about is how

[75:46]

the agent is going to learn and this is

[75:48]

really the meat of everything so

[75:52]

we are doing batch learning so you want

[75:54]

to pass in a batch size

[75:56]

and

[75:57]

the reason we're doing batch learning is

[75:59]

um

[76:00]

[Music]

[76:01]

a number of different reasons so you

[76:02]

want to break correlations

[76:05]

uh state transitions you you

[76:08]

it's even okay if the the batch overlaps

[76:10]

different episodes what you want to get

[76:12]

is a good sub sampling

[76:14]

of

[76:15]

the

[76:16]

overall

[76:17]

parameter space so that way you don't

[76:19]

get trapped in a local minima so you

[76:21]

randomly sample these

[76:23]

state transitions through your memory

[76:25]

otherwise you could end up if you replay

[76:26]

the whole memory you could end up

[76:28]

getting trapped in some local minimum

[76:29]

it's a way to improve the efficiency of

[76:31]

the algorithm to converge to a purely

[76:33]

optimal strategy excuse me

[76:41]

and thursday

[76:43]

all right

[76:45]

first thing we have to do since we're

[76:47]

using batch learning

[76:48]

is uh

[76:50]

we have to zero out our gradients and

[76:53]

what this means is that

[76:56]

the gradients can accumulate from step

[76:58]

to step the network like pi torch

[77:00]

library can keep track of it we don't

[77:01]

want that if you do that if you don't do

[77:04]

the zero grad then you'll end up with

[77:07]

um

[77:08]

basically accumulating for every single

[77:10]

batch and that's really full learning

[77:12]

rather than batch learning

[77:14]

next thing we have to check for is

[77:19]

if we're going to replace a target

[77:20]

network

[77:24]

so if it's not none and

[77:29]

if it's time to do it

[77:35]

release now replace target

[77:39]

account equals zero then we want to

[77:41]

actually replace our target network what

[77:43]

we do there is

[77:44]

we take advantage of the pi torch

[77:46]

representation of our network

[77:48]

in that case it's just

[77:50]

we can convert our entire network into a

[77:53]

dictionary which is really cool so

[77:55]

itself

[77:56]

qnext dot load state dict

[78:00]

so it's going to load

[78:02]

uh a state to the network from a

[78:04]

dictionary

[78:05]

which network the evaluation

[78:08]

network

[78:09]

which we're going to convert to a state

[78:11]

dictionary

[78:13]

we're not actually going to use this in

[78:14]

our implementation but i include it here

[78:16]

for completeness

[78:18]

uh next up uh we want to know

[78:21]

uh we want to select a random sub-sample

[78:24]

of the memory so

[78:26]

we want to make sure we don't go all the

[78:28]

way past the end of our array

[78:31]

so if

[78:33]

our current memory counter plus batch

[78:35]

size is less than our total memory

[78:37]

well then we're free to go ahead and

[78:40]

select

[78:41]

any point

[78:43]

of our memory

[78:45]

because we know we're not going to go

[78:46]

beyond it

[78:50]

range

[78:54]

otherwise if

[78:56]

there is an overlap then we want memstar

[78:58]

to just be an int in the range

[79:00]

[Music]

[79:02]

good grief

[79:04]

i hate that

[79:09]

minus one just to be safe

[79:12]

uh okay so

[79:14]

that is how we choose where to start

[79:16]

just a random number somewhere between

[79:19]

zero and the max memory if we have

[79:20]

enough leftover

[79:23]

in the memory for the bat to accommodate

[79:25]

the batch otherwise subtract that off

[79:27]

and select something from that subset

[79:33]

then we're going to go ahead and get

[79:34]

that mini batch

[79:41]

and convert that to a

[79:44]

numpy array so

[79:46]

i suspect this is not the most efficient

[79:49]

way of doing this

[79:50]

and the reason is that

[79:52]

you run into some difficulties in the

[79:54]

way in which you pass things into the

[79:56]

torch library it has a certain set of

[79:58]

expectations that

[80:01]

are kind of finicky um not to say it's

[80:04]

bad it's just something that i wasn't

[80:08]

uh expecting but

[80:10]

it works nonetheless

[80:12]

so what we want to do next is feed

[80:14]

forward both of our networks we want to

[80:16]

know what is the value of our current

[80:17]

state and what is the value of the

[80:19]

successor state after we take the action

[80:21]

whatever action we're looking at in our

[80:23]

batch

[80:25]

so that's just q eval forward

[80:28]

what are we feeding forward

[80:30]

here's where we got some hackiness we

[80:32]

got to convert it into a list and the

[80:33]

reason is that our

[80:35]

memory is a numpy array

[80:38]

of numpy objects because the

[80:40]

observation vectors are numpy objects so

[80:44]

if you don't convert it into a list

[80:47]

then you have a numpy array of nd array

[80:49]

objects and tensor

[80:51]

pi torch will complain

[80:53]

we don't want tensor we don't want pi

[80:55]

torch to complain so

[80:57]

we want to access all

[80:59]

all rows

[81:00]

right our entire batch and the state is

[81:02]

just the zeroth element

[81:04]

and you want

[81:06]

all of the variable you want all of the

[81:08]

pixels

[81:10]

so you need the second set of columns

[81:12]

there and

[81:14]

we want to send this to the device

[81:17]

self dot

[81:18]

q eval dot device

[81:22]

and this ensures that the

[81:24]

this network this set of variables gets

[81:26]

sent to our gpu as well

[81:28]

the next thing we need is the

[81:31]

value of the successor states

[81:37]

and that is just all the

[81:40]

rows

[81:41]

third column

[81:44]

and all of the

[81:47]

um all of the

[81:50]

members of that array

[81:51]

[Music]

[81:54]

and here i've just

[81:56]

uh

[81:57]

i gotta quit using the visual studio

[81:59]

code this is annoying but um

[82:02]

scroll up here so all i have done here

[82:05]

is

[82:06]

um i'm putting it on qeval.device

[82:09]

because the device for both the

[82:10]

evaluation and the

[82:12]

uh

[82:12]

next network are the same so i only have

[82:14]

one gpu if i had two gpus then this

[82:17]

would matter

[82:18]

it doesn't matter so

[82:20]

you can just call it that

[82:22]

next thing we want to know is what is

[82:24]

the max action for our current for our

[82:27]

next state right because the

[82:29]

update rule actually calculates takes

[82:32]

into account the purely greedy action

[82:33]

for the successor state uh maybe if i

[82:35]

can find an image of it i'll flash it

[82:36]

here on the screen to make life easy but

[82:38]

next thing we have to know is the max

[82:40]

action

[82:41]

and we use the arg max function for that

[82:44]

and remember we want to take the first

[82:46]

dimension because we're

[82:48]

the actions q next q predicted and q

[82:51]

next are actually our actions that's

[82:52]

what we get from the feed forward

[82:55]

and that is batch size times

[82:58]

number of actions and we want the number

[83:00]

of actions so that's first dimension

[83:05]

and i am a little bit

[83:08]

in or attentive here about sending it to

[83:09]

the device just to make sure nothing

[83:11]

gets

[83:13]

off the device because this stuff slows

[83:15]

to a crawl if you run on the cpu

[83:18]

we need to get our rewards

[83:20]

and that is uh obtained from our memory

[83:23]

all the rows and the second element

[83:32]

too many parentheses

[83:34]

and

[83:37]

one thing we want is our loss function

[83:39]

to be zero for every action except for

[83:42]

that max action so

[83:44]

we have q target equal q predicted

[83:49]

but we want q target for all of our our

[83:52]

entire match but the max action

[83:56]

to be rewards plus self dot gamma times

[84:00]

the actual value of that

[84:03]

action

[84:05]

so t.max just gives you the value of the

[84:09]

maximum element and argmax gives you the

[84:11]

index

[84:12]

and you want to find the maximum action

[84:14]

the value of it

[84:18]

so those are our target and predicted

[84:21]

values that's what we use to update our

[84:22]

loss function the next thing we have to

[84:24]

handle is the epsilon decrement so we

[84:27]

want the agent

[84:28]

to gradually converge on a purely greedy

[84:31]

strategy for its

[84:32]

behavior policy

[84:34]

and

[84:35]

the way you do that is by gradually

[84:36]

decreasing epsilon over time i don't

[84:38]

like to let it

[84:41]

simply go to

[84:42]

um start decreasing right away so i have

[84:45]

some set number of steps i let it run

[84:47]

first

[84:51]

and i use a linear decrease over time

[84:56]

you can use exponential

[84:59]

quadratic you can use whatever form you

[85:01]

want

[85:03]

it's not

[85:06]

it's my knowledge it's not super

[85:07]

critical but i could be completely wrong

[85:09]

this seems to work as we'll see in the

[85:10]

third video

[85:12]

so if we don't have enough left then

[85:14]

just set it to epsilon end

[85:20]

scroll up here

[85:21]

and we're almost done so we have

[85:23]

everything we need we have everything we

[85:25]

need to compute our loss which is this

[85:27]

q target

[85:28]

and q predicted

[85:30]

those are the values of q predicted is

[85:32]

the value of the current set of states

[85:36]

and q target is related to q next right

[85:40]

it's the q target is the max action

[85:44]

for the next successor state

[85:48]

and so we're almost there so the loss

[85:54]

it's just

[85:55]

the mean squared error loss if you

[85:56]

recall from the first video where we

[85:58]

defined the

[85:59]

loss function

[86:01]

and

[86:03]

as is the

[86:05]

torch style you have to send it to the

[86:06]

device

[86:08]

and then we want to back propagate with

[86:10]

loss backward

[86:13]

and we just want to step

[86:16]

perform one iteration and go ahead and

[86:19]

increment our learn step

[86:21]

counter

[86:23]

and that's basically it so there was a

[86:25]

lot of code there let's go back and take

[86:27]

a look really quick so first thing you

[86:29]

want to do is zero your gradients

[86:31]

so that way we're doing actual batch

[86:33]

optimization instead of full

[86:35]

optimization

[86:37]

then we want to check to see if we're

[86:38]

gonna if it's if we are going to replace

[86:40]

the target network and if it is time and

[86:42]

if it is load the state dictionary from

[86:44]

the q eval on to the q next network

[86:48]

next up

[86:49]

calculate the start of the bat of the uh

[86:52]

memory sub sampling i'm making sure to

[86:55]

get some subset of the array

[87:00]

go ahead and sample that batch of memory

[87:02]

and convert it to a numpy array

[87:05]

oh pomodoro timer

[87:07]

so if you guys

[87:09]

aren't using the pomodoro method

[87:12]

to work i highly recommend it go look

[87:14]

that up if you don't know what it is but

[87:16]

anyway

[87:17]

convert that to a numpy array and then

[87:18]

go ahead and feed forward the

[87:20]

the current state and the successor

[87:23]

state

[87:24]

using the memory sub sample

[87:27]

um making sure it is sent to your device

[87:30]

next thing we have to know is the

[87:32]

maximum action for the successor state

[87:36]

and calculate the rewards that the agent

[87:38]

was given set the q target to q

[87:40]

predicted because you want the loss for

[87:42]

every state except

[87:43]

the loss for every action except the max

[87:45]

action to be zero

[87:47]

and then update the value of q target

[87:50]

for the max action to be equal to

[87:51]

rewards plus gamma times the actual

[87:53]

value of that max action

[87:56]

next up

[87:57]

make sure that you're using some way of

[88:00]

decrementing epsilon over time such that

[88:02]

it converges to some small value

[88:04]

that

[88:05]

makes the agent

[88:07]

settle on an mostly greedy strategy in

[88:09]

this clay in this case i'm using five

[88:10]

percent of the time for a

[88:12]

random action

[88:14]

finally go ahead and calculate the loss

[88:16]

function back propagated

[88:19]

step your optimizer and increment your

[88:21]

step counter

[88:23]

and that is all she wrote for the learn

[88:25]

function and the aging class slightly

[88:27]

more code than in the network class but

[88:30]

still fairly

[88:34]

we have a typo there still fairly

[88:36]

straightforward

[88:37]

i hope this has been informative and in

[88:39]

part three we're going to go ahead and

[88:40]

code up the main loop and see how all

[88:42]

this performs i look forward to seeing

[88:44]

you in the next video

[88:45]

any comments questions suggestions go

[88:47]

ahead and leave them below if you made

[88:49]

it this far please consider subscribing

[88:50]

i look forward to seeing you all in the

[88:52]

next video

[88:54]

and welcome back everybody to part three

[88:56]

of coding a deep q learning agent in the

[88:58]

open ai gym atari library

[89:01]

uh in parts one and two we took a look

[89:03]

at the

[89:04]

deep neural network class as well as the

[89:06]

aging class for our agent and in part

[89:08]

three we're going to finally put it all

[89:09]

together into the main loop to play the

[89:11]

game and see how our agent does

[89:14]

let's get started

[89:29]

so we begin as usual with our typical

[89:31]

imports we're going to need the gym of

[89:33]

course

[89:34]

and we're going to import our

[89:37]

our model class so from model we'll

[89:39]

import

[89:41]

deep

[89:43]

sorry dq model

[89:45]

and agent

[89:48]

and

[89:49]

i also have a utility function i'm not

[89:52]

going to go over the code it's just a

[89:54]

trivial function to post the uh to print

[89:57]

to plot

[89:58]

the

[90:00]

decaying epsilon and the running average

[90:02]

of previous five scores

[90:05]

from utils import

[90:07]

plot learning

[90:09]

and

[90:11]

uh oh and by the way so

[90:13]

if you haven't seen parts one and two go

[90:15]

ahead check those out

[90:17]

and

[90:18]

if you want the code for this please

[90:19]

check out my github if you would like to

[90:21]

see a

[90:22]

blog article that details all this in

[90:24]

text if you missed something in the

[90:25]

speech

[90:26]

then go ahead and click the link down

[90:27]

below

[90:31]

so it's giving me some issue

[90:35]

uh oh it's not deep cue model this is

[90:37]

the the downside of talking and typing

[90:39]

at the same time i'm not that talented

[90:41]

so

[90:46]

uh we want to go ahead and make our

[90:48]

environment

[90:51]

and that space invaders

[90:54]

v0

[90:55]

uh another thing to know is that there

[90:57]

are implementations of the environment

[90:59]

where instead of being passed back an

[91:01]

image of the screen you're passed back

[91:02]

like a ram image something like that

[91:04]

i've never used it sounds kind of

[91:06]

interesting it might be something for

[91:07]

you to check out and leave a comment

[91:08]

down below if you've played with have

[91:10]

any experience with it

[91:11]

or if you think it sounds cool

[91:13]

so we want to make our agent and i'm

[91:14]

going to call it brain big brain

[91:17]

pinky in the brain baby gamma i have

[91:20]

0.95

[91:22]

an epsilon of 1.0

[91:25]

and

[91:26]

i'm using epsilon 1.0 because it starts

[91:29]

out taking purely random actions and

[91:30]

converges on a mostly greedy strategy

[91:35]

learning rate of 0.03

[91:37]

max memory size

[91:40]

5000 transitions and

[91:43]

we're not going to do any replacement

[91:47]

so you may have noticed uh when we were

[91:49]

building our agent that the memory was

[91:51]

instantiated as an empty list

[91:54]

if you're going to use numpy arrays one

[91:56]

thing you would do is just create an

[91:57]

array of zeros and the shape of you know

[92:00]

your images

[92:03]

as well as the total number of memories

[92:07]

i'm going to do something slightly

[92:08]

different so

[92:09]

one way to help agents learn is to

[92:11]

actually have them watch videos of

[92:13]

humans playing and in fact the

[92:16]

uh deepmind team taught

[92:19]

alpha

[92:20]

alpha zero go to play by showing a board

[92:22]

configurations and saying which which

[92:24]

player won so you it's perfectly

[92:27]

legitimate to leverage the experience of

[92:29]

humans i'm not going to play the game

[92:30]

for the agent but what i'm going to do

[92:32]

is allow the agent to play the game at

[92:34]

totally random he's just going to play a

[92:36]

set number of games to fill up its

[92:37]

memory uh using totally random actions

[92:40]

so it's a bit of a hack but i kind of i

[92:44]

don't know to me it seems legitimate but

[92:45]

some people may have frowned upon it i

[92:47]

don't really care

[92:50]

it's how i chose to solve the problem

[92:52]

and it seems to work fairly well

[92:54]

so brain dot mem size we have to

[92:57]

reset your environment

[93:00]

reset your done flag

[93:02]

and play an episode

[93:04]

so here i'll let you know the action so

[93:06]

zero is no action

[93:09]

one is fire two is move right

[93:12]

three is move left

[93:14]

four is move right fire

[93:17]

five is move left fire so that's zero

[93:19]

through five total of six actions

[93:24]

choose one at random

[93:26]

env.actionspace.sample

[93:30]

if you want to verify that these do that

[93:32]

go ahead and code up a simple loop you

[93:34]

know while loop while not done

[93:36]

take action zero and render it and see

[93:39]

what it does

[93:41]

so next you want to go ahead

[93:44]

and

[93:45]

take that action

[93:51]

and the other thing i do is

[93:53]

the

[93:56]

um and i'm on the fence about doing this

[93:59]

i haven't tested it but in my experience

[94:02]

with other environments

[94:04]

in more basic algorithms that

[94:07]

my experience is that it makes sense to

[94:09]

penalize the agent for losing

[94:11]

so

[94:12]

uh you don't want the agent will

[94:13]

naturally try to maximize its score but

[94:15]

you want it to know that losing is

[94:16]

really bad so

[94:18]

if you're done and the

[94:22]

and this may be something i change on

[94:24]

the github so if you go to the github

[94:26]

and see this isn't there it means that i

[94:27]

tested it and decided it was stupid and

[94:30]

but as of right now i think it's okay

[94:33]

i'm always open to change my mind though

[94:39]

so i want to let it know that

[94:41]

losing really really sucks

[94:43]

and i want to store that transition

[94:47]

and

[94:48]

uh here's a bit of a magical part so

[94:51]

as i said in the in the first video in

[94:53]

the convolutional neural network we want

[94:55]

to reshape it down from three channels

[94:57]

into one because the

[94:59]

the asian doesn't really care about

[95:01]

color it only cares about

[95:03]

is an enemy there or not right and it

[95:05]

can get that information from black and

[95:06]

white so i'm going to take the mean over

[95:08]

the three channels

[95:09]

to get

[95:11]

down to a single channel and i'm also

[95:14]

going to go ahead and truncate it and

[95:17]

the reason is that there isn't a whole

[95:19]

lot of information around the borders of

[95:21]

the screen that the agent needs so we

[95:22]

can get away with reducing our memory

[95:24]

requirements

[95:25]

without losing anything meaningful and

[95:27]

i'm going to go ahead and flash in some

[95:28]

images here of what that looks like

[95:31]

but what i'm going to do is take the ops

[95:36]

observation vector and i'm going to take

[95:40]

15 to

[95:42]

230 to 125

[95:45]

and the mean is performed over access to

[95:50]

and we also want to store our action and

[95:52]

reward

[95:55]

uh you guys can't see that there so we

[95:57]

store the action and reward as well as

[96:00]

let's go ahead and copy this

[96:04]

we also want to copy

[96:06]

we also want to store

[96:08]

the successor state

[96:11]

oh good grief

[96:14]

life is so hard there we go

[96:17]

and that's observation underscore which

[96:18]

is which is the successor state

[96:21]

and then

[96:23]

set your observation to observation

[96:25]

underscore

[96:30]

and then when you're done

[96:33]

just let yourself know

[96:37]

okay

[96:38]

okay and we are almost there so next

[96:41]

thing you want to do is keep track of

[96:42]

the scores you want to know how well the

[96:44]

agent is doing

[96:46]

um

[96:48]

i have this variable epsilon history oh

[96:50]

uh keep track of the

[96:53]

history of epsilons as it decreases over

[96:55]

time because we want to know the

[96:56]

relationship between the score and the

[96:59]

epsilon

[97:00]

and we'll run it for

[97:03]

50 games

[97:05]

and you'll take a batch size of 32

[97:07]

memories

[97:09]

the batch size is it an important hyper

[97:12]

parameter but what you find is that

[97:14]

using a larger batch size may get you a

[97:16]

little bit better performance it slows

[97:19]

down training tremendously so on my

[97:21]

system with an i7 7820x 32 gigs of ram

[97:25]

1080 ti batch size of 32

[97:28]

means that 50 games is gonna run in

[97:30]

about half an hour and it takes quite a

[97:31]

bit of time

[97:35]

using a larger batch size doesn't seem

[97:37]

to produce a whole lot better

[97:38]

performance

[97:39]

but it certainly slows it down by more

[97:41]

than a factor of two so

[97:43]

there's non-linear scaling there

[97:49]

and we want to know

[97:50]

that we're starting game

[97:53]

i plus one with an epsilon of something

[97:59]

dot uh say four significant figures

[98:04]

right not epsilon

[98:06]

and we want to go ahead and append

[98:09]

the

[98:11]

agents epsilon at the beginning of the

[98:13]

episode

[98:14]

reset our done flag

[98:17]

and reset our environment

[98:20]

and okay so the next thing we want to do

[98:25]

is as i said

[98:28]

why is this unhappy

[98:31]

invalid syntax

[98:34]

oh no i've offended it what have i done

[98:38]

oh forgot a comma

[98:41]

there we go so next thing we want to do

[98:43]

is construct our sequence of frames as i

[98:45]

said we're going to pass in some

[98:47]

sequence of frames to allow it to get

[98:49]

some conception of movement in the

[98:51]

system so

[98:54]

i have a rather ugly way of doing this

[98:58]

as usual

[99:00]

but the first thing i want to pass into

[99:02]

it is the

[99:03]

first

[99:06]

the first

[99:08]

observation vector from the beginning of

[99:10]

the game

[99:14]

and i have broken something again

[99:17]

what have i broken

[99:20]

frames done by some

[99:24]

oh of course

[99:27]

of course okay

[99:29]

so the score for this episode is zero

[99:32]

um

[99:39]

i want to keep track of the last action

[99:41]

so

[99:43]

this is something i'm not sure about i

[99:45]

must confess to you guys the

[99:47]

documentation on the open ai gym is

[99:49]

rather lackluster what it says is that

[99:51]

each action will be repeated for k

[99:53]

frames where k is the set two three or

[99:56]

four

[99:57]

uh so i guess it gets repeated some

[99:59]

random number of times so

[100:02]

since i don't know how many times and i

[100:03]

want to keep passing in a consistent set

[100:05]

of observation vectors of frames

[100:08]

i will

[100:09]

do something hacky so i'll keep track of

[100:11]

the last action and i will only update

[100:14]

my action every third action so i want

[100:16]

to pass in a sequence of three frames

[100:19]

and repeat the action three times i'm

[100:21]

kind of forcing the issue

[100:24]

again it seems to work i don't think

[100:26]

it's the best implementation but this is

[100:28]

you know just my quick and dirty

[100:29]

implementation

[100:33]

so

[100:34]

if we have three frames

[100:38]

go ahead and choose an action based on

[100:39]

those and reset your frame variable

[100:42]

to an empty list

[100:44]

otherwise

[100:46]

go ahead and do what you just did

[100:49]

scroll down

[100:52]

so then we want to go ahead and take

[100:55]

that action

[101:05]

keep track of our score

[101:06]

[Music]

[101:07]

and append

[101:09]

our new

[101:11]

observation

[101:14]

uh

[101:15]

i'm just gonna

[101:16]

copy that

[101:20]

yeah

[101:22]

copy that and then

[101:26]

um i am going to go ahead and tell it

[101:29]

that losing is very bad we don't like

[101:31]

losers

[101:33]

and this al dot lives thing is the

[101:36]

number of lives the agent has

[101:41]

ale is just the

[101:43]

um emulator in which the opening atar

[101:45]

openai jim's atari library is built

[101:50]

and next we have to store a transition

[101:53]

i'm going to copy that code precisely

[101:57]

because i have fat fingers and

[101:59]

apparently screw things up so

[102:02]

copy that

[102:04]

and then

[102:05]

[Music]

[102:07]

underscore

[102:09]

brain.learn

[102:11]

batch size

[102:15]

keep track of our action

[102:17]

and here you can put in a render if you

[102:19]

want to see what it's doing

[102:21]

um if not then

[102:24]

at the end of the

[102:26]

episode end of the episode

[102:29]

you want to append a score

[102:32]

which we're going to plot later

[102:36]

and i like to print the score so i can

[102:38]

kind of get an idea of how the agent's

[102:39]

doing

[102:44]

and

[102:47]

we need to make a list of the

[102:51]

x variable

[102:53]

for our plotting function

[102:55]

again for the plotting function

[102:57]

just go ahead and check out my github

[102:59]

for that

[103:00]

that's the easiest way

[103:02]

and

[103:04]

i'm going to set a

[103:06]

file name

[103:08]

[Music]

[103:10]

i'm just gonna call it test for now

[103:13]

plus string um

[103:16]

num game something like that

[103:18]

uh

[103:20]

plus

[103:21]

dot png

[103:24]

so we have a file name then we're going

[103:26]

to plot that

[103:30]

we want to plot the scores the epsilon

[103:31]

history and the file and pass in the

[103:34]

file name so that it saves it

[103:36]

and that's all she wrote for the

[103:39]

for the main loop uh

[103:41]

i've gone ahead and run that so i'm

[103:43]

going to go ahead and flash in the

[103:44]

results here

[103:47]

so as you can see the epsilon decreases

[103:49]

somewhat linearly over time not somewhat

[103:52]

completely linearly and as it does so

[103:54]

the agent's performance gradually

[103:56]

increases over time and keep in mind

[103:58]

here i am plotting the previous uh the

[104:01]

average of the previous five games

[104:04]

the reason i do that is to account for

[104:06]

significant variations in game to game

[104:08]

play right so the agent is always going

[104:10]

to choose some proportion of random

[104:11]

actions and that means it can randomly

[104:14]

choose to move left or right into the

[104:16]

enemies bullets so there's always some

[104:18]

games that's going to get cut short

[104:20]

so

[104:22]

the the general trend in the performance

[104:24]

is up until the very end when it

[104:26]

actually takes a bit of a dive and i've

[104:28]

seen this over many many different

[104:30]

iterations i suspect this has to do with

[104:32]

the way that it is navigating through

[104:34]

parameter space it'll find pretty good

[104:36]

pockets and then kind of shift

[104:38]

into a related

[104:39]

other local minima which isn't quite as

[104:41]

good

[104:43]

if you let it run long enough this will

[104:44]

eventually go back up

[104:46]

but it does have some oscillatory

[104:48]

behavior to it but you can see that it

[104:50]

increases its score quite dramatically

[104:52]

and uh in this particular set of runs i

[104:54]

saw scores in excess of 700 points which

[104:56]

is actually pretty good for an agent um

[104:59]

so let's go ahead and take a look at

[105:00]

what it looks like with the target

[105:02]

network replacement

[105:03]

so here you can see a dramatically

[105:06]

different behavior so in this case uh

[105:08]

epsilon decreases and the score actually

[105:10]

decreases over time

[105:12]

and uh

[105:15]

you know actually i don't quite know why

[105:16]

it does this so the

[105:18]

the oscillations down there are almost

[105:20]

certainly from the target network

[105:22]

replacements uh it could be a fluke but

[105:24]

i have run this several times where i

[105:26]

see this type of behavior where uh with

[105:28]

the target network replacement it

[105:29]

totally takes a nosedive i don't think i

[105:31]

screwed up my implementation please

[105:33]

leave a comment below if you saw

[105:34]

something it looks off but as far as i

[105:35]

can tell it looks it's implemented

[105:36]

correctly you just copy one state dick

[105:38]

to another no real big mystery there uh

[105:41]

but that's why i choose to leave it off

[105:43]

you get a significant variation in

[105:45]

performance um

[105:47]

more of the stories to go ahead and

[105:48]

leave the

[105:49]

target network replacement off and uh

[105:52]

that's it for this series so we have

[105:54]

made an agent to play the atari uh atari

[105:58]

game of space invaders uh you by

[106:01]

uh gradually decreasing epsilon over

[106:02]

time we get really good performance

[106:04]

uh several hundred points in fact

[106:06]

actually learns how to play the game

[106:08]

quite well i'm probably going to go

[106:09]

ahead and spin in a video of it playing

[106:11]

here so you can see how it looks

[106:17]

um if this has been helpful to you

[106:19]

please consider subscribing go ahead and

[106:21]

leave a comment below if you have one a

[106:23]

question suggestion anything uh go ahead

[106:26]

i answer and read all my comments um

[106:29]

and uh go ahead and smash that like

[106:32]

button guys so i hope to see you all in

[106:34]

the next video

[106:35]

and uh take care

[106:40]

in this video i'm going to tell you

[106:42]

everything you need to know to start

[106:43]

solving reinforcement learning problems

[106:45]

with policy gradient methods

[106:48]

i'm going to give you the algorithm and

[106:49]

the implementation details up front and

[106:52]

then we'll go into how it all works and

[106:55]

why you would want to do it let's get to

[106:57]

it

[106:59]

so here's a basic idea behind policy

[107:01]

gradient methods

[107:03]

a policy is just a probability

[107:05]

distribution the agent uses to pick

[107:07]

actions so we use a deep neural network

[107:09]

to approximate the agent's policy the

[107:12]

network takes observations of the

[107:13]

environment as input and outputs actions

[107:16]

selected according to a softmax

[107:18]

activation function

[107:20]

next generate an episode and keep track

[107:22]

of the states actions and rewards in the

[107:24]

agent's memory

[107:26]

at the end of each episode go back

[107:28]

through these states actions and rewards

[107:30]

and compete and compute the discounted

[107:33]

future returns at each time step use

[107:36]

those returns as weights and the actions

[107:38]

the agent took as labels to perform back

[107:40]

propagation and update the weights of

[107:42]

your deep neural network

[107:44]

and just repeat until you have a kick

[107:46]

ass agent simple yeah

[107:49]

so now we know the what let's unpack how

[107:51]

all this works and why it's something

[107:53]

worth doing

[107:55]

remember with reinforcement learning

[107:57]

we're trying to maximize the agent's

[107:59]

performance over time

[108:01]

let's say the agent's performance is

[108:02]

characterized by some function j and

[108:05]

it's a function of the weights theta of

[108:06]

the deep neural network

[108:08]

so our update rule for theta is that the

[108:10]

new theta equals the old theta plus some

[108:13]

learning rate times the gradient of that

[108:15]

performance metric

[108:17]

note that we want to increase

[108:18]

performance over time so this is

[108:20]

technically gradient ascent instead of

[108:23]

gradient descent

[108:25]

the gradient of this performance metric

[108:27]

is going to be proportional to some

[108:30]

overstates for the amount of time we

[108:32]

spend in any given state and a sum over

[108:35]

actions for the value of the state

[108:37]

action pairs and the gradient of the

[108:38]

policy where of course the policy is

[108:41]

just the probability of taking each

[108:42]

action given we're in some state

[108:45]

this is really an expectation value and

[108:47]

after a little manipulation we arrive at

[108:49]

the following expression

[108:54]

when you plug that into the update rule

[108:55]

for theta you get this other expression

[109:00]

there are two important features here

[109:02]

this g sub t term is the discounted

[109:04]

feature returns we referenced in the

[109:06]

opening and this gradient of the policy

[109:09]

divided by the policy is a vector that

[109:11]

tells us the direction and policy space

[109:13]

that maximizes the chance that we repeat

[109:16]

the action a sub t

[109:18]

when you multiply the two you get a

[109:19]

vector that increases the probability of

[109:21]

taking actions with high expected future

[109:24]

returns

[109:25]

this is precisely how the agent learns

[109:27]

over time and what makes policy gradient

[109:29]

methods so powerful

[109:31]

this is called the reinforce algorithm

[109:33]

by the way

[109:35]

if we think about this long enough some

[109:37]

problems start to appear

[109:39]

for one it doesn't seem very sample

[109:41]

efficient

[109:42]

at the top of each episode we reset the

[109:44]

agent's memory so it effectively

[109:46]

discards all its previous experience

[109:49]

aside from the new weights that

[109:50]

parameterize its policy it's kind of

[109:52]

starting from scratch

[109:54]

after every time it learns

[109:56]

worse yet if the agent has some big

[109:58]

probability of selecting any action in

[110:00]

any given state how can we control the

[110:03]

variation between the episodes

[110:05]

for large state spaces aren't there way

[110:07]

too many combinations to consider well

[110:10]

that's actually a non-trivial problem

[110:12]

with policy gradient methods and part of

[110:14]

the reason our agent wasn't so great at

[110:16]

space invaders

[110:18]

obviously no reinforcement learning

[110:19]

method is going to be perfect and we'll

[110:21]

get to the solution to both of these

[110:23]

problems here in a minute

[110:25]

but first let's talk about why we would

[110:27]

want to use policy gradients at all

[110:29]

given these shortcomings

[110:32]

the policy gradient method is a pretty

[110:34]

different approach to reinforcement

[110:35]

learning

[110:36]

many reinforcement learning algorithms

[110:38]

like deep q learning for instance rely

[110:41]

on estimating the value of a state or

[110:43]

state action pair

[110:44]

in other words the agent wants to know

[110:46]

how valuable each state is so that its

[110:49]

epsilon greedy policy can let it select

[110:51]

the action that leads to the most

[110:53]

valuable states

[110:54]

the agent repeats this process over and

[110:56]

over occasionally choosing random

[110:57]

actions to see if it's missing something

[111:00]

the intuition behind epsilon greedy

[111:02]

action selection is really

[111:03]

straightforward

[111:05]

figure out what the best action is and

[111:07]

take it

[111:08]

sometimes do other stuff to make sure

[111:10]

you're not wildly wrong

[111:12]

okay that makes sense but this assumes

[111:14]

that you can accurately learn the action

[111:16]

value function to begin with

[111:19]

in many cases the value or action value

[111:22]

function is incredibly complex and

[111:24]

really difficult to learn on realistic

[111:26]

time scales

[111:28]

in some cases the optimal policy itself

[111:30]

may be much simpler and therefore easier

[111:33]

to approximate

[111:35]

this means the policy gradient agent can

[111:37]

learn to beat certain environments much

[111:39]

more quickly than if it relied on an

[111:40]

algorithm like deep q learning

[111:44]

another thing that makes policy gradient

[111:46]

methods attractive is what if the

[111:48]

optimal policy is actually deterministic

[111:51]

in really simple environments with an

[111:53]

obvious deterministic policy like a grid

[111:55]

world example keeping a finite epsilon

[111:57]

means that you keep on exploring even

[111:59]

after you've found the best possible

[112:01]

solution

[112:02]

obviously this is sub-optimal

[112:05]

for more complex environments the

[112:07]

optimal policy may very well be

[112:09]

deterministic but perhaps it's not so

[112:11]

obvious and you can't guess at it

[112:13]

beforehand

[112:14]

in that case one could argue that deep q

[112:17]

learning would be great because you can

[112:18]

always decrease the exploration factor

[112:20]

epsilon over time and allow the agent to

[112:23]

settle on a purely greedy strategy

[112:26]

this is certainly true but how can we

[112:28]

know how quickly to decrease epsilon

[112:32]

the beauty of policy gradients is that

[112:34]

even though they are stochastic they can

[112:36]

approach a deterministic policy over

[112:38]

time

[112:40]

actions that are optimal will be

[112:41]

selected more frequently and this will

[112:43]

create a sort of momentum that drives

[112:45]

the agent towards that optimal

[112:46]

deterministic policy

[112:48]

this really isn't feasible in action

[112:50]

value algorithms that rely on epsilon

[112:52]

greedy or its variations

[112:55]

so what about a shortcomings as we said

[112:58]

earlier there are really big variations

[113:00]

between episodes since each time the

[113:02]

agent visits the state it can choose a

[113:04]

different action which leads to

[113:06]

radically different future returns

[113:09]

the agent also doesn't make very good

[113:11]

use of its prior experience since it

[113:13]

discards them after each time it learns

[113:16]

while they seem like show stoppers they

[113:18]

have some pretty straightforward

[113:20]

solutions

[113:22]

to deal with the variance between

[113:23]

episodes we want to scale our rewards by

[113:25]

some baseline the simplest baseline to

[113:28]

use is the average reward from the

[113:29]

episode and we can further normalize the

[113:31]

g factor by dividing by the standard

[113:34]

deviation of those rewards this helps

[113:36]

control the variance in the returns so

[113:38]

that we don't end up with wildly

[113:39]

different step sizes when we when we

[113:41]

perform our update to the weights of the

[113:44]

deep neural network

[113:46]

dealing with the sample and efficiency

[113:48]

is even easier while it's possible to

[113:50]

update the weights of the neural net

[113:52]

after each episode nothing says this has

[113:54]

to be the case we can let the agent play

[113:56]

a batch of games so it has a chance to

[113:58]

visit his state more than once before we

[114:01]

update the weights for our network this

[114:03]

introduces an additional hyper parameter

[114:06]

which is the batch size for our updates

[114:08]

but the trade-off is that we end up with

[114:09]

a much faster convergence to a good

[114:11]

policy

[114:13]

now it may seem obvious but increasing

[114:15]

the batch size is what allowed me to go

[114:17]

from no learning at all in space

[114:19]

invaders with policy gradients to

[114:21]

something that actually learns how to

[114:22]

improve its gameplay

[114:25]

so that's policy gradient learning in a

[114:27]

nutshell we're using a deep neural

[114:29]

network to approximate the agent's

[114:31]

policy and then using gradient ascent to

[114:33]

choose actions that result in larger

[114:35]

returns

[114:36]

it may be sample inefficient and have

[114:38]

issues with scaling the returns but we

[114:40]

can deal with these problems to make

[114:42]

policy gradients competitive with other

[114:44]

reinforcement learning algorithms like

[114:46]

dq learning

[114:48]

if you've made it this far check out the

[114:50]

video where i implement policy gradients

[114:52]

in tensorflow if you like the video make

[114:54]

sure to like the video subscribe

[114:57]

comment down below and i'll see you in

[115:00]

the next video

[115:02]

what's up everybody in this tutorial

[115:03]

you're going to learn how to land a

[115:04]

spaceship on the moon using policy

[115:06]

gradient methods you don't need to know

[115:08]

anything about reinforcement learning

[115:10]

you don't need to know anything about

[115:11]

policy gradient methods you just have to

[115:13]

follow along let's get started

[115:16]

so before we begin let's take a look at

[115:19]

the basic idea of what we want to

[115:20]

accomplish

[115:21]

policy gradient methods work by

[115:23]

approximating the policy of the agent

[115:26]

the policy is just the probability

[115:27]

distribution that the agent uses to

[115:29]

select actions so we're going to use a

[115:32]

deep neural network to approximate that

[115:34]

probability distribution and we're going

[115:36]

to be feeding in the input observations

[115:38]

from the environment and getting out a

[115:40]

probability distribution as an output

[115:43]

the agent learns by replaying its memory

[115:45]

of the rewards it received during the

[115:47]

episode and calculating the discounted

[115:49]

future rewards that followed each

[115:51]

particular time step those discounted

[115:53]

feature rewards act as weights in the

[115:56]

update of our deep neural network so

[115:58]

that the agent assigns a higher

[116:00]

probability to actions whose

[116:03]

feature rewards are higher

[116:06]

so we'll start with our imports

[116:09]

and we're going to want os to handle

[116:11]

file operations

[116:14]

numpy to handle numpy type operations

[116:20]

and of course tensorflow to develop our

[116:22]

agent we're going to stick everything in

[116:24]

one class

[116:34]

whose initialize function takes the

[116:36]

learning rate

[116:37]

the discount factor gamma

[116:39]

the

[116:40]

number of actions

[116:42]

for the lunar lander environment that's

[116:44]

just for

[116:45]

the

[116:49]

size of the first

[116:52]

hidden layer of the neural network we'll

[116:54]

default that to 64.

[116:56]

the

[116:57]

size of the second hidden layer of the

[116:59]

deep neural network will also default

[117:01]

that to 64.

[117:03]

we also need the input dimms

[117:07]

and in this case that is 8 so the

[117:09]

observation isn't a pixel image it is

[117:12]

just a vector that represents the state

[117:14]

of the environment

[117:16]

we also want a checkpoint directory

[117:19]

and this will be useful for saving our

[117:21]

model later

[117:38]

so this action space will be what we use

[117:40]

to

[117:41]

select actions later on

[117:43]

and we're going to need a number of

[117:45]

other

[117:46]

administrative type stuff so for

[117:48]

instance the

[117:49]

state memory

[117:53]

is just what the agent will use to keep

[117:55]

track of the states it visited

[117:58]

likewise for the action memory we want

[118:01]

to keep track of the actions the agent

[118:02]

took

[118:04]

and the rewards it received along the

[118:06]

way

[118:08]

we also need the layer one size

[118:12]

and the layer two size

[118:17]

what else we okay so now we can move on

[118:19]

to the administrative stuff with

[118:21]

tensorflow so

[118:23]

tensorflow handles everything in what

[118:25]

are called sessions

[118:26]

so we have to define one of those

[118:29]

we're gonna need a function to build the

[118:30]

network and when we return from the

[118:33]

network we're going to want to

[118:34]

initialize all of the variables so this

[118:36]

build network function is only called

[118:37]

once it will load up all of the

[118:39]

variables and operations under the

[118:41]

tensorflow graph and then we have to

[118:43]

initialize those

[118:45]

variables with some initial values which

[118:48]

will be done at random

[118:58]

we also need a way of saving the model

[119:01]

because your pc may not be fast enough

[119:03]

to run this in a you know short enough

[119:06]

amount of time so you can do this in

[119:07]

chunks by saving and then reloading it

[119:10]

as you have time

[119:25]

we also need a

[119:28]

file to save the checkpoints in

[119:32]

so our next order of business

[119:34]

is to actually construct this network

[119:40]

so we don't need any inputs for that

[119:42]

but we do need a set of placeholders and

[119:44]

the placeholders serve as placeholders

[119:46]

for our inputs it just tells the

[119:48]

tensorflow graph that hey we're going to

[119:50]

be passing in some variables we don't

[119:52]

know what they are yet we may not

[119:53]

necessarily even know their shape or

[119:54]

size

[119:55]

but we know what type they are and we

[119:56]

want to give them names so if something

[119:58]

goes wrong we can debug later

[120:11]

so this input will just be the eight

[120:14]

element vector that represents the

[120:16]

agent's observation of the environment

[120:20]

and if you're not really familiar with

[120:22]

tensorflow

[120:23]

this idiom of saying shape equals a list

[120:26]

whose first element is none

[120:28]

tells tensorflow that we do not know the

[120:31]

batch size of the data we're going to be

[120:33]

loading

[120:34]

so the inputs could be

[120:36]

10 states it could be 100 it could be a

[120:37]

thousand it could be any number of

[120:39]

states and so that none just tells

[120:41]

tensorflow hey we don't know what shape

[120:42]

it's going to be so

[120:45]

you know just take whatever

[120:53]

and this

[120:55]

label is going to be the actions the

[120:57]

agent took during the course of the

[120:58]

episode this will be used in calculating

[121:01]

our loss function

[121:03]

similarly

[121:07]

we have something called g

[121:09]

and g is just the generic name

[121:12]

for the agents discounted future rewards

[121:16]

following each time step

[121:18]

this is what we will use to

[121:21]

bias the agent's loss function towards

[121:24]

increasing the probability of actions

[121:25]

who

[121:27]

generate the most returns over time

[121:37]

so now we're going to construct our

[121:38]

network

[121:44]

so

[121:45]

the first layer will just be the input

[121:47]

and the number of it'll take of course

[121:49]

number of input and input dimms on

[121:53]

input and then output

[121:55]

the

[121:57]

player one size

[121:59]

and the

[122:02]

activation is just going to be a value

[122:03]

function

[122:06]

and then we have to worry about

[122:08]

initializing this so when we call the

[122:10]

tf.global variables initializer it's

[122:12]

going to initialize all of the layers

[122:13]

and variables with some values we can

[122:15]

dictate how it does that and we can

[122:17]

think very carefully about it so

[122:19]

if you've dealt with deep neural

[122:21]

networks in some cases you can get

[122:23]

vanishing or exploding gradients that

[122:24]

cause the

[122:25]

values the network predicts to you know

[122:28]

go to you know either really large or

[122:30]

really small values it produces junk

[122:31]

essentially

[122:32]

there is a

[122:34]

function that will initialize the values

[122:37]

of all the layers such that

[122:39]

they are relatively comparable and we

[122:41]

have

[122:42]

a minimal risk of that happening

[122:50]

and that's called a xavier initializer

[122:55]

and i'm going to want to copy that

[122:56]

because we're going to use that more

[122:58]

than once

[123:02]

so of course the second layer

[123:04]

just takes the first layer's input

[123:08]

has l2 size as the number of units

[123:12]

with a

[123:14]

value activation

[123:18]

and of course the same initializer

[123:22]

and l3 will be the output of our network

[123:32]

however

[123:33]

we don't want to activate it just yet so

[123:38]

this quantity is related to the

[123:41]

probability sorry the policy of the

[123:42]

agent but the policy must have the

[123:45]

uh property that the sum of the

[123:48]

probabilities of taking an action you

[123:50]

know the sum of the probabilities for

[123:52]

all the actions must equal one and it's

[123:55]

the softmax function that has that

[123:56]

property and we're going to separate it

[123:58]

out so that we can just

[124:00]

so that it is a little bit more clean in

[124:02]

terms of the

[124:04]

the code a little bit more readable for

[124:05]

us

[124:06]

but the self.actions variable is what

[124:08]

will actually

[124:10]

calculate the probabilities of selecting

[124:12]

some action and that is just the softmax

[124:16]

of the

[124:18]

l3

[124:19]

and the name of that is probabilities

[124:28]

finally we need to well not finally but

[124:30]

next we need to calculate the

[124:33]

the loss function

[124:34]

so

[124:36]

we'll stick that in a separate scope

[124:44]

and uh what we need is the negative log

[124:47]

probability so

[124:50]

excuse me the

[124:52]

calculation involves the natural log of

[124:54]

the policy and you want to take the

[124:56]

gradient of the natural log of something

[124:57]

so we need a function that matches that

[124:59]

property

[125:01]

so we'll call it neg log

[125:04]

probability

[125:06]

and that's the sparse

[125:09]

soft max cross entropy

[125:12]

with logits

[125:15]

try saying that five times fast

[125:18]

so log x is just l three

[125:21]

and this is important because this is

[125:23]

part of the reason we separated out l

[125:25]

three in actions because when you're

[125:26]

passing in

[125:27]

the logits you don't want it to already

[125:29]

be activated because the negative the

[125:31]

sparse soft max cross entropy will

[125:33]

handle the

[125:35]

softmax activation function

[125:38]

and the labels will just be the label

[125:41]

that we pass in

[125:43]

from the placeholder and then of course

[125:45]

be the actions the agent took

[125:48]

and so the loss is then that quantity

[125:50]

neglog probability

[125:52]

multiplied by the returns g

[125:56]

next we need the training operation

[126:05]

and that of course is just our gradient

[126:08]

descent type algorithm in this case

[126:09]

we'll use the

[126:11]

atom optimizer

[126:14]

the learning rate of whatever we dictate

[126:16]

in the constructor

[126:18]

and we want to minimize that loss

[126:23]

so that is the sum and hole of the deep

[126:26]

neural network we need to we need to

[126:27]

code

[126:29]

the next question we have is how can we

[126:31]

select actions for the agent

[126:34]

so

[126:35]

the

[126:36]

agent is attempting to model its own

[126:38]

probability distribution for selecting

[126:40]

actions so that means what we want to do

[126:42]

is take a state as input pass it through

[126:44]

the network and get out that

[126:46]

probability distribution at the end

[126:48]

given by the variable self.actions

[126:50]

and then we can use numpy to select a

[126:52]

random action according to that

[126:54]

probability distribution

[127:03]

and we're just going to go ahead and

[127:05]

reshape this

[127:09]

bill it is

[127:16]

so when you run an operation through the

[127:19]

tensorflow graph you need to specify a

[127:22]

feed dictionary which gives the graph

[127:24]

all of the input placeholder variables

[127:27]

it's expecting so in this case it wants

[127:28]

self.input

[127:30]

and that takes state

[127:32]

as input

[127:33]

and it's going to return a tuple so

[127:35]

we're going to take the 0th element as

[127:39]

so we can get the correct

[127:42]

value that we want

[127:43]

and then we can select an action

[127:45]

according to

[127:46]

numpy random choice

[127:48]

from the action space using the

[127:50]

probabilities

[127:53]

as our distribution

[127:55]

and we just returned that action

[127:58]

the next problem we have to deal with is

[128:00]

storing an action

[128:04]

sorry the transitions and of course

[128:06]

we'll store

[128:07]

the state action and reward

[128:10]

and this will be useful when we learn

[128:16]

and since we're using lists here we're

[128:18]

just going to append the elements to the

[128:20]

end of the list

[128:34]

next we come to the meat of the problem

[128:36]

the learning function

[128:38]

and this doesn't require any input

[128:40]

so the basic idea here is that we are

[128:42]

going to convert these lists into numpy

[128:45]

arrays so we can more easily manipulate

[128:46]

them

[128:47]

and then we're going to

[128:51]

iterate through the agent's memory of

[128:53]

the rewards it received

[128:54]

and calculate the discounted sum

[128:58]

of rewards that followed each time step

[129:00]

so we're going to need two for loops and

[129:02]

a variable to keep track of the sum as

[129:04]

well as something to keep track of our

[129:05]

discounting

[129:07]

so let's deal with the memories first

[129:34]

that won't work will it

[129:36]

there we go

[129:40]

so now

[129:44]

we'll instantiate our g factor

[129:48]

and get in

[129:49]

shape of reward memory

[129:52]

we will iterate over the

[129:54]

length of that memory

[129:56]

which is just length of our episode

[129:59]

and so for each time step

[130:01]

we want to calculate the sum

[130:05]

of the rewards that follow that time

[130:06]

step

[130:14]

is that correct yes

[130:16]

next we take the sum

[130:22]

and discount it

[130:24]

then of course the discount

[130:27]

is just the

[130:30]

gamma to the k

[130:32]

where k is our time step

[130:37]

so then of course the

[130:39]

rewards following the teeth the teeth

[130:42]

teeth

[130:43]

the t time step is just g sum

[130:46]

so that's the sum that's the weighted

[130:48]

discounted rewards

[130:51]

the next thing we have to think about is

[130:53]

these rewards can vary a lot between

[130:54]

episodes so to promote stability in our

[130:57]

algorithm we want to scale these results

[130:59]

by some number

[131:00]

it turns out that a reasonable number to

[131:02]

use is the mean so we're going to

[131:04]

subtract off the mean of the rewards the

[131:05]

agent received during the episode and

[131:07]

then divide by the standard deviation

[131:09]

this will give us some nice

[131:11]

scaled and normalized numbers such that

[131:13]

the algorithm doesn't produce wacky

[131:15]

results

[131:26]

and since we're dividing by the standard

[131:27]

deviation we have to account for the

[131:28]

possibility that the standard deviation

[131:30]

could be zero

[131:32]

hence the conditional statement

[131:38]

next we have to run our training

[131:41]

operation

[131:42]

so the underscore tells us we don't

[131:44]

really care about what it returns

[131:48]

we have to run the training operation

[131:51]

the feed dictionary

[131:54]

that'll take an input which is just our

[131:55]

state memory

[131:59]

it will take the labels

[132:02]

and that is just the action memory

[132:06]

and it will take the

[132:09]

g factor which is just the g we just

[132:11]

calculated

[132:13]

now at the end of the episode

[132:15]

once we finish learning we want to reset

[132:17]

the agent's memory so that rewards from

[132:18]

one episode don't spill over into

[132:21]

another

[132:36]

so there are two more functions we need

[132:38]

these are administrative we need

[132:40]

a way to load the checkpoint

[132:44]

and we'll go ahead and print out loading

[132:46]

checkpoint

[132:48]

just so we know it's doing something

[132:51]

and then we have the saver object and we

[132:53]

want to restore

[132:56]

a session

[132:57]

from our checkpoint

[133:00]

file

[133:02]

next we want to save a checkpoint

[133:10]

we're not going to print here i take it

[133:11]

back reason is that we're going to be

[133:13]

saving a lot and i don't want to print

[133:14]

out a bunch of junk statements so

[133:24]

and what these are doing is just either

[133:26]

taking the the current graph as it is

[133:28]

right now and sticking it into a file or

[133:31]

conversely taking the graph out of the

[133:33]

file loading it into the graph for the

[133:34]

current session

[133:36]

so that is that

[133:38]

next we can move on to the main program

[133:40]

to actually test our

[133:42]

lander

[133:44]

so we'll need jim

[133:46]

and i didn't i don't know if i made it

[133:47]

clear at the beginning but you'll also

[133:49]

need the box 2d dash pi environment so

[133:53]

go ahead and do pip install box 2d dash

[133:55]

pi if you don't already have that

[134:03]

so we'll need to import our policy

[134:04]

gradient agent

[134:09]

i have this plot learning function i

[134:11]

always use you can find it on my github

[134:13]

along with this code of course

[134:15]

i don't elaborate on it but basically

[134:16]

what it does is it takes a sequence of

[134:19]

rewards

[134:20]

keeps track of it performs a running

[134:22]

average of say the last 20 25 whatever

[134:24]

amount you want and spits that out to a

[134:27]

file

[134:30]

we also have

[134:32]

a way of saving the renderings of the

[134:33]

environment so it runs much faster if

[134:35]

you don't actually render to the screen

[134:37]

while it's training but you can save

[134:39]

those renderings to files in mp4 files

[134:42]

so you can go back and watch them later

[134:43]

it's how i produce the

[134:45]

episodes you saw at the beginning of

[134:47]

this video

[134:56]

so first thing i'm going to do is

[134:57]

instantiate our agent

[135:01]

and we'll use a learning rate of zero

[135:04]

three zeros and a five

[135:07]

and i believe uh oh we'll need a gamma

[135:10]

we use something like 0.99

[135:13]

and all

[135:14]

and then all the other parameters we'll

[135:15]

just leave at the defaults

[135:20]

next we need to make our environment

[135:27]

and that's lunarlander v2

[135:30]

a way to keep track of the scores the

[135:32]

agent received

[135:36]

our initial score

[135:37]

and

[135:38]

number of episodes

[135:40]

so i achieved uh pretty good results

[135:43]

after 2500 episodes so we can

[135:45]

start with that

[135:48]

so the first thing we want to do is

[135:49]

iterate

[135:50]

over

[135:51]

our episodes

[135:54]

oh let me do this for you so

[135:56]

before we do that um i'll comment this

[135:58]

out but if you want to save the output

[136:00]

you do this env equals

[136:02]

wrappers dot monitor

[136:06]

pass in the environment wherever you

[136:08]

want to save it lunar lander

[136:12]

and then you want to use a lambda

[136:13]

function

[136:15]

to tell it

[136:16]

to render on

[136:19]

every episode

[136:23]

and this force equals true i believe

[136:25]

that just

[136:28]

tells it to overwrite if there's already

[136:30]

data in the directory

[136:33]

so at the top of every episode just

[136:35]

print out what episode number you're on

[136:38]

and the

[136:39]

current score

[136:43]

you set your done flag

[136:47]

and for subsequent episodes you'll want

[136:48]

to reset the score

[136:53]

reset your environment

[136:54]

and play an episode

[136:58]

first thing you want to do is select an

[137:00]

action

[137:03]

and that takes the observation as input

[137:07]

so we need to get the new observation

[137:09]

reward done flag and info by stepping

[137:12]

through the environment

[137:16]

once that's done you want to store the

[137:18]

transition

[137:26]

set the old observation to be the new

[137:29]

one so that you select an action based

[137:31]

on the new estate

[137:33]

and keep track of the reward you

[137:36]

received

[137:38]

at the end of every episode we want to

[137:40]

append

[137:43]

the score to the score history

[137:46]

and perform our learning operation

[137:49]

you also want to

[137:50]

save a checkpoint

[137:54]

after every operation ever after every

[137:56]

learning operation

[137:58]

and then when you're done dictate some

[138:00]

file name

[138:03]

dot png

[138:05]

and call my super secret

[138:07]

plot learning function

[138:09]

that just takes the score history

[138:12]

file name

[138:14]

and a window that tells it over how many

[138:16]

games you want to take the running

[138:18]

average

[138:21]

so now let's go to our terminal and see

[138:23]

how many mistakes i made one second

[138:27]

all right

[138:28]

so here we are let's go ahead and

[138:31]

give it a try

[138:37]

so i made some kind of error in the

[138:39]

policy gradient agent let's swing back

[138:41]

to that file and see where it is

[138:44]

one second

[138:45]

so here's the model

[138:47]

it does not have

[138:49]

input dimms that's because i forgot to

[138:52]

keep track of it

[138:57]

save

[138:59]

go back to our terminal and see how it

[139:02]

does

[139:08]

and i apparently called something i

[139:09]

should not have

[139:23]

this is line 27

[139:29]

it says

[139:31]

self.label placeholder got an unexpected

[139:34]

keyword argument named label

[139:36]

ah that's because

[139:39]

it is called name

[139:42]

that's what happens when i try to type

[139:44]

and talk at the same time

[139:47]

let me make sure i didn't call l1 size

[139:49]

l2 size something different no i did not

[139:53]

all right i will run that again

[139:56]

so now it's unhappy about the

[139:58]

choice of oh of course

[140:01]

so it's lunar

[140:02]

there's no dash in there

[140:04]

get rid of that

[140:06]

typos galore tonight

[140:13]

oh really

[140:15]

oh really

[140:22]

ah it's store transitions

[140:25]

yes

[140:28]

so it's actually store transitions so

[140:30]

let's call it that

[140:34]

and there we go

[140:40]

perfect

[140:41]

so now it's actually learning i'm not

[140:43]

going to sit here and wait for this to

[140:44]

do 2500 games because i've already run

[140:46]

this once before that's how i got the

[140:48]

kodi saw at the beginning

[140:50]

so

[140:51]

i'm going to go ahead and show you the

[140:53]

plot that it produces now so you can see

[140:55]

how it actually learns so

[140:57]

by the end it gets up to about an

[140:58]

average reward of around 200 and above

[141:01]

points that's considered solved if you

[141:02]

check the documentation on the openai

[141:04]

gym so congratulations we have solved

[141:06]

the lunar lander environment with the

[141:08]

policy gradient algorithm relatively

[141:10]

simple just a a deep neural network

[141:13]

that calculates the probability of the

[141:15]

agent picking an action

[141:17]

so i hope this has been helpful go ahead

[141:19]

and leave a comment down below

[141:21]

feel free to take this code from my

[141:22]

github fork it make it better do

[141:25]

whatever you want with it i look forward

[141:26]

to seeing you all in the next video

[141:32]

welcome back everybody to a new

[141:33]

reinforcement learning tutorial in

[141:35]

today's episode we're going to teach an

[141:36]

agent to play space invaders using the

[141:38]

policy gradient method let's get to it

[141:41]

for imports we start with the usual

[141:42]

suspects numpy and tensorflow

[141:45]

we start by initializing our class for

[141:47]

the policy gradient agent

[141:49]

we take the learning rate discount

[141:51]

factor number of actions number of

[141:54]

layers for the fully connected layer

[141:57]

the input shape channels

[141:59]

a directory for our checkpoints very

[142:01]

important as well as a parameter to

[142:03]

dictate which gpu we want tensorflow to

[142:05]

use if you only have one gpu or using

[142:08]

the cpu you don't need that parameter

[142:11]

save the relevant parameters and compute

[142:12]

the action space which is just a set of

[142:14]

integers

[142:15]

we want to subtract out the input

[142:17]

heights

[142:18]

and width from the input shapes and keep

[142:20]

track of the number of channels for use

[142:22]

later

[142:23]

our agent's memory will be comprised of

[142:25]

three lifts that keep track of the state

[142:27]

action and rewards

[142:32]

we want a configuration which just tells

[142:34]

tensorflow which gpu we want to use

[142:37]

as well as our session graph that uses

[142:39]

that config we call the build network

[142:41]

function

[142:42]

and then use the tf global variables

[142:44]

initializer

[142:46]

we need to keep track of the saver and a

[142:48]

checkpoint file for saving and loading

[142:50]

the model later

[142:52]

now if you don't know anything about

[142:53]

policy gradient methods don't worry

[142:54]

we're going to cover everything you need

[142:55]

to know as we go along the first thing

[142:58]

we're going to need is a convolutional

[142:59]

neural network to handle image

[143:00]

pre-processing that'll be connected to a

[143:02]

fully connected layer that allows the

[143:04]

agent to estimate what action it wants

[143:06]

to take in contrast to things like deep

[143:09]

q learning policy gradient methods don't

[143:11]

actually try to learn the action value

[143:12]

or value functions rather policy

[143:15]

gradients try to approximate the actual

[143:17]

policy of the agent

[143:18]

let's take a look at that

[143:20]

for our build network function we're

[143:22]

going to construct a convolutional

[143:24]

neural network with a few parameters

[143:26]

an input placeholder that has shape

[143:29]

batch size by input height and width as

[143:33]

well as the number of channels

[143:36]

we will also need an input for the

[143:38]

labels which just correspond to the

[143:40]

actions the agent takes that is shape

[143:42]

batch size

[143:43]

and a factor g which is just the

[143:45]

discounted future rewards following a

[143:47]

given time step that is shape batch size

[143:50]

our convolutional neural network is

[143:52]

going to be pretty straightforward if

[143:54]

you've seen any of my videos you can

[143:55]

kind of know what to expect the first

[143:57]

layer has 32 filters a kernel size of

[143:59]

eight by eight and a stride four

[144:02]

and we're going to want to use an

[144:03]

initializer for this i found that the

[144:05]

xavier initializer works quite well the

[144:07]

purpose of it is to keep the

[144:10]

to initialize all the parameters in such

[144:11]

a way that the

[144:13]

uh they the network doesn't have one

[144:16]

layer with parameters significantly

[144:17]

larger than any other

[144:19]

we want to do batch normalization i

[144:21]

mistyped the epsilon there should be one

[144:23]

by ten to the minus five

[144:24]

and you want to of course use a value

[144:26]

activation on the first convolutional

[144:28]

layer

[144:30]

and that commvault that activated output

[144:32]

serves as the input to the next layer

[144:34]

with 64 filters

[144:35]

kernel size of 4x4 and a stride of 2 and

[144:39]

again we'll use the

[144:41]

xavier initializer

[144:50]

of course we also want to do batch

[144:52]

normalization on this layer and at this

[144:54]

point i think i actually get the correct

[144:56]

epsilon for the

[144:57]

batch norm

[145:00]

and of course we want to use a value

[145:02]

activation on that batch normed output

[145:05]

as well

[145:06]

our third convolutional layer is more of

[145:08]

the same 2d convolution

[145:10]

with 128 filters

[145:12]

it will have a kernel size of 2x2 a

[145:14]

stride of 1

[145:16]

and we'll also use the same

[145:17]

initialization

[145:23]

again batch normalization

[145:25]

with an epsilon of 1 by 10 to the minus

[145:27]

5.

[145:30]

activate with a value

[145:32]

next we have to take into account our

[145:34]

fully connected layers so the first

[145:36]

thing we need to do is flatten the

[145:38]

output of the convolutions

[145:40]

because they come out as matrices we

[145:41]

need a list

[145:43]

go ahead and make the first fully

[145:45]

connected layer using fc1 as the number

[145:48]

of units value activation

[145:50]

and the second dense layer is going to

[145:52]

have units equal to the number of

[145:54]

actions for the agent which in this case

[145:55]

is just six

[146:03]

notice that we don't activate that but

[146:05]

we have a separate variable for the

[146:06]

actions which is the activated output of

[146:08]

the network and we're going to use a

[146:09]

soft max so that way we get

[146:11]

probabilities that add up to one

[146:13]

we need to calculate the negative log

[146:14]

probability with a sparse softmax

[146:17]

cross-entropy function with logits using

[146:19]

dense two as our logits and

[146:22]

labels

[146:23]

as of the actions as our labels the loss

[146:25]

is just that quantity multiplied by the

[146:28]

expected future rewards

[146:30]

and of course we want to reduce that

[146:32]

quantity

[146:37]

now for the training operation we're

[146:39]

going to use the rms prop optimizer with

[146:41]

a set of parameters i found these to

[146:42]

work quite well

[146:44]

this algorithm is pretty finicky so you

[146:46]

may have to play around the next thing

[146:48]

we have to do is

[146:50]

code up the action selection algorithm

[146:52]

for the agent in policy gradient methods

[146:54]

we're trying to actually approximate the

[146:56]

policy which means we're trying to

[146:57]

approximate the distribution by which

[146:59]

the agent chooses actions given it's in

[147:02]

some state s so what we need is a way of

[147:04]

computing those probabilities and then

[147:05]

sampling them

[147:06]

sampling the actions according to those

[147:08]

probabilities

[147:10]

we choose an action

[147:12]

by taking in an observation reshaping it

[147:14]

of course this will be a sequence of

[147:16]

frames

[147:17]

uh for high

[147:20]

and you want to calculate the

[147:21]

probabilities associated for

[147:24]

each action given that observation and

[147:27]

then you want to sample that probability

[147:29]

distribution

[147:30]

using the numpy random choice function

[147:39]

next up we have to take care of the

[147:40]

agent's memory so we're going to store

[147:42]

the observation action and reward in the

[147:44]

agent's list using a simple append

[147:46]

function

[147:54]

so one big problem we're going to have

[147:55]

to solve is the fact that policy

[147:56]

gradient methods are incredibly simple

[147:58]

and efficient these monte carlo methods

[148:00]

meaning that at the end of every episode

[148:01]

the agent is learning so it throws away

[148:04]

all of the

[148:05]

experience that required in prior

[148:06]

episodes so how do we deal with that

[148:08]

well one way to deal with that is to

[148:10]

actually queue up a batch of episodes

[148:12]

and learn based on that batch of

[148:14]

experiences

[148:15]

the trouble here is that when we take

[148:18]

the rewards that follow any given time

[148:20]

step we don't want to account for

[148:22]

rewards following the current episode so

[148:25]

we don't want rewards from one episode

[148:27]

spilling over into another so we have to

[148:29]

take care of that here

[148:30]

next up we handle the learning for the

[148:32]

agent we want to

[148:33]

we want to convert the state action and

[148:36]

reward memories into arrays so that we

[148:39]

can feed them into the numpad the excuse

[148:42]

me tensorflow learning function

[148:44]

into the sorry the tensorflow graph

[148:48]

we have to start by reshaping the state

[148:49]

memory into something feasible and then

[148:52]

we can calculate the expected feature

[148:54]

rewards starting from any given state so

[148:56]

what we're going to do is iterate over

[148:58]

the entire memory

[148:59]

and

[149:02]

take into account the rewards the agent

[149:04]

receives for all subsequent time steps

[149:07]

we also need to make sure that we're not

[149:08]

going to take into account rewards from

[149:09]

the next episode

[149:17]

next up we have the scale the expected

[149:19]

feature rewards this is to reduce

[149:22]

the variance in the problem so let's

[149:24]

make sure we don't have really really

[149:26]

large rewards so everything is just kind

[149:27]

of scaled

[149:29]

next up we call the training operation

[149:31]

with an appropriate feed dict of the

[149:32]

state memory action memory as labels and

[149:36]

the g for our g variable

[149:42]

finally since we're done we're going to

[149:43]

clear out the agent's memories

[149:50]

finally we just have some bookkeeping

[149:51]

functions to load and save checkpoints

[149:54]

you just call the saver restore function

[149:57]

that loads the checkpoint file into the

[150:00]

session

[150:01]

and the save checkpoint just dumps the

[150:03]

current session into the checkpoint file

[150:09]

another problem we have to solve is that

[150:11]

the agent doesn't get a sense of motion

[150:13]

from only a single image right if i show

[150:16]

you a single image you don't know if the

[150:17]

aliens are moving left or right or

[150:19]

really you don't know which direction

[150:20]

you're moving so we have to pass in a

[150:22]

sequence of frames to get a sense of

[150:24]

motion for our agent this is complicated

[150:26]

by the fact that the open ai gym atari

[150:28]

library in particular returns a set of

[150:31]

frames that are repeated so if you

[150:32]

actually cycle through the observations

[150:34]

over time you'll see that the frames

[150:36]

change or sorry don't change

[150:38]

uh based on an interval of one two or

[150:40]

three so we have to capture enough

[150:42]

frames to account for that fact as well

[150:44]

as to get a overall sense of movement so

[150:47]

that means four is going to be our magic

[150:49]

number for so for stacking frames

[150:52]

next we move into the main program we

[150:54]

import gym numpy

[150:56]

our model

[150:58]

as well as the

[151:00]

plot learning function which is a simple

[151:01]

utility you can find on my github as

[151:04]

well as the wrappers to record the

[151:06]

agent's gameplay if you so choose we

[151:08]

need to pre-process the observation by

[151:10]

truncating it and taking the average

[151:13]

next up we stack the frames so at the

[151:16]

beginning of the episode stack frames

[151:18]

will be none so you want to initialize

[151:20]

an empty array of zeros

[151:22]

and iterate over that array and set each

[151:25]

of those rows to be the current

[151:28]

observation

[151:30]

otherwise what you want to do is you

[151:31]

want to pop off the bottom observation

[151:34]

shift everything down and put the fourth

[151:36]

spot or the last spot to be the current

[151:39]

observation

[151:42]

down in the main function we have a

[151:44]

checkpoint flag if you want to load a

[151:46]

checkpoint

[151:47]

we want to initialize our agent with

[151:49]

this set of hyper parameters i found

[151:50]

these to work reasonably well you can

[151:53]

play around with them but it is

[151:54]

incredibly finicky so

[151:56]

your mileage may vary we need a file

[151:58]

name to save our plots

[152:01]

we'll also want to see if we want to

[152:03]

load a checkpoint

[152:06]

next we initialize our environment space

[152:09]

invaders of course

[152:11]

keep track of the score history score

[152:13]

number of episodes and our stack size of

[152:15]

four

[152:16]

one iterate over the number of episodes

[152:18]

resetting the done flag at the top of

[152:20]

each episode

[152:22]

we also want to keep track of the

[152:23]

running average score from the previous

[152:25]

20 games just so we got an idea if it's

[152:27]

actually learning

[152:29]

every 20 games we're gonna print out the

[152:32]

uh episode score and average score

[152:36]

otherwise every other every other

[152:38]

episode we're just going to print out

[152:40]

the episode number and the score

[152:44]

reset the environment and of course you

[152:46]

have to pre-process that observation

[152:48]

and then go ahead and set your stacked

[152:50]

frames to none because we're the top of

[152:51]

the episode and then call the stack

[152:54]

frames function so that we get four of

[152:56]

the initial observation

[152:59]

set the score to zero

[153:01]

and start iterating over the episode so

[153:03]

his first step is to choose an action

[153:05]

based on that set of stacked frames

[153:07]

go ahead and take that action and get

[153:09]

your new state action and reward

[153:12]

go ahead and pre-process that

[153:14]

observation

[153:15]

so that way you can stack it on the

[153:18]

stack of frames

[153:20]

next up you have to take care of the

[153:22]

agent's memory by storing that

[153:23]

transition

[153:26]

and finally you can increment your score

[153:28]

save the score at the end of the episode

[153:30]

and every 10 games are going to handle

[153:31]

learning and saving a checkpoint and

[153:34]

when you're all done go ahead and plot

[153:35]

the learning

[153:40]

now the agent is done we can take a look

[153:42]

at the actual plot it produces over time

[153:44]

this is how you know an agent is

[153:46]

actually learning what you'll see is

[153:47]

that there is some increase in the

[153:49]

average reward over time you'll see

[153:51]

oscillations up and down and that's

[153:52]

perfectly normal but what you want is an

[153:54]

overall upward trend now for this

[153:56]

particular set of algorithms it is

[153:58]

notoriously finicky with respect to

[153:59]

learning rates i didn't spend a huge

[154:01]

amount of time tuning them or playing

[154:03]

with them i just wanted to get something

[154:04]

good enough to show you guys how it

[154:06]

works and turn it over to your capable

[154:07]

hands for fine tuning but what you do

[154:10]

see is a definite increase over time as

[154:13]

the agent's average reward improves by

[154:14]

about 100 points or so that isn't going

[154:16]

to win any awards but it is definitely a

[154:20]

clear and unequivocal sign of learning

[154:23]

so there you have it that was policy

[154:24]

gradients in the space invaders

[154:26]

environment from the open ai gym i hope

[154:28]

you learned something make sure to check

[154:30]

out this code on my github you can fork

[154:32]

it you can copy it you can do whatever

[154:33]

you want with it

[154:35]

make sure to subscribe leave a comment

[154:36]

down below if you found this helpful i

[154:38]

look forward to seeing you all in the

[154:39]

next video

[154:42]

welcome back everybody to neuralnet.ai i

[154:44]

am your host phil tabor

[154:46]

previously a subscriber asked me hey

[154:48]

phil how do i create my own

[154:50]

reinforcement learning environment

[154:53]

i said well that's a great question i

[154:54]

don't have time to answer it in the

[154:55]

comments but i can make a video so here

[154:58]

we are

[154:59]

what we're going to do in the next two

[155:00]

videos is create our own open ai gym

[155:02]

compliant reinforcement learning

[155:05]

environment the grid world it's going to

[155:07]

be text based and if you're not familiar

[155:09]

with it the grid world is aptly named a

[155:11]

grid of size and by n where the agent

[155:13]

starts out in say the top left and

[155:15]

that's to navigate its way all the way

[155:17]

to the bottom right

[155:19]

the twist on this is going to be that

[155:21]

there will be two magic squares that

[155:23]

cause the agent to teleport across the

[155:24]

board the purpose of doing this is to

[155:27]

create a shortcut to see if the agent

[155:28]

can actually learn the shortcut kind of

[155:30]

interesting

[155:32]

the agent receives a reward of -1 with

[155:34]

each step except for the terminal step

[155:35]

or receives a reward of zero

[155:38]

therefore the agent will attempt to

[155:39]

maximize its reward by minimizing the

[155:41]

number of steps it takes to get off the

[155:43]

grid world

[155:46]

what other things two other concepts we

[155:48]

need are the concept of the state space

[155:51]

which is the set of all states minus the

[155:54]

terminal state and the state space plus

[155:57]

which is the set of all states including

[155:59]

the terminal state

[156:01]

this gives us a bit of a handy way to

[156:04]

find out the terminal state

[156:05]

as well as to find out if we're

[156:07]

attempting to make illegal moves

[156:09]

it also follows the nomenclature and

[156:11]

terminology from the sutton bardo book

[156:13]

reinforcement learning

[156:14]

which is an awesome resource you should

[156:16]

definitely check out if you have not

[156:17]

already

[156:19]

so in part one we're going to handle the

[156:20]

environment and in part two we're going

[156:22]

to get to the main loop and the agent

[156:24]

for which we will use q learning now

[156:26]

deep q learning because this is a very

[156:28]

straightforward environment we don't

[156:29]

need

[156:30]

a functional approximation we just need

[156:31]

the tabular representation of the

[156:33]

agent's estimate of the action value

[156:36]

function

[156:38]

so if you're not familiar with q

[156:39]

learning i do have a couple videos on

[156:40]

the topic

[156:42]

one where

[156:43]

the q learning agent solved the card

[156:45]

poll game as well as a an explainer type

[156:48]

video that talks about what exactly

[156:49]

q-learning is

[156:52]

so let's go ahead and get started

[156:55]

we only have a couple dependencies we're

[156:57]

not doing anything on the gpu so just

[157:00]

numpy and matplotlib

[157:05]

we want to close everything up into a

[157:08]

class called grid world

[157:11]

and our

[157:13]

initializer

[157:15]

will take the m and n which is the shape

[157:18]

of the grid as well as the magic squares

[157:23]

so we represent our grid

[157:26]

as an array of

[157:28]

zeros and shape m by n

[157:32]

we want

[157:34]

we want to learn to type uh we want to

[157:36]

learn to

[157:38]

sorry we want to keep tr

[157:40]

we want to keep track of the m and the

[157:42]

end

[157:44]

for

[157:45]

handy use later

[157:47]

so let's go ahead and define our state

[157:49]

space

[157:50]

and that's just going to be a list

[157:51]

comprehension

[157:52]

for all the states in the range

[157:55]

self.m times self.n

[157:59]

now the as i said the state space does

[158:02]

not include the terminal state and the

[158:04]

terminal state is the bottom right so we

[158:05]

have to go ahead and remove or pop off

[158:08]

that particular

[158:09]

state from the list

[158:17]

uh next up so

[158:19]

now let's go ahead and

[158:24]

again learn to type

[158:27]

go ahead and define our

[158:30]

state space plus

[158:36]

also we need to know the

[158:38]

the way that the actions map up to their

[158:40]

change on the environment so we'll call

[158:43]

that

[158:44]

the action space a little bit of a

[158:46]

misnomer but we can live with it for now

[158:50]

so moving up we'll translate the agent

[158:53]

up

[158:54]

one row which is distance m

[158:57]

and moving down will advance the agent's

[159:00]

position

[159:01]

downward by

[159:04]

also m

[159:06]

um

[159:08]

moving left we'll translate the agent

[159:10]

one step we'll decrement the agent's

[159:13]

position by one

[159:14]

and moving right we'll

[159:16]

increase it by one

[159:20]

we also want to keep track of the set of

[159:22]

possible actions

[159:24]

you could use the keys in the action

[159:26]

space dictionary but

[159:28]

let's go ahead and use a separate

[159:30]

structure

[159:32]

and we'll use a list

[159:36]

up down left and right the reason is

[159:38]

that the q learning agent

[159:40]

a q learning algorithm sorry

[159:42]

can it can choose actions at random so

[159:45]

it is handy to have a list from which

[159:47]

you can choose randomly

[159:50]

uh next we need to add the magic squares

[159:55]

because that's a little bit more

[159:56]

complicated than

[159:58]

it may seem

[160:00]

and finally when we initialize the grid

[160:02]

we want to set the agent to the top left

[160:04]

position

[160:07]

let's go ahead and add those magic

[160:08]

squares

[160:13]

so

[160:15]

of course we want to store that

[160:17]

in our

[160:18]

object now there's a little bit of

[160:21]

hokiness that i must explain so

[160:23]

the agent is represented by a zero when

[160:26]

we print out the grid to the terminal

[160:29]

and uh md squares are represented by a

[160:31]

one

[160:32]

and so excuse me and so that means we

[160:35]

need something other than 0 and 1 to

[160:37]

represent these magic squares

[160:40]

i want to when i render the environment

[160:43]

i want to know where the entrance and

[160:44]

where the exit is

[160:46]

so we use different values for

[160:48]

the entrance and exit so that way we can

[160:51]

render it correctly

[160:53]

so

[160:54]

just by royal decree we set i which

[160:56]

would be the representation of the

[160:59]

of the magic square in the grid world to

[161:01]

2 to start

[161:04]

and we're going to go ahead and iterate

[161:07]

over the magic squares

[161:10]

so now what we need to know

[161:14]

is

[161:16]

uh

[161:18]

what position we are in

[161:22]

so

[161:25]

you

[161:26]

sorry it's the color is off indicating

[161:29]

something is wrong i have screwed

[161:31]

something up royally

[161:34]

which i do not see

[161:37]

because i am blind

[161:39]

anyway so

[161:41]

the

[161:42]

the x position is just going to be the

[161:44]

floor of the

[161:46]

current square and the

[161:49]

number of rows and y will be the

[161:53]

modulus of

[161:55]

the number of columns

[161:59]

so then the grid we want to set that x

[162:02]

and y position to i

[162:04]

and since we want to have a different

[162:06]

representation for the entrance and exit

[162:08]

go ahead and set the

[162:10]

increment i by one recall that the

[162:16]

magic squares are is represented as a

[162:19]

dictionary so we're iterating over the

[162:20]

keys and the values are the destinations

[162:24]

so the keys are the source values are

[162:26]

destinations

[162:28]

so

[162:29]

next we want to find out

[162:31]

precisely that

[162:33]

what the destinations are

[162:40]

set that in and then set the grid that

[162:43]

square

[162:45]

to i and then increment i again

[162:48]

and i'm only going to do

[162:51]

i'm only going to do

[162:53]

two magic squares you can do any number

[162:55]

but in this case we're just gonna do two

[162:57]

so

[162:59]

okay so the next thing we need to know

[163:01]

is if we are in the terminal state

[163:05]

and

[163:06]

as i said earlier the state space and

[163:09]

state space plus concepts give us a very

[163:10]

easy way of doing that so

[163:18]

let's go ahead and take care of that so

[163:20]

since the state space plus is all the

[163:23]

states and the state space is all the

[163:25]

states

[163:26]

minus the terminal state we know that

[163:29]

the difference between these two sets

[163:31]

is the terminal state so

[163:35]

state in

[163:37]

state space

[163:39]

plus

[163:40]

and

[163:41]

not in

[163:43]

the state space

[163:46]

how does that look

[163:47]

let me scroll down a bit okay

[163:50]

so

[163:52]

next up

[163:53]

let us

[163:55]

go ahead and get the agent row and

[163:57]

column

[164:02]

and we're going to use the same logic as

[164:04]

above

[164:18]

so next we want to set the state

[164:21]

so that will take the new state as input

[164:25]

and we're going to go ahead and assume

[164:26]

that the new state is allowed so the

[164:29]

agent

[164:30]

if it is along the left edge and

[164:32]

attempts to move left it just receives a

[164:34]

reward of minus one and doesn't actually

[164:36]

do anything

[164:37]

likewise if it's on the top row and

[164:39]

attempts to move up it doesn't actually

[164:40]

do anything it just gets a reward of

[164:41]

minus one for wasting its time

[164:45]

so we want to get

[164:48]

uh sorry the

[164:51]

row and column

[164:53]

and set that space

[164:56]

to zero because zero denotes an empty

[164:58]

square

[165:02]

and the agent position then is the new

[165:04]

state

[165:06]

and again we want to get the new x a new

[165:07]

y

[165:14]

there is a typo there let's fix that

[165:19]

and then set that position

[165:21]

to one because that is how we represent

[165:23]

the agent by royal decree

[165:26]

so the next thing we have to know

[165:29]

is if we're attempting to move off the

[165:31]

grid that's not allowed

[165:34]

the agent can only

[165:36]

stay on the grid so let's take care of

[165:37]

that

[165:42]

so we want to take the new and old

[165:44]

states as input

[165:47]

and the first thing we want to know is

[165:49]

if we're attempting to move off the grid

[165:51]

world entirely

[165:55]

that's ah

[165:59]

so

[166:02]

i hate these editors so

[166:05]

uh if we are if the new state is not in

[166:08]

the new state space plus we are

[166:09]

attempting to move off the grid so you

[166:11]

return true

[166:13]

otherwise

[166:16]

if the old state

[166:19]

modulus

[166:23]

m equals zero

[166:25]

and new state

[166:27]

modulus

[166:30]

um self.m equals self.m minus one

[166:35]

then we return true

[166:38]

and

[166:40]

for brevity i could explain this but the

[166:42]

video is running long already so for

[166:44]

brevity

[166:45]

the reason this is true is left as an

[166:47]

exercise to the reader bet you didn't

[166:50]

know this was going to be like a college

[166:52]

course

[166:53]

so now

[166:54]

uh basically what we're trying to do

[166:56]

here i'll just give you a hint what

[166:57]

we're trying to do here is determine if

[166:59]

we're trying to move off the grid either

[167:00]

to the left or to the right we don't

[167:02]

want to wrap around so

[167:05]

so if you're for instance if we have a

[167:07]

nine by nine grid it goes from zero to

[167:09]

eight so then if you add one

[167:12]

right you would get nine which would

[167:14]

teleport you to the other row

[167:16]

uh and the zeroth column you don't want

[167:18]

that what you want to do is waste spa

[167:20]

ways to move and receive a reward of

[167:22]

minus one so that's what we're doing

[167:24]

here

[167:25]

um

[167:26]

old state

[167:28]

modulus

[167:36]

good grief

[167:44]

so if

[167:45]

neither of those are true then you can

[167:47]

go ahead and return false

[167:49]

meaning you're not trying to move off

[167:51]

the grid

[167:53]

so let's see can you see that you can so

[167:58]

next function we need is

[168:00]

a way to actually step

[168:03]

so let's go ahead and do that let's say

[168:09]

the only thing we need is to take in the

[168:11]

action

[168:13]

so

[168:14]

the first thing you want to do

[168:18]

is get the x and y again

[168:25]

and here's where we're going to check to

[168:26]

make sure it's a legal move so the

[168:28]

resulting state

[168:32]

is then agent position

[168:38]

plus the mapping so the agent position

[168:41]

is whatever it is and recall that the

[168:44]

action space

[168:46]

is this dictionary here that maps the

[168:47]

actions to the translations in the grid

[168:50]

so we're doing down here then is saying

[168:52]

the new state is equal to the current

[168:54]

state plus whatever the

[168:57]

resulting translation is for whatever

[169:00]

action we're attempting to make

[169:02]

so

[169:05]

next thing we need to know is are we on

[169:07]

a magic square

[169:13]

and if we are

[169:16]

um

[169:26]

and if we are then the um

[169:29]

agent teleports to its new position

[169:32]

okay

[169:33]

so

[169:35]

next up we need to handle the reward

[169:38]

so it's minus one if not

[169:41]

um

[169:42]

is terminal

[169:44]

state

[169:47]

so it's minus one if we haven't

[169:48]

transitioned into the terminal state

[169:49]

otherwise it is zero

[169:54]

if we're not trying to move off the grid

[170:02]

then we can go ahead and set that state

[170:09]

self.set state

[170:12]

resulting state

[170:16]

and then we're ready to go ahead and

[170:18]

return

[170:20]

so in the openai gym uh whenever you

[170:22]

take a step it returns the new state the

[170:25]

reward

[170:26]

um

[170:28]

whether or not the game is over and some

[170:31]

debug information

[170:33]

so we're gonna do the same thing

[170:36]

resulting state reward

[170:40]

and

[170:42]

the

[170:44]

whether or not it is the terminal state

[170:50]

and our debug info is just going to be

[170:51]

none

[170:54]

so if we are attempting to move off the

[170:56]

grid what do we want to do nothing

[170:58]

so we want to return

[171:00]

agent position

[171:04]

um

[171:06]

and the

[171:08]

reward

[171:12]

and

[171:18]

whether or not it's terminal

[171:21]

and the null debug info

[171:24]

we're almost there so

[171:26]

next thing we need to know is

[171:30]

how do we reset the grid because at the

[171:32]

end of every episode we have to reset

[171:34]

right

[171:38]

first thing to do is set the agent

[171:39]

position to zero

[171:42]

reset the grid to zeros

[171:48]

and go ahead and add the magic squares

[171:51]

back in

[171:56]

and return the

[171:59]

agent position which is of course zero

[172:06]

oh wow that's real close all right so

[172:08]

next up

[172:10]

one last function i swear just one more

[172:13]

i promise all right

[172:15]

i wouldn't lie to you

[172:17]

all right next up

[172:19]

we want to provide a way of rendering

[172:21]

because hey that's helpful for debug

[172:24]

i like to print a whole big string of

[172:26]

you know dashes because it's party

[172:30]

[Music]

[172:33]

we want to iterate over the grid

[172:36]

for column in row

[172:39]

column equals

[172:40]

zero in other words if it's an empty

[172:43]

square we're just going to print a dash

[172:46]

and we're going to end it with a tab

[172:50]

if the column is 1 meaning we have an

[172:52]

agent there

[172:54]

we're going to print an x

[172:56]

to denote the agent

[173:00]

now

[173:00]

if the column is 2

[173:03]

then that is one of the entrances to

[173:07]

our magic squares

[173:09]

so print the

[173:12]

a in

[173:14]

with a

[173:15]

tab delimiter a tab end

[173:18]

if the column

[173:20]

equals three

[173:23]

you can print a out

[173:26]

and equals tab

[173:28]

um

[173:29]

and if the column

[173:31]

equals four

[173:33]

then we know we're at the

[173:35]

other magic square entrance

[173:44]

and finally if it's five then

[173:46]

we know we're at the

[173:48]

other

[173:49]

magic squares exit

[173:57]

after each

[173:58]

row we want to print a new line

[174:02]

and at the end we'll go ahead and print

[174:08]

another

[174:09]

chunk of pretty dashes

[174:13]

oh

[174:15]

ah yeah that's it that is it okay so

[174:19]

that is it for our agent class that only

[174:22]

took how long 20 some minutes wow okay

[174:26]

i hope you're still with me

[174:29]

basic idea here is to make your own

[174:31]

environment you need an initialize a

[174:33]

reset

[174:34]

a state space state space plus a way to

[174:37]

denote possible actions

[174:39]

a way to make sure the move is legal and

[174:41]

a way to actually affect that

[174:42]

environment

[174:44]

the step function needs to return the

[174:47]

new position the reward

[174:49]

whether or not the state is the new

[174:50]

state is terminal as well as some debug

[174:52]

information

[174:53]

you also need a way of resetting and

[174:55]

printing out your environment to the

[174:57]

terminal

[174:59]

so in part two we're actually going to

[175:00]

fire this baby up with a q learning

[175:03]

algorithm and see how she do

[175:06]

that's actually quite exciting it well

[175:08]

moderately exciting anyway it actually

[175:10]

learns it does quite well and it does

[175:12]

find the magic square

[175:14]

spoiler alert if you made it this far it

[175:16]

finds a magic square and gets out of the

[175:17]

minimum number of moves required

[175:20]

um

[175:21]

it's pretty cool to see so that will

[175:23]

come in the next video on vedna's day i

[175:25]

hope to see you all then

[175:28]

if you like the video make sure to leave

[175:30]

a thumbs up subscribe if you have not

[175:32]

already for more reinforcement learning

[175:34]

content and i will see you all in the

[175:37]

next video

[175:39]

welcome back everybody to a new tutorial

[175:41]

from neuralnet.ai i am your host phil

[175:44]

taber

[175:45]

if you're new to the channel i'm a

[175:46]

physicist former semiconductor process

[175:48]

engineer turned machine learning

[175:50]

practitioner

[175:51]

if you haven't subscribed yet go ahead

[175:52]

and hit the the subscribe button so you

[175:54]

don't miss any future reinforcement

[175:56]

learning tutorials

[175:58]

when we left off in our previous video

[176:00]

we just finished up the

[176:02]

bulk of our open ai gym compliant

[176:05]

reinforcement learning environment

[176:07]

today we're going to go ahead and code

[176:09]

up a q learning agent and the main loop

[176:11]

of the program to see how it all

[176:13]

performs

[176:14]

so let's go ahead and get started

[176:17]

so the uh first thing we are going to

[176:19]

need is the

[176:22]

um

[176:23]

is the

[176:24]

magic squares right

[176:26]

if you recall the magic squares are the

[176:30]

teleporters in the grid world that

[176:31]

either advance the agent forward or

[176:33]

backward

[176:34]

so the first one is going to be at

[176:36]

position 18 and dump out at position 54

[176:39]

so it'll move it forward

[176:41]

and the next one will be at let's say 63

[176:45]

and dump out at position 14. so

[176:48]

teleporter a will advance the agent

[176:50]

through the grid world and teleporter b

[176:52]

will send it back to

[176:54]

an earlier square

[176:57]

so we need to create our grid world

[176:59]

we use a nine by nine grid and pass in

[177:01]

the magic squares we just created

[177:05]

next up we have to worry about the model

[177:07]

hyper parameters so if you are not

[177:09]

familiar with that let me give you a

[177:11]

quick rundown these are the parameters

[177:13]

that control how fast the agent learns

[177:15]

and how much it chooses to value the

[177:18]

potential future rewards

[177:20]

so the first parameter is alpha that is

[177:22]

our learning rate

[177:24]

0.1

[177:27]

a gamma of 1.0 tells us that the agent

[177:29]

is going to be totally farsighted it

[177:31]

will count all future rewards equally

[177:35]

an epsilon of 1.0 this is of course the

[177:37]

epsilon for epsilon greedy action

[177:40]

selection

[177:41]

so it will start out

[177:44]

behaving pretty much randomly and

[177:45]

eventually converge on a purely greedy

[177:47]

strategy

[177:50]

so q learning is a tabular method where

[177:52]

you have a table of state and action

[177:54]

pairs and you want to find the value of

[177:56]

those state action pairs so to construct

[177:59]

that we have to iterate over the set of

[178:02]

states and actions

[178:06]

state space plus

[178:08]

and

[178:10]

emv dot possible actions

[178:17]

and you have to pick something for an

[178:18]

initial value it's really arbitrary but

[178:21]

the cool thing about picking zero is

[178:23]

that we're using something called

[178:24]

optimistic initial values what this

[178:27]

means is that since the agent takes or

[178:30]

receives a reward of minus one for every

[178:32]

step

[178:33]

it can never have a reward of zero right

[178:35]

because there's some distance between

[178:37]

the agent and the exit

[178:39]

so by setting the

[178:42]

initial estimate at zero you actually

[178:44]

encourage exploration of unexplored

[178:46]

states because if the agent takes a move

[178:49]

it realizes oh i get a reward of -1

[178:51]

that's significantly worse than 0. let

[178:53]

me try this other unexplored option so

[178:56]

over time it will gradually explore all

[178:58]

the available actions for any given

[179:00]

state

[179:01]

because it's been disappointed by all

[179:02]

the stuff it has previously tried just a

[179:04]

fun little fact

[179:07]

we want to play

[179:10]

50 000 games

[179:13]

we need a way of keeping track of our

[179:15]

rewards

[179:19]

numpy array will do just fine yes

[179:22]

so now let's iterate over the total

[179:25]

number of games

[179:29]

and um

[179:31]

thief

[179:32]

i like to print out a

[179:34]

marker to the terminal so that way i

[179:36]

know

[179:37]

it's actually working

[179:39]

so every five thousand games just print

[179:41]

that we're starting

[179:45]

the ith game

[179:47]

at the top of every episode you want to

[179:49]

reset your done flag you want to reset

[179:51]

your episode rewards

[179:53]

so you don't accumulate rewards from

[179:54]

episode episode and of course you want

[179:57]

to reset your environment

[180:00]

oh let me scroll down here

[180:02]

there we go

[180:05]

you want to reset your environment

[180:06]

just as you would with any open ai gym

[180:09]

type problem

[180:12]

next up

[180:13]

we begin each episode so while not done

[180:17]

we want to take a

[180:19]

random number

[180:21]

for our

[180:22]

epsilon greedy action selection

[180:26]

so

[180:27]

we're going to just make use of this max

[180:29]

action before we define it

[180:31]

q

[180:32]

observation

[180:36]

and

[180:37]

env.possible actions

[180:40]

and what that will do is

[180:43]

uh we're going to write it here

[180:44]

momentarily but what it's going to do

[180:46]

is it is going to

[180:49]

find the maximum action for a given

[180:52]

state

[180:53]

so the random number is less than one

[180:54]

minus epsilon we want to do that can you

[180:58]

guys see that yep

[181:00]

otherwise

[181:03]

we want to take

[181:06]

a random sample of the action space so

[181:08]

we have to write these two functions

[181:10]

let's do that quite quickly

[181:14]

so the

[181:18]

action space sample is pretty

[181:19]

straightforward

[181:23]

we can just return a random choice from

[181:25]

the

[181:28]

list of possible actions and that's the

[181:30]

reason we chose a list as that data

[181:32]

structure just to make it easy

[181:35]

next up we have the max action max

[181:38]

yeah max action function

[181:40]

but that doesn't need to belong to the

[181:42]

class

[181:44]

that takes the q the state and the set

[181:47]

of possible actions

[181:50]

we want to take a numpy array of the

[181:54]

estimates agent

[181:56]

sorry the agent's estimate of the

[181:58]

present value of the expected future

[181:59]

rewards

[182:01]

for the stated stand in all possible

[182:02]

actions

[182:08]

a in actions

[182:11]

and then we want to find the maximum of

[182:13]

that

[182:16]

and that's just an index so we want oop

[182:18]

sorry that's just an index so we want to

[182:20]

return

[182:21]

the action that that actually

[182:22]

corresponds to

[182:26]

all right that's all well and good

[182:29]

we need more space

[182:31]

let's do a little bit more

[182:33]

there we go

[182:35]

so next

[182:37]

we want to actually take the action

[182:40]

so we get our new state observation

[182:42]

underscore reward done and info

[182:46]

envy.step action

[182:49]

and next up uh we have to calculate the

[182:53]

maximal action for this new state so

[182:55]

that we can insert that into

[182:57]

our

[182:58]

update equation for the q function

[183:02]

so let's do that

[183:09]

and we're not worried about epsilon

[183:11]

greedy here because we're not actually

[183:13]

taking that action

[183:16]

next up we have to update rq function

[183:20]

for the current action and state

[183:28]

and

[183:29]

that's where our alpha comes in

[183:32]

ward plus

[183:35]

make sure that is visible to you

[183:39]

reward plus

[183:41]

some quantity

[183:43]

which is gamma our discount factor times

[183:46]

q

[183:47]

observation underscore action underscore

[183:50]

so the new state and action

[183:52]

minus q observation

[183:56]

action

[183:57]

let me tab this over there we go

[184:00]

nice and compliant with the pep style

[184:02]

guides right

[184:03]

mostly

[184:04]

okay so this is the update equation for

[184:07]

the q function that will update the

[184:09]

agent's estimate

[184:10]

of the

[184:11]

value of the current state and action

[184:14]

pair

[184:16]

next up

[184:17]

we just need to let the agent know that

[184:19]

the uh environment has changed states so

[184:23]

you set observation to observation

[184:25]

underscore

[184:27]

and that is it for q learning in a

[184:29]

nutshell folks that's really that

[184:31]

straightforward

[184:33]

so the end of each episode we want to

[184:36]

decrease epsilon

[184:38]

so that way the agent eventually settles

[184:39]

on a purely greedy strategy

[184:41]

you can do this a number of ways you can

[184:43]

do it you know with a square root

[184:44]

function a log function

[184:46]

i'm just going to do it linearly

[184:49]

it's not that critical for something

[184:50]

like this

[184:59]

so

[185:01]

it's going to decrease it by 2 divided

[185:02]

by num games every every game so about

[185:05]

halfway through it'll be purely greedy

[185:08]

and at the end of every episode you want

[185:10]

to make sure you're keeping track of the

[185:13]

total rewards which is something i

[185:15]

forgot up here

[185:18]

yeah so one thing i did forget is to

[185:20]

keep track of the

[185:23]

total reward for the episode don't

[185:25]

forget that very important

[185:29]

and at the end of all the episodes

[185:32]

you want

[185:35]

to plot the total rewards

[185:41]

and that is it for the coding portion oh

[185:44]

one other thing i take it back so let's

[185:46]

scroll up here i do want to show you the

[185:47]

environment so

[185:49]

let's just do that env dot render

[185:53]

and the

[185:54]

purpose of doing that is so that you can

[185:56]

see how many moves it takes the agent to

[185:58]

escape from the grid world

[186:00]

that will tell us if it's doing good or

[186:02]

not right because there's a minimum

[186:04]

minimum number of moves it takes to

[186:06]

escape

[186:07]

so i'm going to fire up the terminal and

[186:09]

go ahead and get that started

[186:12]

one second

[186:13]

and here we are in the terminal

[186:17]

let's go ahead and run that

[186:20]

and you can see here that we start at

[186:22]

the top left so it takes one

[186:24]

two

[186:25]

moving to a out is free

[186:27]

so 3

[186:28]

4 5 6 7 8 9 10 11. sorry 11 and the 12th

[186:35]

move is free because it's the exit to

[186:37]

the maze sorry to the grid world so

[186:40]

total reward of minus 11 is the best the

[186:42]

agent can possibly do

[186:44]

it's gone ahead and plotted so let's

[186:46]

check that out and here is the plot and

[186:49]

you can see that indeed the agent starts

[186:50]

out

[186:51]

rather poorly

[186:53]

exploring finding sub-optimal routes

[186:55]

through the grid world but eventually

[186:57]

and about halfway through here at um

[187:01]

2500 or so sorry 25 000 you can see that

[187:05]

it settles on at least a constant value

[187:08]

let's prove that it is

[187:11]

the maximum value of minus 11 and you

[187:14]

can see that

[187:16]

it's 10.97 that is

[187:19]

close enough for government work so you

[187:21]

see that the agent

[187:22]

is able to actually solve the maze sorry

[187:24]

the grid world i keep calling it amaze

[187:26]

is able to solve the grid world using

[187:27]

the q learning algorithm now this isn't

[187:29]

surprising you know we would expect this

[187:31]

uh what's novel here is that we have

[187:32]

created our own reinforcement learning

[187:34]

environment that uses a very similar

[187:36]

format to the open ai gym

[187:40]

so anytime you want to create a new

[187:41]

environment you can use

[187:42]

you can fire this video up and use the

[187:44]

you know set of code here

[187:47]

just as a template for your own projects

[187:49]

i'm going to put this up on my github

[187:50]

i'll link that down below and i'm also

[187:53]

going to write up a tutorial for uh in

[187:55]

text form and upload it to neuralnet.ai

[187:58]

i don't know if all that done tonight

[188:00]

i'll update the description with it

[188:01]

that's if you are a

[188:04]

you know if you consume text more easily

[188:06]

than than video then you can go ahead

[188:08]

and check that out i hope this has been

[188:11]

helpful

[188:12]

uh make sure to leave a comment

[188:14]

subscribe if you haven't already and i

[188:16]

hope to see you all in the next video

[188:21]

welcome back data manglers thanks for

[188:23]

tuning in for another episode from

[188:25]

neuralnet.ai

[188:27]

if you're new to the channel i'm phil

[188:28]

tabor a physicist and former

[188:30]

semiconductor engineer turned machine

[188:32]

learning practitioner

[188:34]

i'm on a mission to teach the next

[188:35]

generation of data engineers so we can

[188:37]

stay one step ahead of our robot

[188:39]

overlords

[188:41]

if you're not subscribed be sure to do

[188:42]

that now so you don't miss any future

[188:44]

reinforcement learning content

[188:47]

we've touched on reinforcement learning

[188:49]

many times here on the channel

[188:51]

as it represents our best chance at

[188:53]

developing something approximating

[188:55]

artificial general intelligence

[188:57]

we've covered everything from monte

[188:59]

carlo methods to deep q q-learning to

[189:01]

policy gradient methods using both the

[189:04]

pi torch and tensorflow frameworks

[189:08]

what we haven't discussed on this

[189:09]

channel is the what and the how of

[189:11]

reinforcement learning

[189:13]

that oversight ends today

[189:15]

right now

[189:17]

okay maybe a few seconds from now but

[189:20]

either way we're going to cover the

[189:21]

essentials of reinforcement learning

[189:24]

but first let's take a quick step back

[189:26]

you're probably familiar with supervised

[189:28]

learning which has been successfully

[189:30]

applied to fields like computer vision

[189:32]

and linear regression

[189:34]

here we need mountains of data all

[189:36]

classified by hand just to train a

[189:39]

neural network

[189:41]

while this is proven quite effective it

[189:43]

has some pretty significant limitations

[189:46]

how do you get the data how do you label

[189:48]

it

[189:49]

these barriers put many of the most

[189:51]

interesting problems in the realm of

[189:52]

mega corporations and this does us the

[189:55]

individual practitioners no good

[189:58]

to top it off it's not really

[190:00]

intelligence

[190:02]

you and i don't have to see thousands of

[190:04]

examples of a thing to understand what

[190:06]

that thing is

[190:08]

most of us learn actively by doing

[190:11]

sure we can shortcut the process by

[190:12]

reading books or watching youtube videos

[190:15]

but ultimately we have to get our hands

[190:18]

dirty to learn if we abstract out the

[190:20]

important concepts here we see that the

[190:22]

essential stuff is the environment that

[190:24]

facilitates our learning the actions

[190:26]

that affect that environment and the

[190:28]

thing that does the learning the agent

[190:30]

no jacket or labels required

[190:34]

enter reinforcement learning this is our

[190:36]

attempt to take those ingredients and

[190:38]

incorporate them into artificial

[190:40]

intelligence

[190:41]

the environment can be anything from

[190:42]

text-based environments like card games

[190:45]

to classic atari games to real to the

[190:48]

real world

[190:49]

at least if you're not afraid of skynet

[190:51]

starting an all-out nuclear war that is

[190:54]

our ai interacts with this environment

[190:56]

through some set of actions which is

[190:58]

usually discrete move in some direction

[191:00]

or fire at the enemy for instance

[191:03]

these actions in turn cause some

[191:04]

observable change in the environment

[191:06]

meaning the environment transitions from

[191:08]

one state to another

[191:10]

so for example in the space invaders

[191:12]

environment in the open ai gym

[191:14]

attempting to move left caused the agent

[191:16]

to move left with 100 probability

[191:19]

that need not be the case though

[191:21]

in the frozen lake environment

[191:23]

attempting to move left can result in

[191:25]

the agent moving right or up or down

[191:28]

even

[191:29]

so just keep that in mind that these

[191:31]

state transitions are probabilistic and

[191:33]

their probabilities don't have to be one

[191:35]

hundred percent merely their sum the

[191:38]

most important part of the environment

[191:40]

is the reward or penalty the agent

[191:42]

receives

[191:43]

if you take only one thing away from

[191:44]

this video it should be that the design

[191:47]

of the reward is the most critical

[191:49]

component of creating effective

[191:51]

reinforcement learning systems

[191:53]

this is because all reinforcement

[191:55]

learning algorithms seek to maximize the

[191:57]

reward of the agent

[191:59]

nothing more nothing less

[192:02]

in fact this is where the real danger of

[192:04]

ai is

[192:05]

it's not that it would be malicious but

[192:07]

that it would be ruthlessly rational

[192:10]

the classic example is the case of an

[192:12]

artificial general intelligence whose

[192:14]

reward is centered around how many paper

[192:16]

clips it churns out sounds innocent

[192:19]

right

[192:20]

well if you're a paper clip making bot

[192:22]

and you figure out that humans consume a

[192:24]

bunch of resources that you need to make

[192:26]

paper clips

[192:27]

then those pesky humans are in the way

[192:29]

of an orderly planetary scale office

[192:32]

that's problematic for all involved

[192:35]

what this means is we must think long

[192:38]

and hard about what we want to reward

[192:40]

the agent for and even introduce

[192:42]

penalties for undertaking actions that

[192:43]

endanger human safety at least and

[192:46]

systems that will see action in the real

[192:47]

world

[192:50]

perhaps less dramatic although no less

[192:52]

important are the implications for

[192:54]

introducing inefficiencies in your agent

[192:57]

consider the game of chess

[192:59]

you might be tempted to give the agent a

[193:01]

penalty for losing pieces but this would

[193:03]

potentially prevent the agent from

[193:05]

discovering gambits where it sacrifices

[193:07]

a piece for a longer term positional

[193:10]

advantage

[193:11]

the alpha zero engine a chess playing

[193:14]

artificial intelligence is notorious for

[193:16]

this

[193:17]

it will sacrifice multiple pawns and yet

[193:20]

still dominate the best traditional

[193:21]

chess engines we have to offer

[193:23]

[Music]

[193:24]

so we have the reward the actions and

[193:27]

the environment what are the agent

[193:29]

itself

[193:30]

the agent is the part of the software

[193:32]

that keeps track of these state

[193:33]

transitions actions and rewards and

[193:36]

looks for patterns to maximize its total

[193:38]

reward over time

[193:41]

the algorithm that dictates how the

[193:43]

agent will act in any given situation or

[193:45]

state of the environment is called its

[193:47]

policy

[193:48]

it is expressed as a probability of

[193:50]

choosing some action a

[193:52]

given the environment is in some state s

[193:55]

please note these probabilities are not

[193:57]

the same as the state transition

[193:59]

probabilities

[194:00]

the mathematical relationship between

[194:02]

state transitions rewards and the policy

[194:05]

is known as the bellman equation and it

[194:08]

tells us the value meaning the expected

[194:10]

future reward of a policy for some state

[194:13]

of the environment

[194:15]

reinforcement learning often though not

[194:17]

always means maximizing or solving that

[194:19]

bellman equation more on that in future

[194:21]

videos

[194:23]

this desire to maximize reward leads to

[194:25]

a dilemma

[194:26]

should the agent maximize his short-term

[194:28]

reward by exploiting the best-known

[194:30]

action or should it be adventurous and

[194:32]

choose actions whose reward appears

[194:34]

smaller or maybe even unknown

[194:36]

this is known as the explore exploit

[194:38]

dilemma and one popular solution is to

[194:41]

choose the best known action most of the

[194:43]

time and occasionally choose a

[194:45]

sub-optimal action to see if there's

[194:47]

something better out there

[194:48]

this is called an epsilon greedy policy

[194:52]

when we think of reinforcement learning

[194:54]

we're often thinking about the algorithm

[194:56]

the agent uses to solve the bellman

[194:58]

equation

[194:59]

these generally fall into two categories

[195:02]

algorithms that require a full model of

[195:04]

their environment and algorithms that

[195:06]

don't

[195:06]

what does this mean exactly to have a

[195:08]

model of the environment

[195:10]

as i said earlier actions cause the

[195:13]

environment to transition from one state

[195:14]

to another with some probability

[195:17]

having a full model of the environment

[195:19]

means knowing all the state transition

[195:21]

probabilities with certainty

[195:24]

of course it's quite rare to know this

[195:26]

beforehand and so the algorithms that

[195:28]

require a full model are of somewhat

[195:30]

limited utility

[195:32]

this class of algorithms is known as

[195:34]

dynamic programming if we don't have a

[195:36]

model or a model of the environment is

[195:38]

incomplete we can't use dynamic

[195:40]

programming

[195:41]

instead we have to rely on the family of

[195:43]

model-free algorithms

[195:45]

one popular such algorithm is q learning

[195:48]

or deep q learning which you studied on

[195:50]

this channel

[195:51]

these rely on keeping track of the state

[195:53]

transitions actions and rewards to learn

[195:56]

the model of the environment over time

[195:58]

in the case of q-learning these

[196:00]

parameters are saved in a table and in

[196:02]

the case of deep q learning the

[196:04]

relationships between them are expressed

[196:05]

as an approximate functional

[196:07]

relationship which is learned by a deep

[196:09]

neural network

[196:11]

that's really all there is at least at a

[196:14]

high level

[196:15]

so to recap

[196:17]

reinforcement learning is a class of

[196:18]

machine learning algorithms that help an

[196:20]

autonomous agent navigate a complex

[196:23]

environment

[196:24]

the agent must be given a sequence of

[196:26]

rewards or penalties to learn what is

[196:28]

required of it the agent attempts to

[196:31]

maximize this reward over time or

[196:33]

mathematical terms to solve the bellman

[196:35]

equation

[196:37]

the algorithms that help the agent

[196:38]

estimate future rewards fall into two

[196:41]

classes

[196:42]

those that require we know the state

[196:44]

transition probabilities for the

[196:45]

environment beforehand and those that

[196:47]

don't

[196:49]

since knowing these probabilities is a

[196:50]

rare luxury we often rely on model-free

[196:53]

algorithms like deep queue learning

[196:56]

if you'd like to know more please check

[196:58]

out some of the other videos on this

[196:59]

channel

[197:00]

i hope this has been helpful please

[197:02]

leave a comment a like and subscribe if

[197:04]

you haven't already look forward to

[197:07]

seeing you all in the next video

[197:10]

welcome back to the free reinforcement

[197:12]

learning course from neuralnet.ai

[197:15]

i'm your host phil tabor

[197:17]

if you're not subscribed be sure to do

[197:19]

that now and hit the bell icon so you

[197:21]

get notified for each new module in the

[197:23]

course

[197:25]

in module 1 we covered some essential

[197:27]

concepts in reinforcement learning so if

[197:29]

you haven't seen it go ahead and check

[197:32]

it out now so this module makes more

[197:34]

sense

[197:35]

if you have seen it you may remember

[197:37]

that reinforcement learning basically

[197:39]

boils down to an agent interacting with

[197:41]

some environment and receiving some

[197:43]

rewards in the process

[197:46]

these rewards tell the agent what's good

[197:48]

and bad and the agent uses some

[197:50]

algorithm to try to maximize rewards

[197:53]

over time

[197:54]

in practice what we get is a sequence of

[197:57]

decisions by the agent and each decision

[198:00]

doesn't just influence its immediate

[198:01]

reward rather each decision influences

[198:04]

all future rewards

[198:06]

in mathematical terms we have a sequence

[198:08]

of states actions and rewards that one

[198:11]

could call a decision process

[198:14]

if each state in this process is purely

[198:16]

a function of the previous state and

[198:18]

action of the agent then this process is

[198:20]

called a markov decision process or mdp

[198:23]

for short

[198:25]

these are an idealized mathematical

[198:27]

abstraction that we use to construct the

[198:28]

theory of reinforcement learning

[198:31]

for many problems this assumption can be

[198:33]

broken to various degrees

[198:35]

how much that really matters is often a

[198:37]

complicated question and one we're just

[198:39]

going to dodge for now

[198:42]

regardless in most cases the assumption

[198:44]

that a process obeys the markov property

[198:46]

is good enough and we can use all the

[198:48]

resulting mathematics

[198:50]

for reinforcement learning problems

[198:53]

by now i've said that a reinforcement

[198:55]

learning agent seeks to maximize rewards

[198:57]

over time

[198:58]

so how does this fit into a markov

[199:00]

decision process

[199:02]

from the agent's perspective it receives

[199:04]

some sequence of rewards over time and

[199:07]

that sequence of rewards can be used to

[199:09]

construct the expected return for the

[199:11]

agent

[199:12]

then the return at some time step t

[199:15]

is just the sum of the rewards that

[199:17]

follow

[199:18]

all the way up to some final time

[199:20]

capital t

[199:21]

this final time step naturally

[199:23]

introduces the concept of episodes which

[199:26]

are discrete periods of gameplay that

[199:28]

are characterized by state transitions

[199:30]

actions and rewards

[199:32]

upon taking this final time step the

[199:35]

agent enters some terminal state which

[199:37]

is unique

[199:38]

this means that no matter how we end the

[199:40]

episode the terminal state is always the

[199:43]

same

[199:44]

no future rewards follow after we reach

[199:46]

the terminal state so the agent's

[199:48]

expected reward for that terminal state

[199:50]

is precisely

[199:52]

zero

[199:53]

with a bit of creativity we call tasks

[199:56]

that can be broken into episodes

[199:58]

episodic tasks

[200:00]

of course not all tasks are episodic

[200:03]

many are in fact continuous this is a

[200:05]

bit of a problem since if the final time

[200:07]

step is at infinity the total reward

[200:10]

could also be infinite this makes the

[200:12]

concept of maximizing rewards

[200:14]

meaningless so we have to introduce an

[200:16]

additional concept

[200:18]

the fix and we use this for both

[200:20]

episodic and continuing tasks is the

[200:22]

idea of discounting

[200:24]

this basically means the agent values

[200:26]

future rewards less and less

[200:28]

this discounting follows a power law

[200:31]

where each time step results in more and

[200:33]

more discounting

[200:34]

this hyperparameter gamma is called the

[200:36]

discount rate and you've no doubt seen

[200:38]

this before in our videos on

[200:40]

reinforcement learning

[200:42]

if you use this form for the expected

[200:44]

return and do some simple factoring you

[200:46]

derive a really useful fact

[200:48]

there is a recursive relationship

[200:50]

between rewards at subsequent time steps

[200:53]

this is something we'll exploit

[200:55]

constantly in reinforcement learning

[200:58]

so we have an agent that is engaged in

[201:00]

some discrete processes receiving

[201:02]

rewards and trying to maximize its

[201:04]

expected feature returns

[201:06]

if you remember from the first lecture

[201:08]

the algorithm that determines how the

[201:10]

agent is going to act is called its

[201:12]

policy

[201:13]

since the agent has a set of defined

[201:15]

rules for how it's going to act in any

[201:17]

given state

[201:18]

it can use a sequence of states actions

[201:20]

and rewards to figure out the value of

[201:23]

any given state

[201:25]

the value of a state is the expected

[201:27]

return when starting in that state and

[201:29]

following the policy

[201:31]

it's given formally by the following

[201:33]

equation

[201:36]

in some problems like say q learning

[201:38]

we're more concerned with maximizing the

[201:40]

action value function which tells the

[201:42]

agent the value of taking some action

[201:44]

while in some given state and following

[201:46]

the policy thereafter

[201:48]

[Music]

[201:49]

remember how i said we can exploit the

[201:51]

recursive relationship between

[201:54]

subsequent returns

[201:55]

well if we plug that into the expression

[201:57]

for the value function we actually

[201:59]

discover that the value function itself

[202:01]

is defined recursively

[202:03]

this is called the bellman equation from

[202:05]

the first module and this is the

[202:07]

quantity many algorithms seek to

[202:09]

maximize

[202:10]

the bellman equation is really an

[202:12]

expectation value as it's a weighted

[202:14]

average of how likely each particular

[202:16]

sequence of states actions and rewards

[202:19]

is given the state transition

[202:21]

probabilities and the probability of the

[202:23]

agent selecting that action

[202:25]

much of the following material will

[202:27]

involve coming up with various schemes

[202:29]

to solve the bellman equation and evolve

[202:32]

the policy in such a way that the value

[202:34]

function increases over time

[202:37]

in the next module we'll take a look at

[202:39]

the explore exploit dilemma which is the

[202:42]

expression of the trade-off between long

[202:44]

and short-term rewards

[202:46]

i hope this has been helpful

[202:48]

questions comments suggestions leave

[202:50]

them below i read and answer all my

[202:52]

comments if you made it this far

[202:55]

consider subscribing so you get notified

[202:57]

when the rest of the course drops i look

[202:59]

forward to seeing you

[203:01]

in the next video

[203:04]

welcome to module 3 of the free

[203:06]

reinforcement learning course from

[203:07]

neural net dot ai i'm your host phil

[203:10]

taper if you're not subscribed make sure

[203:13]

to do that now so you don't miss the

[203:14]

rest of the course

[203:17]

in the previous video we learned about a

[203:19]

special type of process called the

[203:20]

markov decision process

[203:23]

there each state depends only on the

[203:25]

previous state and the action taken by

[203:27]

the agent

[203:29]

this leads to the recursive relationship

[203:31]

between the agent's estimate of returns

[203:33]

at successive time steps

[203:36]

this relationship extends to the agent's

[203:38]

estimate of the value function which is

[203:40]

given by the bellman equation

[203:44]

as we covered in module 1 reinforcement

[203:46]

learning for the most part boils down to

[203:49]

maximizing this value function

[203:52]

however it's not always so simple

[203:54]

surprise surprise

[203:56]

just like you and i have trade-offs in

[203:57]

real life

[203:58]

reinforcement learning agents are faced

[204:00]

with similar considerations

[204:03]

should the agent take the action that it

[204:04]

knows will immediately provide the most

[204:07]

reward or should it explore other

[204:09]

actions to see if it can do better this

[204:12]

conundrum is known as the explorer

[204:14]

exploit dilemma and every reinforcement

[204:16]

learning algorithm has to deal with this

[204:20]

fortunately there are many solutions and

[204:22]

we'll cover some of them here

[204:24]

one such solution is the idea of

[204:26]

optimistic initial values

[204:29]

when the agent starts playing the game

[204:30]

it has to use some initial estimate for

[204:32]

the value or action value function

[204:35]

this estimate is totally arbitrary but

[204:37]

if you know something about the reward

[204:39]

structure beforehand we can actually

[204:41]

initialize it in such a way as to

[204:43]

encourage exploration

[204:46]

suppose we have an environment like our

[204:47]

grid world and the video on creating our

[204:49]

own reinforcement learning environment

[204:52]

in that environment the agent receives a

[204:54]

reward of minus one for each step and so

[204:56]

the expected returns are always negative

[204:58]

or zero no matter the state of the

[205:00]

environment or the action the agent

[205:02]

takes

[205:03]

so what would happen if we tell the

[205:05]

agent that the value of all the state

[205:07]

action pairs are positive or even zero

[205:10]

on the first move the agent picks some

[205:12]

action randomly because all the actions

[205:15]

look identical

[205:16]

it receives a reward of -1 and updates

[205:19]

his estimates accordingly

[205:20]

so it's a bit disappointed it was

[205:22]

expecting chocolate cake and got a mud

[205:24]

pie

[205:25]

the next time it encounters that state

[205:26]

it will take a different action because

[205:28]

the other actions have an estimate of

[205:30]

zero reward for that state which is

[205:32]

better than the negative reward it

[205:34]

actually received this means that the

[205:36]

agent ends up exploring all the state

[205:39]

action pairs many times as each update

[205:41]

makes the agent's estimate more and more

[205:43]

accurate

[205:44]

we never had to explicitly tell the

[205:46]

agent to take exploratory actions

[205:48]

because it's greed drobit to take

[205:50]

exploratory actions after it became

[205:53]

disappointed with whatever action it

[205:55]

just took

[205:57]

again this is called optimistic initial

[205:59]

values

[206:01]

another feasible solution is to spend

[206:03]

some portion of the time choosing random

[206:05]

actions and the majority of the time

[206:07]

choosing greedy actions this is called

[206:09]

an epsilon greedy strategy and it's the

[206:11]

one we employ the most

[206:13]

it's quite robust as we can change the

[206:15]

random parameter over time so the agent

[206:18]

converges onto a nearly pure greedy

[206:20]

strategy

[206:21]

the proportion of the time the agent

[206:23]

spends exploring is a hyper parameter of

[206:25]

the problem and we typically call it

[206:27]

epsilon

[206:28]

one potential strategy is to start out

[206:31]

completely randomly and then use some

[206:33]

decay function to gradually increase the

[206:35]

proportion of greedy actions the agent

[206:37]

takes

[206:39]

the form of this function isn't

[206:40]

critically important it can be linear a

[206:43]

power law or really any other function

[206:46]

whether or not the agent converges to a

[206:47]

purely greedy strategy is going to

[206:49]

depend on the problem

[206:51]

for simple environments like the grid

[206:52]

world where we know the optimal solution

[206:54]

beforehand it makes quite a bit of sense

[206:56]

converged to a purely greedy strategy

[207:00]

however with a game like space invaders

[207:02]

a popular environment from the open ai

[207:04]

gym there are so many variables that

[207:06]

it's hard to be sure the agent has

[207:08]

settled on the truly optimal strategy

[207:10]

the solution there is to leave epsilon

[207:12]

at some small but finite value so the

[207:15]

agent is occasionally taking exploratory

[207:17]

actions to test its understanding of the

[207:19]

environment

[207:22]

all this discussion has made a very

[207:24]

important assumption

[207:26]

we've assumed the agent only uses a

[207:28]

single policy

[207:29]

the agent uses both the same policy to

[207:32]

update his estimate of the value

[207:33]

function as well as to generate actions

[207:36]

there's no rule this has to be the case

[207:38]

in fact an agent can leverage two

[207:40]

policies

[207:41]

it can use one policy to generate

[207:43]

actions and then use the data that

[207:45]

generates to update the value function

[207:47]

for some other policy

[207:49]

this is called off policy learning and

[207:51]

this is precisely what we use in

[207:53]

q-learning

[207:54]

the agent uses some epsilon greedy

[207:56]

strategy to generate steps in the markov

[207:59]

chain which is the sequence of state

[208:01]

action rewards and resulting states and

[208:03]

then uses that data to update the

[208:05]

estimate of the action value function

[208:07]

for the purely greedy action in effect

[208:11]

we're using an epsilon greedy strategy

[208:13]

to update our estimate of the purely

[208:14]

greedy strategy

[208:16]

needless to say this works quite well

[208:19]

and it's something we'll come back to in

[208:20]

later modules when we get to monte carlo

[208:22]

methods and temporal difference learning

[208:25]

that's it for now

[208:27]

reinforcement learning agents seek to

[208:28]

maximize their total reward but face a

[208:31]

dilemma of whether to maximize current

[208:33]

reward or take exploratory steps with

[208:35]

suboptimal actions in the hope of

[208:37]

optimizing long-term rewards

[208:40]

one solution is to bias the agent's

[208:42]

initial estimates in such a way that it

[208:44]

encourages exploration before settling

[208:46]

on a purely greedy strategy

[208:49]

another is to spend some proportion of

[208:50]

the time exploring and the majority of

[208:52]

the time exploiting the best known

[208:54]

action

[208:56]

and finally the agent can leverage two

[208:58]

policies one to generate data and the

[209:00]

other to update the estimate of the

[209:02]

action value or value function

[209:04]

in the next module we're going to get to

[209:06]

dynamic programming class of model based

[209:08]

reinforcement learning algorithms

[209:10]

make sure to subscribe so you don't miss

[209:12]

the remainder of this course and i look

[209:14]

forward to seeing you in the next video

[209:20]

welcome back everybody to machine

[209:21]

learning with phil i am your host dr

[209:23]

phil

[209:24]

when we last touched on the open ai gym

[209:26]

we did q-learning to teach the cartpole

[209:29]

robot how to dance basically how to

[209:31]

balance the pole

[209:32]

in this video we're going to take a look

[209:33]

at a related algorithm called sarsa so

[209:36]

they're related in the sense that

[209:38]

they're both types of temporal

[209:40]

difference learning algorithms the

[209:41]

difference being that

[209:43]

sarsa is an on policy method and q

[209:46]

learning is an off policy method

[209:48]

hey appearance by the cat um

[209:52]

if you if you don't know what that means

[209:53]

i highly encourage you to check out my

[209:54]

course reinforcement learning in motion

[209:56]

on manning publications i go in depth on

[209:59]

all this stuff

[210:00]

in that course uh enough plugging let's

[210:03]

get back to it so the other cool thing

[210:05]

is that it that sarsa as well as q

[210:07]

learning are model free meaning that you

[210:10]

do not need a complete model of your

[210:12]

environment to actually get some

[210:13]

learning done and that's important

[210:15]

because there's many cases in which you

[210:16]

don't know the full model of the

[210:18]

environment what does that mean it means

[210:20]

you don't know the state transition

[210:21]

probabilities so if you're in some state

[210:23]

s and take some action a what is the

[210:25]

probability you will end up in state s

[210:27]

prime and get reward r those

[210:29]

probabilities are not completely known

[210:31]

for all problems and so

[210:33]

algorithms that that handle that

[210:35]

uncertainty are critical for real-world

[210:37]

applications

[210:39]

another neat thing is uh that this is a

[210:42]

bootstrapped method meaning that it uses

[210:46]

estimates to generate other estimates

[210:48]

right so you don't need to know too much

[210:50]

about the system to get started you just

[210:51]

make some wild ass guesses and you get

[210:53]

moving let's take a look at the

[210:55]

algorithm

[210:57]

so uh your first step is to initialize

[210:59]

your learning rate alpha

[211:01]

uh and of course that's going to control

[211:02]

the rate of learning how quickly you

[211:04]

make adjustments to the q function uh

[211:06]

then you initialize the q function the q

[211:08]

function is just the agent's estimate of

[211:10]

its discounted future rewards

[211:12]

starting from a given state s and taking

[211:14]

an action a and it may have some

[211:15]

assumptions built in onto whether or not

[211:16]

you follow some particular policy or not

[211:19]

but that's a general gist

[211:20]

so you need to initialize your state and

[211:23]

choose some initial action based on that

[211:24]

state using an epsilon greedy strategy

[211:26]

from that function q

[211:28]

then you loop over the episode taking

[211:30]

the action getting your reward and your

[211:32]

new state s prime choose an action a

[211:34]

prime as a function of that state s

[211:35]

prime using epsilon greedy from your q

[211:38]

function and then go ahead and update

[211:39]

the q function according to the update

[211:41]

rule you see on the screen and then go

[211:43]

ahead and store your state prime into s

[211:45]

and your a prime into a and loop until

[211:47]

the episode is done again in the course

[211:49]

i go into many more details this is just

[211:51]

quick and dirty a bit of a teaser video

[211:53]

to get you guys

[211:54]

interested in the course and to give you

[211:56]

some useful information at the same time

[211:58]

so with that being said let's go ahead

[212:00]

and jump into the code i'm not going to

[212:01]

be doing typing on screen

[212:03]

but i will be showing you the relevant

[212:06]

code as we go along

[212:09]

and boom we are back in the code editor

[212:12]

so here i am using visual studio code um

[212:15]

even on linux this is a great editor if

[212:16]

you're not using it i highly recommend

[212:18]

it adam was a little bit buggy for me

[212:20]

and of course sublime is now is nag ware

[212:22]

so go ahead and give it a look if you

[212:25]

haven't already so

[212:26]

we need to define a function to

[212:28]

take the max action and that takes as

[212:31]

inputs the q function as well as the

[212:33]

state and you're just converting

[212:35]

the um

[212:37]

the q function into an array and to a

[212:40]

numpy array uh for each action in that

[212:42]

in that list

[212:44]

and finding the arg max of that now

[212:46]

recall that in numpy the arg max takes

[212:48]

the

[212:49]

returns the first element of a max so if

[212:51]

you have two actions that are tied it'll

[212:52]

give you the first one so of course in

[212:54]

the cart poll example our action space

[212:56]

is just moving left and right right if

[212:58]

you don't remember it's just a cart that

[213:00]

slides along the x-axis

[213:01]

trying to keep a pole vertical

[213:04]

of course this is a continuous space and

[213:07]

the q function is a discrete uh a

[213:09]

discrete mathematical construct right so

[213:12]

the states are discrete numbers and so

[213:14]

you have to do a little trick here to

[213:16]

discretize your space and so if you look

[213:18]

in the documentation for the cartpole

[213:21]

example you'll find the limits on these

[213:22]

variables and you can use that to create

[213:26]

a linear space based out of it

[213:28]

based on those limits and divide it up

[213:30]

into 10 different buckets right so that

[213:32]

way you get

[213:33]

you go from a continuous representation

[213:35]

to a discrete representation of your

[213:37]

state space

[213:38]

and then i define a small helper

[213:40]

function here

[213:41]

to get the state based on the

[213:42]

observation it just digitizes these

[213:47]

it digitizes those linear spaces using

[213:49]

the observation that you pass in from

[213:51]

the open ai gym

[213:53]

and it returns a four vector that is a

[213:56]

the buckets that correspond to the

[213:59]

value of the

[214:01]

element of the observation

[214:03]

the main program we want to use

[214:07]

small learning rate alpha 0.1

[214:10]

for a gamma something like 0.9 of course

[214:12]

the gamma is the discount factor it's

[214:14]

debatable whether or not you need it

[214:16]

here so

[214:17]

discounting in general is used when you

[214:20]

don't know the

[214:22]

we you don't know for certain you're

[214:23]

going to get some reward in the future

[214:24]

so it doesn't make sense to give it a

[214:26]

100 percent weight you could just as

[214:28]

easily here use a 1.0

[214:31]

because the state transition functions

[214:32]

in the cardboard example are

[214:33]

deterministic as far as i'm aware some

[214:35]

if i'm wrong please someone correct me

[214:38]

and of course the epsilon for the

[214:39]

epsilon greedy we're going to start out

[214:41]

at 1.0

[214:42]

you'll see why here in a second

[214:44]

and so you need to construct the set of

[214:46]

states which of course

[214:49]

just corresponds to the

[214:51]

integer representations of our

[214:52]

continuous space so you just have um

[214:56]

ranges from zero to zero to nine

[215:00]

and you construct a four vector out of

[215:02]

out of that right so you have zero zero

[215:04]

zero one one one et cetera et cetera et

[215:06]

cetera

[215:07]

and initialize your q function here i'm

[215:10]

going to initialize everything as

[215:13]

a zero right recall that we had to

[215:16]

we could initialize it arbitrarily but

[215:18]

for the terminal states you want that to

[215:20]

be zero because again the value of the

[215:22]

terminal state is zero and a is two in a

[215:25]

range of two because we only have two

[215:26]

actions move left move right

[215:29]

whoops

[215:31]

also i'm gonna run fifty thousand games

[215:33]

if you have a slower computer you might

[215:35]

wanna run fewer it takes quite a bit of

[215:36]

time to run and i'm going to track the

[215:38]

total rewards as we go along

[215:41]

so

[215:42]

just a little helper line here to print

[215:44]

out the the number of games you're

[215:45]

playing it's always good to know where

[215:48]

you are right you if it stops chugging

[215:50]

along you want to know if it's broken or

[215:52]

actually doing something useful

[215:55]

so you get your initial observation by

[215:57]

resetting the environment get your state

[215:59]

and calculate a random number and so you

[216:02]

take a maximum action if the random

[216:04]

number is less than one minus epsilon so

[216:07]

epsilon is starting out at one so if

[216:09]

random is less than zero otherwise

[216:12]

randomly sample your action space

[216:14]

done flag defaults and your rewards for

[216:16]

the episode to zero

[216:18]

then you loop over the episode until

[216:20]

you're done

[216:21]

and you go ahead and take the action a

[216:24]

getting your reward and the new

[216:26]

observation

[216:27]

the

[216:28]

state prime then is going to be the

[216:32]

get state of the observation right these

[216:34]

observation is a four vector of

[216:35]

continuous numbers that we have to

[216:36]

transform into a set of discrete

[216:39]

integers a four vector of discrete

[216:41]

integers then we go ahead and calculate

[216:43]

another random number and choose another

[216:45]

action based upon that

[216:47]

then calculate sum up the total rewards

[216:50]

and update the q function based on the

[216:53]

update rule i gave you in the slides and

[216:55]

of course set the state in action to the

[216:58]

new the s prime and a prime

[217:01]

and after each episode you're going to

[217:03]

decrease epsilon because you want this

[217:05]

you don't want the epsilon to be

[217:07]

permanently one right you want to

[217:09]

encourage some amount of exploration and

[217:10]

some amount of exploitation so epsilon

[217:12]

has to be a function of time

[217:14]

and just save your total rewards when

[217:16]

it's all done it's going to go ahead and

[217:17]

plot it out

[217:18]

and you should see something similar to

[217:21]

the following i'm going to go ahead and

[217:22]

run that now

[217:27]

and that is going to take a minute to

[217:29]

run and so here you have the output of

[217:30]

the source algorithm after running 50

[217:32]

000 iterations so what you see is first

[217:36]

of all a messy plot that's to be

[217:38]

expected with 50 000 games when you're

[217:39]

plotting every single point but what you

[217:41]

notice immediately is that there is a

[217:43]

general trend upward and when epsilon

[217:46]

reaches its minimum epsilon goes to zero

[217:49]

and it does a fully exploitative

[217:51]

strategy the algorithm actually does a

[217:53]

really good job of hitting 200 moves

[217:54]

most of the time recall that 200 moves

[217:57]

is the

[217:58]

um

[217:59]

200 moves is the maximum number of steps

[218:02]

for the cart pull problem uh because

[218:04]

good algorithms can get it to to balance

[218:06]

uh pretty much indefinitely so it would

[218:08]

never terminate so the open ai gym just

[218:11]

terminates at 200 steps so anything

[218:12]

close to that is pretty good now one

[218:14]

thing that's interesting is that it does

[218:16]

have a fair amount of variability it

[218:17]

doesn't actually

[218:19]

balance it 200 moves the entire time and

[218:22]

there are a number of reasons for this

[218:23]

perhaps you can speculate below i invite

[218:25]

you to speculate my thought process is

[218:27]

that the

[218:29]

the way we have discretized this space

[218:31]

isn't sufficient to characterize the

[218:33]

problem

[218:34]

in such a way that the algorithm can

[218:36]

learn something completely and totally

[218:37]

useful so it just doesn't have enough

[218:39]

information based on the ten thousand

[218:42]

ten of the four yeah ten thousand uh

[218:44]

states we've we've

[218:45]

discretized it into

[218:48]

uh and there could be other things that

[218:49]

matter you know uh you could have other

[218:51]

features for instance

[218:53]

combinations of velocities and positions

[218:56]

that matter so we could have under

[218:58]

engineered the problem slightly but for

[219:00]

just a quick little

[219:02]

chunk of

[219:03]

170 lines of code or so it's actually

[219:05]

quite good

[219:06]

so uh any questions be sure to leave

[219:09]

them below and hey if you've made it

[219:10]

this far and you haven't subscribed

[219:12]

please consider i'm going to be

[219:13]

releasing more and more content like

[219:15]

this i'm doing this full time now um

[219:17]

and i look forward to seeing you all in

[219:20]

the next video oh and by the way in the

[219:22]

next video we're going to be taking a

[219:23]

look at double q learning uh which is

[219:26]

yet another variation of these uh model

[219:28]

free bootstrap methods see you then

[219:34]

oh and one other thing if you want the

[219:36]

code for this i'll leave the code i'll

[219:38]

leave the link to my github

[219:40]

this is code for my course reinforcement

[219:42]

learning and motion i'm just showcasing

[219:44]

it here to show what you're going to

[219:45]

learn in the course so go ahead and

[219:46]

click the link in the description and

[219:48]

it'll take you to my github where you

[219:49]

can find that code as well as all the

[219:50]

code from the course

[219:52]

hope you like it see you guys in the

[219:53]

next video

[219:56]

welcome back everybody to machine

[219:58]

learning with phil i am your host dr

[220:00]

phil

[220:01]

in yesterday's video we took a look at

[220:03]

sarsa in the open ai gym getting the

[220:04]

cart pole to balance itself as promised

[220:07]

today we are looking at the algorithm of

[220:09]

double queue learning also in the

[220:11]

cartpole openaigm environment

[220:14]

so we touched on q-learning many many

[220:16]

months ago and the basic idea is that

[220:18]

q-learning is a

[220:20]

model-free bootstrapped off-policy

[220:23]

learning algorithm what that means is

[220:25]

model-free it does not need to know it

[220:28]

does not need the complete state

[220:29]

transition dynamics of the environment

[220:30]

to function it learns the game by

[220:32]

playing it bootstrapped in that it

[220:34]

doesn't need very many very much help

[220:36]

getting started it generates

[220:38]

estimates using its initial estimates

[220:40]

which are totally arbitrary except for

[220:41]

the

[220:42]

terminal states off policy meaning that

[220:45]

it is using a separate policy other than

[220:47]

it is using a behavioral policy and a

[220:49]

target policy to to both learn about the

[220:50]

environment and generate behavior

[220:52]

respectively

[220:54]

now when you deal with problems that uh

[220:57]

when you deal with algorithms that take

[220:58]

a maximizing approach to choosing

[221:00]

actions you always get something called

[221:02]

maximization bias so say you have some

[221:04]

set of states with many different

[221:06]

actions such that the action value

[221:09]

function for that state and all actions

[221:11]

is zero

[221:12]

then the

[221:13]

agent's estimate the q capital q of s a

[221:15]

can actually be

[221:17]

will actually have some uncertainty to

[221:18]

it and that uncertainty is actually a

[221:20]

spread in the values right and that

[221:22]

spread causes it to have some amount of

[221:23]

positive bias

[221:25]

and the max of the true values is zero

[221:27]

but the max of the capital q the agent's

[221:29]

estimate is positive hence you have a

[221:31]

positive bias and that can often be a

[221:33]

problem in

[221:34]

in reinforcement learning algorithms so

[221:37]

this happens because you're using the

[221:39]

same set of samples to max to determine

[221:41]

the maximizing action as well as the

[221:43]

value of that action and one way to

[221:45]

solve this problem is to use two

[221:46]

separate q functions to determine the

[221:49]

max action and the value and you

[221:51]

set up a relationship between them and

[221:53]

then you alternate between them as you

[221:54]

play the game so you're using one of

[221:56]

them to determine the max action one of

[221:58]

them to determine its value and you

[222:00]

alternate between them so that you

[222:01]

eliminate the bias over time

[222:04]

that's double q learning in a nutshell

[222:06]

the algorithm is the following so you

[222:08]

initialize your alpha and your epsilon

[222:10]

where alpha is your learning rate

[222:11]

epsilon is what you use for epsilon

[222:13]

greedy you want to initialize the q1 and

[222:15]

q2 functions for all states and actions

[222:18]

in your state in action space of course

[222:19]

that's arbitrary except for the terminal

[222:21]

states which must have a value of zero

[222:24]

and you loop over your set of episodes

[222:26]

and you initialize your state and for

[222:28]

each episode write each step within the

[222:30]

episode choose an action from uh using

[222:33]

your state using epsilon greedy strategy

[222:35]

in the sum of q1 and q2 so you have the

[222:37]

two separate q functions

[222:39]

so if you're using single queue learning

[222:41]

you would take the

[222:43]

max action over just one queue but since

[222:45]

you're dealing with two you have to

[222:47]

account for that somehow right you could

[222:48]

do a max you could do a sum

[222:51]

you could do an average in this case

[222:52]

we're going to take the sum of the two q

[222:54]

functions take that action get your

[222:57]

reward observe the new state and then

[222:59]

with the 0.5 probability either update

[223:01]

q1 or q2 according to this update rule

[223:04]

here and of course at the end of the

[223:06]

step go ahead and set your estate to the

[223:08]

new state and keep looping until the

[223:10]

game is done

[223:12]

so clear as mud i hope so by the way if

[223:15]

you want more reinforcement learning

[223:16]

content make sure to subscribe hit the

[223:18]

bell icon so you get notified

[223:21]

let's get to it so next up we have our

[223:24]

code

[223:24]

and here we are inside of our code

[223:26]

editor again i'm using visual studio

[223:28]

code to take a look at our double queue

[223:30]

learning script i'm not going to be

[223:32]

typing into the terminal i think that's

[223:34]

probably a little bit annoying i'm just

[223:35]

going to review the code as we go along

[223:38]

if you have seen my video on the source

[223:40]

algorithm there's going to be a fair

[223:41]

amount of overlap because we're solving

[223:43]

the same set of problems over again the

[223:44]

only real difference is

[223:46]

in that video we source it to calculate

[223:48]

the

[223:49]

action value function and in this case

[223:50]

we're using double q learning

[223:52]

again we have a max action function what

[223:54]

this does is tells us the max action for

[223:57]

a given state to construct that you make

[223:59]

a numpy array out of a list that is for

[224:02]

a given state both actions and as we

[224:04]

said in the video we're going to take

[224:06]

the sum of the q1 and q2 for a given

[224:08]

state for both actions

[224:10]

you want to take the arg max of that and

[224:12]

recall in numpy the arg max function

[224:14]

if there is a tie returns the first

[224:17]

element so if the left and right actions

[224:20]

both have identical action value

[224:21]

functions then it will return the left

[224:23]

action consistently

[224:26]

that may or may not be a problem it's

[224:28]

just something to be aware of

[224:31]

and once again we have to discretize the

[224:32]

spaces recall that the cart pull problem

[224:35]

which is just the cart sliding along a

[224:37]

track with a pole that is that must be

[224:39]

maintained vertically right

[224:41]

in the cart pole example we have a

[224:43]

continuous space the x and the theta can

[224:45]

be any number

[224:47]

within a given range and likewise for

[224:49]

the velocities

[224:51]

to deal with that we have a couple

[224:52]

options we could simply use neural

[224:54]

networks to approximate those functions

[224:56]

but in this case we're going to use

[224:58]

a little trick to discretize the space

[225:00]

so we're going to divide it up into 10

[225:02]

equal chunks and any number that falls

[225:04]

within a particular chunk will be

[225:05]

assigned an integer so you'll go from a

[225:08]

continuous to a

[225:10]

discrete representation of your four

[225:12]

vector the observation

[225:16]

along with that comes a get state

[225:18]

observat state

[225:20]

along with that comes a get state

[225:22]

function

[225:23]

that

[225:24]

you pass in the observation

[225:26]

and it just uses those

[225:28]

uh digitized spaces excuse me just use

[225:31]

those linear spaces

[225:33]

to use the numpy digitized function to

[225:35]

get the integer representation

[225:37]

of the respective elements of your

[225:38]

observation

[225:40]

i've also added a function to plot the

[225:42]

running average here i do this because

[225:44]

in the sarsa video we end up with a

[225:46]

little bit of a mess with 50 000 data

[225:47]

points this will plot a running average

[225:49]

over the prior 100 games

[225:52]

next up we have to initialize our hyper

[225:54]

parameters our learning rate of 0.1 this

[225:56]

just controls the step size in the

[225:58]

update equation the gamma is of course

[226:00]

the discount factor the agent uses in

[226:02]

its estimates of the future rewards

[226:05]

so i don't believe this should actually

[226:07]

be 0.9 i i left it here because it's not

[226:10]

super critical as far as i'm concerned

[226:12]

it should really be 1.0 and the reason

[226:14]

is that

[226:16]

the purpose of discounting is to account

[226:18]

for uncertainties and future rewards if

[226:20]

you have some sequence of rewards with a

[226:22]

probability of receiving them then it

[226:24]

makes no sense to

[226:26]

give each of those rewards equal weight

[226:27]

because you don't know if you're going

[226:28]

to get them in the cart poll example the

[226:31]

rewards are certain as far as i'm aware

[226:32]

the state transition probabilities are

[226:34]

one you know that if you move right

[226:35]

you're going to actually end up moving

[226:37]

right you know deterministically where

[226:38]

the pole and the cart are going to move

[226:42]

so it shouldn't be discounted as far as

[226:43]

i'm concerned epsilon is just the

[226:46]

epsilon factor for our for our epsilon

[226:48]

greedy

[226:50]

algorithm and

[226:52]

that's

[226:53]

pretty much it for hyperparameters of

[226:54]

the model next up we have to construct

[226:57]

our state space so what this means oh

[227:00]

baby's unhappy

[227:03]

the state space is of course the

[227:05]

um the representation of the digitized

[227:08]

space so we're going to have

[227:10]

for the cart position you're going to

[227:12]

have 10 buckets the velocity is 10

[227:14]

buckets and likewise for the thetas

[227:16]

theta position and theta velocity so

[227:18]

you're going to have 10 to the four

[227:19]

possible states so 10 000 states and

[227:22]

those are going to be numbered all the

[227:23]

way from 0 0 0 to 99.99 that's all we're

[227:26]

doing here is we're constructing the set

[227:28]

of states

[227:30]

next up we have to initialize our q

[227:32]

functions recall that the initialization

[227:34]

is arbitrary except for the terminal

[227:36]

state which must have a value of zero

[227:38]

the reason for this is that the

[227:40]

terminal state by definition has a

[227:42]

future value of zero because you stopped

[227:44]

playing the game right makes sense you

[227:46]

could initialize this randomly you could

[227:48]

initialize it with minus one plus one

[227:51]

doesn't really matter so long as the

[227:53]

terminal state is zero for simplicity

[227:54]

i'm initializing everything at zero

[227:57]

i'm going to play a hundred thousand

[227:58]

games the reason is that this algorithm

[228:02]

eliminates bias but at the expense of

[228:03]

convergence speed so you have to let it

[228:05]

run a little bit longer

[228:07]

uh an array for keeping track of the

[228:09]

total rewards and we're gonna loop over

[228:11]

a hundred thousand games printing out

[228:13]

every five thousand games to let us know

[228:15]

it's still running

[228:17]

always want to reset your done flag your

[228:18]

rewards and reset the episode at the top

[228:21]

and you're going to loop over the

[228:23]

episode getting your state

[228:25]

calculating a random number for your

[228:27]

epsilon greedy strategy you're gonna set

[228:29]

the action to be the max action of q1

[228:32]

and q2 if the random number is less than

[228:34]

one minus epsilon otherwise you're going

[228:36]

to randomly sample your action space in

[228:38]

any event you take that action get your

[228:40]

new state reward and done flag and go

[228:43]

ahead and tally up your reward and

[228:45]

convert that observation to a state s

[228:48]

prime

[228:50]

then go ahead and calculate a separate

[228:52]

random number the purpose of this random

[228:54]

number is to determine which q function

[228:55]

we're going to update you know we're

[228:57]

going to be using one to calculate

[229:00]

we're alternating between them because

[229:01]

we have to eliminate the

[229:04]

maximization bias right one is for

[229:06]

finding the max action one is for

[229:09]

finding the value of that action we

[229:10]

alternate between episodes by way of

[229:12]

this random number

[229:14]

in both cases you want to collect the

[229:16]

you want to calculate the max action

[229:18]

either q1 or q2 and use the update rule

[229:21]

i showed you in the slides to update the

[229:23]

estimates for q1 and q2

[229:27]

as you go

[229:28]

at the end of the episode sorry at the

[229:30]

end of the step excuse me you want to

[229:32]

reset the

[229:33]

old observation to the new one so that

[229:35]

way you can get

[229:36]

the state up here and at the end of the

[229:38]

episode you want to go ahead and

[229:39]

decrease epsilon if you're not familiar

[229:41]

with this

[229:42]

epsilon greedy is just a strategy for

[229:44]

dealing with the explore exploit dilemma

[229:46]

so an agent always has some estimate of

[229:48]

the future rewards based on its model of

[229:50]

the environment or its experience

[229:52]

playing the game if it's model free or

[229:54]

a model uh problem

[229:57]

right it can either explore or exploit

[230:00]

its best known actions so one way of

[230:01]

dealing with the dilemma of how much

[230:03]

time should you spend exploring versus

[230:04]

how much time should you spend

[230:06]

exploiting is to use something called

[230:07]

epsilon greedy meaning that some

[230:09]

percentage of the time you explore some

[230:10]

percentage of the time you exploit

[230:12]

and the way that you get it to settle on

[230:14]

a greedy strategy is to gradually

[230:16]

decrease that

[230:17]

exploration parameter epsilon over time

[230:20]

and that's what we're doing here

[230:22]

and of course you want to keep track of

[230:23]

the total rewards for that episode and

[230:25]

recall in the current poll example

[230:27]

the agent gets a reward of positive one

[230:29]

every time the poll stays

[230:32]

vertical so every move that it doesn't

[230:34]

flop over it gets one point

[230:37]

and at the end you're going to go ahead

[230:38]

and plot your running averages

[230:40]

so i'm going to go ahead and run that

[230:44]

and that'll take a minute uh while it's

[230:45]

running i want to ask you guys a

[230:47]

question so what type of material do you

[230:49]

want to see

[230:50]

from what i'm seeing in the data the

[230:53]

the reinforcement learning stuff is

[230:54]

immensely popular my other content not

[230:56]

so much so i'm going to keep focusing on

[230:58]

this type of stuff but are you happy

[230:59]

seeing the sutton bardo type

[231:02]

introductory material or do you want to

[231:04]

see more deep learning type material

[231:05]

right there's a whole host of dozens of

[231:08]

deep reinforcement learning algorithms

[231:09]

we can cover

[231:10]

but i'm actually quite content to cover

[231:12]

this stuff because

[231:14]

i believe that if you can't master the

[231:15]

basics then the deep learning stuff

[231:17]

isn't going to make sense anyway right

[231:19]

because you have the complexity of deep

[231:21]

learning on top of

[231:22]

the

[231:23]

complexity of the reinforcement learning

[231:25]

material on top of it

[231:28]

so if there's anything in particular you

[231:30]

guys want to see make sure to leave a

[231:32]

comment below and hey if you haven't

[231:33]

subscribed and you happen to like

[231:35]

reinforcement learning and machine

[231:36]

learning material please consider doing

[231:38]

so if you like the video make sure to

[231:40]

leave a thumbs up hey if you thought it

[231:41]

sucked go ahead and leave a thumbs down

[231:43]

and tell me why i'm happy to answer the

[231:45]

comments answer your objections and if

[231:47]

you guys have suggestions for

[231:48]

improvement i'm all ears

[231:51]

and here we are it is finally finished

[231:53]

with all hundred thousand episodes

[231:55]

and you can see here the running average

[231:57]

over the course of those games

[231:59]

as you would expect the agent begins to

[232:02]

learn fairly quickly

[232:03]

balancing the cart pull more and more

[232:05]

and more by about 60 000 games it starts

[232:07]

to hit the consistently hit the 200 move

[232:10]

threshold where it is able to balance

[232:12]

the cart pull all 200 moves of the game

[232:14]

now recall this was with a gamma of 1.0

[232:18]

i'm going to go ahead and rerun this

[232:19]

with a gamma of 0.9 and see how it does

[232:21]

so burn this image into your brain and

[232:24]

i'm going to go ahead and check it out

[232:26]

with a gamma of 0.9 and see if we can do

[232:29]

any better

[232:31]

and we are back with the second run

[232:33]

using a gamma of 0.9 and you can see

[232:36]

something quite interesting here

[232:38]

so it actually

[232:39]

only kind of ever reaches the 200 mark

[232:42]

uh

[232:43]

just for a handful of games and then

[232:45]

kind of stutters along actually

[232:46]

decreasing in performance as it goes

[232:47]

along so something funny is going on

[232:50]

here and to be frank i off the top of my

[232:52]

head i'm not entirely certain why so

[232:55]

i invite you all to speculate however

[232:57]

the

[232:58]

what's also interesting is that i this

[233:00]

is the second time i'm recording this i

[233:01]

recorded it earlier and didn't scroll

[233:04]

down the code so you ended up staring at

[233:05]

the same chunk of stuff had to redo it

[233:08]

and in that case i had a gamma of 0.9 as

[233:10]

well and it seemed to work just fine so

[233:12]

i suspect there's some significant

[233:14]

variation here to do with the random

[233:16]

number generator

[233:17]

um

[233:18]

it could just all be due to that right

[233:20]

this is a complex space and it

[233:23]

wanders around different portions this

[233:25]

could happen potentially because it

[233:26]

doesn't visit all areas of the parameter

[233:28]

space enough times to get a reasonable

[233:30]

estimate of the samples and there may be

[233:32]

some type of bias on where it visits

[233:34]

later on in the course of the episodes

[233:37]

although that sounds kind of unlikely to

[233:39]

me but either way that is double q

[233:41]

learning you can see how the

[233:44]

hyper parameters actually affect the

[233:45]

model it seems to have a fairly large

[233:47]

effect as you might expect

[233:50]

and the next video we're going to be

[233:51]

taking a look at double sarsa so if you

[233:54]

are not subscribed i ask you to please

[233:56]

consider doing so hit the notification

[233:58]

icon so you can see when i release that

[234:00]

video i look forward to seeing you all

[234:02]

in the next video

[234:06]

well i hope that was helpful everyone so

[234:08]

what did we learn we learned about

[234:10]

q-learning policy gradient methods sarsa

[234:14]

double q learning and even how to create

[234:16]

our own reinforcement learning

[234:17]

environments this is a very solid

[234:19]

foundation in the topic of reinforcement

[234:22]

learning and you're pretty well prepared

[234:23]

to go out and explore more advanced

[234:25]

topics so what are those more advanced

[234:27]

topics so right now the forefront are

[234:30]

things like deep deterministic policy

[234:32]

gradients which is as you might guess

[234:33]

from the name a more

[234:35]

advanced version of policy gradient

[234:37]

methods they're also actor critic

[234:39]

methods

[234:40]

uh behavioral cloning there's all sorts

[234:41]

of more advanced topics out there that

[234:43]

you're now pretty well equipped to go

[234:45]

explore

[234:46]

these are particularly useful in

[234:48]

environments where you have continuous

[234:49]

action spaces so all the environments we

[234:51]

studied in this set of tutorials have a

[234:54]

discrete action space meaning the agent

[234:55]

only moves

[234:56]

or takes some discrete set of actions

[234:59]

other environments such as the bipedal

[235:01]

walker

[235:02]

car racing things of that nature have

[235:04]

continuous state spaces so excuse me

[235:06]

continuous action spaces which require

[235:08]

different mechanisms to solve q learning

[235:10]

really can't handle it so you're now

[235:12]

free to go ahead and check that stuff

[235:14]

out if you've made it this far please

[235:16]

consider subscribing to my channel

[235:17]

machine learning with phil and i hope

[235:19]

this is helpful for all of you leave a

[235:20]

comment down below and make sure to

[235:22]

share this and i'll see you all

[235:24]

in the next video

Keep this transcript

Save it to LunaNotes and it becomes a real note in your library — editable, searchable, and ready to turn into flashcards or a diagram. Free to start.

Save to LunaNotes

Or download subtitles for another video.

These subtitles were extracted using the Free YouTube subtitle downloader by LunaNotes.

Related videos

Download Subtitles for All Machine Learning Concepts Video

Download Subtitles for All Machine Learning Concepts Video

Enhance your understanding by downloading accurate subtitles for the 'All Machine Learning Concepts Explained in 22 Minutes' video. Access clear captions to follow complex topics with ease and improve your learning experience.

Download Recurrent Neural Networks (RNNs) Subtitles & Captions for Clear Understanding

Download Recurrent Neural Networks (RNNs) Subtitles & Captions for Clear Understanding

Get accurate, easy-to-follow subtitles for 'Recurrent Neural Networks (RNNs), Clearly Explained!!!' to enhance your machine learning study. Download SRT captions to unlock every detail of this intuitive RNN tutorial for better comprehension and note-taking.

Download Subtitles for Complete RAG Crash Course with Langchain

Download Subtitles for Complete RAG Crash Course with Langchain

Enhance your learning experience by downloading subtitles for the Complete RAG Crash Course with Langchain video. Subtitles help you follow along easily, support better comprehension, and make revisiting key concepts effortless. Access accurate captions to maximize your understanding of Langchain in just 2 hours.

Download Subtitles for Introduction to DaVinci Resolve Full Course

Download Subtitles for Introduction to DaVinci Resolve Full Course

Enhance your learning experience by downloading accurate subtitles for the Introduction to DaVinci Resolve full course. Captions help you follow along effortlessly, improve comprehension, and make the tutorial accessible anytime, anywhere.

Download Subtitles for CLAUDE CODE Full Course 2026

Download Subtitles for CLAUDE CODE Full Course 2026

Enhance your learning experience with downloadable subtitles for the CLAUDE CODE FULL COURSE 4 HOURS: Build & Sell (2026). These captions help you follow along easily, improve comprehension, and revisit key concepts anytime. Perfect for learners who want clear, accessible content at their own pace.

Most viewed

Untertitel für 'Nicos Weg' Deutsch lernen A1 Film herunterladen

Untertitel für 'Nicos Weg' Deutsch lernen A1 Film herunterladen

Laden Sie die Untertitel für den gesamten Film 'Nicos Weg' herunter, um Ihr Deutschlernen auf A1 Niveau zu unterstützen. Untertitel helfen Ihnen, Wortschatz und Aussprache besser zu verstehen und verbessern das Hörverständnis effektiv.

ดาวน์โหลดซับไตเติ้ล DMD LAND 3 The Final Land Day 1

ดาวน์โหลดซับไตเติ้ล DMD LAND 3 The Final Land Day 1

ดาวน์โหลดซับไตเติ้ลสำหรับวิดีโอ DMD LAND 3 The Final Land Day 1 เพื่อช่วยให้เข้าใจเนื้อหาได้ง่ายขึ้น และเพิ่มความสะดวกในการติดตามทุกช่วงเวลา เหมาะสำหรับผู้ชมที่ต้องการความชัดเจนและเข้าถึงข้อมูลอย่างครบถ้วน

Subtítulos para TIPOS DE APEGO | 6 DE COPAS Episodio 56

Subtítulos para TIPOS DE APEGO | 6 DE COPAS Episodio 56

Descarga los subtítulos para el episodio 56 de la tercera temporada de 6 DE COPAS, centrado en los tipos de apego. Mejora tu comprensión y disfruta del contenido en detalle con nuestros subtítulos precisos y accesibles.

Download Subtitles for Harvard CS50 2026 Computer Science Course

Download Subtitles for Harvard CS50 2026 Computer Science Course

Enhance your learning experience with downloadable subtitles for the Harvard CS50 2026 full computer science course. Easily follow along with lectures, improve comprehension, and access the content offline anytime. Perfect for students and enthusiasts aiming to master computer science concepts.

Descarga Subtítulos para NARCISISMO | 6 DE COPAS - Episodio 63

Descarga Subtítulos para NARCISISMO | 6 DE COPAS - Episodio 63

Accede fácilmente a los subtítulos del episodio 63 de '6 DE COPAS', centrado en el narcisismo. Descargar estos subtítulos te ayudará a entender mejor el contenido y mejorar la experiencia de visualización.

Found this transcript useful?

Take it with you. One click puts it in your own LunaNotes library.

Save to LunaNotes

Start taking better notes today with LunaNotes