{
    "componentChunkName": "component---src-templates-blog-post-js",
    "path": "/i-fine-tuned-gpt-2-on-my-commit-messages-im-sorry/",
    "result": {"data":{"site":{"siteMetadata":{"title":"catch { snail }","author":"Andrew"}},"markdownRemark":{"id":"c7da3764-3eb0-523d-bd3e-d8149b7dfd57","excerpt":"At the end of the last post I threatened to fine-tune GPT-2 on my own commit messages. Well, we’re all locked at home now, so no more excuses. Getting the data…","html":"<p>At the end of the <a href=\"/playing-with-gpt-2-text-generation-in-python/\">last post</a> I threatened to fine-tune GPT-2 on my own commit messages. Well, we’re all locked at home now, so no more excuses.</p>\n<h2 id=\"getting-the-data\" style=\"position:relative;\"><a href=\"#getting-the-data\" aria-label=\"getting the data permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Getting the data</h2>\n<p>First, scrape commit messages out of every repo I could find on my machine:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token keyword\">for</span> <span class=\"token for-or-select variable\">repo</span> <span class=\"token keyword\">in</span> ~/projects/*/<span class=\"token punctuation\">;</span> <span class=\"token keyword\">do</span>\n  <span class=\"token function\">git</span> -C <span class=\"token string\">\"<span class=\"token variable\">$repo</span>\"</span> log --all --pretty<span class=\"token operator\">=</span>format:<span class=\"token string\">\"%s\"</span> <span class=\"token operator\">>></span> commits.txt\n  <span class=\"token builtin class-name\">echo</span> <span class=\"token operator\">>></span> commits.txt\n<span class=\"token keyword\">done</span>\n\n<span class=\"token function\">sort</span> -u commits.txt <span class=\"token operator\">></span> commits_clean.txt\n<span class=\"token function\">wc</span> -l commits_clean.txt\n<span class=\"token comment\"># 3124</span></code></pre></div>\n<p>3,124 unique commit messages. That is a <em>tiny</em> dataset by language model standards, which becomes important later.</p>\n<h2 id=\"fine-tuning\" style=\"position:relative;\"><a href=\"#fine-tuning\" aria-label=\"fine tuning permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Fine-tuning</h2>\n<p>The <code class=\"language-text\">transformers</code> repo ships an example script for this — <code class=\"language-text\">run_language_modeling.py</code> (it was called <code class=\"language-text\">run_lm_finetuning.py</code> until a few weeks ago, most tutorials still use the old name). Training on my laptop CPU was hopeless, so like everyone else in 2020 I did it on a free Google Colab GPU:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">python run_language_modeling.py <span class=\"token punctuation\">\\</span>\n  --model_name_or_path gpt2 <span class=\"token punctuation\">\\</span>\n  --model_type gpt2 <span class=\"token punctuation\">\\</span>\n  --do_train <span class=\"token punctuation\">\\</span>\n  --train_data_file commits_clean.txt <span class=\"token punctuation\">\\</span>\n  --line_by_line <span class=\"token punctuation\">\\</span>\n  --block_size <span class=\"token number\">64</span> <span class=\"token punctuation\">\\</span>\n  --per_gpu_train_batch_size <span class=\"token number\">8</span> <span class=\"token punctuation\">\\</span>\n  --num_train_epochs <span class=\"token number\">3</span> <span class=\"token punctuation\">\\</span>\n  --output_dir gpt2-commits <span class=\"token punctuation\">\\</span>\n  --overwrite_output_dir</code></pre></div>\n<p>That’s the small 124M model. Three epochs over 3k lines takes about ten minutes on the Colab K80.</p>\n<h2 id=\"the-horror-as-promised\" style=\"position:relative;\"><a href=\"#the-horror-as-promised\" aria-label=\"the horror as promised permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The horror, as promised</h2>\n<p>Sampling from the fine-tuned model:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">fix bug in fix\nremove console.log for real this time\nfinal fix (final) v2\nupdate readme to match the code that no longer exists\nWIP: everything\nadd tests, disable tests\nrefactor the refactor\nfix typo in previous typo</code></pre></div>\n<p>I genuinely cannot tell some of these apart from my real commit history, which says more about my commit history than about the model.</p>\n<h2 id=\"what-i-actually-learned\" style=\"position:relative;\"><a href=\"#what-i-actually-learned\" aria-label=\"what i actually learned permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What I actually learned</h2>\n<p>The interesting part wasn’t the jokes, it was watching what a language model does with a dataset this small:</p>\n<p><strong>It memorizes.</strong> By epoch 3 the training loss was still dropping, but a lot of “generated” samples were my real commit messages, verbatim. With 3k examples the model isn’t learning the <em>style</em> of commit messages so much as compressing my git history into its weights. If I’d trained 10 epochs it would basically be a lossy <code class=\"language-text\">commits.txt</code>. This is the overfitting/memorization tradeoff everyone hand-waves about, visible in ten minutes on a free GPU.</p>\n<p><strong>Temperature is everything.</strong> At low temperature it plays it safe (“fix bug”, “update readme” forever). Around 0.9–1.0 you get the creative nonsense above. Higher and it starts inventing words.</p>\n<p><strong>One epoch was probably enough.</strong> The epoch-1 checkpoint produced messages that were on-style but <em>new</em>. More training made it more accurate and less interesting — for a toy like this, “less overfit” is literally funnier.</p>\n<h2 id=\"next\" style=\"position:relative;\"><a href=\"#next\" aria-label=\"next permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Next</h2>\n<p>I have a half-working <code class=\"language-text\">prepare-commit-msg</code> git hook that asks the model to suggest a message from the diff. It is wrong 100% of the time but with confidence. Maybe a post on that if quarantine lasts long enough.</p>","frontmatter":{"title":"I fine-tuned GPT-2 on my commit messages (I'm sorry)","date":"March 21, 2020","description":"Fine-tuning GPT-2 small on 3,000 of my own git commit messages, with predictable results"}}},"pageContext":{"slug":"/i-fine-tuned-gpt-2-on-my-commit-messages-im-sorry/","previous":{"fields":{"slug":"/playing-with-gpt-2-text-generation-in-python/"},"frontmatter":{"title":"Playing with GPT-2 text generation in Python"}},"next":{"fields":{"slug":"/my-ai-writes-the-commit-message-first-then-i-write-the-code/"},"frontmatter":{"title":"My AI writes the commit message first. Then I write the code"}}}},
    "staticQueryHashes": ["3435731857","426816048","63159454"]}