<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>divergences</title>
<link>https://divergences.xyz/tag/time-series.html</link>
<atom:link href="https://divergences.xyz/tag/time-series.xml" rel="self" type="application/rss+xml"/>
<description>A blog by Sigrid Keydana. Opinions are exclusively mine.</description>
<generator>quarto-1.10.19</generator>
<lastBuildDate>Thu, 19 Jan 2023 00:00:00 GMT</lastBuildDate>
<item>
  <title>AO, NAO, ENSO: A wavelet analysis example</title>
  <dc:creator>Sigrid Keydana</dc:creator>
  <link>https://divergences.xyz/posts/torchwavelets/</link>
  <description><![CDATA[ 






<p>Recently, we showed how to use <code>torch</code> for <a href="https://blogs.rstudio.com/ai/posts/2022-10-27-wavelets/">wavelet analysis</a>. A member of the family of spectral analysis methods, wavelet analysis bears some similarity to the Fourier Transform, and specifically, to its popular two-dimensional application, the spectrogram.</p>
<p>As explained in that book excerpt, though, there are significant differences. For the purposes of the current post, it suffices to know that frequency-domain patterns are discovered by having a little “wave” (that, really, can be of any shape) “slide” over the data, computing degree of match (or mismatch) in the neighborhood of every sample.</p>
<p>With this post, then, my goal is two-fold.</p>
<p>First, to introduce <a href="https://github.com/skeydan/torchwavelets">torchwavelets</a>, a tiny, yet useful package that automates all of the essential steps involved. Compared to the Fourier Transform and its applications, the topic of wavelets is rather “chaotic” – meaning, it enjoys much less shared terminology, and much less shared practice. Consequently, it makes sense for implementations to follow established, community-embraced approaches, whenever such are available and well documented. With <code>torchwavelets</code>, we provide an implementation of Torrence and Compo’s 1998 “Practical Guide to Wavelet Analysis” (<span class="citation" data-cites="Torrence.Compo1998">Torrence and Compo (1998)</span>), an oft-cited paper that proved influential across a wide range of application domains. Code-wise, our package is mostly a port of <a href="https://github.com/QUVA-Lab/PyTorchWavelets/">Tom Runia’s PyTorch implementation</a>, itself based on a prior implementation by <a href="https://github.com/aaren/wavelets/">Aaron O’Leary</a>.</p>
<div class="no-row-height column-margin column-container"><div id="ref-Torrence.Compo1998" class="csl-entry">
Torrence, C., and G. P. Compo. 1998. <span>“A Practical Guide to Wavelet Analysis.”</span> <em>Bulletin of the American Meteorological Society</em> 79 (1): 61–78.
</div></div><p>Second, to show an attractive use case of wavelet analysis in an area of great scientific interest and tremendous social importance (meteorology/climatology). Being by no means an expert myself, I’d hope this could be inspiring to people working in these fields, as well as to scientists and analysts in other areas where temporal data arise.</p>
<p>Concretely, what we’ll do is take three different atmospheric phenomena – El Niño–Southern Oscillation (ENSO), North Atlantic Oscillation (NAO), and Arctic Oscillation (AO) – and investigate them using wavelet analysis. In each case, we also look at the overall frequency spectrum, given by the Discrete Fourier Transform (DFT), as well as a classic time-series decomposition into trend, seasonal components, and remainder.</p>
<section id="three-oscillations" class="level2">
<h2 class="anchored" data-anchor-id="three-oscillations">Three oscillations</h2>
<p>By far the best-known – the most infamous, I should say – among the three is <a href="https://en.wikipedia.org/wiki/El_Ni%C3%B1o%E2%80%93Southern_Oscillation">El Niño–Southern Oscillation (ENSO)</a>, a.k.a. El Niño/La Niña. The term refers to a changing pattern of sea surface temperatures and sea-level pressures occurring in the equatorial Pacific. Both El Niño and La Niña can and do have catastrophic impact on people’s lives, most notably, for people in developing countries west and east of the Pacific.</p>
<p>El Niño occurs when surface water temperatures in the eastern Pacific are higher than normal, and the strong winds that normally blow from east to west are unusually weak. From April to October, this leads to hot, extremely wet weather conditions along the coasts of northern Peru and Ecuador, continually resulting in major floods. La Niña, on the other hand, causes a drop in sea surface temperatures over Southeast Asia as well as heavy rains over Malaysia, the Philippines, and Indonesia. While these are the areas most gravely impacted, changes in ENSO reverberate across the globe.</p>
<p>Less well known than ENSO, but highly influential as well, is the <a href="https://en.wikipedia.org/wiki/North_Atlantic_oscillation">North Atlantic Oscillation (NAO)</a>. It strongly affects winter weather in Europe, Greenland, and North America. Its two states relate to the size of the pressure difference between the Icelandic High and the Azores Low. When the pressure difference is high, the jet stream – those strong westerly winds that blow between North America and Northern Europe – is yet stronger than normal, leading to warm, wet European winters and calmer-than-normal conditions in Eastern North America. With a lower-than-normal pressure difference, however, the American East tends to incur more heavy storms and cold-air outbreaks, while winters in Northern Europe are colder and more dry.</p>
<p>Finally, the <a href="https://en.wikipedia.org/wiki/Arctic_oscillation">Arctic Oscillation (AO)</a> is a ring-like pattern of sea-level pressure anomalies centered at the North Pole. (Its Southern-hemisphere equivalent is the <a href="https://en.wikipedia.org/wiki/Antarctic_oscillation">Antarctic Oscillation</a>.) AO’s influence extends beyond the Arctic Circle, however; it is indicative of whether and how much Arctic air flows down into the middle latitudes. AO and NAO are strongly related, and might designate the same physical phenomenon at a fundamental level.</p>
<p>Now, let’s make these characterizations more concrete by looking at actual data.</p>
</section>
<section id="analysis-enso" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="analysis-enso">Analysis: ENSO</h2>
<p>We begin with the best-known of these phenomena: ENSO. Data are available from 1854 onwards; however, for comparability with AO, we discard all records prior to January, 1950. For analysis, we pick <code>NINO34_MEAN</code>, the monthly average sea surface temperature in the Niño 3.4 region (i.e., the area between 5° South, 5° North, 190° East, and 240° East). Finally, we convert to a <code>tsibble</code>, the format expected by <code>feasts::STL()</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tsibble)</span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">download.file</span>(</span>
<span id="cb1-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://bmcnoldy.rsmas.miami.edu/tropics/oni/ONI_NINO34_1854-2022.txt"</span>,</span>
<span id="cb1-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">destfile =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ONI_NINO34_1854-2022.txt"</span></span>
<span id="cb1-7">)</span>
<span id="cb1-8"></span>
<span id="cb1-9">enso <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_table</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ONI_NINO34_1854-2022.txt"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">skip =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb1-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yearmonth</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(YEAR, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MON/MMM</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-01"</span>)))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb1-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">enso =</span> NINO34_MEAN) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb1-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yearmonth</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1950-01"</span>), x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yearmonth</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2022-09"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb1-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_tsibble</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">index =</span> x)</span>
<span id="cb1-14"></span>
<span id="cb1-15">enso</span></code></pre></div></div>
<pre><code># A tsibble: 873 x 2 [1M]
          x  enso
      &lt;mth&gt; &lt;dbl&gt;
 1 1950 Jan  24.6
 2 1950 Feb  25.1
 3 1950 Mar  25.9
 4 1950 Apr  26.3
 5 1950 May  26.2
 6 1950 Jun  26.5
 7 1950 Jul  26.3
 8 1950 Aug  25.9
 9 1950 Sep  25.7
10 1950 Oct  25.7
# … with 863 more rows</code></pre>
<p>As already announced, we want to look at seasonal decomposition, as well. In terms of seasonal periodicity, what do we expect? Unless told otherwise, <code>feasts::STL()</code> will happily pick a window size for us. However, there’ll likely be several important frequencies in the data. (Not wanting to ruin the suspense, but for AO and NAO, this will definitely be the case!). Besides, we want to compute the Fourier Transform anyway, so why not do that first?</p>
<p>Here is the power spectrum:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torch)</span>
<span id="cb3-2">fft <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_fft_fft</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(enso<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>enso)))</span></code></pre></div></div>
<p>In the below plot, the x axis corresponds to frequencies, expressed as “number of times per year”. We only display frequencies up to and including the Nyquist frequency, i.e., half the sampling rate, which in our case is 12 (per year).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">num_samples <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(enso)</span>
<span id="cb4-2">nyquist_cutoff <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ceiling</span>(num_samples <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># highest discernible frequency</span></span>
<span id="cb4-3">bins_below_nyquist <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>nyquist_cutoff</span>
<span id="cb4-4"></span>
<span id="cb4-5">sampling_rate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># per year</span></span>
<span id="cb4-6">frequencies_per_bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sampling_rate <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> num_samples</span>
<span id="cb4-7">frequencies <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> frequencies_per_bin <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> bins_below_nyquist</span>
<span id="cb4-8"></span>
<span id="cb4-9">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">f =</span> frequencies, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(fft[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(nyquist_cutoff <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>()))</span>
<span id="cb4-10">df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(f, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"frequency (per year)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ylab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magnitude"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggtitle</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Spectrum of Niño 3.4 data"</span>)</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="spectrum-enso.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-1" title="Frequency spectrum of monthly average sea surface temperature in the Niño 3.4 region, 1950 to present."><img src="https://divergences.xyz/posts/torchwavelets/spectrum-enso.png" class="img-fluid figure-img column-body-outset-right" alt="Frequency spectrum of monthly average sea surface temperature in the Niño 3.4 region, 1950 to present."></a></p>
<figcaption>Frequency spectrum of monthly average sea surface temperature in the Niño 3.4 region, 1950 to present.</figcaption>
</figure>
</div>
</div>
<p>There is one dominant frequency, corresponding to about once a year. From this component alone, we’d expect one El Niño event – or equivalently, one La Niña – per year. But let’s locate important frequencies more precisely. With not many other periodicities standing out, we may as well restrict ourselves to three:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">strongest <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_topk</span>(fft[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(nyquist_cutoff<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb5-2">strongest</span></code></pre></div></div>
<pre><code>[[1]]
torch_tensor
233.9855
172.2784
142.3784
[ CPUFloatType{3} ]

[[2]]
torch_tensor
74
21
7
[ CPULongType{3} ]</code></pre>
<p>What we have here are the magnitudes of the dominant components, as well as their respective bins in the spectrum. Let’s see which actual frequencies these correspond to:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">important_freqs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> frequencies[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(strongest[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]])]</span>
<span id="cb7-2">important_freqs</span></code></pre></div></div>
<pre><code>[1] 1.00343643 0.27491409 0.08247423 </code></pre>
<p>That’s once per year, once per quarter, and once every twelve years, approximately. Or, expressed as periodicity, in terms of months (i.e., how many months are there in a period):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">num_observations_in_season <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>important_freqs  </span>
<span id="cb9-2">num_observations_in_season</span></code></pre></div></div>
<pre><code>[1] 11.95890  43.65000 145.50000  </code></pre>
<p>We now pass these to <code>feasts::STL()</code>, to obtain a five-fold decomposition into trend, seasonal components, and remainder.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(feasts)</span>
<span id="cb11-2">enso <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb11-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">STL</span>(enso <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">44</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-4">              <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">145</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb11-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">components</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb11-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">autoplot</span>()</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="stl_enso.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-2" title="Decomposition of ENSO data into trend, seasonal components, and remainder by feasts::STL()."><img src="https://divergences.xyz/posts/torchwavelets/stl_enso.png" class="img-fluid figure-img column-body-outset-right" alt="Decomposition of ENSO data into trend, seasonal components, and remainder by feasts::STL()."></a></p>
<figcaption>Decomposition of ENSO data into trend, seasonal components, and remainder by <code>feasts::STL()</code>.</figcaption>
</figure>
</div>
</div>
<p>According to Loess decomposition, there still is significant noise in the data – the remainder remaining high despite our hinting at important seasonalities. In fact, there is no big surprise in that: Looking back at the DFT output, not only are there many, close to one another, low- and lowish-frequency components, but in addition, high-frequency components just won’t cease to contribute. And really, as of today, ENSO forecasting – tremendously important in terms of human impact – is focused on predicting oscillation state just a year in advance. This will be interesting to keep in mind for when we proceed to the other series – as you’ll see, it’ll only get worse.</p>
<p>By now, we’re well informed about how dominant temporal rhythms determine, or fail to determine, what actually happens in atmosphere and ocean. But we don’t know anything about whether, and how, those rhythms may have varied in strength over the time span considered. This is where wavelet analysis comes in.</p>
<p>In <code spellcheck="false">torchwavelets</code>, the central operation is a call to <code>wavelet_transform()</code>, to instantiate an object that takes care of all required operations. One argument is required: <code>signal_length</code>, the number of data points in the series. And one of the defaults we <em>need</em> to override: <code>dt</code>, the time between samples, expressed in the unit we’re working with. In our case, that’s <em>year</em>, and, having monthly samples, we need to pass a value of 1/12. With all other defaults untouched, analysis will be done using the <a href="https://en.wikipedia.org/wiki/Morlet_wavelet">Morlet wavelet</a> (available alternatives are <a href="https://en.wikipedia.org/wiki/Ricker_wavelet">Mexican Hat</a> and <a href="https://reference.wolfram.com/language/ref/PaulWavelet.html">Paul</a>), and the transform will be computed in the Fourier domain (the fastest way, unless you have a GPU).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torchwavelets)</span>
<span id="cb12-2">enso_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> enso<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>enso <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tensor</span>()</span>
<span id="cb12-3">dt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span></span>
<span id="cb12-4">wtf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wavelet_transform</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(enso_idx), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dt =</span> dt)</span></code></pre></div></div>
<p>A call to <code>power()</code> will then compute the wavelet transform:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">power_spectrum <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">power</span>(enso_idx)</span>
<span id="cb13-2">power_spectrum<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>shape</span></code></pre></div></div>
<pre><code>[1]  71 873</code></pre>
<p>The result is two-dimensional. The second dimension holds measurement times, i.e., the months between January, 1950 and September, 2022. The first dimension warrants some more explanation.</p>
<p>Namely, we have here the set of scales the transform has been computed for. If you’re familiar with the Fourier Transform and its analogue, the spectrogram, you’ll probably think in terms of time versus frequency. With wavelets, there is an additional parameter, the scale, that determines the spread of the analysis pattern.</p>

