<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Adam Paszke</title>
    <description>A blog.
</description>
    <link>https://apaszke.github.io/</link>
    <atom:link href="https://apaszke.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 15 Feb 2024 08:11:20 +0000</pubDate>
    <lastBuildDate>Thu, 15 Feb 2024 08:11:20 +0000</lastBuildDate>
    <generator>Jekyll v3.9.5</generator>
    
      <item>
        <title>A quick tour of Torch internals</title>
        <description>&lt;p&gt;Recently, I have been kind of confused. I couldn’t find myself
anything to work on and had no ideas for new projects (apparently, I just had to wait
for the new academic year to start - I have plenty of ideas now, but no time for them).&lt;/p&gt;

&lt;p&gt;Anyway, I often get the impression that many people are using Machine
Learning libraries as a kind of black-boxes with only a high-level API. It’s as if they
weren’t interested at all in how they work, but solely in the output (this is why I like
Torch so much - it’s hackable to the bone). I’ve been using Torch for a few months
now and I’ve always been curious how it’s built. This is why I decided to get
down to it and browse the code of TH library, which is at the core of Torch.&lt;/p&gt;

&lt;p&gt;It’s really a great thing to do. I’ll write more about it in the end of this post,
but you should seriously consider doing it with your favourite library
or framework too.&lt;/p&gt;

&lt;p&gt;Torch’s source is written in plain C, which was very pleasing to me. I don’t
really like many C++ features and although I find it very powerful and flexible,
it often seems confusing. C’s extremely minimal syntax allows you to read and quickly
grasp what exactly happens at any moment. However, if C++ is the way to go
for you, there is also a wrapper around TH called &lt;a href=&quot;https://github.com/facebook/thpp&quot;&gt;thpp&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;where-can-you-get-it&quot;&gt;Where can you get it?&lt;/h2&gt;

&lt;p&gt;You can find the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt; library in two places:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/torch/TH&quot;&gt;In its standalone repository&lt;/a&gt; (git subtree of torch7; outdated at the time of writing)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/torch/torch7&quot;&gt;In torch7 repository&lt;/a&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib/TH&lt;/code&gt; folder (always up to date)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The folder structure is very simple. There are some cmake tests and definitions
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; directory while the code is located both in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generic&lt;/code&gt; directory and at the repo root.&lt;/p&gt;

&lt;h2 id=&quot;interesting-findings&quot;&gt;Interesting findings&lt;/h2&gt;

&lt;p&gt;Before going into the details and describing functionality implemented in individual
files I’d like to point out some really cool techniques that I’ve found in the implementation.&lt;/p&gt;

&lt;h3 id=&quot;code-generation&quot;&gt;Code generation&lt;/h3&gt;

&lt;p&gt;First thing that appeared really strange to me was that many files existed both in the
root folder as well as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generic&lt;/code&gt;. If you opened them, you would quickly notice
that copies in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generic&lt;/code&gt; contain the actual code, while at the root they all look
very similar. Here is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THStorage.c&lt;/code&gt; for example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;THAtomic.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;THStorage.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;generic/THStorage.c&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;THGenerateAllTypes.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;generic/THStorageCopy.c&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;THGenerateAllTypes.h&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Quite unusual for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.c&lt;/code&gt; file, right?&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THGenerateAllTypes&lt;/code&gt; sounds interesting so i looked it up and this if what I’ve
found:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#ifndef TH_GENERIC_FILE
#error &quot;You must define TH_GENERIC_FILE before including THGenerateAllTypes.h&quot;
#endif
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define real unsigned char
#define accreal long
#define Real Byte
#define TH_REAL_IS_BYTE
#line 1 TH_GENERIC_FILE
#include TH_GENERIC_FILE
#undef real
#undef accreal
#undef Real
#undef TH_REAL_IS_BYTE
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define real char
#define accreal long
#define Real Char
#define TH_REAL_IS_CHAR
#line 1 TH_GENERIC_FILE
#include TH_GENERIC_FILE
#undef real
#undef accreal
#undef Real
#undef TH_REAL_IS_CHAR
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Which continued for a few more types. At first I was puzzled, but then I suddenly
realized what it does and how brilliant this is! There are no templates in C, but
objects like THStorage should be available for different types. It would be a
terrible waste to repeat the same implementation with just a few words replaced
and this is what this piece achieves! In generic files you can see
variables of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;real&lt;/code&gt; all over the place. At first it was obvious to me that
it’s probably a matter of some compile time optimizations whether it was chosen to
be a float or a double, but apparently it’s different - it allows code generation
for many other types too!&lt;/p&gt;

