{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Softmax and Sparsemax\n\n:code:`deepdow` offers multiple allocation layers. Among them are the :code:`SoftmaxAllocator` and\n:code:`SparsemaxAllocator`. Softmax is a very popular technique that turns vectors of numbers (logits)\ninto probability distributions. If we do not allow for short selling (no weights below zero) and\nleveraging (no weight above 1) then weight allocation can be seen as a probability distribution.\nAdditionally, sparsemax was proposed by [Martins2016]_ as an alternative to softmax. It enforces\nsparsity. Both :code:`SoftmaxAllocator` and :code:`SparsemaxAllocator` support :code:`max_weight`\nparameter controlling the maximum possible weight of a single asset and :code:`temperature`.\n\n\nThe below plot shows how these two allocators react to changes in :code:`max_weight` and\n:code:`temperature`.\n\n<div class=\"alert alert-danger\"><h4>Warning</h4><p>Note that we are using the :code:`seaborn` to plot a heatmap.</p></div>\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from deepdow.layers import SoftmaxAllocator, SparsemaxAllocator\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport torch\n\nn_assets = 10\nseed = 6\ntemperatures = [0.2, 0.4, 1]\nmax_weights = [0.2, 0.5, 1]\n\ntorch.manual_seed(seed)\nlogits = torch.rand(size=(1, n_assets)) - 0.5\n\nfig, axs = plt.subplots(len(temperatures),\n                        len(max_weights),\n                        sharex=True,\n                        sharey=True,\n                        figsize=(15, 5))\ncbar_ax = fig.add_axes([.91, .3, .03, .4])\n\nfor r, temperature in enumerate(temperatures):\n    for c, max_weight in enumerate(max_weights):\n        sparsemax = SparsemaxAllocator(n_assets,\n                                       max_weight=max_weight,\n                                       temperature=temperature\n                                       )\n\n        softmax = SoftmaxAllocator(n_assets=n_assets,\n                                   temperature=temperature,\n                                   max_weight=max_weight,\n                                   formulation='variational')\n\n        w_sparsemax = sparsemax(logits).detach().numpy()\n        w_softmax = softmax(logits).detach().numpy()\n\n        df = pd.DataFrame(np.concatenate([w_softmax, w_sparsemax], axis=0),\n                          index=['softmax', 'sparsemax'])\n\n        axs[r, c].set_title('temp={}, max_weight={}'.format(temperature, max_weight))\n        sns.heatmap(df,\n                    vmin=0,\n                    vmax=1,\n                    center=0.5,\n                    cmap='hot',\n                    ax=axs[r, c],\n                    cbar_ax=cbar_ax,\n                    square=True)"
      ]
    }
  ],
  "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
}