<div class="no-row-height column-margin column-container"><div class="">
<p>The aforementioned <a href="https://blogs.rstudio.com/ai/posts/2022-10-27-wavelets/">book excerpt</a> discusses this in detail.</p>
</div></div><p>Some wavelets have both a scale and a frequency, in which case these can interact in complex ways. Others are defined such that no separate frequency appears. In the latter case, you immediately end up with the time vs.&nbsp;scale layout we see in wavelet diagrams (scaleograms). In the former, most software hides the complexity by merging scale and frequency into one, leaving just scale as a user-visible parameter. In <code>torchwavelets</code>, too, the wavelet frequency (if existent) has been “streamlined away”. Consequently, we’ll end up plotting time versus scale, as well. I’ll say more when we actually see such a scaleogram.</p>
<p>For visualization, we transpose the data and put it into a <code>ggplot</code>-friendly format:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1">times <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lubridate<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">year</span>(enso<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lubridate<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">month</span>(enso<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span></span>
<span id="cb15-2">scales <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scales)</span>
<span id="cb15-3"></span>
<span id="cb15-4">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_tibble</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(power_spectrum<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>()), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.name_repair =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"universal"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">time =</span> times) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>time, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> scales[scale <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_remove</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.]{3}"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>()])</span>
<span id="cb15-10">df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glimpse</span>()</span></code></pre></div></div>
<pre><code>Rows: 61,983
Columns: 3
$ time  &lt;dbl&gt; 1950.083, 1950.083, 1950.083, 1950.083, 195…
$ scale &lt;dbl&gt; 0.1613356, 0.1759377, 0.1918614, 0.2092263,…
$ power &lt;dbl&gt; 0.03617507, 0.05985500, 0.07948010, 0.09819…</code></pre>
<p>There is one additional piece of information to be incorporated, still: the so-called “cone of influence” (COI). Visually, this is a shading that tells us which part of the plot reflects incomplete, and thus, unreliable and to-be-disregarded, data. Namely, the bigger the scale, the more spread-out the analysis wavelet, and the more incomplete the overlap at the borders of the series when the wavelet slides over the data. You’ll see what I mean in a second.</p>
<p>The COI gets its own data frame:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1">coi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coi</span>(times[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], times[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(enso_idx)])</span>
<span id="cb17-2">coi_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(coi[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(coi[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]))</span></code></pre></div></div>
<p>And now we’re ready to create the scaleogram:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">labeled_scales <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>)</span>
<span id="cb18-2">labeled_frequencies <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fourier_period</span>(labeled_scales)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb18-3"></span>
<span id="cb18-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(df) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(</span>
<span id="cb18-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trans =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose_trans</span>(scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2_trans</span>(), scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reverse_trans</span>()),</span>
<span id="cb18-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>),</span>
<span id="cb18-8">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(scales), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(scales)),</span>
<span id="cb18-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expand =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>),</span>
<span id="cb18-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sec.axis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dup_axis</span>(</span>
<span id="cb18-11">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">label_number</span>(labeled_frequencies),</span>
<span id="cb18-12">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fourier period (years)"</span></span>
<span id="cb18-13">    )</span>
<span id="cb18-14">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ylab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale (years)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1950</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2020</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expand =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"year"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_contour_filled</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(time, scale, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">z =</span> power), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_viridis_d</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"turbo"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_ribbon</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> coi_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymin =</span> y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymax =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(scales)),</span>
<span id="cb18-21">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>)</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="scaleogram-enso.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-3" title="Scaleogram of ENSO data."><img src="https://divergences.xyz/posts/torchwavelets/scaleogram-enso.png" class="img-fluid figure-img column-body-outset-right" alt="Scaleogram of ENSO data."></a></p>
<figcaption>Scaleogram of ENSO data.</figcaption>
</figure>
</div>
</div>
<p>What we see here is how, in ENSO, different rhythms have prevailed over time. Instead of “rhythms”, I could have said “scales”, or “frequencies”, or “periods” – all those translate into one another. Since, to us humans, wavelet scales don’t mean that much, the period (in years) is displayed on an additional y axis on the right.</p>
<p>So, we see that in the eighties, an (approximately) four-year period had exceptional influence. Thereafter, yet longer periodicities gained in dominance. And, in accordance with what we expect from prior analysis, there is a <em>basso continuo</em> of annual similarity.</p>
<p>Also, note how, at first sight, there seems to have been a decade where a six-year period stood out: right at the beginning of where (for us) measurement starts, in the fifties. However, the dark shading – the COI – tells us that, in this region, the data is not to be trusted.</p>
<p>Summing up, the two-dimensional analysis nicely complements the more compressed characterization we got from the DFT. Before we move on to the next series, however, let me just quickly address one question, in case you were wondering (if not, just read on, since I won’t be going into details anyway): How is this different from a spectrogram?</p>
<p>In a nutshell, the spectrogram splits the data into several “windows”, and computes the DFT independently on all of them. To compute the scaleogram, on the other hand, the analysis wavelet slides continuously over the data, resulting in a spectrum-equivalent for the neighborhood of each sample in the series. With the spectrogram, a fixed window size means that not all frequencies are resolved equally well: The higher frequencies appear more frequently in the interval than the lower ones, and thus, will allow for better resolution. Wavelet analysis, in contrast, is done on a set of scales deliberately arranged so as to capture a broad range of frequencies theoretically visible in a series of given length.</p>

<div class="no-row-height column-margin column-container"><div class="">
<p>Take a look at the aforementioned <a href="https://blogs.rstudio.com/ai/posts/2022-10-27-wavelets/">book excerpt</a> to see spectrogram and scaleogram compared in a nice application.</p>
</div></div></section>
<section id="analysis-nao" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="analysis-nao">Analysis: NAO</h2>
<p>The data file for NAO is in fixed-table format. After conversion to a <code>tsibble</code>, we have:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">download.file</span>(</span>
<span id="cb19-2"> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://crudata.uea.ac.uk/cru/data//nao/nao.dat"</span>,</span>
<span id="cb19-3"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">destfile =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nao.dat"</span></span>
<span id="cb19-4">)</span>
<span id="cb19-5"></span>
<span id="cb19-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># needed for AO, as well</span></span>
<span id="cb19-7">use_months <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq.Date</span>(</span>
<span id="cb19-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">from =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1950-01-01"</span>),</span>
<span id="cb19-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">to =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2022-09-01"</span>),</span>
<span id="cb19-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"months"</span></span>
<span id="cb19-11">)</span>
<span id="cb19-12"></span>
<span id="cb19-13">nao <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb19-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_table</span>(</span>
<span id="cb19-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nao.dat"</span>,</span>
<span id="cb19-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col_names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb19-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-99.99"</span>,</span>
<span id="cb19-18">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">skip =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb19-19">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>X1, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>X14) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-24">  .[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(use_months)] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-25">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb19-26">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> use_months,</span>
<span id="cb19-27">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nao =</span> .</span>
<span id="cb19-28">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-29">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yearmonth</span>(x)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-30">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fill</span>(nao) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb19-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_tsibble</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">index =</span> x)</span>
<span id="cb19-32"></span>
<span id="cb19-33">nao</span></code></pre></div></div>
<pre><code># A tsibble: 873 x 2 [1M]
          x   nao
      &lt;mth&gt; &lt;dbl&gt;
 1 1950 Jan -0.16
 2 1950 Feb  0.25
 3 1950 Mar -1.44
 4 1950 Apr  1.46
 5 1950 May  1.34
 6 1950 Jun -3.94
 7 1950 Jul -2.75
 8 1950 Aug -0.08
 9 1950 Sep  0.19
10 1950 Oct  0.19
# … with 863 more rows</code></pre>
<p>Like before, we start with the spectrum:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1">fft <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_fft_fft</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(nao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>nao)))</span>
<span id="cb21-2"></span>
<span id="cb21-3">num_samples <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(nao)</span>
<span id="cb21-4">nyquist_cutoff <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ceiling</span>(num_samples <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb21-5">bins_below_nyquist <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>nyquist_cutoff</span>
<span id="cb21-6"></span>
<span id="cb21-7">sampling_rate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> </span>
<span id="cb21-8">frequencies_per_bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sampling_rate <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> num_samples</span>
<span id="cb21-9">frequencies <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> frequencies_per_bin <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> bins_below_nyquist</span>
<span id="cb21-10"></span>
<span id="cb21-11">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">f =</span> frequencies, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(fft[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(nyquist_cutoff <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>()))</span>
<span id="cb21-12">df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(f, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"frequency (per year)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ylab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magnitude"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb21-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggtitle</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Spectrum of NAO data"</span>)</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="spectrum-nao.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-4" title="Spectrum of NAO data, 1950 to present."><img src="https://divergences.xyz/posts/torchwavelets/spectrum-nao.png" class="img-fluid figure-img column-body-outset-right" alt="Spectrum of NAO data, 1950 to present."></a></p>
<figcaption>Spectrum of NAO data, 1950 to present.</figcaption>
</figure>
</div>
</div>
<p>Have you been wondering for a tiny moment whether this was time-domain data – not spectral? It does look a lot more noisy than the ENSO spectrum for sure. And really, with NAO, predictability is much worse - forecast lead time usually amounts to just <a href="https://www.cpc.ncep.noaa.gov/products/precip/CWlink/pna/nao_index_mrf.shtml">one or two weeks</a>.</p>
<p>Proceeding as before, we pick dominant seasonalities (at least this still is possible!) to pass to <code>feasts::STL()</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1">strongest <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_topk</span>(fft[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(nyquist_cutoff<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span>
<span id="cb22-2">strongest</span></code></pre></div></div>
<pre><code>[[1]]
torch_tensor
102.7191
80.5129
76.1179
75.9949
72.9086
60.8281
[ CPUFloatType{6} ]

[[2]]
torch_tensor
147
99
146
59
33
78
[ CPULongType{6} ]</code></pre>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb24-1">important_freqs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> frequencies[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(strongest[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]])]</span>
<span id="cb24-2">important_freqs</span></code></pre></div></div>
<pre><code>[1] 2.0068729 1.3470790 1.9931271 0.7972509 0.4398625 1.0584192</code></pre>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1">num_observations_in_season <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>important_freqs  </span>
<span id="cb26-2">num_observations_in_season</span></code></pre></div></div>
<pre><code>[1]  5.979452  8.908163  6.020690 15.051724 27.281250 11.337662</code></pre>
<p>Important seasonal periods are of length six, nine, eleven, fifteen, and twenty-seven months, approximately - pretty close together indeed! No wonder that, in STL decomposition, the remainder is even more significant than with ENSO:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb28-1">nao <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb28-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">STL</span>(nao <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb28-3">              <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">27</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb28-4">              <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb28-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">components</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb28-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">autoplot</span>()</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="stl-nao.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-5" title="Decomposition of NAO data into trend, seasonal components, and remainder by feasts::STL()."><img src="https://divergences.xyz/posts/torchwavelets/stl-nao.png" class="img-fluid figure-img column-body-outset-right" alt="Decomposition of NAO data into trend, seasonal components, and remainder by feasts::STL()."></a></p>
<figcaption>Decomposition of NAO data into trend, seasonal components, and remainder by <code>feasts::STL()</code>.</figcaption>
</figure>
</div>
</div>
<p>Now, what will we see in terms of temporal evolution? Much of the code that follows is the same as for ENSO, repeated here for the reader’s convenience:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb29-1">nao_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> nao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>nao <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tensor</span>()</span>
<span id="cb29-2">dt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same interval as for ENSO</span></span>
<span id="cb29-3">wtf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wavelet_transform</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(nao_idx), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dt =</span> dt)</span>
<span id="cb29-4">power_spectrum <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">power</span>(nao_idx)</span>
<span id="cb29-5"></span>
<span id="cb29-6">times <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lubridate<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">year</span>(nao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lubridate<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">month</span>(nao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># also same</span></span>
<span id="cb29-7">scales <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scales) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># will be same because both series have same length</span></span>
<span id="cb29-8"></span>
<span id="cb29-9">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_tibble</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(power_spectrum<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>()), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.name_repair =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"universal"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb29-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">time =</span> times) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb29-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>time, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb29-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> scales[scale <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb29-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_remove</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.]{3}"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb29-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>()])</span>
<span id="cb29-15"></span>
<span id="cb29-16">coi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coi</span>(times[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], times[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(nao_idx)])</span>
<span id="cb29-17">coi_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(coi[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(coi[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]))</span>
<span id="cb29-18"></span>
<span id="cb29-19">labeled_scales <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same since scales are same </span></span>
<span id="cb29-20">labeled_frequencies <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fourier_period</span>(labeled_scales)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb29-21"></span>
<span id="cb29-22"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(df) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(</span>
<span id="cb29-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trans =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose_trans</span>(scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2_trans</span>(), scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reverse_trans</span>()),</span>
<span id="cb29-25">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>),</span>
<span id="cb29-26">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(scales), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(scales)),</span>
<span id="cb29-27">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expand =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>),</span>
<span id="cb29-28">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sec.axis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dup_axis</span>(</span>
<span id="cb29-29">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">label_number</span>(labeled_frequencies),</span>
<span id="cb29-30">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fourier period (years)"</span></span>
<span id="cb29-31">    )</span>
<span id="cb29-32">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-33">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ylab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale (years)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-34">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1950</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2020</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expand =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-35">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"year"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-36">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_contour_filled</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(time, scale, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">z =</span> power), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-37">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_viridis_d</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"turbo"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-38">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_ribbon</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> coi_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymin =</span> y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymax =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(scales)),</span>
<span id="cb29-39">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb29-40">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>)</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="scaleogram-nao.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-6" title="Scaleogram of NAO data."><img src="https://divergences.xyz/posts/torchwavelets/scaleogram-nao.png" class="img-fluid figure-img column-body-outset-right" alt="Scaleogram of NAO data."></a></p>
<figcaption>Scaleogram of NAO data.</figcaption>
</figure>
</div>
</div>
<p>That, literally, is a much more colorful picture than with ENSO! High frequencies are present, and continually dominant, over the whole time period.</p>
<p>Interestingly, though, we see similarities to ENSO, as well: In both, there is an important pattern, of periodicity four or slightly more years, that exerces influence during the eighties, nineties, and early two-thousands – only with ENSO, it shows peak impact during the nineties, while with NAO, its dominance is most visible in the first decade of this century. Also, both phenomena exhibit a strongly visible peak, of period two years, around 1970. So, is there a close(-ish) connection between both oscillations? This question, of course, is for the domain experts to answer. At least I found a recent study (<span class="citation" data-cites="scaife2014skillful">Scaife et al. (2014)</span>) that not only suggests there is, but uses one (ENSO, the more predictable one) to inform forecasts of the other:</p>
<div class="no-row-height column-margin column-container"><div id="ref-scaife2014skillful" class="csl-entry">
Scaife, A. A., Alberto Arribas Herranz, E. Blockley, et al. 2014. <span>“Skillful Long-Range Prediction of European and North American Winters.”</span> <em>Geophysical Research Letters</em> 41 (7): 2514–19. <a href="https://www.microsoft.com/en-us/research/publication/skillful-long-range-prediction-of-european-and-north-american-winters/">https://www.microsoft.com/en-us/research/publication/skillful-long-range-prediction-of-european-and-north-american-winters/</a>.
</div></div><blockquote class="blockquote">
<p>Previous studies have shown that the El Niño–Southern Oscillation can drive interannual variations in the NAO [Brönnimann et al., 2007] and hence Atlantic and European winter climate via the stratosphere [Bell et al., 2009]. […] this teleconnection to the tropical Paciﬁc is active in our experiments, with forecasts initialized in El Niño/La Niña conditions in November tending to be followed by negative/positive NAO conditions in winter.</p>
</blockquote>
<p>Will we see a similar relationship for AO, our third series under investigation? We might expect so, since AO and NAO are closely related (or even, two sides of the same coin).</p>
</section>
<section id="analysis-ao" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="analysis-ao">Analysis: AO</h2>
<p>First, the data:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb30-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">download.file</span>(</span>
<span id="cb30-2"> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.cpc.ncep.noaa.gov/products/precip/CWlink/daily_ao_index/monthly.ao.index.b50.current.ascii.table"</span>,</span>
<span id="cb30-3"> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">destfile =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ao.dat"</span></span>
<span id="cb30-4">)</span>
<span id="cb30-5"></span>
<span id="cb30-6">ao <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb30-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_table</span>(</span>
<span id="cb30-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ao.dat"</span>,</span>
<span id="cb30-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col_names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb30-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">skip =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb30-11">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>X1) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb30-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-16">  .[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(use_months)] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> use_months,</span>
<span id="cb30-18">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ao =</span> .) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yearmonth</span>(x)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fill</span>(ao) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb30-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_tsibble</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">index =</span> x) </span>
<span id="cb30-22"></span>
<span id="cb30-23">ao</span></code></pre></div></div>
<pre><code># A tsibble: 873 x 2 [1M]
          x     ao
      &lt;mth&gt;  &lt;dbl&gt;
 1 1950 Jan -0.06 
 2 1950 Feb  0.627
 3 1950 Mar -0.008
 4 1950 Apr  0.555
 5 1950 May  0.072
 6 1950 Jun  0.539
 7 1950 Jul -0.802
 8 1950 Aug -0.851
 9 1950 Sep  0.358