&lt;div style=&quot;height: 17px&quot;&gt;&lt;/div&gt;

&lt;p&gt;Clever usage of macros also makes the generic files more readable.
Take this example from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generic/THStorage.c&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;real&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THStorage_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THStorage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It looks nice, but what about name conflicts for different types? It can’t be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THStorage&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THStorage_data&lt;/code&gt; all the time! Worry not, macros take care of that as well:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#define THStorage        TH_CONCAT_3(TH,Real,Storage)
#define THStorage_(NAME) TH_CONCAT_4(TH,Real,Storage_,NAME)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;During preprocessing this function name will be expanded to something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THByteStorage_data&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THStorage&lt;/code&gt; will be replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THByteStorage&lt;/code&gt;. Super cool x2!&lt;/p&gt;

&lt;div style=&quot;height: 17px&quot;&gt;&lt;/div&gt;

&lt;p&gt;It’s also smart to use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#line 1 TH_GENERIC_FILE&lt;/code&gt; directive, because if there
would be any errors they will appear in the compiler as if they were in the original
generic file - not in the middle of the implementation pasted over and over.&lt;/p&gt;

&lt;p&gt;I think that these are some awesome ways to make C code more type-agnostic.&lt;/p&gt;

&lt;h3 id=&quot;oop--virtual-tables&quot;&gt;OOP &amp;amp; Virtual tables&lt;/h3&gt;

&lt;p&gt;TH also implements a file API, where you can find good examples of how you could
implement some basic OOP patterns in C. There are four files that I’ll be
talking about here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THFilePrivate.h&lt;/code&gt; - defines basic structs&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THFile.c&lt;/code&gt; - contains some generic implementation&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THDiskFile.c&lt;/code&gt; - code for handling disk files&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THMemoryFile.c&lt;/code&gt; - implementation of in-memory files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start with the private header file.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THFile__&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THFileVTable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vtable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isQuiet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THFileVTable&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&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;isOpened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;long&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;readByte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&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;readChar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&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;readShort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;short&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&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;readInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can see that it defines a &lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_method_table&quot;&gt;virtual method table&lt;/a&gt;
with pointers to functions that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THFile&lt;/code&gt; subclasses will have to implement
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THFile&lt;/code&gt; is an abstract class - it has no constructors). Other structs are
defined as such:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THDiskFile__&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isNativeEncoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THDiskFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What makes this struct interesting is that because it’s first member is of type THFile
it’s actually valid to cast &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct THDiskFile *&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct THFile *&lt;/code&gt; and use
it normally. What’s more, because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THDiskFile&lt;/code&gt;’s constructor fills in the function pointers
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt; field’s virtual table, it will behave as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THDiskFile&lt;/code&gt; object even when casted to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THFile&lt;/code&gt;!&lt;/p&gt;

&lt;h3 id=&quot;shared-memory&quot;&gt;Shared memory&lt;/h3&gt;

&lt;p&gt;I had little knowledge about UNIX process management and threading until now, when
I took up an operating systems course at my university, so it was really interesting
to learn about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; (maps a file to memory, so you can use it like an array)
and to see how memory can be shared between processes with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shm_open&lt;/code&gt;. I even
wrote a piece of code to try it out. You can find it &lt;a href=&quot;https://github.com/apaszke/apaszke.github.io/tree/master/assets/posts/torch-internals/shared_mem&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;simd&quot;&gt;SIMD&lt;/h3&gt;

