<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://davidenunes.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://davidenunes.com/" rel="alternate" type="text/html" /><updated>2022-06-23T22:35:50+00:00</updated><id>https://davidenunes.com/feed.xml</id><title type="html">Davide Nunes</title><subtitle>Davide Nunes personal website</subtitle><author><name>Davide Nunes</name></author><entry><title type="html">Python Autodocs with MkGenDocs</title><link href="https://davidenunes.com/mkgendocs/" rel="alternate" type="text/html" title="Python Autodocs with MkGenDocs" /><published>2020-12-21T00:00:00+00:00</published><updated>2020-12-21T00:00:00+00:00</updated><id>https://davidenunes.com/mkgendocs</id><content type="html" xml:base="https://davidenunes.com/mkgendocs/">&lt;h1 id=&quot;mkgendocs&quot;&gt;mkgendocs&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/davidenunes/mkgendocs&quot; target=&quot;_blank&quot;&gt;mkgendocs&lt;/a&gt; is a
Python package for automatically generating documentation pages in &lt;strong&gt;markdown&lt;/strong&gt;
from Python source files, by parsing Google-style &lt;strong&gt;docstring&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/automation_python.png&quot; alt=&quot;python automation&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you search for automated documentation generators for Python (or any language
really), half the Web will tell you that relying on auto-documentation tools
instead of writing good useful documentation by hand, is a bad practice. They
are partially right, but real projects are not a salty thread from Reddit, so
take all the advice, like anything else, critically!&lt;/p&gt;

&lt;p&gt;Open source project success can depend on how well you communicate about it with
your community, and good documentation is an important component of this
process. Nevertheless, there is something to be said about generating useful
documentation from existing source files. In the case of Python, &lt;strong&gt;docstrings&lt;/strong&gt;
are at the frontline of your project documentation. Not every project will
benefit from a publicly documented API, but some will (e.g. a library of
re-usable components). Creating reference documentation is essencial when the
number of components in a library or framework is extensive. Examples of such
projects include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://numpy.org/doc/stable/reference/index.html&quot;&gt;NumPy Reference&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf&quot;&gt;Tensorflow API&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pytorch.org/docs/stable/&quot;&gt;PyTorch API&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scikit-learn.org/stable/modules/classes.html&quot;&gt;scikit-learn API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These examples include API reference documentation that is generated and linked
to the original source files (usually hosted on publicly available online
repositories).&lt;/p&gt;

&lt;h2 id=&quot;from-sphinx-to-mkdocs&quot;&gt;From Sphinx to MkDocs&lt;/h2&gt;
&lt;p&gt;The most feature-complete documentation generator for Python is without a doubt &lt;a href=&quot;https://www.sphinx-doc.org/en/master/index.html&quot;&gt;Sphinx&lt;/a&gt;. It is robust and feature rich, it can be made to work with other markdown languages besides &lt;a href=&quot;https://docutils.sourceforge.io/rst.html&quot;&gt;reStructuredText&lt;/a&gt;, and different styles of docstrings with extensions like &lt;a href=&quot;Support for NumPy and Google style docstrings&quot;&gt;napoleon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.mkdocs.org/&quot;&gt;MkDocs&lt;/a&gt; on the other hand, is a static documentation website generator from Markdown. It has less features, but being more simple it also requires less extensions and configuration. Overall, it has a lower barrier of entry for someone wanting to start deploying documentation for a project. One of the downsides of MkDocs, is the fact that doesn’t include robust plugins for automatically building API documentation from docstrings. This led me to create &lt;a href=&quot;https://github.com/davidenunes/mkgendocs&quot; target=&quot;_blank&quot;&gt;mkgendocs&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;beautiful-documentation-for-python-projects&quot;&gt;Beautiful Documentation for Python Projects&lt;/h2&gt;

&lt;p&gt;I was leaning towards MkDocs because of themes like &lt;a href=&quot;https://squidfunk.github.io/mkdocs-material/&quot;&gt;Material for
MkDocs&lt;/a&gt;. The theme follows the
spirit of Google’s material design guidelines. It is responsive, great on mobile
devices, and highly customizable. It also offers a search bar with live updates,
automated table of contents, among other features such as support for
&lt;a href=&quot;https://squidfunk.github.io/mkdocs-material/reference/mathjax/&quot;&gt;MathJax&lt;/a&gt;,
&lt;a href=&quot;https://squidfunk.github.io/mkdocs-material/reference/admonitions/&quot;&gt;Admonitions&lt;/a&gt;,
etc. This makes for documentation that is not only good looking, but easy to
navigate, comprehend, and generally pleasant to use.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/davidenunes/mkgendocs&quot; target=&quot;_blank&quot;&gt;mkgendocs&lt;/a&gt; provides
a simple tool that takes existing Python source files and generates API
documentation pages that work well with Material for MkDocs.&lt;/p&gt;

&lt;p class=&quot;notice--warning&quot;&gt;For now it only supports Google style docstrings.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/assets/images/posts/mkgendocs.png&quot;&gt;&lt;img src=&quot;/assets/images/posts/mkgendocs.png&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;Example of API documentation generation for &lt;a href=&quot;https://tensorx.org&quot;&gt;TensorX&lt;/a&gt; library.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If a repository url is provided, mkgendocs uses this to automatically link the generated API documentation pages to the source files online.&lt;/p&gt;

&lt;p class=&quot;notice--warning&quot;&gt;For now I only added support for Github. Should not be difficult to add and test the source code linking feature for other providers.&lt;/p&gt;

&lt;h2 id=&quot;getting-started-with-mkgendocs&quot;&gt;Getting started with mkgendocs&lt;/h2&gt;

&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;

&lt;p&gt;Install mkgendocs from &lt;a href=&quot;https://pypi.org/project/mkgendocs/&quot;&gt;PyPI&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mkgendocs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;usage&quot;&gt;Usage&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gendocs &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt; mkgendocs.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A sources directory is created with the documentation that was automatically generated.
Any examples in a “examples” directory are automatically copied over to the documentation, 
the module level docstrings of any example source files are also copied and converted to markdown.&lt;/p&gt;

&lt;h3 id=&quot;configuration-example&quot;&gt;Configuration Example&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;sources_dir&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;docs/sources&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;templates_dir&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;docs/templates&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/davidenunes/tensorx&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#link to sources on github&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;master&lt;/span&gt;                               &lt;span class=&quot;c1&quot;&gt;#link to sources on github&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;pages&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;api/train/model.md&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tensorx/train/model.py&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;train&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;set_optimizer&lt;/span&gt;
  
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;api/layers/core.md&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tensorx/layers.py'&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;classes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;compute_shape&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Module&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;math.md&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tensorx/math.py'&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;functions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sparse_multiply_dense&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# creates an index page based on everything from target source&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;api/layers/index.md&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tensorx/layers.py&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;sources_dir&lt;/strong&gt;: directory where the resulting markdown files are created&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;templates_dir&lt;/strong&gt;: directory where template files can be stored. All the
folders and files are copied to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sources_dir&lt;/code&gt;. Any markdown files are used
as templates with the tag `` in the template files being
replaced by the generated documentation.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;repo&lt;/strong&gt;: repository to create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;view source&lt;/code&gt; links automatically for each
class, function, and method;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;version&lt;/strong&gt;: defaults to “master” to create link to sources in the form
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://repo/blob/version/file.py/#L1425&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;pages&lt;/strong&gt;: list of pages to be automatically generated from the respective
source files and templates:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;page&lt;/strong&gt;: path for page template / sources dir for the resulting page;&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;source&lt;/strong&gt;: path to source file from which the page is to be generated;&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;classes&lt;/strong&gt;: list of classes to be fully documented; a list of method
  names can be passed for each class, the default is to generate all
  methods;&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;functions&lt;/strong&gt;: list of functions to be documented.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;index&lt;/strong&gt;: if True creates an index page for the given sources, you can also
specify classes and functions, but not methods&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;thank-you&quot;&gt;Thank you&lt;/h2&gt;

&lt;p&gt;Thank you for your interest. This is very much a work in progress, evolving
according to my own needs, but if you find any of this useful, consider getting
me some coffee, coffee is great!&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
&lt;a href=&quot;https://ko-fi.com/Y8Y0RZO6&quot; target=&quot;_blank&quot;&gt;&lt;img height=&quot;36&quot; style=&quot;border:0px;height:36px;&quot; src=&quot;https://az743702.vo.msecnd.net/cdn/kofi3.png?v=0&quot; border=&quot;0&quot; alt=&quot;Buy Me a Coffee at ko-fi.com&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content><author><name>Davide Nunes</name></author><category term="tools" /><category term="python" /><category term="technical" /><category term="documentation" /><category term="api" /><summary type="html">Generating documentation from Python docstrings</summary></entry><entry><title type="html">Git Good</title><link href="https://davidenunes.com/git-good/" rel="alternate" type="text/html" title="Git Good" /><published>2020-09-01T00:00:00+00:00</published><updated>2020-09-01T00:00:00+00:00</updated><id>https://davidenunes.com/git-good</id><content type="html" xml:base="https://davidenunes.com/git-good/">&lt;p&gt;&lt;img src=&quot;/assets/images/git_illustration.png&quot; alt=&quot;git ilustration&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Git is a free and open source distributed Version Control System (VCS). Git can
be hard, especially for people discovering it for the first time, but there are
a lot of things that make this an exceptional VCS worth learning. This post is
not meant to be a git tutorial, but rather a compilation of things and tips I
find interesting. I also wanted to give a perspective of git independent of
services like GitHub. Hopefully you can find something useful and “&lt;em&gt;git better
at it&lt;/em&gt;” 🙃.&lt;/p&gt;