10 1950 Oct -0.379
# … with 863 more rows</code></pre>
<p>And the spectrum:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb32-1">fft <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_fft_fft</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(ao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ao)))</span>
<span id="cb32-2"></span>
<span id="cb32-3">num_samples <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(ao)</span>
<span id="cb32-4">nyquist_cutoff <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ceiling</span>(num_samples <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb32-5">bins_below_nyquist <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>nyquist_cutoff</span>
<span id="cb32-6"></span>
<span id="cb32-7">sampling_rate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># per year</span></span>
<span id="cb32-8">frequencies_per_bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sampling_rate <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> num_samples</span>
<span id="cb32-9">frequencies <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> frequencies_per_bin <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> bins_below_nyquist</span>
<span id="cb32-10"></span>
<span id="cb32-11">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">f =</span> frequencies, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(fft[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(nyquist_cutoff <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>()))</span>
<span id="cb32-12">df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(f, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb32-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb32-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"frequency (per year)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb32-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ylab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magnitude"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb32-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggtitle</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Spectrum of AO data"</span>)</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="spectrum-ao.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-7" title="Spectrum of AO data, 1950 to present."><img src="https://divergences.xyz/posts/torchwavelets/spectrum-ao.png" class="img-fluid figure-img column-body-outset-right" alt="Spectrum of AO data, 1950 to present."></a></p>
<figcaption>Spectrum of AO data, 1950 to present.</figcaption>
</figure>
</div>
</div>
<p>Well, this spectrum looks even more random than NAO’s, in that not even a single frequency stands out. For completeness, here is the STL decomposition:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb33-1">strongest <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_topk</span>(fft[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(nyquist_cutoff<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb33-2"></span>
<span id="cb33-3">important_freqs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> frequencies[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(strongest[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]])]</span>
<span id="cb33-4">important_freqs</span>
<span id="cb33-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [1] 0.01374570 0.35738832 1.77319588 1.27835052 0.06872852</span></span>
<span id="cb33-6"></span>
<span id="cb33-7">num_observations_in_season <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>important_freqs  </span>
<span id="cb33-8">num_observations_in_season</span>
<span id="cb33-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [1] 873.000000  33.576923   6.767442   9.387097 174.600000 </span></span>
<span id="cb33-10"></span>
<span id="cb33-11">ao <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb33-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">STL</span>(ao <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">33</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb33-13">              <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">season</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">period =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">174</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb33-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">components</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb33-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">autoplot</span>()</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="stl-ao.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-8" title="Decomposition of AO data into trend, seasonal components, and remainder by feasts::STL()."><img src="https://divergences.xyz/posts/torchwavelets/stl-ao.png" class="img-fluid figure-img column-body-outset-right" alt="Decomposition of AO data into trend, seasonal components, and remainder by feasts::STL()."></a></p>
<figcaption>Decomposition of AO data into trend, seasonal components, and remainder by feasts::STL().</figcaption>
</figure>
</div>
</div>
<p>Finally, what can the scaleogram tell us about dominant patterns?</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1">ao_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ao <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tensor</span>()</span>
<span id="cb34-2">dt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same interval as for ENSO and NAO</span></span>
<span id="cb34-3">wtf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wavelet_transform</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(ao_idx), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dt =</span> dt)</span>
<span id="cb34-4">power_spectrum <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">power</span>(ao_idx)</span>
<span id="cb34-5"></span>
<span id="cb34-6">times <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lubridate<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">year</span>(ao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lubridate<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">month</span>(ao<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># also same</span></span>
<span id="cb34-7">scales <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scales) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># will be same because all series have same length</span></span>
<span id="cb34-8"></span>
<span id="cb34-9">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_tibble</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(power_spectrum<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>()), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.name_repair =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"universal"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb34-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">time =</span> times) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb34-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>time, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb34-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> scales[scale <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb34-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_remove</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.]{3}"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb34-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>()])</span>
<span id="cb34-15"></span>
<span id="cb34-16">coi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coi</span>(times[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], times[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(ao_idx)])</span>
<span id="cb34-17">coi_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(coi[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(coi[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]))</span>
<span id="cb34-18"></span>
<span id="cb34-19">labeled_scales <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same since scales are same </span></span>
<span id="cb34-20">labeled_frequencies <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(wtf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fourier_period</span>(labeled_scales)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb34-21"></span>
<span id="cb34-22"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(df) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(</span>
<span id="cb34-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trans =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose_trans</span>(scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2_trans</span>(), scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reverse_trans</span>()),</span>
<span id="cb34-25">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>),</span>
<span id="cb34-26">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(scales), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(scales)),</span>
<span id="cb34-27">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expand =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>),</span>
<span id="cb34-28">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sec.axis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dup_axis</span>(</span>
<span id="cb34-29">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">label_number</span>(labeled_frequencies),</span>
<span id="cb34-30">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fourier period (years)"</span></span>
<span id="cb34-31">    )</span>
<span id="cb34-32">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-33">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ylab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale (years)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-34">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1950</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2020</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expand =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-35">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xlab</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"year"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-36">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_contour_filled</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(time, scale, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">z =</span> power), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-37">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_viridis_d</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"turbo"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-38">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_ribbon</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> coi_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymin =</span> y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymax =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(scales)),</span>
<span id="cb34-39">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb34-40">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>)</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="scaleogram-ao.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-9" title="Scaleogram of AO data."><img src="https://divergences.xyz/posts/torchwavelets/scaleogram-ao.png" class="img-fluid figure-img column-body-outset-right" alt="Scaleogram of AO data."></a></p>
<figcaption>Scaleogram of AO data.</figcaption>
</figure>
</div>
</div>
<p>Having seen the overall spectrum, the lack of strongly dominant patterns in the scaleogram does not come as a big surprise. It is tempting – for me, at least – to see a reflection of ENSO around 1970, all the more since by transitivity, AO and ENSO should be related in some way. But here, qualified judgment really is reserved to the experts.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Like I said in the beginning, this post would be about inspiration, not technical detail or reportable results. And I hope that inspirational it has been, at least a little bit. If you’re experimenting with wavelets yourself, or plan to – or if you work in the atmospheric sciences, and would like to provide some insight on the above data/phenomena – we’d love to hear from you!</p>
<p>As always, thanks for reading!</p>
<div class="photo-credit">
<p>Photo by <a href="https://unsplash.com/@actionvance?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">ActionVance</a> on <a href="https://unsplash.com/images/nature/earth?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
</div>



</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Deep Learning</category>
  <category>Climate &amp; Weather</category>
  <guid>https://divergences.xyz/posts/torchwavelets/</guid>
  <pubDate>Thu, 19 Jan 2023 00:00:00 GMT</pubDate>
  <media:content url="https://divergences.xyz/posts/torchwavelets/preview.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Forecasting El Niño-Southern Oscillation (ENSO)</title>
  <dc:creator>Sigrid Keydana</dc:creator>
  <link>https://divergences.xyz/posts/enso-prediction/</link>
  <description><![CDATA[ 






<p>Today, we use the convLSTM introduced in a <a href="https://blogs.rstudio.com/ai/posts/2020-12-17-torch-convlstm/">previous</a> post to predict <a href="https://en.wikipedia.org/wiki/El_Ni%C3%B1o%E2%80%93Southern_Oscillation">El Niño-Southern Oscillation (ENSO).</a></p>
<section id="el-niño-la-niña" class="level1 page-columns page-full">
<h1>El Niño, la Niña</h1>
<p>ENSO refers to a changing pattern of sea surface temperatures and sea-level pressures occurring in the equatorial Pacific. From its three overall states, probably the best-known is El Niño. El Niño occurs when surface water temperatures in the eastern Pacific are higher than normal, and the strong winds that normally blow from east to west are unusually weak. The opposite conditions are termed La Niña. Everything in-between is classified as normal.</p>
<p>ENSO has great impact on the weather worldwide, and routinely harms ecosystems and societies through storms, droughts and flooding, possibly resulting in famines and economic crises. The best societies can do is try to adapt and mitigate severe consequences. Such efforts are aided by accurate forecasts, the further ahead the better.</p>
<p>Here, deep learning (DL) can potentially help: Variables like sea surface temperatures and pressures are given on a spatial grid – that of the earth – and as we know, DL is good at extracting spatial (e.g., image) features. For ENSO prediction, architectures like convolutional neural networks (<span class="citation" data-cites="dlenso">Ham et al. (2019)</span>) or convolutional-recurrent hybrids<sup>1</sup> are habitually used. One such hybrid is just our convLSTM; it operates on sequences of features given on a spatial grid. Today, thus, we’ll be training a model for ENSO forecasting. This model will have a convLSTM for its central ingredient.</p>
<div class="no-row-height column-margin column-container"><div id="fn1"><p><sup>1</sup>&nbsp;E.g., <a href="https://www.climatechange.ai/papers/neurips2019/40/paper.pdf">Forecasting El Niño with Convolutional and Recurrent Neural Networks</a>.</p></div><div id="fn2"><p><sup>2</sup>&nbsp;E.g., <a href="https://esgf-node.llnl.gov/projects/cmip5/">CMIP5</a>, <a href="http://www.umr-cnrm.fr/spip.php?article126&amp;lang=en">CNRM-CM5</a>, or <a href="https://southernocean.arizona.edu/content/hadgem2-es">HADGEM2-ES</a>.</p></div></div><p>Before we start, a note. While our model fits well with architectures described in the relevant papers, the same cannot be said for amount of training data used. For reasons of practicality, we use actual observations only; consequently, we end up with a small (relative to the task) dataset. In contrast, research papers tend to make use of climate simulations<sup>2</sup>, resulting in significantly more data to work with.</p>
<p>From the outset, then, we don’t expect stellar performance. Nevertheless, this should make for an interesting case study, and a useful code template for our readers to apply to their own data.</p>
</section>
<section id="data" class="level1 page-columns page-full">
<h1>Data</h1>
<p>We will attempt to predict monthly average sea surface temperature in the Niño 3.4 region<sup>3</sup>, as represented by the Niño 3.4 Index, plus categorization as one of <em>El Niño</em>, <em>La Niña</em> or <em>neutral</em><sup>4</sup>. Predictions will be based on prior monthly sea surface temperatures spanning a large portion of the globe.</p>
<div class="no-row-height column-margin column-container"><div id="fn3"><p><sup>3</sup>&nbsp;This region extends over latitudes from 5° south to 5° north and longitudes from 120° west to 170° west.</p></div><div id="fn4"><p><sup>4</sup>&nbsp;That classification is based on ONI (Oceanic Niño Index), a measure representing 3-month average anomalies in the Niño 3.4 Index.</p></div></div><p>On the input side, public and ready-to-use data may be downloaded from <a href="https://ds.data.jma.go.jp/tcc/tcc/index.html">Tokyo Climate Center</a>; as to prediction targets, we obtain index and classification <a href="https://bmcnoldy.rsmas.miami.edu/tropics/oni/">here</a>.</p>
<p>Input and target data both are provided monthly. They intersect in the time period ranging from 1891-01-01 to 2020-08-01; so this is the range of dates we’ll be zooming in on.</p>
<section id="input-sea-surface-temperatures" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="input-sea-surface-temperatures">Input: Sea Surface Temperatures</h2>
<p>Monthly sea surface temperatures are provided in a latitude-longitude grid of resolution 1°. Details of how the data were processed are available <a href="https://ds.data.jma.go.jp/tcc/tcc/library/MRCS_SV12/explanation/cobe_sst_e.htm">here</a>.</p>
<p>Data files are available in <a href="https://en.wikipedia.org/wiki/GRIB">GRIB</a> format; each file contains averages computed for a single month. We can either download individual files or <a href="https://ds.data.jma.go.jp/tcc/tcc/products/elnino/cobesst/cobe-sst.html">generate a text file of URLs</a> for download. Once you’ve saved these URLs to a file, you can have R get the files for you like so:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1">purrr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">walk</span>(</span>
<span id="cb1-2">   <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">readLines</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files"</span>),</span>
<span id="cb1-3">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(f) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">download.file</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">url =</span> f, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">destfile =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">basename</span>(f))</span>
<span id="cb1-4">)</span></code></pre></div></div>
<p>From R, we can read GRIB files using <a href="https://cran.r-project.org/web/packages/stars/">stars</a>. For example:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># let's just quickly load all libraries we require to start with</span></span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torch)</span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(stars)</span>
<span id="cb2-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(viridis)</span>
<span id="cb2-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggthemes)</span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_manual_seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">777</span>)</span>
<span id="cb2-10"></span>
<span id="cb2-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_stars</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file.path</span>(grb_dir, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sst189101.grb"</span>))</span></code></pre></div></div>
<pre><code>stars object with 2 dimensions and 1 attribute
attribute(s):
 sst189101.grb   
 Min.   :-274.9  
 1st Qu.:-272.8  
 Median :-259.1  
 Mean   :-260.0  
 3rd Qu.:-248.4  
 Max.   :-242.8  
 NA's   :21001   
dimension(s):
  from  to offset delta                       refsys point values    
x    1 360      0     1 Coordinate System importe...    NA   NULL [x]
y    1 180     90    -1 Coordinate System importe...    NA   NULL [y]</code></pre>
<p>So in this GRIB file, we have one attribute - which we know to be sea surface temperature – on a two-dimensional grid. As to the latter, we can complement what <code>stars</code> tells us with additional info found in the <a href="https://ds.data.jma.go.jp/tcc/tcc/library/MRCS_SV12/explanation/cobe_sst_e.htm">documentation</a>:</p>
<blockquote class="blockquote">
<p>The east-west grid points run eastward from 0.5ºE to 0.5ºW, while the north-south grid points run northward from 89.5ºS to 89.5ºN.</p>
</blockquote>
<p>We note a few things we’ll want to do with this data. For one, the temperatures seem to be given in Kelvin, but with minus signs.<sup>5</sup> We’ll remove the minus signs and convert to degrees Celsius for convenience. We’ll also have to think about what to do with the <code>NA</code>s that appear for all non-maritime coordinates.</p>
<div class="no-row-height column-margin column-container"><div id="fn5"><p><sup>5</sup>&nbsp;This may also be an artifact produced by the software stack involved in reading the file.</p></div></div><p>Before we get there though, we need to combine data from all files into a single data frame. This adds an additional dimension, time, ranging from 1891/01/01 to 2020/01/12:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">grb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_stars</span>(</span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file.path</span>(grb_dir, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">readLines</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">warn =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>), basename)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">along =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"time"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb4-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_set_dimensions</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb4-4">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1891-01-01"</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2020-12-01"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"months"</span>),</span>
<span id="cb4-5">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"time"</span></span>
<span id="cb4-6">                    )</span>
<span id="cb4-7"></span>
<span id="cb4-8">grb</span></code></pre></div></div>
<pre><code>stars object with 3 dimensions and 1 attribute
attribute(s), summary of first 1e+05 cells:
 sst189101.grb   
 Min.   :-274.9  
 1st Qu.:-273.3  
 Median :-258.8  
 Mean   :-260.0  
 3rd Qu.:-247.8  
 Max.   :-242.8  
 NA's   :33724   
dimension(s):
     from   to offset delta                       refsys point                    values    
