{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Zoom layer\n\nThe `layers_zoom` layer is inspired by the Spatial Transformer Network [Jaderberg2015]_.\nIts goal is to be able to zoom in and zoom out across the time dimension. In other words,\nit performs dynamic time warping. Note that this warping is identical over all\nassets and channels. In the example below, we show how one can use this layer to both `speed up` and\n`slow down` the original input tensor **x**.\n\nSpecifically, let us assume that we have 50 assets that have identical returns that follow a\nsinusoid. The period of this sinusoid is equal to our lookback which is 40 (i.e. hours).\n\nThe first column shows the original input tensor. The second column shows a slow down (scale = 0.5).\nHere we only look at the previous 20 hours, however, we stretch each hour to last two hours.\nFinally, the third column shows a speed up (scale = 2). Each hour is shrunk to last 30 minutes.\nNote that in the case of speed up the :code:`padding_mode` becomes important since we do not\nhave access to what happened more than 40 hours ago.\n\n\n<div class=\"alert alert-info\"><h4>Note</h4><p>This layer does not modify the shape of the input.</p></div>\n\n\nAs with many other layers in :code:`deepdow` one can either learn one :code:`scale` for the entire\ntraining set or have a separate network that predicts a different one for each sample.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from deepdow.data.synthetic import sin_single\nfrom deepdow.layers import Zoom\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\n\nnp.random.seed(3)\ntorch.manual_seed(3)\n\nlookback, n_assets = 40, 50\nscale_grid = [1, 0.5, 2]\npadding_grid = ['zeros', 'reflection']\n\ndtype = torch.float\n\nx = torch.as_tensor(np.stack(n_assets * [-sin_single(lookback, freq=1 / lookback)],\n                             axis=1),\n                    dtype=dtype)\n\nx = x[None, None, ...]  # add sample and channel dimension\n\nfig, axs = plt.subplots(len(padding_grid), len(scale_grid), sharex=True, sharey=True)\n\nfor r, padding_mode in enumerate(padding_grid):\n    for c, scale in enumerate(scale_grid):\n        layer = Zoom(padding_mode=padding_mode)\n        x_out = layer(x, torch.ones(1) * scale)\n\n        axs[r, c].imshow(x_out.numpy()[0, 0])\n        axs[r, c].set_title('scale={}\\npad={}'.format(scale, padding_mode))\n\nplt.setp(axs[-1, :], xlabel='Assets')\nplt.setp(axs[:, 0], ylabel='Time')\nfig.subplots_adjust(hspace=1)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}