&lt;p&gt;Another cool thing you can find in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt; are vector instructions.
There are some cmake tests that check if they are available on your CPU
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake/FindSSE.cmake&lt;/code&gt;) and several files implementing convolution operations
using them (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generic/simd/*&lt;/code&gt;). I can’t understand it yet - function that takes
10 lines of code is expanded to unrolled vectorized loop taking more than 120
lines and using APIs with unreadable function names for a SSE beginner.
This code spans 134 lines after macro expansion:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;convolve_5x5_1_avx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputStride&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputStride&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alignedCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xFFFFFFF8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;DECLARE_OUTPUT_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alignedCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;CONVOLVE_8COLS_XROWS&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Anyway, it’s definitely a thing worth learning so I will probably write more about it soon!&lt;/p&gt;

&lt;h3 id=&quot;allocators&quot;&gt;Allocators&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt; declares it’s own function for memory allocation called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THAlloc&lt;/code&gt;. It tries
to allocate a properly aligned chunks if you allocate big blocks and handles
out-of-memory errors. Before reading Torch’s source I didn’t know about the
concept of allocators. They are just small virtual tables providing their own
memory management API (alloc, realloc, free). It’s cool that you can pass an
Allocator to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THStorage&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THTensor&lt;/code&gt; and construct it not only in the regular
heap region, but also allocate it in the shared memory.&lt;/p&gt;

&lt;h3 id=&quot;random-module&quot;&gt;Random module&lt;/h3&gt;

&lt;p&gt;It’s natural to have a pseudorandom number generator in all programming
languages, but I’ve never read an implementation of one (ok, except the &lt;a href=&quot;https://en.wikipedia.org/wiki/Linear_congruential_generator&quot;&gt;linear congruential generator&lt;/a&gt;). In
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THRandom.c&lt;/code&gt; you can find a full implementation of &lt;a href=&quot;https://en.wikipedia.org/wiki/Mersenne_Twister&quot;&gt;Mersenne twister&lt;/a&gt;,
which (according to Wikipedia) is a default implementation for R, Python, Ruby,
PHP, CMU Common Lisp, GLib, MATLAB and some more. There are also several methods
which convert returned uniform distribution into other shapes.&lt;/p&gt;

&lt;h2 id=&quot;quick-library-overview&quot;&gt;Quick library overview&lt;/h2&gt;

&lt;p&gt;In this section I will briefly describe most of the functionalities provided by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;THAllocator&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;creates a default default allocator, which just calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt; memory
  management functions and, if possible, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THMapAllocator&lt;/code&gt; that can map files
  or shared memory objects into memory.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THAtomic&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;multiplatform implementation of atomic operations&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THTensor&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;defines a general Tensor type&lt;/li&gt;
      &lt;li&gt;supports lots of indexing, linear algebra and math operations&lt;/li&gt;
      &lt;li&gt;available for all primitive datatypes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&amp;lt;type&amp;gt;Tensor&lt;/code&gt;, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THFloatTensor&lt;/code&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THBlas&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;wraps BLAS library for use in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THTensor&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;provides a general implementation as a fallback&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THLapack&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;wraps LAPACK library for use in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THTensor&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;DOESN’T&lt;/strong&gt; provide fallbacks - throws errors if called&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THFile&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;abstract file class&lt;/li&gt;
      &lt;li&gt;only creates wrappers for calling methods contained in virtual table&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THDiskFile&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;concrete file class&lt;/li&gt;
      &lt;li&gt;wraps disk file APIs&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THMemoryFile&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;concrete file class&lt;/li&gt;
      &lt;li&gt;operates on an in-memory buffer and fakes file operations&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THGeneral&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;implements general utilities&lt;/li&gt;
      &lt;li&gt;contains memory management routines&lt;/li&gt;
      &lt;li&gt;can notify external GCs&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THRandom&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;implements a random number generator&lt;/li&gt;
      &lt;li&gt;can sample from many distributions&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;THStorage&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;defines a general storage object&lt;/li&gt;
      &lt;li&gt;contains mainly bookkeeping code&lt;/li&gt;
      &lt;li&gt;available for all primitive datatypes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&amp;lt;type&amp;gt;Storage&lt;/code&gt;, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THFloatStorage&lt;/code&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;

&lt;p&gt;If you want to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt; you can either perform a full Torch installation or
you can follow these steps:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# clone Torch repository&lt;/span&gt;
git clone https://github.com/torch/torch7
&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;th_build
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;th_build
&lt;span class=&quot;c&quot;&gt;# configure TH build&lt;/span&gt;
cmake ../torch7/lib/TH
&lt;span class=&quot;c&quot;&gt;# compile library&lt;/span&gt;
make
&lt;span class=&quot;c&quot;&gt;# install shared library and header files&lt;/span&gt;
make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, you only have to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#include &amp;lt;TH/TH.h&amp;gt;&lt;/code&gt; in your program and link the library
during the compilation process (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-lTH&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;example-program&quot;&gt;Example program&lt;/h2&gt;

&lt;p&gt;To wrap up I just wanted to show you an example program using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt;. It will
simply load 10 floats from two files into tensors, compute their dot product
and add to it a sum of all values in one of them. This is the code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;TH/TH.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THDiskFile_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;THFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THDiskFile_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;THFloatTensor&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;THFloatTensor_newWithSize1d&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;THFloatTensor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THFloatTensor_newWithSize1d&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;THFile_readFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_file&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;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;storage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;THFile_readFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;storage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THFloatTensor_dot&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;y&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;THFloatTensor_sumall&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;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;THFloatTensor_free&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;THFloatTensor_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;THFile_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;THFile_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_file&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All input parsing and possible errors are handled by Torch. Convenient, isn’t it?&lt;/p&gt;

&lt;h2 id=&quot;afterthoughts&quot;&gt;Afterthoughts&lt;/h2&gt;

&lt;p&gt;I actually enjoy reading other’s source code -
especially if it’s well written. If you have some spare time, then seriously, consider
picking your favourite library or framework, and try to understand how it works - even
the tiniest bits of it. I guarantee that you will find many fascinating things
and learn many concepts and ways of structuring your code that you had no idea existed.
I haven’t learned that much in such short period of time for a while. I liked
it so that I’m thinking about doing this on a more regular basis.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TH&lt;/code&gt; has no documentation at the moment. Since I’ve already studied most of it’s
code, I’ll probably try to write at least a bit. I’ve used Torch for so long
that it’s time to make some contribution myself.&lt;/p&gt;

&lt;p&gt;Thanks for reading! I hope that you liked it!&lt;/p&gt;
</description>
        <pubDate>Sun, 18 Oct 2015 20:05:24 +0000</pubDate>
        <link>https://apaszke.github.io/torch-internals.html</link>
        <guid isPermaLink="true">https://apaszke.github.io/torch-internals.html</guid>
        
        
      </item>
    
      <item>
        <title>LSTM implementation explained</title>
        <description>&lt;h2 id=&quot;preface&quot;&gt;Preface&lt;/h2&gt;
&lt;p&gt;For a long time I’ve been looking for a good tutorial on implementing LSTM networks.
They seemed to be complicated and I’ve never done anything with them before.
Quick googling didn’t help, as all I’ve found were some slides.&lt;/p&gt;

&lt;p&gt;Fortunately, I took part in &lt;a href=&quot;https://www.kaggle.com/c/grasp-and-lift-eeg-detection&quot;&gt;Kaggle EEG Competition&lt;/a&gt; and thought that it might be fun
to use LSTMs and finally learn how they work. I based &lt;a href=&quot;https://github.com/apaszke/kaggle-grasp-and-lift&quot;&gt;my solution&lt;/a&gt; and this post’s code on &lt;a href=&quot;https://github.com/karpathy/char-rnn&quot;&gt;char-rnn&lt;/a&gt;
by &lt;a href=&quot;https://karpathy.github.io&quot;&gt;Andrej Karpathy&lt;/a&gt;,
which I highly recommend you to check out.&lt;/p&gt;

&lt;h3 id=&quot;rnn-misconception&quot;&gt;RNN misconception&lt;/h3&gt;
&lt;p&gt;There is one important thing that as I feel
hasn’t been emphasized strongly enough (and is the main reason why I couldn’t get myself to
do anything with RNNs). There isn’t much difference between an RNN and
feedforward network implementation. It’s the easiest to implement an RNN just
as a feedforward network with some parts of the input feeding into the middle of the stack,
and a bunch of outputs coming out from there as well. There is no magic internal state
kept in the network. It’s provided as a part of the input!&lt;/p&gt;

&lt;div class=&quot;images&quot;&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/RNNvsFNN.svg&quot; /&gt;
  &lt;div class=&quot;label&quot;&gt;
    The overall structure of RNNs is very similar to that of feedforward networks.
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;lstm-refresher&quot;&gt;LSTM refresher&lt;/h3&gt;

&lt;p&gt;This section will cover only the formal definition of LSTMs. There are lots of other nice
blog posts describing in detail how can you imagine and think of these equations.&lt;/p&gt;

&lt;p&gt;LSTMs have many variations,
but we’ll stick to a simple one. One cell consists of three gates (input, forget, output),
and a cell unit. Gates use a sigmoid activation, while input and cell state is often
transformed with tanh. LSTM cell can be defined with a following set of equations:&lt;/p&gt;

&lt;p&gt;Gates:&lt;/p&gt;

\[i_{t} = g(W_{xi}x_{t} + W_{hi}h_{t-1} + b_{i})\]

\[f_{t} = g(W_{xf}x_{t} + W_{hf}h_{t-1} + b_{f})\]

\[o_{t} = g(W_{xo}x_{t} + W_{ho}h_{t-1} + b_{o})\]

&lt;p&gt;Input transform:&lt;/p&gt;

\[c\_in_{t} = tanh(W_{xc}x_{t} + W_{hc}h_{t-1} + b_{c\_in})\]

&lt;p&gt;State update:&lt;/p&gt;

\[c_{t} = f_{t} \cdot c_{t-1} + i_{t} \cdot c\_in_{t}\]

\[h_{t} = o_{t} \cdot tanh(c_{t})\]

&lt;p&gt;It can be pictured like this:&lt;/p&gt;

&lt;div class=&quot;images&quot;&gt;
  &lt;img alt=&quot;LSTM cell diagram&quot; src=&quot;assets/posts/lstm-explained/cell.svg&quot; style=&quot;width: 40%&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Because of the gating mechanism the cell can keep a piece of information for long
periods of time during work and protect the gradient inside the cell from harmful changes during the training.
Vanilla LSTMs don’t have a forget gate and add unchanged cell state
during the update (it can be seen as a recurrent connection with a constant weight of 1),
what is often referred to as a Constant Error Carousel (CEC).
It’s called like that, because it solves a serious RNN training problem of vanishing and exploding gradients,
which in turn makes it possible to learn long-term relationships.&lt;/p&gt;

&lt;h2 id=&quot;building-your-own-lstm-layer&quot;&gt;Building your own LSTM layer&lt;/h2&gt;
&lt;p&gt;The code for this tutorial will be using Torch7.
&lt;strong&gt;Don’t worry if you don’t know it&lt;/strong&gt;. I’ll explain everything, so you’ll be able
to implement the same algorithm in your favorite framework.&lt;/p&gt;

&lt;p&gt;The network will be implemented as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nngraph.gModule&lt;/code&gt;, which basically means that we’ll define
a computation graph consisting of standard &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn&lt;/code&gt; modules.
We will need the following layers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Identity()&lt;/code&gt; - passes on the input (used as a placeholder for input)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Dropout(p)&lt;/code&gt; - standard dropout module (drops with probability &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 - p&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Linear(in, out)&lt;/code&gt; - an affine transform from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in&lt;/code&gt; dimensions to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out&lt;/code&gt; dims&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Narrow(dim, start, len)&lt;/code&gt; - selects a subvector along &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dim&lt;/code&gt; dimension having &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;len&lt;/code&gt; elements starting from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt; index&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Sigmoid()&lt;/code&gt; - applies sigmoid element-wise&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Tanh()&lt;/code&gt; - applies tanh element-wise&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.CMulTable()&lt;/code&gt; - outputs the product of tensors in forwarded table&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.CAddTable()&lt;/code&gt; - outputs the sum of tensors in forwarded table&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;inputs&quot;&gt;Inputs&lt;/h3&gt;

&lt;p&gt;First, let’s define the input structure. The array-like objects in lua
are called tables. This network will accept a table of tensors like the one below:&lt;/p&gt;

&lt;div class=&quot;images&quot;&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/input_table.svg&quot; alt=&quot;Input table structure&quot; style=&quot;width: 30%;&quot; /&gt;
&lt;/div&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputs&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;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()())&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- network input&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()())&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- c at time t-1&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()())&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- h at time t-1&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&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;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prev_c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prev_h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Identity modules will just copy whatever we provide to the network into the graph.&lt;/p&gt;

&lt;h3 id=&quot;computing-gate-values&quot;&gt;Computing gate values&lt;/h3&gt;

&lt;p&gt;To make our implementation faster we will be applying the transformations of the whole
LSTM layer simultaneously.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i2h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- input to hidden&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h2h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prev_h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- hidden to hidden&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;preactivations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CAddTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i2h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h2h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;-- i2h + h2h&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you’re unfamiliar with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nngraph&lt;/code&gt; it probably seems strange that we’re constructing
a module and already calling it once more with a graph node. What actually happens is that the
second call converts the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Module&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nngraph.gModule&lt;/code&gt; and the argument specifies it’s parent in the graph.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preactivations&lt;/code&gt; outputs a vector created by a linear transform of input
and previous hidden state. These are raw values which will be used to compute the
gate activations and the cell input. This vector is divided into 4 parts, each
of size &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rnn_size&lt;/code&gt;. The first will be used for in gates, second for forget gates,
third for out gates and the last one as a cell input (so the indices of respective gates
and input of a cell number \(i\) are
\(\left\{i,\ \text{rnn_size}+i,\ 2\cdot\text{rnn_size}+i,\  3\cdot\text{rnn_size}+i\right\}\)).&lt;/p&gt;

&lt;div class=&quot;images&quot;&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/graph1_full.svg&quot; alt=&quot;First graph part&quot; style=&quot;width: 30%;&quot; /&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/preactivation_graph.svg&quot; alt=&quot;First part closeup&quot; style=&quot;width: 40%;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Next, we have to apply a nonlinearity, but while all the gates use the sigmoid,
we will use a tanh for the input preactivation. Because of this, we will place two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Narrow&lt;/code&gt;
modules, which will select appropriate parts of the preactivation vector.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;c1&quot;&gt;-- gates&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pre_sigmoid_chunk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Narrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;preactivations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_gates&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sigmoid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pre_sigmoid_chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- input&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in_chunk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Narrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rnn_size&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;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;preactivations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in_transform&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tanh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in_chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After the nonlinearities we have to place a couple more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Narrow&lt;/code&gt;s and we have the gates done!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in_gate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Narrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all_gates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forget_gate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Narrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rnn_size&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;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all_gates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out_gate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Narrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rnn_size&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;n&quot;&gt;rnn_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all_gates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;images&quot;&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/graph2_full.svg&quot; alt=&quot;Second graph part&quot; style=&quot;width: 30%;&quot; /&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/gates.svg&quot; alt=&quot;Second part closeup&quot; style=&quot;width: 40%;&quot; /&gt;
&lt;/div&gt;

&lt;h3 id=&quot;cell-and-hidden-state&quot;&gt;Cell and hidden state&lt;/h3&gt;

&lt;p&gt;Having computed the gate values we can now calculate the current cell state. All that’s required are just
two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.CMulTable&lt;/code&gt; modules (one for \(f \cdot c_{t-1}^{l}\) and one for \(i \cdot x\)),
and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.CAddTable&lt;/code&gt; to sum them up to a current cell state.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;c1&quot;&gt;-- previous cell state contribution&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_forget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CMulTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forget_gate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prev_c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- input contribution&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CMulTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in_gate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in_transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- next cell state&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CAddTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()({&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;c_forget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;c_input&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s finally time to implement hidden state calculation. It’s the simplest part, because it just
involves applying tanh to current cell state (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.Tanh&lt;/code&gt;) and multiplying it with an output gate
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nn.CMulTable&lt;/code&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_transform&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tanh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CMulTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out_gate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;images&quot;&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/graph3_full.svg&quot; alt=&quot;Third graph part&quot; style=&quot;width: 30%;&quot; /&gt;
  &lt;img src=&quot;assets/posts/lstm-explained/state_calculation.svg&quot; alt=&quot;Third part closeup&quot; style=&quot;width: 40%;&quot; /&gt;
&lt;/div&gt;

&lt;h3 id=&quot;defining-the-module&quot;&gt;Defining the module&lt;/h3&gt;

&lt;p&gt;Now, if you want to export the whole graph as a standalone module you can wrap it like that:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;c1&quot;&gt;-- module outputs&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;outputs&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;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;outputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;table.insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;outputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- packs the graph into a convenient module with standard API (:forward(), :backward())&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;

&lt;p&gt;LSTM layer implementation is available &lt;a href=&quot;/assets/posts/lstm-explained/LSTM.lua&quot;&gt;here&lt;/a&gt;.
You can use it like that:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;th&amp;gt; LSTM &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; require &lt;span class=&quot;s1&quot;&gt;'LSTM.lua'&lt;/span&gt;
                                                                      &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0.0224s]
th&amp;gt; layer &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; LSTM.create&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3, 2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                                                                      &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0.0019s]
th&amp;gt; layer:forward&lt;span class=&quot;o&quot;&gt;({&lt;/span&gt;torch.randn&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1,3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, torch.randn&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1,2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, torch.randn&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1,2&lt;span class=&quot;o&quot;&gt;)})&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  1 : DoubleTensor - size: 1x2
  2 : DoubleTensor - size: 1x2
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
                                                                      &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0.0005s]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To make a multi-layer LSTM network you can forward subsequent layers in a for loop,
taking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next_h&lt;/code&gt; from previous layer as next layer’s input. You can check &lt;a href=&quot;/assets/posts/lstm-explained/multilayer.lua&quot;&gt;this example&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;training&quot;&gt;Training&lt;/h3&gt;

&lt;p&gt;If you’re interested please leave a comment and I’ll try to expand this post!&lt;/p&gt;

&lt;h2 id=&quot;thats-it&quot;&gt;That’s it!&lt;/h2&gt;

&lt;p&gt;That’s it. It’s quite easy to implement any RNN when you understand how to deal with the hidden state.
After connecting several layers just put a regular MLP on top and connect it to last
layer’s hidden state and you’re done!&lt;/p&gt;

&lt;p&gt;Here are some nice papers on RNNs if you’re interested:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://arxiv.org/abs/1506.02078&quot;&gt;Visualizing and Understanding Recurrent Networks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf&quot;&gt;An Empirical Exploration of Recurrent Network Architectures&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://arxiv.org/abs/1409.2329&quot;&gt;Recurrent Neural Network Regularization&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-networks.pdf&quot;&gt;Sequence to Sequence Learning with Neural Networks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;script&gt;
  var disqus_identifier = 'lstm-explained';
  var disqus_title = 'LSTM implementation explained'
  var disqus_url = 'https://apaszke.github.io/lstm-explained.html'
&lt;/script&gt;

</description>
        <pubDate>Sun, 30 Aug 2015 20:04:15 +0000</pubDate>
        <link>https://apaszke.github.io/lstm-explained.html</link>
        <guid isPermaLink="true">https://apaszke.github.io/lstm-explained.html</guid>
        
        
      </item>
    
  </channel>
</rss>