x       1  360      0     1 Coordinate System importe...    NA                      NULL [x]
y       1  180     90    -1 Coordinate System importe...    NA                      NULL [y]
time    1 1560     NA    NA                         Date    NA 1891-01-01,...,2020-12-01    </code></pre>
<p>Let’s visually inspect the spatial distribution of monthly temperatures for one year, 2020:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_stars</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> grb <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">between</span>(time, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2020-01-01"</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2020-12-01"</span>))), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"time"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_viridis</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_equal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_map</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) </span></code></pre></div></div>
<p><a href="enso.png" class="lightbox" data-gallery="quarto-lightbox-gallery-1"><img src="https://divergences.xyz/posts/enso-prediction/enso.png" class="img-fluid" alt="Monthly sea surface temperatures, 2020/01/01 - 2020/01/12."></a></p>
</section>
<section id="target-niño-3.4-index" class="level2">
<h2 class="anchored" data-anchor-id="target-niño-3.4-index">Target: Niño 3.4 Index</h2>
<p>For the Niño 3.4 Index, we download the monthly <a href="https://bmcnoldy.rsmas.miami.edu/tropics/oni/ONI_NINO34_1854-2020.txt">data</a> and, among the provided features, zoom in on two: the index itself (column <code>NINO34_MEAN</code>) and <code>PHASE</code>, which can be <code>E</code> (El Niño), <code>L</code> (La Niño) or <code>N</code> (neutral).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_table2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ONI_NINO34_1854-2020.txt"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">skip =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb7-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">month =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(YEAR, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MON/MMM</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-01"</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb7-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(month, NINO34_MEAN, PHASE) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb7-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">between</span>(month, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1891-01-01"</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2020-08-01"</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb7-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phase_code =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.factor</span>(PHASE)))</span>
<span id="cb7-6"></span>
<span id="cb7-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(nino)</span></code></pre></div></div>
<pre><code>1556</code></pre>
<p>Next, we look at how to get the data into a format convenient for training and prediction.</p>
</section>
</section>
<section id="preprocessing" class="level1 page-columns page-full">
<h1>Preprocessing</h1>
<section id="input" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="input">Input</h2>
<p>First, we remove all input data for points in time where ground truth data are still missing.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> grb <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2020-08-01"</span>))</span></code></pre></div></div>
<p>Next, as is done by e.g. <span class="citation" data-cites="dlenso">Ham et al. (2019)</span>, we only use grid points between 55° south and 60° north. This has the additional advantage of reducing memory requirements.</p>
<div class="no-row-height column-margin column-container"><div id="ref-dlenso" class="csl-entry">
Ham, Yoo-Geun, Jeong-Hwan Kim, and Jing-Jia Luo. 2019. <span>“<span class="nocase">Deep learning for multi-year ENSO forecasts</span>.”</span> 573 (7775): 568–72. <a href="https://doi.org/10.1038/s41586-019-1559-7">https://doi.org/10.1038/s41586-019-1559-7</a>.
</div></div><div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> grb <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">between</span>(y,<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">55</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>))</span>
<span id="cb10-2"></span>
<span id="cb10-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(sst)</span></code></pre></div></div>
<pre><code>360, 115, 1560</code></pre>
<p>As already alluded to, with the little data we have we can’t expect much in terms of generalization. Still, we set aside a small portion of the data for validation, since we’d like for this post to serve as a useful template to be used with bigger datasets.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">sst_train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sst <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1990-01-01"</span>))</span>
<span id="cb12-2">sst_valid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sst <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(time <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1990-01-01"</span>))</span></code></pre></div></div>
<p>From here on, we work with R arrays.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">sst_train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.tbl_cube.stars</span>(sst_train)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mets[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb13-2">sst_valid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.tbl_cube.stars</span>(sst_valid)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mets[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span></code></pre></div></div>
<p>Conversion to degrees Celsius is not strictly necessary, as initial experiments showed a slight performance increase due to normalizing the input, and we’re going to do that anyway. Still, it reads nicer to humans than Kelvin.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">sst_train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sst_train <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">273.15</span></span>
<span id="cb14-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(sst_train, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
<pre><code>     0%     25%     50%     75%    100% 
-1.8000 12.9975 21.8775 26.8200 34.3700 </code></pre>
<p>Not at all surprisingly, global warming is evident from inspecting temperature distribution on the validation set (which was chosen to span the last thirty-one years).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">sst_valid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sst_valid <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">273.15</span></span>
<span id="cb16-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(sst_valid, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
<pre><code>    0%    25%    50%    75%   100% 
-1.800 13.425 22.335 27.240 34.870 </code></pre>
<p>The next-to-last step normalizes both sets according to training mean and variance.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">train_mean <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(sst_train, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb18-2">train_sd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</span>(sst_train, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb18-3"></span>
<span id="cb18-4">sst_train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (sst_train <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> train_mean) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> train_sd</span>
<span id="cb18-5"></span>
<span id="cb18-6">sst_valid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (sst_valid <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> train_mean) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> train_sd</span></code></pre></div></div>
<p>Finally, what should we do about the <code>NA</code> entries? We set them to zero, the (training set) mean. That may not be enough of an action though: It means we’re feeding the network roughly 30% misleading data. This is something we’re not done with yet.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1">sst_train[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(sst_train)] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb19-2">sst_valid[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(sst_valid)] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span></code></pre></div></div>
</section>
<section id="target" class="level2">
<h2 class="anchored" data-anchor-id="target">Target</h2>
<p>The target data are split analogously. Let’s check though: Are phases (categorizations) distributedly similarly in both sets?</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1">nino_train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> nino <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(month <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1990-01-01"</span>))</span>
<span id="cb20-2">nino_valid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> nino <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(month <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1990-01-01"</span>))</span>
<span id="cb20-3"></span>
<span id="cb20-4">nino_train <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(phase_code, PHASE) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">count =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">avg =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(NINO34_MEAN))</span></code></pre></div></div>
<pre><code># A tibble: 3 x 4
# Groups:   phase_code [3]
  phase_code PHASE count   avg
       &lt;dbl&gt; &lt;chr&gt; &lt;int&gt; &lt;dbl&gt;
1          1 E       301  27.7
2          2 L       333  25.6
3          3 N       554  26.7</code></pre>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1">nino_valid <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(phase_code, PHASE) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">count =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">avg =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(NINO34_MEAN))</span></code></pre></div></div>
<pre><code># A tibble: 3 x 4
# Groups:   phase_code [3]
  phase_code PHASE count   avg
       &lt;dbl&gt; &lt;chr&gt; &lt;int&gt; &lt;dbl&gt;
1          1 E        93  28.1
2          2 L        93  25.9
3          3 N       182  27.2</code></pre>
<p>This doesn’t look too bad. Of course, we again see the overall rise in temperature, irrespective of phase.</p>
<p>Lastly, we normalize the index, same as we did for the input data.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb24-1">train_mean_nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(nino_train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>NINO34_MEAN)</span>
<span id="cb24-2">train_sd_nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</span>(nino_train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>NINO34_MEAN)</span>
<span id="cb24-3"></span>
<span id="cb24-4">nino_train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> nino_train <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">NINO34_MEAN =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(NINO34_MEAN, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">center =</span> train_mean_nino, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> train_sd_nino))</span>
<span id="cb24-5">nino_valid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> nino_valid <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">NINO34_MEAN =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(NINO34_MEAN, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">center =</span> train_mean_nino, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> train_sd_nino))</span></code></pre></div></div>
<p>On to the <code>torch</code> dataset.</p>
</section>
</section>
<section id="torch-dataset" class="level1">
<h1><code>Torch</code> dataset</h1>
<p>The dataset is responsible for correctly matching up inputs and targets.</p>
<p>Our goal is to take six months of global sea surface temperatures and predict the Niño 3.4 Index for the following month. Input-wise, the model will expect the following format semantics:</p>
<p><code>batch_size * timesteps * width * height * channels</code>, where</p>
<ul>
<li><p><code>batch_size</code> is the number of observations worked on in one round of computations,</p></li>
<li><p><code>timesteps</code> chains consecutive observations from adjacent months,</p></li>
<li><p><code>width</code> and <code>height</code> together constitute the spatial grid, and</p></li>
<li><p><code>channels</code> corresponds to available visual channels in the “image”.</p></li>
</ul>
<p>In <code>.getitem()</code>, we select the consecutive observations, starting at a given index, and stack them in dimension one. (One, not two, as batches will only start to exist once the <code>dataloader</code> comes into play.)</p>
<p>Now, what about the target? Our ultimate goal was – is – predicting the Niño 3.4 Index. However, as you see we define three targets: One is the index, as expected; an additional one holds the spatially-gridded sea surface temperatures for the prediction month. Why? Our main instrument, the most prominent constituent of the model, will be a convLSTM, an architecture designed for <em>spatial</em> prediction. Thus, to train it efficiently, we want to give it the opportunity to predict values on a spatial grid. So far so good; but there’s one more target, the phase/category. This was added for experimentation purposes: Maybe predicting <em>both</em> index <em>and</em> phase helps in training?</p>
<p>Finally, here is the code for the dataset. In our experiments, we based predictions on inputs from the preceding six months (<code>n_timesteps &lt;- 6</code>). This is a parameter you might want to play with, though.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1">n_timesteps <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span></span>
<span id="cb25-2"></span>
<span id="cb25-3">enso_dataset <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dataset</span>(</span>
<span id="cb25-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"enso_dataset"</span>,</span>
<span id="cb25-5">  </span>
<span id="cb25-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">initialize =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(sst, nino, n_timesteps) {</span>
<span id="cb25-7">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sst</span>
<span id="cb25-8">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> nino</span>
<span id="cb25-9">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_timesteps <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_timesteps</span>
<span id="cb25-10">  },</span>
<span id="cb25-11">  </span>
<span id="cb25-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.getitem =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i) {</span>
<span id="cb25-13">    x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tensor</span>(self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sst[, , i<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(n_timesteps <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)]) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (360, 115, n_timesteps)</span></span>
<span id="cb25-14">    x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">permute</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unsqueeze</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (n_timesteps, 1, 360, 115))</span></span>
<span id="cb25-15">    </span>
<span id="cb25-16">    y1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tensor</span>(self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sst[, , n_timesteps <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i])<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unsqueeze</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (1, 360, 115)</span></span>
<span id="cb25-17">    y2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tensor</span>(self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>nino<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>NINO34_MEAN[n_timesteps <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i])</span>
<span id="cb25-18">    y3 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tensor</span>(self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>nino<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>phase_code[n_timesteps <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i])<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">squeeze</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_long</span>())</span>
<span id="cb25-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y1 =</span> y1, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y2 =</span> y2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y3 =</span> y3)</span>
<span id="cb25-20">  },</span>
<span id="cb25-21">  </span>
<span id="cb25-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.length =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>() {</span>
<span id="cb25-23">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>nino) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n_timesteps</span>
<span id="cb25-24">  }</span>
<span id="cb25-25">  </span>
<span id="cb25-26">)</span>
<span id="cb25-27"></span>
<span id="cb25-28">valid_ds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enso_dataset</span>(sst_valid, nino_valid, n_timesteps)</span></code></pre></div></div>
</section>
<section id="dataloaders" class="level1">
<h1>Dataloaders</h1>
<p>After the custom dataset, we create the – pretty typical – <code>dataloader</code>s, making use of a batch size of 4.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1">batch_size <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb26-2"></span>
<span id="cb26-3">train_dl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> train_ds <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dataloader</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_size =</span> batch_size, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shuffle =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb26-4"></span>
<span id="cb26-5">valid_dl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> valid_ds <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dataloader</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_size =</span> batch_size)</span></code></pre></div></div>
<p>Next, we proceed to model creation.</p>
</section>
<section id="model" class="level1">
<h1>Model</h1>
<p>The model’s main ingredient is the convLSTM introduced in a <a href="https://blogs.rstudio.com/ai/posts/2020-12-17-torch-convlstm/">prior post</a>. For convenience, we reproduce the code in the appendix.</p>
<p>Besides the convLSTM, the model makes use of three convolutional layers, a batchnorm layer and five linear layers. The logic is the following.</p>
<p>First, the convLSTM job is to predict the next month’s sea surface temperatures on the spatial grid. For that, we <em>almost</em> just return its final state, - almost: We use <code>self$conv1</code> to reduce the number channels to one.</p>
<p>For predicting index and phase, we then need to flatten the grid, as we require a single value each. This is where the additional conv layers come in. We <em>do</em> hope they’ll aid in learning, but we also want to reduce the number of parameters a bit, downsizing the grid (<code>strides = 2</code> and <code>strides = 3</code>, resp.) a bit before the upcoming <code>torch_flatten()</code>.</p>
<p>Once we have a flat structure, learning is shared between the tasks of index and phase prediction (<code>self$linear</code>), until finally their paths split (<code>self$cont</code> and <code>self$cat</code>, resp.), and they return their separate outputs.</p>
<p>(The batchnorm? I’ll comment on that in the Discussion.)</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb27-1">model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_module</span>(</span>
<span id="cb27-2">  </span>
<span id="cb27-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">initialize =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(channels_in,</span>
<span id="cb27-4">                        convlstm_hidden,</span>
<span id="cb27-5">                        convlstm_kernel,</span>
<span id="cb27-6">                        convlstm_layers) {</span>
<span id="cb27-7">    </span>
<span id="cb27-8">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> convlstm_layers</span>
<span id="cb27-9">    </span>
<span id="cb27-10">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>convlstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">convlstm</span>(</span>
<span id="cb27-11">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_dim =</span> channels_in,</span>
<span id="cb27-12">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_dims =</span> convlstm_hidden,</span>
<span id="cb27-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_sizes =</span> convlstm_kernel,</span>
<span id="cb27-14">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_layers =</span> convlstm_layers</span>
<span id="cb27-15">    )</span>
<span id="cb27-16">    </span>
<span id="cb27-17">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb27-18">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_conv2d</span>(</span>
<span id="cb27-19">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>,</span>
<span id="cb27-20">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">out_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb27-21">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="cb27-22">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padding =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb27-23">      )</span>
<span id="cb27-24">    </span>
<span id="cb27-25">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb27-26">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_conv2d</span>(</span>
<span id="cb27-27">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>,</span>
<span id="cb27-28">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">out_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>,</span>
<span id="cb27-29">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="cb27-30">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stride =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb27-31">      )</span>
<span id="cb27-32">    </span>
<span id="cb27-33">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv3 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb27-34">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_conv2d</span>(</span>
<span id="cb27-35">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>,</span>
<span id="cb27-36">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">out_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>,</span>
<span id="cb27-37">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="cb27-38">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stride =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb27-39">      )</span>
<span id="cb27-40">    </span>
<span id="cb27-41">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>linear <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_linear</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">33408</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>)</span>
<span id="cb27-42">    </span>
<span id="cb27-43">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>b1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_batch_norm1d</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">num_features =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>)</span>
<span id="cb27-44">        </span>
<span id="cb27-45">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cont <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_linear</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)</span>
<span id="cb27-46">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_linear</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)</span>
<span id="cb27-47">    </span>
<span id="cb27-48">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cont_output <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_linear</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb27-49">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cat_output <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_linear</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb27-50">    </span>
<span id="cb27-51">  },</span>
<span id="cb27-52">  </span>
<span id="cb27-53">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">forward =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) {</span>
<span id="cb27-54">    </span>
<span id="cb27-55">    ret <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">convlstm</span>(x)</span>
<span id="cb27-56">    layer_last_states <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ret[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb27-57">    last_hidden <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> layer_last_states[[self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers]][[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb27-58">    </span>
<span id="cb27-59">    next_sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> last_hidden <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conv1</span>() </span>
<span id="cb27-60">    </span>
<span id="cb27-61">    c2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> last_hidden <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conv2</span>() </span>
<span id="cb27-62">    c3 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> c2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conv3</span>() </span>
<span id="cb27-63">    </span>
<span id="cb27-64">    flat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_flatten</span>(c3, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">start_dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb27-65">    common <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">linear</span>(flat) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">b3</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_relu</span>()</span>
<span id="cb27-66"></span>
<span id="cb27-67">    next_temp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> common <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cont</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_relu</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cont_output</span>()</span>
<span id="cb27-68">    next_nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> common <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_relu</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat_output</span>()</span>
<span id="cb27-69">    </span>
<span id="cb27-70">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(next_sst, next_temp, next_nino)</span>
<span id="cb27-71">    </span>
<span id="cb27-72">  }</span>
<span id="cb27-73">  </span>
<span id="cb27-74">)</span></code></pre></div></div>
<p>Next, we instantiate a pretty small-ish model. You’re more than welcome to experiment with larger models, but training time as well as GPU memory requirements will increase.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb28-1">net <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model</span>(</span>
<span id="cb28-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">channels_in =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb28-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">convlstm_hidden =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>),</span>
<span id="cb28-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">convlstm_kernel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>),</span>
<span id="cb28-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">convlstm_layers =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb28-6">)</span>
<span id="cb28-7"></span>
<span id="cb28-8">device <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_device</span>(<span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cuda_is_available</span>()) <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb28-9"></span>
<span id="cb28-10">net <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> net<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device)</span>
<span id="cb28-11">net</span></code></pre></div></div>
<pre><code>An `nn_module` containing 2,389,605 parameters.

── Modules ───────────────────────────────────────────────────────────────────────────────
● convlstm: &lt;nn_module&gt; #182,080 parameters
● conv1: &lt;nn_conv2d&gt; #801 parameters
● conv2: &lt;nn_conv2d&gt; #25,632 parameters
● conv3: &lt;nn_conv2d&gt; #25,632 parameters
● linear: &lt;nn_linear&gt; #2,138,176 parameters
● b1: &lt;nn_batch_norm1d&gt; #128 parameters
● cont: &lt;nn_linear&gt; #8,320 parameters
● cat: &lt;nn_linear&gt; #8,320 parameters
● cont_output: &lt;nn_linear&gt; #129 parameters
● cat_output: &lt;nn_linear&gt; #387 parameters</code></pre>
</section>
<section id="training" class="level1">
<h1>Training</h1>
<p>We have three model outputs. How should we combine the losses?</p>
<p>Given that the main goal is predicting the index, and the other two outputs are essentially means to an end, I found the following combination rather effective:</p>
<pre><code># weight for sea surface temperature prediction
lw_sst &lt;- 0.2

