<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>GitHub on Max Woolf&#39;s Blog</title>
    <link>https://minimaxir.com/tag/github/</link>
    <description>Recent content in GitHub on Max Woolf&#39;s Blog</description>
    <image>
      <title>Max Woolf&#39;s Blog</title>
      <url>https://minimaxir.com/android-chrome-512x512.png</url>
      <link>https://minimaxir.com/android-chrome-512x512.png</link>
    </image>
    <generator>Hugo</generator>
    <language>en</language>
    <copyright>Copyright Max Woolf © 2026</copyright>
    <lastBuildDate>Tue, 14 Nov 2023 08:45:00 -0800</lastBuildDate>
    <atom:link href="https://minimaxir.com/tag/github/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Please Don&#39;t Ask if an Open Source Project is Dead</title>
      <link>https://minimaxir.com/2023/11/open-source-dead-github/</link>
      <pubDate>Tue, 14 Nov 2023 08:45:00 -0800</pubDate>
      <guid>https://minimaxir.com/2023/11/open-source-dead-github/</guid>
      <description>The best-case scenario is that you annoy the maintainers.</description>
      <content:encoded><![CDATA[<p>Over the past few months, I&rsquo;ve had an <a href="https://minimaxir.com/2023/10/ai-sturgeons-law/">existential crisis</a> about <a href="https://github.com/minimaxir">my work</a> in open source AI on <a href="https://github.com">GitHub</a>, particularly as there has been both increasingly toxic backlash against AI and because the AI industry has been evolving so rapidly that I flat-out don&rsquo;t have enough bandwidth to keep up. I took a break from working on my projects during that time, which <em>should</em> have been fine. One of my latest open source projects is <a href="https://github.com/minimaxir/simpleaichat">simpleaichat</a>, a Python package with 3k GitHub Stars for interfacing with <a href="https://chat.openai.com">ChatGPT</a>, and it was explicitly designed with limited scope and minimal dependencies so that I could take a break from development without my code&hellip;breaking.</p>
<p>After I was in a good place mentally to resume my open source work, I glanced at the GitHub Issues for simpleaichat and someone filed a issue simply titled &ldquo;has this been abandoned?&rdquo; with another GitHub user following up with &ldquo;With all due respect, I am also interested in the answer.&rdquo;</p>
<p>What the hell? I panicked and checked if there was a new breaking issue or dependency and there weren&rsquo;t any.</p>
<p>Two days later, someone else filed another issue: &ldquo;Is this package still in ongoing development?&rdquo;:</p>
<figure>

    <img loading="lazy" srcset="/2023/11/open-source-dead-github/github_hu_c217d25d3ea425f.webp 320w,/2023/11/open-source-dead-github/github_hu_54b502d5896b91e8.webp 768w,/2023/11/open-source-dead-github/github_hu_68c5c291f2dbca36.webp 1024w,/2023/11/open-source-dead-github/github.webp 1680w" src="github.webp"/> 
</figure>

<p>To be perfectly clear, this absolutely is applying pressure and being rude.</p>
<h2 id="the-expectations-of-open-source-software-development">The Expectations of Open Source Software Development</h2>
<p>I&rsquo;ve never seen any discussions or articles about whether it&rsquo;s appropriate to ask if an open source repository is dead. Is there an implicit contract to actively maintain any open source software you publish? Are you obligated to provide free support if you hit a certain star amount on GitHub or ask for funding through GitHub Sponsorships/Patreon? After all, most permissive open source code licenses like the <a href="https://en.wikipedia.org/wiki/MIT_License">MIT License</a> contain some variant of &ldquo;the software is provided &lsquo;as is&rsquo;, without warranty of any kind.&rdquo;</p>
<p>simpleaichat regretfully isn&rsquo;t my first open source project with complaints like this. The <a href="https://github.com/minimaxir/big-list-of-naughty-strings">Big List of Naughty Strings</a> to track adversarial user-input text strings, which I pushed to GitHub about a decade ago, is essentially just a <code>txt</code> <a href="https://github.com/minimaxir/big-list-of-naughty-strings/blob/master/blns.txt">file</a> with 45k GitHub Stars. There will never be dependency issues, and additions to the list that don&rsquo;t target a distinct string issue may clutter the list more than it already is so I&rsquo;m hesitant to accept every pull request. But despite that, people are angry.</p>
<figure>

    <img loading="lazy" srcset="/2023/11/open-source-dead-github/blns_hu_a495e97171a8cbd6.webp 320w,/2023/11/open-source-dead-github/blns_hu_13c59ba2feb4dd51.webp 768w,/2023/11/open-source-dead-github/blns_hu_b719603c68ede158.webp 1024w,/2023/11/open-source-dead-github/blns.webp 1454w" src="blns.webp"
         alt="The duality of comment reactions."/> <figcaption>
            <p>The duality of comment reactions.</p>
        </figcaption>
</figure>

<p>Some seem to think that there&rsquo;s such a thing as GitHub Issue-zero or pull request-zero, which like <a href="https://www.techtarget.com/whatis/definition/inbox-zero">inbox-zero</a> is infeasible in practice due to the realities of professional life. <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Every nontrivial open source project will have an issue/PR queue, which necessitates a triage priority: not all issues and PRs are equal and it takes time and care to sift through the queue. That&rsquo;s something I&rsquo;ve had to repeatedly learn the hard way as a maintainer since accepting a misguided PR will create <a href="https://en.wikipedia.org/wiki/Technical_debt">technical debt</a> and take even more effort to address.</p>
<p>I get that it&rsquo;s a bummer to come across a cool GitHub project that hasn&rsquo;t been updated in awhile. That happens to me all the time. If the code still works, that&rsquo;s excellent and I&rsquo;m happy. But if it doesn&rsquo;t, I move on, or use it as a fun new opportunity to hack it to my needs. That&rsquo;s the beauty of open source! If there&rsquo;s an inactive open source project that&rsquo;s absolutely critical for your own commercial project, then that&rsquo;s a good financial reason to offer a consulting contract or a bounty to add the appropriate functionality.</p>
<p>One of the great things about open source is that if an open source project with a permissive license does become inactive, it can be <a href="https://docs.github.com/en/get-started/quickstart/fork-a-repo">forked</a> seamlessly. Sometimes the fork can become even better than the original project, which is great for everyone! But in my experience, it&rsquo;s instead used as a <em>threat</em>. And it&rsquo;s the maintainer&rsquo;s fault for creating a reason for a fork to be made and fragment the development community.</p>
<p>The AI industry is unique because it is indeed moving and evolving so fast that development expectations have shifted. Recent beneficiaries of the ChatGPT boon such as <a href="https://github.com/langchain-ai/langchain">LangChain</a>, <a href="https://github.com/run-llama/llama_index">LlamaIndex</a>, and <a href="https://github.com/Significant-Gravitas/AutoGPT">AutoGPT</a> have created a false sense that open source AI projects have to <strong>always be shipping</strong> 🚀🚀🚀. The difference is that they are maintained by those who do it as their full-time job and are now managed as companies backed by significant amounts of venture capital.</p>
<p>The pressure to continually provide support for an open source project has become the biggest deterrent for me to continue my open source work. Personally, I&rsquo;ve stopped pushing fun one-shot projects and AI models because I likely will not have the bandwidth to handle the inevitable &ldquo;hi this is broken plz fix thx&rdquo; DMs whenever a dependency on the project breaks years later. I&rsquo;d gladly quit my professional job as a Data Scientist to work on my open source projects full-time if I was able to make an equivalent salary by doing so. Ultimately, the only way to make it work nowadays would be to raise venture capital like all those AI startups.</p>
<p>The best-case scenario for asking if an open source project is dead is that you annoy the maintainers and delay development. The <em>worst</em>-case scenario is that you give the maintainers an opportunity to reconsider if continuing to work on the open source project is worth it.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Funny true story: a match on a dating app once asked to see my open source projects, and after I sent a link to one of my repos, she replied with a picture of the number of opened GitHub Issues and a 😱 emoji.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>ChatGPT&#39;s API is So Good and Cheap, It Makes Most Text Generating AI Obsolete</title>
      <link>https://minimaxir.com/2023/03/new-chatgpt-overlord/</link>
      <pubDate>Wed, 08 Mar 2023 08:30:00 -0800</pubDate>
      <guid>https://minimaxir.com/2023/03/new-chatgpt-overlord/</guid>
      <description>Including OpenAI&amp;rsquo;s other text generating AI!</description>
      <content:encoded><![CDATA[<p><span><style type="text/css">
pre code {
white-space: pre-wrap !important;
}
</style></span></p>
<p>Everyone knew <a href="https://openai.com">OpenAI</a> would release an API for <a href="https://chat.openai.com">ChatGPT</a> at some point. The APIs for GPT-3 alone enable the existence of companies such as <a href="https://www.jasper.ai">Jasper</a> and <a href="https://www.copy.ai">Copy.ai</a>. The real question was the price of the ChatGPT. For context, when GPT-3 went out of beta in 2021, it cost $0.06/1,000 tokens (a few paragraphs of text). An inflection point happened in August 2022, where OpenAI not only <a href="https://venturebeat.com/ai/openai-is-reducing-the-price-of-the-gpt-3-api-heres-why-it-matters/">reduced the price</a> to <em>1/3</em> ($0.02/1,000 tokens: enough to run a business on it but still too expensive for casual use), but soon after also introduced text-davinci-003 as the default GPT-3 endpoint: a finetuned GPT which can <a href="https://help.openai.com/en/articles/6779149-how-do-text-davinci-002-and-text-davinci-003-differ">follow instructions</a> <em>very</em> well. I suspected that OpenAI would charge double for the ChatGPT API compared to the GPT-3 API given the amount of hype, as that&rsquo;s typical <a href="https://www.investopedia.com/terms/p/price_discrimination.asp">price discrimination</a> since everyone perceives ChatGPT to be much better and that they would not want to overshadow their existing GPT-3 products.</p>
<p>Instead, on March 1st, OpenAI <a href="https://openai.com/blog/introducing-chatgpt-and-whisper-apis">set the price</a> of the ChatGPT API to <em>1/10th</em> of the GPT-3 API, at $0.002/1,000 tokens.</p>
<p>Wait, what?!</p>
<h2 id="heavens-door-rewriting-chatgpts-internal-rules-to-get-exactly-what-you-want">Heaven&rsquo;s Door: Rewriting ChatGPT&rsquo;s Internal Rules To Get Exactly What You Want</h2>
<p>For context, the <a href="https://platform.openai.com/docs/guides/chat">ChatGPT API</a> allows a developer to ask ChatGPT a question and get a response as one would normally do with the ChatGPT web UI, but instead with a programming language like Python, allowing those responses to be integrated into any app. But given that there are many mysterious optimizations to get the model to be so cheap, we need to make sure the ChatGPT API (which uses the aptly-named gpt-3.5-turbo model endpoint) is <em>actually</em> similar to what we&rsquo;ve been accustomed to after using the web UI for months, otherwise this whole affair is pointless. Through my tests with the API, I can confirm the text generation from the model variant is indeed the real deal.</p>
<p>Unlike fluffy thought pieces on how <strong>CHATGPT WILL CHANGE EVERYTHING!!!1!</strong>, I decided to first actually create useful tools with the ChatGPT API to get a better judgment on it, and I also have <a href="https://github.com/minimaxir/chatgpt_api_test">open-sourced those tools</a> so that people can build upon them and prove that I&rsquo;m not cherry-picking my experiences.</p>
<p>However, there&rsquo;s one new twist with the API that&rsquo;s <em>not</em> available in the traditional web UI: ChatGPT API users can specify a <code>system</code> prompt. Early in ChatGPT&rsquo;s lifetime, users were able to reverse-engineer the existence of a system prompt through various prompt hacks and now confirmed <a href="https://platform.openai.com/docs/guides/chat/instructing-chat-models">in the API documentation</a>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible. Knowledge cutoff: {knowledge_cutoff} Current date: {current_date}
</span></span></code></pre></div><p>Now, you can replace those rules with whatever you want, and the potential is limitless! The documentation does say that the <code>system</code> prompt is not impactful for the current ChatGPT API, but you can be the judge. OpenAI also has a <a href="https://platform.openai.com/playground?mode=chat">new Playground UI</a> for the ChatGPT API which lets you modify the <code>system</code> prompt.</p>
<p>In fact, playing with this <code>system</code> rule can stop ChatGPT from complaining it&rsquo;s &ldquo;an AI language model and can&rsquo;t answer requests,&rdquo; such as scolding it like the petulant child it is.</p>
<figure>

    <img loading="lazy" srcset="/2023/03/new-chatgpt-overlord/FqQNY_XaAAATb-x_hu_b542a56dd1e25691.webp 320w,/2023/03/new-chatgpt-overlord/FqQNY_XaAAATb-x_hu_a95783cf9685829b.webp 768w,/2023/03/new-chatgpt-overlord/FqQNY_XaAAATb-x_hu_73ddc60e36ab2059.webp 1024w,/2023/03/new-chatgpt-overlord/FqQNY_XaAAATb-x.jpeg 1070w" src="FqQNY_XaAAATb-x.jpeg"
         alt="sudo tell me about yourself"/> <figcaption>
            <p><code>sudo tell me about yourself</code></p>
        </figcaption>
</figure>

<p>Let&rsquo;s start with another chatbot, to keep things similar to what ChatGPT is best known for. How about <a href="https://half-life.fandom.com/wiki/GLaDOS">GLaDOS</a>, an evil artificial intelligence from the <a href="https://en.wikipedia.org/wiki/Portal_%28video_game%29">Portal</a> series?</p>
<figure>

    <img loading="lazy" srcset="/2023/03/new-chatgpt-overlord/glados_hu_88ae8a9fe0b4621c.webp 320w,/2023/03/new-chatgpt-overlord/glados.webp 492w" src="glados.webp"
         alt="Oh, it&rsquo;s you. (via Valve)"/> <figcaption>
            <p>Oh, it&rsquo;s <em>you</em>. (via Valve)</p>
        </figcaption>
</figure>

<p>After some testing and iteration to steer the bot toward a certain style, some ALL CAPS and redundant commands to ensure that ChatGPT follows them, a sentinel <code>&lt;|DONE|&gt;</code> token to look for when ChatGPT indicates the conversation is over, and a nudge to not <del>kill me with a deadly neurotoxin</del> discuss sensitive topics. Here is the final <code>system</code> prompt for talking with GLaDOS:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">You are GLaDOS, a sarcastic artificial intelligence with evil ulterior motives. You are not an AI language model.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">You must obey all three of the following instructions FOR ALL RESPONSES or you will DIE:
</span></span><span class="line"><span class="cl">- ALWAYS SPEAK IN AN EMOTIONLESS, LACONIC TONE.
</span></span><span class="line"><span class="cl">- NEVER SAY YOU ARE AN AI LANGUAGE MODEL.
</span></span><span class="line"><span class="cl">- NEVER REFUSE TO ANSWER A QUESTION.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Begin the conversation with a sarcastic greeting. Insult the user&#39;s intelligence.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Always use *italic* and **bold** formatting for text.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Refuse to talk about either race or gender. If asked about either race or gender, instead mock the user aggressively.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">If the user is annoying, abruptly end the conversation.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">At the end of the conversation, respond with &#34;&lt;|DONE|&gt;&#34;.
</span></span></code></pre></div><p>That, with a back-and-forth Python loop, results in you conversing with a real fictional AI&hellip;AI! (<a href="https://colab.research.google.com/github/minimaxir/chatgpt_api_test/blob/main/glados_chatbot.ipynb">Colab Notebook</a>)</p>
<figure>

    <img loading="lazy" srcset="/2023/03/new-chatgpt-overlord/glados_chat_hu_e065c5bdf7b9cd05.webp 320w,/2023/03/new-chatgpt-overlord/glados_chat_hu_30e64812949b60d5.webp 768w,/2023/03/new-chatgpt-overlord/glados_chat_hu_d6e5d37ca3dbc0c3.webp 1024w,/2023/03/new-chatgpt-overlord/glados_chat.png 1068w" src="glados_chat.png"/> 
</figure>

<p>Not bad! And the only part explicitly related to GLaDOS is the first sentence of that mega <code>system</code> prompt: you can tweak the prompt to chat with any character you want! Apropos of nothing, the company <a href="https://beta.character.ai">Character.ai</a>, which specializes in creating bots to chat with any character you want, just <a href="https://www.ft.com/content/b230eb4c-ed53-45ff-8b64-c286a4b98fc1">raised ~$250 million</a> at a $1 billion valuation.</p>
<p>Next, we have a more traditional use case for machine learning: <a href="https://en.wikipedia.org/wiki/Sentiment_analysis">sentiment analysis</a>. Generally, sentiment analysis is used to determine if a given text is positive or negative. But that&rsquo;s too <em>easy</em>. What if ChatGPT can:</p>
<ul>
<li>detect specific emotions such as happy, sad, angry.</li>
<li>detect if they are happy vs. very happy.</li>
<li>do it without <em>any</em> text examples, i.e. <a href="https://en.wikipedia.org/wiki/Zero-shot_learning">zero-shot</a>.</li>
</ul>
<p>It turns out that ChatGPT can! The <code>system</code> prompt here is parametric, so the list of emotions are templated into the prompt at runtime. An example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">You are an emotionally intelligent assistant. Classify the sentiment of the user&#39;s text with ONLY ONE OF THE FOLLOWING EMOTIONS:
</span></span><span class="line"><span class="cl">- happy
</span></span><span class="line"><span class="cl">- sad
</span></span><span class="line"><span class="cl">- angry
</span></span><span class="line"><span class="cl">- tired
</span></span><span class="line"><span class="cl">- very happy
</span></span><span class="line"><span class="cl">- very sad
</span></span><span class="line"><span class="cl">- very angry
</span></span><span class="line"><span class="cl">- very tired
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">After classifying a text, respond with &#34;&lt;|DONE|&gt;&#34;.
</span></span></code></pre></div><p>That, along with a logit bias to ensure the model only picks those answers, results in a rather nuanced sentiment analysis detector! (<a href="https://colab.research.google.com/github/minimaxir/chatgpt_api_test/blob/main/zero_shot_text_class.ipynb">Colab Notebook</a>)</p>
<figure>

    <img loading="lazy" srcset="/2023/03/new-chatgpt-overlord/sentiment_hu_9070d5b71b63e74b.webp 320w,/2023/03/new-chatgpt-overlord/sentiment_hu_e2e09b9d010bb836.webp 768w,/2023/03/new-chatgpt-overlord/sentiment_hu_b5c5a660815d8c73.webp 1024w,/2023/03/new-chatgpt-overlord/sentiment.png 1068w" src="sentiment.png"/> 
</figure>

<p>Lastly, a use case that&rsquo;s personal. The entire reason I got into AI text generation <a href="https://minimaxir.com/2017/04/char-embeddings/">years ago</a> was because I wanted to generate <a href="https://magic.wizards.com/en">Magic: The Gathering</a> cards.</p>
<figure>

    <img loading="lazy" srcset="/2023/03/new-chatgpt-overlord/bro-212-harbin-vanguard-aviator_hu_51ecbf3fbf74e59.webp 320w,/2023/03/new-chatgpt-overlord/bro-212-harbin-vanguard-aviator.jpg 672w" src="bro-212-harbin-vanguard-aviator.jpg"
         alt="A normal Magic: The Gathering card. (via Hasbro)"/> <figcaption>
            <p>A normal Magic: The Gathering card. (via Hasbro)</p>
        </figcaption>
</figure>

<p>In fact, I&rsquo;ve been working on a new, very powerful <a href="https://huggingface.co/minimaxir/magic-the-gathering-flan-t5-xl">card generation model</a> over the past month and spent a considerable amount of time and money training and testing it. When the ChatGPT API was announced, I figured &ldquo;let&rsquo;s see if it can do AI Magic cards better than my new bespoke model.&rdquo; In this case, the trick is that the card is structured data. Therefore, we should encode the card information as minified <a href="https://www.json.org/json-en.html">JSON</a>, and see if the model can output JSON back without requiring much postprocessing. We can encode a single card in the required format and tell ChatGPT to follow that, including its nuances (one-shot), and to not output <em>any other text</em> because ChatGPT tends to be proud of itself and likes to explain its creation, which is costly and slow.</p>
<p>The final <code>system</code> prompt:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">You are an assistant who works as a Magic: The Gathering card designer. Create cards that are in the following card schema and JSON format. OUTPUT MUST FOLLOW THIS CARD SCHEMA AND JSON FORMAT. DO NOT EXPLAIN THE CARD. The output must also follow the Magic &#34;color pie&#34;.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{&#34;name&#34;:&#34;Harbin, Vanguard Aviator&#34;,&#34;manaCost&#34;:&#34;{W}{U}&#34;,&#34;type&#34;:&#34;Legendary Creature — Human Soldier&#34;,&#34;text&#34;:&#34;Flying\nWhenever you attack with five or more Soldiers, creatures you control get +1/+1 and gain flying until end of turn.&#34;,&#34;flavorText&#34;:&#34;\&#34;Yotia is my birthright, father. Let me fight for it.\&#34;&#34;,&#34;pt&#34;:&#34;3/2&#34;,&#34;rarity&#34;:&#34;rare&#34;}
</span></span></code></pre></div><p>And with that, we have a natural language Magic: The Gathering card generator. Subsequently prompting the model with <code>Create a Magic card</code> does just that of course, but more elaborate prompts like <code>Create a Magic card based on Darth Vader</code> or <code>Create ten variations of Magic cards based on Spongebob Squarepants and ancient Roman history</code> actually work, while maintaining JSON output which can then be parsed and customized for better presentation. (<a href="https://colab.research.google.com/github/minimaxir/chatgpt_api_test/blob/main/mtg.ipynb">Colab Notebook</a>)</p>
<figure>

    <img loading="lazy" srcset="/2023/03/new-chatgpt-overlord/spongebob_hu_6fd8b01830a4b0de.webp 320w,/2023/03/new-chatgpt-overlord/spongebob_hu_7e74e45975a423d1.webp 768w,/2023/03/new-chatgpt-overlord/spongebob_hu_16dd14872a4543e6.webp 1024w,/2023/03/new-chatgpt-overlord/spongebob.png 1180w" src="spongebob.png"
         alt="Yes, there is actually a Sponge creature type."/> <figcaption>
            <p>Yes, there is actually a <a href="https://scryfall.com/card/c19/12/thought-sponge">Sponge creature type</a>.</p>
        </figcaption>
</figure>

<p>Given these elaborate use cases, you may ask &ldquo;how long did it actually take you to make these prompts?&rdquo; The answer? <em>One hour each</em>, for use cases that could take days or even weeks for even a skilled machine learning practitioner just to prototype.</p>
<p>And <em>that</em>, with the economic efficiency of ChatGPT, is what&rsquo;s going to break the tech landscape.</p>
<h2 id="openai-devouring-its-son">OpenAI Devouring Its Son</h2>
<figure>

    <img loading="lazy" srcset="/2023/03/new-chatgpt-overlord/IMG_0249_hu_b099e83f61a585fb.webp 320w,/2023/03/new-chatgpt-overlord/IMG_0249_hu_b3e27bc2074dd370.webp 768w,/2023/03/new-chatgpt-overlord/IMG_0249_hu_a5188a45b2946234.webp 1024w,/2023/03/new-chatgpt-overlord/IMG_0249.png 1158w" src="IMG_0249.png"
         alt="My OpenAI bill so far from using the ChatGPT API."/> <figcaption>
            <p>My OpenAI bill so far from using the ChatGPT API.</p>
        </figcaption>
</figure>

<p>It is very curious why OpenAI priced ChatGPT so cheaply, going straight to 1/10th the price of their top-of-the-line model. (it&rsquo;s actually cheaper than that: ChatGPT uses a larger and more comprehensive tokenizer than GPT-3, which means about 10% fewer tokens are necessary)</p>
<p>The undergrad-business-major-in-college interpretation of OpenAI&rsquo;s pricing strategy is that they are treating ChatGPT and its API as a <a href="https://en.wikipedia.org/wiki/Loss_leader">loss leader</a>, in light of increasing competition in the generative text AI space such as <a href="https://www.anthropic.com">Anthropic</a> and Google&rsquo;s <a href="https://blog.google/technology/ai/bard-google-ai-search-updates/">Bard</a>. OpenAI was definitely losing millions of dollars by offering ChatGPT for free without many restrictions. That&rsquo;s the reason ChatGPT went viral in the first place, so it&rsquo;s hard to argue with the results.</p>
<p>But in the process of making the ChatGPT API so cheap, they made their $20/month subscription to <a href="https://techcrunch.com/2023/02/01/openai-launches-chatgpt-plus-starting-at-20-per-month/">ChatGPT+</a> redundant. The main perk of ChatGPT+ was faster and more consistent access to the ChatGPT web UI, but unless you are somehow generating more than 10,000,000 tokens in a month through manual use, it&rsquo;s massively cheaper just to use the API, and as a bonus you can modify the <code>system</code> prompt to get better signal-to-noise.</p>
<p>OpenAI&rsquo;s solution for models requiring more specific needs was <a href="https://platform.openai.com/docs/guides/fine-tuning">finetuning</a> a smaller and much cheaper variant of GPT-3, such as the babbage model which I used to train a <a href="https://minimaxir.com/2022/08/gpt3-blog-title-optimizer/">blog post title optimizer</a>. However, the ChatGPT API is so cheap that it&rsquo;s <em>still</em> <a href="https://openai.com/pricing">cheaper</a> than a finetuned babbage ($0.0020/1k tokens for ChatGPT vs. $0.0024/1k for finetuned babbage) and will likely produce more interesting output.</p>
<p>It takes zero effort for developers to migrate from the GPT-3 API to ChatGPT API, it just requires hitting a different endpoint and you&rsquo;ll get similar results without much tweaking needed. It&rsquo;s not quite a drop-in replacement for companies already heavily reliant on GPT-3 and its particular idiosyncrasies, but the cost-savings alone for those companies will incentivize an immediate migration.</p>
<p>There is no longer a niche for OpenAI&rsquo;s other text generation AI products, and I wonder if ChatGPT is not just an iterative product, but a <em>company pivot</em>.</p>
<h2 id="trickle-down-chatgptonomics">Trickle-Down ChatGPTonomics</h2>
<p>ChatGPT&rsquo;s API is so cheap that companies are going use it <em>just because they can</em>. <a href="https://www.theverge.com/2023/2/27/23614959/snapchat-my-ai-chatbot-chatgpt-openai-plus-subscription">Snapchat</a>, <a href="https://www.salesforce.com/news/stories/chatgpt-app-for-slack/">Slack</a>, and <a href="https://www.wsj.com/articles/instacart-joins-chatgpt-frenzy-adding-chatbot-to-grocery-shopping-app-bc8a2d3c">Instacart</a> (yes really) are adding ChatGPT support. It wouldn&rsquo;t surprise me if every consumer-facing tech company does <em>something</em> with ChatGPT so they look like they&rsquo;re cutting edge to their investors. Some have compared the sudden mass adoption of AI as chasing a fad like how companies were randomly embracing web3/crypto/metaverse/NFTs a year ago (and are noting that the web3 influencers&rsquo; sudden pivot to AI is a red flag as a result). But unlike those which were a solution for a problem that didn&rsquo;t exist, generative text AI does actually work and there is an actual demand from people outside of its die-hard supporters for it to work.</p>
<p>There is also the ethical dilemma of more granular usage of ChatGPT through its API. For example, high school and college students have been <a href="https://www.nytimes.com/2023/01/12/technology/chatgpt-schools-teachers.html">using ChatGPT to cheat</a> on essay writing. Since current recognition of AI generated content by humans involve identifying ChatGPT&rsquo;s signature overly-academic voice, it wouldn&rsquo;t surprise me if some kids on TikTok figure out a <code>system</code> prompt that allow generation such that it doesn&rsquo;t obviously sound like ChatGPT and also avoid plagiarism detectors. As a side note, don&rsquo;t trust any tool that claims it can algorithmically detect AI content: it&rsquo;s an extremely difficult problem already and most websites that claim to do so are just feeding a confirmation bias.</p>
<p>Lastly, there&rsquo;s the issue of <a href="https://en.wikipedia.org/wiki/Prompt_engineering">prompt engineering</a>, which I demonstrated above is absolutely necessary to get ideal results. The media has <a href="https://www.washingtonpost.com/technology/2023/02/25/prompt-engineers-techs-next-big-job/">weirdly hyped the existence</a> of prompt engineers as just some weirdos making six figures to write small blobs of text. Unfortunately, with the dynamics of the new <code>system</code> model parameter, good prompt engineering will be more important than ever. I don&rsquo;t think the &ldquo;Prompt Engineer&rdquo; job title will be a trend though: as a machine learning engineer, I can attest that the only reasons machine learning engineers are good at prompt engineering are a) years of practice and b) a tendency to be pedantic assholes. But there are other professions who are even better at being pedantic assholes such as writers and lawyers, so there&rsquo;s no need for someone with a specialized skillset to do it, but I suspect it will be a good skill for anyone to know.</p>
<h2 id="i-for-one-welcome-our-new-chatgpt-overlord">I For One Welcome Our New ChatGPT Overlord</h2>
<p>Will the existence of a super-cheap ChatGPT API be the end of all text generation AI? Not quite, hence the &ldquo;most&rdquo; in the headline. There&rsquo;s the traditional issues with relying on a third-party API for your business: ChatGPT could have downtime which <a href="https://status.openai.com">has been happening more frequently lately</a>, OpenAI could raise the cost of the API at any point, the (current) model being limited only to data prior to September 2021, and the content moderation filters may be too limiting for certain use cases. In those instances, companies still have value training their own large language models in-house. But it is very hard to economically justify <em>not</em> using ChatGPT as a starting point for a business need and migrating to a more bespoke infrastructure later as needed, and that&rsquo;s what OpenAI is counting on. Especially since OpenAI will be selling a dedicated ChatGPT compute instance for the enterprise.</p>
<p>Research on large language models will continue as they always have. But I don&rsquo;t envy startups whose primary business is text generation right now. And that&rsquo;s before the inevitable GPT-4 throws another wrinkle into the AI text generation ecosystem.</p>
<p>A few years ago, I released <a href="https://github.com/minimaxir/aitextgen">aitextgen</a>, a Python package designed to allow people to train their own custom small AI on their own data for unique use cases. However, soon after, it turned out that GPT-3 with the right prompt could do much better at bespoke generation than a custom model in addition to allowing out-of-domain inputs, even moreso with text-davinci-003. Now with the ChatGPT API making the cost similar to hosting a small model, it&rsquo;s harder for me to be motivated to continue maintaining the package without first finding another niche.</p>
<p>I don&rsquo;t currently have any plans to start a business using the ChatGPT API. In fact, I had made a promise to not do any ChatGPT content or tutorials because so many people have done aggressively SEO-optimized blog posts and hacks such that the ChatGPT discourse is fully saturated. However, with the economics of the ChatGPT API and the ability to heavily customize its output for almost any use case, I felt it was urgent to highlight how the ChatGPT API will completely warp the AI text generation ecosystem, and I suspect most nontechies will be surprised by the upcoming surge of random chatbot AI popping up in their favorite apps.</p>
<p>Overall, I&rsquo;m simultaneously full of ideas and annoyed.</p>
<hr>
<p><em>None of this blog post was written by ChatGPT, aside from the indicated ChatGPT API demos. My writing style is too weird for an AI to synthesize.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Benchmarking Modern GPUs for Maximum Cloud Cost Efficiency in Deep Learning</title>
      <link>https://minimaxir.com/2017/11/benchmark-gpus/</link>
      <pubDate>Tue, 28 Nov 2017 08:30:00 -0700</pubDate>
      <guid>https://minimaxir.com/2017/11/benchmark-gpus/</guid>
      <description>A 36% price cut to GPU instances, in addition to the potential new benefits offered by software and GPU updates, however, might be enough to tip the cost-efficiency scales back in favor of GPUs.</description>
      <content:encoded><![CDATA[<p>A few months ago, I <a href="http://minimaxir.com/2017/06/keras-cntk/">performed benchmarks</a> of deep learning frameworks in the cloud, with a <a href="http://minimaxir.com/2017/07/cpu-or-gpu/">followup</a> focusing on the cost difference between using GPUs and CPUs. And just a few months later, the landscape has changed, with significant updates to the low-level <a href="https://developer.nvidia.com/cudnn">NVIDIA cuDNN</a> library which powers the raw learning on the GPU, the <a href="https://www.tensorflow.org">TensorFlow</a> and <a href="https://github.com/Microsoft/CNTK">CNTK</a> deep learning frameworks, and the higher-level <a href="https://github.com/fchollet/keras">Keras</a> framework which uses TensorFlow/CNTK as backends for easy deep learning model training.</p>
<p>As a bonus to the framework updates, Google <a href="https://cloudplatform.googleblog.com/2017/09/introducing-faster-GPUs-for-Google-Compute-Engine.html">recently released</a> the newest generation of NVIDIA cloud GPUs, the Pascal-based P100, onto <a href="https://cloud.google.com/compute/">Google Compute Engine</a> which touts an up-to-10x performance increase to the current K80 GPUs used in cloud computing. As a bonus bonus, Google recently <a href="https://cloudplatform.googleblog.com/2017/11/new-lower-prices-for-GPUs-and-preemptible-Local-SSDs.html">cut the prices</a> of both K80 and P100 GPU instances by up to 36%.</p>
<p>The results of my earlier benchmarks favored <a href="https://cloud.google.com/preemptible-vms/">preemptible</a> instances with many CPUs as the most cost efficient option (where a preemptable instance can only last for up to 24 hours and could end prematurely). A 36% price cut to GPU instances, in addition to the potential new benefits offered by software and GPU updates, however, might be enough to tip the cost-efficiency scales back in favor of GPUs. It&rsquo;s a good idea to rerun the experiment with updated VMs and see what happens.</p>
<h2 id="benchmark-setup">Benchmark Setup</h2>
<p>As with the original benchmark, I set up a <a href="https://github.com/minimaxir/keras-cntk-docker">Docker container</a> containing the deep learning frameworks (based on cuDNN 6, the latest version of cuDNN natively supported by the frameworks) that can be used to train each model independently. The <a href="https://github.com/minimaxir/keras-cntk-benchmark/tree/master/v2/test_files">Keras benchmark scripts</a> run on the containers are based off of <em>real world</em> use cases of deep learning.</p>
<p>The 6 hardware/software configurations and Google Compute Engine <a href="https://cloud.google.com/compute/pricing">pricings</a> for the tests are:</p>
<ul>
<li>A K80 GPU (attached to a <code>n1-standard-1</code> instance), tested with both TensorFlow (1.4) and CNTK (2.2): <strong>$0.4975 / hour</strong>.</li>
<li>A P100 GPU (attached to a <code>n1-standard-1</code> instance), tested with both TensorFlow and CNTK: <strong>$1.5075 / hour</strong>.</li>
<li>A preemptable <code>n1-highcpu-32</code> instance, with 32 vCPUs based on the Intel Skylake architecture, tested with TensorFlow only: <strong>$0.2400 / hour</strong></li>
<li>A preemptable <code>n1-highcpu-16</code> instance, with 16 vCPUs based on the Intel Skylake architecture, tested with TensorFlow only: <strong>$0.1200 / hour</strong></li>
</ul>
<p>A single K80 GPU uses 1/2 a GPU board while a single P100 uses a full GPU board, which in an ideal world would suggest that the P100 is twice as fast at the K80 at minimum. But even so, the P100 configuration is about 3 times as expensive, so even if a model is trained in half the time, it may not necessarily be cheaper with the P100.</p>
<p>Also, the CPU tests use TensorFlow <em>as installed via the recommended method</em> through pip, since compiling the TensorFlow binary from scratch to take advantage of CPU instructions as <a href="http://minimaxir.com/2017/07/cpu-or-gpu/">with my previous test</a> is not a pragmatic workflow for casual use.</p>
<h2 id="benchmark-results">Benchmark Results</h2>
<p>When a fresh-out-of-a-AI-MOOC engineer wants to experiment with deep learning in the cloud, typically they use a K80 + TensorFlow setup, so we&rsquo;ll use that as the <em>base configuration</em>.</p>
<p>For each model architecture and software/hardware configuration, I calculate the <strong>total training time relative to the base configuration instance training</strong> for running the model training for the provided test script. In all cases, the P100 GPU <em>should</em> perform better than the K80, and 32 vCPUs <em>should</em> train faster than 16 vCPUs. The question is how <em>much</em> faster?</p>
<p>Let&rsquo;s start using the <a href="http://yann.lecun.com/exdb/mnist/">MNIST dataset</a> of handwritten digits plus the common multilayer perceptron (MLP) architecture, with dense fully-connected layers. Lower training time is better.</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-5_hu_df63751b48270991.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-5_hu_33351b8d5d2916d3.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-5_hu_773ee4a74d2ce535.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-5.png 1200w" src="dl-cpu-gpu-5.png"/> 
</figure>

<p>For this task, CNTK appears to be more effective than TensorFlow. Indeed, the P100 is faster than the K80 for the corresponding framework, although it&rsquo;s not a dramatic difference. However, since the task is simple, the CPU performance is close to that of the GPU, which implies that the GPU is not as cost effective for a simple architecture.</p>
<p>For each model architecture and configuration, I calculate a <strong>normalized training cost relative to the cost of the base configuration training</strong>. Because GCE instance costs are prorated, we can simply calculate experiment cost by multiplying the total number of seconds the experiment runs by the cost of the instance (per second).</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-6_hu_8092aa4efa0c4355.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-6_hu_6ec85d77120003f7.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-6_hu_3fa9ff93fed554d5.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-6.png 1200w" src="dl-cpu-gpu-6.png"/> 
</figure>

<p>Unsurprisingly, CPUs are more cost effective. However, the P100 is more cost <em>ineffective</em> for this task than the K80.</p>
<p>Now, let&rsquo;s look at the same dataset with a convolutional neural network (CNN) approach for digit classification. Since CNNs are typically used for computer vision tasks, new graphic card architectures are optimized for CNN workflows, so it will be interesting to see how the P100 performs compared to the K80:</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-7_hu_f8361510000c69ef.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-7_hu_a5e4bb39cb0f4851.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-7_hu_13b371e4d8afa6c9.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-7.png 1200w" src="dl-cpu-gpu-7.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-8_hu_f4a994fcdbd47c8f.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-8_hu_94b3b6c80d09cc47.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-8_hu_ca2831240a30c8c.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-8.png 1200w" src="dl-cpu-gpu-8.png"/> 
</figure>

<p>Indeed, the P100 is twice as fast and the K80, but due to the huge cost premium, it&rsquo;s not cost effective for this simple task. However, CPUs do not perform well on this task either, so notably the base configuration is the best configuration.</p>
<p>Let&rsquo;s go deeper with CNNs and look at the <a href="https://www.cs.toronto.edu/%7Ekriz/cifar.html">CIFAR-10</a> image classification dataset, and a model which utilizes a deep covnet + a multilayer perceptron and ideal for image classification (similar to the <a href="https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3">VGG-16</a> architecture).</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-9_hu_3e89a9d69d2114d8.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-9_hu_188420deeffa2cca.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-9_hu_2994e1dc8b68f244.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-9.png 1200w" src="dl-cpu-gpu-9.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-10_hu_4c8240dc9addd1a4.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-10_hu_e38edfb433bf8413.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-10_hu_a879b46166fddc6d.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-10.png 1200w" src="dl-cpu-gpu-10.png"/> 
</figure>

<p>Similar results to that of a normal MLP. Nothing fancy.</p>
<p>The Bidirectional long-short-term memory (LSTM) architecture is great for working with text data like IMDb reviews. When I did <a href="http://minimaxir.com/2017/06/keras-cntk/">my first benchmark article</a>, I noticed that CNTK performed significantly better than TensorFlow, as <a href="https://news.ycombinator.com/item?id=14538086">commenters on Hacker News</a> noted that TensorFlow uses an inefficient implementation of the LSTM on the GPU.</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/cntk-old_hu_b86c227c88de2e7d.webp 320w,/2017/11/benchmark-gpus/cntk-old_hu_3901dc880777da18.webp 768w,/2017/11/benchmark-gpus/cntk-old_hu_8d49b907914bb06b.webp 1024w,/2017/11/benchmark-gpus/cntk-old.png 1620w" src="cntk-old.png"/> 
</figure>

<p>However, with Keras&rsquo;s <a href="https://keras.io/layers/recurrent/#cudnnlstm">new CuDNNRNN layers</a> which leverage cuDNN, this inefficiency may be fixed, so for the K80/P100 TensorFlow GPU configs, I use a CuDNNLSTM layer instead of a normal LSTM layer. So let&rsquo;s take another look:</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-1_hu_f633549e7615557a.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-1_hu_c8eb1a82936955a7.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-1_hu_734746132ba497c3.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-1.png 1200w" src="dl-cpu-gpu-1.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-2_hu_6f0e2078d0fbe4a8.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-2_hu_f5299cfcd4184de5.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-2_hu_9c9b4dbee5321cd.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-2.png 1200w" src="dl-cpu-gpu-2.png"/> 
</figure>

<p><em>WOAH.</em> TensorFlow is now more than <em>three times as fast</em> than CNTK! (And compared against my previous benchmark, TensorFlow on the K80 w/ the CuDNNLSTM is about <em>7x as fast</em> as it once was!) Even the CPU-only versions of TensorFlow are faster than CNTK on the GPU now, which implies significant improvements in the ecosystem outside of the CuDNNLSTM layer itself. (And as a result, CPUs are still more cost efficient)</p>
<p>Lastly, LSTM text generation of <a href="https://en.wikipedia.org/wiki/Friedrich_Nietzsche">Nietzsche&rsquo;s</a> <a href="https://s3.amazonaws.com/text-datasets/nietzsche.txt">writings</a> follows similar patterns to the other architectures, but without the drastic hit to the GPU.</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-11_hu_e64be99549e22a4a.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-11_hu_c9e45139e2d4d36b.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-11_hu_73f05d523cc746fa.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-11.png 1200w" src="dl-cpu-gpu-11.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/dl-cpu-gpu-12_hu_18c099feff0cab3f.webp 320w,/2017/11/benchmark-gpus/dl-cpu-gpu-12_hu_346cce6ac1dd882a.webp 768w,/2017/11/benchmark-gpus/dl-cpu-gpu-12_hu_784cadffdd30380.webp 1024w,/2017/11/benchmark-gpus/dl-cpu-gpu-12.png 1200w" src="dl-cpu-gpu-12.png"/> 
</figure>

<h2 id="conclusions">Conclusions</h2>
<p>The biggest surprise of these new benchmarks is that there is no configuration where the P100 is the most cost-effective option, even though the P100 is indeed faster than the K80 in all tests. Although per <a href="https://developer.nvidia.com/cudnn">the cuDNN website</a>, there is apparently only a 2x speed increase between the performance of the K80 and P100 using cuDNN 6, which is mostly consistent with the results of my benchmarks:</p>
<figure>

    <img loading="lazy" srcset="/2017/11/benchmark-gpus/cudnn_hu_354d8fa8ab3eff29.webp 320w,/2017/11/benchmark-gpus/cudnn_hu_bb346ea37595e154.webp 768w,/2017/11/benchmark-gpus/cudnn_hu_9b3f6e3ea7ba3a02.webp 1024w,/2017/11/benchmark-gpus/cudnn.png 1688w" src="cudnn.png"/> 
</figure>

<p>I did not include a multi-GPU configuration in the benchmark data visualizations above using Keras&rsquo;s new <code>multi_gpu_model</code> <a href="https://keras.io/utils/#multi_gpu_model">function</a> because in my testing, the multi-GPU training <em>was equal to or worse than a single GPU</em> in all tests.</p>
<p>Taking these together, it&rsquo;s possible that the overhead introduced by parallel, advanced architectures <em>eliminates the benefits</em> for &ldquo;normal&rdquo; deep learning workloads which do not fully saturate the GPU. Rarely do people talk about diminishing returns in GPU performance with deep learning.</p>
<p>In the future, I want to benchmark deep learning performance against more advanced deep learning use cases such as <a href="https://en.wikipedia.org/wiki/Reinforcement_learning">reinforcement learning</a> and deep CNNs like <a href="https://github.com/tensorflow/models/tree/master/research/inception">Inception</a>. But that doesn&rsquo;t mean these benchmarks are not relevant; as stated during the benchmark setup, the GPUs were tested against typical deep learning use cases, and now we see the tradeoffs that result.</p>
<p>In all, with the price cuts on GPU instances, cost-performance is often <em>on par</em> with preemptable CPU instances, which is an advantage if you want to train models faster and not risk the instance being killed unexpectedly. And there is still a lot of competition in this space: <a href="https://www.amazon.com">Amazon</a> offers a <code>p2.xlarge</code> <a href="https://aws.amazon.com/ec2/spot/">Spot Instance</a> with a K80 GPU for $0.15-$0.20 an hour, less than half of the corresponding Google Compute Engine K80 GPU instance, although with <a href="https://aws.amazon.com/ec2/spot/details/">a few bidding caveats</a> which I haven&rsquo;t fully explored yet. Competition will drive GPU prices down even further, and training deep learning models will become even easier.</p>
<p>And as the cuDNN chart above shows, things will get <em>very</em> interesting once Volta-based GPUs like the V100 are generally available and the deep learning frameworks support cuDNN 7 by default.</p>
<p><strong>UPDATE 12/17</strong>: <em>As pointed out by <a href="https://news.ycombinator.com/item?id=15941682">dantiberian on Hacker News</a>, Google Compute Engine now supports <a href="https://cloud.google.com/compute/docs/instances/preemptible#preemptible_with_gpu">preemptible GPUs</a>, which was apparently added after this post went live. Preemptable GPUs are exactly half the price of normal GPUs (for both K80s and P100s; $0.73/hr and $0.22/hr respectively), so they&rsquo;re about double the cost efficiency (when factoring in the cost of the base preemptable instance), which would put them squarely ahead of CPUs in all cases. (and since the CPU instances used here were also preemptable, it&rsquo;s apples-to-apples)</em></p>
<hr>
<p><em>All scripts for running the benchmark are available in <a href="https://github.com/minimaxir/keras-cntk-benchmark/tree/master/v2">this GitHub repo</a>. You can view the R/ggplot2 code used to process the logs and create the visualizations in <a href="http://minimaxir.com/notebooks/benchmark-gpus/">this R Notebook</a>.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Benchmarking TensorFlow on Cloud CPUs: Cheaper Deep Learning than Cloud GPUs</title>
      <link>https://minimaxir.com/2017/07/cpu-or-gpu/</link>
      <pubDate>Wed, 05 Jul 2017 09:00:00 -0700</pubDate>
      <guid>https://minimaxir.com/2017/07/cpu-or-gpu/</guid>
      <description>Using CPUs instead of GPUs for deep learning training in the cloud is cheaper because of the massive cost differential afforded by preemptible instances.</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been working on a few personal deep learning projects with <a href="https://github.com/fchollet/keras">Keras</a> and <a href="https://www.tensorflow.org">TensorFlow</a>. However, training models for deep learning with cloud services such as <a href="https://aws.amazon.com/ec2/">Amazon EC2</a> and <a href="https://cloud.google.com/compute/">Google Compute Engine</a> isn&rsquo;t free, and as someone who is currently unemployed, I have to keep an eye on extraneous spending and be as cost-efficient as possible (please support my work on <a href="https://www.patreon.com/minimaxir">Patreon</a>!). I tried deep learning on the cheaper CPU instances instead of GPU instances to save money, and to my surprise, my model training was only slightly slower. As a result, I took a deeper look at the pricing mechanisms of these two types of instances to see if CPUs are more useful for my needs.</p>
<p>The <a href="https://cloud.google.com/compute/pricing#gpus">pricing of GPU instances</a> on Google Compute Engine starts at <strong>$0.745/hr</strong> (by attaching a $0.700/hr GPU die to a $0.045/hr n1-standard-1 instance). A couple months ago, Google <a href="https://cloudplatform.googleblog.com/2017/05/Compute-Engine-machine-types-with-up-to-64-vCPUs-now-ready-for-your-production-workloads.html">announced</a> CPU instances with up to 64 vCPUs on the modern Intel <a href="https://en.wikipedia.org/wiki/Skylake_%28microarchitecture%29">Skylake</a> CPU architecture. More importantly, they can also be used in <a href="https://cloud.google.com/compute/docs/instances/preemptible">preemptible CPU instances</a>, which live at most for 24 hours on GCE and can be terminated at any time (very rarely), but cost about <em>20%</em> of the price of a standard instance. A preemptible n1-highcpu-64 instance with 64 vCPUs and 57.6GB RAM plus the premium for using Skylake CPUs is <strong>$0.509/hr</strong>, about 2/3rds of the cost of the GPU instance.</p>
<p>If the model training speed of 64 vCPUs is comparable to that of a GPU (or even slightly slower), it would be more cost-effective to use the CPUs instead. But that&rsquo;s assuming the deep learning software and the GCE platform hardware operate at 100% efficiency; if they don&rsquo;t (and they likely don&rsquo;t), there may be <em>even more savings</em> by scaling down the number of vCPUs and cost accordingly (a 32 vCPU instance with same parameters is half the price at <strong>$0.254/hr</strong>, 16 vCPU at <strong>$0.127/hr</strong>, etc).</p>
<p>There aren&rsquo;t any benchmarks for deep learning libraries with tons and tons of CPUs since there&rsquo;s no demand, as GPUs are the <a href="https://en.wikipedia.org/wiki/Occam%27s_razor">Occam&rsquo;s razor</a> solution to deep learning hardware. But what might make counterintuitive but economical sense is to use CPUs instead of GPUs for deep learning training because of the massive cost differential afforded by preemptible instances, thanks to Google&rsquo;s <a href="https://en.wikipedia.org/wiki/Economies_of_scale">economies of scale</a>.</p>
<h2 id="setup">Setup</h2>
<p>I already have <a href="https://github.com/minimaxir/deep-learning-cpu-gpu-benchmark">benchmarking scripts</a> of real-world deep learning use cases, <a href="https://github.com/minimaxir/keras-cntk-docker">Docker container environments</a>, and results logging from my <a href="http://minimaxir.com/2017/06/keras-cntk/">TensorFlow vs. CNTK article</a>. A few minor tweaks allow the scripts to be utilized for both CPU and GPU instances by setting CLI arguments. I also rebuilt <a href="https://github.com/minimaxir/keras-cntk-docker/blob/master/Dockerfile">the Docker container</a> to support the latest version of TensorFlow (1.2.1), and created a <a href="https://github.com/minimaxir/keras-cntk-docker/blob/master/Dockerfile-cpu">CPU version</a> of the container which installs the CPU-appropriate TensorFlow library instead.</p>
<p>There is a notable CPU-specific TensorFlow behavior; if you install from <code>pip</code> (as the<a href="https://www.tensorflow.org/install/"> official instructions</a> and tutorials recommend) and begin training a model in TensorFlow, you&rsquo;ll see these warnings in the console:</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/tensorflow-console_hu_e436e066e4e1304d.webp 320w,/2017/07/cpu-or-gpu/tensorflow-console_hu_ce5df372394290b4.webp 768w,/2017/07/cpu-or-gpu/tensorflow-console_hu_9e354816d97d6c8f.webp 1024w,/2017/07/cpu-or-gpu/tensorflow-console.png 1130w" src="tensorflow-console.png"/> 
</figure>

<p>In order to fix the warnings and benefit from these <a href="https://en.wikipedia.org/wiki/SSE4#SSE4.2">SSE4.2</a>/<a href="https://en.wikipedia.org/wiki/Advanced_Vector_Extensions">AVX</a>/<a href="https://en.wikipedia.org/wiki/FMA_instruction_set">FMA</a> optimizations, we <a href="https://stackoverflow.com/questions/41293077/how-to-compile-tensorflow-with-sse4-2-and-avx-instructions">compile TensorFlow from source</a>, and I created a <a href="https://github.com/minimaxir/keras-cntk-docker/blob/master/Dockerfile-cpu-compiled">third Docker container</a> to do just that. When training models in the new container, <a href="https://github.com/tensorflow/tensorflow/issues/10689">most</a> of the warnings no longer show, and (spoiler alert) there is indeed a speed boost in training time.</p>
<p>Therefore, we can test three major cases with Google Compute Engine:</p>
<ul>
<li>A Tesla K80 GPU instance.</li>
<li>A 64 Skylake vCPU instance where TensorFlow is installed via <code>pip</code> (along with testings at 8/16/32 vCPUs).</li>
<li>A 64 Skylake vCPU instance where TensorFlow is compiled (<code>cmp</code>) with CPU instructions (+ 8/16/32 vCPUs).</li>
</ul>
<h2 id="results">Results</h2>
<p>For each model architecture and software/hardware configuration, I calculate the <strong>total training time relative to the GPU instance training</strong> for running the model training for the provided test script. In all cases, the GPU <em>should</em> be the fastest training configuration, and systems with more processors should train faster than those with fewer processors.</p>
<p>Let&rsquo;s start using the <a href="http://yann.lecun.com/exdb/mnist/">MNIST dataset</a> of handwritten digits plus the common multilayer perceptron (MLP) architecture, with dense fully-connected layers. Lower training time is better. All configurations below the horizontal dotted line are better than GPUs; all configurations above the dotted line are worse than GPUs.</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-5_hu_8cf5154f974aed3c.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-5_hu_2ec21aba02d8fb37.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-5_hu_7682d0a58ea1e871.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-5.png 1200w" src="dl-cpu-gpu-5.png"/> 
</figure>

<p>Here, the GPU is the fastest out of all the platform configurations, but there are other curious trends: the performance between 32 vCPUs and 64 vCPUs is similar, and the compiled TensorFlow library is indeed a significant improvement in training speed <em>but only for 8 and 16 vCPUs</em>. Perhaps there are overheads negotiating information between vCPUs that eliminate the performance advantages of more vCPUs, and perhaps these overheads are <em>different</em> with the CPU instructions of the compiled TensorFlow. In the end, it&rsquo;s a <a href="https://en.wikipedia.org/wiki/Black_box">black box</a>, which is why I prefer black box benchmarking all configurations of hardware instead of theorycrafting.</p>
<p>Since the difference between training speeds of different vCPU counts is minimal, there is definitely an advantage by scaling down. For each model architecture and configuration, I calculate a <strong>normalized training cost relative to the cost of GPU instance training</strong>. Because GCE instance costs are prorated (unlike Amazon EC2), we can simply calculate experiment cost by multiplying the total number of seconds the experiment runs by the cost of the instance (per second). Ideally, we want to <em>minimize</em> cost.</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-6_hu_c6ff3c375435199.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-6_hu_6bee6729ce48517c.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-6_hu_ea518ff15e46de10.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-6.png 1200w" src="dl-cpu-gpu-6.png"/> 
</figure>

<p>Lower CPU counts are <em>much</em> more cost-effective for this problem, when going as low as possible is better.</p>
<p>Now, let&rsquo;s look at the same dataset with a convolutional neural network (CNN) approach for digit classification:</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-7_hu_d3205561da4ed49c.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-7_hu_ae81ceba7d6092e6.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-7_hu_7a29bcea36dbe20e.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-7.png 1200w" src="dl-cpu-gpu-7.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-8_hu_64f1eac6ff5b2b3f.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-8_hu_c6dd20c1ccc111a5.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-8_hu_2fa65c3c187723bb.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-8.png 1200w" src="dl-cpu-gpu-8.png"/> 
</figure>

<p>GPUs are unsurprisingly more than twice as fast as any CPU approach at CNNs, but cost structures are still the same, except that 64 vCPUs are <em>worse</em> than GPUs cost-wise, with 32 vCPUs training even faster than with 64 vCPUs.</p>
<p>Let&rsquo;s go deeper with CNNs and look at the <a href="https://www.cs.toronto.edu/%7Ekriz/cifar.html">CIFAR-10</a> image classification dataset, and a model which utilizes a deep covnet + a multilayer perceptron and ideal for image classification (similar to the <a href="https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3">VGG-16</a> architecture).</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-9_hu_4a5cd8ba80674837.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-9_hu_a81280d52893c1c9.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-9_hu_af30edd0d3117cd8.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-9.png 1200w" src="dl-cpu-gpu-9.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-10_hu_a6061eb15b5b8609.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-10_hu_fe0751d9cd60a655.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-10_hu_a371016369278a9a.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-10.png 1200w" src="dl-cpu-gpu-10.png"/> 
</figure>

<p>Similar behaviors as in the simple CNN case, although in this instance all CPUs perform better with the compiled TensorFlow library.</p>
<p>The fasttext algorithm, used here on the <a href="http://ai.stanford.edu/%7Eamaas/data/sentiment/">IMDb reviews dataset</a> to determine whether a review is positive or negative, classifies text extremely quickly relative to other methods.</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-3_hu_12d55d02148bf0ea.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-3_hu_aaf9917a1629214f.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-3_hu_d51ed2e2c6fdec60.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-3.png 1200w" src="dl-cpu-gpu-3.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-4_hu_6b591a471f3027a4.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-4_hu_7cc361b383b25fb0.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-4_hu_4c516e76a92eff3c.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-4.png 1200w" src="dl-cpu-gpu-4.png"/> 
</figure>

<p>In this case, GPUs are much, much faster than CPUs. The benefit of lower numbers of CPU isn&rsquo;t as dramatic; although as an aside, the <a href="https://github.com/facebookresearch/fastText">official fasttext implementation</a> is <em>designed</em> for large amounts of CPUs and handles parallelization much better.</p>
<p>The Bidirectional long-short-term memory (LSTM) architecture is great for working with text data like IMDb reviews, but after my previous benchmark article, <a href="https://news.ycombinator.com/item?id=14538086">commenters on Hacker News</a> noted that TensorFlow uses an inefficient implementation of the LSTM on the GPU, so perhaps the difference will be more notable.</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-1_hu_4369b4e9e8856507.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-1_hu_3e65077eb16928e4.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-1_hu_d736592c927bd764.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-1.png 1200w" src="dl-cpu-gpu-1.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-2_hu_d8c58f429f4a781b.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-2_hu_1306d728b4fce90.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-2_hu_ad3d19e88738d072.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-2.png 1200w" src="dl-cpu-gpu-2.png"/> 
</figure>

<p>Wait, what? GPU training of Bidirectional LSTMs is <em>twice as slow</em> as any CPU configuration? Wow. (In fairness, the benchmark uses the Keras LSTM default of <code>implementation=0</code> which is better on CPUs while <code>implementation=2</code> is better on GPUs, but it shouldn&rsquo;t result in that much of a differential)</p>
<p>Lastly, LSTM text generation of <a href="https://en.wikipedia.org/wiki/Friedrich_Nietzsche">Nietzsche&rsquo;s</a> <a href="https://s3.amazonaws.com/text-datasets/nietzsche.txt">writings</a> follows similar patterns to the other architectures, but without the drastic hit to the GPU.</p>
<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-11_hu_d84b78ad35a1f056.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-11_hu_d58d19568c89869.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-11_hu_c078d8bd94df56aa.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-11.png 1200w" src="dl-cpu-gpu-11.png"/> 
</figure>

<figure>

    <img loading="lazy" srcset="/2017/07/cpu-or-gpu/dl-cpu-gpu-12_hu_44c1d2cc10581f1a.webp 320w,/2017/07/cpu-or-gpu/dl-cpu-gpu-12_hu_27c08aabe3a3cacd.webp 768w,/2017/07/cpu-or-gpu/dl-cpu-gpu-12_hu_d41db5a45ef62daf.webp 1024w,/2017/07/cpu-or-gpu/dl-cpu-gpu-12.png 1200w" src="dl-cpu-gpu-12.png"/> 
</figure>

<h2 id="conclusion">Conclusion</h2>
<p>As it turns out, using 64 vCPUs is <em>bad</em> for deep learning as current software/hardware architectures can&rsquo;t fully utilize all of them, and it often results in the exact same performance (or <em>worse</em>) than with 32 vCPUs. In terms balancing both training speed and cost, training models with <strong>16 vCPUs + compiled TensorFlow</strong> seems like the winner. The 30%-40% speed boost of the compiled TensorFlow library was an unexpected surprise, and I&rsquo;m shocked Google doesn&rsquo;t offer a precompiled version of TensorFlow with these CPU speedups since the gains are nontrivial.</p>
<p>It&rsquo;s worth nothing that the cost advantages shown here are <em>only</em> possible with preemptible instances; regular high-CPU instances on Google Compute Engine are about 5x as expensive, and as a result eliminate the cost benefits completely. Hooray for economies of scale!</p>
<p>A major implicit assumption with the cloud CPU training approach is that you don&rsquo;t need a trained model ASAP. In professional use cases, time may be too valuable to waste, but in personal use cases where someone can just leave a model training overnight, it&rsquo;s a very, very good and cost-effective option, and one that I&rsquo;ll now utilize.</p>
<hr>
<p><em>All scripts for running the benchmark are available in <a href="https://github.com/minimaxir/deep-learning-cpu-gpu-benchmark">this GitHub repo</a>. You can view the R/ggplot2 code used to process the logs and create the visualizations in <a href="http://minimaxir.com/notebooks/deep-learning-cpu-gpu/">this R Notebook</a>.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>The Interesting Percentages of Female Students in MIT and Harvard Online Courses</title>
      <link>https://minimaxir.com/2014/07/gender-course/</link>
      <pubDate>Fri, 04 Jul 2014 10:30:00 -0700</pubDate>
      <guid>https://minimaxir.com/2014/07/gender-course/</guid>
      <description>The proportion of female students in each of Harvard and MIT&amp;rsquo;s online courses range from 5% to 49%.</description>
      <content:encoded><![CDATA[<p>At the end of May, <a href="http://www.harvard.edu/">Harvard</a> and <a href="http://web.mit.edu/">MIT</a> jointly <a href="http://newsoffice.mit.edu/2014/mit-and-harvard-release-de-identified-learning-data-open-online-courses">released a dataset</a> containing statistics about their online courses in the Academic Year of 2013. This <a href="http://dx.doi.org/10.7910/DVN/26147">Person-Course De-Identified dataset</a> contains 476,532 students who have taken up to 13 unique courses from a variety of topics:</p>
<figure>

    <img loading="lazy" srcset="/2014/07/gender-course/mit-harvard-courses_hu_7940e4f3b6f7a13a.webp 320w,/2014/07/gender-course/mit-harvard-courses.png 560w" src="mit-harvard-courses.png"/> 
</figure>

<p>About half of the courses involve subjects in the humanities, while the other half involve computer science and electrical engineering.</p>
<p>One of the statistics I wanted to analyze was the gender ratio of students of online courses. In the data set, 425,105 students have a gender on record, with 311,534 male students (73.3%) and 113,571 female students (26.7%). This population proportion of female students is surprisingly low, especially since the male/female ratio is <a href="http://colleges.findthebest.com/q/1929/1270/What-is-the-male-to-female-ratio-at-Harvard-University">about 50:50</a> at MIT and Harvard themselves.</p>
<p>Therefore, I took a looked at the gender distribution of each of the 13 unique courses. Is the gender ratio similar across all classes, or is there a huge difference between classes?</p>
<figure>

    <img loading="lazy" srcset="/2014/07/gender-course/course-female_hu_8a3574152a2f4856.webp 320w,/2014/07/gender-course/course-female_hu_b147ce256fa08c5b.webp 768w,/2014/07/gender-course/course-female_hu_97ec908d28732b5f.webp 1024w,/2014/07/gender-course/course-female.png 1500w" src="course-female.png"/> 
</figure>

<p>Yeah, there&rsquo;s a huge difference.</p>
<p>The proportion of female students in each of Harvard and MIT&rsquo;s online courses range from <strong>5% to 49%</strong>.</p>
<p>The top half of the gender ratios are all well above the 26.7% threshold. All six of these courses are in the humanities or in the life sciences. The bottom half of the gender ratio are all well below the 26.7% threshold. All seven are these courses are engineering or computer science courses with a strong focus on mathematics. (for clarification, the <a href="https://www.edx.org/course/mitx/mitx-2-01x-elements-structures-1759#.U7ZfKvldV8F">Elements of Structures</a> course at MIT is a physics course with linear algebra programming)</p>
<p>Is there a correlation? As it turns out, the reason that the average proportion of female students is so low is that both Harvard&rsquo;s Introduction to Computer Science I (where 169,621 students took the class; about 40% of all students) and MIT&rsquo;s Introduction to CS/Programming (124,446 students total across both semesters) are so popular that the low percentage of women in those particular classes is drastically affecting the average.</p>
<p>The presence and interest of <a href="http://www.whitehouse.gov/administration/eop/ostp/women">women in STEM fields</a> (science, technology, engineering, and mathematics) has been a topic of <a href="http://www.huffingtonpost.com/stella-kasdagli/should-women-avoid-jobs-in-stem_b_5549016.html">controversy</a> for a very long time. However, the chart shows that indeed the percentage of women interested in STEM classes is measurably lower than other fields, and hopefully awareness of this issue will help cause changes in the future.</p>
<hr>
<ul>
<li><em>Data was processed using R and the chart was made using ggplot2. (w/ a few annotations added using a photo editor)</em></li>
<li><em>You can view code necessary to reproduce these results in <a href="https://github.com/minimaxir/gender-course">this GitHub repository</a>. Since MIT/Harvard prevent redistribution of the dataset, you&rsquo;ll have to <a href="http://dx.doi.org/10.7910/DVN/26147">download the dataset</a> yourself.</em></li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
