<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Yash Patel on Medium]]></title>
        <description><![CDATA[Stories by Yash Patel on Medium]]></description>
        <link>https://medium.com/@yashpatel_86510?source=rss-68694da71a5f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*___MnwCLk7NXM6xZIipDBA.png</url>
            <title>Stories by Yash Patel on Medium</title>
            <link>https://medium.com/@yashpatel_86510?source=rss-68694da71a5f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 12 Nov 2026 14:04:56 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@yashpatel_86510/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[The 4-Hour Workweek: A Discussion]]></title>
            <link>https://medium.com/@yashpatel_86510/the-4-hour-workweek-a-discussion-f38244d36e33?source=rss-68694da71a5f------2</link>
            <guid isPermaLink="false">https://medium.com/p/f38244d36e33</guid>
            <category><![CDATA[tim-ferriss]]></category>
            <category><![CDATA[books]]></category>
            <category><![CDATA[4-hour-workweek]]></category>
            <category><![CDATA[review]]></category>
            <category><![CDATA[productivity]]></category>
            <dc:creator><![CDATA[Yash Patel]]></dc:creator>
            <pubDate>Mon, 27 Aug 2018 04:28:41 GMT</pubDate>
            <atom:updated>2018-08-27T04:28:41.794Z</atom:updated>
            <content:encoded><![CDATA[<p>When people talk about “self-improvement” or “self-help” books, <em>The 4-Hour Workweek</em> is often cited as the canonical example. And there’s a pretty good reason why.</p><h3>Objective</h3><p>Learn exactly what it is that Tim Ferris believes makes a 4-hour workweek both a desirable and achievable goal.</p><h3>Takeaways</h3><p>There’s not a whole lot of plot to discuss, with the exception of the brief anecdotes that Tim indulges himself in, so we’ll just jump into the takeaways.</p><ul><li>The 4-hour workweek is largely a goal if you <strong>exclusively </strong>use your job as a means of generating cash to engage in other, “more enjoyable” activities</li><li>Escaping the supposed drudgery of working a “typical” job means being efficient with time, cutting out distractions and being in an environment where getting work done is truly the determining factor. It also involves automating the laborious tasks we must complete but have little reason to focus on</li><li>Escaping the confines of a typical job allow for people to explore the world they otherwise block out</li><li>The goal in life is for continuous <em>excitement </em>rather than <em>happiness</em>, which involves constant development, rather than working towards a final ultimatum of retirement</li></ul><p>While I can’t say I fully agree with these takeaways, I believe this list captures the essential points of Tim’s work. My main disagreement, in fact, arises from one of the central theses of his book, that is, that we are using our job solely as a means of raising capital. Instead, I greatly relish the chance to learn more about my fields of interest at work and can’t imagine a sustained activity that would give me as much enjoyment were it to replace this daily work. That being said, many of Tim’s points still apply in my case.</p><p>Point and case is the cutting out of unnecessary time wastes and distractions, such as messenging and email, and block off times for completing necessary errands. Rather than interrupting periods of great productivity, these activities can be siphoned off into periods relegated to such activities. This is definitely a point everyone can learn and implement, regardless of what you’re end goals are, seeing as it will make you more productive in whatever work or task it is you’re involved with. Could be developing, writing, recording music. Working without distractions and switch cost of multitasking greatly improves efficiency.</p><p>In addition, Tim’s point of sustained <em>excitement </em>is a surprisingly satisfying answer to being the primary goal of life. Sure, no simple sentence can truly capture this age-old discussion. But of the ones I’ve heard, this one resonates with me the most. This is largely because I can hardly picture myself retiring. I can barely sit at home for two days when there’s no work to be done without trying to find a new subject to learn or explore. His conception of life as a series of adventures hopping from one boat to the next with no final land to end on is definitely an appealing one.</p><h3>Review</h3><p>With all these points being said, I still think there’s plenty to glean from <em>The 4-Hour Workweek</em>. You’ll see how someone who’s goals of solely earning money from work can manifest most effectively. And even if, like me, this isn’t the case in your life, there’s still plenty you can learn from Tim’s streamlined lifestyle.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f38244d36e33" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Shoe Dog: A Discussion]]></title>
            <link>https://medium.com/@yashpatel_86510/shoe-dog-a-discussion-a3c8a6e021eb?source=rss-68694da71a5f------2</link>
            <guid isPermaLink="false">https://medium.com/p/a3c8a6e021eb</guid>
            <category><![CDATA[books]]></category>
            <category><![CDATA[entrepreneurship]]></category>
            <category><![CDATA[review]]></category>
            <category><![CDATA[shoe-dog]]></category>
            <category><![CDATA[phil-knight]]></category>
            <dc:creator><![CDATA[Yash Patel]]></dc:creator>
            <pubDate>Sun, 26 Aug 2018 01:31:47 GMT</pubDate>
            <atom:updated>2018-08-26T01:31:47.013Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/324/1*mzWd3fGHta45NunyS2IONw.jpeg" /></figure><p>Few books give me as much pleasure discussing as Phil Knight’s <em>Shoe Dog</em>. While I strongly believe that different books hold varying appeal for different people, with some enjoying exploring the halls of Hogwarts and others learning the recounting of the troubles in Wall Street during the financial crisis, I strongly believe that everyone should at least give <em>Shoe Dog </em>a shot. Even if you’ve never read a biography before. Or even if you haven’t read a book in years. I can almost guarantee this will single-handedly remind you of what you’ve been missing — it sure reminded me. In any case, enough fan boying — let’s get to the actual discussion.</p><h3>Objective</h3><p>When reading in general, I strongly believe that having an objective in mind is necessary. As with anything you partake, there should be some rationale behind you investing time in doing it. That objective need not be related to work or business by any means — being entertained is a perfectly fine goal! But definitely let it be known to you that this is in fact your goal in beginning to read a book, since the way you approach this book will definitely be quite different than if you were doing it for something you want to influence your work. That being said, this is more explicitly elaborated in <a href="https://robertheaton.com/2018/06/25/how-to-read/">https://robertheaton.com/2018/06/25/how-to-read/</a>, which I highly recommend go and check out.</p><p>My particular goal in reading <em>Shoe Dog </em>was to see first-hand how supposedly “traditional” businesses (that don’t have to do with the tech sector) are formed and the principles that Phil Knight followed to succeed.</p><h3>Plot Summary</h3><p><em>Shoe Dog </em>recounts the story of Phil Knight, founder and eventual CEO of Nike, from its conception as a subsidiary of a Japanese shoe company, to its becoming a public US company. While most of us don’t think at all when we tie our shoes to go to school in the morning, this is what occupied the mind and work day of Knight for most of his life, and it is a truly fascinating experience to not only see this side of the business, but also the more messy, corporate mess he had to navigate to get Nike to the juggernaut it is today.</p><h3>Takeaways</h3><p>Three immediate takeaways become clear in reading the book, both about the business and Phil Knight himself. These were:</p><ul><li>Develop a business in which you have a personal stake, since it not only compels you to go to all the ends in the world to see it succeed, but also because you are more likely to know people from previous exposure in this familiar field than one that’s completely foreign to you</li><li>The road taken to forming a successful company is often locally very circuitous, while remaining globally targeted</li><li>Cultural understanding in a world business is crucial to success</li></ul><p>Developing a business with a personal stake is almost always the first rule of thumb that business leaders will ascribe to. This was nowhere more clear in seeing how Phil Knight was able to navigate all the sh*t storms that would normally end a company: being screwed over by a deal from your corporate parents, getting investigated by the FBI, or losing a key player in your advertising campaign. While the details of how he evaded each of these circumstances largely evades my recall, what stuck was how his drive to see his designs brought to the market really compelled him to unearthly efforts to circumvent these pitfalls. Its this burning desire to see this idea come to fruition that brought Knight, along with many other visionaries, to push through all the points where, if they believed <em>even one </em>alternative could bring them as much satisfaction in its pursuit, they would have quit. Finding this singular drive is definitely a compelling point to admire in visionaries, especially as you see it unfold in Knight’s actions.</p><p>Much in this same line, Knight goes through <em>so much </em>more corporate drama than I could have imagined. And, it was really insightful to see that, while most leaders have a very composed appearance at the head of the company, they similarly go through all sorts of struggles in managing the mess that is an organization from its inside. Knight’s recount also showed his great indebtedness to luck and others he had met in his time in both business and outside alike. Seeing the direct ramifications of treating other business leaders, despite their clear supposed cultural differences, was enlightening, especially in the form of the contacts he retained in Japan.</p><h3>Review</h3><p>Honestly, the main thing that’s probably holding my ability to express how incredible Phil Knight’s <em>Shoe Dog </em>is is my writing ability. This truly is a must-read for anyone who can read. Go out and buy the book. Or buy the Kindle edition. Or buy the audiobook. Doesn’t matter how you read/listen to this book. You owe it to yourself to see how incredible the story of Nike truly is.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a3c8a6e021eb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Returning to the Reading Scene]]></title>
            <link>https://medium.com/@yashpatel_86510/returning-to-the-reading-scene-632840ea1a3e?source=rss-68694da71a5f------2</link>
            <guid isPermaLink="false">https://medium.com/p/632840ea1a3e</guid>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[entrepreneurship]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[reading]]></category>
            <dc:creator><![CDATA[Yash Patel]]></dc:creator>
            <pubDate>Sun, 26 Aug 2018 00:44:59 GMT</pubDate>
            <atom:updated>2018-08-26T00:49:03.566Z</atom:updated>
            <content:encoded><![CDATA[<p><em>This blog post’s a pretty stark departure from my technical posts in the past. My current plan is to include a mix of posts along these lines (what that exactly entails should be clear by the end of this post) along with more technical posts. Thanks to everyone who’s read my previous posts!</em></p><p>Like a relatively large portion of college students, I loved reading as a kid, only to let go of this hobby in entering high school. Swearing off reading for many of the years that followed, it was only after becoming friends with another student in my college class senior year of college that I truly rediscovered the joys of reading. Unlike my reading passions as a (younger) kid, however, I greatly relish reading non-fiction books, for the joy of getting to learn about a person, subject, or world that I would otherwise had little to no idea about. While I still very much love fantasy and sci-fi books (<em>The Hitchhiker’s Guide to the Galaxy </em>and <em>Harry Potter</em> will always have a special place in my mind), I’ve definitely started to slowly drift towards more non-fiction books.</p><p>With that in mind, I recently came across this journal article by Robert Heaton talking about learning “How to Read.” For anyone who hasn’t read this article, I <strong>highly </strong>recommend you take a moment and read it <strong>now (</strong>and then finish reading this article once you’re done): <a href="https://robertheaton.com/2018/06/25/how-to-read/">https://robertheaton.com/2018/06/25/how-to-read/</a>. Not only did all the points in the beginning exposition resonate with me, but I had in fact become fully aware of these issues myself in the weeks before coming across this article. While I’ve known about this article for a couple months now, I’m only attempting to put his ideas in practice now.</p><p>And that brings me to the entire point of this particular blog post. I’m going to keep a running series of posts that go through the books that I’m reading to talk about my objectives in reading the book, a brief summary of its takeaways, my opinions on these takeaways, and a brief review. Hopefully this will help solidify my learnings from books while also inciting some interesting discussions about the matter.</p><p>For a general sense of the books I’m reading, feel free to check out my Goodreads page (<a href="https://www.goodreads.com/user/show/83094203-yash-patel">https://www.goodreads.com/user/show/83094203-yash-patel</a>) — highly recommend everyone get one! Anyway, this blog post was just intended as setup for the following blog posts that come out of my account, since I’ll be going through this exercise for the next week or so to get through the backlog of books that I’ve read over the last couple months!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=632840ea1a3e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reinforcement Learning w/ Keras + OpenAI: Actor-Critic Models]]></title>
            <link>https://medium.com/data-science/reinforcement-learning-w-keras-openai-actor-critic-models-f084612cfd69?source=rss-68694da71a5f------2</link>
            <guid isPermaLink="false">https://medium.com/p/f084612cfd69</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[reinforcement-learning]]></category>
            <dc:creator><![CDATA[Yash Patel]]></dc:creator>
            <pubDate>Mon, 31 Jul 2017 04:16:54 GMT</pubDate>
            <atom:updated>2017-07-31T04:16:54.005Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Quick Recap</strong></p><p>Last time in our Keras/OpenAI tutorial, we discussed a very fundamental algorithm in reinforcement learning: the DQN. The Deep Q-Network is actually a fairly new advent that arrived on the seen only a couple years back, so it is quite incredible if you were able to understand and implement this algorithm having just gotten a start in the field. As with the original post, let’s take a quick moment to appreciate how <strong>incredible</strong> results we achieved are: in a continuous output space scenario and starting with absolutely <em>no</em> knowledge on what “winning” entails, we were able to explore our environment and “complete” the trials.</p><p>Put yourself in the situation of this simulation. This would essentially be like asking you to play a game, without a rulebook or specific endgoal, and demanding you to continue to play until you win (almost seems a bit cruel). And not only that: the possible result states you could reach with a series of actions is infinite (i.e. continuous observation space)! Yet, the DQN converges surprising quickly in tackling this seemingly impossible task by maintaining and slowly updating value internally to actions.</p><p><strong>Even More Complex Environment</strong></p><p>The step up from the previous MountainCar environment to the Pendulum is very similar to that from CartPole to MountainCar: we are expanding from a discrete environment to continuous. The Pendulum environment has an infinite input space, meaning that the number of actions you can take at any given time is unbounded. Why is DQN no longer applicable in this environment? Wasn’t our implementation of it completely independent of the structure of the environment actions?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/376/1*J_oEx0kpBpwXoVmRytn6qg.gif" /><figcaption>Unlike the MountainCar-v0, Pendulum-v0 poses an even greater challenge by giving us an infinite input space to work with.</figcaption></figure><p>While it <em>was</em> indepedent of <em>what </em>the actions were, the DQN was fundamentally premised on having a finite output space. After all, think about how we structured the code: the prediction looked to assign a score to each of the possible actions at each time step (given the current environment state) and simply taking the action that had the highest score. We had previously reduced the problem of reinforcement learning to effectively assigning scores to actions. But, how would this be possible if we have an infinite input space? We would need an infinitely large table to keep track of all the Q values!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/1*uIClHh6szIhLnMO7Q9YtAw.png" /><figcaption>Infinite spreadsheets sound pretty far from ideal!</figcaption></figure><p>So, how do we go about tackling this seemingly impossible task? After all, we’re being asked to do something even more insane than before: not only are we given a game without instructions to play and win, but this game has a controller with infinite buttons on it! Let’s see why it is that DQN is restricted to a finite number of actions.</p><p>The reason stems from how the model is structured: we have to be able to <em>iterate </em>at each time step to update how our position on a particular action has changed. That’s exactly why we were having the model predict the Q values rather than directly predicting what action to take. If we did the latter, we would have no idea how to update the model to take into account the prediction and what reward we received for future predictions. So, the fundamental issue stems from the fact that it seems like our model <em>has </em>to output a tabulated calculation of the rewards associated with all the possible actions. What if, instead, we broke this model apart? What if we had two separate models: one outputting the desired action (in the continuous space) and another taking in an action as input to produce the Q values from DQNs? That seems to solve our problems and is exactly the basis of the actor-critic model!</p><p><strong>Actor-Critic Model Theory</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/390/1*-GfRVLWhcuSYhG25rN0IbA.png" /><figcaption>Unlike DQNs, the Actor-critic model (as implied by its name) has two separate networks: one that’s used for doing predictions on what action to take given the current environment state and another to find the value of an action/state</figcaption></figure><p>As we went over in previous section, the entire Actor-Critic (AC) method is premised on having two interacting models. This theme of having multiple neural networks that interact is growing more and more relevant in both RL and supervised learning, i.e. GANs, AC, A3C, DDQN (dueling DQN), and so on. Getting familiar with these architectures may be somewhat intimidating the first time through but is certainly a worthwhile exercise: you’ll be able to understand and program some of the algorithms that are at the forefront of modern research in the field!</p><p>Getting back to the topic at hand, the AC model has two aptly named components: an actor and a critic. The former takes in the current environment state and determines the best action to take from there. It is essentially what would have seemed like the natural way to implement the DQN. The critic plays the “evaluation” role from the DQN by taking in the environment state and an action and returning a score that represents how apt the action is for the state.</p><p>Imagine this as a playground with a kid (the “actor”) and her parent (the “critic”). The kid is looking around, exploring all the possible options in this environment, such as sliding up a slide, swinging on a swing, and pulling grass from the ground. The parent will look at the kid, and either criticize or complement here based on what she did, taking the environment into account. The fact that the parent’s decision is environmentally-dependent is both important and intuitive: after all, if the child tried to swing on the swing, it would deserve far less praise than if she tried to do so on a slide!</p><p><strong>Brief Aside: Chain Rule (Optional)</strong></p><p>The main point of theory you need to understand is one that underpins a large part of modern-day machine learning: the chain rule. It would not be a tremendous overstatement to say that chain rule may be one of the most pivotal, even though somewhat simple, ideas to grasp to understand practical machine learning. In fact, you could probably get away with having little math background if you just intuitively understand what is conceptually convenyed by the chain rule. I’ll take a very quick aside to describe the chain rule, but if you feel quite comfortable with it, feel free to jump to the next section, where we actually see what the practical outline for developing the AC model looks like and how the chain rule fits into that plan.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/197/1*UDtlMxua_agArXLSwcfAwg.png" /><figcaption>A seemingly simple concept probably from your first calculus class, but one that forms the modern basis of practical machine learning, due to the incredible speedup it enabled in backprop and similar algorithms</figcaption></figure><p>Pictorially, this equation seems to make very intuitive sense: after all, just “cancel out the numerator/denominator.” There’s one major problem with this “intuitive explanation” though: the reasoning in this explanation is completely backwards! It is important to remember that math is just as much about developing intuitive notation as it is about understanding the concepts. And so, people developing this “fractional” notation <em>because </em>the chain rule behaves very similarly to simplifying fractional products. So, people who try to explain the concept just through the notation are skipping a key step: why is it that this notation is even applicable? As in, why <em>do </em>derivatives behave this way?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/702/1*x3XLlTSnrAG4FzjViPsF_g.png" /><figcaption>The classic series of springs example is actually a pretty direct way you can visualize the chain rule in movement</figcaption></figure><p>The underlying concept is actually not too much more difficult to grasp than this notation. Imagine we had a series of ropes that are tied together at some fixed points, similar to how springs in series would be attached. Let’s say you’re holding one end of this spring system and your goal is to shake the opposite end at some rate 10 ft/s. You <em>could </em>just shake your end at that speed and have it propagate to the other end. <em>Or</em> you could hook up some intermediary system that shakes the middle connection at some lower rate, i.e. at 5 ft/s. In that case, you’d only need to move your end at 2 ft/s, since whatever movement you’re making will be carried on from where you making the movement to the endpoint. This is because the physical connections force the movement on one end to be carried through to the end. <em>Note: of course, as with any analogy, there are points of discrepancy here, but this was mostly for the purposes of visualization.</em></p><p>In a very similar way, if we have two systems where the output of one feeds into the input of the other, jiggling the parameters of the “feeding network,” will shake its output, which will propagate and be multiplied by any further changes through to the end of the pipeline.</p><p><strong>AC Model Overview</strong></p><p>Therefore, we have to develop an ActorCritic class that has some overlap with the DQN we previously implemented, but is more complex in its training. Because we’ll need some more advanced features, we’ll have to make use of the underlying library Keras rests upon: Tensorflow. <em>Note: You can definitely implement this in Theano as well, but I haven’t worked with it in the past and so have not included its code. Feel free to submit expansions of this code to Theano if you choose to do so to me!</em></p><p>The model implementation will consist of four main parts, which directly parallel how we implemented the DQN agent:</p><ul><li>Model parameters/setup</li><li>Training code</li><li>Prediction code</li></ul><p><strong>AC Parameters</strong></p><p>First off, just the imports we’ll be needing:</p><pre>import gym<br>import numpy as np <br>from keras.models import Sequential, Model<br>from keras.layers import Dense, Dropout, Input<br>from keras.layers.merge import Add, Multiply<br>from keras.optimizers import Adam<br>import keras.backend as K</pre><pre>import tensorflow as tf</pre><pre>import random<br>from collections import deque</pre><p>The parameters are very similar to those in the DQN. After all, this actor-critic model has to do the same exact tasks as the DQN except in two separate modules. We also continue to use the “target network hack” that we discussed in the DQN post to ensure the network successfully converges. The only new parameter is referred to as “tau” and relates to a slight change in how the target network learning takes place in this case:</p><pre>class ActorCritic:<br>    def __init__(self, env, sess):<br>        self.env  = env<br>        self.sess = sess</pre><pre>        self.learning_rate = 0.001<br>        self.epsilon = 1.0<br>        self.epsilon_decay = .995<br>        self.gamma = .95<br>        self.tau   = .125<br>        self.memory = deque(maxlen=2000)</pre><p>The exact use of the tau parameter is explained more in the training section that follows but essentially plays the role of shifting from the prediction models to the target models gradually. Now, we reach the main points of interest: defining the models. As described, we have two separate models, each associated with its own target network.</p><p>We start with defining actor model. The purpose of the actor model is, given the current state of the environment, determine the best action to take. Once again, this task has numeric data that we are given, meaning there is no room or need to involve any more complex layers in the network than simply the Dense/fully-connected layers we’ve been using thus far. And so, the Actor model is quite simply a series of fully connected layers that maps from the environment observation to a point in the environment space:</p><pre>def create_actor_model(self):<br>        state_input = Input(shape=self.env.observation_space.shape)<br>        h1 = Dense(24, activation=&#39;relu&#39;)(state_input)<br>        h2 = Dense(48, activation=&#39;relu&#39;)(h1)<br>        h3 = Dense(24, activation=&#39;relu&#39;)(h2)<br>        output = Dense(self.env.action_space.shape[0],  <br>            activation=&#39;relu&#39;)(h3)<br>        <br>        model = Model(input=state_input, output=output)<br>        adam  = Adam(lr=0.001)<br>        model.compile(loss=&quot;mse&quot;, optimizer=adam)<br>        return state_input, model</pre><p>The main difference is that we return the a reference to the Input layer. The reason for this will be more clear by the end of this section, but briefly, it is for how we handle the training differently for the actor model.</p><p>The tricky part for the actor model comes in determining how to train it, and this is where the chain rule comes into play. But before we discuss that, let’s think about why it is any different than the standard critic/DQN network training. After all, aren’t we simply going to fit as in the DQN case, where we fit the model according to the current state and what the best action would be based on current and discounted future rewards? The problem lies in the question: if we’re able to do what we asked, then this would be a solved issue. The issue arises in how we determine what the “best action” to take would be, since the Q scores are now calculated separately in the critic network.</p><p>So, to overcome this, we choose an alternate approach. Rather than finding the “best option” and fitting on that, we essentially do hill climbing (gradient ascent). For those not familiar with the concept, hill climbing is a simple concept: from your local POV, determine the steepest direction of incline and move incrementally in that direction. In other words, hill climbing is attempting to reach a global max by simply doing the naive thing and following the directions of the local maxima. There are scenarios you could imagine where this would be hopelessly wrong, but more often than not, it works well in practical situations.</p><p>As a result, we want to use this approach to updating our actor model: we want to determine what change in parameters (in the actor model) would result in the largest increase in the Q value (predicted by the critic model). Since the output of the actor model is the action and the critic evaluates based on an environment state+action pair, we can see how the chain rule will play a role. We’ll want to see how changing the parameters of the actor will change the eventual Q, using the output of the actor network as our “middle link” (code below is all in the “<em>__init__(self)</em>” method):</p><pre>        self.actor_state_input, self.actor_model = \<br>            self.create_actor_model()<br>        _, self.target_actor_model = self.create_actor_model()</pre><pre>        self.actor_critic_grad = tf.placeholder(tf.float32, <br>            [None, self.env.action_space.shape[0]]) <br>        <br>        actor_model_weights = self.actor_model.trainable_weights<br>        self.actor_grads = tf.gradients(self.actor_model.output, <br>            actor_model_weights, -self.actor_critic_grad)<br>        grads = zip(self.actor_grads, actor_model_weights)<br>        self.optimize =  tf.train.AdamOptimizer(<br>            self.learning_rate).apply_gradients(grads)</pre><p>We see that here we hold onto the gradient between the model weights and the output (action). We’ve also scaled it by the negation of self.actor_critic_grad (since we want to do gradient ascent in this case), which is held by a placeholder. For those unfamiliar with Tensorflow or learning for the first time, a placeholder plays the role of where you “input data” when you run the Tensorflow session. I won’t go into details about how it works, but the tensorflow.org tutorial goes through the material quite beautifully.</p><p>Moving on to the critic network, we are essentially faced with the opposite issue. That is, the network definition is slightly more complicated, but its training is relatively straightforward. The critic network is intended to take <em>both </em>the environment state and action as inputs and calculate a corresponding valuation. We do this by a series of fully-connected layers, with a layer in the middle that merges the two before combining into the final Q-value prediction:</p><pre>def create_critic_model(self):<br>        state_input = Input(shape=self.env.observation_space.shape)<br>        state_h1 = Dense(24, activation=&#39;relu&#39;)(state_input)<br>        state_h2 = Dense(48)(state_h1)<br>        <br>        action_input = Input(shape=self.env.action_space.shape)<br>        action_h1    = Dense(48)(action_input)<br>        <br>        merged    = Add()([state_h2, action_h1])<br>        merged_h1 = Dense(24, activation=&#39;relu&#39;)(merged)<br>        output = Dense(1, activation=&#39;relu&#39;)(merged_h1)<br>        model  = Model(input=[state_input,action_input], <br>            output=output)<br>        <br>        adam  = Adam(lr=0.001)<br>        model.compile(loss=&quot;mse&quot;, optimizer=adam)<br>        return state_input, action_input, model</pre><p>The main points of note are the asymmetry in how we handle the inputs and what we’re returning. For the first point, we have one extra FC (fully-connected) layer on the environment state input as compared to the action. I did so because that is the recommended architecture for these AC networks, but it probably works equally (or marginally less) well with the FC layer slapped onto both inputs. As for the latter point (what we’re returning), we need to hold onto references of both the input state and action, since we need to use them in doing updates for the actor network:</p><pre>        self.critic_state_input, self.critic_action_input, \<br>            self.critic_model = self.create_critic_model()<br>        _, _, self.target_critic_model = self.create_critic_model()</pre><pre>        self.critic_grads = tf.gradients(self.critic_model.output, <br>            self.critic_action_input)<br>        <br>        # Initialize for later gradient calculations<br>        self.sess.run(tf.initialize_all_variables())</pre><p>Here we set up the missing gradient to be calculated: the output Q with respect to the action weights. This is directly called in the training code, as we will now look into.</p><p><strong>AC Training</strong></p><p>The last main part of this code that is different from the DQN is the actual training. We do, however, make use of the same basic structure of pulling episodes from memory and learning from those. Since we have two training methods, we have separated the code into different training functions, cleanly calling them as:</p><pre>def train(self):<br>        batch_size = 32<br>        if len(self.memory) &lt; batch_size:<br>            return</pre><pre>        rewards = []<br>        samples = random.sample(self.memory, batch_size)<br>        self._train_critic(samples)<br>        self._train_actor(samples)</pre><p>Now we define the two train methods. The, however, is very similar to that from the DQN: we are simply finding the discounted future reward and training on that. The only difference is that we’re training on the state/action pair and are using the <em>target_critic_model</em> to predict the future reward rather than the actor:</p><pre><br>    def _train_critic(self, samples):<br>        for sample in samples:<br>            cur_state, action, reward, new_state, done = sample<br>            if not done:<br>                target_action = <br>                    self.target_actor_model.predict(new_state)<br>                future_reward = self.target_critic_model.predict(<br>                    [new_state, target_action])[0][0]<br>                reward += self.gamma * future_reward<br>            self.critic_model.fit([cur_state, action], <br>                reward, verbose=0)</pre><p>As for the actor, we luckily did all the hard work before! We already set up how the gradients will work in the network and now simply have to call it with the actions and states we encounter:</p><pre>def _train_actor(self, samples):<br>        for sample in samples:<br>            cur_state, action, reward, new_state, _ = sample<br>            predicted_action = self.actor_model.predict(cur_state)<br>            grads = self.sess.run(self.critic_grads, feed_dict={<br>                self.critic_state_input:  cur_state,<br>                self.critic_action_input: predicted_action<br>            })[0]</pre><pre>            self.sess.run(self.optimize, feed_dict={<br>                self.actor_state_input: cur_state,<br>                self.actor_critic_grad: grads<br>            })</pre><p>As mentioned, we made use of the target model. And so, we have to update its weights at every time step. However, we only do so slowly. More concretely, we retain the value of the target model by a fraction <em>self.tau </em>and update it to be the corresponding model weight the remainder <em>(1-self.tau)</em> fraction. We do this for both the actor/critic, but only the actor is given below (you can see the critic in the full code at the bottom of the post):</p><pre>def _update_actor_target(self):<br>        actor_model_weights  = self.actor_model.get_weights()<br>        actor_target_weights =self.target_critic_model.get_weights()<br>        <br>        for i in range(len(actor_target_weights)):<br>            actor_target_weights[i] = actor_model_weights[i]<br>        self.target_critic_model.set_weights(actor_target_weights</pre><p><strong>AC Prediction</strong></p><p>This is identical to how we did it in the DQN, and so there’s not much to discuss on its implementation:</p><pre>def act(self, cur_state):<br>  self.epsilon *= self.epsilon_decay<br>  if np.random.random() &lt; self.epsilon:<br>   return self.env.action_space.sample()<br>  return self.actor_model.predict(cur_state)</pre><p><strong>Prediction Code</strong></p><p>The prediction code is also very much the same as it was in previous reinforcement learning algorithms. That is, we just have to iterate through the trial and call predict, remember, and train on the agent:</p><pre>def main():<br>    sess = tf.Session()<br>    K.set_session(sess)<br>    env = gym.make(&quot;Pendulum-v0&quot;)<br>    actor_critic = ActorCritic(env, sess)<br>    <br>    num_trials = 10000<br>    trial_len  = 500<br>    <br>    cur_state = env.reset()<br>    action = env.action_space.sample()<br>    while True:<br>        env.render()<br>        cur_state = cur_state.reshape((1, <br>            env.observation_space.shape[0]))<br>        action = actor_critic.act(cur_state)<br>        action = action.reshape((1, env.action_space.shape[0]))<br>        <br>        new_state, reward, done, _ = env.step(action)<br>        new_state = new_state.reshape((1, <br>            env.observation_space.shape[0]))<br>        <br>        actor_critic.remember(cur_state, action, reward, <br>            new_state, done)<br>        actor_critic.train()<br>        <br>        cur_state = new_state</pre><p><strong>Complete Code</strong></p><p>With that, here is the complete code used for training against the “Pendulum-v0” environment using AC (Actor-Critic)!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5d2fdb7b2612c0f58492d62f0a3df5b4/href">https://medium.com/media/5d2fdb7b2612c0f58492d62f0a3df5b4/href</a></iframe><p>Boy, that was long: thanks for reading all the way through (or at least skimming)! Keep an eye out for the next Keras+OpenAI tutorial!</p><h3>Comment and click that ❤️ below to show support!</h3><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f084612cfd69" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/reinforcement-learning-w-keras-openai-actor-critic-models-f084612cfd69">Reinforcement Learning w/ Keras + OpenAI: Actor-Critic Models</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reinforcement Learning w/ Keras + OpenAI: DQNs]]></title>
            <link>https://medium.com/data-science/reinforcement-learning-w-keras-openai-dqns-1eed3a5338c?source=rss-68694da71a5f------2</link>
            <guid isPermaLink="false">https://medium.com/p/1eed3a5338c</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[towards-data-science]]></category>
            <category><![CDATA[deep-leraning]]></category>
            <category><![CDATA[reinforcement-learning]]></category>
            <category><![CDATA[keras]]></category>
            <dc:creator><![CDATA[Yash Patel]]></dc:creator>
            <pubDate>Sun, 30 Jul 2017 07:02:37 GMT</pubDate>
            <atom:updated>2017-07-30T08:22:13.411Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Quick Recap</strong></p><p>Last time in our Keras/OpenAI tutorial, we discussed a very basic example of applying deep learning to reinforcement learning contexts. This was an incredible showing in retrospect! If you looked at the training data, the random chance models would usually only be able to perform for 60 steps in median. And yet, by training on this seemingly very mediocre data, we were able to “beat” the environment (i.e. get &gt;200 step performance). How is this possible?</p><p>We can get directly an intuitive feel for this. Let’s imagine the perfectly random series we used as our training data. It is extremely unlikely that any two series will have high overlap with one another, since these are generated completely randomly. However, there <strong>are</strong> key features that are common between successful trials, such as pushing the cart right when the pole is leaning right and vice versa. And so, by training our NN on all these trials data, we extract the shared patterns that contributed to them being successful and are able to smooth over the details that resulted in their independent failures.</p><p>That being said, the environment we consider this week is significantly more difficult than that from last week: the MountainCar.</p><p><strong>More Complex Environments</strong></p><p>Even though it seems we should be able to apply the same technique as that we applied last week, there is one key features here that makes doing so impossible: we can’t generate training data. Unlike the very simple Cartpole example, taking random movements often simply leads to the trial ending in us at the bottom of the hill. That is, we have several trials that are all identically -200 in the end. This is practically useless to use as training data. Imagine you were in a class where no matter what answers you put on your exam, you got a 0%! How are you going to learn from any of those experiences?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*nbCSvWmyS_BUDz_WAJyKUw.gif" /><figcaption>Random inputs for the “MountainCar-v0” environment does not produce any output that is worthwhile or useful to train on</figcaption></figure><p>In line with that, we have to figure out a way to incrementally improve upon previous trials. For this, we use one of the most basic stepping stones for reinforcement learning: Q-learning!</p><p><strong>DQN Theory Background</strong></p><p>Q-learning (which doesn’t stand for anything, by the way) is centered around creating a “virtual table” that accounts for how much reward is assigned to each possible action given the current state of the environment. Let’s break that down one step at a time:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/686/1*WEfdub-U4i5HRLunOlXj8g.png" /><figcaption>You can imagine the DQN network as internally maintaining a spreadsheet of the values of each of the possible actions that can be taken given the current environment state</figcaption></figure><p>What do we mean by “virtual table?” Imagine that for each possible configuration of the input space, you have a table that assigns a score for each of the possible actions you can take. If this were magically possible, then it would be extremely easy for you to “beat” the environment: simply choose the action that has the highest score! Two points to note about this score. First, this score is conventionally referred to as the “Q-score,” which is where the name of the overall algorithm comes from. Second, as with any other score, these Q score have <em>no meaning </em>outside the context of their simulation. That is, they have <strong>no absolute significance</strong>, but that’s perfectly fine, since we solely need it to do comparisons.</p><p>Why then do we need virtual table for <em>each </em>input configuration? Why can’t we just have one table to rule them all? The reason is that it doesn’t make sense to do so: that would be the same as saying the best action to take while at the bottom of the valley is exactly that which you should take when you are perched on the highest point of the left incline.</p><p>Now, the main problem with what I described (maintaining a virtual table for <em>each </em>input configuration) is that this is impossible: we have a continuous (infinite) input space! We could get around this by discretizing the input space, but that seems like a pretty hacky solution to this problem that we’ll be encountering over and over in future situations. So, how do we get around this? By applying neural nets to the situation: that’s where the D in DQN comes from!</p><p><strong>DQN Agent</strong></p><p>So, we’ve now reduced the problem to finding a way to assign the different actions Q-scores given the current state. This is the answer to a very natural first question to answer when employing any NN: what are the inputs and outputs of our model? The extent of the math you need to understand for this model is the following equation (don’t worry, we’ll break it down):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/740/1*IyrdggWA1wsce4nBA6u2VA.png" /></figure><p>Q, as mentioned, represents the value estimated by our model given the current state (s) and action taken (a). The goal, however, is to determine the <em>overall </em>value of a state. What do I mean by that? The <em>overall </em>value is <strong>both </strong>the immediate reward you will get <strong>and </strong>the expected rewards you will get in the future from being in that position. That is, we want to account for the fact that the value of a position often reflects not only its immediate gains but also the future gains it enables (damn, deep). In any case, we discount future rewards because, if I compare two situations in which I expect to get $100 one of the two being in the future, I would always take the present deal, since the position of the future one may change between when I made the deal and when I receive the money. The gamma factor reflects this depreciated value for the expected future returns on the state.</p><p>And that’s it: that’s all the math we’ll need for this! Time to actually move on to some code!</p><p><strong>DQN Agent Implementation</strong></p><p>The Deep Q Network revolves around continuous learning, meaning that we don’t simply accrue a bunch of trial/training data and feed it into the model. Instead, we create training data through the trials we run and feed this information into it directly after running the trial. If this all seems somewhat vague right now, don’t worry: time to see some code about this. The code largely revolves around defining a DQN class, where all the logic of the algorithm will actually be implemented, and where we expose a simple set of functions for the actual training.</p><p><strong>DQN Hyperparameters</strong></p><p>First off, we’re going to discuss some parameters of relevance for DQNs. Most of them are standard from most neural net implementations:</p><pre>class DQN:<br>    def __init__(self, env):<br>        self.env     = env<br>        self.memory  = deque(maxlen=2000)<br>        <br>        self.gamma = 0.95<br>        self.epsilon = 1.0<br>        self.epsilon_min = 0.01<br>        self.epsilon_decay = 0.995<br>        self.learning_rate = 0.01</pre><p>Let’s step through these one at a time. The first is simply the environment, which we supply for convenience when we need to reference the shapes in creating our model. The “memory” is a key component of DQNs: as mentioned previously, the trials are used to continuously train the model. However, rather than training on the trials as they come in, we add them to memory and train on a random sample of that memory. Why do this instead of just training on the last <em>x </em>trials as our “sample?” The reason is somewhat subtle. Imagine instead we were to just train on the most recent trials as our sample: in this case, our results would only learn on its most recent actions, which may not be directly relevant for future predictions. In this environment in particular, if we were moving down the right side of the slope, training on the most recent trials would entail training on the data where you were moving up the hill towards the right. But, this would not be at all relevant to determining what actions to take in the scenario you would soon be facing of scaling up the left hill. So, by taking a random sample, we don’t bias our training set, and instead ideally learn about scaling all environments we would encounter equally well.</p><p>So, we now discuss hyperparameters of the model: gamma, epsilon/epsilon decay, and the learning rate. The first is the future rewards depreciation factor (&lt;1) discussed in the earlier equation, and the last is the standard learning rate parameter, so I won’t discuss that here. The second, however, is an interesting facet of RL that deserves a moment to discuss. In any sort of learning experience, we always have the choice between exploration vs. exploitation. This isn’t limited to computer science or academics: we do this on a day to day basis!</p><p>Consider the restaurants in your local neighborhood. When was the last time you went to a new one? Probably a long time ago. That corresponds to your shift from <em>exploration </em>to <em>exploitation</em>: rather than trying to find new and better opportunities, you settle with the best one you’ve found in your past experiences and maximize your utility from there. Contrast that to when you moved into your house: at that time, you had no idea what restaurants were good or not and so were enticed to explore your options. In other words, there’s a clear trend for learning: explore all your options when you’re unaware of them, and gradually shift over to exploiting once you’ve established opinions on some of them. In the same manner, we want our model to capture this natural model of learning, and epsilon plays that role.</p><p>Epsilon denotes the fraction of time we will dedicate to exploring. That is, a fraction <em>self.epsilon </em>of the trials, we will simply take a random action rather than the one we would predict to be the best in that scenario. As stated, we want to do this more often than not in the beginning, before we form stabilizing valuations on the matter, and so initialize epsilon to close to 1.0 at the beginning and decay it by some fraction &lt;1 at every successive time step.</p><p><strong>DQN Models</strong></p><p>There was one key thing that was excluded in the initialization of the DQN above: the actual model used for predictions! As in our original Keras RL tutorial, we are directly given the input and output as numeric vectors. So, there’s no need to employ more complex layers in our network other than fully connected layers. Specifically, we define our model just as:</p><pre>def create_model(self):<br>        model   = Sequential()<br>        state_shape  = self.env.observation_space.shape<br>        model.add(Dense(24, input_dim=state_shape[0], <br>            activation=&quot;relu&quot;))<br>        model.add(Dense(48, activation=&quot;relu&quot;))<br>        model.add(Dense(24, activation=&quot;relu&quot;))<br>        model.add(Dense(self.env.action_space.n))<br>        model.compile(loss=&quot;mean_squared_error&quot;,<br>            optimizer=Adam(lr=self.learning_rate))<br>        return model</pre><p>And use this to define the model and target model (explained below):</p><pre>def __init__(self, env):<br>        self.env     = env<br>        self.memory  = deque(maxlen=2000)<br>        <br>        self.gamma = 0.95<br>        self.epsilon = 1.0<br>        self.epsilon_min = 0.01<br>        self.epsilon_decay = 0.995<br>        self.learning_rate = 0.01<br>        self.tau = .05</pre><pre>        self.model = self.create_model()<br>        # &quot;hack&quot; implemented by DeepMind to improve convergence<br>        self.target_model = self.create_model()</pre><p>The fact that there are two <em>separate </em>models, one for doing predictions and one for tracking “target values” is definitely counter-intuitive. To be explicit, the role of the model (<em>self.model</em>) is to do the actual predictions on what action to take, and the target model (<em>self.target_model</em>) tracks what action we <em>want </em>our model to take.</p><p>Why not just have a single model that does both? After all, if something is predicting the action to take, shouldn’t it be implicitly determine what model we <em>want </em>our model to take? This is actually one of those “weird tricks” in deep learning that DeepMind developed to get convergence in the DQN algorithm. If you use a single model, it can (and often does) converge in simple environments (such as the CartPole). But, the reason it doesn’t converge in these more complex environments is because of how we’re training the model: as mentioned previously, we’re training it “on the fly.”</p><p>As a result, we are doing training at each time step and, if we used a single network, would also be essentially changing the “goal” at each time step. Think of how confusing that would be! That would be like if a teacher told you to go finish pg. 6 in your textbook and, by the time you finished half of it, she changed it to pg. 9, and by the time you finished half of that, she told you to do pg. 21! This, therefore, causes a lack of convergence by a lack of clear direction in which to employ the optimizer, i.e. the gradients are changing too rapidly for stable convergence. So, to compensate, we have a network that changes more slowly that tracks our eventual goal and one that is trying to achieve those.</p><p><strong>DQN Training</strong></p><p>The training involves three main steps: remembering, learning, and reorienting goals. The first is basically just adding to the memory as we go through more trials:</p><pre>def remember(self, state, action, reward, new_state, done):<br>        self.memory.append([state, action, reward, new_state, done])</pre><p>There’s not much of note here other than that we have to store the <em>done</em> phase for how we later update the reward function. Moving on to the main body of our DQN, we have the train function. This is where we make use of our stored memory and actively learn from what we’ve seen in the past. We start by taking a sample from our entire memory storage. From there, we handle each sample different. As we saw in the equation before, we want to update the <em>Q </em>function as <strong>the sum of </strong>the current reward <strong>and </strong>expected future rewards (depreciated by gamma). In the case we are at the end of the trials, there are no such future rewards, so the entire value of this state is just the current reward we received. In a non-terminal state, however, we want to see what the maximum reward we would receive would be if we were able to take any possible action, from which we get:</p><pre>def replay(self):<br>        batch_size = 32<br>        if len(self.memory) &lt; batch_size: <br>            return</pre><pre>        samples = random.sample(self.memory, batch_size)<br>        for sample in samples:<br>            state, action, reward, new_state, done = sample<br>            target = self.target_model.predict(state)<br>            if done:<br>                target[0][action] = reward<br>            else:<br>                Q_future = max(<br>                    self.target_model.predict(new_state)[0])<br>                target[0][action] = reward + Q_future * self.gamma<br>            self.model.fit(state, target, epochs=1, verbose=0)</pre><p>And finally, we have to reorient our goals, where we simply copy over the weights from the main model into the target one. Unlike the main train method, however, this target update is called less frequently:</p><pre>def target_train(self):<br>        weights = self.model.get_weights()<br>        target_weights = self.target_model.get_weights()<br>        for i in range(len(target_weights)):<br>            target_weights[i] = weights[i]<br>        self.target_model.set_weights(target_weights)</pre><p><strong>DQN Action</strong></p><p>The final step is simply getting the DQN to actually perform the desired action, which alternates based on the given epsilon parameter between taking a random action and one predicated on past training, as follows:</p><pre>def act(self, state):<br>        self.epsilon *= self.epsilon_decay<br>        self.epsilon = max(self.epsilon_min, self.epsilon)<br>        if np.random.random() &lt; self.epsilon:<br>            return self.env.action_space.sample()<br>        return np.argmax(self.model.predict(state)[0])</pre><p><strong>Training Agent</strong></p><p>Training the agent now follows naturally from the complex agent we developed. We have to instantiate it, feed it the experiences as we encounter them, train the agent, and update the target network:</p><pre>def main():<br>    env     = gym.make(&quot;MountainCar-v0&quot;)<br>    gamma   = 0.9<br>    epsilon = .95</pre><pre>    trials  = 100<br>    trial_len = 500</pre><pre>    updateTargetNetwork = 1000<br>    dqn_agent = DQN(env=env)<br>    steps = []<br>    for trial in range(trials):<br>        cur_state = env.reset().reshape(1,2)<br>        for step in range(trial_len):<br>            action = dqn_agent.act(cur_state)<br>            env.render()<br>            new_state, reward, done, _ = env.step(action)</pre><pre>            reward = reward if not done else -20<br>            print(reward)<br>            new_state = new_state.reshape(1,2)<br>            dqn_agent.remember(cur_state, action, <br>                reward, new_state, done)<br>            <br>            dqn_agent.replay()<br>            dqn_agent.target_train()</pre><pre>            cur_state = new_state<br>            if done:<br>                break<br>        if step &gt;= 199:<br>            print(&quot;Failed to complete trial&quot;)<br>        else:<br>            print(&quot;Completed in {} trials&quot;.format(trial))<br>            break</pre><p><strong>Complete Code</strong></p><p>With that, here is the complete code used for training against the “MountainCar-v0” environment using DQN!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d989aded95a0d7dd02464fc56ddbb54e/href">https://medium.com/media/d989aded95a0d7dd02464fc56ddbb54e/href</a></iframe><p>Keep an eye out for the next Keras+OpenAI tutorial!</p><h3>Comment and click that ❤️ below to show support!</h3><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1eed3a5338c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/reinforcement-learning-w-keras-openai-dqns-1eed3a5338c">Reinforcement Learning w/ Keras + OpenAI: DQNs</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reinforcement Learning w/ Keras+OpenAI: The Basics]]></title>
            <link>https://medium.com/@yashpatel_86510/reinforcement-learning-w-keras-openai-698add10b4eb?source=rss-68694da71a5f------2</link>
            <guid isPermaLink="false">https://medium.com/p/698add10b4eb</guid>
            <category><![CDATA[keras]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[gym]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Yash Patel]]></dc:creator>
            <pubDate>Wed, 26 Jul 2017 07:46:38 GMT</pubDate>
            <atom:updated>2017-07-27T07:35:39.902Z</atom:updated>
            <content:encoded><![CDATA[<p>Reinforcement learning has been heralded by many as one of the gateway technologies/concepts to have emerged from the theoretical studies of machine learning. We’ll go through a very quick overview of reinforcement learning before we diving into the code.</p><p><strong>Quick Background</strong></p><p>Reinforcement learning (RL) is a general umbrella term for any algorithm that does not require explicit pairs of data and their corresponding desired labels as is the case in traditional supervised learning but requires some numeric indication of “how a sample is.” This quality of the “goodness” of a sample has no meaning in an absolute sense. You can imagine this generically as your score in a video game. If the screen displays a score of “218,” that presumably carries absolutely no meaning to you, the gamer, unless you are aware of how difficult or easy it is to earn a point and what score you start with. And that’s basically the extent of background we’ll be delving into: there will be more in-depth discussions of RL in the future, but the code we go through in this post is a very basic example of RL and so does not entail any further meddling in the subject theory.</p><p><strong>Keras Notes</strong></p><p>For anyone just getting started in AI/ML programming, welcome! The field has grown so much in the past years that it is quite overwhelming to jump in just now. But there’s still plenty of time to get involved and learn in this massive field! In line with that, Keras is the library I’ll primarily be using for my tutorials to come, including this one. Keras is essentially a wrapper library for Tensorflow and Theano. Its interface is quite similar to that exposed by tflearn but is slightly more generic in its applicability to Theano as the backend. <em>Take note though! The dimensions in Theano are slightly different from those in Tensorflow. </em>I would recommend, therefore, to adjust your Keras to use TF as its backend to avoid any frustrations with dimensions going forward (should be the default when you install, if you have TF installed already).</p><p>You could also just as easily do this with TF, but Keras gives us the nice flexibility when getting started of not having to keep track of dimensions through convolutions and all that crap. Anyway, enough words: time to move to the code!</p><p><strong>Code</strong></p><p>We’ll be exploring the most basic OpenAI environment here: the CartPole! As a final quick note, you can find the instructions to install OpenAI’s gym package here: <a href="https://gym.openai.com/docs">https://gym.openai.com/docs</a>. Just running “sudo pip install gym” should work on most platforms.</p><p>The <strong>CartPole </strong>environment has a very simple premise: balance the pole on the cart.</p><p><strong>Data Collection</strong></p><p>The first part of any machine learning problem is gathering the data, and this one is no different. Luckily, OpenAI’s gym environment provides a very straightforward way of gathering data: we can essentially just run through the simulation many times and take random steps every time. OpenAI Gym environments are structured around two main parts: an observation space and an action space. We observe the former from the environment and use that to determine how best to update it through an action, i.e. based on the current state of the pole (observation), determine whether to move the cart left or right (action).</p><p>As a result, we need to take an action that fits in the scope of the allowable actions of the action space, which is of size 2 in this case (left or right). We take the output space to be one-hot encoded, the reason being we want the neural net to eventually predict the probability of moving left vs. right given the current state of the environment. In this case, we could get away with just having the output be a single 1x1 float matrix (i.e. a scalar) and round it for our final result, but the one-hot encoding practice can be more widely applied.</p><p>So, to accumulate the actions and corresponding observations, a <strong>first thought </strong>may simply be:</p><pre>for _ in range(10000):<br>    observation = env.reset()<br>    training_sampleX, training_sampleY = [], []<br>    for step in range(sim_steps):<br>        action = np.random.randint(0, 2)<br>        one_hot_action = np.zeros(2)<br>        one_hot_action[action] = 1<br>        training_sampleX.append(observation)<br>        training_sampleY.append(one_hot_action)<br>        <br>        observation, reward, done, _ = env.step(action)<br>        if done:<br>            break<br>    trainingX += training_sampleX<br>    trainingY += training_sampleY</pre><p>However, if we were to train on this, the final predictor would likely do no better than random chance. After all, “garbage in, garbage out”: we would be doing no more than feeding the neural net a collection of both good and bad samples and expecting it to solely learn from the good. If we take a step back, however, this is completely implausible, since a single sample is indistinguishable from any other, even comparing those that come from good trials and those from poor trials.</p><p>So, instead, we’ll be only looking at the samples that result in trials with high scores. That is, we want to filter the samples to only allow those that eventually result in high scores in their trials. In this case, we arbitrarily chose 50 to be the “minimum cutoff” to be considered a “good trial,” and only select those samples:</p><pre>def gather_data(env):<br>    min_score = 50<br>    sim_steps = 500<br>    trainingX, trainingY = [], []</pre><pre>    scores = []<br>    for _ in range(10000):<br>        observation = env.reset()<br>        score = 0<br>        training_sampleX, training_sampleY = [], []<br>        for step in range(sim_steps):<br>            action = np.random.randint(0, 2)<br>            one_hot_action = np.zeros(2)<br>            one_hot_action[action] = 1<br>            training_sampleX.append(observation)<br>            training_sampleY.append(one_hot_action)<br>            <br>            observation, reward, done, _ = env.step(action)<br>            score += reward<br>            if done:<br>                break<br>        if score &gt; min_score:<br>            scores.append(score)<br>            trainingX += training_sampleX<br>            trainingY += training_sampleY</pre><pre>    trainingX, trainingY = np.array(trainingX), np.array(trainingY)<br>    print(&quot;Average: {}&quot;.format(np.mean(scores)))<br>    print(&quot;Median: {}&quot;.format(np.median(scores)))<br>    return trainingX, trainingY</pre><p><strong>Model Definition</strong></p><p>Now that we have the data, we need to go about defining the model. Before doing any machine learning problem, it is always worthwhile stepping back to consider what it is we’re modelling, specifically what the expected inputs and desired results are. In our case, we’ll be receiving the current state of the environment (i.e. the “observations” from before) and wish to predict the probabilities of moving in each of the two directions. From this, we can easily figure out which of the two to take by taking the max arg.</p><p>The model we use here is a very simple one: several fully-connected layers (a.k.a. Dense layers in Keras). These are often the final layers used in deep CNNs (Convolution Neural Networks), since they are the ones that combine all the feature maps or input layers into the final scalar values. Fully-connected layers essentially make up the backbone of neural networks and are what allow them to effectively map high dimensional functions, ignoring all the modern enhancements with convolutions, LSTMs, Dropout, etc….</p><p>The only one of these enhancements that is relevant here is Dropout, since it helps ensure we do not overfit on the training data. So, we essentially sandwich a Dropout layer between each fully connected mapping to make sure that no one layer of the mapping becomes reliant on any small subset of connections that are specifically apparent in the training data.</p><p>Finally, we need to determine the loss function that we’ll train against. Since we encoded the output space as a one-hot 2D vector, the natural choice becomes categorical cross entropy, given that we wish to identify the result as either left ([1,0]) or right ([0,1]). I won’t go in-depth about what cross entropy entails, but it’s a very worthwhile function to understand, given its prevalence in these sorts of problems. From a high level, the cross entropy is, given two distributions (a true underlying distribution and our model thereof), a measure of how much information we need to convey something drawn from the true distribution by the model distribution.</p><p>Therefore, we define the model as:</p><pre>from keras.models import Sequential<br>from keras.layers import Dense, Dropout</pre><pre>def create_model():<br>    model = Sequential()<br>    model.add(Dense(128, input_shape=(4,), activation=&quot;relu&quot;))<br>    model.add(Dropout(0.6))<br>    <br>    model.add(Dense(256, activation=&quot;relu&quot;))<br>    model.add(Dropout(0.6))<br>    <br>    model.add(Dense(512, activation=&quot;relu&quot;))<br>    model.add(Dropout(0.6))<br>    <br>    model.add(Dense(256, activation=&quot;relu&quot;))<br>    model.add(Dropout(0.6))<br>    <br>    model.add(Dense(128, activation=&quot;relu&quot;))<br>    model.add(Dropout(0.6))<br>    model.add(Dense(2, activation=&quot;softmax&quot;))<br>    <br>    model.compile(<br>        loss=&quot;categorical_crossentropy&quot;,<br>        optimizer=&quot;adam&quot;,<br>        metrics=[&quot;accuracy&quot;])<br>    return model</pre><p>A few more subtle technical points of the model: each of the layers of the model have ReLU activations to allow the model to train more rapidly than with saturating activation functions, such as tanh and sigmoid. The model will likely also train in these cases, but would take far longer to converge than if using ReLU activation.</p><p><strong>Prediction</strong></p><p>From there, we can simply get our training data, train the model, and iterate through several trials to see how well our model performs!</p><pre>import gym<br>import numpy as np</pre><pre>from data import gather_data<br>from model import create_model</pre><pre>def predict():<br>    env = gym.make(&quot;CartPole-v0&quot;)<br>    trainingX, trainingY = gather_data(env)<br>    model = create_model()<br>    model.fit(trainingX, trainingY, epochs=5)<br>    <br>    scores = []<br>    num_trials = 50<br>    sim_steps = 500</pre><pre>    for trial in range(num_trials):<br>        observation = env.reset()<br>        score = 0<br>        for step in range(sim_steps):<br>            action = np.argmax(model.predict(<br>                observation.reshape(1,4)))<br>            observation, reward, done, _ = env.step(action)<br>            score += reward<br>            if done:<br>                break<br>        scores.append(score)<br>    <br>    print(np.mean(scores))</pre><p><strong>Full Code</strong></p><p>With that step-by-step, here is the complete source code of the OpenAI Cartpole Keras implementation!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/29f563acca747d39ac00edea433eaee4/href">https://medium.com/media/29f563acca747d39ac00edea433eaee4/href</a></iframe><p>Keep an eye out for the next Keras+OpenAI tutorial!</p><h3>Comment and click that ❤️ below to show support!</h3><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=698add10b4eb" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>