&lt;p&gt;If you’re looking to learn how to use git, take a look at the &lt;a href=&quot;https://git-scm.com/book/en/v2/&quot;&gt;Pro Git
book&lt;/a&gt;, it’s free and it is a great resource!&lt;/p&gt;

&lt;h2 id=&quot;git-is-not-github-&quot;&gt;Git is not GitHub 😮&lt;/h2&gt;

&lt;p&gt;Services like &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; made git particularly popular, but
the convenience of something like Github has its downsides for new users: it
causes confusion about the differences between &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; or
&lt;a href=&quot;https://gitlab.com/&quot;&gt;GitLab&lt;/a&gt;, and the actual version control system, &lt;em&gt;git&lt;/em&gt;.
While the former are great to host git repositories and make them publicly
available (among other things), git is a piece of software designed to allow for
distributed version control and collaboration. This means that you can use it
offline, without GitHub, you can collaborate with people via chat, email, and
anything that allows you to send text to someone else. Yes, GitHub makes it
convenient to host your project and make it discoverable; it provides an
incentive for collaboration, but, at the end of the day, GitHub is not git, just
as Gmail is not e-mail.&lt;/p&gt;

&lt;h2 id=&quot;git-is-distributed-&quot;&gt;Git is distributed 🖧&lt;/h2&gt;

&lt;p&gt;For those used to GitHub, collaborating with git over e-mail might seem
anachronistic, but, consider the scale of projects and what git was designed to
do. Being able to send contributions as plain text allied with the threaded
nature of e-mail, means that you can have multiple discussions around certain
aspects of a contribution, which is a big plus. Linux kernel development, for
example, doesn’t happen on GitHub or GitLab. From the linux kernel GitHub Pull
requests (GitHub’s system for submitting contributions):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Thanks for your contribution to the Linux kernel!&lt;/p&gt;

  &lt;p&gt;Linux kernel development happens on mailing lists, rather than on GitHub -
this GitHub repository is a read-only mirror that isn’t used for accepting
contributions. So that your change can become part of Linux, please email it
to us as a patch.&lt;/p&gt;

  &lt;p&gt;Sending patches isn’t quite as simple as sending a pull request, but
fortunately it is a well documented process.&lt;/p&gt;

  &lt;p&gt;Here’s what to do:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Format your contribution according to kernel requirements&lt;/li&gt;
    &lt;li&gt;Decide who to send your contribution to&lt;/li&gt;
    &lt;li&gt;Set up your system to send your contribution as an email&lt;/li&gt;
    &lt;li&gt;Send your contribution and wait for feedback&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;The development happens on various mailing lists for multiple subsystems. It’s
distributed development to an unprecedented scale. This scale has a price,
discipline in your contributions, something that GitHub doesn’t really help
reinforce –which seems to be the whole
&lt;a href=&quot;https://github.com/torvalds/linux/pull/17#issuecomment-5654674&quot;&gt;issue&lt;/a&gt; that the
creator of git Linus Torvalds has with it.&lt;/p&gt;

&lt;h3 id=&quot;git-daemon-&quot;&gt;Git daemon 🌐&lt;/h3&gt;

&lt;p&gt;Focusing the development on a centralised service like GitHub can feel like
you’re using an improved version of Subversion client/server approach, but
remember, git is truly a decentralized system and we can do better. Suppose you
don’t want to use GitHub, but want to make your repository available for other
people to clone, pull from, etc. Git supports Peer-to-Peer setup out of the box
with &lt;a href=&quot;https://git-scm.com/book/en/v2/Git-on-the-Server-Git-Daemon&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
daemon&lt;/code&gt;&lt;/a&gt;.
Collaboration then happens on each peer local copy of the source tree and some
form of communication channel (e.g. e-mail, chat, etc).&lt;/p&gt;

&lt;p&gt;From your git folder you can execute the following command&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git daemon &lt;span class=&quot;nt&quot;&gt;--export-all&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--base-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--reuseaddr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enable=upload-pack&lt;/code&gt;: (enabled by default) allows for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git fetch&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--export-all&lt;/code&gt;: means that you don’t have to create a file named git-daemon-export-ok in each exported repository.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--base-path&lt;/code&gt;: allows people to clone projects without specifying the entire
path. Example: if you start the daemon with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--base-path=/srv/git&lt;/code&gt; and try to
pull from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git://example.com/hello.git&lt;/code&gt;, git daemon will interpret the path as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/git/hello.git&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--reuseaddr&lt;/code&gt;: allows the server to restart without waiting for old connections to time out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congratulations, your machine is now running a git server and anyone can do:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git://192.168.1.42/  &lt;span class=&quot;c&quot;&gt;#Your IP&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
git remote add Foo git://192.168.1.42/
git fetch Foo
git checkout develop
git push Foo develop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;git-patches-&quot;&gt;Git patches 📝&lt;/h3&gt;

&lt;p&gt;As we have discussed, git is a decentralized system, you can send contributions
to anyone without the need of a centralized git repository. This is not only the
default way of collaborating with git, it is particularly useful when a server
is down, or if you don’t have permissions to write to a remote repository
—but would still like to propose changes.&lt;/p&gt;

&lt;p&gt;You can create a patch from your current changes without committing the code on
your source tree:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# changes in the working tree not yet staged for commit&lt;/span&gt;
git diff &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; big-improvements.patch
&lt;span class=&quot;c&quot;&gt;# or changes between the index and your last commit;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# what you would be committing if you run &quot;git commit&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# without &quot;-a&quot; option.&lt;/span&gt;
git diff &lt;span class=&quot;nt&quot;&gt;--cached&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; big-improvements.patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As an example suppose the change is the addition of a README file, the diff
would look like this:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gh&quot;&gt;diff --git a/README b/README
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;new file mode 100644
&lt;/span&gt;&lt;span class=&quot;gh&quot;&gt;index 0000000..e69de29
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;More often, what we would like to do is to propose a change we have made in your
local source tree. To do this, we can use the &lt;a href=&quot;https://git-scm.com/docs/git-format-patch&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
format-patch&lt;/code&gt;&lt;/a&gt; command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git format-patch master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;if we have commits ahead of the master branch, a diff file will be generated. We can also reference other commits in the same branch.
Suppose we made changes in the current branch and want to reference the changes in relation to the last commit. We can do:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git format-patch HEAD~1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;the patch file will contain something like:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;From daf1010eb425a67ca6b0ba60f7cbec15bcff31f1 Mon Sep 17 00:00:00 2001
From: John Doe &amp;lt;heresjohnny@bestmail.com&amp;gt;
Date: Tue, 09 Sep 2020 15:42:00 +0100
Subject: [PATCH] Update README
&lt;/span&gt;
---
 README | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README b/README
&lt;span class=&quot;gh&quot;&gt;index e69de29..d0fc019 100644
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;--- a/README
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/README
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -0,0 +1 @@&lt;/span&gt;
&lt;span class=&quot;gi&quot;&gt;+This is a README file, that is all.
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;--
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;2.28.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to apply the patch we do:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# patch as unstaged changes in your branch&lt;/span&gt;
git apply 0001-Update-README.patch

&lt;span class=&quot;c&quot;&gt;# patch as commits&lt;/span&gt;
git am 0001-Update-README.patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;notice--primary&quot;&gt;For more information, check the documentation for &lt;a href=&quot;https://git-scm.com/docs/git-diff&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
diff&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://git-scm.com/docs/git-format-patch&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
format-patch&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://git-scm.com/docs/git-apply&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
apply&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;https://git-scm.com/docs/git-am&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
am&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;!-- 
### git request-pull ✉️