# weight for prediction of El Nino 3.4 Index
lw_temp &lt;- 0.4

# weight for phase prediction
lw_nino &lt;- 0.4</code></pre>
<p>The training process follows the pattern seen in all <code>torch</code> posts so far: For each epoch, loop over the training set, backpropagate, check performance on validation set.</p>
<p><em>But</em>, when we did the pre-processing, we were aware of an imminent problem: the missing temperatures for continental areas, which we set to zero. As a sole measure, this approach is clearly insufficient. What if we had chosen to use latitude-dependent averages? Or interpolation? Both may be better than a global average, but both have their problems as well. Let’s at least alleviate negative consequences by not using the respective pixels for spatial loss calculation. This is taken care of by the following line below:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb31-1">sst_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_mse_loss</span>(sst_output[sst_target <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], sst_target[sst_target <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span></code></pre></div></div>
<p>Here, then, is the complete training code.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb32-1"></span>
<span id="cb32-2">optimizer <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optim_adam</span>(net<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parameters, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lr =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb32-3"></span>
<span id="cb32-4">num_epochs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span>
<span id="cb32-5"></span>
<span id="cb32-6">train_batch <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(b) {</span>
<span id="cb32-7">  </span>
<span id="cb32-8">  optimizer<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zero_grad</span>()</span>
<span id="cb32-9">  output <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">net</span>(b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device))</span>
<span id="cb32-10">  </span>
<span id="cb32-11">  sst_output <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb32-12">  sst_target <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device)</span>
<span id="cb32-13">  </span>
<span id="cb32-14">  sst_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_mse_loss</span>(sst_output[sst_target <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], sst_target[sst_target <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb32-15">  temp_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_mse_loss</span>(output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]], b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device))</span>
<span id="cb32-16">  nino_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_cross_entropy</span>(output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]], b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device))</span>
<span id="cb32-17">  </span>
<span id="cb32-18">  loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lw_sst <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sst_loss <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lw_temp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> temp_loss <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lw_nino <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> nino_loss</span>
<span id="cb32-19">  loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">backward</span>()</span>
<span id="cb32-20">  optimizer<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">step</span>()</span>
<span id="cb32-21"></span>
<span id="cb32-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(sst_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>(), temp_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>(), nino_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>(), loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>())</span>
<span id="cb32-23">  </span>
<span id="cb32-24">}</span>
<span id="cb32-25"></span>
<span id="cb32-26">valid_batch <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(b) {</span>
<span id="cb32-27">  </span>
<span id="cb32-28">  output <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">net</span>(b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device))</span>
<span id="cb32-29">  </span>
<span id="cb32-30">  sst_output <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb32-31">  sst_target <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device)</span>
<span id="cb32-32">  </span>
<span id="cb32-33">  sst_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_mse_loss</span>(sst_output[sst_target <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], sst_target[sst_target <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb32-34">  temp_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_mse_loss</span>(output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]], b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device))</span>
<span id="cb32-35">  nino_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_cross_entropy</span>(output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]], b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device))</span>
<span id="cb32-36">  </span>
<span id="cb32-37">  loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb32-38">    lw_sst <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sst_loss <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lw_temp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> temp_loss <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lw_nino <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> nino_loss</span>
<span id="cb32-39"></span>
<span id="cb32-40">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(sst_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>(),</span>
<span id="cb32-41">       temp_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>(),</span>
<span id="cb32-42">       nino_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>(),</span>
<span id="cb32-43">       loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>())</span>
<span id="cb32-44">}</span>
<span id="cb32-45"></span>
<span id="cb32-46"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (epoch <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>num_epochs) {</span>
<span id="cb32-47">  </span>
<span id="cb32-48">  net<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">train</span>()</span>
<span id="cb32-49">  </span>
<span id="cb32-50">  train_loss_sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-51">  train_loss_temp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-52">  train_loss_nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-53">  train_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-54"></span>
<span id="cb32-55">  coro<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">loop</span>(<span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (b <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_dl) {</span>
<span id="cb32-56">    losses <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">train_batch</span>(b)</span>
<span id="cb32-57">    train_loss_sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(train_loss_sst, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="cb32-58">    train_loss_temp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(train_loss_temp, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]])</span>
<span id="cb32-59">    train_loss_nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(train_loss_nino, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]])</span>
<span id="cb32-60">    train_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(train_loss, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]])</span>
<span id="cb32-61">  })</span>
<span id="cb32-62">  </span>
<span id="cb32-63">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(</span>
<span id="cb32-64">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb32-65">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Epoch %d, training: loss: %3.3f sst: %3.3f temp: %3.3f nino: %3.3f </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>,</span>
<span id="cb32-66">      epoch, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(train_loss), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(train_loss_sst), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(train_loss_temp), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(train_loss_nino)</span>
<span id="cb32-67">    )</span>
<span id="cb32-68">  )</span>
<span id="cb32-69">  </span>
<span id="cb32-70">  net<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb32-71">  </span>
<span id="cb32-72">  valid_loss_sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-73">  valid_loss_temp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-74">  valid_loss_nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-75">  valid_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb32-76"></span>
<span id="cb32-77">  coro<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">loop</span>(<span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (b <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> valid_dl) {</span>
<span id="cb32-78">    losses <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">valid_batch</span>(b)</span>
<span id="cb32-79">    valid_loss_sst <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(valid_loss_sst, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="cb32-80">    valid_loss_temp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(valid_loss_temp, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]])</span>
<span id="cb32-81">    valid_loss_nino <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(valid_loss_nino, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]])</span>
<span id="cb32-82">    valid_loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(valid_loss, losses[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]])</span>
<span id="cb32-83">    </span>
<span id="cb32-84">  })</span>
<span id="cb32-85">  </span>
<span id="cb32-86">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(</span>
<span id="cb32-87">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb32-88">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Epoch %d, validation: loss: %3.3f sst: %3.3f temp: %3.3f nino: %3.3f </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>,</span>
<span id="cb32-89">      epoch, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(valid_loss), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(valid_loss_sst), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(valid_loss_temp), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(valid_loss_nino)</span>
<span id="cb32-90">    )</span>
<span id="cb32-91">  )</span>
<span id="cb32-92">  </span>
<span id="cb32-93">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_save</span>(net, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(</span>
<span id="cb32-94">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model_"</span>, epoch, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(train_loss), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(valid_loss), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".pt"</span></span>
<span id="cb32-95">  ))</span>
<span id="cb32-96">  </span>
<span id="cb32-97">}</span></code></pre></div></div>
<p>When I ran this, performance on the training set decreased in a not-too-fast, but continuous way, while validation set performance kept fluctuating. For reference, total (composite) losses looked like this:</p>
<pre><code>Epoch     Training    Validation
   
   10        0.336         0.633
   20        0.233         0.295
   30        0.135         0.461
   40        0.099         0.903
   50        0.061         0.727</code></pre>
