Code a Reinforcement Learning Library in C from Scratch (Full Course)

#Reinforcement Learning #C Programming #Autograd Engine #REINFORCE Algorithm #Snake Game AI #Machine Learning from Scratch #Programming
💬 Chat with this Video
Ask anything about this video…
Welcome to this deep dive into building a custom reinforcement learning library entirely from scratch in C. Throughout this tutorial, you will construct an autograd engine and implement the policy gradient reinforce algorithm without relying on any external machine learning frameworks to put our custom library to the test. We will also code a complete snake game environment to train our AI agent and watch it learn how to navigate the grid. >> Hi everyone, I hope you're doing good. In this video, we will going to implement reinforcement learning library from scratch in C. So I hope you have some understanding of the reinforcement learning how the agent loop works and how the agent takes action in the environment and environment gives the report to the agent and that how the agent learns and get feedback uh and also have some understanding of the machine learning and stuff. So yeah I think u if you have these all the prerequisics then let's get started. I think this is a very good video because here we can actually go very deep and implement things from very scratch in C and uh we will implement the policy gradient reinforcement reinforce algorithm and we will implement the model from scratch. We will implement the environment RL environment from scratch and also we will not implement these things but also implement the autograd engine which is like a computational graph of the gradients where that's how neural network trains. So yeah, let's get started. U there's some of the things that uh I already defined which like base which is like some types here which I have already defined and this files contains some random numbers which will help us to use it in further video. Uh so here are some things I want to mention first like this is the video you can probably see in the screen this video is really good video uh and I think this person actually taught really good about like how to build the machine learning library from scratch. So this is kind of an inspiration that I took and okay let's go and implement the RL library from scratch. So yeah, if you want to check out this video, please check out that too. And uh pretty good video. So let's get started here. Uh I think first we can uh let's define the autograd because that is one of the fundamentals right now and then we can uh go for like defining model and then our our environment. So let's get started. Autograd C. Um okay. And uh here we have this u what we need. Um so as you probably have the understanding of like how the model works you have like forward pass and then backward pass. So which requires a lot of which requires a graph uh to go from one direction and then also in the reverse direction and that graph is what we're going to be define here like this the autograph which computes the auto differentiation stuff uh in the backward pass. So here we will define the graph of the forward pass and then in the backward pass when we are going that backward pass basically creates the traversal graph and identify variables uh within that and then computes the gradients and that's why we call autograd which is like auto differentiation stuff. So yeah uh let's go and define the variable first like what is variable you know variable is basically the uh which is struck it could be and uh it will contains index u32 index and then will have the number of inputs you know and that number of inputs is will be like a number of it's also a var so inputs because one variable can contains the inputs of it. So let's suppose I have a + b equals to c that c is also where a is also where b is also where v variable is basically the parameter you can say in model. So this is what it is. It will have flags you know uh U32 flags and uh this v inputs basically will have number of inputs and then it will also contain so basically this v inputs is the number of inputs uh number of inputs it will contain a basically the inputs it can have like one input or two input so because like for Some of the operations like relu soft max requires just one input but for the operations like addition subtraction that requires two inputs which like could be a and b and any kind of variables. So yeah I think uh what else we need like we need value which is like a what which will be a matrix. So here we will create a matrix. We haven't defined the matrix yet. So but we'll we will define later and uh a gradient. So gradient is also matrix right. So these are the things. Uh what else we doing in a variable can you think of um bar can have like columns and stuff? I guess not really but a metric can have. So we can define in the metrics. So yeah um you can define create metrics which will have U32 rows 32 columns and um to and then we it will have like a data right and that data is could be 32 okay let's define first this thing have this and then a data I So we can have like a U32 data or I can say like F32. Yeah, we can now this is like uh the actual definition like the the initialization of the stuff we can define the definition here also so it won't get confused that defined earlier or later. So type def I hope it is recording it is recording I guess. Yes. So, so right we can check it if this is working or not. Go to terminal C run. So this is very confusing you know when we are using Python and C at the same time. Q32 will come from nice. Uh then we have like strruct bar type. So this is the bar we have defined. But like you know we also need what is the type of this V because it can have like addition bar it can have soft max bar. It can have like different operational types of R. So with what type of V is a bar type and this can have like this var type can have um the types which is basically shape. You can have bar function shape. This shape you know this this function basically will help in shaping this v type and this v type have can have like v funk back forward function and backward function. So then it will have a good definition of our type like what kind of function it has, what kind of backup function it has and obviously the name. So it will have a name, right? And that's it. That's uh that is the bar type and also the type. So now we also need to define the function here which is like this function and stuff right. So after our definition of v we can define or like there's not nothing needed for that because like say here v32 and uh function which will have like the v32 columns 32 rows. This will have just one. Okay. Now this is we have defined it will have forward backward shape type and stuff four errors which is like type this should be I guess uh should be this should be a pointer. Got it. Uh the type will already be defined by the name here. So I guess that's it. And uh that also requires like how many inputs it has this um this part type will have. So we can also define like the 32 number inputs right it is working. Um we can now we need to define some of the definitions here which is the v it will have like v soft max you know that will have me arena okay I haven't defined the mem arena right so I'll just what I'll just do is like I will also include the arena thing which is arena is basically which defines the memory location allocations and stuff and for this kind of projects. So I will just going to go and I have defined the arena here. This is the arena. So it will help us to actually create the arena and stuff. And uh arena.h will have the all the definitions. So yeah um in autograph we can just like import it like this. Now this softmax will have me arena now which ask for space and stuff model state model and then war input actually just input I will define the model state so we will get the arena from the arena itself and uh I'll define the model state but we can define it first it's not a great big you. So strct model and uh in this model we have you know model state is that model state uh in this we'll have like you know a lot of things uh which help us to build the model the one of the things that I actually getting in my mind which is advantages. So advantage to Y in reinforcement learning. So we will store the advantage here and this is basically going to be float 32 right and uh this is the advantage and it will this contains a lot of things like number of bars and number of bars will be again this U32 and it can have it can also have a lot of different things I guess model state not model it can have you I guess that's it we will innovate it later I think we can just find what are exactly required for us so this is the model state uh we can define it here again type dev straw basically we can just define it here like that bar soft max bar arena arena in a state model where input and we can copy it right over the where add now this v a b this again subtract I guess we also need type of it which is like the v type I'm guessing v type type subtraction is done now maximum is the matrix multiplication you know and model state reinforce and R we'll get like a pro probabilities and art stuff. So let's run this after this draft. Okay nice now you know we also need like backward pass and forward pass thing. So void will basically you know which is where soft max forward which basically going to forward the soft max and that require these things like me arena and all stuffs inputs and this will compute the I guess this will compute the softmax and stuff yeah so you don't need bar type you don't you need this and uh yeah why we are just doing this is again going to be you know same same going for the backward so soft max backward although like here we just need don't need like because we we're not computing anything we're just computing gradients and we already have like the uh calculation stuff so we are going backward word and then using this var we can just get the output of it and we can compute the gradients. Got it? V backward. This is our backward pass functions and stuff now. Okay. Now we need to build function which can create variables. you know we have to find this is some abstraction for us this variable. Now we need to define variables um like create variables. So a variable will a function that returns variable create bar arena arena model state and uh view 32 rows 32 columns right and flags. Now in arena you will find like this push truck function which is here push truck function which basically can be used to allocate the memory for the specific var first right so we will use this this autograd you know I hope I'm recording yeah all good so this auto grad let's create where basic Basically first it will do is like var out equals to this is how you define it right like this and uh and this out index plus equals to 1 + = to 1 ++ I can say out and then it will have now we need to define create a matrix so matrix m equals to create matrix a function that can Create matrix. Now before creating that we should have created metrics. Create matrix that contains like you know arena arena rows columns and the matrix is this right rows column data I guess like this is uh let me confirm it will be a pointer to be honest. Um yeah it will be a pointer. So yeah, I think this is uh this how you define create metrics. Create matrix and uh you basically going to push struck the metrics. This push truck will contain arena and that say out columns return out data will be okay. So yeah data we probably we can like define data as as push truck this data is push array because we already have this function push array. So we can use this arena tn. So arena t is basically the tricks size of tricks and then rows and columns rows. We can just like push array paste like this. Yeah, exactly. That's how we use this. We can directly use this. Uh it's getting confusing. So this working we can try finding create metrics. We don't have arena. So create arena create arena. Arena will take capacity. So let's define 1,00 and uh arena 25 25. We can also print out the matrix which is the matrix A as it has 0 0 0. So this printed the first. Okay. And we just print the rows you verify. That's great. So this is uh we are this is here we are right now. Uh instead of like defining this we can also say like push strruct and then uh it contains and then create a metric arena rows columns here and uh we haven't defined the flags right we haven't defined the flags so flags are something you know we can define here as enum flags which has var flag none which is zero where requires have this value binary flag. So these are the flags you know uh like what exactly this variable have is it a variable that contains gradient or is it this variable is a parameter like it's none or something like that just useful computations so that's what it is require right and um yeah I hope it is recording thing my voice is clear and uh yeah so this is what so we are here right now define the matrix and then matt will have you know this will have a name value and then out val equals to val out grad equals to if it has a you know if I would just say type defum max it's just defining as 232 let's say if flags if flags uh flags uh if it is a bad lag cat then probably we also need to add gradient into it create metrics columns that's it I think inside this there's nothing else uh there's inputs so for that like I guess we also need to define the inputs um zero equals to a = to b. And it will only happen that if this if dot number of inputs contain greater than one then you have to basically store it there. And this number of inputs comes you know comes from type number of inputs contains them. Add this you know we also need to add type here which is like which we will get type and uh we will also I guess like model state is not required here. We'll just remove this and we can also remove uh I guess like when we are creating V like first time we will create so we don't we will not have like inputs and we cannot define this. So I guess uh earlier version was better which is like model state and uh this thing and uh type we can say null just say this. Yeah I uh that's it. Now we can just return the value we will define like the inputs and stuff when we we will create a node you know so out we we have defined and uh type because we haven't defined in here would be like this is working I guess and uh then we have to define node this creates the bar and we can actually go and then try to create it. Uh we can just go and where B is a v arena then model state is state. I don't know like why did we needed a model state here you know state model flags will be like zero I would say. So yeah it's working. Uh does it have a grab? it won't have a grant because like we have to write this well uh you know this model state that I just remembered like it will have a number of bars so when we create this thing that's why we need model state because index we can say it number of this will have a index right this will have a index so number of V model number of bars ++ means like as we create this var that will also reflect in model which is like a you know model will have it will actually automatically goes inside the model you know and then it increments the number of bars although like this limits the possibilities like if you want to create number of bars outside the model And but yeah, I think for now it's good. So V create V. This is done. This is working. And then when we have to create a node, you know, uh what does node will do? B uh node basically the graph nodes of graph you know because we have graph from bottom to like operations like soft max. This is it's itself is a node. This itself is a node. This is a node. This is a node. So as the computational graph grows it will create a node based on that. So that's why like we need to create a node and for that like we have to define graph uh which is like again a strct strct graph and this graph will contain you know u this graph contain the variables. So because graph is contains like a notes we can say like a notes but like instead we say like v and that where is a pointer the area of pointers. So you can say like also this double asterric is the uh the pointer to the location of pointers you know. So this will have bars and uh will have a size. What is the size of the graph? That's it. Uh this is the graph and uh matrix in the graph. What exactly is happening here? Why does I did something? Okay, I just did something here crazy which is okay because the model wise is is is [snorts] is null it's just definition is wrong but yeah I think number of hours will be going to a plus+ in this Um, I'll take a little break, I guess. You know, I should take a little break or like I should go create something really. Okay. So, so graph has no problem with this and okay now this is done this the graph is like we have defined a graph now node that node basically will give us the v itself you know create node and that contains v a and v b you know and uh because a node itself is a soft max let's suppose so it can contain bar a and bar b and uh can have like a model state can have flags no 32 max that's it um so if inputs and it will have like a type v type type and this type will be basically a point so this uh will create a node sorry create a this bar basically arena and stuff will have like the VA A and V B model state for and then okay got it. Um now this var type you know if type is type equal equals to bar will have like type equals type if now this type contains you know this type contains shape. So and that shape is basically can have a b can have a and b. We have seen it like that function contains a and b a b columns and rows a b f this is basically returns true because it's a um this shape this v fun type is a boolean itself. So if this thing contains if it is true then that means that the shape is right of a and b compatible enough to the operation whatever the operation uh based on the type and uh if it is true then I guess like we can just move forward with that. Um so I have just do it like bar type shape and before that I think I have to define row equals to zero column= to zero and then we have to provide the reference of it and that will have the things but what we will do inside of this is like create a node and then model state I guess like that's why I like models was required. This is the right way is creating a new variable based this is based on this the the the goal of this create node is that you know to create a new variable and uh but that variable is already coming from something so variable A and variable B you know so that's why like it's not like independent variable like this so but I guess like we don't have to do that Because this is already doing inside this create v that requires model that's why like model rows column and flags we are making complicated a lot with this because uh you know so a lot of things we are actually taking here which is not required. So as if the goal of this node is to create a new variable based on the past A and B. So we don't need like a lot of information. We already have some information from A and B. So I guess like we just remove this thing arena we have model state v and this this type only. Now this flag we can just define you know we do flags as a bar flag none first right and then if flag if a isn't if a isn't equals to null and and a flags and required grabbed or r or b isn't equals to null and and E flag and where flag requires graph. So if this condition is true like means like A has this either A has like the gradient on or B has this gradient on then we can say like black is requires that you know I it requires only one of it because we are using R here. So this is how we can get like flag and uh for the rows and columns here we have defined it here rows and columns and then inside this if this is not true you know if if this type dot shape is not true then we can just return null and uh after that we can like create this bar because we now we have rows and columns. So this shape will you know I haven't defined the shape function but this shape will do some kind of like manipulation with this rows and column that's why like we are passing the reference so it will change the whole this rows and columns and then we will provide here so we don't need to pass from the arguments we already getting it by when you like because a and b you know is a this new variable is coming out from A and B. So either it is exactly their shape or like some kind of uh matrix multiplication they are doing. So we can already compute like the out shape and compute the rows and columns of the out thing out shape. So this and then flags right arena model rows columns and flag and then where type is type we can define it like this. We already had defined it doesn't make okay now if so we can also define this because it is coming out of A and B so A and B's are basically and we are the inputs of this U so if var bar v bar v bar v bar v bar v bar v bar v bar v bar v bar v inputs zero is basically a and if var dot type number of inputs greater than one are inputs to That's it. Uh this is this will create the node. We will return the awesome. This is this is great. Four errors which is like a flag. It should be flags. Okay. It should be flags in. Yeah. Should be flags columns and rows. It should rows and columns. I guess this wasn't the error. Incompatible pointer to integer conversion is give 32 star. What does it mean here which is it should have is working. I guess I should take a little break and then we can just come back and start it. Okay. So this is great. Uh next we have to implement uh the graph. So the basically the how we going to build the graph is we can build the graph using the output. So let's suppose the first is input and the last is output. So output could be like after the soft max and in between there's a matrix multiplication value and all these layers but soft max is basically going to be the last layers and that soft max we can put at outwire and then outwire that will back propagate and discover the nodes discover the nodes and then eventually going to figure it out. So I can just show you like I basically like this is slides I made. Um yeah like this is the graph like this will have inputs matt I I think it's visible right this input matt activation stop. So this is like the forward pass but you know during the gradient computation stuff it will going to be a little different because uh we need to provide we need to go backward. So we will provide the output wire and then it will discover the inputs because we are storing the inputs also. So it will go to the all inputs and then discover everything and then finds out like okay which uh finds out the dependency of the inputs and then compute the gradients. Um and uh yeah I think that's we have to do now for that I guess uh there's this thing called create graph return graph and uh it will have outline. So there's this algorithm called uh depth for depthwise traversal algorithm which will take uh the one node and then finds out the inputs node and then traverse back you know so it it will have like a stack so it will have a stack and in that stack we can put a lot of different things. So it's like this uh you know stack will have some you know we will put lot of things uh more like a b c d e all these computations and but it is going in the forward direction sorry it's going in the from backward direction so because we want to create this graph we will probably what we will do we will go out and Um using output graph we will okay let me explain again like so in stack we have this a lot of computation a b c and d and all the stuff right so these computation basically will have uh from backward so we are going from outward which is like out bar to the inputs so this will go into the from out bar which like the out bar wire will be here and then it will discover the inputs which dependent on the out. So that why like it's it is not in the right order. So we want in the right order for the graph to execute the forward pass. Uh and so there will be two kind of of these things and uh this will be one is stack and other will be out which will have all the in the right order whatever the right order will be. So the the first it will the f it will contain leaves first and then contains here all the output and stuff. uh I can explain you better if I have like I have chat jupitia asked about like to create the computational graph so you can look at those graph let me just pull this thing so yeah so let's suppose like you know you have this graph zed zed is the output and then you will traverse back to discover some of the inputs so zed is dependent on x and y okay and then x is dependent on a and b and y is dependent on b and c. So you will see like you know um you probably find that okay when you go in the in this direction you will see you will check the inputs y okay and then uh you will add in the stack you will add zed in the stack y in the stack and then add c and b in the stack and then check another input x then b and c. So you will actually create stack like this um from backward. But the problem here is like there's a lot of problems with this uh which is like here you can see like this y is also dependent on uh b and x is also dependent on b. So if you just like go in one order and then uh discover the inputs then you will basically going to have basically add this b twice. So you will have two bs. So you have to make sure that okay you are not adding the the same parameter same variable and you are also adding these variable in the right order. So then we can actually create the graph create a graph. So yeah, I think this is what we want to do uh here right now to create this graph like first we need to define some of the things which is like graph and this graph is empty here and uh some of the variables like stack that stack is honestly the pointers of point location it is a pointer to locate uh points the location of pointers the stack and this maloc size of bar model number of bars and same as out and then visited because we have to check like we are not adding adding the same variable twice. So visited will be uh P32 boolean visited um well this will have this will also be a pointer and like this and then basically You know stack will have this uh initial stack will contain stack size. Stack size equals zero and out size equals to zero. Stack stack size ++ equals to stack size stack size ++ equals to outl. Okay. So this will contains the outbire and then we will traverse back you know wire. So I hope you understood this like which is this is a post increment thing. So it is exactly like this stack height. So initially it will get the value of like zero with index stack and zero with index we are storing the out bar and then stack size increasing after that. So stack size will become one. While stack size is greater than zero, what we have to do is like we have to go and then pop out the stack. So by current and stack stack size, this will pop the index. So this is a pre-increment. So it will turn to zero and then it will index. So this current is stack stack minus minus stack size. Then what will happen that we have popped out the stack size is zero. It has zero length. But um we can actually see if this current dot uh current if this index if this um visited current dot index if it is visited then just add in the output you know add the out add in the output out don't go further just continue because like we already so as we have seen mean like okay if it already visited this kind of a thing then just add into the outsides and continue u otherwise like just go and do more computation which is more computation which will be like just discover more inputs. So let's suppose what we are trying to say is like you know if you have not visited this thing you discover more inputs and if you already visit visited this variable okay don't discover this okay we will add add this thing into the uh output I hope you're getting I I know this is not kind of makes sense but like when we actually run this create graph you can actually understand we will see like what exactly it's doing through the output So if visited current index out out size++ current continue and uh and then then then then we have this for use 32 I = to0 less than input size. So we have to like find out like the inputs which is the type is not null type is not null dot type will have number of inputs otherwise zero. So if it is inputs I less than inputs I ++ input is okay. So if this input if this input is um if this input is less than the input is we have to like iterate uh for U32 a =0 J less than ST it will make sense like I'll explain what I'm trying to do here I J equal if it is like equals to that means like it is like a duplicated so because like as we have seen like X also had this B variable able Y also had this uh V B variable dependent on. So both shared the same variable. So we need to make sure that okay one is only added. So first when we discovered X we will add the B. Now when we discovered Y's variable the variable of Y we can actually uh update B you know we can replace the stack. So let's suppose like this it will add X Y by B let's suppose like this B and A right so again when it finds that you know Z now in next iteration like it if it finds like Y is also dependent on B you know B so this condition matches okay this is actually already in the stack Right. This is already in the stack. So it will going what we need to do is like remove the old position thing. Just have this in the here. So it will re basically remove the old thing and then have this in the right order. So only one B is going to be there. That's what we will going to do. Um it's already there. How we can remove this is basically we can shift the order. So let's suppose when we discovered this you know this is here. So we can just remove this and uh shift the order. So how we can like do this is basically we will just go iterate k equals to j. So we have discovered this at the j position. So we'll start with J and J will go to the stack size minus one and uh K++ and this will what will what will happen that stack of K equals to stack K + one right so the K + one position will become the K position so Yeah. And then here we can just do the stack size minus minus. So one position like because one position is already shifted to the left. So reducing the stack size also and that's it. Um what else is needed like we haven't stored the inputs. So this was the input right? and uh stack stack size ++ nice that's it like this is the graph um so it will run the this traversal until the stack size is not less than zero and uh pop up the st pop the last um last thing in the stack and um finds out if it's already visited. If it's not then uh continue here. If it's v visited already just add into the out um stack and this input is basically will discover the number of inputs and then I trade over the inputs and then I after I trading the inputs let's check like whether we have already uh added this in the graph in the stack if it's not all if it's already added then reorder the position and then remove the last one. So kind of a graph it will have you know and we can see like uh we can print it that will give a better idea. So first let's let me define the model state you know I don't know like why it is not getting initialized in the right way I guess. Uh okay this is done to be honest like I wanted to check like this thing but we haven't like defined the model yet like so we need to first define the model and then we can use that model to define a model state let's define the model uh let's see I'm going to basically copy some of the things here just the imports because imports is like difficult to manage stuff um in C and uh yeah to include base arena matt we don't have anything in that I guess you can define a m dot c m okay okay nice uh this should be let's define somewhere else also okay so I'll be doing because of this it should point it the input is coming from the current so not from here you So here we can define like the actor model just this will give us model actual model because we are going to use re uh reinforce only not spo and stuff right now which I thought to actually also implement this but probably this were going to a lot long so yeah let's go with like actor actor model only it's like simple not do much in this. We don't have a value function in here which is great. Um but it will be very um high variance. So make sure like when we were going to train we'll see like a very high variance and it will train in a very long time. So yeah I think create actor model model state model it will have you know the weights and stuff. So where input arena I guess model uh the input will be so we are going to create some uh kind of we can create a graph later on. We can create a graph later on. Uh so when we have like a model state defined what we can do right now like and we can uh finish this function which is these things. So you have actually just noticed that it requires a var type you know. So for that V type I'm going to define the V type here which is our soft max which will have number of inputs equals to 1 dot name equals to soft max and uh I hope like it's the right syntax number of inputs shape will be okay we haven't defined the shape you know so there will be two functions actually which is v32 which is like boolean and bar shape this will contain the bar a b and column we will check if in this implementation I'm not checking too much thing making it simpler so we'll only check like if a isn't equals to a dot rows isn't equals to b rows or our a columns isn't equals to B columns return false because this is a same shape thing. The function the goal we are trying to achieve with this function is that it should have a shame same shape and uh this same shape will going to have also update the rows and columns. Because these rows and columns here you can see like when we are creating the node we are calling this shape thing and we are passing the reference. So this will change the rows and columns here which which is defined as 0 0. So it will change to the right column and stuff. So this we will dreference this and we will update this as a row and similar to like where where a b now in u the matrix multiplication it's kind of a different so if a rows isn't equals to a columns isn't equals to b columns. Oh my alarm is when did I have alarm? I did have alarm like I I didn't know like I had alarm. I always I guess always had skipped. This is the first time I'm discovering. Anyways, it's 5:30 a.m. right now happening though. So if a columns isn't equals to uh b columns and uh so it should have like this kind of because in matrix multiplication you basically compare with like the first dimension of the matrix last dimension of the first matrix and the second dimension of the first matrix. If it compatible with this then it can only do the matrix multiplication otherwise it can know. So return false and uh dreference this rows and change the parameter will be a rows and columns will be b column. This is it now. Yeah we can pass these things into here. Don't I I hope like I'm defining kind of the same. I have to check and then forward function which is going to be you know soft max forward function and uh dot backward function will be soft max backward function. Okay. And uh we can define the same thing with other also v= to dot name although let's check like if it's compiles. Wow. Because because because because it is giving errors because the thing is that it is a var you know so it will have valed here so we can also this should be void wait this should not be v okay so I guess like the the error is basically because of the signature is not matching with this error is because the bar softwax bar. Okay, so I found it like what exactly the error is. Um you know so this is just a definition right now. Define it not coming right now. This is good. Um now what we can do um we can here we can here define these functions you know um we can put information inside this function where softmax for this will basically do the softmax operation. So you know soft max operation we can just define it here which is what is soft max operation if if you just think of it for u32 inputs uh right we'll have inputs and uh so we can actually define size so u 64 size equals to you know and iterate and compute the softmax so I've already like did some define the actual thing like this is soft max and this is the formula really this is this and policy gradient like reinforce this is it so you probably have familiar with this I guess um and then what we're going to just do is like we will iterate over this Z to collect the Z I and then compute each of the uh with each of this element and similar to all those goes you This size will come from bar columns and then go to size I ++ if now what we have to do is like okay we have gone into this size now because if you check this formula I hope I'm recording this if you check this formula you are basically doing the max of zed so first data like a max let's say 32 f32 okay and then we can do uh this should be the output of it so I guess like we have defined it the right way input is the data which is the I will store the formula I check it was the I guess the max value like this we have to just do the uh sum and then We can divide this uh with the thing right. This is the this is this this is the thing we have to do um var val and uh this is only for max value then i then we have to do the sum because you know uh we also have the sum and then we'll divide it with the um we will scale this later but like let's compute the sum first and then we will okay let me explain this again I guess you haven't uh really got what exactly I'm saying to to compute this uh softmax forward uh what we need to do is like you know we have to compute these formula and it's it's simple it's not really difficult so because we are we have this V we can get actually the inputs so like this Q3 we can calculate the size which is the is the which is the bar val columns and multiply by R valu like it this is not a mattable operation so I'm just like doing val I'm just resting on the val otherwise like I have to I can take take this from input as well so for 32 I zero I go size I ++ now because if you see this it's basically like we have to compute is in element wise where the uler has the power of like zi minus max of zed and then it is normalized with some summation although the this is exactly the same like this equation and this equation is same it's just like it is summed over it. So the easy way to do is like you basically I less than zero you you do max value do max f32 max value is let's initialize with this bar inputs zero is also a val right input is also a val I forgot that like input is also a bar so it will have a data. Now this max value going to be changed because like we need to find the max value. It can have max value on like this thing. Now again go for size plus then the sum you know. So sum will be to do sum and which is the this function which is we are trying to do is and what is the function name uh it's x f you know um the xf and it will basically if I just and z i is basically you know uh is the input so this we're going to store in where this we're going to store and var val data I and so the upper part is done like this will also compute the upper part and then with the sum we can compute this um and then we can actually divide it you know so how we can divide it divide with the sum so go with the U32 I = 0 size ++ then that's it this is our soft max. This is our sort max and exactly this is going to be for the value also that um you have the size then you iterate it over it and uh in this iteration I hope like I'm audible to yeah in this iteration in this iteration we can just like go and then see what exactly is happening like because really is basically turning all the negative thing to zero. Z and then all the positive thing to whatever the the value they have. Right? So if the data if the V dot inputs of zero it will also have the only one input which is zero. V data I is less than zero. then v input v val data i equals to zero. Else if it's not like this v val= to inputs whatever the input is just store there and it should be inputs. Now for the R operation, it's R operation is good. It's not very complicated. So again the size will be this. And in this size we can just say you know if val data I = to bar inputs zero val data I plus v inputs zero val data I should be one. So we have element wise addition right. The same goes with the sub also. We just going to subtract it here. Now, Matt Mull is kind of very very different because it will have you know a lot of things which could be a transpose non-transpose and stuff. So for this one like we will define another set of function. Okay. So, so the batmo is kind of different here because it will have a a transpose and different kind of stuff. So, what I can do here is like no here we can define another set of things which is matrix. This matrix multiplication we will have uh you know we are not going to take anything out from the function we can just actually means no transpose in either side of it so it will basically going to yeah I guess like we don't need this kind of a thing void because we are passing the out metrics matrix and uh a matrix B right and for do I = to0 I less than size I ++ basically this uh this this this this a you know uh how we can compute the size which is we don't need to like to go in the same way like how we went through in the last add and uh soft max thing but rather we can call this And then u32 J = J less than matrix A to columns and then A++ for two we can say I64 because you know maybe matrix is bigger than ready very ready. K equals to we need three iteration because you know the first is the out rows and then we are going indexing on the actual matrix A which will help us the second uh second iteration will help us to indexing on A and B right and um the out which is again going to less than these three indexing which help us to it's going to help us to do the whole thing. Now I'm going to explain again. So white mat n this n is basically the uh not transpose. So to have this out matrix matrix out matrix A matrix B you know and if basically we can just U64 I = to0 we are just using U64 here maybe like matrix is very big although like it doesn't make sense why we use only U32 in earlier version but it's Okay, earlier version means in soft max radio we could also use the U64. It will go to the a rows columns. Oh sorry a out rows out plus i ++ you know. So out to the rows plus again J = to0 J less than columns J ++ for K =0 K less than it is K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K Z K less than out columns K ++. So basically these three iteration we are going to do to actually index the matrix. So if you don't know like the matrix is basically just the you know how we index things because we are not using like any kind of array we are just like indexing through the the the actual memory. So if you think of this is as a matrix then 1 2 3 4 5 6 7 8 9 you know this is a matrix row if you want to access the memory the location of this matrix the row major you basically mostly use row major basically and how you store the how you also store in the memory of the matrix which is the row major majority of the time which is like your flattened memory will be 1 2 3 4 5 6 7 like this. It will be like this. And the column major will be if you want to store with the column major it will be like 1 5 93 like like this 1 15 93 26 10 like this. So here we are using like a row major thing. So it has a formula to access the do the indexing basically which is like column plus rows number of columns multiply by number of columns. So row multiply by number of columns will happen first and then you just add with the column. This is exactly like you know this is exactly like telling you have this matrix M and then row and column and like probably you have used this in Python which is like slicing this is row and column right um so this is how you actually store these things otherwise right now we're going to use this formula which is column row so here's a twist Let's suppose if we want to transpose because you know if you know more about transpose if you don't know transpose is basically transpose is like changing this row to column. So this will become column and row and then so this thing will also change. So this will become row and column right? So this will change it. Now when this will change we can able to define functions like with if you want to multiply with transpose or not transpose. So we can also change the formula and use the right formula indexing thing right. So transpose and basically you it is exactly like a transpose if you do a transpose on i on k it is exactly like a of k and i. So here the out of data will be I + K I + K. So sorry I + J. J + I sorry if I just say J + I because J is the column and row should be here because if you just using this column plus rows multiply by number of columns. So ji columns equals to you have this out a data and uh which is k + i which is so here you can see like k is zero and i is zero the first index and then you just and if it's zero then basically this whole thing cancels out and you're left with like a k. So you K is become like a column for you here and row is zero. So here's like K is something that I able going to index over it and uh you're going to do the dot product with B then B dot product will happen with the J and K. That's it. Like this is the whole formula. This is this is the thing. Now the cool part is that you can just change the indexing you know let me check like if it is correct. Yeah it is actually correct. Now this map N can be like NT which is like a transpose the P matrix. So you just have to do you know what you have to just do is like you have to just change this order just I + you know so if you just change the order sorry uh I guess like I change the A of it which should be the here K + J then B is transpose. Now if we want to transpose this t and n then basically a should be transpose. So if a is transpose so the iteration we are doing over the k over the a sorry will become rows here. [snorts] So and this will also change i + k. Why it will become why it will become rows because you know it will also it is transposing things you know the A is transposing because right now we were actually moving over the A. We're using A to iterate but like A wasn't changing b was changing. So our iteration loop was exactly like this. But like right now our A is affected which was using which we were using in the um in the iteration. We can also use the B. So that will create a non-effect thing. But like right now it's good that we are using only A for the iteration. But as A changes, A is getting transposed. So we have to also change the iteration loops. Okay. So and then we can have like a TT which is like both are changed. So now it will become I + K K + J then also become like rows. Now we can just like define the final mat which is like a case of it you know matrix A and matrix B. Now this will basically you know end. Okay. So this is like just a zero if if all are zero then we will use this n1 and if n1 is true we can use this thing. So we can define like um case thing like you know there's one more thing like we can also say which is zero out if you want to do the zero out although like it's not very important and then we can just get rid of both because like if both are true then it's already going to be tt. So zero out will help us to basically initialize the matrix with all zero. Um so f0 out. So I initialize with R U64 and uh transpose transpose A or transpose B if it is kind of a situation then switch and then I can just copy this case that going to be. Okay. Uh this is this now we can utilize the same manual here. We can say let me just check if we haven't made any mistake. Yeah, this looks fine. Let me just fix this quickly these errors. Let's implement this reinforce forward which will be the the computation of the log and the returns right uh it will be the logs and the returns. So the log of probabilities basically will be I can just copy it from here size right and in that basically what we can do is uh to make it more safer because we will get like a probability from the inputs. So max of either one that's zero one this is the uh this is the max or basically do the one will be the returns this is rainforce forward okay now we have to compute the backward passes and stuff so backward passes the gradient we have to compute it's very simple uh also like it's not difficult I have added what will be the loss. So you can see like in the for the reinforce loss the grain will be like GI times the RA I which is the reward here divided by PI and negative. So and really for it is x if it is greater than zero then ti it's like the the previous gradient or the evaluation gradient of value or if it will be going to zero and then soft max gradient will be this. So yeah, I think let's let's compute this first. We have we can compute the reinforce gradient and do like this and if I guess this should be 64 to only use 64 and uh and then over it and uh grad will be TI is basically the grad. We can also uh do similar kind of thing here as well. what we have done here because I think you know if and wire if this is like this you know in the input uh this is getting very confused you know but the thing is that I want the prob should be the uh gradient you know so input will have is input will have this this zero index is probability you know so val I can say cra I guess this is something like this I think you know it's basically a transpose so if you when you do when you do uh matrix multiplication it will going to transpose so for the gradients you know I will do much better if I just if I can just do it like this a and b and we have to compute the gradients of a N and B. So here you have seen like we haven't computed the we haven't computed the gradients of inputs two because with input two is basically RT which is the minus R it's like reward here. So we don't need like uh to compute the gradient of return. It'll just it is just a weightage. So we can just leave it and then we can only compute the gradients of the probability which is the probability of given action and state probability taking action given state you know. So if variable this flag a we can just say a flags then we can do match we can pass the ban inputs zero b transpose will be because it's a so transpose b will be transpose here to calculate the gradient uh for the a having the gradient of a will be basically going to be the transpose of AB. So AB transpose B transpose and this here A is transpose and B. I hope you're getting it. So yeah for the addition it is basically the addition. Yeah. Now we have to do the same thing which is like addition and uh put the entire thing in here. It will be not just like plus equals to but rather okay here we have just did some kind of a mistake. It just it will be crap. No it is fine. Okay. So some errors which I will solve here. 394. This is for the A and same goes for the B. So B it will be this B is B going to be one one and that's it right like for the subtraction I think for the subtraction it is also kind of a similar I guess it's it's it's very similar because but here it will going to be negative we can change this to now again like this input equals to only one input put okay and size will be this size is you know this size is uh and in this input what we're going to do is like if equals = to zero is greater than zero this otherwise this y can also add one more thing which is like a floating point right and it's going to be plus equals to okay now we only have left this soft max. So the easiest part about this is that the vector form this is uh our equation which is like a dotproduct of g and s. S is basically the soft max data and G minus G is the gradient of the the bar and uh G minus G multiply G dot product with this and then soft max data again dot product. So let's compute this dot product. Going to take this and uh also going to take this I will say dot because you know we want to use the softmax data. This is the dot product it will do. Now again we have to do but this time data dot product of dot dot s minus s. Okay. So I hope the computation is right. Okay, we have implemented everything now like all the things which we have defined as a function. So the next what we have to do is like we can start building up a model you know because we have built all the things required to build a model. So we can start building model and for that like model C. Okay. So we have implemented this autograd thing. Uh now let's create environment um or we can create model but I think uh I want to create environment first. So environment let's see is this the here we probably going to do is uh create some strct and enums. So let's first understand what kind of environment we are trying to create. We will create a snake game environment. I think this is going to be a really simple one and this uh which can actually have some level of difficulty also which have reward structure where the snake will get reward and if it hits the wall it will get penalty and stuff. So this will going to be simple snake uh simple environment. So let's go just going to have like actions action left uh left will be zero right will be one up two down three right uh this is going to be action now snake env this will contain a lot of information like you know state uh which which has a state uh variable type so this state variable type will be Drop right and this state is not state it's snake state food what will be the state of food and uh score score will be at 32 score and uh action will be POV like what exactly the point of view because snake can point because in snake game you probably have seen like snake has a point of view it goes in one direction then we if in keyboard like in keyboard phone when you press the low button down button then it POV changes and then it moves and downward. So something like this it's basically the point of view of the snake. Now this is the action POV and then what we'll have POV that's it I think what else we can have this current state will be snake state food then score this yeah and uh then we have like this uh type defct I hope it's recording I guess yeah it's recording type defv then we have a replay buffer you know because in reinforcement learning You probably have like heard of this kind of you play buffer where you do the gradient accumulation later after doing the roll outs. So you do the roll outs. So I can explain you like this. You do the roll outs. Roll outs you do the rollouts is basically collection of data. Collection of data. you do the roll outs and then after doing the roll outs you do the step gradient step using that roll out. So you collect the experience. So that's why like ARL is uh is basically doesn't require training data because it generates the training data uh the pure AR thing. So this will generate the data the experience from the snake and then we will use this experience to correct the agent's action. So we need to store these experience. Uh that's what we call like replay buffer strct. This replay buffer you know will have um a lot of things also. This snake game will have like a rows and columns and grid size and action POV and number of steps it had took. So use 64 steps. This replay will have you know the first is like trajectories and this trajectory is itself a shock. So let's suppose the buffer size is 512. Okay. And uh episode length because episode is basically snake is collecting the uh states and actions in a single game. So it goes to x0 y 0 like the coordinates x1 y1. So it basically navigating the environment. So how many steps it is taking in a game is called episode length because it cannot like take forever. We have to like it can take forever. It can just like take uh until it's win or lose. But like let's define a definite uh uh steps. So it could be like 200, right? Or maybe like we can define more let's go with like 100 and uh this can be,24. Now this trajectory you know this trajectory contains a lot of information which is like states state episode length state it states which is like all the states the snake went through and this food states episode length action and all the action it took and uh action what is the POV episode length rewards and returns. Um F2 returns and uh state next state because we have to store the what next state it went through. What will be what was the next state after taking the action and uh next states and done like is the game done? Do we have a result of it? So not then we can actually iterate again and again and again. So this is some kind of abstraction layer in trajectory we can say 32 count right and here we can also say length. Now this is the abstraction define what exactly is exactly is this error just pass the chance why we getting this error now the error will go away now create the env. So this basically create TNV will take a because we are not like defining this in arena now like it's very array kind of thing. So here like in trajectory and all stuff we haven't used any kind of a pointer thing but that's okay I guess like let's go with grid size rows will be two side because it the grid size grid will be a square so we can like qrtf and uh grid size right and this 32 call equals to side same thing then This will have like a columns and rows and then we can define like snake take the push truck which is the arena itself and the size and all stuff. So I'm going to go like there's other ways which is like maloc you know we can just take and say size of this thing size of CNV but like let's go with like arena arena arena and now 25 or 36 let's go with like 36 okay created the env you know snake dox equals to zero that's how we can define n dot c 0 and uh actual po right so because it's starting from 0 0 so 0 0 will be like top left bottom left and then in the x and yax x and y graph so 0 0 will be like a top b Sorry bottom left and then it can POV towards the right. So this will define the ENV if we can actually enter the print enter. Okay. Why we were doing this? Damn. What exactly is this? It should be zero, right? I think it should be zero. Um I guess like you know we have defined in a wrong way we can defined like this uh which is much better this matter is like this why it is getting like this long with this damn it when we are returning env that's it small small mistakes okay so now this is done we have created the env U this is our env and uh we need to find the you know we need to reset this state also. So after episode end we need to reset it reset again like this going to be like this but we can make it more interesting here which is like get random lock. So this will give you the random food location based on the number provided number provided which could be uh so I'm not doing any checks here so just to make it simple but you can just think like okay there will be a check which checks the range within the range of like grid size and rows and columns. So if there's function random in the PRNG this file which is which is which is which is this function define it like this this will be I32 because this can be negative. Yeah. So that's why define this side here why the Got it. Got it. Got it. And same here now. Okay. Okay. So this reset uh env is done again you know you can see by passing it we are getting random. Now taking action we we need to make sure that we are taking the right action in the environment the valid action. So we have to define that you know action this will basically have snake game will be action. There will be one more action here. Okay, that's it. I guess there can be one more action like which could be none like no action. Okay. And uh take action. If a entaction if action equal equals to write you know action equal to none action if action is none then action will become you know POV env is POV like because we are not taking the model decided to not take any action. So the POV the whatever the POV of the snake will become its action you know. So just take action make push snake in the POV direction because snake will going to take action at every tank step with its POV. What the model has to do is to take action to prevent it from hitting the wall or like to get in the direction of food. So if action is none action this this action is right envo to action whatever the action was okay that's it in the else we we can return action is tide The snake position would become should be one nice one. And if it's left then it should be minus one. And if it's up should be the y should be okay. Y it's been a lot of time. So yeah. So this is working right. You know what we need? uh we need to build uh some sort of [snorts] vector which is the some sort of vector in the sense because you know you have this inputs and math and stuff like that. So this input will be like some kind of embeddings and some some one hot coded vector which has all the information about the snake world or snake env you know because we don't have any kind of like input like text or something like that but this snake env world which has a lot of information like where the snake is going what's POV what's date and all stuffs it's actually a lot of information so we will provide this as input to the model and model will actually find patterns and observe it and produce an output based on that. But we need to convert this input in a right way so the model can actually understand it. So uh the best way to do so is to create a some kind of vector right. So build state vector which contains some informations like which has like metrics and state and then state of this will be state of snake and food and uh action what will be the POV what is the POV of the action and uh column right uh now to compute the snake I we know the formula of this this column row in intro major thing. So in a grid size like we are storing let's suppose this is the state it will have like for 0 0 0 0 0 0 0 and then for like grid size till the 36th 36th of 36th of this thing length or I can say 35th because if we have like 36 grid size we have like this kind of a state and snake eye will be you know one here and one like if the x and y is like this. So this will have some kind of a information in our flat vector and we can do this same with the snake um with the food also you know snake position it's like a one hot encoded thing and then for the POV we can for the POV it can have again some kind of a similar similar similar vector which can actually have some information. Well, we are going to create a very simple simple vector not very like kind of a embedding type dimensional thing. So just a one hard code which has some information which can actually help the model to absorb it. U snake I which is uh this columns plus rows rows is basically U32 snake columns will be snake doy right and uh multiply by and then plus like it's little bit weird I would say but I can define it like this X state doy that's kind of different here but like it's Okay, columns is x. Sorry, I'm just got confused in this state.x and then plus state snake snake doy then multiply with columns. This is the right thing exactly with the food and then we can store in the inmetrics which we are which we have here which is the input matrix data snake I to snake 1 0. So whatever the index of the snake I will have like a 1.0 floating point and in data I size plus 0. This is a flat vector which have like a you know uh in Python or like in other matrices we in numpy we actually see shape like this you know where we have this three three inputs and then the grit size but here we we have platin thing right so three into grid size so this is exactly our input vector there will be like a another function which will help us to find the reports Because you know we have defined the take action but we haven't defined the reward function which help us to get the reward. So when the agent will take action in this let's suppose if it finds the food and uh finds the food of the state uh then we have to give them a reward and if it hits the wall then we have to give them a negative reward. So right this will give reward and it will it will have snake. Now if env.x X dot snake dox greater than less than zero or R env dot env snake dot y less than zero r env if it is like this you know then give them a negative reward or something like that right rv snake dox is greater than the env rose or or we could say to i32 and if it's like greater than the envir f32 give them uh basically minus min - 5 okay 5 1 0 f now if it lands on the food if snake dox equal equals to envood.x X you know and then envake doy equal = to food doy and reward give them reward like + 10 f these are the two things basically um now it is done um like it will get the positive reward here but like now we have to when it eats the food when it actually lands the food we have to give them a new location to this uh food. So that's why like uh new food will be we'll do do while do while new food equals to state get location close. Okay. And if new food new food dox equals equals to inv snake.x X and and and means like a we don't want like where where the position of the snake is we don't want the food should be again come at this position so we'll just like okay if this is the condition is true then you know run again iteration and find new food a new location that's it uh that's it I guess and uh yeah have record and then turn rebar. All done. We can actually train this uh simulation this environment you know we can simulate this environment and train the model. Uh we haven't defined the model yet but it's okay like we will define later. So here we can actually create a training pipeline. Training pipeline will be simple also. won't have much uh there like you know in training pipeline we we have this training of RL and in training of RL you basically do rollouts collect experience you will compute the returns of this compute the returns of the roll out and the buffer and then sample experience from the buffer and then train it this is the whole pipeline of the RL training you know so void train arena I guess like there's no arena model state model and uh snake env me arena there's this arena I don't know why we need arena we need to create here but okay uh the first thing we have to do is like you know we'll do the forward pass and we haven't defined the forward pass you know because uh throw out will do the forward pass and stuff. Well, I will just you know uh for the ease of this what I will just going to do is like I will paste this epox size episode length and gamma which will help us to basically these are the hyperparameters and uh let's see if it's compiling. Okay. Uh we'll we'll see this later. Here we need to do is like forward pass right and backward pass right. This forward pass basically will have arena I guess arena. No this forward pass will have you know graph. Now U32 is the size of the graph of dot. This will be a pointer and then U32 I = to0 I less than size I ++ F. Now iterate the Iate the size. Uh what else we need from here is access the V because you know we the graph will have that build graph we had here create graph. This will give us the graph from the forward pass and we can use this to write where it went. So we have to iterate over this I compute the bars location right dot type parent dot type which is like a itself is a bar and if it doesn't have a type type isn't is equal to null return otherwise just to because it will have a forward function type and this forward function you know will need a bar which is again see yeah that's it this is the forward pass but the backward pass here uh it will be exactly kind of similar to this but if uh if this is not true if this is not true then what you have to do is like continue and if you have to continue again and if it is like a bad require ire grad as if it's parameter which a bar require grad then we need to clear this thing uh it's grad so this will clear the gradients the gradients so clear the gradients and uh then you can use fill uh I guess bill is there then fill the graph r² minus one the last variable should be 1 right uh So fill the last variable last gradient last variable's gradient to 1.0 0 and then traverse back. Basically I 32 I 64 = to 0 less than I I should be sorry I should be graph I g 0 I - traverse back and then you know where where and check if it has gradient gradient then you know current equals to zero then continue if current dot type type isn't equals to null and current type back over isn't equals to null. I can change to current because like we already defined C uh okay so it's good we have implemented the backward pass is not defined uh you know why is not defined because copy this there's some function we can actually import we can define in which basically fills and fill the random we don't need this random thing okay is compiling then in the in the arena or in the ENV you can go and train it proper. So this will we will do like a roll out experience collection. So 32 I epoch equals to 0 goes to epoch ++ right and then in this epoch we probably will do forward pass. How how we can do forward pass from the model because we have model right. So but I guess you know in here model state when we have defined it has only these things. So it will have forward graph VR graph output. These are the things model state will have. again go for J =0 I less than roll out size I ++ this will be roll out now we need to take a step in the environment so let's generate an action first let's see like if it is working or not so we can call train model state so this training function is working right uh then what we have to do is uh what we have to do is roll out sizes and then then then then in here you can say model dot forward graph is equals to build create graph and uh you know the create graph what the create graph will take arena model state and outvar the out bar will be you know and the backward graph will The order output this will be a cost that's why like we need to define a cost here it is null so it will probably will give this uh auto graph return a pointer of graph and this is not done yet we have defined this graph as this I guess you know we don't we can change the definition of the model state that we don't need this and uh this will graph dot because you know we are actually adding in the out of it here out so the graph dot varss will be out now the graph bars is basically not defined yet push truck push truck or basically we can do there's this another thing which is push array int uh it will save some memory of it but basically just not initialize this array like others like you can see it is true true means like it initializes everything with zero but it doesn't so yeah v prop isn't equals to null means it has space allocation equals to graph dot = to dot number of hours equals to out size and then we can just do me cpy to move the variables locations pointers to here from out size of will be and then we can just free the stack because it was a temporary location which visited is not number of hours. So the issue is uh issue was coming from here this this kind of a issue because you were defined after this I'm using here so that will resolve issue and uh okay so this is done uh now what else we need here we haven't defined these functions you know so by softmax which basically creates the the variable of softmax so we already have this create node so There's not really needed for any kind of logic. Just need to call these functions, right? So we need to call this return it and this uh takes up some input which is arena model state var variables. Okay, that's it. And then v type you know a and b is basically input null v type we have defined it right we haven't defined that thing we haven't defined the bar type really oh wow we have defined the bar this thing and rel for the rel dot number of inputs equals to 1 dot shape equals to v same dot Forward view type it will be exactly like this. So this will be M two inputs where shape M forward audible. Yes. What is this error? V type of max. We can find this. Let me search like why exactly I'm getting this error. Okay. It's again like the same issue. I have to put this in here. So this is a big issue. So what I will just going to do you know I'll just define definition here. So it would be better. No it will not going to work I guess cuz it's started. So okay we can complete this non noun type. This one is this is nice. Uh so we were completing the our training pipeline in this we probably you know take the action so let's suppose the action for right now let's take the action of this thing you know print of action you this is the action this action is okay this is working I would say we have like a five action 1 2 3 4 5 Right. So it should be fine. Why sometimes it fails? I just don't know. But it's okay. Like we have this action and uh take action and this is the envir action x will be like taking this thing. If it does not take action then um Oh, got it. Got it. Got it. It can happen because you know is game over. What we need to do is like w 32 game env snake.x less than zero r. It's exactly the same. It is working right now. Much better way. But okay. So if this is true then okay. Yeah it's working. And when it gets minus one it is it. Yeah. When it gets minus one the game is over. Right. Uh see I'm going because it is like it's been so long and we haven't finished yet. So, I'm going to take this so fast and uh let's go. Let's go finish this. Uh okay this is uh how the game will over you know and uh every time we have to reset the state for every roll out size we have to take this thing and uh for the trajectory trajectory define a trajectory trajectory which is a buffer and this is this buffer you know it's coming from here and uh this has I okay now we can store it inside this trajectory the information 32 I I go to episode length okay length is I already defined defined but it's okay I ++ now in this um inside this we will take the action now we have state equals to env state next state food state okay action pub is npv. Now we need to build the state vector and inside this input model val. I hope it will work I guess because val is not a null state state loop state and pnv columns pnv rows like this it will going to fail because we don't have model right. So what I will going to do like I will you know quickly I will just going to copy and paste the model which because I have a model is simple it's nothing here so these are the things it has create after critic model which is basically arena and we'll take model and uh this is input and we are creating a bar of size like 76 and one because you know 36 is grit size and again 36 is for the hour uh storing the food position and four is for storing the POV you know. So this is 76 one bad none actually I we have five actions but like eventually the actions becomes four because you know if it is non action then we are actually defining it. You can see here action equals to. So yeah, even if it's a action none, we are actually changing the action. So it becomes code action. That's why like 76 by we have to add one more. So uh this weight weight zero is we are creating bar create for this 128 76 it's 178 um size and the bias. This is the bias and we are providing the flag of it which is a it's a parameter and also a require gratuit for the input. It's required none basically doesn't need to have gradients and it's not a parameter also it's just input. So and then we have this uh weight one and bias one weight two and bias two with like 128 128 hidden dimensions and the bias will have 128 one dimension. Okay. And then here we are initializing this with like f rad and all stuff. Uh which we had already defined I guess or if not then I think we have to define it here and we can import stuff here. Okay this this is that's why like it is so let me just like think like what exactly is the error. Okay. So the error is gone but I have to change a lot of things because the code I pasted it was different what we have created. So like different kind of function name and like parameters required for that. So yeah I think now we don't have any error. So yeah I think this is uh weights bias weights bias we created like a three weights and three bias corresponding to that and then this basically randomly initialize this things and um you know it will initialize the layers and uh z a is basically the the map of weight and input and then we are adding v adds using v add we are adding the the this thing set not a and b not. So that's why like we created this v mat where add v which basically creates the nodes and then do it will not going to compute right now it will create a nodes that what are the operations required okay so it will create each node like this and then similar to that we have another matrix multiplication with weight one and the input is a not which is the previous uh output it exactly like PyTorch we do in uh in Python but like we we are basically doing more scratch way and can see layers in front of it. So Z 1B is basically the bias again is added with Z1 A B1 and then this is the radio layer after to normalize this thing. And then for the again doing the matrix multiplication with the last weights and then doing the addition bar add and then we are basically doing the computing the probabilities using v softmax and defining a model output equals to output. Okay. And advantage is basically the it's actually none right now like it doesn't have anything just create a bar and does not have any information but we will add the information inside this advantage during the training and this uh cost is basically the reinforce loss we have so v reinforce and then basically it will have like a bar type reinforce and output and advantage it will have then the cost function is this right uh now Here we can now say no we can now say create actor model arena model now this will work okay so there's something which is basically doing some sort of you know we can use uh coding agent I guess to other it will take a lot of time so we can just say like okay what exactly is okay. So these are basically the errors uh which is like null but we have created the model isn't it? Okay number of bars equals to zero because number of bars are basically kind of this condition we can actually have to secure the model. Okay, we have allocated more memory. Now let's see. Okay, but this is exact. Okay, I got it. That was mistake. Okay, so the major issue was basically here as I was like very confused on like you know maybe like we needed 77 dimension because like we had five actions. So I thought like no okay it's only four I guess because like action is but it is actually going to be 77 uh that was making the issue here and now it is actually working fine and uh yeah this uh will be cost graph. Now if you just run the training okay build the state and uh now let's finish this quickly. Um we have this uh arena env there's this you know we can sample the action uh using our probability distribution right now but let's not focus on that let's build the pipeline first take the action we can take the action now we need to store uh the store the all these things so if uh before this we have to like f2 report at reward or if this thing is reward. Uh now this give function we are getting here reward then we can actually score plus equals to reward right and then done will be calculated like here and then next state is basically n snake after the action. The previous state was the like this you know then trajectory we can actually copy this and it will actually store all the information states food states POV actions reward and all stuff this will store the informations there's no words there's no rewards okay there should be a rewards yeah you can say there's st because it's trajectory we that I'm creating over uh done done is actually there's still more errors trajectory. Now this roll out is done. You know after this roll out this uh roll out is done. What we can do is like we can compute the returns compute the returns like because what exactly the returns of each thing returns that it's going trajectory of 0 to episode length and we will compute the returns which returns the sum of all the reports at each step in a trajectory. So I guess like this is buffer count. It's not very efficient way to do so but like it's okay. So this trajectory gain the buffer trees F32 GG is basically return 0F or 32 32. So you know in advantage is you basically go from you go from trajectory length to zero and then computes the trajec uh the returns at each step. So t equals to trajectory rewards rewards of t plus gamma returns returns of t. I can uh basically paste this algorithm. This will go to trajectory and computes the using gamma. Gamma is basically used for is a discount factor and then trajectory returns is g and then sum return sum. We haven't defined any kind of return sum here but like so we don't need this return sum return square some yeah it is useful like u standard deviation calculation sample count uh that is also not needed average return well we can actually define this thing do average return which will be outside of this Let's print this. Uh we will going to we also have to add this in our buffer. We are getting returned which is like a negative. So our snake game basically snake is getting killed every time. I don't think I can find any positive here. Can you find any positive? I don't think. Okay, this is good. What else we need? uh we have computed the returns now it's time for to compute the gradients and all stuff which is like actual training thing isn't it so we will going to go again and backward pass in that backward pass you know we have computed this thing which is clearing the gradient clear the gradient uh so again like we will do this before computing in the gradients we have to clear it. So 32 I = to zero. I will go to graph dot size I ++ and then there's no model.graph. Okay, this is clearing the gradient. Now what we need to do is like again this is a training phase. In this training phase, you know, uh what you need to do is like just go through all the buffer. buffer count is basically the rollout size. So U32 I = to U32 and then go to the trajectory is the trajectory iteration but here instead of absolute length we will go trajectory dotlength. Okay. And uh again build the vector build this vector. And this time the state is coming from trajectory trajectory dot state of I and trajectory state pro trajectory. Now this is done. Uh what we need to do is like again clear the advantages. So for U32 I K equals to0 K less than the model dot advantages this will go to the I we just want like because we will compute the advantage so just get rid of like the old advantages thing. So advantage now to compute the advantage it's simple advantage is basically trajectory returns of t minus the baseline. The baseline is basically the return mean and some okay this is basically the return mean. How can we compute this? We can compute this uh average return. we can not average return we can just say to return mean okay and average return is kind of so for the return mean I can uh like there was this sample 32 samples number of samples zero and uh return sum average return is basically something else you can just like remove the average return error and put this uh inside this number of samples you know in a trajectory and uh return sum plus equals to g that's it and then after that u number of return sum f32 return mean is sum is sample number of samples So this is our advantage and uh yeah this is our advantage and then we can just model advantage equals to advantage right. Um this advantage is basically val trajectory actions. Okay, that makes more sense because you know so there will be five accents so five index for it but like it will only store whatever the action it it took. So it will only store the advantage on the whatever the action it was. So action actions now just do the forward pass with given the model dot forward graph and then do the backward pass given the model backward pass cost graph actually. Awesome. This is actually computing the gradients. And now after doing this uh after computing this optimizer step we have to do the optimizer step. Gradient scale is learning rate divided by 32 samples count right. Um now what we have just done here have to do the same thing and uh inside this the gradient current data will be into gradient scale. This will take the gradient. Well this will just the gradient scale but we need to also subtract this. So it will also going to subscribe subtract this and subtract current val width inside this the out matrix will be current val current val width current gradient sub will be not defined I guess because sub is where it is in the autograph can say like this this is actually working now and this is the whole implementation of the reinforcement learning from scratch and see and I know probably I have made some of the mistakes here like implementing in life some of the few things probably although like the library is pretty big uh what I actually built but it's a very minimal implementation of it where I just try to get rid of lot of functions and try to attend everything in a single file like it's going 400 500 lines codes in some files is so I try to attend everything not try to manage everything not try to check the uh safety checks and all the stuff so it was like very minimal implementation try to simplify this and I hope this made sense so I guess like probably I don't like this will learn but it will going to learn probably like if you just like leave it for like 20 30 minutes it can find So you can see right now it has started getting positive rewards after uh I adjusted some of the things and improved logging system and stuff. So you can see like the returns are like positive earlier it was negative um negative negative negative negative then started learning and I trading it I trading it I trading and then become better so reinforce is a very like unstable algorithm you can say because it has a very high standard deviation but still it can learn uh it can perform really good uh when you actually train for longer time and it can figure it out. So yeah, I think this was about the reinforce algorithm. In this video, I thought to actually implement also more like um more algorithms like PO and um the the versions of PO and stuff. But I guess like it this video is going very long. So I'll cover this in next few videos or like in any other project. But see you next time. Bye.

Generated algorithmically for Search Engine Indexing.

Summarize Another Video