{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "seed = 0\n",
    "n_samples = 10000\n",
    "n_features = 2\n",
    "n_hstates = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "rnd = np.random.RandomState(seed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bernoulli HMM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from kerasy.ML.HMM import BernoulliHMM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = BernoulliHMM(n_hstates, random_state=seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "samples = rnd.rand(n_samples, 1).round().astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      "BernoulliHMM (Baum-Welch) 01/10 [##------------------]  10.00% - 0.000s  log probability: -8149.581802262507\r",
      "BernoulliHMM (Baum-Welch) 02/10 [####----------------]  20.00% - 0.119s  log probability: -6932.359137050144"
     ]
    }
   ],
   "source": [
    "model.fit(samples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "| Parameter |   Value|\n",
      "----------------------\n",
      "| n_hstates |       3|\n",
      "| init      |  random|\n",
      "| algorithm | viterbi|\n",
      "| up_params |     ite|\n",
      "| n_states  |       2|\n"
     ]
    }
   ],
   "source": [
    "model.params()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.62268276, 0.37731724],\n",
       "       [0.68768748, 0.31231252],\n",
       "       [0.06198365, 0.93801635]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.emission"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `emission[k,0]` is **succes/yes probability** when hidden state is $k$.\n",
    "- `emission[k,1]` is **failure/no probability** when hidden state is $k$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Algorithm: viterbi\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 5848 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(model.predict(samples[0:300]), bins=n_hstates)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "samples[0:300] = samples[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      "BernoulliHMM (Baum-Welch) 01/10 [##------------------]  10.00% - 0.000s  log probability: -7571.2059422712155\r",
      "BernoulliHMM (Baum-Welch) 02/10 [####----------------]  20.00% - 0.100s  log probability: -6919.715264595409"
     ]
    }
   ],
   "source": [
    "model.fit(samples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.40315904, 0.59684096],\n",
       "       [0.60127766, 0.39872234],\n",
       "       [0.05677903, 0.94322097]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.emission"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Algorithm: viterbi\n",
      "Algorithm: viterbi\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 7552 characters]\n",
      "text/plain": [
       "<Figure size 864x432 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, (axL,axR) = plt.subplots(1, 2, sharey=True, figsize=(12,6))\n",
    "axL.hist(model.predict(samples[0:300]), bins=n_hstates)\n",
    "axR.hist(model.predict(samples), bins=n_hstates)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 18036 characters]\n",
      "text/plain": [
       "<Figure size 432x576 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "model.heatmap_params()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Multinomial HMM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "from kerasy.ML.HMM import MultinomialHMM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = MultinomialHMM(n_hstates, random_state=seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "samples = rnd.uniform(low=0, high=3, size=(n_samples,1)).round().astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      "MultinomialHMM (Baum-Welch) 01/10 [##------------------]  10.00% - 0.000s  log probability: -13960.502531142072\r",
      "MultinomialHMM (Baum-Welch) 02/10 [####----------------]  20.00% - 0.122s  log probability: -13372.824284845465"
     ]
    }
   ],
   "source": [
    "model.fit(samples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "| Parameter |   Value|\n",
      "----------------------\n",
      "| n_hstates |       3|\n",
      "| init      |  random|\n",
      "| algorithm | viterbi|\n",
      "| up_params |     ite|\n",
      "| n_states  |       4|\n"
     ]
    }
   ],
   "source": [
    "model.params()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Algorithm: viterbi\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 7280 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(model.predict(samples), bins=n_hstates)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Binomial HMM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "from kerasy.ML.HMM import BinomialHMM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = BinomialHMM(n_hstates, random_state=seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "samples = rnd.uniform(low=1,high=100, size=(n_samples, n_features)).astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      "BinomialHMM (Baum-Welch) 01/10 [##------------------]  10.00% - 0.000s  log probability: -76236.79380486414\r",
      "BinomialHMM (Baum-Welch) 02/10 [####----------------]  20.00% - 0.075s  log probability: -57269.53733544918"
     ]
    }
   ],
   "source": [
    "model.fit(samples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "| Parameter |   Value|\n",
      "----------------------\n",
      "| n_hstates |       3|\n",
      "| init      |  random|\n",
      "| algorithm | viterbi|\n",
      "| up_params |     itθ|\n"
     ]
    }
   ],
   "source": [
    "model.params()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Algorithm: viterbi\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 6268 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(model.predict(samples), bins=n_hstates)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Gaussian HMM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "from kerasy.ML.HMM import GaussianHMM\n",
    "from kerasy.ML.HMM import COVARIANCE_TYPES"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "from kerasy.utils import findLowerUpper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "covs = [\n",
    "    np.eye(2)*2,\n",
    "    np.full(fill_value=0.3, shape=(2,2)) + np.eye(2),\n",
    "    rnd.rand(2,2),\n",
    "]\n",
    "means = [\n",
    "    [-3,-4],\n",
    "    [-1, 3],\n",
    "    [ 2, 1],\n",
    "]\n",
    "Ns = [n_samples//n_hstates for _ in range(n_hstates)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/iwasakishuto/.pyenv/versions/anaconda3-5.0.1/lib/python3.6/site-packages/ipykernel_launcher.py:1: RuntimeWarning: covariance is not symmetric positive-semidefinite.\n",
      "  \"\"\"Entry point for launching an IPython kernel.\n"
     ]
    }
   ],
   "source": [
    "samples = np.concatenate([rnd.multivariate_normal(mean=means[k], cov=covs[k], size=Ns[k]) for k in range(n_hstates)])\n",
    "labels = np.concatenate([[k for _ in range(n)] for k,n in enumerate(Ns)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 86372 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(samples[:,0], samples[:,1], c=labels, s=1)\n",
    "plt.title(\"Sample data\"), plt.grid()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "(xmin,ymin),(xmax,ymax) = findLowerUpper(samples)\n",
    "Xs,Ys = np.meshgrid(np.linspace(xmin, xmax, 100), np.linspace(ymin, ymax, 100))\n",
    "XYs = np.c_[Xs.ravel(),Ys.ravel()]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**The difference by `covariance_type`**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "from kerasy.utils import galleryplot\n",
    "from scipy import stats"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_func(ax, cov_type):\n",
    "    model = GaussianHMM(n_hstates, covariance_type=cov_type, random_state=seed)\n",
    "    model.fit(samples, verbose=-1)\n",
    "    Zs = np.sum([stats.multivariate_normal(\n",
    "        model.means[k], \n",
    "        model.covariances[k]\n",
    "    ).pdf(XYs) for k in range(n_hstates)], axis=0).reshape(Xs.shape)\n",
    "    \n",
    "    ax.pcolor(Xs,Ys,Zs,alpha=0.3, cmap=\"jet\")\n",
    "    ax.set_title(cov_type, fontsize=16)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 116052 characters]\n",
      "text/plain": [
       "<Figure size 576x576 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = galleryplot(plot_func, argnames=\"cov_type\", ncols=2, iterator=COVARIANCE_TYPES, sharex=\"all\", sharey=\"all\")\n",
    "fig.suptitle(\"The difference by `covariance_type`\", fontsize=18)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "hide_input": false,
  "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.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