<p>Thinking of the size of the validation set - thirty-one years, or equivalently, 372 data points – those fluctuations may not be all too surprising.</p>
</section>
<section id="predictions" class="level1 page-columns page-full">
<h1>Predictions</h1>
<p>Now losses tend to be abstract; let’s see what actually gets predicted. We obtain predictions for index values and phases like so …</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1">net<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb34-2"></span>
<span id="cb34-3">pred_index <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb34-4">pred_phase <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb34-5"></span>
<span id="cb34-6">coro<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">loop</span>(<span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (b <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> valid_dl) {</span>
<span id="cb34-7"></span>
<span id="cb34-8">  output <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">net</span>(b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> device))</span>
<span id="cb34-9"></span>
<span id="cb34-10">  pred_index <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(pred_index, output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>))</span>
<span id="cb34-11">  pred_phase <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(pred_phase, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(output[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)))</span>
<span id="cb34-12"></span>
<span id="cb34-13">})</span></code></pre></div></div>
<p>… and combine these with the ground truth, stripping off the first six rows (six was the number of timesteps used as predictors):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb35-1">valid_perf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb35-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">actual_temp =</span> nino_valid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>NINO34_MEAN[(batch_size <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(nino_valid)] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> train_sd_nino <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> train_mean_nino,</span>
<span id="cb35-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">actual_nino =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(nino_valid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>phase_code[(batch_size <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(nino_valid)]),</span>
<span id="cb35-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pred_temp =</span> pred_index <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> train_sd_nino <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> train_mean_nino,</span>
<span id="cb35-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pred_nino =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(pred_phase <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, which.max))</span>
<span id="cb35-6">)</span></code></pre></div></div>
<p>For the phase, we can generate a confusion matrix:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb36-1">yardstick<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conf_mat</span>(valid_perf, actual_nino, pred_nino)</span></code></pre></div></div>
<pre><code>          Truth
Prediction   1   2   3
         1  70   0  43
         2   0  47  10
         3  23  46 123</code></pre>
<p>This looks better than expected (based on the losses). Phases 1 and 2 correspond to El Niño and La Niña, respectively, and these get sharply separated.</p>
<p>What about the Niño 3.4 Index? Let’s plot predictions versus ground truth:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb38" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb38-1">valid_perf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> valid_perf <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb38-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">actual =</span> actual_temp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">predicted =</span> pred_temp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb38-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_column</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">month =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1990-07-01"</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.Date</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2020-08-01"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"months"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb38-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>month, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Index"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"temperature"</span>)</span>
<span id="cb38-5"></span>
<span id="cb38-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(valid_perf, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> month, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> temperature, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> Index)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb38-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb38-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#006D6F"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#B2FFFF"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb38-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>()</span></code></pre></div></div>
<div class="dv-wide-figure page-columns page-full">
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p class="page-columns page-full"><a href="preds.png" class="lightbox page-columns page-full" data-gallery="quarto-lightbox-gallery-2" title="Nino 3.4 Index: Ground truth vs.&nbsp;predictions (validation set)."><img src="https://divergences.xyz/posts/enso-prediction/preds.png" class="img-fluid figure-img column-body-outset-right" alt="Nino 3.4 Index: Ground truth vs.&nbsp;predictions (validation set)."></a></p>
<figcaption>Nino 3.4 Index: Ground truth vs.&nbsp;predictions (validation set).</figcaption>
</figure>
</div>
</div>
<p>This does not look bad either. However, we need to keep in mind that we’re predicting just a single time step ahead. We probably should not overestimate the results. Which leads directly to the discussion.</p>
</section>
<section id="discussion" class="level1">
<h1>Discussion</h1>
<p>When working with small amounts of data, a lot can be learned by quick-ish experimentation. However, when <em>at the same time</em>, the task is complex, one should be cautious extrapolating.</p>
<p>For example, well-established regularizers such as batchnorm and dropout, while intended to improve generalization to the validation set, may turn out to severely impede training itself. This is the story behind the one batchnorm layer I kept (I did try having more), and it is also why there is no dropout.</p>
<p>One lesson to learn from this experience then is: Make sure the amount of data matches the complexity of the task. This is what we see in the ENSO prediction papers published on arxiv.</p>
<p>If we should treat the results with caution, why even publish the post?</p>
<p>For one, it shows an application of convLSTM to real-world data, employing a reasonably complex architecture and illustrating techniques like custom losses and loss masking. Similar architectures and strategies should be applicable to a wide range of real-world tasks – basically, whenever predictors in a time-series problem are given on a spatial grid.</p>
<p>Secondly, the application itself – forecasting an atmospheric phenomenon that greatly affects ecosystems as well as human well-being – seems like an excellent use of deep learning. Applications like these stand out as all the more worthwhile as the same cannot be said of everything deep learning is – and will be, barring effective regulation – used for.</p>
<p>Thanks for reading!</p>
</section>
<section id="appendix-convlstm-code" class="level1">
<h1>Appendix: <code>convlstm</code> code</h1>
<p>For an in-depth explanation of <code>convlstm</code>, see <a href="https://blogs.rstudio.com/ai/posts/2020-12-17-torch-convlstm/">the blog post</a>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb39-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torch)</span>
<span id="cb39-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torchvision)</span>
<span id="cb39-3"></span>
<span id="cb39-4">convlstm_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_module</span>(</span>
<span id="cb39-5">  </span>
<span id="cb39-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">initialize =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(input_dim, hidden_dim, kernel_size, bias) {</span>
<span id="cb39-7">    </span>
<span id="cb39-8">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> hidden_dim</span>
<span id="cb39-9">    </span>
<span id="cb39-10">    padding <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> kernel_size <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%/%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb39-11">    </span>
<span id="cb39-12">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_conv2d</span>(</span>
<span id="cb39-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in_channels =</span> input_dim <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim,</span>
<span id="cb39-14">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for each of input, forget, output, and cell gates</span></span>
<span id="cb39-15">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">out_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim,</span>
<span id="cb39-16">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_size =</span> kernel_size,</span>
<span id="cb39-17">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padding =</span> padding,</span>
<span id="cb39-18">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bias =</span> bias</span>
<span id="cb39-19">    )</span>
<span id="cb39-20">  },</span>
<span id="cb39-21">  </span>
<span id="cb39-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">forward =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, prev_states) {</span>
<span id="cb39-23"></span>
<span id="cb39-24">    h_prev <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> prev_states[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb39-25">    c_prev <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> prev_states[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb39-26">    </span>
<span id="cb39-27">    combined <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_cat</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(x, h_prev), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># concatenate along channel axis</span></span>
<span id="cb39-28">    combined_conv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conv</span>(combined)</span>
<span id="cb39-29">    gate_convs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_split</span>(combined_conv, self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb39-30">    cc_i <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> gate_convs[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb39-31">    cc_f <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> gate_convs[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb39-32">    cc_o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> gate_convs[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]]</span>
<span id="cb39-33">    cc_g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> gate_convs[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]]</span>
<span id="cb39-34">    </span>
<span id="cb39-35">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># input, forget, output, and cell gates (corresponding to torch's LSTM)</span></span>
<span id="cb39-36">    i <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_sigmoid</span>(cc_i)</span>
<span id="cb39-37">    f <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_sigmoid</span>(cc_f)</span>
<span id="cb39-38">    o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_sigmoid</span>(cc_o)</span>
<span id="cb39-39">    g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tanh</span>(cc_g)</span>
<span id="cb39-40">    </span>
<span id="cb39-41">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cell state</span></span>
<span id="cb39-42">    c_next <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> f <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> c_prev <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> g</span>
<span id="cb39-43">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># hidden state</span></span>
<span id="cb39-44">    h_next <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> o <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tanh</span>(c_next)</span>
<span id="cb39-45">    </span>
<span id="cb39-46">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(h_next, c_next)</span>
<span id="cb39-47">    </span>
<span id="cb39-48">  },</span>
<span id="cb39-49">  </span>
<span id="cb39-50">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">init_hidden =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(batch_size, height, width) {</span>
<span id="cb39-51">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_zeros</span>(batch_size, self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim, height, width, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>device),</span>
<span id="cb39-52">         <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_zeros</span>(batch_size, self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim, height, width, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>device))</span>
<span id="cb39-53">  }</span>
<span id="cb39-54">)</span>
<span id="cb39-55"></span>
<span id="cb39-56">convlstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_module</span>(</span>
<span id="cb39-57">  </span>
<span id="cb39-58">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">initialize =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(input_dim, hidden_dims, kernel_sizes, n_layers, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bias =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>) {</span>
<span id="cb39-59"> </span>
<span id="cb39-60">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_layers</span>
<span id="cb39-61">    </span>
<span id="cb39-62">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_module_list</span>()</span>
<span id="cb39-63">    </span>
<span id="cb39-64">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_layers) {</span>
<span id="cb39-65">      cur_input_dim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) input_dim <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> hidden_dims[i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb39-66">      self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">append</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">convlstm_cell</span>(cur_input_dim, hidden_dims[i], kernel_sizes[i], bias))</span>
<span id="cb39-67">    }</span>
<span id="cb39-68">  },</span>
<span id="cb39-69">  </span>
<span id="cb39-70">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># we always assume batch-first</span></span>
<span id="cb39-71">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">forward =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) {</span>
<span id="cb39-72">    </span>
<span id="cb39-73">    batch_size <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb39-74">    seq_len <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb39-75">    height <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]</span>
<span id="cb39-76">    width <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span>
<span id="cb39-77">   </span>
<span id="cb39-78">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># initialize hidden states</span></span>
<span id="cb39-79">    init_hidden <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers)</span>
<span id="cb39-80">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers) {</span>
<span id="cb39-81">      init_hidden[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list[[i]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">init_hidden</span>(batch_size, height, width)</span>
<span id="cb39-82">    }</span>
<span id="cb39-83">    </span>
<span id="cb39-84">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list containing the outputs, of length seq_len, for each layer</span></span>
<span id="cb39-85">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this is the same as h, at each step in the sequence</span></span>
<span id="cb39-86">    layer_output_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers)</span>
<span id="cb39-87">    </span>
<span id="cb39-88">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list containing the last states (h, c) for each layer</span></span>
<span id="cb39-89">    layer_state_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers)</span>
<span id="cb39-90"></span>
<span id="cb39-91">    cur_layer_input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> x</span>
<span id="cb39-92">    hidden_states <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> init_hidden</span>
<span id="cb39-93">    </span>
<span id="cb39-94">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># loop over layers</span></span>
<span id="cb39-95">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers) {</span>
<span id="cb39-96">      </span>
<span id="cb39-97">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># every layer's hidden state starts from 0 (non-stateful)</span></span>
<span id="cb39-98">      h_c <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> hidden_states[[i]]</span>
<span id="cb39-99">      h <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> h_c[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb39-100">      c <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> h_c[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb39-101">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># outputs, of length seq_len, for this layer</span></span>
<span id="cb39-102">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># equivalently, list of h states for each time step</span></span>
<span id="cb39-103">      output_sequence <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> seq_len)</span>
<span id="cb39-104">      </span>
<span id="cb39-105">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># loop over timesteps</span></span>
<span id="cb39-106">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (t <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>seq_len) {</span>
<span id="cb39-107">        h_c <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list[[i]](cur_layer_input[ , t, , , ], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(h, c))</span>
<span id="cb39-108">        h <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> h_c[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb39-109">        c <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> h_c[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb39-110">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep track of output (h) for every timestep</span></span>
<span id="cb39-111">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># h has dim (batch_size, hidden_size, height, width)</span></span>
<span id="cb39-112">        output_sequence[[t]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> h</span>
<span id="cb39-113">      }</span>
<span id="cb39-114"></span>
<span id="cb39-115">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># stack hs for all timesteps over seq_len dimension</span></span>
<span id="cb39-116">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># stacked_outputs has dim (batch_size, seq_len, hidden_size, height, width)</span></span>
<span id="cb39-117">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same as input to forward (x)</span></span>
<span id="cb39-118">      stacked_outputs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_stack</span>(output_sequence, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb39-119">      </span>
<span id="cb39-120">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pass the list of outputs (hs) to next layer</span></span>
<span id="cb39-121">      cur_layer_input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> stacked_outputs</span>
<span id="cb39-122">      </span>
<span id="cb39-123">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep track of list of outputs or this layer</span></span>
<span id="cb39-124">      layer_output_list[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> stacked_outputs</span>
<span id="cb39-125">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep track of last state for this layer</span></span>
<span id="cb39-126">      layer_state_list[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(h, c)</span>
<span id="cb39-127">    }</span>
<span id="cb39-128"> </span>
<span id="cb39-129">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(layer_output_list, layer_state_list)</span>
<span id="cb39-130">      </span>
<span id="cb39-131">  }</span>
<span id="cb39-132">    </span>
<span id="cb39-133">)</span></code></pre></div></div>



</section>


<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Deep Learning</category>
  <category>Climate &amp; Weather</category>
  <guid>https://divergences.xyz/posts/enso-prediction/</guid>
  <pubDate>Wed, 02 Feb 2022 00:00:00 GMT</pubDate>
  <media:content url="https://divergences.xyz/posts/enso-prediction/pic.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Convolutional LSTM for spatial forecasting</title>
  <dc:creator>Sigrid Keydana</dc:creator>
  <link>https://divergences.xyz/posts/torch-convlstm/</link>
  <description><![CDATA[ 






<p>This post is the first in a loose series exploring forecasting of spatially-determined data over time. By spatially-determined I mean that whatever the quantities we’re trying to predict – be they univariate or multivariate time series, of spatial dimensionality or not – the <em>input</em> data are given on a spatial grid.</p>
<p>For example, the input could be atmospheric measurements, such as sea surface temperature or pressure, given at some set of latitudes and longitudes. The target to be predicted could then span that same (or another) grid. Alternatively, it could be a univariate time series, like a meteorological index.</p>
<p>But wait a second, you may be thinking. For time-series prediction, we have that time-honored set of recurrent architectures (e.g., LSTM, GRU), right? Right. We do; but, once we feed spatial data to an RNN, treating different locations as different input features, we lose an essential structural relationship. Importantly, we need to operate in both space and time. We want both: recurrence relations and convolutional filters. Enter <em>convolutional RNNs</em>.</p>
<section id="what-to-expect-from-this-post" class="level2">
<h2 class="anchored" data-anchor-id="what-to-expect-from-this-post">What to expect from this post</h2>
<p>Today, we won’t jump into real-world applications just yet. Instead, we’ll take our time to build a convolutional LSTM (henceforth: convLSTM) in <code>torch</code>. For one, we have to – there is no official PyTorch implementation.</p>
<p>(Keras, on the other hand, has one. If you’re interested in quickly playing around with a Keras convLSTM, check out <a href="https://tensorflow.rstudio.com/guide/keras/examples/conv_lstm/">this nice example</a>.)</p>
<p>What’s more, this post can serve as an introduction to building your own modules. This is something you may be familiar with from Keras or not – depending on whether you’ve used custom models or rather, preferred the declarative <em>define -&gt; compile -&gt; fit</em> style. (Yes, I’m implying there’s some transfer going on if one comes to <code>torch</code> from Keras custom training. Syntactic and semantic details may be different, but both share the object-oriented style that allows for great flexibility and control.)</p>
<p>Last but not least, we’ll also use this as a hands-on experience with RNN architectures (the LSTM, specifically). While the general concept of recurrence may be easy to grasp, it is not necessarily self-evident how those architectures should, or could, be coded. Personally, I find that independent of the framework used, RNN-related documentation leaves me confused. What exactly <em>is</em> being returned from calling an LSTM, or a GRU? (In Keras this depends on how you’ve defined the layer in question.) I suspect that once we’ve decided what we <em>want</em> to return, the actual code won’t be that complicated. Consequently, we’ll take a detour clarifying what it is that <code>torch</code> and Keras are giving us. Implementing our convLSTM will be a lot more straightforward thereafter.</p>
</section>
<section id="a-torch-convlstm" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="a-torch-convlstm">A <code>torch</code> convLSTM</h2>
<p>The code discussed here may be found on <a href="https://github.com/skeydan/convlstm">GitHub</a>. (Depending on when you’re reading this, the code in that repository may have evolved though.)</p>
<p>My starting point was one of the PyTorch implementations found on the net, namely, <a href="https://github.com/ndrplz/ConvLSTM_pytorch/blob/master/convlstm.py">this one</a>. If you search for “PyTorch convGRU” or “PyTorch convLSTM”, you will find stunning discrepancies in how these are realized – discrepancies not just in syntax and/or engineering ambition, but on the semantic level, right at the center of what the architectures may be expected to do. As they say, let the buyer beware. (Regarding the implementation I ended up porting, I am confident that while numerous optimizations will be possible, the basic mechanism matches my expectations.)</p>
<p>What do I expect? Let’s approach this task in a top-down way.</p>
<section id="input-and-output" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="input-and-output">Input and output</h3>
<p>The convLSTM’s input will be a time series of spatial data, each observation being of size <code>(time steps, channels, height, width)</code>.</p>
<p>Compare this with the usual RNN input format, be it in <code>torch</code> or Keras. In both frameworks, RNNs expect tensors of size <code>(timesteps, input_dim)</code><sup>1</sup>. <code>input_dim</code> is <img src="https://latex.codecogs.com/png.latex?1"> for univariate time series and greater than <img src="https://latex.codecogs.com/png.latex?1"> for multivariate ones. Conceptually, we may match this to convLSTM’s <code>channels</code> dimension: There could be a single channel, for temperature, say – or there could be several, such as for pressure, temperature, and humidity. The two additional dimensions found in convLSTM, <code>height</code> and <code>width</code>, are spatial indexes into the data.</p>
<div class="no-row-height column-margin column-container"><div id="fn1"><p><sup>1</sup>&nbsp;Leaving aside the batch dimension in this discussion.</p></div></div><p>In sum, we want to be able to pass data that:</p>
<ul>
<li><p>consist of one or more features,</p></li>
<li><p>evolve in time, and</p></li>
<li><p>are indexed in two spatial dimensions.</p></li>
</ul>
<p>How about the output? We want to be able to return forecasts for as many time steps as we have in the input sequence. This is something that <code>torch</code> RNNs do by default, while Keras equivalents do not. (You have to pass <code>return_sequences = TRUE</code> to obtain that effect.) If we’re interested in predictions for just a single point in time, we can always pick the last time step in the output tensor.</p>
<p>However, with RNNs, it is not all about outputs. RNN architectures also carry through hidden states.</p>
<p>What are hidden states? I carefully phrased that sentence to be as general as possible – deliberately circling around the confusion that, in my view, often arises at this point. We’ll attempt to clear up some of that confusion in a second, but let’s first finish our high-level requirements specification.</p>
<p>We want our convLSTM to be usable in different contexts and applications. Various architectures exist that make use of hidden states, most prominently perhaps, encoder-decoder architectures. Thus, we want our convLSTM to return those as well. Again, this is something a <code>torch</code> LSTM does by default, while in Keras it is achieved using <code>return_state = TRUE</code>.</p>
<p>Now though, it really is time for that interlude. We’ll sort out the ways things are called by both <code>torch</code> and Keras, and inspect what you get back from their respective GRUs and LSTMs.</p>
</section>
<section id="interlude-outputs-states-hidden-values-whats-what" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="interlude-outputs-states-hidden-values-whats-what">Interlude: Outputs, states, hidden values … what’s what?</h3>
<p>For this to remain an interlude, I summarize findings on a high level. The code snippets in the appendix show how to arrive at these results. Heavily commented, they probe return values from both Keras and <code>torch</code> GRUs and LSTMs. Running these will make the upcoming summaries seem a lot less abstract.</p>
<p>First, let’s look at the ways you create an LSTM in both frameworks. (I will generally use LSTM as the “prototypical RNN example”, and just mention GRUs when there are differences significant in the context in question.)</p>
<p>In Keras, to create an LSTM you may write something like this:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1">lstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_lstm</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<p>The <code>torch</code> equivalent would be:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">lstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_lstm</span>(</span>
<span id="cb2-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of input features</span></span>
<span id="cb2-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of hidden (and output!) features</span></span>
<span id="cb2-4">)</span></code></pre></div></div>
<p>Don’t focus on <code>torch</code>‘s <code>input_size</code> parameter for this discussion. (It’s the number of features in the input tensor.) The parallel occurs between Keras’ <code>units</code> and <code>torch</code>’s <code>hidden_size</code>. If you’ve been using Keras, you’re probably thinking of <code>units</code> as the thing that determines output size (equivalently, the number of features in the output). So when <code>torch</code> lets us arrive at the same result using <code>hidden_size</code>, what does that mean? It means that somehow we’re specifying the same thing, using different terminology. And it does make sense, since at every time step current input and previous hidden state are added<sup>2</sup>:</p>
<div class="no-row-height column-margin column-container"><div id="fn2"><p><sup>2</sup>&nbsp;In theory, it would be possible for them to be of different sizes if the respective weight matrices transformed their operands to the same output size.</p></div></div><p><img src="https://latex.codecogs.com/png.latex?%0A%5Cmathbf%7Bh%7D_t%20=%20%5Cmathbf%7BW%7D_%7Bx%7D%5Cmathbf%7Bx%7D_t%20+%20%5Cmathbf%7BW%7D_%7Bh%7D%5Cmathbf%7Bh%7D_%7Bt-1%7D%0A"></p>
<p>Now, <em>about those hidden states</em>.</p>
<p>When a Keras LSTM is defined with <code>return_state = TRUE</code>, its return value is a structure of three entities called output, memory state, and carry state. In <code>torch</code>, the same entities are referred to as output, hidden state, and cell state. (In <code>torch</code>, we always get all of them.)</p>
<p>So are we dealing with three different types of entities? We are not.</p>
<p>The cell, or carry state is that special thing that sets apart LSTMs from GRUs deemed responsible for the “long” in “long short-term memory”. Technically, it could be reported to the user at all points in time; as we’ll see shortly though, it is not.</p>
<p>What about outputs and hidden, or memory states? Confusingly, these really are the same thing. Recall that for each input <em>item</em> in the input <em>sequence</em>, we’re combining it with the previous state, resulting in a new state, to be made used of in the next step<sup>3</sup>:</p>
<div class="no-row-height column-margin column-container"><div id="fn3"><p><sup>3</sup>&nbsp;Yes, this is the same formula as above.</p></div></div><p><img src="https://latex.codecogs.com/png.latex?%0A%5Cmathbf%7Bh%7D_t%20=%20%5Cmathbf%7BW%7D_%7Bx%7D%5Cmathbf%7Bx%7D_t%20+%20%5Cmathbf%7BW%7D_%7Bh%7D%5Cmathbf%7Bh%7D_%7Bt-1%7D%0A"></p>
<p>Now, say that we’re interested in looking at just the final time step – that is, the default output of a Keras LSTM. From that point of view, we can consider those intermediate computations as “hidden”. Seen like that, output and hidden states feel different.</p>
<p>However, we can also request to see the outputs for every time step. If we do so, there is no difference – the output<strong>s</strong> (plural) equal the hidden states. This can be verified using the code in the appendix.</p>
<p>Thus, of the three things returned by an LSTM, two are really the same. How about the GRU, then? As there is no “cell state”, we really have just one type of thing left over – call it outputs or hidden states.</p>
<p>Let’s summarize this in a table.</p>
<div class="column-body-outset-right">
<table class="caption-top table">
<caption>Table 1: RNN terminology. Comparing torch-speak and Keras-speak. In row 1, the terms are parameter names. In rows 2 and 3, they are pulled from current documentation.</caption>
<colgroup>
<col style="width: 80%">
<col style="width: 9%">
<col style="width: 9%">
</colgroup>
<thead>
<tr class="header">
<th>Referring to this entity:</th>
<th><code>torch</code> says:</th>
<th>Keras says:</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p><em>Number of features in the output</em></p>
<p>This determines both how many output features there are <em>and</em> the dimensionality of the hidden states.</p></td>
<td><code>hidden_size</code></td>
<td><code>units</code></td>
</tr>
<tr class="even">
<td><p><em>Per-time-step output; latent state; intermediate state …</em></p>
<p>This could be named “public state” in the sense that we, the users, are able to obtain <em>all values.</em></p></td>
<td>hidden state</td>
<td>memory state</td>
</tr>
<tr class="odd">
<td><p><em>Cell state; inner state … (LSTM only)</em></p>
<p>This could be named “private state” in that we are able to obtain a value <em>only for the last time step</em>. More on that in a second.</p></td>
<td>cell state</td>
<td>carry state</td>
</tr>
</tbody>
</table>
</div>
<p>Now, about that public vs.&nbsp;private distinction. In both frameworks, we can obtain outputs (hidden states) for every time step. The cell state, however, we can access only for the very last time step. This is purely an implementation decision. As we’ll see when building our own recurrent module, there are no obstacles inherent in keeping track of cell states and passing them back to the user.</p>
<p>If you dislike the pragmatism of this distinction, you can always go with the math. When a new cell state has been computed (based on prior cell state, input, forget, and cell gates – the specifics of which we are not going to get into here), it is transformed to the hidden (a.k.a. output) state making use of yet another, namely, the output gate:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ah_t%20=%20o_t%20%5Codot%20%5Ctanh(c_t)%0A"></p>
<p>Definitely, then, hidden state (output, resp.) builds on cell state, adding additional modeling power.</p>
<p>Now it is time to get back to our original goal and build that convLSTM. First though, let’s summarize the return values obtainable from <code>torch</code> and Keras.</p>
<div class="column-body-outset-right">
<table class="caption-top table">
<caption>Table 2: Contrasting ways of obtaining various return values in <code>torch</code> vs.&nbsp;Keras. Cf. the appendix for complete examples.</caption>
<colgroup>
<col style="width: 54%">
<col style="width: 12%">
<col style="width: 31%">
</colgroup>
<thead>
<tr class="header">
<th>To achieve this goal:</th>
<th>in <code>torch</code> do:</th>
<th>in Keras do:</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>access all intermediate outputs ( = per-time-step outputs)</td>
<td><code>ret[[1]]</code></td>
<td><code>return_sequences = TRUE</code></td>
</tr>
<tr class="even">
<td>access both “hidden state” (output) and “cell state” from final time step (only!)</td>
<td><code>ret[[2]]</code></td>
<td><code>return_state = TRUE</code></td>
</tr>
<tr class="odd">
<td>access all intermediate outputs and the final “cell state”</td>
<td>both of the above</td>
<td><code>return_sequences = TRUE, return_state = TRUE</code></td>
</tr>
<tr class="even">
<td>access all intermediate outputs and “cell states” from all time steps</td>
<td>no way</td>
<td>no way</td>
</tr>
</tbody>
</table>
</div>
</section>
<section id="convlstm-the-plan" class="level3">
<h3 class="anchored" data-anchor-id="convlstm-the-plan"><code>convLSTM</code>, the plan</h3>
<p>In both <code>torch</code> and Keras RNN architectures, single time steps are processed by corresponding <code>Cell</code> classes: There is an LSTM Cell matching the LSTM, a GRU Cell matching the GRU, and so on. We do the same for ConvLSTM. In <code>convlstm_cell()</code>, we first define what should happen to a single observation; then in <code>convlstm()</code>, we build up the recurrence logic.</p>
<p>Once we’re done, we create a dummy dataset, as reduced-to-the-essentials as can be. With more complex datasets, even artificial ones, chances are that if we don’t see any training progress, there are hundreds of possible explanations. We want a sanity check that, if failed, leaves no excuses. Realistic applications are left to future posts.</p>
</section>
<section id="a-single-step-convlstm_cell" class="level3">
<h3 class="anchored" data-anchor-id="a-single-step-convlstm_cell">A single step: <code>convlstm_cell</code></h3>
<p>Our <code>convlstm_cell</code>’s constructor takes arguments <code>input_dim</code> , <code>hidden_dim</code>, and <code>bias</code>, just like a <code>torch</code> LSTM Cell.</p>
<p>But we’re processing two-dimensional input data. Instead of the usual affine combination of new input and previous state, we use a convolution of kernel size <code>kernel_size</code>. Inside <code>convlstm_cell</code>, it is <code>self$conv</code> that takes care of this.</p>
<p>Note how the <code>channels</code> dimension, which in the original input data would correspond to different variables, is creatively used to consolidate four convolutions into one: Each channel output will be passed to just one of the four cell gates. Once in possession of the convolution output, <code>forward()</code> applies the gate logic, resulting in the two types of states it needs to send back to the caller.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torch)</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(zeallot)</span>
<span id="cb3-3"></span>
<span id="cb3-4">convlstm_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_module</span>(</span>
<span id="cb3-5">  </span>
<span id="cb3-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">initialize =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(input_dim, hidden_dim, kernel_size, bias) {</span>
<span id="cb3-7">    </span>
<span id="cb3-8">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> hidden_dim</span>
<span id="cb3-9">    </span>
<span id="cb3-10">    padding <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> kernel_size <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%/%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb3-11">    </span>
<span id="cb3-12">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_conv2d</span>(</span>
<span id="cb3-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in_channels =</span> input_dim <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim,</span>
<span id="cb3-14">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for each of input, forget, output, and cell gates</span></span>
<span id="cb3-15">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">out_channels =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim,</span>
<span id="cb3-16">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_size =</span> kernel_size,</span>
<span id="cb3-17">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padding =</span> padding,</span>
<span id="cb3-18">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bias =</span> bias</span>
<span id="cb3-19">    )</span>
<span id="cb3-20">  },</span>
<span id="cb3-21">  </span>
<span id="cb3-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">forward =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, prev_states) {</span>
<span id="cb3-23"></span>
<span id="cb3-24">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(h_prev, c_prev) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&lt;-%</span> prev_states</span>
<span id="cb3-25">    </span>
<span id="cb3-26">    combined <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_cat</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(x, h_prev), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># concatenate along channel axis</span></span>
<span id="cb3-27">    combined_conv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conv</span>(combined)</span>
<span id="cb3-28">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(cc_i, cc_f, cc_o, cc_g) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&lt;-%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_split</span>(combined_conv, self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb3-29">    </span>
<span id="cb3-30">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># input, forget, output, and cell gates (corresponding to torch's LSTM)</span></span>
<span id="cb3-31">    i <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_sigmoid</span>(cc_i)</span>
<span id="cb3-32">    f <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_sigmoid</span>(cc_f)</span>
<span id="cb3-33">    o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_sigmoid</span>(cc_o)</span>
<span id="cb3-34">    g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tanh</span>(cc_g)</span>
<span id="cb3-35">    </span>
<span id="cb3-36">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cell state</span></span>
<span id="cb3-37">    c_next <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> f <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> c_prev <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> g</span>
<span id="cb3-38">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># hidden state</span></span>
<span id="cb3-39">    h_next <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> o <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_tanh</span>(c_next)</span>
<span id="cb3-40">    </span>
<span id="cb3-41">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(h_next, c_next)</span>
<span id="cb3-42">  },</span>
<span id="cb3-43">  </span>
<span id="cb3-44">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">init_hidden =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(batch_size, height, width) {</span>
<span id="cb3-45">    </span>
<span id="cb3-46">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb3-47">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_zeros</span>(batch_size, self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim, height, width, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>device),</span>
<span id="cb3-48">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_zeros</span>(batch_size, self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hidden_dim, height, width, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">device =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conv<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>device))</span>
<span id="cb3-49">  }</span>
<span id="cb3-50">)</span></code></pre></div></div>
<p>Now <code>convlstm_cell</code> has to be called for every time step. This is done by <code>convlstm</code>.</p>
</section>
<section id="iteration-over-time-steps-convlstm" class="level3">
<h3 class="anchored" data-anchor-id="iteration-over-time-steps-convlstm">Iteration over time steps: <code>convlstm</code></h3>
<p>A <code>convlstm</code> may consist of several layers, just like a <code>torch</code> LSTM. For each layer, we are able to specify hidden and kernel sizes individually.</p>
<p>During initialization, each layer gets its own <code>convlstm_cell</code>. On call, <code>convlstm</code> executes two loops. The outer one iterates over layers. At the end of each iteration, we store the final pair <code>(hidden state, cell state)</code> for later reporting. The inner loop runs over input sequences, calling <code>convlstm_cell</code> at each time step.</p>
<p>We also keep track of intermediate outputs, so we’ll be able to return the complete list of <code>hidden_state</code>s seen during the process. Unlike a <code>torch</code> LSTM, we do this <em>for every layer</em>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">convlstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_module</span>(</span>
<span id="cb4-2">  </span>
<span id="cb4-3">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># hidden_dims and kernel_sizes are vectors, with one element for each layer in n_layers</span></span>
<span id="cb4-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">initialize =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(input_dim, hidden_dims, kernel_sizes, n_layers, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bias =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>) {</span>
<span id="cb4-5"> </span>
<span id="cb4-6">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_layers</span>
<span id="cb4-7">    </span>
<span id="cb4-8">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_module_list</span>()</span>
<span id="cb4-9">    </span>
<span id="cb4-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_layers) {</span>
<span id="cb4-11">      cur_input_dim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) input_dim <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> hidden_dims[i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-12">      self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">append</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">convlstm_cell</span>(cur_input_dim, hidden_dims[i], kernel_sizes[i], bias))</span>
<span id="cb4-13">    }</span>
<span id="cb4-14">  },</span>
<span id="cb4-15">  </span>
<span id="cb4-16">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># we always assume batch-first</span></span>
<span id="cb4-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">forward =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) {</span>
<span id="cb4-18">    </span>
<span id="cb4-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(batch_size, seq_len, num_channels, height, width) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&lt;-%</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>()</span>
<span id="cb4-20">   </span>
<span id="cb4-21">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># initialize hidden states</span></span>
<span id="cb4-22">    init_hidden <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers)</span>
<span id="cb4-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers) {</span>
<span id="cb4-24">      init_hidden[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list[[i]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">init_hidden</span>(batch_size, height, width)</span>
<span id="cb4-25">    }</span>
<span id="cb4-26">    </span>
<span id="cb4-27">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list containing the outputs, of length seq_len, for each layer</span></span>
<span id="cb4-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this is the same as h, at each step in the sequence</span></span>
<span id="cb4-29">    layer_output_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers)</span>
<span id="cb4-30">    </span>
<span id="cb4-31">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list containing the last states (h, c) for each layer</span></span>
<span id="cb4-32">    layer_state_list <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers)</span>
<span id="cb4-33"></span>
<span id="cb4-34">    cur_layer_input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> x</span>
<span id="cb4-35">    hidden_states <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> init_hidden</span>
<span id="cb4-36">    </span>
<span id="cb4-37">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># loop over layers</span></span>
<span id="cb4-38">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_layers) {</span>
<span id="cb4-39">      </span>
<span id="cb4-40">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># every layer's hidden state starts from 0 (non-stateful)</span></span>
<span id="cb4-41">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(h, c) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&lt;-%</span> hidden_states[[i]]</span>
<span id="cb4-42">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># outputs, of length seq_len, for this layer</span></span>
<span id="cb4-43">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># equivalently, list of h states for each time step</span></span>
<span id="cb4-44">      output_sequence <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> seq_len)</span>
<span id="cb4-45">      </span>
<span id="cb4-46">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># loop over time steps</span></span>
<span id="cb4-47">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (t <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>seq_len) {</span>
<span id="cb4-48">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(h, c) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&lt;-%</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_list[[i]](cur_layer_input[ , t, , , ], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(h, c))</span>
<span id="cb4-49">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep track of output (h) for every time step</span></span>
<span id="cb4-50">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># h has dim (batch_size, hidden_size, height, width)</span></span>
<span id="cb4-51">        output_sequence[[t]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> h</span>
<span id="cb4-52">      }</span>
<span id="cb4-53"></span>
<span id="cb4-54">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># stack hs for all time steps over seq_len dimension</span></span>
<span id="cb4-55">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># stacked_outputs has dim (batch_size, seq_len, hidden_size, height, width)</span></span>
<span id="cb4-56">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same as input to forward (x)</span></span>
<span id="cb4-57">      stacked_outputs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_stack</span>(output_sequence, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb4-58">      </span>
<span id="cb4-59">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pass the list of outputs (hs) to next layer</span></span>
<span id="cb4-60">      cur_layer_input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> stacked_outputs</span>
<span id="cb4-61">      </span>
<span id="cb4-62">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep track of list of outputs or this layer</span></span>
<span id="cb4-63">      layer_output_list[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> stacked_outputs</span>
<span id="cb4-64">      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep track of last state for this layer</span></span>
<span id="cb4-65">      layer_state_list[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(h, c)</span>
<span id="cb4-66">    }</span>
<span id="cb4-67"> </span>
<span id="cb4-68">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(layer_output_list, layer_state_list)</span>
<span id="cb4-69">  }</span>
<span id="cb4-70">    </span>
<span id="cb4-71">)</span></code></pre></div></div>
</section>
<section id="calling-the-convlstm" class="level3">
<h3 class="anchored" data-anchor-id="calling-the-convlstm">Calling the <code>convlstm</code></h3>
<p>Let’s see the input format expected by <code>convlstm</code>, and how to access its different outputs.</p>
<p>Here is a suitable input tensor.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># batch_size, seq_len, channels, height, width</span></span>
<span id="cb5-2">x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_rand</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>))</span></code></pre></div></div>
<p>First we make use of a single layer.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">convlstm</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_dims =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_sizes =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_layers =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(layer_outputs, layer_last_states) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&lt;-%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model</span>(x)</span></code></pre></div></div>
<p>We get back a list of length two, which we immediately split up into the two types of output returned: intermediate outputs from all layers, and final states (of both types) for the last layer.</p>
<p>With just a single layer, <code>layer_outputs[[1]]</code>holds all of the layer’s intermediate outputs, stacked on dimension two.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(layer_outputs[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="cb7-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [1]  2  4  5 16 16</span></span></code></pre></div></div>
<p><code>layer_last_states[[1]]</code>is a list of tensors, the first of which holds the single layer’s final hidden state, and the second, its final cell state.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(layer_last_states[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]][[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="cb8-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [1]  2  5 16 16</span></span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(layer_last_states[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]][[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]])</span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [1]  2  5 16 16</span></span></code></pre></div></div>
<p>For comparison, this is how return values look for a multi-layer architecture.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">convlstm</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_dims =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_sizes =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_layers =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(layer_outputs, layer_last_states) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&lt;-%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model</span>(x)</span>
<span id="cb9-3"></span>
<span id="cb9-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for each layer, tensor of size (batch_size, seq_len, hidden_size, height, width)</span></span>
<span id="cb9-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(layer_outputs[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="cb9-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2  4  5 16 16</span></span>
<span id="cb9-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(layer_outputs[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]])</span>
<span id="cb9-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2  4  1 16 16</span></span>
<span id="cb9-9"></span>
<span id="cb9-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list of 2 tensors for each layer</span></span>
<span id="cb9-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str</span>(layer_last_states)</span>
<span id="cb9-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># List of 3</span></span>
<span id="cb9-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#  $ :List of 2</span></span>
<span id="cb9-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   ..$ :Float [1:2, 1:5, 1:16, 1:16]</span></span>
<span id="cb9-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   ..$ :Float [1:2, 1:5, 1:16, 1:16]</span></span>
<span id="cb9-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#  $ :List of 2</span></span>
<span id="cb9-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   ..$ :Float [1:2, 1:5, 1:16, 1:16]</span></span>
<span id="cb9-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   ..$ :Float [1:2, 1:5, 1:16, 1:16]</span></span>
<span id="cb9-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#  $ :List of 2</span></span>
<span id="cb9-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   ..$ :Float [1:2, 1:1, 1:16, 1:16]</span></span>
<span id="cb9-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   ..$ :Float [1:2, 1:1, 1:16, 1:16]</span></span>
<span id="cb9-22"></span>
<span id="cb9-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># h, of size (batch_size, hidden_size, height, width)</span></span>
<span id="cb9-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(layer_last_states[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]][[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="cb9-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2  1 16 16</span></span>
<span id="cb9-26"></span>
<span id="cb9-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># c, of size (batch_size, hidden_size, height, width)</span></span>
<span id="cb9-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(layer_last_states[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]][[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]])</span>
<span id="cb9-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2  1 16 16</span></span></code></pre></div></div>
<p>Now we want to sanity-check this module with the simplest-possible dummy data.</p>
</section>
<section id="sanity-checking-the-convlstm" class="level3">
<h3 class="anchored" data-anchor-id="sanity-checking-the-convlstm">Sanity-checking the <code>convlstm</code></h3>
<p>We generate black-and-white “movies” of diagonal beams successively translated in space.</p>
<p>Each sequence consists of six time steps, and each beam of six pixels. Just a single sequence is created manually. To create that one sequence, we start from a single beam:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torchvision)</span>
<span id="cb10-2"></span>
<span id="cb10-3">beams <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span>
<span id="cb10-4">beam <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_eye</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_pad</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># left, right, top, bottom</span></span>
<span id="cb10-5">beams[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> beam</span></code></pre></div></div>
<p>Using <code>torch_roll()</code> , we create a pattern where this beam moves up diagonally, and stack the individual tensors along the <code>timesteps</code> dimension.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) {</span>
<span id="cb11-2">  beams[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_roll</span>(beam, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>(i<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>),i<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb11-3">}</span>
<span id="cb11-4"></span>
<span id="cb11-5">init_sequence <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_stack</span>(beams, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<p>That’s a single sequence. Thanks to <code>torchvision::transform_random_affine()</code>, we almost effortlessly produce a dataset of a hundred sequences. Moving beams start at random points in the spatial frame, but they all share that upward-diagonal motion.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">sequences <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vector</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)</span>
<span id="cb12-2">sequences[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> init_sequence</span>
<span id="cb12-3"></span>
<span id="cb12-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>) {</span>
<span id="cb12-5">  sequences[[i]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transform_random_affine</span>(init_sequence, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">degrees =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">translate =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>))</span>
<span id="cb12-6">}</span>
<span id="cb12-7"></span>
<span id="cb12-8">input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_stack</span>(sequences, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb12-9"></span>
<span id="cb12-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># add channels dimension</span></span>
<span id="cb12-11">input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> input<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unsqueeze</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb12-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(input)</span>
<span id="cb12-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [1] 100   6  1  24  24</span></span></code></pre></div></div>
<p>That’s it for the raw data. Now we still need a <code>dataset</code> and a <code>dataloader</code>. Of the six time steps, we use the first five as input and try to predict the last one.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">dummy_ds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dataset</span>(</span>
<span id="cb13-2">  </span>
<span id="cb13-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">initialize =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(data) {</span>
<span id="cb13-4">    self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> data</span>
<span id="cb13-5">  },</span>
<span id="cb13-6">  </span>
<span id="cb13-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.getitem =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i) {</span>
<span id="cb13-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>data[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, ..], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>data[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, ..])</span>
<span id="cb13-9">  },</span>
<span id="cb13-10">  </span>
<span id="cb13-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.length =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>() {</span>
<span id="cb13-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(self<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>data)</span>
<span id="cb13-13">  }</span>
<span id="cb13-14">)</span>
<span id="cb13-15"></span>
<span id="cb13-16">ds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dummy_ds</span>(input)</span>
<span id="cb13-17">dl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dataloader</span>(ds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)</span></code></pre></div></div>
<p>Here is a tiny-ish convLSTM, trained for motion prediction:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">convlstm</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_dim =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_dims =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_sizes =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_layers =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb14-2"></span>
<span id="cb14-3">optimizer <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optim_adam</span>(model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parameters)</span>
<span id="cb14-4"></span>
<span id="cb14-5">num_epochs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb14-6"></span>
<span id="cb14-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (epoch <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>num_epochs) {</span>
<span id="cb14-8">  </span>
<span id="cb14-9">  model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">train</span>()</span>
<span id="cb14-10">  batch_losses <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb14-11">  </span>
<span id="cb14-12">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (b <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(dl)) {</span>
<span id="cb14-13">    </span>
<span id="cb14-14">    optimizer<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zero_grad</span>()</span>
<span id="cb14-15">    </span>
<span id="cb14-16">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># last-time-step output from last layer</span></span>
<span id="cb14-17">    preds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model</span>(b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x)[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]][[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]][[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb14-18">  </span>
<span id="cb14-19">    loss <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nnf_mse_loss</span>(preds, b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y)</span>
<span id="cb14-20">    batch_losses <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(batch_losses, loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">item</span>())</span>
<span id="cb14-21">    </span>
<span id="cb14-22">    loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">backward</span>()</span>
<span id="cb14-23">    optimizer<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">step</span>()</span>
<span id="cb14-24">  }</span>
<span id="cb14-25">  </span>
<span id="cb14-26">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (epoch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb14-27">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Epoch %d, training loss:%3f</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, epoch, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(batch_losses)))</span>
<span id="cb14-28">}</span></code></pre></div></div>
<pre><code>Epoch 10, training loss:0.008522

Epoch 20, training loss:0.008079

Epoch 30, training loss:0.006187

Epoch 40, training loss:0.003828

Epoch 50, training loss:0.002322

Epoch 60, training loss:0.001594

Epoch 70, training loss:0.001376

Epoch 80, training loss:0.001258

Epoch 90, training loss:0.001218

Epoch 100, training loss:0.001171</code></pre>
<p>Loss decreases, but that in itself is not a guarantee the model has learned anything. Has it? Let’s inspect its forecast for the very first sequence and see.</p>
<p>For printing, I’m zooming in on the relevant region in the 24x24-pixel frame. Here is the ground truth for time step six:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>]</span></code></pre></div></div>
<pre><code>0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  1  0  0  0  0  0  0  0
0  0  0  1  0  0  0  0  0  0
0  0  0  0  1  0  0  0  0  0
0  0  0  0  0  1  0  0  0  0
0  0  0  0  0  0  1  0  0  0
0  0  0  0  0  0  0  1  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0</code></pre>
<p>And here is the forecast. This does not look bad at all, given there was neither experimentation nor tuning involved.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(preds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<pre><code>       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10]
 [1,]  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00     0
 [2,] -0.02  0.36  0.01  0.06  0.00  0.00  0.00  0.00  0.00     0
 [3,]  0.00 -0.01  0.71  0.01  0.06  0.00  0.00  0.00  0.00     0
 [4,] -0.01  0.04  0.00  0.75  0.01  0.06  0.00  0.00  0.00     0
 [5,]  0.00 -0.01 -0.01 -0.01  0.75  0.01  0.06  0.00  0.00     0
 [6,]  0.00  0.01  0.00 -0.07 -0.01  0.75  0.01  0.06  0.00     0
 [7,]  0.00  0.01 -0.01 -0.01 -0.07 -0.01  0.75  0.01  0.06     0
 [8,]  0.00  0.00  0.01  0.00  0.00 -0.01  0.00  0.71  0.00     0
 [9,]  0.00  0.00  0.00  0.01  0.01  0.00  0.03 -0.01  0.37     0
[10,]  0.00  0.00  0.00  0.00  0.00  0.00 -0.01 -0.01 -0.01     0</code></pre>
<p>This should suffice for a sanity check. If you made it till the end, thanks for your patience! In the best case, you’ll be able to apply this architecture (or a similar one) to your own data – but even if not, I hope you’ve enjoyed learning about <code>torch</code> model coding and/or RNN weirdness ;-)</p>
<p>I, for one, am certainly looking forward to exploring convLSTMs on real-world problems in the near future. Thanks for reading!</p>
</section>
</section>
<section id="appendix" class="level2">
<h2 class="anchored" data-anchor-id="appendix">Appendix</h2>
<p>This appendix contains the code used to create tables 1 and 2 above.</p>
<section id="keras" class="level3">
<h3 class="anchored" data-anchor-id="keras">Keras</h3>
<section id="lstm" class="level4">
<h4 class="anchored" data-anchor-id="lstm">LSTM</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(keras)</span>
<span id="cb20-2"></span>
<span id="cb20-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># batch of 3, with 4 time steps each and a single feature</span></span>
<span id="cb20-4">input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">k_random_normal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>L, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>L, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>L))</span>
<span id="cb20-5">input</span>
<span id="cb20-6"></span>
<span id="cb20-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default args</span></span>
<span id="cb20-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = (batch_size, units)</span></span>
<span id="cb20-9">lstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_lstm</span>(</span>
<span id="cb20-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb20-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb20-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb20-13">)</span>
<span id="cb20-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lstm</span>(input)</span>
<span id="cb20-15"></span>
<span id="cb20-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return_sequences = TRUE</span></span>
<span id="cb20-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = (batch_size, time steps, units)</span></span>
<span id="cb20-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb20-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note how for each item in the batch, the value for time step 4 equals that obtained above</span></span>
<span id="cb20-20">lstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_lstm</span>(</span>
<span id="cb20-21">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb20-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_sequences =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb20-23">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb20-24">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb20-25">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># bias is by default initialized to 0</span></span>
<span id="cb20-26">)</span>
<span id="cb20-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lstm</span>(input)</span>
<span id="cb20-28"></span>
<span id="cb20-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return_state = TRUE</span></span>
<span id="cb20-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = list of:</span></span>
<span id="cb20-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#                - outputs, of shape: (batch_size, units)</span></span>
<span id="cb20-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#                - "memory states" for the last time step, of shape: (batch_size, units)</span></span>
<span id="cb20-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#                - "carry states" for the last time step, of shape: (batch_size, units)</span></span>
<span id="cb20-34"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb20-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note how the first and second list items are identical!</span></span>
<span id="cb20-36">lstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_lstm</span>(</span>
<span id="cb20-37">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb20-38">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_state =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb20-39">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb20-40">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb20-41">)</span>
<span id="cb20-42"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lstm</span>(input)</span>
<span id="cb20-43"></span>
<span id="cb20-44"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return_state = TRUE, return_sequences = TRUE</span></span>
<span id="cb20-45"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = list of:</span></span>
<span id="cb20-46"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#                - outputs, of shape: (batch_size, time steps, units)</span></span>
<span id="cb20-47"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#                - "memory" states for the last time step, of shape: (batch_size, units)</span></span>
<span id="cb20-48"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#                - "carry states" for the last time step, of shape: (batch_size, units)</span></span>
<span id="cb20-49"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb20-50"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note how again, the "memory" state found in list item 2 matches the final-time step outputs reported in item 1</span></span>
<span id="cb20-51">lstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_lstm</span>(</span>
<span id="cb20-52">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb20-53">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_sequences =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb20-54">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_state =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb20-55">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb20-56">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb20-57">)</span>
<span id="cb20-58"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lstm</span>(input)</span></code></pre></div></div>
</section>
<section id="gru" class="level4">
<h4 class="anchored" data-anchor-id="gru">GRU</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default args</span></span>
<span id="cb21-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = (batch_size, units)</span></span>
<span id="cb21-3">gru <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_gru</span>(</span>
<span id="cb21-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb21-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb21-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb21-7">)</span>
<span id="cb21-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gru</span>(input)</span>
<span id="cb21-9"></span>
<span id="cb21-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return_sequences = TRUE</span></span>
<span id="cb21-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = (batch_size, time steps, units)</span></span>
<span id="cb21-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb21-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note how for each item in the batch, the value for time step 4 equals that obtained above</span></span>
<span id="cb21-14">gru <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_gru</span>(</span>
<span id="cb21-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb21-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_sequences =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb21-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb21-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb21-19">)</span>
<span id="cb21-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gru</span>(input)</span>
<span id="cb21-21"></span>
<span id="cb21-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return_state = TRUE</span></span>
<span id="cb21-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = list of:</span></span>
<span id="cb21-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - outputs, of shape: (batch_size, units)</span></span>
<span id="cb21-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - "memory" states for the last time step, of shape: (batch_size, units)</span></span>
<span id="cb21-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb21-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note how the list items are identical!</span></span>
<span id="cb21-28">gru <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_gru</span>(</span>
<span id="cb21-29">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb21-30">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_state =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb21-31">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb21-32">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb21-33">)</span>
<span id="cb21-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gru</span>(input)</span>
<span id="cb21-35"></span>
<span id="cb21-36"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return_state = TRUE, return_sequences = TRUE</span></span>
<span id="cb21-37"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = list of:</span></span>
<span id="cb21-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - outputs, of shape: (batch_size, time steps, units)</span></span>
<span id="cb21-39"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - "memory states" for the last time step, of shape: (batch_size, units)</span></span>
<span id="cb21-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb21-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note how again, the "memory state" found in list item 2 matches the final-time-step outputs reported in item 1</span></span>
<span id="cb21-42">gru <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_gru</span>(</span>
<span id="cb21-43">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">units =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb21-44">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_sequences =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb21-45">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return_state =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb21-46">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kernel_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb21-47">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recurrent_initializer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">initializer_constant</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb21-48">)</span>
<span id="cb21-49"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gru</span>(input)</span></code></pre></div></div>
</section>
</section>
<section id="torch" class="level3">
<h3 class="anchored" data-anchor-id="torch"><code>torch</code></h3>
<section id="lstm-non-stacked-architecture" class="level4">
<h4 class="anchored" data-anchor-id="lstm-non-stacked-architecture">LSTM (non-stacked architecture)</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(torch)</span>
<span id="cb22-2"></span>
<span id="cb22-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># batch of 3, with 4 time steps each and a single feature</span></span>
<span id="cb22-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># we will specify batch_first = TRUE when creating the LSTM</span></span>
<span id="cb22-5">input <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">torch_randn</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb22-6">input</span>
<span id="cb22-7"></span>
<span id="cb22-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default args</span></span>
<span id="cb22-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = (batch_size, units)</span></span>
<span id="cb22-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb22-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note: there is an additional argument num_layers that we could use to specify a stacked LSTM - effectively composing two LSTM modules</span></span>
<span id="cb22-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default for num_layers is 1 though </span></span>
<span id="cb22-13">lstm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_lstm</span>(</span>
<span id="cb22-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of input features</span></span>
<span id="cb22-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of hidden (and output!) features</span></span>
<span id="cb22-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_first =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for easy comparability with Keras</span></span>
<span id="cb22-17">)</span>
<span id="cb22-18"></span>
<span id="cb22-19"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(lstm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight_ih_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb22-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(lstm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight_hh_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb22-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(lstm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bias_ih_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb22-22"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(lstm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bias_hh_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb22-23"></span>
<span id="cb22-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># returns a list of length 2, namely</span></span>
<span id="cb22-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   - outputs, of shape (batch_size, time steps, hidden_size) - given we specified batch_first</span></span>
<span id="cb22-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#       Note 1: If this is a stacked LSTM, these are the outputs from the last layer only.</span></span>
<span id="cb22-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#               For our current purpose, this is irrelevant, as we're restricting ourselves to single-layer LSTMs.</span></span>
<span id="cb22-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#       Note 2: hidden_size here is equivalent to units in Keras - both specify number of features</span></span>
<span id="cb22-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#  - list of:</span></span>
<span id="cb22-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - hidden state for the last time step, of shape (num_layers, batch_size, hidden_size)</span></span>
<span id="cb22-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - cell state for the last time step, of shape (num_layers, batch_size, hidden_size)</span></span>
<span id="cb22-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#      Note 3: For a single-layer LSTM, the hidden states are already provided in the first list item.</span></span>
<span id="cb22-33"></span>
<span id="cb22-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lstm</span>(input)</span></code></pre></div></div>
</section>
<section id="gru-non-stacked-architecture" class="level4">
<h4 class="anchored" data-anchor-id="gru-non-stacked-architecture">GRU (non-stacked architecture)</h4>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb23-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default args</span></span>
<span id="cb23-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return shape = (batch_size, units)</span></span>
<span id="cb23-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#</span></span>
<span id="cb23-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note: there is an additional argument num_layers that we could use to specify a stacked GRU - effectively composing two GRU modules</span></span>
<span id="cb23-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default for num_layers is 1 though </span></span>
<span id="cb23-6">gru <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_gru</span>(</span>
<span id="cb23-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of input features</span></span>
<span id="cb23-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of hidden (and output!) features</span></span>
<span id="cb23-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_first =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for easy comparability with Keras</span></span>
<span id="cb23-10">)</span>
<span id="cb23-11"></span>
<span id="cb23-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(gru<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight_ih_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb23-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(gru<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>weight_hh_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb23-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(gru<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bias_ih_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb23-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nn_init_constant_</span>(gru<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bias_hh_l1, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb23-16"></span>
<span id="cb23-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># returns a list of length 2, namely</span></span>
<span id="cb23-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   - outputs, of shape (batch_size, time steps, hidden_size) - given we specified batch_first</span></span>
<span id="cb23-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#       Note 1: If this is a stacked GRU, these are the outputs from the last layer only.</span></span>
<span id="cb23-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#               For our current purpose, this is irrelevant, as we're restricting ourselves to single-layer GRUs.</span></span>
<span id="cb23-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#       Note 2: hidden_size here is equivalent to units in Keras - both specify number of features</span></span>
<span id="cb23-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#  - list of:</span></span>
<span id="cb23-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - hidden state for the last time step, of shape (num_layers, batch_size, hidden_size)</span></span>
<span id="cb23-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#    - cell state for the last time step, of shape (num_layers, batch_size, hidden_size)</span></span>
<span id="cb23-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#       Note 3: For a single-layer GRU, these values are already provided in the first list item.</span></span>
<span id="cb23-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gru</span>(input)</span></code></pre></div></div>


</section>
</section>
</section>


<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Deep Learning</category>
  <guid>https://divergences.xyz/posts/torch-convlstm/</guid>
  <pubDate>Thu, 17 Dec 2020 00:00:00 GMT</pubDate>
  <media:content url="https://divergences.xyz/posts/torch-convlstm/preview.jpeg" medium="image" type="image/jpeg"/>
</item>
</channel>
</rss>