Git comes with its own [pull request
module](https://www.git-scm.com/docs/git-request-pull).

This feature has nothing to do with [GitHubs pull
request](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/creating-an-issue-or-pull-request).
It's mean to facilitate the creation of summary messages to be sent through
e-mail for example. If you want to use GitHubs pull request feature without the
web interface, check out the [hub](https://hub.github.com/) command line interface tool.
{: .notice--danger}

Imagine that you built your work on your master branch on top of the v1.0
release, and want it to be integrated to the project. First you push that change
to your public repository for others to see. If this is a remote repository you might do it like this:

```bash
git push https://bestgitserver.com/project master
```

Then we run the following command:

```bash
git request-pull v1.0 https://bestgitserver.com/project master
```

This will produce a request message with information about:

 1. where to pull from (your downstream repository address)
 2. the upstream repository
 3. a summary of the changes between v1.0 release and your master.

You can then send this request by e-mail for instance, making the pull request
completely distributed and independent from GitHub proprietary system.
--&gt;

&lt;h2 id=&quot;git-tips-&quot;&gt;Git tips 🔥&lt;/h2&gt;

&lt;p&gt;We are all bound to get stuck sometimes when things go wrong. A good starting
point is this &lt;a href=&quot;https://ohshitgit.com/&quot;&gt;compilation&lt;/a&gt;. These are solutions to
problems I often have to solve.&lt;/p&gt;

&lt;h3 id=&quot;premature-commit-&quot;&gt;Premature commit 🔧&lt;/h3&gt;

&lt;p&gt;You pulled the trigger too fast on that commit and wish you could include
additional changes? Make your changes, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --amend&lt;/code&gt; and done. (Also
useful to change the commit message.)&lt;/p&gt;

&lt;h3 id=&quot;go-back-&quot;&gt;Go back ⌛&lt;/h3&gt;

&lt;p&gt;We messed up, go back to a previous commit.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# go back n commits n=1 in this case,&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# --soft: optionally don't discard changes&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# and put them on the staging area instead&lt;/span&gt;
git reset HEAD~1 &lt;span class=&quot;nt&quot;&gt;--soft&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;put-changes-on-hold-&quot;&gt;Put changes on hold 🚧&lt;/h3&gt;

&lt;p&gt;So you want to get back to the state before you started making changes, but
don’t want to throw these changes away:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# stash the changes&lt;/span&gt;
git stash
&lt;span class=&quot;c&quot;&gt;# get the changes back when needed&lt;/span&gt;
git stash pop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;where-it-went-wrong-&quot;&gt;Where it went wrong 🔍&lt;/h3&gt;

&lt;p&gt;You have a problem and don’t know which commit introduced it, enter &lt;a href=&quot;https://git-scm.com/docs/git-bisect&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git bisect&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git bisect start          &lt;span class=&quot;c&quot;&gt;# start a bisect section&lt;/span&gt;
git bisect bad            &lt;span class=&quot;c&quot;&gt;# Current version is bad&lt;/span&gt;
git bisect good v2.2.1    &lt;span class=&quot;c&quot;&gt;# v2.2.1 is known to be good&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;bisect will now choose commits in the middle of the history and you can mark
them as good or bad with the same commands. When no more revisions are available
you’ll have a description of the commit that caused the problem. You can then reset
the bisect state with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git bisect reset&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;rebasing-commits-&quot;&gt;Rebasing commits 💥&lt;/h3&gt;

&lt;p&gt;Sometimes we make two commits when in reality, we could have included all the
changes in a single commit, and our history would be clearer. This is what is
known as &lt;em&gt;squashing&lt;/em&gt;. We can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; to meld commits with previous
commits. It can also be used instead of merging branches. Git’s rebase command
temporarily rewinds the commits on your current branch, pulls in the commits
from the other reference and reapplies the re-winded commits back on top.&lt;/p&gt;

&lt;p&gt;Most people will advise you to always squash the commits and rebase them onto
the parent branch (like master or develop) before you submit a pull request or
send out a patch. Whether rebasing is preferred to merging really depends on the
context.&lt;/p&gt;

&lt;p class=&quot;notice--primary&quot;&gt;If you want to read more about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rebase&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merge&lt;/code&gt;, check out &lt;a href=&quot;https://medium.com/hackernoon/mastering-git-why-rebase-is-amazing-a954485b128a&quot;&gt;this
post&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;notice--danger&quot;&gt;Whatever you do &lt;strong&gt;DO NOT&lt;/strong&gt; rebase commits in a upstream repository people can
pull from. It will mess everyone’s history and lead to conflicts that all
downstream peers will need to fix.
Also, it’s &lt;strong&gt;never&lt;/strong&gt; a good idea to &lt;strong&gt;rebase somebody else’s work&lt;/strong&gt;, see &lt;a href=&quot;https://yarchive.net/comp/linux/git_rebase.html&quot;&gt;this
discussion&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# rebase last 2 commits&lt;/span&gt;
git rebase &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; HEAD~2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The interactive system will open an editor where you can choose each commit in a
list that are about to be changed. In this case, it will list 2 lines with the
last 2 commits. This list reflects exactly how your branch will look like after
the rebase:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pick c8175df added line
pick dc58443 added final line

&lt;span class=&quot;c&quot;&gt;# Rebase 65e38e0..dc58443 onto 65e38e0 (2 commands)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Commands:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# p, pick &amp;lt;commit&amp;gt; = use commit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# s, squash &amp;lt;commit&amp;gt; = meld into previous commit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# f, fixup &amp;lt;commit&amp;gt; = like &quot;squash&quot;, but discard log message&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can pick, reorder or squash any commits you want to make for a more readable
history.&lt;/p&gt;

&lt;p&gt;As we discussed, you can also rebase the current branch onto another&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout feature
git rebase &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;notice--primary&quot;&gt;For more information about rebase see the &lt;a href=&quot;https://git-scm.com/docs/git-rebase&quot;&gt;documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;good-commit-messages-&quot;&gt;Good commit messages 🧐&lt;/h3&gt;

&lt;p&gt;Commit messages should be consistent across a project in terms of &lt;strong&gt;style&lt;/strong&gt;,
&lt;strong&gt;content&lt;/strong&gt;, and &lt;strong&gt;metadata&lt;/strong&gt;. But some good rules are as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;the minimum is a single short descriptive line (e.g. less than 50 characters);&lt;/li&gt;
  &lt;li&gt;separate subject, body, other data, with blank lines;&lt;/li&gt;
  &lt;li&gt;include metadata such as references to commits that introduce problems being
solved.&lt;/li&gt;
  &lt;li&gt;wrap the body to 72 characters.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A good one liner can be something like this&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Fix typos in the abstract
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Verb&amp;gt; &amp;lt;Target&amp;gt; &amp;lt;Description&amp;gt;&lt;/code&gt; is sometimes enough context to describe
a simple change.&lt;/p&gt;

&lt;p&gt;A great way to learn what good commit messages look like is to study
repositories where this is done right. It is to no surprise that the &lt;a href=&quot;https://github.com/torvalds/linux/commits/master&quot;&gt;Linux
kernel&lt;/a&gt; and
&lt;a href=&quot;https://github.com/git/git/commits/master&quot;&gt;git&lt;/a&gt; itself are good examples. There
are also plenty resources on the subject such as &lt;a href=&quot;https://chris.beams.io/posts/git-commit/&quot;&gt;How to Write a Git Commit
Message&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good commit messages are an important collaboration tool. They are the best way
to communicate context about a change to a fellow developer, or to our future
selves. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; will tell us what changed, the &lt;em&gt;WHAT&lt;/em&gt;, but this added context
documents the &lt;em&gt;WHY&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;git-for-writing-&quot;&gt;Git for writing 👨‍💻&lt;/h2&gt;

&lt;p&gt;I have been experimenting with git for writing. The idea being that we can
benefit from using version control with our papers, lecture notes, blog posts,
etc. Suppose we are considering git to track changes in a scientific paper. We
can mark submissions with tags, use patches to incorporate changes from
collaborators, branches to work on revisions, git diff to visualize the changes,
etc.&lt;/p&gt;

&lt;p&gt;Remember that git cares about meaningful lines, so the first thing to take into
account is that we should, at minimum hard wrap our lines at a given character
limit, &lt;strong&gt;and/or&lt;/strong&gt; write each sentence on a different line. By using Markdown or
LaTex to write a document, we will be tempted to use the editor for soft word
wrapping. This can lead to huge one-line paragraphs. The problem with this is
that changing a word in that paragraph will be recorded as a change to the
entire paragraph. Moving lines around has a similar effect.&lt;/p&gt;

&lt;p&gt;As a workaround, to visualise changes in such cases, we can use the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--color-words&lt;/code&gt; option with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Consider a LaTeX document, for example. If we move lines around and call the
following command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git diff &lt;span class=&quot;nt&quot;&gt;--color-words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;this is what we get:&lt;/p&gt;
&lt;figure&gt;
  &lt;a href=&quot;https://davidenunes.com/assets/images/posts/git_diff_color_words.png&quot;&gt;
  &lt;img src=&quot;https://davidenunes.com/assets/images/posts/git_diff_color_words.png&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;But what is actually recorded in the diff is the following:&lt;/p&gt;

&lt;figure&gt;
	&lt;a href=&quot;https://davidenunes.com/assets/images/posts/git_diff_lines_moved.png&quot;&gt;
  &lt;img src=&quot;https://davidenunes.com/assets/images/posts/git_diff_lines_moved.png&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;To generate a pdf to visualise the changes in our tracked latex document, check
out the &lt;a href=&quot;https://gitlab.com/git-latexdiff/git-latexdiff/&quot;&gt;git latexdiff&lt;/a&gt; tool
that wraps around git and &lt;a href=&quot;https://www.ctan.org/pkg/latexdiff&quot;&gt;latexdiff&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The result of the following command is an output pdf with the changes in
relation with the previous commit&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git latexdiff HEAD~1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;figure&gt;
	&lt;a href=&quot;https://davidenunes.com/assets/images/posts/git_latexdiff.png&quot;&gt;
  &lt;img src=&quot;https://davidenunes.com/assets/images/posts/git_latexdiff.png&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;archiving-projects-️&quot;&gt;Archiving projects 🏛️&lt;/h2&gt;

&lt;p&gt;This is not related to git specifically, but more with good open science
practices. Online repository hosts like Github are not archival. Git itself lets
us tag commits to mark versions and releases, but tags can be deleted, and
storage is totally dependent on us. Remember, git distributed, and local. Git is
meant to track changes and collaborate, not archive the state of projects.&lt;/p&gt;

&lt;p&gt;Platforms like &lt;a href=&quot;https://zenodo.org/&quot;&gt;Zenodo&lt;/a&gt;, on the other hand, let you
conveniently archive versions of GitHub repositories based on GitHub releases
(tags).&lt;/p&gt;

&lt;p&gt;If you already use GitHub as a public accessible mirror for your project tracked
by git, this means you can easily archive certain versions of your project and
automatically make them citable since Zenodo attributes a Digital Object
Identifier (DOI) to its submissions.&lt;/p&gt;

&lt;p class=&quot;notice--primary&quot;&gt;With this said, we should discuss how to &lt;strong&gt;archive&lt;/strong&gt;, &lt;strong&gt;backup&lt;/strong&gt;, or &lt;strong&gt;share&lt;/strong&gt;
your entire git repository &lt;strong&gt;without depending on any specific platform&lt;/strong&gt;. There
are a couple of options.&lt;/p&gt;

&lt;h3 id=&quot;you-could-zip-it-but-️&quot;&gt;You could zip it but… 🗄️&lt;/h3&gt;

&lt;p&gt;A zip of your project folder will include EVERYTHING, yes, including your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt;
folder with all the changes, branches,
&lt;a href=&quot;https://git-scm.com/docs/git-reflog&quot;&gt;reflogs&lt;/a&gt; but &lt;strong&gt;this might not be what you
actually want&lt;/strong&gt;. A zip of the project folder will include untracked files, and
you could accidentally share sensitive information, irrelevant temporary files
or IDE and editor configuration folders, etc.&lt;/p&gt;

&lt;h3 id=&quot;mirror-clone-&quot;&gt;Mirror clone 🔗&lt;/h3&gt;

&lt;p&gt;A git clone with the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mirror&lt;/code&gt; creates a bare repository (which contains
only the stuff in the .git directory) and it maps all refs (including
remote-tracking branches, etc.) to the target repository. This means that these
refs can be updated by a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git remote update&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone &lt;span class=&quot;nt&quot;&gt;--mirror&lt;/span&gt; myrepo repo.git
&lt;span class=&quot;c&quot;&gt;# or some remote repository&lt;/span&gt;
git clone &lt;span class=&quot;nt&quot;&gt;--mirror&lt;/span&gt; https://github.com/davidenunes/repo repo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You could make a backup of your repository by creating a mirror (bare) repository and
archive it.&lt;/p&gt;

&lt;p&gt;To restore the bare repository, you can do the following:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;myrepo
&lt;span class=&quot;nb&quot;&gt;mv &lt;/span&gt;repo.git myrepo/.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;myrepo
git init
git checkout &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;notice--primary&quot;&gt;If you want to refresh the backup you just need to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git remote update&lt;/code&gt; from the clone location.&lt;/p&gt;

&lt;h3 id=&quot;bundling-&quot;&gt;Bundling 📦&lt;/h3&gt;

&lt;p&gt;Git is capable of &lt;a href=&quot;https://git-scm.com/book/en/v2/Git-Tools-Bundling&quot;&gt;bundling&lt;/a&gt;
its data into a single binary file. You need to list out every reference or
specific range of commits that you want to be included. If you intend for this
to be cloned somewhere else, you should add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; as a reference as well.
Alternatively, you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--all&lt;/code&gt; to include all refs.&lt;/p&gt;

&lt;p&gt;Within the project folder do:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# this will include all info to recreate the master branch&lt;/span&gt;
git bundle create repo.bundle HEAD master
&lt;span class=&quot;c&quot;&gt;# optionally --all for all refs to be included&lt;/span&gt;
git bundle create repo.bundle &lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can then send or store this file, and in another machine unbundle it into a repository:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; master repo.bundle repo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;notice--warning&quot;&gt;If you don’t include the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; reference (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--all&lt;/code&gt;) you will get the
following error:&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;warning: remote HEAD refers to non-existent ref, unable to
checkout.&lt;/code&gt;&lt;/p&gt;

&lt;p class=&quot;notice--primary&quot;&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--all&lt;/code&gt; makes your bundle file match what you would get with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone
--mirror&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;thank-you&quot;&gt;Thank You&lt;/h2&gt;

&lt;p&gt;Thank you for reading ❤️ I would love to know what you think, if you do things
differently, or have any other neat tips / suggestions. Let me know in the
comment section. You can also follow me on
&lt;a href=&quot;https://twitter.com/davidelnunes&quot;&gt;Twitter&lt;/a&gt;, or subscribe to the &lt;a href=&quot;https://davidenunes.com/feed.xml&quot;&gt;RSS
feed&lt;/a&gt; for more content.&lt;/p&gt;</content><author><name>Davide Nunes</name></author><category term="git" /><category term="tutorial" /><category term="technical" /><summary type="html">Git is a free and open source distributed Version Control System (VCS). Git can be hard, especially for people discovering it for the first time, but there are a lot of things that make this an exceptional VCS worth learning. This post is not meant to be a git tutorial, but rather a compilation of things and tips I find interesting. I also wanted to give a perspective of git independent of services like GitHub. Hopefully you can find something useful and “git better at it” 🙃. If you’re looking to learn how to use git, take a look at the Pro Git book, it’s free and it is a great resource! Git is not GitHub 😮 Services like GitHub made git particularly popular, but the convenience of something like Github has its downsides for new users: it causes confusion about the differences between GitHub or GitLab, and the actual version control system, git. While the former are great to host git repositories and make them publicly available (among other things), git is a piece of software designed to allow for distributed version control and collaboration. This means that you can use it offline, without GitHub, you can collaborate with people via chat, email, and anything that allows you to send text to someone else. Yes, GitHub makes it convenient to host your project and make it discoverable; it provides an incentive for collaboration, but, at the end of the day, GitHub is not git, just as Gmail is not e-mail. Git is distributed 🖧 For those used to GitHub, collaborating with git over e-mail might seem anachronistic, but, consider the scale of projects and what git was designed to do. Being able to send contributions as plain text allied with the threaded nature of e-mail, means that you can have multiple discussions around certain aspects of a contribution, which is a big plus. Linux kernel development, for example, doesn’t happen on GitHub or GitLab. From the linux kernel GitHub Pull requests (GitHub’s system for submitting contributions): Thanks for your contribution to the Linux kernel! Linux kernel development happens on mailing lists, rather than on GitHub - this GitHub repository is a read-only mirror that isn’t used for accepting contributions. So that your change can become part of Linux, please email it to us as a patch. Sending patches isn’t quite as simple as sending a pull request, but fortunately it is a well documented process. Here’s what to do: Format your contribution according to kernel requirements Decide who to send your contribution to Set up your system to send your contribution as an email Send your contribution and wait for feedback The development happens on various mailing lists for multiple subsystems. It’s distributed development to an unprecedented scale. This scale has a price, discipline in your contributions, something that GitHub doesn’t really help reinforce –which seems to be the whole issue that the creator of git Linus Torvalds has with it. Git daemon 🌐 Focusing the development on a centralised service like GitHub can feel like you’re using an improved version of Subversion client/server approach, but remember, git is truly a decentralized system and we can do better. Suppose you don’t want to use GitHub, but want to make your repository available for other people to clone, pull from, etc. Git supports Peer-to-Peer setup out of the box with git daemon. Collaboration then happens on each peer local copy of the source tree and some form of communication channel (e.g. e-mail, chat, etc). From your git folder you can execute the following command git daemon --export-all --base-path=. --reuseaddr --enable=upload-pack: (enabled by default) allows for git fetch, git pull, and git clone. --export-all: means that you don’t have to create a file named git-daemon-export-ok in each exported repository. --base-path: allows people to clone projects without specifying the entire path. Example: if you start the daemon with --base-path=/srv/git and try to pull from git://example.com/hello.git, git daemon will interpret the path as /srv/git/hello.git. --reuseaddr: allows the server to restart without waiting for old connections to time out. Congratulations, your machine is now running a git server and anyone can do: git clone git://192.168.1.42/ #Your IP # or git remote add Foo git://192.168.1.42/ git fetch Foo git checkout develop git push Foo develop Git patches 📝 As we have discussed, git is a decentralized system, you can send contributions to anyone without the need of a centralized git repository. This is not only the default way of collaborating with git, it is particularly useful when a server is down, or if you don’t have permissions to write to a remote repository —but would still like to propose changes. You can create a patch from your current changes without committing the code on your source tree: # changes in the working tree not yet staged for commit git diff &amp;gt; big-improvements.patch # or changes between the index and your last commit; # what you would be committing if you run &quot;git commit&quot; # without &quot;-a&quot; option. git diff --cached &amp;gt; big-improvements.patch As an example suppose the change is the addition of a README file, the diff would look like this: diff --git a/README b/README new file mode 100644 index 0000000..e69de29 More often, what we would like to do is to propose a change we have made in your local source tree. To do this, we can use the git format-patch command: git format-patch master if we have commits ahead of the master branch, a diff file will be generated. We can also reference other commits in the same branch. Suppose we made changes in the current branch and want to reference the changes in relation to the last commit. We can do: git format-patch HEAD~1 the patch file will contain something like: From daf1010eb425a67ca6b0ba60f7cbec15bcff31f1 Mon Sep 17 00:00:00 2001 From: John Doe &amp;lt;heresjohnny@bestmail.com&amp;gt; Date: Tue, 09 Sep 2020 15:42:00 +0100 Subject: [PATCH] Update README --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index e69de29..d0fc019 100644 --- a/README +++ b/README @@ -0,0 +1 @@ +This is a README file, that is all. -- 2.28.0 to apply the patch we do: # patch as unstaged changes in your branch git apply 0001-Update-README.patch # patch as commits git am 0001-Update-README.patch For more information, check the documentation for git diff, git format-patch, git apply, and git am. Git tips 🔥 We are all bound to get stuck sometimes when things go wrong. A good starting point is this compilation. These are solutions to problems I often have to solve. Premature commit 🔧 You pulled the trigger too fast on that commit and wish you could include additional changes? Make your changes, call git commit --amend and done. (Also useful to change the commit message.) Go back ⌛ We messed up, go back to a previous commit. # go back n commits n=1 in this case, # --soft: optionally don't discard changes # and put them on the staging area instead git reset HEAD~1 --soft Put changes on hold 🚧 So you want to get back to the state before you started making changes, but don’t want to throw these changes away: # stash the changes git stash # get the changes back when needed git stash pop Where it went wrong 🔍 You have a problem and don’t know which commit introduced it, enter git bisect: git bisect start # start a bisect section git bisect bad # Current version is bad git bisect good v2.2.1 # v2.2.1 is known to be good bisect will now choose commits in the middle of the history and you can mark them as good or bad with the same commands. When no more revisions are available you’ll have a description of the commit that caused the problem. You can then reset the bisect state with git bisect reset. Rebasing commits 💥 Sometimes we make two commits when in reality, we could have included all the changes in a single commit, and our history would be clearer. This is what is known as squashing. We can use git rebase to meld commits with previous commits. It can also be used instead of merging branches. Git’s rebase command temporarily rewinds the commits on your current branch, pulls in the commits from the other reference and reapplies the re-winded commits back on top. Most people will advise you to always squash the commits and rebase them onto the parent branch (like master or develop) before you submit a pull request or send out a patch. Whether rebasing is preferred to merging really depends on the context. If you want to read more about rebase vs merge, check out this post Whatever you do DO NOT rebase commits in a upstream repository people can pull from. It will mess everyone’s history and lead to conflicts that all downstream peers will need to fix. Also, it’s never a good idea to rebase somebody else’s work, see this discussion. # rebase last 2 commits git rebase -i HEAD~2 The interactive system will open an editor where you can choose each commit in a list that are about to be changed. In this case, it will list 2 lines with the last 2 commits. This list reflects exactly how your branch will look like after the rebase: pick c8175df added line pick dc58443 added final line # Rebase 65e38e0..dc58443 onto 65e38e0 (2 commands) # # Commands: # p, pick &amp;lt;commit&amp;gt; = use commit # r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message # r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message # s, squash &amp;lt;commit&amp;gt; = meld into previous commit # f, fixup &amp;lt;commit&amp;gt; = like &quot;squash&quot;, but discard log message # ... You can pick, reorder or squash any commits you want to make for a more readable history. As we discussed, you can also rebase the current branch onto another git checkout feature git rebase -i master For more information about rebase see the documentation Good commit messages 🧐 Commit messages should be consistent across a project in terms of style, content, and metadata. But some good rules are as follows: the minimum is a single short descriptive line (e.g. less than 50 characters); separate subject, body, other data, with blank lines; include metadata such as references to commits that introduce problems being solved. wrap the body to 72 characters. A good one liner can be something like this Fix typos in the abstract the form &amp;lt;Verb&amp;gt; &amp;lt;Target&amp;gt; &amp;lt;Description&amp;gt; is sometimes enough context to describe a simple change. A great way to learn what good commit messages look like is to study repositories where this is done right. It is to no surprise that the Linux kernel and git itself are good examples. There are also plenty resources on the subject such as How to Write a Git Commit Message. Good commit messages are an important collaboration tool. They are the best way to communicate context about a change to a fellow developer, or to our future selves. git diff will tell us what changed, the WHAT, but this added context documents the WHY. Git for writing 👨‍💻 I have been experimenting with git for writing. The idea being that we can benefit from using version control with our papers, lecture notes, blog posts, etc. Suppose we are considering git to track changes in a scientific paper. We can mark submissions with tags, use patches to incorporate changes from collaborators, branches to work on revisions, git diff to visualize the changes, etc. Remember that git cares about meaningful lines, so the first thing to take into account is that we should, at minimum hard wrap our lines at a given character limit, and/or write each sentence on a different line. By using Markdown or LaTex to write a document, we will be tempted to use the editor for soft word wrapping. This can lead to huge one-line paragraphs. The problem with this is that changing a word in that paragraph will be recorded as a change to the entire paragraph. Moving lines around has a similar effect. As a workaround, to visualise changes in such cases, we can use the --color-words option with git diff. Consider a LaTeX document, for example. If we move lines around and call the following command: git diff --color-words this is what we get: But what is actually recorded in the diff is the following: To generate a pdf to visualise the changes in our tracked latex document, check out the git latexdiff tool that wraps around git and latexdiff. The result of the following command is an output pdf with the changes in relation with the previous commit git latexdiff HEAD~1 Archiving projects 🏛️ This is not related to git specifically, but more with good open science practices. Online repository hosts like Github are not archival. Git itself lets us tag commits to mark versions and releases, but tags can be deleted, and storage is totally dependent on us. Remember, git distributed, and local. Git is meant to track changes and collaborate, not archive the state of projects. Platforms like Zenodo, on the other hand, let you conveniently archive versions of GitHub repositories based on GitHub releases (tags). If you already use GitHub as a public accessible mirror for your project tracked by git, this means you can easily archive certain versions of your project and automatically make them citable since Zenodo attributes a Digital Object Identifier (DOI) to its submissions. With this said, we should discuss how to archive, backup, or share your entire git repository without depending on any specific platform. There are a couple of options. You could zip it but… 🗄️ A zip of your project folder will include EVERYTHING, yes, including your .git folder with all the changes, branches, reflogs but this might not be what you actually want. A zip of the project folder will include untracked files, and you could accidentally share sensitive information, irrelevant temporary files or IDE and editor configuration folders, etc. Mirror clone 🔗 A git clone with the option --mirror creates a bare repository (which contains only the stuff in the .git directory) and it maps all refs (including remote-tracking branches, etc.) to the target repository. This means that these refs can be updated by a git remote update. git clone --mirror myrepo repo.git # or some remote repository git clone --mirror https://github.com/davidenunes/repo repo.git You could make a backup of your repository by creating a mirror (bare) repository and archive it. To restore the bare repository, you can do the following: mkdir myrepo mv repo.git myrepo/.git cd myrepo git init git checkout -f If you want to refresh the backup you just need to call git remote update from the clone location. Bundling 📦 Git is capable of bundling its data into a single binary file. You need to list out every reference or specific range of commits that you want to be included. If you intend for this to be cloned somewhere else, you should add HEAD as a reference as well. Alternatively, you can use --all to include all refs. Within the project folder do: # this will include all info to recreate the master branch git bundle create repo.bundle HEAD master # optionally --all for all refs to be included git bundle create repo.bundle --all You can then send or store this file, and in another machine unbundle it into a repository: git clone -b master repo.bundle repo If you don’t include the HEAD reference (or --all) you will get the following error:warning: remote HEAD refers to non-existent ref, unable to checkout. Using --all makes your bundle file match what you would get with git clone --mirror Thank You Thank you for reading ❤️ I would love to know what you think, if you do things differently, or have any other neat tips / suggestions. Let me know in the comment section. You can also follow me on Twitter, or subscribe to the RSS feed for more content.</summary></entry><entry><title type="html">Gumbel-Top Trick</title><link href="https://davidenunes.com/gumbel-top/" rel="alternate" type="text/html" title="Gumbel-Top Trick" /><published>2020-05-01T00:00:00+00:00</published><updated>2020-05-01T00:00:00+00:00</updated><id>https://davidenunes.com/gumbel-top</id><content type="html" xml:base="https://davidenunes.com/gumbel-top/">&lt;h2 id=&quot;how-to-vectorize-sampling-from-a-discrete-distribution&quot;&gt;How to vectorize sampling from a discrete distribution&lt;/h2&gt;

&lt;p&gt;If you work with libraries such as &lt;a href=&quot;https://numpy.org/&quot;&gt;NumPy&lt;/a&gt;,
&lt;a href=&quot;https://jax.readthedocs.io/en/latest/&quot;&gt;Jax&lt;/a&gt;
&lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;Tensorflow&lt;/a&gt;, or &lt;a href=&quot;https://pytorch.org/&quot;&gt;PyTorch&lt;/a&gt;
you (should) end-up writing a lot of vectorization code: instead of using
control-flow operations (e.g. for loops), you write code that operates on an
entire set of values at once. Inputs and outputs of your functions are
multidimensional arrays or tensors. Lower-level libraries optimized for linear
algebra operations (such as matrix multiplications) make dramatic performance
improvements, especially when aided by modern hardware with direct support for
vector-based instructions.&lt;/p&gt;

&lt;p&gt;In libraries like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NumPy&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tensorflow&lt;/code&gt; sampling from a discrete distribution
without replacement is not vectorized because it requires bookkeeping. In other
words, sampling from a population depends on the values we already sampled.&lt;/p&gt;

&lt;p&gt;So some time ago, I came across a set of re-parametrization tricks that allow us
to vectorize sampling from discrete distributions. This peaked my interest
because I was looking for a way to build stochastic neural networks where neuron
activations could be modelled with certain types of discrete distributions
parametrized by unnormalized log-probabilities.&lt;/p&gt;

&lt;p&gt;To get a probability distribution from unconstrained vectors, usually we use the
&lt;em&gt;softmax&lt;/em&gt; function:&lt;/p&gt;

&lt;p&gt;\[ \sigma(y) = \frac{e^{y_i}}{\sum_{j=1}^N e^{y_j}} \]&lt;/p&gt;

&lt;p&gt;We would then use the resulting distribution to sample classes from it, for
example, using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Inverse_transform_sampling&quot;&gt;inverse transform
sampling&lt;/a&gt;: this takes
uniform samples of a number \(u\ \in [0,1)\), interpreted as a probability,
and then returns the largest number \(y\) from the domain of the distribution
\(P(Y)\) such that \(P(-\infty &amp;lt; Y &amp;lt; y) \le u \). What we are doing is
randomly choosing a proportion of the area under the curve and returning the
number in the domain such that exactly this proportion of the area occurs to the
left of that number.&lt;/p&gt;

&lt;h2 id=&quot;the-gumbel-max-trick&quot;&gt;The Gumbel-Max Trick&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Gumbel-Max&lt;/strong&gt; trick can be used to sample from the previous discrete
distribution without marginalizing all the unnormalized log probabilities (i.e,
without \(\sum_{j=1}^N e^{y_j}\)). The procedure consists in taking the
unnormalized log probabilities \(y_i\), adding noise \(z_i \sim~Gumbel(0,1)
\) (i.i.d. from a Gumbel distribution)
and taking &lt;em&gt;arg max&lt;/em&gt;. In other words:&lt;/p&gt;

&lt;p&gt;\[
    y = \underset{ i \in K }{\operatorname{arg max}} x_i + z_i  &lt;br /&gt;
\]&lt;/p&gt;

&lt;p&gt;This eliminates the need for the marginalization (which can be expensive for
high-dimensional vectors). Another consequence of doing away with the
computation of a &lt;em&gt;normalized&lt;/em&gt; probability distribution, is the fact that we
don’t need to see all of the data before doing partial sampling, this means
&lt;strong&gt;Gumbel-Max&lt;/strong&gt; can be used for &lt;strong&gt;weighted sampling from a stream&lt;/strong&gt; (see
&lt;a href=&quot;http://utopia.duth.gr/~pefraimi/research/data/2007EncOfAlg.pdf&quot;&gt;this&lt;/a&gt;). The
&lt;a href=&quot;https://en.wikipedia.org/wiki/Gumbel_distribution&quot;&gt;Gumbel Distribution&lt;/a&gt; is used
to model the distribution of the maximum (or the minimum) of a number of samples
of various distributions and, as it turns out, \(z_i\) is distributed
according to a softmax function \(\sigma(y)\).&lt;/p&gt;

&lt;figure class=&quot;half&quot;&gt;
    &lt;a href=&quot;/assets/images/posts/gumbel_density.png&quot;&gt;&lt;img src=&quot;/assets/images/posts/gumbel_density.png&quot; /&gt;&lt;/a&gt;
    &lt;a href=&quot;/assets/images/posts/gumbel_cumulative.png&quot;&gt;&lt;img src=&quot;/assets/images/posts/gumbel_cumulative.png&quot; /&gt;&lt;/a&gt;
    &lt;figcaption&gt;Gumbel Probability Density Function (PDF) and  Cumulative Distribution Function (CDF) respectively.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Gumbel distribution with location parameter \(\alpha\) and unit scale
parameter has the following Cumulative Distribution Function (CDF):&lt;/p&gt;

&lt;p&gt;\[
    F(z;\alpha) =  \exp \left[ -\exp\left[-(z-\alpha) \right]\right]
\]&lt;/p&gt;

&lt;p&gt;If \(z_k\) is the \(k^{th}\) element of the Gumbel distribution with
location \(\alpha_k\), the probability that all of the other \(z_{k’\neq
k}\) are less than \(z_k\) is:&lt;/p&gt;

&lt;p&gt;\[
    Pr(k &amp;gt; k’ | z_k, \{ \alpha_{k’}\}_{k’=1}^K) = \prod_{k’\neq k} \exp \left[ -\exp\left[-(z_k-\alpha_{k’}) \right] \right]
\]&lt;/p&gt;

&lt;p&gt;integrating the marginal distribution over \(z_k\) we have an integral which
has the closed form:&lt;/p&gt;

&lt;p&gt;\[
    Pr(k &amp;gt; k’ | \{ \alpha_{k’}\}) = \frac{\exp\left [\alpha_k \right]}{\sum_{k’=1}^K \exp\left [\alpha_{k’} \right]} 
\]&lt;/p&gt;

&lt;p&gt;which is exactly the softmax function.&lt;/p&gt;

&lt;h2 id=&quot;the-gumbel-top-trick&quot;&gt;The Gumbel-Top Trick&lt;/h2&gt;
&lt;p&gt;If we look at the &lt;strong&gt;Gumbel-Max&lt;/strong&gt; trick as form of weighted reservoir sampling,
we can see that if instead of &lt;em&gt;arg max&lt;/em&gt; we take the &lt;em&gt;top-k&lt;/em&gt; args, we are
instead, sampling without replacement from the discrete categorical
distribution. We can call this the &lt;a href=&quot;http://disq.us/p/1xber9v&quot;&gt;&lt;strong&gt;Gumble-Top&lt;/strong&gt;
trick&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-reparameterization-trick-in-neural-networks&quot;&gt;The Reparameterization Trick in Neural Networks&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://arxiv.org/pdf/1611.00712.pdf&quot;&gt;reparameterization trick&lt;/a&gt; allows for
the optimization of stochastic computation graphs via gradient descent. The
essence of the trick is to refactor each stochastic node into a differentiable
function of its parameters and a random variable with fixed distribution. As we
have seen previously, some closed formed densities have a simple
reparameterization. The choice of noise (e.g. Gumbel) gives the trick its name.&lt;/p&gt;

&lt;p&gt;Generally speaking, this trick consists in sampling from \(p_\phi(x)\) by
first sampling \(Z\) from some fixed distribution \(q(z)\) and then
transforming the sample using some function \(g_\phi(z)\). This two step
process is precisely what we call &lt;em&gt;reparameterization trick&lt;/em&gt;, and it is what
makes it possible to reduce the problem of estimating the gradient w.r.t.
parameters of a distribution to the simpler problem of estimating the gradient
w.r.t. parameters of a deterministic function. Once we reparameterized
\(p_\phi(x)\), one can now express the objective as an expectation w.r.t.q(z):&lt;/p&gt;

&lt;p&gt;\[
    L(\theta, \phi)=\mathbb{E}_{X \sim p_{\phi}(x)} \left[ f_{\theta}(X) \right]=\mathbb{E}_{Z \sim q(z)} \left[ f_{\theta}\left(g_{\phi}(Z) \right) \right]
\]&lt;/p&gt;

&lt;p&gt;This trick was introduced in the context of variational inference independently
by &lt;a href=&quot;https://arxiv.org/pdf/1312.6114.pdf&quot;&gt;[Kingma &amp;amp; Welling 2014]&lt;/a&gt;, &lt;a href=&quot;https://arxiv.org/abs/1401.4082&quot;&gt;[Rezende
et al. 2014]&lt;/a&gt;, and &lt;a href=&quot;http://proceedings.mlr.press/v32/titsias14.pdf&quot;&gt;[Titsias &amp;amp; L
́azaro-Gredilla]&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;h3 id=&quot;sampling-from-the-gumbel-distribution&quot;&gt;Sampling from the Gumbel Distribution&lt;/h3&gt;
&lt;p&gt;We can sample \(z_i \sim \mathit{Gumbel(0,1)}\) as follows:&lt;/p&gt;

&lt;p&gt;\[
    \begin{eqnarray}
    x_i \sim \mathit{Uniform(0,1)} \nonumber \\&lt;br /&gt;
    z_i = -\log(-\log(x_i)) \nonumber
    \end{eqnarray}
\]&lt;/p&gt;

&lt;h3 id=&quot;numpy-gumbel-top&quot;&gt;NumPy Gumbel-Top&lt;/h3&gt;
&lt;p&gt;To finish this post and get you an idea of how simple the vectorized procedure
is, here’s an implementation using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NumPy&lt;/code&gt;.&lt;/p&gt;

&lt;!-- 
    &quot;&quot;&quot; top_k
    
    Args:
        x (ndarray): an array of elements  
        k (int): number of elements to return

    Returns:
        an array (ndarray[int]): with the indices of the largest elements in x
    &quot;&quot;&quot;

    &quot;&quot;&quot; samples_k

    Args:
        logits: ndarray with unnormalized log probabilities
        k: number of classes to be sampled
    
    Returns:
        an array (ndarray[int]): with the indices of the sampled classes
    &quot;&quot;&quot;
--&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;top_k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argpartition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[...,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sample_k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uniform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;top_k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;!--
from tensorflow 
```
// Guesstimate of cost; 4*N*log(K) 
    // If K == N, assume the cost is N*log(K + 1).
```
or topk parallel partial sort http://on-demand.gputechconf.com/gtc/2009/presentations/1034-Multi-GPU-Recommendation-System.pdf
https://code.google.com/archive/p/ggks/
Facebook implementation over cuda using radixSelect:
https://github.com/facebook/fbcuda/blob/master/TopKElements.cuh
most implementations use radix select
https://github.com/facebook/fbcuda/blob/master/TopKElements.cuh

To get the top-k elements in sorted order in this way takes O(n + k log k) time.
--&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;h3 id=&quot;blog-posts&quot;&gt;Blog Posts&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Vieira, Tim. &lt;a href=&quot;https://timvieira.github.io/blog/post/2014/07/31/gumbel-max-trick/&quot;&gt;Gumbel-Max-Trick&lt;/a&gt;. 2014.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Ryans, Adam. &lt;a href=&quot;https://lips.cs.princeton.edu/the-gumbel-max-trick-for-discrete-distributions/&quot;&gt;The Gumbel-Max Trick for Discrete Distributions&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mena, Gonzalo. &lt;a href=&quot;https://casmls.github.io/general/2017/02/01/GumbelSoftmax.html&quot;&gt;The Gumbel-Softmax Trick for Inference of Discrete Variables&lt;/a&gt;. 2017&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;papers&quot;&gt;Papers&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Maddison, Chris J., Daniel Tarlow, and Tom Minka. &lt;a href=&quot;https://papers.nips.cc/paper/5449-a-sampling.pdf&quot;&gt;A* sampling&lt;/a&gt;. &lt;em&gt;Advances in Neural Information Processing Systems&lt;/em&gt;. 2014.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Kusner, Matt J., and José Miguel Hernández-Lobato. &lt;a href=&quot;https://arxiv.org/abs/1611.04051&quot;&gt;Gans for sequences of discrete elements with the gumbel-softmax distribution&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Jang, Eric, Shixiang Gu, and Ben Poole. &lt;a href=&quot;https://arxiv.org/pdf/1611.01144.pdf&quot;&gt;Categorical reparameterization with
gumbel-softmax.&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Efraimidis, Pavlos S., and Paul G. Spirakis. &lt;a href=&quot;http://utopia.duth.gr/~pefraimi/research/data/2007EncOfAlg.pdf&quot;&gt;Weighted random sampling with a
reservoir&lt;/a&gt;. Information Processing Letters 97.5 (2006): 181-185.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Kool, Wouter, Herke Van Hoof, and Max Welling. &lt;a href=&quot;https://arxiv.org/abs/1903.06059&quot;&gt;Stochastic beams and where to
find them: The gumbel-top-k trick for sampling sequences without
replacement&lt;/a&gt;. (2019).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;</content><author><name>Davide Nunes</name></author><category term="neural networks" /><category term="statistics" /><category term="technical" /><category term="probability" /><category term="sampling" /><category term="Tensorflow" /><category term="NumPy" /><summary type="html">How to vectorize sampling from a discrete distribution If you work with libraries such as NumPy, Jax Tensorflow, or PyTorch you (should) end-up writing a lot of vectorization code: instead of using control-flow operations (e.g. for loops), you write code that operates on an entire set of values at once. Inputs and outputs of your functions are multidimensional arrays or tensors. Lower-level libraries optimized for linear algebra operations (such as matrix multiplications) make dramatic performance improvements, especially when aided by modern hardware with direct support for vector-based instructions. In libraries like NumPy or Tensorflow sampling from a discrete distribution without replacement is not vectorized because it requires bookkeeping. In other words, sampling from a population depends on the values we already sampled. So some time ago, I came across a set of re-parametrization tricks that allow us to vectorize sampling from discrete distributions. This peaked my interest because I was looking for a way to build stochastic neural networks where neuron activations could be modelled with certain types of discrete distributions parametrized by unnormalized log-probabilities. To get a probability distribution from unconstrained vectors, usually we use the softmax function: \[ \sigma(y) = \frac{e^{y_i}}{\sum_{j=1}^N e^{y_j}} \] We would then use the resulting distribution to sample classes from it, for example, using the inverse transform sampling: this takes uniform samples of a number \(u\ \in [0,1)\), interpreted as a probability, and then returns the largest number \(y\) from the domain of the distribution \(P(Y)\) such that \(P(-\infty &amp;lt; Y &amp;lt; y) \le u \). What we are doing is randomly choosing a proportion of the area under the curve and returning the number in the domain such that exactly this proportion of the area occurs to the left of that number. The Gumbel-Max Trick The Gumbel-Max trick can be used to sample from the previous discrete distribution without marginalizing all the unnormalized log probabilities (i.e, without \(\sum_{j=1}^N e^{y_j}\)). The procedure consists in taking the unnormalized log probabilities \(y_i\), adding noise \(z_i \sim~Gumbel(0,1) \) (i.i.d. from a Gumbel distribution) and taking arg max. In other words: \[ y = \underset{ i \in K }{\operatorname{arg max}} x_i + z_i \] This eliminates the need for the marginalization (which can be expensive for high-dimensional vectors). Another consequence of doing away with the computation of a normalized probability distribution, is the fact that we don’t need to see all of the data before doing partial sampling, this means Gumbel-Max can be used for weighted sampling from a stream (see this). The Gumbel Distribution is used to model the distribution of the maximum (or the minimum) of a number of samples of various distributions and, as it turns out, \(z_i\) is distributed according to a softmax function \(\sigma(y)\). Gumbel Probability Density Function (PDF) and Cumulative Distribution Function (CDF) respectively. Gumbel distribution with location parameter \(\alpha\) and unit scale parameter has the following Cumulative Distribution Function (CDF): \[ F(z;\alpha) = \exp \left[ -\exp\left[-(z-\alpha) \right]\right] \] If \(z_k\) is the \(k^{th}\) element of the Gumbel distribution with location \(\alpha_k\), the probability that all of the other \(z_{k’\neq k}\) are less than \(z_k\) is: \[ Pr(k &amp;gt; k’ | z_k, \{ \alpha_{k’}\}_{k’=1}^K) = \prod_{k’\neq k} \exp \left[ -\exp\left[-(z_k-\alpha_{k’}) \right] \right] \] integrating the marginal distribution over \(z_k\) we have an integral which has the closed form: \[ Pr(k &amp;gt; k’ | \{ \alpha_{k’}\}) = \frac{\exp\left [\alpha_k \right]}{\sum_{k’=1}^K \exp\left [\alpha_{k’} \right]} \] which is exactly the softmax function. The Gumbel-Top Trick If we look at the Gumbel-Max trick as form of weighted reservoir sampling, we can see that if instead of arg max we take the top-k args, we are instead, sampling without replacement from the discrete categorical distribution. We can call this the Gumble-Top trick. The Reparameterization Trick in Neural Networks The reparameterization trick allows for the optimization of stochastic computation graphs via gradient descent. The essence of the trick is to refactor each stochastic node into a differentiable function of its parameters and a random variable with fixed distribution. As we have seen previously, some closed formed densities have a simple reparameterization. The choice of noise (e.g. Gumbel) gives the trick its name. Generally speaking, this trick consists in sampling from \(p_\phi(x)\) by first sampling \(Z\) from some fixed distribution \(q(z)\) and then transforming the sample using some function \(g_\phi(z)\). This two step process is precisely what we call reparameterization trick, and it is what makes it possible to reduce the problem of estimating the gradient w.r.t. parameters of a distribution to the simpler problem of estimating the gradient w.r.t. parameters of a deterministic function. Once we reparameterized \(p_\phi(x)\), one can now express the objective as an expectation w.r.t.q(z): \[ L(\theta, \phi)=\mathbb{E}_{X \sim p_{\phi}(x)} \left[ f_{\theta}(X) \right]=\mathbb{E}_{Z \sim q(z)} \left[ f_{\theta}\left(g_{\phi}(Z) \right) \right] \] This trick was introduced in the context of variational inference independently by [Kingma &amp;amp; Welling 2014], [Rezende et al. 2014], and [Titsias &amp;amp; L ́azaro-Gredilla]. Implementation Sampling from the Gumbel Distribution We can sample \(z_i \sim \mathit{Gumbel(0,1)}\) as follows: \[ \begin{eqnarray} x_i \sim \mathit{Uniform(0,1)} \nonumber \\ z_i = -\log(-\log(x_i)) \nonumber \end{eqnarray} \] NumPy Gumbel-Top To finish this post and get you an idea of how simple the vectorized procedure is, here’s an implementation using NumPy. import numpy as np def top_k(x, k): return np.argpartition(x, k)[..., -k:] def sample_k(logits, k): u = np.random.uniform(size=np.shape(logits)) z = -np.log(-np.log(u)) return top_k(logits + z, k) References Blog Posts Vieira, Tim. Gumbel-Max-Trick. 2014. Ryans, Adam. The Gumbel-Max Trick for Discrete Distributions Mena, Gonzalo. The Gumbel-Softmax Trick for Inference of Discrete Variables. 2017 Papers Maddison, Chris J., Daniel Tarlow, and Tom Minka. A* sampling. Advances in Neural Information Processing Systems. 2014. Kusner, Matt J., and José Miguel Hernández-Lobato. Gans for sequences of discrete elements with the gumbel-softmax distribution. Jang, Eric, Shixiang Gu, and Ben Poole. Categorical reparameterization with gumbel-softmax. Efraimidis, Pavlos S., and Paul G. Spirakis. Weighted random sampling with a reservoir. Information Processing Letters 97.5 (2006): 181-185. Kool, Wouter, Herke Van Hoof, and Max Welling. Stochastic beams and where to find them: The gumbel-top-k trick for sampling sequences without replacement. (2019).</summary></entry><entry><title type="html">EXP — A Tool for Hyperparameter Tuning</title><link href="https://davidenunes.com/exp/" rel="alternate" type="text/html" title="EXP — A Tool for Hyperparameter Tuning" /><published>2020-02-29T00:00:00+00:00</published><updated>2020-02-29T00:00:00+00:00</updated><id>https://davidenunes.com/exp</id><content type="html" xml:base="https://davidenunes.com/exp/">&lt;h1 id=&quot;exp&quot;&gt;exp&lt;/h1&gt;

&lt;p align=&quot;center&quot;&gt;
&lt;img src=&quot;https://davidenunes.com/assets/images/posts/exp.png&quot; width=&quot;50%&quot; alt=&quot;EXP Logo&quot; /&gt;
&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;Experiment &lt;strong&gt;design&lt;/strong&gt;, &lt;strong&gt;deployment&lt;/strong&gt;, and &lt;strong&gt;optimization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optimizing model
&lt;a href=&quot;https://en.wikipedia.org/wiki/Hyperparameter_(machine_learning)&quot; target=&quot;_blank&quot;&gt;hyperparameters&lt;/a&gt;&lt;/strong&gt;
is an ubiquitous task in Machine Learning research. Finding baselines that are
useful as a ground truth for ablation studies implies that you want the
comparison to be as fair as possible: we want to compare the best possible
models for the given architectures. In the case of neural network models, this
can mean adjusting &lt;em&gt;learning rate&lt;/em&gt;, &lt;em&gt;regularization weights&lt;/em&gt;, &lt;em&gt;dropout
probabilities&lt;/em&gt;, etc. Doing ablation studies for large models (or large datasets)
can be particularly expensive, not just in terms of time, but (for
GPU-accelerated models) of energy as well.&lt;/p&gt;

&lt;p&gt;Writing code to run the experiments, take advantage of multiprocessing, or
distributing model runs through different GPUs can be a pain. &lt;strong&gt;EXP&lt;/strong&gt; separates
model specification from model configuration, experiment deployment and result
logging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EXP&lt;/strong&gt; is a tool / library for experiment design, model deployment, and
hyperparameter optimization that performs 2 basic tasks:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;model execution from parameter specifications;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;model optimization given a parameter space.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;model-search-with-bayesian-optimization&quot;&gt;Model Search with Bayesian Optimization&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;EXP&lt;/strong&gt; wraps around scikit-optimize to find the best configuration for a model
using global &lt;a href=&quot;https://en.wikipedia.org/wiki/Bayesian_optimization&quot;&gt;Bayesian
optimization&lt;/a&gt;. For a
tutorial on Bayesian Optimization see
&lt;a href=&quot;https://arxiv.org/pdf/1807.02811.pdf&quot; target=&quot;_blank&quot;&gt;1807.02811&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; exp.gopt &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; basic.conf &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; runnable.py &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 20 &lt;span class=&quot;nt&quot;&gt;--workers&lt;/span&gt; 4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/posts/exp_progress.gif&quot; alt=&quot;exp progress cli&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;step-by-step&quot;&gt;Step-by-step&lt;/h2&gt;

&lt;p&gt;With a single command, we can take any model and a parameter space specified in
a configuration file and the optimization procedure will try to find the best
possible model iteratively. Each model run informs the model about possible
configuration candidates that might lead to better performance.&lt;/p&gt;

&lt;p&gt;Suppose you want to optimize a simple function, say x², you want to find the
parameter that minimizes this function, a parameter space file written in
&lt;a href=&quot;https://github.com/toml-lang/toml&quot;&gt;TOML&lt;/a&gt; might look like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;random&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;int&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;prior&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;uniform&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The only thing you need now is a runnable model. A model here is just a python
file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runnable.py&lt;/code&gt; with a run function that takes a parameter dictionary as
input:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running the previous command with these two files will evaluate a number of
initially random configurations in parallel (one for each available worker),
generate a bayesian model of how the performance function might react to
different configurations. The optimizer then suggests new configurations within
the defined parameter value bounds. This continues iteratively until a number of
specified runs n has passed.&lt;/p&gt;

&lt;p&gt;Additionally, a gpu flag can be added to restrict the number of workers to the
number of available GPU units in a machine. Each worker will only have access to
1 gpu unit (in this case using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CUDA_VISIBLE_DEVICES&lt;/code&gt; variable). This allows
for a safe deployment of models using frameworks like TensorFlow or PyTorch that
use every single GPU unit available to run their computational graphs.&lt;/p&gt;

&lt;h2 id=&quot;some-caveats&quot;&gt;Some caveats&lt;/h2&gt;

&lt;p&gt;The larger the parameter space, the harder the optimization problem, so this is
not a silver bullet. I use Bayesian Optimization to complement my intuition
about what parameters might yield a good model.&lt;/p&gt;

&lt;p&gt;Gaussian optimization assumes that the parameter values are continuous, the
optimizer does take care of corner cases, like integer or categorical values,
but I recommend reading on the subject if you need to optimize discrete
parameters, a better alternative for neural network architecture search might be
the use of evolutionary computation techniques, but these are not yet available
in the tool.&lt;/p&gt;

&lt;h2 id=&quot;thank-you&quot;&gt;Thank You&lt;/h2&gt;

&lt;p&gt;For more documentation check out the project on
&lt;a href=&quot;https://github.com/davidenunes/exp&quot; target=&quot;_blank&quot;&gt;Github&lt;/a&gt;. If you have any
questions, drop me a line on &lt;a href=&quot;https://twitter.com/davidelnunes&quot;&gt;twitter&lt;/a&gt;, or leave a comment bellow.&lt;/p&gt;</content><author><name>Davide Nunes</name></author><category term="tools" /><summary type="html">A tool/library for experiment design, deployment, and model optimization with hyperparameter tuning.</summary></entry><entry><title type="html">The Ignorant Schoolmaster</title><link href="https://davidenunes.com/the-ignorant-schoolmaster/" rel="alternate" type="text/html" title="The Ignorant Schoolmaster" /><published>2020-02-19T00:00:00+00:00</published><updated>2020-02-19T00:00:00+00:00</updated><id>https://davidenunes.com/the-ignorant-schoolmaster</id><content type="html" xml:base="https://davidenunes.com/the-ignorant-schoolmaster/">&lt;div class=&quot;feature__wrapper&quot;&gt;

  

&lt;/div&gt;

&lt;p&gt;The book &lt;a href=&quot;http://www.goodreads.com/book/show/445408.The_Ignorant_Schoolmaster&quot;&gt;The Ignorant Schoolmaster: Five Lessons in Intellectual
Emancipation&lt;/a&gt;
(1987), by the French philosopher Jacques Rancière, presents the notion of
&lt;em&gt;intellectual emancipation&lt;/em&gt;. He explores the idea of &lt;em&gt;equality of minds&lt;/em&gt; while
criticizing theories of pedagogical reform for failing to account for the fact
that one cannot remove bias the education system using theories born from and
designed to reinforce the very same bias they intend to remove.&lt;/p&gt;

&lt;figure&gt;
	&lt;a href=&quot;https://davidenunes.com/assets/images/posts/book_ignorant_schoolmaster.jpg&quot;&gt;
  &lt;img src=&quot;https://davidenunes.com/assets/images/posts/book_ignorant_schoolmaster.jpg&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Every time I find myself ranting about what makes something art, communication
always comes to mind:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The impossibility of our saying the truth, even when we feel it, makes us
speak as poets, makes us tell the story of our mind’s adventures and verify
that they are understood by other adventurers.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and communication is so much about thinking as it is about doing:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The virtue of our intelligence is less in knowing than in doing. Knowing is
nothing, doing is everything, but this doing is fundamentally an act of
communication.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;but cynic in me resonates especially with the following:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“There is no pride in saying out loud: Me too, I’m a painter! Pride consists in
saying softly to others: You neither, you aren’t a painter! “Me too, I’m a
painter” means: me too, I have a feelings to communicate to my fellow men.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and this is exactly why sharing is so much more important —but less
popular— than signalling (the two being often hard to distinguish):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“One must learn near those who have worked in the gap between feeling and
expression , between the silent language of emotion and the arbitrariness of
the spoken tongue, near those who have tried to give voice to the silent
dialogue the soul has with itself, who have gambled all their credibility on
the bet of the similarity of minds.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The recurrent message of “he  who knows how to remain true to himself in the
middle of irrationality  will triumph over  the  passions  of others  exactly as
he triumphs over his own” takes me back to
&lt;a href=&quot;https://en.wikipedia.org/wiki/Stoicism&quot;&gt;stoicism&lt;/a&gt; and Marcus Aurelius’
&lt;em&gt;Meditations&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The happiness of those who want to be popular depends on others; the happiness
of those who seek pleasure fluctuates with moods outside their control; but the
happiness of the wise grows out of their own free acts.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rancière’s &lt;em&gt;emancipation&lt;/em&gt;, much like stoicism, falls back to reason above all
else as a way to deal with our innate biases. Reason (and the awareness to
reason) is perhaps the way to avoid “falling into the gravitational field of
other minds”. But then again, as the economist Herbert Simon puts it, people do
things for certain reasons, and those reasons need not be rational, we are after
all being of &lt;em&gt;bounded rationality&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The other recurrent theme in the book is a critique of theories of pedagogical
reform. Theories that present themselves as an attempt to reform the social
inequities of the school system without realizing that school is not a
preparation for life, but a reflection that models it’s stratification.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For if science (theory) forms an enclave of freedom in a world of ideological
enslavement, if science belongs to the intellectuals —the masters—
and the critique of bourgeois content is reserved for those who already know,
then there is only one way for students to criticize their masters’ knowledge
from the point of view of class, and that is to become their peers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rancière’s critique of the educational  theories shows them to have at least one
thing in common: a lesson in inequality. Each, that is, by beginning with
inequality, proves it, and by proving it, in the end, is obliged to rediscover
it again and again. Erecting and maintaining the distance separating a future
reconciliation from a present inequality —a distance discursively invented and
reinvented so that it may never be abolished.&lt;/p&gt;</content><author><name>Davide Nunes</name></author><category term="books" /><category term="scrapbook" /><summary type="html">The book The Ignorant Schoolmaster by the French philosopher Jacques Rancière explores the idea of _equality of minds_ while criticizing theories of pedagogical reform, biased against intellectual emancipation.</summary></entry><entry><title type="html">Hello World</title><link href="https://davidenunes.com/hello-world/" rel="alternate" type="text/html" title="Hello World" /><published>2020-01-07T00:00:00+00:00</published><updated>2020-01-07T00:00:00+00:00</updated><id>https://davidenunes.com/hello-world</id><content type="html" xml:base="https://davidenunes.com/hello-world/">&lt;p&gt;Welcome to my Web page. I enjoy maintaining control over my content somewhere, especially when other third-party
“web-identity” services invite you to invest time and attention without matching
the commitment with adequate levels of ownership and control. I will post about
ongoing projects Artificial Intelligence in general, Natural Natural Language
Processing, Machine Learning in particular along with musings on the
philosophical aspects of intelligence, consciousness, and learning. More about
me &lt;a href=&quot;https://davidenunes.com/about&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content><author><name>Davide Nunes</name></author><category term="updates" /><summary type="html">Welcome to my Web page. I enjoy maintaining control over my content somewhere, especially when other third-party “web-identity” services invite you to invest time and attention without matching the commitment with adequate levels of ownership and control. I will post about ongoing projects Artificial Intelligence in general, Natural Natural Language Processing, Machine Learning in particular along with musings on the philosophical aspects of intelligence, consciousness, and learning. More about me here.</summary></entry></feed>