<?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/enso.html</link>
<atom:link href="https://divergences.xyz/tag/enso.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>
</channel>
</rss>
