From 2d09b6de120c03e814efd09ba22a1b598e1631c7 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Fri, 10 Apr 2020 12:16:29 +0100 Subject: [PATCH 01/16] Negative Binomial and Gamma loss functions added --- notebooks/Loss function Calculations.ipynb | 658 +++++++ ...s functions fitted to simulated data.ipynb | 1613 +++++++++++++++++ pygom/loss/loss_type.py | 269 ++- pygom/loss/ode_loss.py | 40 +- pygom/utilR/distn.py | 100 + 5 files changed, 2675 insertions(+), 5 deletions(-) create mode 100644 notebooks/Loss function Calculations.ipynb create mode 100644 notebooks/Testing loss functions fitted to simulated data.ipynb diff --git a/notebooks/Loss function Calculations.ipynb b/notebooks/Loss function Calculations.ipynb new file mode 100644 index 00000000..3f46b706 --- /dev/null +++ b/notebooks/Loss function Calculations.ipynb @@ -0,0 +1,658 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Deriving derivative of loss class and testing markdown conversion for equation.#" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sympy as sym\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Negative binomial loss class ##" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 Logliklihood function" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + " x, mu , k = sym.symbols('x mu k')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Probability mass function (PMF) of negative binomial ${p}(x; \\mu,k) = \\frac{\\Gamma \\left(k+x\\right)}{\\Gamma \\left(k\\right)x!}(\\frac{k}{k+\\mu})^{k}(\\frac{\\mu}{k+\\mu})^{x}$ \n", + "This definition of the negative binomial distribution is often refered to as negative binomial 2. This parameterisation takes the mean (usually refered as $\\mu$, but in pygom $\\hat{y}$ as we are looking at a prediction) and $k$ (an overdispersion parameter). The variance = $\\mu+\\frac{\\mu^2}{k}$, some notation uses $\\alpha$, ($k=\\alpha^{-1}$). \n", + "See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{\\left(\\frac{k}{k + \\mu}\\right)^{k} \\left(\\frac{\\mu}{k + \\mu}\\right)^{x} \\Gamma\\left(k + x\\right)}{x! \\Gamma\\left(k\\right)}$" + ], + "text/plain": [ + "(k/(k + mu))**k*(mu/(k + mu))**x*gamma(k + x)/(factorial(x)*gamma(k))" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbpmf = (sym.gamma(k+x)/(sym.gamma(k)*sym.factorial(x)))*(k/(k+mu))**k*(mu/(k+mu))**x\n", + "nbpmf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Due to the this PMF containing gamma functions and a factorial it is easier to calculate the sum of it's logged terms than to log it as one object (you end up with infinities otherwise). " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "((k/(k + mu))**k, (mu/(k + mu))**x, 1/factorial(x), 1/gamma(k), gamma(k + x))" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbpmf.args" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle k \\left(\\log{\\left(k \\right)} - \\log{\\left(k + \\mu \\right)}\\right) + x \\left(\\log{\\left(\\mu \\right)} - \\log{\\left(k + \\mu \\right)}\\right) - \\log{\\left(x! \\right)} - \\log{\\left(\\Gamma\\left(k\\right) \\right)} + \\Gamma\\left(k + x\\right)$" + ], + "text/plain": [ + "k*(log(k) - log(k + mu)) + x*(log(mu) - log(k + mu)) - log(factorial(x)) - log(gamma(k)) + gamma(k + x)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logpmf_p1= k*(sym.ln(k)-sym.ln(k+mu))\n", + "logpmf_p2= x*(sym.ln(mu)-sym.ln(k+mu))\n", + "logpmf_p3= -sym.ln(sym.factorial(x))\n", + "logpmf_p4= -sym.ln(sym.gamma(k))\n", + "logpmf_p5= sym.gamma(k+x)\n", + "logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5\n", + "logpmf" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(-log(factorial(x)),\n", + " -log(gamma(k)),\n", + " k*(log(k) - log(k + mu)),\n", + " x*(log(mu) - log(k + mu)),\n", + " gamma(k + x))" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logpmf.args" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.special import gammaln\n", + "def nb2logpmf(x, mu,k):\n", + " '''\n", + " The log probability mass function (pmf) of Negative Binomial 2 distribution. \n", + "\n", + " Parameters\n", + " ----------\n", + " x: array like observation.\n", + " mu: mean or prediction.\n", + " k: overdispersion parameter (variance = mean(1+mean/k)). Note some notation uses $\\alpha$, ($k=\\alpha^{-1}$).\n", + " See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press.\n", + "\n", + " Returns\n", + " -------\n", + " log pmf:\n", + " math:`\\\\mathcal\\\\ln({p}(x; \\\\mu,k)) = \\\\ln(\\\\frac{\\\\Gamma \\\\left(k+x\\\\right)}{\\\\Gamma \\\\left(k\\\\right)x!}(\\\\frac{k}{k+\\\\mu})^{k}(\\\\frac{\\\\mu}{k+\\\\mu})^{x})`\n", + "\n", + " '''\n", + " # note that we input k the overdispersion parameter here\n", + "\n", + "\n", + " logpmf_p1= -gammaln(x+1) \n", + " logpmf_p2= -gammaln(k)\n", + " logpmf_p3= k*(np.log(k) - np.log(k + mu)) \n", + " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", + " logpmf_p5= gammaln(k+x)\n", + " logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5\n", + " return logpmf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our loss function is the negative of the logliklihood above." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "negloglikli=-logpmf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1st derivative of -Loglikelihood of negative binomial loss with respect to $\\mu$." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{k \\left(\\mu - x\\right)}{\\mu \\left(k + \\mu\\right)}$" + ], + "text/plain": [ + "k*(mu - x)/(mu*(k + mu))" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbfirstderv= sym.diff(negloglikli,mu).simplify()\n", + "nbfirstderv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1st derivative of -Loglikelihood of negative binomial loss with respect to yhat: \n", + "$\\frac{k(\\mu-y)}{\\mu(k + \\mu)} $" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{k \\left(- \\mu \\left(k + \\mu\\right) + \\mu \\left(\\mu - x\\right) + \\left(k + \\mu\\right) \\left(\\mu - x\\right)\\right)}{\\mu^{2} \\left(k + \\mu\\right)^{2}}$" + ], + "text/plain": [ + "-k*(-mu*(k + mu) + mu*(mu - x) + (k + mu)*(mu - x))/(mu**2*(k + mu)**2)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbsecderv = sym.diff(nbfirstderv,mu).simplify()\n", + "nbsecderv.simplify()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2nd derivative of -Loglikelihood of negative binomial loss with respect to yhat: \n", + "$\\frac{k(\\mu(k + \\mu) + \\mu(y -\\mu) + (k + \\mu)(y - \\mu)}{\\mu^{2}(k + \\mu)^{2}} $" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(k, mu**(-2), (k + mu)**(-2), mu*(k + mu) - mu*(mu - x) - (k + mu)*(mu - x))" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbsecderv.args" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2. Gamma loss class in terms of mean and shape" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + " a, s, x, mu= sym.symbols('a s x mu')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Probability density function (PDF) of the gamma distribution is $\\frac{1}{s^a\\Gamma(a)}x^{a-1}e^{-x/s}$. However we need this in terms of mean (here $\\mu$), luckily we can subistitute in $s=\\frac{\\mu}{a}$ to get our likelihood function. But lets start with a log tranformation of the pdf.\n", + "\n", + "See Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). Princeton University Press." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{s^{- a} x^{a - 1} e^{- \\frac{x}{s}}}{\\Gamma\\left(a\\right)}$" + ], + "text/plain": [ + "s**(-a)*x**(a - 1)*exp(-x/s)/gamma(a)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pdf_gamma = 1/(s**a*sym.gamma(a))*(x**(a-1)*sym.E**(-x/s))\n", + "pdf_gamma" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(s**(-a), x**(a - 1), 1/gamma(a), exp(-x/s))" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pdf_gamma.args" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - a \\log{\\left(s \\right)} + \\left(a - 1\\right) \\log{\\left(x \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)} - \\frac{x}{s}$" + ], + "text/plain": [ + "-a*log(s) + (a - 1)*log(x) - log(gamma(a)) - x/s" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "log_pdf_gamma_p1 = -a*sym.ln(s)\n", + "log_pdf_gamma_p2 = (a-1)*sym.ln(x)\n", + "log_pdf_gamma_p3 = -sym.ln(sym.gamma(a))\n", + "log_pdf_gamma_p4 = -x/s\n", + "log_pdf_gamma= log_pdf_gamma_p1+log_pdf_gamma_p2+log_pdf_gamma_p3+log_pdf_gamma_p4\n", + "log_pdf_gamma" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - a \\log{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\log{\\left(x \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)}$" + ], + "text/plain": [ + "-a*log(mu/a) - a*x/mu + (a - 1)*log(x) - log(gamma(a))" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s_in_terms_mu_a = mu/a\n", + "log_pdf_mu_a_gamma = log_pdf_gamma.subs(s,s_in_terms_mu_a) \n", + "log_pdf_mu_a_gamma" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(-log(gamma(a)), (a - 1)*log(x), -a*log(mu/a), -a*x/mu)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "log_pdf_mu_a_gamma.args" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "- a \\log{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\log{\\left(x \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)}\n" + ] + } + ], + "source": [ + "sym.print_latex(log_pdf_mu_a_gamma)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.special import gamma, factorial, gammaln\n", + "def gamma_mu_shape_logpdf(x, mu,shape):\n", + " '''\n", + " The log probability density function (pdf) of gamma distrbution in terms of mean and shape. \n", + "\n", + " Parameters\n", + " ----------\n", + " x: array like observation.\n", + " mu: mean or prediction.\n", + " v: variance.\n", + " See Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). Princeton University Press.\n", + "\n", + "\n", + " Returns\n", + " -------\n", + " log pdf, :math:`\\\\mathcal\\\\ln({p}(x; \\\\mu,a)) = - a \\log{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\log{\\left(x \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)}`\n", + "`\n", + "\n", + " '''\n", + "\n", + " logpdf_p1= -gammaln(shape)\n", + " logpdf_p2= (shape - 1)*np.log(x)\n", + " logpdf_p3= -shape*np.log(mu/shape)\n", + " logpdf_p4= -shape*x/mu\n", + " logpdf = logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4\n", + " return logpdf" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle a \\log{\\left(\\frac{\\mu}{a} \\right)} + \\frac{a x}{\\mu} - \\left(a - 1\\right) \\log{\\left(x \\right)} + \\log{\\left(\\Gamma\\left(a\\right) \\right)}$" + ], + "text/plain": [ + "a*log(mu/a) + a*x/mu - (a - 1)*log(x) + log(gamma(a))" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "negloglikli_gamma_mu_a = -log_pdf_mu_a_gamma\n", + "negloglikli_gamma_mu_a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1st derivative of -Loglikelihood (gamma loss) with respect to $\\mu$." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a}{\\mu} - \\frac{a x}{\\mu^{2}}$" + ], + "text/plain": [ + "a/mu - a*x/mu**2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a \\left(\\mu - x\\right)}{\\mu^{2}}$" + ], + "text/plain": [ + "a*(mu - x)/mu**2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "gammafirstderv= sym.diff(negloglikli_gamma_mu_a,mu)\n", + "display(gammafirstderv,gammafirstderv.simplify())" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\\frac{a \\left(\\mu - x\\right)}{\\mu^{2}}\n" + ] + } + ], + "source": [ + "sym.print_latex(gammafirstderv.simplify())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2nd derivative of -Loglikelihood (gamma loss) with respect to $\\mu$.: " + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a \\left(- \\mu + 2 x\\right)}{\\mu^{3}}$" + ], + "text/plain": [ + "a*(-mu + 2*x)/mu**3" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a \\left(- \\mu + 2 x\\right)}{\\mu^{3}}$" + ], + "text/plain": [ + "a*(-mu + 2*x)/mu**3" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "gammasecderv = sym.diff(gammafirstderv,mu).simplify()\n", + "display(gammasecderv,gammasecderv.simplify())" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\\frac{a \\left(- \\mu + 2 x\\right)}{\\mu^{3}}\n" + ] + } + ], + "source": [ + "sym.print_latex(gammasecderv)" + ] + } + ], + "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.8.1" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/Testing loss functions fitted to simulated data.ipynb b/notebooks/Testing loss functions fitted to simulated data.ipynb new file mode 100644 index 00000000..c73591c1 --- /dev/null +++ b/notebooks/Testing loss functions fitted to simulated data.ipynb @@ -0,0 +1,1613 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Testing Negativ Binomail and Gamma loss Data fitting and parameter estimation within PyGOM\n", + "\n", + "This is an example of parameter fitting with an SIR model." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import Transition, TransitionType, SimulateOde, SquareLoss, PoissonLoss, NormalLoss, NegBinomLoss, GammaLoss\n", + "import numpy as np\n", + "import scipy.integrate\n", + "import matplotlib.pyplot as plt\n", + "import copy\n", + "\n", + "from scipy.optimize import minimize" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Generate some data for fitting\n", + "\n", + "# Standard SIR model with 2 parameters\n", + "# construct model \n", + "states = ['S', 'I', 'R']\n", + "params = ['beta', 'gamma', 'N']\n", + "transitions = [Transition(origin='S', destination='I', equation='beta*S*I/N', \n", + " transition_type=TransitionType.T),\n", + " Transition(origin='I', destination='R', equation='gamma*I', \n", + " transition_type=TransitionType.T)]\n", + "model = SimulateOde(states, params, transition=transitions)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# initial conditions \n", + "N = 1e6\n", + "in_inf = 2\n", + "init_state = [N - in_inf, in_inf, 0.0]\n", + "# time \n", + "t = np.arange (0 , 51 , 0.25)\n", + "# deterministic parameter values\n", + "param_evals = [('beta', 3.6), ('gamma', 0.2), ('N', N)]\n", + "model.parameters = param_evals\n", + "model.initial_values = (init_state, t[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# run 1 simulations\n", + "data = model.integrate(t[1:])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Data over 100 days, with observations from every day for infected and removed populations." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(t,data[:,0], 'bo') # infected observations\n", + "plt.plot(t,data[:,1], 'ro') # infected observations\n", + "plt.plot(t,data[:,2], 'go') # removed observations (recoverd/died)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Adding random noise to produce Continuos Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our data needs to be have some noise so lets put it through a function for randomisation using the gamma distribution." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def runif_noise(x,noise_prop):\n", + " '''\n", + " Takes x and adds noise on the uniform distribution.\n", + " '''\n", + " i_len,j_len = x.shape\n", + " ans = copy.deepcopy(x)\n", + " for i in range(i_len):\n", + " for j in range(j_len):\n", + " ans[i,j]=x[i,j] + x[i,j]*np.random.uniform(low=-noise_prop,high=noise_prop,size=1)\n", + " \n", + " return ans" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([9.99998e+05, 2.00000e+00, 0.00000e+00])" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data[0,:]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":4: RuntimeWarning: invalid value encountered in true_divide\n", + " (noised_data-data)/data\n" + ] + }, + { + "data": { + "text/plain": [ + "array([[ 0. , 0. , nan],\n", + " [-0.26594371, 0.0481614 , 0.14354852],\n", + " [ 0.18044689, -0.21459589, -0.23607263],\n", + " [-0.22631835, -0.25986512, 0.00977265],\n", + " [ 0.08317535, -0.24033984, -0.13717155],\n", + " [ 0.01893378, -0.30765339, -0.20936384],\n", + " [-0.1927195 , -0.20495292, 0.14883087],\n", + " [-0.31513136, 0.29092017, 0.20333613],\n", + " [-0.0144959 , -0.15434097, 0.15017585],\n", + " [-0.06943103, -0.04553612, 0.24527238],\n", + " [ 0.1423363 , -0.26289285, -0.27731679],\n", + " [ 0.22902387, -0.11970823, -0.0786823 ],\n", + " [ 0.24507763, 0.13939913, 0.19873885],\n", + " [ 0.0851626 , 0.33156697, -0.02946794],\n", + " [-0.18589297, 0.28048003, 0.15186529],\n", + " [ 0.10976604, -0.27140908, -0.29451267],\n", + " [-0.02481169, -0.01567338, 0.12217416],\n", + " [-0.00554871, -0.31163176, 0.09909475],\n", + " [ 0.20449806, -0.13271217, -0.21380146],\n", + " [ 0.23288222, -0.26931907, 0.17116807],\n", + " [-0.16775002, -0.08171666, 0.3285523 ],\n", + " [-0.13957109, -0.00980709, -0.0315168 ],\n", + " [ 0.06701958, 0.12872299, -0.03394576],\n", + " [-0.10946453, 0.20814074, -0.19773507],\n", + " [ 0.01024636, -0.18041067, -0.23682284],\n", + " [-0.07439538, 0.25262383, -0.17858645],\n", + " [ 0.29102576, 0.1511979 , -0.14440452],\n", + " [-0.11485163, 0.04940554, 0.06448306],\n", + " [ 0.10676958, 0.21332199, -0.10266298],\n", + " [ 0.05285174, 0.14572103, -0.30224747],\n", + " [ 0.21323456, -0.11097107, -0.09723039],\n", + " [-0.26727707, 0.18230789, -0.04970821],\n", + " [ 0.16396675, 0.30519932, 0.19783618],\n", + " [-0.29474402, 0.26031346, 0.15008278],\n", + " [ 0.1983954 , -0.09186773, 0.1033981 ],\n", + " [ 0.01819894, -0.30503091, -0.00801638],\n", + " [ 0.18546865, 0.17688293, 0.07902597],\n", + " [ 0.0076256 , -0.30361511, -0.15894734],\n", + " [-0.14879804, -0.19371648, -0.20285748],\n", + " [ 0.02042512, -0.03584361, 0.02819072],\n", + " [ 0.23491568, -0.06869137, -0.17772354],\n", + " [-0.06566397, -0.06776337, -0.12467524],\n", + " [-0.24064783, -0.02981388, -0.20090267],\n", + " [-0.2546167 , -0.09699615, 0.33171511],\n", + " [-0.28714369, -0.15456429, 0.17458153],\n", + " [ 0.30123993, 0.18002521, 0.1692988 ],\n", + " [ 0.02128767, -0.15262815, -0.32506278],\n", + " [ 0.33296938, 0.237988 , -0.30015583],\n", + " [-0.2934129 , 0.08130536, -0.09999738],\n", + " [-0.3235725 , 0.13686141, -0.2596026 ],\n", + " [ 0.15582601, -0.02119342, 0.0201688 ],\n", + " [-0.09663488, -0.00329313, -0.0186065 ],\n", + " [-0.13049885, -0.2873186 , 0.15998342],\n", + " [ 0.1820132 , 0.15728375, -0.17590421],\n", + " [ 0.32023337, -0.29931336, -0.07075369],\n", + " [-0.2687179 , 0.11859697, 0.19943461],\n", + " [-0.15646938, 0.32058394, 0.11942069],\n", + " [ 0.01135593, 0.20676602, -0.19312968],\n", + " [-0.12103279, 0.27442481, -0.06271944],\n", + " [ 0.16266687, 0.31851177, 0.00352883],\n", + " [-0.08580615, 0.18960581, 0.16840495],\n", + " [-0.08982207, 0.03192396, 0.1188008 ],\n", + " [-0.20494301, -0.01120558, 0.25235198],\n", + " [-0.1467698 , 0.22918715, -0.1282447 ],\n", + " [ 0.17906087, -0.10461238, 0.13495474],\n", + " [ 0.17601782, -0.03623687, -0.25142906],\n", + " [ 0.30978103, 0.00397469, 0.22194208],\n", + " [ 0.25752416, 0.1042392 , 0.25591297],\n", + " [-0.13772319, -0.11275306, 0.01176822],\n", + " [-0.1576899 , -0.07936526, -0.14969428],\n", + " [ 0.22779235, 0.15750085, -0.28242108],\n", + " [-0.0992169 , -0.24829993, -0.24564635],\n", + " [ 0.2802134 , -0.26679643, 0.14145995],\n", + " [-0.19666873, 0.10925674, -0.15420511],\n", + " [-0.15718523, -0.04667504, 0.10463 ],\n", + " [ 0.23934475, 0.23012487, 0.19921085],\n", + " [-0.05472834, -0.01380446, -0.2970063 ],\n", + " [ 0.10511899, -0.21625187, -0.00291365],\n", + " [-0.25868477, -0.10864835, -0.10815295],\n", + " [-0.0549668 , -0.26682451, 0.30208219],\n", + " [-0.2252228 , -0.28258864, 0.24447319],\n", + " [ 0.32262681, 0.24986113, -0.26776005],\n", + " [-0.28439645, 0.17894896, 0.04479451],\n", + " [ 0.23324145, 0.14693671, 0.03221976],\n", + " [ 0.19536078, 0.29770609, 0.28112025],\n", + " [ 0.26628981, -0.05904756, 0.25696101],\n", + " [ 0.26286499, -0.21866198, 0.25475143],\n", + " [-0.17818083, 0.21188372, 0.2483309 ],\n", + " [ 0.17844389, 0.08694361, 0.28079217],\n", + " [-0.2312997 , 0.06568179, 0.13610579],\n", + " [ 0.2905747 , -0.25361048, -0.05708808],\n", + " [ 0.22593571, 0.09708349, 0.07385119],\n", + " [ 0.01186936, -0.15807059, -0.08762729],\n", + " [-0.00639177, 0.0221159 , -0.03221789],\n", + " [-0.11634133, -0.23084855, -0.08819899],\n", + " [ 0.10440324, -0.2578205 , 0.04979053],\n", + " [ 0.19253324, 0.08374047, -0.32555527],\n", + " [-0.31328116, -0.31449333, -0.29090413],\n", + " [ 0.11266601, 0.02762068, 0.05099049],\n", + " [-0.009882 , 0.11925011, 0.29849163],\n", + " [ 0.07112188, -0.17385365, 0.06267588],\n", + " [-0.23180648, -0.02778307, -0.30315784],\n", + " [-0.10563222, 0.06910103, 0.2532015 ],\n", + " [ 0.07369744, 0.26329815, 0.15720732],\n", + " [ 0.12417477, 0.245335 , -0.04359579],\n", + " [-0.01950269, -0.22894254, 0.27712502],\n", + " [ 0.04573258, -0.04995886, 0.31596549],\n", + " [ 0.16523415, -0.17750199, -0.154256 ],\n", + " [-0.06935528, -0.11561912, -0.32852905],\n", + " [ 0.17573865, -0.16438354, 0.08092944],\n", + " [-0.14557532, -0.16221617, 0.20846123],\n", + " [-0.1530618 , 0.00607467, 0.1679275 ],\n", + " [ 0.2915459 , 0.03303514, 0.01665417],\n", + " [ 0.25416671, -0.13892646, -0.32628175],\n", + " [ 0.18898644, 0.21485992, -0.16411458],\n", + " [-0.31186503, -0.23293792, 0.24676476],\n", + " [ 0.01727794, -0.16295204, 0.29225053],\n", + " [-0.30057741, -0.19557768, 0.28403295],\n", + " [-0.08805621, -0.21801336, -0.14952844],\n", + " [ 0.17080778, -0.19999893, 0.10857179],\n", + " [-0.01016595, 0.03945573, -0.23341481],\n", + " [ 0.0889063 , -0.22661675, 0.27247754],\n", + " [-0.10284494, -0.21721198, -0.01215395],\n", + " [ 0.04750522, -0.05609498, -0.11760032],\n", + " [-0.12049032, 0.16369776, 0.22946754],\n", + " [-0.3259247 , 0.14942894, 0.01034819],\n", + " [ 0.30482666, 0.10876203, 0.18606517],\n", + " [-0.22421853, -0.1229635 , 0.31979197],\n", + " [-0.31666275, 0.18239926, -0.31941235],\n", + " [-0.15058556, 0.2803648 , 0.29741955],\n", + " [ 0.27943625, -0.31952391, -0.11504683],\n", + " [ 0.02835105, -0.15542857, -0.12654592],\n", + " [ 0.25274379, 0.06784749, -0.02814774],\n", + " [ 0.18619024, -0.15448604, -0.27449163],\n", + " [-0.19728779, 0.02537731, -0.00569949],\n", + " [-0.21443474, -0.01553967, 0.091896 ],\n", + " [-0.26827219, -0.05445831, -0.02413247],\n", + " [ 0.00827749, 0.1737784 , -0.02126288],\n", + " [ 0.23937747, 0.25076279, -0.00298444],\n", + " [-0.12216854, 0.29956893, 0.2265178 ],\n", + " [ 0.15886145, 0.1952358 , -0.10230103],\n", + " [-0.16707728, -0.11592906, 0.23063125],\n", + " [ 0.08048473, -0.28616788, 0.27649409],\n", + " [-0.2399056 , 0.17466809, 0.2670509 ],\n", + " [ 0.01100893, -0.22544906, 0.03502344],\n", + " [-0.24534992, -0.0282792 , 0.04012958],\n", + " [-0.32417314, 0.30503388, 0.07024417],\n", + " [-0.30165476, -0.03131702, -0.11390332],\n", + " [ 0.11602546, 0.17258092, 0.27320442],\n", + " [-0.01679539, 0.17988321, 0.07326227],\n", + " [ 0.32585914, -0.31318578, 0.21703063],\n", + " [-0.25118099, 0.08755176, 0.1418994 ],\n", + " [ 0.25308867, 0.27702219, -0.26432973],\n", + " [ 0.1694537 , 0.15167072, -0.24991087],\n", + " [ 0.32780948, -0.30710299, -0.16902237],\n", + " [ 0.25018489, -0.24231413, 0.03174931],\n", + " [ 0.05986629, 0.03359792, -0.30558626],\n", + " [-0.30815473, -0.11973154, 0.01174757],\n", + " [-0.13523555, -0.02621417, 0.18494329],\n", + " [ 0.19637621, -0.06536179, 0.16160518],\n", + " [ 0.16124011, 0.12639132, -0.02431527],\n", + " [ 0.19221785, 0.24196546, 0.00068597],\n", + " [ 0.08134284, 0.31422214, -0.20704816],\n", + " [ 0.1727692 , 0.02115635, -0.13793911],\n", + " [-0.28248369, 0.05719562, -0.09881328],\n", + " [-0.15519892, 0.30149671, 0.30585306],\n", + " [ 0.18343869, -0.18022277, 0.23596179],\n", + " [-0.09597099, 0.31572377, -0.02601189],\n", + " [-0.23722386, -0.20593368, -0.01834659],\n", + " [ 0.21902069, 0.24623962, -0.19736678],\n", + " [ 0.02226348, 0.21272945, -0.30751679],\n", + " [-0.24202336, -0.2567437 , 0.14965649],\n", + " [-0.25945811, 0.28880295, 0.33275319],\n", + " [ 0.28975049, 0.04492393, 0.24388337],\n", + " [-0.09991367, 0.11365879, -0.30462007],\n", + " [-0.33098441, -0.20249934, -0.32534145],\n", + " [-0.00702099, -0.2097019 , -0.11255923],\n", + " [ 0.23478388, 0.14543586, 0.32737759],\n", + " [-0.32148961, 0.03430904, -0.23725884],\n", + " [-0.15295436, -0.23766421, 0.16057446],\n", + " [ 0.24874516, 0.02814334, 0.05567249],\n", + " [ 0.18373544, 0.05456167, -0.00065203],\n", + " [ 0.29179694, -0.02776448, -0.27429118],\n", + " [ 0.19373542, -0.10868194, 0.10012632],\n", + " [-0.05908267, -0.20556755, -0.06223371],\n", + " [-0.08392523, -0.13577942, -0.14284998],\n", + " [ 0.10779361, 0.11329162, 0.17968936],\n", + " [-0.04555323, 0.22342669, 0.302655 ],\n", + " [ 0.31417606, 0.32366651, -0.24461707],\n", + " [ 0.25052832, 0.04730799, 0.0135891 ],\n", + " [ 0.24008863, 0.11260373, 0.10348191],\n", + " [ 0.26464085, -0.16812188, -0.23981266],\n", + " [-0.23031692, 0.25901614, 0.25404338],\n", + " [-0.08783901, 0.21082491, 0.09234899],\n", + " [-0.12828791, 0.23402825, -0.13942016],\n", + " [ 0.17317795, 0.06544127, -0.32470743],\n", + " [-0.01350832, -0.20846687, 0.06141013],\n", + " [ 0.08516377, -0.27381567, 0.19523863],\n", + " [-0.2885919 , 0.04913673, 0.27292814],\n", + " [-0.14942594, -0.11490962, -0.27067257],\n", + " [ 0.0428627 , 0.22205546, 0.16590721],\n", + " [ 0.16898513, -0.03668338, -0.06368085],\n", + " [ 0.30915912, -0.13559047, -0.05790722],\n", + " [ 0.28353642, -0.20041566, -0.00223925]])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "noised_data = runif_noise(data,1/3)\n", + "#we stil want the first row from data\n", + "noised_data[0,:] = data[0,:]\n", + "(noised_data-data)/data" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEDCAYAAAAlRP8qAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO2dfZAcZ33nv78drZJdy17jkZwKtnfGUALOh2wn1gEJuZxBV4clYnyowh2+kbInY7YkASVXHRcMWxXju5pK4F5iXWHJt0dMxO7EFHexjcECh9OFQHi5s5zYXhvH4DM7i84UklZYRt4lknZ/90dPj3p7n6f76fe336dqa+elp+fpnu5vP/17JWaGIAiCUHwGsh6AIAiCEA8i6IIgCCVBBF0QBKEkiKALgiCUBBF0QRCEkiCCLgiCUBIyFXQiup+IjhPRM4bL/wsi+j4RPUtEf5b0+ARBEIoEZRmHTkS/DeAMgM8z85t9lt0I4IsA3snMPyOiy5n5eBrjFARBKAKZztCZ+ZsATjlfI6LXE9HXiOgJIvoWEb2p99YHAdzLzD/rfVbEXBAEwUEebeiTAD7CzDcA+CiAA73X3wDgDUT0bSL6HhHdlNkIBUEQcsiarAfghIjWAfhNAP+diOyXf6n3fw2AjQBuBHAlgG8R0ZuZ+eW0xykIgpBHciXosO4YXmbm6xXvHQPwPWY+B+BHRPQ8LIF/PM0BCoIg5JVcmVyY+RVYYv0+ACCL63pvPwzgHb3X18MywbyYyUAFQRBySNZhiw8A+C6ANxLRMSL6AIAWgA8Q0VMAngVwS2/xxwDME9H3AfwlgH/LzPNZjFsQBCGPZBq2KAiCIMRHrkwugiAIQngyc4quX7+em81mVl8vCIJQSJ544omTzLxB9V5mgt5sNnH06NGsvl4QBKGQEFFX956YXARBEEqCCLogCEJJEEEXBEEoCSLogiAIJUEEXRAEoSSIoAuCUCg6Mx0072li4O4BNO9pojPTyXpIuUEEXRCEwtCZ6WD8y+Ponu6Cweie7mL8y+MrRL3Kgi+CLghCYZg4MoGFcwsrXls4t4CJIxMAzAS/zIigC0IBqPKs08nc6TnP1/0Ev+yIoAtCzqnKrNPkojU6Mqr8rP26n+CXHRF0QTAgyxlyFWadphet9pY2hgeHV7w2PDiM9pY2AH/BNxlHke+ERNAFwYesZ8i62WX3dLeQoqPC9KLV2tTC5M2TaIw0QCA0RhqYvHkSrU0tAP6C70XWv3McZFYPffPmzSzFuYQi0Lynie7p1fWQGiMNzN4x6/v5zkwHE0cmMHd6DqMjo2hvafcFKMr32wwPDq8QtSIycPcAGKu1iEBYvms50LrC7u+ov3NaENETzLxZ9Z7M0IVKY3KLHcUuG8esTzXrdFIG80tUU4mT1qYWZu+YxfJdy5i9Y9b4QlcG+7sIulBZTMU2itjoTAljD40Zi7rTzKAjrOiYXNDSsCtHMZXERRwXlaxt8CLoQmUxtdtGERud0C7xUv/iYSIC9qxTJ+phZrKqC9qOB3dg/afX98eQll3ZzzaeBlEvKnmwwYsNXagspnbbzkwH+766D/OLVk/y+lAd+7fuj2SXtakP1bF4fnHFhcXLJm6LhunyYcdmr3PiyEQh7MpxEcXfkZYNXmzogqDA5BbbFlBbzAFg8fyi8Xf42b/nF+cDhSTGOZP1MtPYYyiDXTkIXvZ3vzupPOwrEXQhF4SxPUa1V5rcYkeNAbcFuEa1QGPzEoGwTj83fmYae5Ya5rNpkKa92sSckod9JYIuZI7fyaI6ceOwV6pmu2PXjWHiyET/u3QmCdNZl30Lv8RLINCK94YHh1Efqis/l4YI+N092CaHrJ2VKtK2V5tc2POwr8SGLmSOl+2xvaWttBkPrRlaYQZxfiasvVJlnyaQ0s5u8j1e67O3DUBsNvEwuP0DqjFEjaMPOh6T70o7ZjyIvyXpfeVlQxdBFzLH62QZHRn1dCqqPhM0EcVGJxJuUTcVXFPRcYvAto3bcPiHhxMRBed3XTZ0GQDg1OKpFY+TFm2vsZle3OJMRDIhT0lH4hQVco2X7TGoQymKqUL3XfaMOqgT0tRJ5rSJt7e0ceipQ4mYEtxmivnFecwvzvcfL55fxNT2qUh2+SgE8Vekba/OgznFBBF0IXO8TpYgJ2jUE0z3XfYsLKgTMozoJFmIS7XuoN+TpCMySJRI2gKbhzh5E0TQhczxOln8HHc2BMLYdWORTrC4RSLM+pIMfTNZh9cySTsig1wAsxDYuKKLksRX0InofiI6TkTPaN5vEdHTvb/vENF18Q8zPjodoNkEBgas/53iFFIrNbqTxT5x/WAwDv/wcOQxBBUJrxlrmPUlaUowWUdWdw9A8AtgEQQ2bXydokT02wDOAPg8M79Z8f5vAniOmX9GRFsBfJKZ3+r3xVk4RTsdYHwcWHAck8PDwOQk0JJjIXO8IgT8Mi6B5BxiOuLM2kxynV7rduL3PWk4ItOMqImbtMYeOcqFiJoAvqISdNdyrwHwDDNf4bfOLAS92QS6Ck1oNIDZ2VSHIrjwE7LOTAe7Ht6Fc8vntOtIO+IgqciHJIVBF+Vi8j1htrfIAh2EJC/EbtIU9I8CeBMz3655fxzAOACMjo7e0FWpqyGdDjAxAczNAaOjQLvtP8seGAB0m5tR9KbQw0QsdDHTQDY1was2Yw0qWmmKXFSSqlmfxCQjlbBFInoHgA8A+JhuGWaeZObNzLx5w4YNob/LNp10u5YQd7vWcz97+KjGPEgktvSsMXEGtja1cPL3T4LvYkxvn8484iDp0Lk8VO9zEtQnUJTWeXHs5zzUcQFimqET0bUAHgKwlZl/YPLFUUwuYU0nnQ6wc6d6Ni5ml2zJU+KGKUnPQIu4T5yknfwTljj2s24dNaphmZdjvbtKdIZORKMAHgSw01TMozKnuejpXrdptfSmFb/PCmriiksuSuKGE3fjiRrV+jPQOGbReZn1hUV3pzJAA6ndZSTdkcpGF167xEup3l2ZhC0+AOC7AN5IRMeI6ANEtJuIdvcW+QMAdQAHiOhJIkrc06kznehed9LQNH0x+aywkjhNAkVJ3HDjjJVf4iUAiO3kzUP1vih4iVzY/RNkApFGRyob9/Grqq6ZhrmpkLVcooQfSuhifBTdJOBFECdZktEuRXEq6ujMdDD20Fj/Yuck6P4Juj+C1NKJez8naW4qXS2XVssS4EbDcmg2GuaCHOWzwkrC3Kpm3XPRhKB3HkmZRvJ812L6O7Y2tbDMagELun+COlmD1NKJez9ndXdVyBl6GMKEOQrhkn10M6+izDiDbleZ71RUJDVT9iPorDfL3yXJY710M/SghA1zrDpeM9XOTAdnzp5Z9RkvR2ZRwtiCzriL6NCNQtDfMa79E3TWm+XvktXdVSVm6JIhGg7dDEfV2Nh+3at5cpnD2PKUAJQ0YX7HOPZPmFlvGX+Xyje40GWIEgHL+dGR3KE7cXX43coWxTRRFNNQVmRtyiibQAel8iaXKGGOVSaoA8fPyZXULXDcjtY0bpeL4BzWkbUpI80Ki0X7nSoh6O22FZroZHjYel3QoztxwzY2TkIok0qPT1I48pbSH5Q8R9+YYiLURfydKmFyASTKJSyqW1wg28bGTopixnGSxpjFNKHH1KTm5UNat3ZdZvu29DZ0Eev0yYtgFMXR6iTpMYsPwBvTC6qpDyntfVtqG7qEJGZDXrrFFDE9PukxFyU8NCtMw1JNf4887dvCC/rExMo0fsB6PpGP/Vtp0nAoZemgC7t9SY85jsxV1bYVzUGow/SCatrPFshPwbTCC3rYyotCsqTlUMrKQRdl+5Iec9Q7ANW27Xp4F2770m2FchDqML2gqn4nXUDAAA3k4kJXeBu6JA3lkyI6K4OQ5+2LakM36d9qk4ft9UPn2A/jA/Lrywokb1MvtQ1dQhLzSVa1vNMyC+S5VnnUO4Ag25CH7fVCdycFIJQPKC9lcnUUXtClemL8xCGKutt7BicmtGHNIGG2N+/O2ChO6yDbkJft1ZGEg9i5b+OqJBkXhRd0wBLv2VkrjX92VsQ8Cn4FuUyFz8uhlJT9NczJG/YiUOaCXNs2bgOBVrw2ODCItbW1K14rwvYmfSeVtwt7KQRdCI5OnHWiuO+r+wIJn7s9m5skbku9Tl739u59dC+a9zSx48EdoWZwZciWdNOZ6WD9p9fj4NGDK+KvCYTbf/123H/L/b7bm7dImKQFN28X9sI7RYXgeDnNdj64M9aCXEB6yT9Bq0N6kefEpCTwc/aZ/M55TGhKY0xpJ9mV2inqpNOxol4GBqz/klykxss0EXdBLiC921LdbAlAIDEH8m8bjhvVMeHE5HfOY0JTGndSeUmyA0ok6JIxao6XaSLuglxAuNvSMLfuupP31OIp388GGVucY84LfoJt8jvr1tE93c10f4QV3CL+nr6CTkT3E9FxInpG8z4R0X8hoheI6Gki+vX4h+mPZIya4zVjdtu+a1Trz7rCOsWCzpKiJu24T94gs+2wM7gkEqnSFBSvfWT6O3uto2iJSEWstAiYzdD/FMBNHu9vBbCx9zcO4GD0YanxMqlUJWM0jpPcb8bc2tTqL2N3a59fnAczoz5UD3XrGmSWpLt1H3toLLbtdTM8OIzp7dOhb5njNjfELSh+x41uH9WH6sa/s99+tvdHVjPfIN+blPko6W03cooSURPAV5j5zYr3/iuAbzDzA73nzwO4kZl/4rXOoE5R26TinIUPD1+IOa9CxmicDh4/R06WmZBeVe7i2t5tG7fh8A8Px+bIitvxG3b/Ryl3HFebuIkjE56ZpsODw6k7ToOeO0k48uM6fyOXz/UR9K8A+CNm/uve8yMAPsbMnmodVND9BFsl+IODwCWXAKdOlaOsbpoim2VZWr/U8zymm0f9bdxiqtt+v76dKsEYWjOE+cX50GMLg25/1KjWv+vzG0uc0SNBf58kzrW41pl0lAspXlNeJYhonIiOEtHREydOBPoSP5OKO2O0Xrf+z8+Xx0maZrp5lgkTfrfueUw3jxKPrDKvuBN7bLz2v85MoBJzINn9qNofgwODSjFXjWXvo3ux88GdsZmcgp47ScSXp3H+xiHoxwBc5Xh+JYCXVAsy8yQzb2bmzRs2bAj0JSZ9QZ0Zo+vWAWfPrly26E7SsCKrs9t52fOy7hs5efOksk4GkM+QwijhcSohZvAqUdftf/t3NC2oZZPkfnTvj/pQHUTqi5R7LJ2ZDu47et+qO8QoNuyg504S4Y5pTJLiEPRHAPxeL9rlbQBO+9nPwxC0CFcZnaRhw/9UzrW9j+71dLplnQnZ2tTCofceylUWnh9hw+N0MzQGG2Vm2r9jEAiU+H507o91a9fh7NJZ5XLu33TiyITWhxJ2Nhvm3Ik7vjyNSZKvDZ2IHgBwI4D1AH4K4C4AgwDAzPeRddn9DKxImAUAu/zs50C4TNEgreZMnKRFbF0X1K4Yhy0zS/LS6i5JothWw8zMbfiu9LLEvRzd09unV/ymXstGOT7zcCzFMYbS9xRV4RcV4/d+WTDti2iTZsp70idYHk5gE6JEPwT9fW3SvnAHuWjpliUQprZP5fI3TJPKpP478SurW5VEJJ19Lmv7dNKJG3GsP6146SjmLd3vVR+qax3LWZitgpgbVMsSCLs37y6smKd1LJV2hu7HwIAV/eKGyHKqlgXd7G/sujEceupQKjHtKpIOwYwjjDBvhaZUeI0TQD8m3DaxNUYamd2pBDlO0ri7SusObu+je1c5eaMcS5U0uThR2conJsqfiGSjO3DjSiQJI3xJx7lHXX+eW8y5KYppKU+kdcHuzHS0FUzDHkuVFnSdrXxsDDh0qPw29KQJK3xxC6Zb1M6cPRMpmSbLxCohedK6YHs5rcMeS5W0odvobOWHD0vrujgImywRZwiXyl7+yt+/EqnDTt460QjxklaSntf6kjiWSi/oXvHo0rouOmGFL844d1Vizrnlc7h47cWh15+3TjRCvKR1wdatL6k8gNILukmGaVHJQ73mKMIXV+KGbhZ0avFU6PVnnVhVJbI4jtO6YKcdsVN6QQ+aYVoU8lKvOQ/C5zXbiiIWeepEEyd5mAg4x5LFcZzWcav6nqntUzjw7gOxfo9N6Z2iQDEzQr3ozHQw9tBYIpmeRYyYUEUsEKhfDyWucLEykLdwzDidk0U8dsNQaacoUC5buX1CmlatC7PurGf9QXF3WXKKeJwFnvJE2Fl20MYNSc/m43JOFvXYjZtKCHqZ8GvmG8Wpk8cmv6bY5pHGSMM3FT6P5XdtTAQ0ingFEdA0RDIu52SRj904EUEvGF5iVIR6zUljMta8hh6aCmiUFn1BBDQNkYzLOVmGYzcORNALhldtliLUa04av7HmOfTQVEB1IrXES74z6CACmpZIDq0Z6j8O0sPUSdrHbp4cy05E0AuG7oQ89N5DhajX7CbuE0MXJgYg96GHpgLqJVJ+M+gg0R1Ji6R9R+LM6F08vxhqXVE7RgU5BvNsrxdBLxhJhlulHYKYxImhCxPjuzgXoYde4mEqoFFb9JmGYyZ9gY/TpBP22A1zDObZXl+JsEUhnxSpAFYc+IUMBgkpTDJ01f09SYUC5qFeTphjMOtxVz5ssYrk1cbnpIiOrCj71W9mF2SWmVaLviSTq/LgswlzDOZh3DpE0MPS6Vh97gYGrP+d/Ahmnm18TvJ8YqgIsl9Vwm8iHkEENA9ZujZhLnR5qJcT5hjMw7h1iMklDDnvXxfmNjKLLLu8ZS36Ybpfdds1tGYoUknfvBLld8w6uzPs2LMcd6XroSeCSQfqDAnSkBfIVlizPqGDYGo71Ql/faiOxfOLhbmAmVJ0X0iRjkGgYoKeeN2WTgfYsUP9Xk7613kV1VcJSNFPyLQw3U9ewj+1fapQ4mFC1k7CqhHZKUpENxHR80T0AhHdqXh/hIi+TERPEdGzRLQr6qDDYFtCul2rX2i3az2Pzbxtf4GOnNTk9QprC5KokmfnZBaY2k697LJlrOCYRrx63h38ecFX0ImoBuBeAFsBXAPgViK6xrXYhwB8n5mvA3AjgP9ERGuRMrruRBNxhYeqvsAmRzV5bWeZju7p7oqTI64TUnfileWENHVC5tlplgRhttf0mCiKgz8v+JpciOg3AHySmd/Ve/5xAGDmP3Qs83EAV8ES9iaArwN4AzNr77eSMLkMDFgzczexWUJ0XwAA09O5cIg68TK92AwPDmPsujEceuqQp23Xz86os8ObrLuMFM0uG5Ug2xvEZyPmwNVEsqET0e8CuImZb+893wngrcz8YccyFwN4BMCbAFwM4F8y86OKdY0DGAeA0dHRG7oqx2IEEvdV6r6gXgfWrctdwXXViaOiMdJAe0tbe0KanIC6E69GtcSTX4RiEUSkxT6/mqg2dFK85t7D7wLwJIDXArgewGeI6JJVH2KeZObNzLx5w4YNBl/tjzMc/MwZYK3L0BOrJUTV/mhwEPj5zxM03IfHbSLQMXd6ztO2a5Lq7FUwSvedQjUJ4rMpWq5C1pgI+jFY5hSbKwG85FpmF4AH2eIFAD+CNVtPFLcTdH7e+l+vW2aWRiPm0PBWy1pho3HhCy65BDh7duVysRruo+EUarsBhBu/k8PkBPSqAhnmO4XyEkSkq+aPiIqJoD8OYCMRXd1zdL4flnnFyRyALQBARL8C4I0AXoxzoCpUPspz5yzrR2Ldidztj06dUi83l78ZaNiTw+QE1K17/IZxOSE1lMVZHJQgx2GUoltx7tvC/FbM7PsHYBuAHwD4vwAmeq/tBrC79/i1AP4CwAyAZwDs8FvnDTfcwFEhYrbm5Cv/iCKv2pxGQz2IRiPFQZgz/fQ0N/64wfRJ4sYfN3j66Wmjzwy3hxmfRP9vuD286rO6dYf5zrJjuk/LSpLHRNR96x7bnq/sydVvBeAoa3S10IlFuUjYzHkZgLioWtRG0pQpeiNvx0aUfevVcDzM+pKgtNUWVT7KRMPBVQW5VHb1kok5kGzVvSpSlmSuPMaJR9m3qgAAXRmNPP5WhRR0W1d37gSGhhJ0grq/VJeG6rarl0zMhfgpQ/SGXZM9b80eouzbICKdx9+qcIKuimxZXASmphLW0sTTUIUqUfToDXtmnsewVK996+fc1Im0O+w3rkzYuCmcoGemq7qolRxFsxTGEy8kUss8zd9fZZpwkuXsVbdvAfiah3QXg92bdxv/VlmaoQrnFE08vV9HLjyweopWW1yIl7R/f68SzXk97oLUs4/i5E3a4V0qp6iuoGGihQ47HSsN1U2CHtigs60ojWuTmNlFWafcaQQn7cbFXolkeRRzwNxZGjUAIEuHd+EEPZPIlvFxy1jvpF5PzAMb5pbN5CBSCWUSt4dR1pnG7WoZLxhpi4jONHHovYdyKeZAeo7oLB3ehRP01KMEdSVz162L7UvdArPvq/sCz7b8DiKdUIb5Lj+izBaTnmnmMcwuDtIWES8fQJp3fEG+Ky1HdJYO78LZ0E2JrXNRwkZ704qIgHeFOT8bqkkp3SDf5WVjjFIhL+nqel72Ta+Kk3knLz6UJMYRZ2nmtJKgkvyeSrWgA2JO3jR1hoa8ggQRWj+nitdB5OXECvJdUUrpmjiFknYo+TnzshZEL0xq0md9QUri95PSzCsplVPUhFhDG02M9oa971S3h6Y2TpNbNi9nju7Wuz5UD3R76GcS6cx0cObsagey6S1n0rerXs68vCXIODExFeUhmzcJW37Q0szd093UTGh588eUUtBjCRkPko5qcAVRnZA7HtyhnS3Wh+qxxijrhHL/1v2B4qG9Tlh7G+cXVzqQ60P1Vd2PdCdBEvHZTnT7IUiCjN9JnMRJnnYUS1iSsOUHLc0MIBW/SB79MaU0uUQOGQ9qszGwswcxrSR1qx/HLbnXLTUA39vtLG299vZ3T3f7t+tO27lpjLLX+JPavqJ07snahu4kadNLVgXWKmdyiRzaGNRmowuCZ+4X8TK95Yx7RuokjltyL5OIye12VjNN52wKsG7X7XG3NrWMTT1+409q+4pS+yWJOyzdOg+8+4BnM/Sk477zWGCtlIIeJrTRWUhxuRvQZqO6gtj07Omjay7zHTeBcl/J0OuENRGdrE4CP6E1FSK/8Se1fUWq/ZKELV+3ztamVuhOXFHJ40W2lIIOBCuA6PZpziFgOqrzCqJiYQHt/4lVJ+Sq1edstqVDd3KZiE5WJ4GJ0JoIkd/4k9q+pH0LRSari10eL7KlFfQguC0sn0AbryKgzca+gpC6GXPrr05h8uZJ1IfqyvfX1tZqD4S8edJ1mIhOVidBXELrN/4kty8PUSx5JKuLXS4vsrpWRkn/xdGCLi5UrexuxTT/CA3rzUaDedqw3ZRBS7rpp6e5/ql6v51V/VN1bTurMrYqy6IlXZz70W/80nJPSBKUtQVdHHQ6wNgYsKSIWgtVSDFghIxf5EmZWpVlTR4SbwQhKl5RLmvSHkyesLVXJeahC37Zom2QNeoOx7LjWAH0hSaPnvSi0trUEgEXSk2lZ+i6ePVaDTh0KPlOciazb5mhC4LgJHIcOhHdRETPE9ELRHSnZpkbiehJInqWiP4qyoDTQheFuLycTltQk9l3GCdbUZyogiDEi6+gE1ENwL0AtgK4BsCtRHSNa5lLARwA8B5m/ocA3pfAWGMnkWYZzoD2XlKR9vsNIi+CetLzmI4sCEI6mMzQ3wLgBWZ+kZnPAvgCgFtcy/wrAA8y8xwAMPPxeIeZDLE3y1AV6dq50wplVIi76ezbzmQcHRnF3Ok5TByZ0Ap0UWp+CIIQPyZO0SsA/Njx/BiAt7qWeQOAQSL6BoCLAexn5s+7V0RE4wDGAWA00Z5xZgTwX5qhKhlg+yjsCoyOL7Zn2brIC2ftEQL1a3monKc24kQVhOri6xQlovcBeBcz3957vhPAW5j5I45lPgNgM4AtAIYAfBfAu5n5B7r15sEpakSQOue6Il1OajXLSO+zLpPGFyrHqDhRBaHcRHWKHgNwleP5lQBeUizzNWZ+lZlPAvgmgOvCDDZXGNY572Ny17G0ZLQulenEjWrWncd0ZEEQ0sFE0B8HsJGIriaitQDeD+AR1zJfAvCPiWgNEQ3DMsk8F+9QU8Dt0Ny3L1jVRa8iXSo81mViIlE5VXOZjiwIQir42tCZ+TwRfRjAYwBqAO5n5meJaHfv/fuY+Tki+hqApwEsA/gsMz+T5MBjx53hqQpQt9HFOzqN8t2u5Qz1M8E41uXMZBygAW3TBWD1rFuyIAVBqHRi0Qp0WUYqTGsCOO3vuqbSvXWZ2Mxtx6jdlMHpPM1Dg2BBEJKncg0uQmHan84Z1+gXc25XYJyaspyhbtau7a9LZzMfoIG+6WRq+xT4Ll5VaU9CFQVBACpey2UFo6PqGXq9DqxbtzrKRWWicYUl9pmYAM6dW73uiy/uL6uzmS/zMqa3T3vOtCVUURAEQGboF9BlGe3fr+6UEaRNnW72Pz/fn9l71eX2mml3ZjoYIPXPWJSGGYIgxIMIuk3QvnU6kVa97hXO2JvZt39pm3YR3Uzbtp2rnKcSqigI1UME3UmQvnVBCsG02+jcMIjmHcDAXUDzDqCzyfH+wgJanzqs7Wakm2nr7O41qolDVBAqiAh6WAIUgulcC4y/h9C9FGACupcC4ze7RH1uDvu37g+UFORldxcxF4TqIYIelgAmmokjE1jgsyteW1gLTGxxvDA6GjgpKI9dxwVByA6JQ0+BgbsH+oW1nBADy3fDs0WdFxJ/LgjVQ+LQgxKgprkJ2pn0afg7Xz2QNH9BEJzIDN1NwCbPRquUmbQgCDEhM/QgBIkvN0Rm0oIgpIFkiroJEl+uwF0ka9vGbTj8w8P951Pbp0TIBUFIBBF0N7oSAAa1zt2mle7pLg4ePdh/36vTkCAIQlTE5OImQqNRk6YUUjRLEISkEEF3E7QEgAPTYlhSNEsQhCQQk4uKVitURMvoyKiyn6dqOUEQhLiRGXqMqPp5uhmmtVI0SxCERBBBj5FV4Ylr6tjzxAAaL1tZoY2XgclHGK2nXR+MOZFJEIRqIiaXmLGjVyaOTGDu5S4Ovx5oHwFaM/YS56yYdtukE6RRhiAIggcyQ48ZO3Sxe7rrWVmxTwKJTMa6uC0AABC6SURBVIIgVBMjQSeim4joeSJ6gYju9FjuHxHREhH9bnxDLBbK/p6Kyop9IiYyCYIg2PgKOhHVANwLYCuAawDcSkTXaJb7FIDH4h5kkdD29xzpPXDHtAdplCEIguCByQz9LQBeYOYXmfksgC8AuEWx3EcA/DmA4zGOr3AErqwYIZFJEATBiYmgXwHgx47nx3qv9SGiKwC8F8B98Q2tmKhCF4cHh9G+bVrd1i5CIpMgCIITkygXUrzmrrl7D4CPMfMSkWrx3oqIxgGMA8BoSU0KK6JcegW52lva3rVbQiYyCYIgOPGth05EvwHgk8z8rt7zjwMAM/+hY5kf4YLwrwewAGCcmR/WrTeP9dA7HSu4ZG7OMmG326KzgiDki6j10B8HsJGIriaitQDeD+AR5wLMfDUzN5m5CeB/ANjrJeZ5xA4H73YB5gvh4Inl+EgykSAIMeMr6Mx8HsCHYUWvPAfgi8z8LBHtJqLdSQ8wLVINB0/96iEIQhWQFnQ9BgYsbXVDBCwv+3/e3djC027ebKprrjcaluNUEARBg7SgMyBKOPiK7FBwv5HF3kf3onlPEwN3D6B5TxOdmd4MXJKJBEFIABH0HlHCwZXZoecWcN/R+1aJfGemI8lEgiAkggh6jyjh4LrsUHZFd/a7FUkykSAICSCC7qDVskzYy8vqHCAdQRpWzJ2ek2QiQRASQQQ9BlTZoaTMx3KIf9irhyAIggYR9JgYWjPUf1wfqmP35t3qEgDSrUgQhIQQQY+IHeEyvzjff23x/CLePvr2ld2LRhqYvHnSuwSAIAhCBCQOPSLNe5rKxtCNkQZm75gNv2KpQyAIggKvOHRpQRcRbf1zzetGSFs6QRBCICYXu6YKEbBmjfU/QG0Vbf3zAJEvq5C2dIIghKDagu6sqQIAS0vW/wC1VbT1z6M4P3UZo6pyAYIgCD2qLeiqmbCNY0bcmen0U/jXf3o91n96fT+dH0D8zk9dxijRyouMVGwUBMFBtW3ofrVT5ub6USx2ar8zmqV7uoudD+4Eg9EYaWBq+1RwIXc7P7dtA86cUS/LDIyNXXgudnZBEBxUO8pFV/XQptFA8w4oo1hUDA8OB5udu52fphABF12kF/5GQ6JiBKGkSLVFHaqaKja92ipBolX6tVpM8TL5eMGsF3NA6qsLQkWptqA7a6oAQK1m/XfUVgkarRIoXDHJcrkSFSMIlaPagg5cqKnCDJw/b/131FZRRbF4EegCkHS5XKmvLgiVQgTdh9amVj+KBdAX3bIJFK7oZfKxse8aVBAB9br+famvLgiVQgTdgNamVn+m7q5x7qQ+VA8W5eI2+ai49FJgzx5LvN0wA4uL1vtSX10QKo8IugJVeLeqK5GT4cFh7N+6P/iX2SYflWADwKlTwIEDwNSUera+sAAcPmxdGJyz9V/8AtixQ+LTBaFCiKC7cCaPMl8IGOl6ODsTTSYaddRP13Wrtm3li4sXXrOXlYgXQagMRoJORDcR0fNE9AIR3al4v0VET/f+vkNE18U/1HTQlVGpnVELrl1VMXJZXJO2dDrRv+wy46xXQRDKi6+gE1ENwL0AtgK4BsCtRHSNa7EfAfgnzHwtgH8PYDLugaaFLjBk6bEEarY4MWlL124Dg4OrP/vzn/vXeZGIF0EoPSYz9LcAeIGZX2TmswC+AOAW5wLM/B1m/lnv6fcAXBnvMNNj1SR4Uwe4owls34mhNUOoD9WTa1jh15au1QIuuWT1586e9V+3RLwIQukxEfQrAPzY8fxY7zUdHwDwVdUbRDROREeJ6OiJEyfMR5kiKywfmzrAzePApV2AGPOL81g8v4ip7VPxmFnCcOpU8M/Yphsp5iUIpcZE0FXhF8rYPSJ6ByxB/5jqfWaeZObNzLx5w4YN5qNMkRWRhFsmgLUr7dKB0/vjxnSm7YyaGRoCvv3t1d7eXbuA9etF4AWhJJgI+jEAVzmeXwngJfdCRHQtgM8CuIWZ593vF4l+JOGlCXQjiopJMhJgibjN/Dxw8OBqp+m5c9Z7znAeEXVBKCwmgv44gI1EdDURrQXwfgCPOBcgolEADwLYycw/iH+Y2ZBIN6KomCQj1Wrhin5JNIwgFBpfQWfm8wA+DOAxAM8B+CIzP0tEu4lod2+xPwBQB3CAiJ4kouJ3f0ZC3YjiwL6FmJ5WhzranZfC0O1aZhiZqQtC4TCKQ2fmw8z8BmZ+PTO3e6/dx8z39R7fzsyvYebre3/KWr25w8dJ6KzjklhkSxR0oY5es3cT5uetLFMRdkEoFNVtcKFqLjE8vDr2u4iEbZyhoiz7RBBKgjS4UKFLCbX7iBY5ws+euasqMZo4VJ2IXV0QCkN1BV2XOTk3p63nUjhRP3nSsrNHNcn4ZaEKgpALqivoHsWwfCbvxUKVfWoa+mhDVLCrmSBUk+oKukcxLI/JezFx24+Alc7Uet1qOq2DGdi3r8A2KEGoBtUVdI9iWH6VbAuFzn4EXJi5nzxpNZ32cpDPzxfcBiUI5ae6gg5oi2GZVLItDDr7ka75hal9vbA2KEEoL2uyHkAuubYD+tg+YNmqYDDw93WMje5Hq4ihe152Iuds3d62dts85LGwNihBKCfVnqEr6Mx0sOvhXXiV562yZAQs//I8/mT+NnRmCmhi8LMTuWfatinKdN2Fju8UhHJR3cQiDc17muieVofp2d2JCoVJkhHR6vZ2zWa4cEVJRBKERJHEogB4VVLMtMpiWEyKealm8WEdBgsLwNiYzNgFIQNE0F14VVIcODNaTH3yK+alEu9WS51pasLSkkTDCEIGVFPQNXbfzkwHZ86eUX/m/FosPdYutj6Z9C11sn9/8FIBbhYWVsawr18vTTUEISGqZ0PXFOXq/McxjP/sEBbOOV63d81CHfjafmDGEr5Gw5rwVoJOx3KaJpX+LzZ3QQiE2NCdaOKyJ16cXCnmgBXlcroB/IeTfTEHKhat52WuiQN7Bu9EImcEIRTVE3SNGs9dpGkKMbJ6+UJmjEbF7Vx19iyNyvy8tb5mE9i7d3Vm644d1vtEUqNdEDyonqBr1Hj01ZrydXpl5fKFzRiNA3u2zmyFOTLHO3PvdtW9T53MzwO33WYJv8ziBWEF1RN0TV5/+3XjynZzuze2jX2IlcQ9c6+pL4yxcvasJfyqWbw4XYUKUz1BB4Chof7DztsuQvMTQ9hx/CAWzy32X68P1TF58yQO7Gmh3bYm9nNzlgleNMKFc+Z+/nz0FnhRmJ+3/txCb5tz3NE2RMCaNReWkR9XKDDVEnQ7wmXeqtHS2QSMb3kV3fPWc8aFiJ/F84srPuKeDIop14N2Gxgc1L8fp/3dFNucY/+QtvADF5pqu+31zr9162TmL+Seagh6p2OdjDt2AAsL6GwCmncAO7YDCxrdWTi3gIkjE8qgGOBCH2WZ2ClotYDPfW5lYlK9btnbmYGpqXRMM3Hy6qvqmX9Wf7Wa+s5DDsZKYxSHTkQ3AdgPoAbgs8z8R673qff+NgALAP41M/+N1zrDxKF3Du7FxIuT6F60BGKA7YkewwoxNH0M12MNBALuXvYsEy6E41Z08N8wjovgXdWRASyDMAA2+ckqifvQZsXr8jg/j5cxAMIyXqo1MDvexm8dCOaUixSHTkQ1APcC2ArgGgC3EtE1rsW2AtjY+xsHcDDQCA3oHNyL8f93EN11SwABPIB+NUQEfWyoDKMjo9UMUUyBB9DCBzGJWTSwDMIruMhh8LJ4FcNoYRprsIwWpvELeJhxKoz7cA57WsjjdB7XsIwBAFcudfFrB8fx13vju6MyMbm8BcALzPwiM58F8AUAt7iWuQXA59niewAuJaJfjW2UgJX4k+L5PDw4jPaWduD2m4I5D6CFqzGLGpYxgjNoYbov8LNo4IOYxANo9Ze9DZ/DCdTBsGY8r+AinEAdy8Cqi4EgFIGLsIDmZHyNYkwE/QoAP3Y8P9Z7LegyIKJxIjpKREdPnDgRaKDaxJ8EaIw0MHnzJFqbWv2ovLB1qgRznAJ/NWb7Yu58/3KcxAAYA2CM4Awux0nUwCsuBidQDyT0cjEQsuS1S/GlnpsIuspA4T4HTJYBM08y82Zm3rxhwwaT8fXRJf7EyfDgMKa3T2P2jlm0Nl0Qk1bLaru5Zw8yCdAQ/HFeDC7HSYXQA+dRwzLgEHzrTuBe7OkvswTq3wHYFwQRfCFJXqrFZ9c1EfRjAK5yPL8SwEshlolE+3XjGD4X5xpX4pyV6zhwwArQyDLMWgjGBaFnDOI8amCH4Ft3Ah/Bgf4ya7DcvwOo9f67Z/+2vd8t+mk+lotMOXgVw5gdjy/13ETQHwewkYiuJqK1AN4P4BHXMo8A+D2yeBuA08z8k9hGCaC15wAmr9iDxpkawACFORt6DJC12Y2RBqa3T4Pv4lWzcu04HDk009PJlDYR8oV79j+CM6tEP+3HujuPPFxs5LH34yUMYBnAsVoDf7tnMnCUixemYYvbANwDK2zxfmZuE9FuAGDm+3phi58BcBOssMVdzOwZk5jXFnSCIAh5xitscY3JCpj5MIDDrtfuczxmAB+KMkhBEAQhGtXIFBUEQagAIuiCIAglQQRdEAShJIigC4IglITMmkQT0QkA3ZAfXw/gZIzDyTuyveVGtrfcxL29DWZWZmZmJuhRIKKjurCdMiLbW25ke8tNmtsrJhdBEISSIIIuCIJQEooq6JNZDyBlZHvLjWxvuUltewtpQxcEQRBWU9QZuiAIguBCBF0QBKEkFE7QiegmInqeiF4gojuzHk/cENH9RHSciJ5xvHYZEX2diH7Y+/+aLMcYJ0R0FRH9JRE9R0TPEtG+3uul3GYi+mUi+j9E9FRve+/uvV7K7QWsvsRE9LdE9JXe89JuKwAQ0SwRzRDRk0R0tPdaKttcKEE3bFhddP4UVhliJ3cCOMLMGwEc6T0vC+cB/Btm/gcA3gbgQ73ftKzb/PcA3snM1wG4HsBNvR4CZd1eANgH4DnH8zJvq807mPl6R/x5KttcKEGHWcPqQsPM3wRwyvXyLQAO9R4fAvDPUx1UgjDzT5j5b3qPfw7rxL8CJd3mXiP1M72ng70/Rkm3l4iuBPBuAJ91vFzKbfUhlW0umqAbNaMuIb9id4Dq/b884/EkAhE1AfwagP+NEm9zzwTxJIDjAL7OzGXe3nsA/D5W9Awr7bbaMIC/IKIniGi891oq22zU4CJHGDWjFooHEa0D8OcA7mDmV6jEPf2YeQnA9UR0KYCHiOjNWY8pCYjodwAcZ+YniOjGrMeTIm9n5peI6HIAXyeiv0vri4s2Q0+8GXVO+SkR/SoA9P4fz3g8sUJEg7DEvMPMD/ZeLvU2AwAzvwzgG7B8JmXc3rcDeA8RzcIyj76TiKZRzm3tw8wv9f4fB/AQLFNxKttcNEE3aVhdRh4BMNZ7PAbgSxmOJVZ6/Wj/BMBzzPyfHW+VcpuJaENvZg4iGgLwTwH8HUq4vcz8cWa+kpmbsM7V/8XMO1DCbbUhoouI6GL7MYB/BuAZpLTNhcsUVTWsznhIsUJEDwC4EVbJzZ8CuAvAwwC+CGAUwByA9zGz23FaSIjotwB8C8AMLthZPwHLjl66bSaia2E5xWqwJlRfZOZ/R0R1lHB7bXoml48y8++UeVuJ6HWwZuWAZdL+M2Zup7XNhRN0QRAEQU3RTC6CIAiCBhF0QRCEkiCCLgiCUBJE0AVBEEqCCLogCEJJEEEXBEEoCSLogiAIJeH/A+Xevf6PRHpfAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(t,noised_data[:,0], 'bo') # infected observations\n", + "plt.plot(t,noised_data[:,1], 'ro') # infected observations\n", + "plt.plot(t,noised_data[:,2], 'go') # removed observations (recoverd/died)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We provide a guess for $\\beta$ and $\\gamma$. \n", + "\n", + "This example assumes we have information about the infected and removed population, up to 50 days of the epidemic.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[4.90464096e+00, 1.80229297e-01],\n", + " [8.59843745e+00, 4.02088747e-01],\n", + " [1.89574734e+01, 1.40262775e+00],\n", + " [4.55221314e+01, 2.94002911e+00],\n", + " [9.70595088e+01, 6.42741549e+00],\n", + " [2.60715165e+02, 2.20294695e+01],\n", + " [9.89941096e+02, 5.41627913e+01],\n", + " [1.51549915e+03, 1.21234960e+02],\n", + " [3.99119374e+03, 3.06882053e+02],\n", + " [7.16646079e+03, 4.15491759e+02],\n", + " [1.97356855e+04, 1.23045676e+03],\n", + " [5.78166023e+04, 3.68388673e+03],\n", + " [1.46862042e+05, 6.72234947e+03],\n", + " [2.83221926e+05, 1.72384073e+04],\n", + " [2.82099064e+05, 2.11595297e+04],\n", + " [5.58399812e+05, 6.05232963e+04],\n", + " [4.82619234e+05, 9.44362098e+04],\n", + " [6.65765758e+05, 9.66241419e+04],\n", + " [5.72747123e+05, 1.89549046e+05],\n", + " [7.09146912e+05, 2.66809758e+05],\n", + " [7.40234990e+05, 2.31329292e+05],\n", + " [8.09839926e+05, 2.66144343e+05],\n", + " [8.28408036e+05, 2.49165951e+05],\n", + " [5.35922195e+05, 2.62582973e+05],\n", + " [7.80220803e+05, 3.08835399e+05],\n", + " [6.82617907e+05, 3.47689342e+05],\n", + " [5.92186788e+05, 4.63366922e+05],\n", + " [6.51475912e+05, 4.15308489e+05],\n", + " [5.85276935e+05, 3.41209635e+05],\n", + " [4.32046981e+05, 4.63958279e+05],\n", + " [5.46589709e+05, 5.10905271e+05],\n", + " [5.74001575e+05, 6.71000810e+05],\n", + " [5.27246397e+05, 6.68918229e+05],\n", + " [3.61392141e+05, 6.64278025e+05],\n", + " [2.63079400e+05, 6.16456105e+05],\n", + " [4.23783943e+05, 6.90468622e+05],\n", + " [2.38533388e+05, 5.52959981e+05],\n", + " [2.62709237e+05, 5.37407391e+05],\n", + " [2.98828587e+05, 7.09511325e+05],\n", + " [2.74571172e+05, 5.79847948e+05],\n", + " [2.61441068e+05, 6.29842262e+05],\n", + " [2.58814617e+05, 5.85922250e+05],\n", + " [2.29144409e+05, 9.93779854e+05],\n", + " [2.04073231e+05, 8.91056939e+05],\n", + " [2.70945802e+05, 9.00814781e+05],\n", + " [1.85076291e+05, 5.27522223e+05],\n", + " [2.57204604e+05, 5.54443973e+05],\n", + " [2.13695888e+05, 7.22136698e+05],\n", + " [2.13717852e+05, 6.01210232e+05],\n", + " [1.75031250e+05, 8.37740727e+05],\n", + " [1.69539766e+05, 8.14458217e+05],\n", + " [1.15314773e+05, 9.72293020e+05],\n", + " [1.78120848e+05, 6.97256650e+05],\n", + " [1.02585057e+05, 7.93198444e+05],\n", + " [1.55782711e+05, 1.03239372e+06],\n", + " [1.74943163e+05, 9.71126263e+05],\n", + " [1.52068538e+05, 7.05193833e+05],\n", + " [1.52762181e+05, 8.24930915e+05],\n", + " [1.50338761e+05, 8.89104794e+05],\n", + " [1.29025441e+05, 1.04167885e+06],\n", + " [1.06464615e+05, 1.00337291e+06],\n", + " [9.70395803e+04, 1.12944693e+06],\n", + " [1.14748290e+05, 7.90374269e+05],\n", + " [7.95105215e+04, 1.03417055e+06],\n", + " [8.14083834e+04, 6.85339633e+05],\n", + " [8.06690402e+04, 1.12375935e+06],\n", + " [8.43980836e+04, 1.15992224e+06],\n", + " [6.45058699e+04, 9.38209174e+05],\n", + " [6.36689048e+04, 7.91500558e+05],\n", + " [7.61459197e+04, 6.70373122e+05],\n", + " [4.70386884e+04, 7.07148873e+05],\n", + " [4.36435911e+04, 1.07351504e+06],\n", + " [6.28077554e+04, 7.97904695e+05],\n", + " [5.13460989e+04, 1.04513457e+06],\n", + " [6.30232768e+04, 1.13777135e+06],\n", + " [4.80618082e+04, 6.68733585e+05],\n", + " [3.63328010e+04, 9.50863634e+05],\n", + " [3.93058078e+04, 8.52519368e+05],\n", + " [3.07539481e+04, 1.24746471e+06],\n", + " [2.86250646e+04, 1.19481806e+06],\n", + " [4.74378807e+04, 7.04448109e+05],\n", + " [4.25641347e+04, 1.00707379e+06],\n", + " [3.93888722e+04, 9.96770546e+05],\n", + " [4.23931532e+04, 1.23926888e+06],\n", + " [2.92396611e+04, 1.21790150e+06],\n", + " [2.30955819e+04, 1.21766218e+06],\n", + " [3.40750253e+04, 1.21323104e+06],\n", + " [2.90715064e+04, 1.24653594e+06],\n", + " [2.71127364e+04, 1.10720133e+06],\n", + " [1.80632805e+04, 9.20092600e+05],\n", + " [2.52555051e+04, 1.04913048e+06],\n", + " [1.84364518e+04, 8.92393680e+05],\n", + " [2.12905604e+04, 9.47623291e+05],\n", + " [1.52399694e+04, 8.93734566e+05],\n", + " [1.39883494e+04, 1.03000441e+06],\n", + " [1.94297894e+04, 6.62352965e+05],\n", + " [1.16906798e+04, 6.97002881e+05],\n", + " [1.66704070e+04, 1.03394095e+06],\n", + " [1.72713306e+04, 1.27845437e+06],\n", + " [1.21266522e+04, 1.04707729e+06],\n", + " [1.35747674e+04, 6.87112352e+05],\n", + " [1.41995065e+04, 1.23655680e+06],\n", + " [1.59604690e+04, 1.14258717e+06],\n", + " [1.49661903e+04, 9.44910315e+05],\n", + " [8.81448811e+03, 1.26252531e+06],\n", + " [1.03308974e+04, 1.30165545e+06],\n", + " [8.50777068e+03, 8.36995757e+05],\n", + " [8.70172886e+03, 6.64864104e+05],\n", + " [7.82093131e+03, 1.07081249e+06],\n", + " [7.45879620e+03, 1.19770227e+06],\n", + " [8.52024863e+03, 1.15803653e+06],\n", + " [8.32189873e+03, 1.00846421e+06],\n", + " [6.59831222e+03, 6.68555612e+05],\n", + " [8.85531680e+03, 8.29792492e+05],\n", + " [5.31855548e+03, 1.23812008e+06],\n", + " [5.52075923e+03, 1.28372745e+06],\n", + " [5.04682049e+03, 1.27597711e+06],\n", + " [4.66679110e+03, 8.45396050e+05],\n", + " [4.54145355e+03, 1.10227862e+06],\n", + " [5.61300707e+03, 7.62445652e+05],\n", + " [3.97255243e+03, 1.26594133e+06],\n", + " [3.82476121e+03, 9.83019339e+05],\n", + " [4.38706165e+03, 8.78298467e+05],\n", + " [5.14482874e+03, 1.22403191e+06],\n", + " [4.83390522e+03, 1.00609917e+06],\n", + " [4.43546984e+03, 1.18132044e+06],\n", + " [3.33736908e+03, 1.31476977e+06],\n", + " [4.27992342e+03, 6.78124116e+05],\n", + " [4.40850014e+03, 1.29295231e+06],\n", + " [2.22871884e+03, 8.82054729e+05],\n", + " [2.63126192e+03, 8.70732818e+05],\n", + " [3.16462468e+03, 9.68972110e+05],\n", + " [2.38352132e+03, 7.23463131e+05],\n", + " [2.74958560e+03, 9.91634243e+05],\n", + " [2.51111756e+03, 1.08911082e+06],\n", + " [2.29421855e+03, 9.73499719e+05],\n", + " [2.70910290e+03, 9.76478163e+05],\n", + " [2.74599424e+03, 9.94826643e+05],\n", + " [2.71399644e+03, 1.22395635e+06],\n", + " [2.37437235e+03, 8.95915646e+05],\n", + " [1.67058137e+03, 1.22830577e+06],\n", + " [1.28310408e+03, 1.27419959e+06],\n", + " [2.00847418e+03, 1.26488445e+06],\n", + " [1.25975575e+03, 1.03334003e+06],\n", + " [1.50336053e+03, 1.03852036e+06],\n", + " [1.92056369e+03, 1.06866912e+06],\n", + " [1.35604430e+03, 8.84856232e+05],\n", + " [1.56142207e+03, 1.27150899e+06],\n", + " [1.49452022e+03, 1.07190279e+06],\n", + " [8.27536828e+02, 1.21556422e+06],\n", + " [1.24647414e+03, 1.14059062e+06],\n", + " [1.39224948e+03, 7.34868209e+05],\n", + " [1.19435169e+03, 7.49311234e+05],\n", + " [6.83530459e+02, 8.30157875e+05],\n", + " [7.10990264e+02, 1.03078113e+06],\n", + " [9.22595586e+02, 6.93793896e+05],\n", + " [7.47412178e+02, 1.01088851e+06],\n", + " [7.86491010e+02, 1.18398624e+06],\n", + " [7.18057337e+02, 1.16071273e+06],\n", + " [8.23171200e+02, 9.74971676e+05],\n", + " [8.63367455e+02, 9.99990314e+05],\n", + " [8.69040904e+02, 7.92427482e+05],\n", + " [6.42316325e+02, 8.61518628e+05],\n", + " [6.32553637e+02, 9.00647496e+05],\n", + " [7.40747779e+02, 1.30510982e+06],\n", + " [4.43821580e+02, 1.23529263e+06],\n", + " [6.77583106e+02, 9.73486505e+05],\n", + " [3.88991313e+02, 9.81172515e+05],\n", + " [5.80724252e+02, 8.02259191e+05],\n", + " [5.37548455e+02, 6.92176252e+05],\n", + " [3.13384546e+02, 1.14917174e+06],\n", + " [5.16905055e+02, 1.33221864e+06],\n", + " [3.98652245e+02, 1.24340879e+06],\n", + " [4.04154080e+02, 6.95127565e+05],\n", + " [2.75303132e+02, 6.74425641e+05],\n", + " [2.59511329e+02, 8.87149341e+05],\n", + " [3.57784433e+02, 1.32696295e+06],\n", + " [3.07316774e+02, 7.62514516e+05],\n", + " [2.15460438e+02, 1.16024642e+06],\n", + " [2.76414090e+02, 1.05538866e+06],\n", + " [2.69689336e+02, 9.99092387e+05],\n", + " [2.36509482e+02, 7.25532274e+05],\n", + " [2.06250526e+02, 1.09987173e+06],\n", + " [1.74865694e+02, 9.37559865e+05],\n", + " [1.80949557e+02, 8.56970535e+05],\n", + " [2.21731370e+02, 1.17945438e+06],\n", + " [2.31782922e+02, 1.30240818e+06],\n", + " [2.38543368e+02, 7.55246791e+05],\n", + " [1.79534727e+02, 1.01341533e+06],\n", + " [1.81426132e+02, 1.10330196e+06],\n", + " [1.29034045e+02, 7.60069418e+05],\n", + " [1.85763844e+02, 1.25385833e+06],\n", + " [1.69940356e+02, 1.09219566e+06],\n", + " [1.64750052e+02, 8.60464933e+05],\n", + " [1.35305439e+02, 6.75206798e+05],\n", + " [9.56181015e+01, 1.06128189e+06],\n", + " [8.34455489e+01, 1.19510127e+06],\n", + " [1.14676301e+02, 1.27278898e+06],\n", + " [9.20268352e+01, 7.29251586e+05],\n", + " [1.20865697e+02, 1.16579188e+06],\n", + " [9.06288530e+01, 9.36231050e+05],\n", + " [7.73574703e+01, 9.42008457e+05],\n", + " [6.80663206e+01, 9.97675798e+05]])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data_to_fit = noised_data[:,1:3]\n", + "data_to_fit = data_to_fit[1::,:]\n", + "data_to_fit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fitting Normal loss" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "param_evals" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "theta = [3, 0.15,1e6]\n", + "boxBounds = [(2,5),(0.0,1.0),(1e6,1e6)]\n", + "\n", + "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4209072260954.626" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.cost()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\scipy\\optimize\\_minimize.py:521: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + " warn('Method %s cannot handle constraints nor bounds.' % method,\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 3149715468391.5137\n", + " hess_inv: array([[ 1.02285673e-11, -3.28483610e-14, 3.23263121e-06],\n", + " [-3.28483423e-14, 5.00246087e-15, -3.92052034e-09],\n", + " [ 3.23263111e-06, -3.92052576e-09, 1.06428103e+00]])\n", + " jac: array([-1.89198473e+03, 2.05662437e+05, 6.51297284e-03])\n", + " message: 'Desired error not necessarily achieved due to precision loss.'\n", + " nfev: 74\n", + " nit: 10\n", + " njev: 62\n", + " status: 2\n", + " success: False\n", + " x: array([3.84976144e+00, 2.02859211e-01, 1.11835931e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='BFGS')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 3149715468391.6045\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", + " jac: array([ 2.80002429e+03, 1.18458645e+05, -9.63846812e-03])\n", + " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", + " nfev: 12\n", + " nit: 9\n", + " status: 0\n", + " success: True\n", + " x: array([3.44232967e+00, 2.02859211e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='L-BFGS-B')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 0.15, 1000000.0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[(2, 5), (0.0, 1.0), (1000000.0, 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(theta,boxBounds,param_evals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fitting Gamma loss" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = GammaLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-1.17798986e+03, -1.40835509e+04, 3.53396958e-03])" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.sensitivity()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5065.797364214306" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.cost()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\scipy\\optimize\\_minimize.py:521: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + " warn('Method %s cannot handle constraints nor bounds.' % method,\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 4716.804547726841\n", + " hess_inv: array([[ 1.93830562e-03, -1.55181618e-05, 1.36514445e-06],\n", + " [-1.55181618e-05, 1.96280251e-06, 1.90886878e-08],\n", + " [ 1.36514445e-06, 1.90886878e-08, 1.00000000e+00]])\n", + " jac: array([ 8.67860428e-08, -3.11402124e-06, -3.11981179e-13])\n", + " message: 'Optimization terminated successfully.'\n", + " nfev: 15\n", + " nit: 10\n", + " njev: 15\n", + " status: 0\n", + " success: True\n", + " x: array([3.59483138e+00, 1.99847237e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='BFGS')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", + " logpdf_p3= -shape*np.log(mu/shape)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 4716.804547726802\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", + " jac: array([-9.16923207e-05, -1.70890676e-03, 3.29618418e-10])\n", + " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", + " nfev: 15\n", + " nit: 10\n", + " status: 0\n", + " success: True\n", + " x: array([3.59483123e+00, 1.99847235e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='L-BFGS-B')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 0.15, 1000000.0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[(2, 5), (0.0, 1.0), (1000000.0, 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(theta,boxBounds,param_evals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Adding random noise to produce Count Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our data needs to a be counts:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[5.000000e+00, 0.000000e+00],\n", + " [9.000000e+00, 0.000000e+00],\n", + " [1.900000e+01, 1.000000e+00],\n", + " [4.600000e+01, 3.000000e+00],\n", + " [9.700000e+01, 6.000000e+00],\n", + " [2.610000e+02, 2.200000e+01],\n", + " [9.900000e+02, 5.400000e+01],\n", + " [1.515000e+03, 1.210000e+02],\n", + " [3.991000e+03, 3.070000e+02],\n", + " [7.166000e+03, 4.150000e+02],\n", + " [1.973600e+04, 1.230000e+03],\n", + " [5.781700e+04, 3.684000e+03],\n", + " [1.468620e+05, 6.722000e+03],\n", + " [2.832220e+05, 1.723800e+04],\n", + " [2.820990e+05, 2.116000e+04],\n", + " [5.584000e+05, 6.052300e+04],\n", + " [4.826190e+05, 9.443600e+04],\n", + " [6.657660e+05, 9.662400e+04],\n", + " [5.727470e+05, 1.895490e+05],\n", + " [7.091470e+05, 2.668100e+05],\n", + " [7.402350e+05, 2.313290e+05],\n", + " [8.098400e+05, 2.661440e+05],\n", + " [8.284080e+05, 2.491660e+05],\n", + " [5.359220e+05, 2.625830e+05],\n", + " [7.802210e+05, 3.088350e+05],\n", + " [6.826180e+05, 3.476890e+05],\n", + " [5.921870e+05, 4.633670e+05],\n", + " [6.514760e+05, 4.153080e+05],\n", + " [5.852770e+05, 3.412100e+05],\n", + " [4.320470e+05, 4.639580e+05],\n", + " [5.465900e+05, 5.109050e+05],\n", + " [5.740020e+05, 6.710010e+05],\n", + " [5.272460e+05, 6.689180e+05],\n", + " [3.613920e+05, 6.642780e+05],\n", + " [2.630790e+05, 6.164560e+05],\n", + " [4.237840e+05, 6.904690e+05],\n", + " [2.385330e+05, 5.529600e+05],\n", + " [2.627090e+05, 5.374070e+05],\n", + " [2.988290e+05, 7.095110e+05],\n", + " [2.745710e+05, 5.798480e+05],\n", + " [2.614410e+05, 6.298420e+05],\n", + " [2.588150e+05, 5.859220e+05],\n", + " [2.291440e+05, 9.937800e+05],\n", + " [2.040730e+05, 8.910570e+05],\n", + " [2.709460e+05, 9.008150e+05],\n", + " [1.850760e+05, 5.275220e+05],\n", + " [2.572050e+05, 5.544440e+05],\n", + " [2.136960e+05, 7.221370e+05],\n", + " [2.137180e+05, 6.012100e+05],\n", + " [1.750310e+05, 8.377410e+05],\n", + " [1.695400e+05, 8.144580e+05],\n", + " [1.153150e+05, 9.722930e+05],\n", + " [1.781210e+05, 6.972570e+05],\n", + " [1.025850e+05, 7.931980e+05],\n", + " [1.557830e+05, 1.032394e+06],\n", + " [1.749430e+05, 9.711260e+05],\n", + " [1.520690e+05, 7.051940e+05],\n", + " [1.527620e+05, 8.249310e+05],\n", + " [1.503390e+05, 8.891050e+05],\n", + " [1.290250e+05, 1.041679e+06],\n", + " [1.064650e+05, 1.003373e+06],\n", + " [9.704000e+04, 1.129447e+06],\n", + " [1.147480e+05, 7.903740e+05],\n", + " [7.951100e+04, 1.034171e+06],\n", + " [8.140800e+04, 6.853400e+05],\n", + " [8.066900e+04, 1.123759e+06],\n", + " [8.439800e+04, 1.159922e+06],\n", + " [6.450600e+04, 9.382090e+05],\n", + " [6.366900e+04, 7.915010e+05],\n", + " [7.614600e+04, 6.703730e+05],\n", + " [4.703900e+04, 7.071490e+05],\n", + " [4.364400e+04, 1.073515e+06],\n", + " [6.280800e+04, 7.979050e+05],\n", + " [5.134600e+04, 1.045135e+06],\n", + " [6.302300e+04, 1.137771e+06],\n", + " [4.806200e+04, 6.687340e+05],\n", + " [3.633300e+04, 9.508640e+05],\n", + " [3.930600e+04, 8.525190e+05],\n", + " [3.075400e+04, 1.247465e+06],\n", + " [2.862500e+04, 1.194818e+06],\n", + " [4.743800e+04, 7.044480e+05],\n", + " [4.256400e+04, 1.007074e+06],\n", + " [3.938900e+04, 9.967710e+05],\n", + " [4.239300e+04, 1.239269e+06],\n", + " [2.924000e+04, 1.217901e+06],\n", + " [2.309600e+04, 1.217662e+06],\n", + " [3.407500e+04, 1.213231e+06],\n", + " [2.907200e+04, 1.246536e+06],\n", + " [2.711300e+04, 1.107201e+06],\n", + " [1.806300e+04, 9.200930e+05],\n", + " [2.525600e+04, 1.049130e+06],\n", + " [1.843600e+04, 8.923940e+05],\n", + " [2.129100e+04, 9.476230e+05],\n", + " [1.524000e+04, 8.937350e+05],\n", + " [1.398800e+04, 1.030004e+06],\n", + " [1.943000e+04, 6.623530e+05],\n", + " [1.169100e+04, 6.970030e+05],\n", + " [1.667000e+04, 1.033941e+06],\n", + " [1.727100e+04, 1.278454e+06],\n", + " [1.212700e+04, 1.047077e+06],\n", + " [1.357500e+04, 6.871120e+05],\n", + " [1.420000e+04, 1.236557e+06],\n", + " [1.596000e+04, 1.142587e+06],\n", + " [1.496600e+04, 9.449100e+05],\n", + " [8.814000e+03, 1.262525e+06],\n", + " [1.033100e+04, 1.301655e+06],\n", + " [8.508000e+03, 8.369960e+05],\n", + " [8.702000e+03, 6.648640e+05],\n", + " [7.821000e+03, 1.070812e+06],\n", + " [7.459000e+03, 1.197702e+06],\n", + " [8.520000e+03, 1.158037e+06],\n", + " [8.322000e+03, 1.008464e+06],\n", + " [6.598000e+03, 6.685560e+05],\n", + " [8.855000e+03, 8.297920e+05],\n", + " [5.319000e+03, 1.238120e+06],\n", + " [5.521000e+03, 1.283727e+06],\n", + " [5.047000e+03, 1.275977e+06],\n", + " [4.667000e+03, 8.453960e+05],\n", + " [4.541000e+03, 1.102279e+06],\n", + " [5.613000e+03, 7.624460e+05],\n", + " [3.973000e+03, 1.265941e+06],\n", + " [3.825000e+03, 9.830190e+05],\n", + " [4.387000e+03, 8.782980e+05],\n", + " [5.145000e+03, 1.224032e+06],\n", + " [4.834000e+03, 1.006099e+06],\n", + " [4.435000e+03, 1.181320e+06],\n", + " [3.337000e+03, 1.314770e+06],\n", + " [4.280000e+03, 6.781240e+05],\n", + " [4.409000e+03, 1.292952e+06],\n", + " [2.229000e+03, 8.820550e+05],\n", + " [2.631000e+03, 8.707330e+05],\n", + " [3.165000e+03, 9.689720e+05],\n", + " [2.384000e+03, 7.234630e+05],\n", + " [2.750000e+03, 9.916340e+05],\n", + " [2.511000e+03, 1.089111e+06],\n", + " [2.294000e+03, 9.735000e+05],\n", + " [2.709000e+03, 9.764780e+05],\n", + " [2.746000e+03, 9.948270e+05],\n", + " [2.714000e+03, 1.223956e+06],\n", + " [2.374000e+03, 8.959160e+05],\n", + " [1.671000e+03, 1.228306e+06],\n", + " [1.283000e+03, 1.274200e+06],\n", + " [2.008000e+03, 1.264884e+06],\n", + " [1.260000e+03, 1.033340e+06],\n", + " [1.503000e+03, 1.038520e+06],\n", + " [1.921000e+03, 1.068669e+06],\n", + " [1.356000e+03, 8.848560e+05],\n", + " [1.561000e+03, 1.271509e+06],\n", + " [1.495000e+03, 1.071903e+06],\n", + " [8.280000e+02, 1.215564e+06],\n", + " [1.246000e+03, 1.140591e+06],\n", + " [1.392000e+03, 7.348680e+05],\n", + " [1.194000e+03, 7.493110e+05],\n", + " [6.840000e+02, 8.301580e+05],\n", + " [7.110000e+02, 1.030781e+06],\n", + " [9.230000e+02, 6.937940e+05],\n", + " [7.470000e+02, 1.010889e+06],\n", + " [7.860000e+02, 1.183986e+06],\n", + " [7.180000e+02, 1.160713e+06],\n", + " [8.230000e+02, 9.749720e+05],\n", + " [8.630000e+02, 9.999900e+05],\n", + " [8.690000e+02, 7.924270e+05],\n", + " [6.420000e+02, 8.615190e+05],\n", + " [6.330000e+02, 9.006470e+05],\n", + " [7.410000e+02, 1.305110e+06],\n", + " [4.440000e+02, 1.235293e+06],\n", + " [6.780000e+02, 9.734870e+05],\n", + " [3.890000e+02, 9.811730e+05],\n", + " [5.810000e+02, 8.022590e+05],\n", + " [5.380000e+02, 6.921760e+05],\n", + " [3.130000e+02, 1.149172e+06],\n", + " [5.170000e+02, 1.332219e+06],\n", + " [3.990000e+02, 1.243409e+06],\n", + " [4.040000e+02, 6.951280e+05],\n", + " [2.750000e+02, 6.744260e+05],\n", + " [2.600000e+02, 8.871490e+05],\n", + " [3.580000e+02, 1.326963e+06],\n", + " [3.070000e+02, 7.625150e+05],\n", + " [2.150000e+02, 1.160246e+06],\n", + " [2.760000e+02, 1.055389e+06],\n", + " [2.700000e+02, 9.990920e+05],\n", + " [2.370000e+02, 7.255320e+05],\n", + " [2.060000e+02, 1.099872e+06],\n", + " [1.750000e+02, 9.375600e+05],\n", + " [1.810000e+02, 8.569710e+05],\n", + " [2.220000e+02, 1.179454e+06],\n", + " [2.320000e+02, 1.302408e+06],\n", + " [2.390000e+02, 7.552470e+05],\n", + " [1.800000e+02, 1.013415e+06],\n", + " [1.810000e+02, 1.103302e+06],\n", + " [1.290000e+02, 7.600690e+05],\n", + " [1.860000e+02, 1.253858e+06],\n", + " [1.700000e+02, 1.092196e+06],\n", + " [1.650000e+02, 8.604650e+05],\n", + " [1.350000e+02, 6.752070e+05],\n", + " [9.600000e+01, 1.061282e+06],\n", + " [8.300000e+01, 1.195101e+06],\n", + " [1.150000e+02, 1.272789e+06],\n", + " [9.200000e+01, 7.292520e+05],\n", + " [1.210000e+02, 1.165792e+06],\n", + " [9.100000e+01, 9.362310e+05],\n", + " [7.700000e+01, 9.420080e+05],\n", + " [6.800000e+01, 9.976760e+05]])" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "int_data_to_fit = np.around(data_to_fit)\n", + "int_data_to_fit " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Poisson loss" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = PoissonLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8329023.1484972015" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.cost()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 3557908.6464113127\n", + " hess_inv: array([[ 1.27472646e-07, -3.23818317e-09, 2.26214178e-06],\n", + " [-3.23818317e-09, 9.56376557e-10, 2.13419691e-08],\n", + " [ 2.26214178e-06, 2.13419691e-08, 1.00001208e+00]])\n", + " jac: array([-6.34498993e-04, 1.86534335e-03, 2.25490671e-09])\n", + " message: 'Desired error not necessarily achieved due to precision loss.'\n", + " nfev: 109\n", + " nit: 11\n", + " njev: 97\n", + " status: 2\n", + " success: False\n", + " x: array([3.55378376e+00, 1.99169650e-01, 1.00000147e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='BFGS')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 3557908.646411574\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", + " jac: array([-2.83986623e-01, -4.04398552e-01, 1.00922556e-06])\n", + " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", + " nfev: 15\n", + " nit: 11\n", + " status: 0\n", + " success: True\n", + " x: array([3.55377851e+00, 1.99169650e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='L-BFGS-B')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 0.15, 1000000.0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[(2, 5), (0.0, 1.0), (1000000.0, 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(theta,boxBounds,param_evals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## NegBinom loss" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", + " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", + " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" + ] + } + ], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = NegBinomLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'])" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-2.92555910e+02, -3.50195352e+03, 8.77667731e-04])" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.sensitivity()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5041.425763395273" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.cost()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\scipy\\optimize\\_minimize.py:521: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + " warn('Method %s cannot handle constraints nor bounds.' % method,\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 4867.899797539529\n", + " hess_inv: array([[ 7.67776936e-03, -5.97617430e-05, 1.74660277e-06],\n", + " [-5.97617430e-05, 7.85112146e-06, 1.25323010e-08],\n", + " [ 1.74660277e-06, 1.25323010e-08, 1.00000000e+00]])\n", + " jac: array([ 8.13167572e-09, -3.92696007e-06, -2.92247481e-14])\n", + " message: 'Optimization terminated successfully.'\n", + " nfev: 15\n", + " nit: 10\n", + " njev: 15\n", + " status: 0\n", + " success: True\n", + " x: array([3.59393939e+00, 1.99830691e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='BFGS')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", + " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 4867.899797547801\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", + " jac: array([ 4.12746856e-04, 1.84890228e-02, -1.48338804e-09])\n", + " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", + " nfev: 17\n", + " nit: 12\n", + " status: 0\n", + " success: True\n", + " x: array([3.59394146e+00, 1.99830811e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='L-BFGS-B')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 0.15, 1000000.0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[(2, 5), (0.0, 1.0), (1000000.0, 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(theta,boxBounds,param_evals)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index 0263e163..457371c1 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -9,14 +9,16 @@ __all__ = [ 'Square', 'Normal', - 'Poisson' + 'Poisson', + 'Gamma', + 'NegBinom' ] import numpy as np from pygom.model._model_errors import InitializeError from pygom.model.ode_utils import check_array_type -from pygom.utilR.distn import dnorm, dpois +from pygom.utilR.distn import dnorm, dpois, gamma_mu_shape, dnbinom class InputError(Exception): ''' @@ -253,6 +255,133 @@ def residual(self, yhat): resid = self._y - yhat return resid + +class Gamma(object): + ''' + Gamma distribution loss object + + Parameters + ---------- + y: array like + observation + Shape: float + shape (a in latex equations) + ''' + + def __init__(self, y, shape=2.0): + err_str = "Shape is not of the correct " + self._y = check_array_type(y) + if isinstance(shape, np.ndarray): + if len(shape.shape) > 1: + if 1 in shape.shape: + shape = shape.flatten() + + if y.shape == shape.shape: + self._shape = shape + else: + raise InitializeError(err_str + "size") + else: + if y.shape == shape.shape: + self._shape = shape + else: + raise InitializeError(err_str + "size") + elif shape is None or shape == 2.0: + self._shape = 2*np.ones(self._y.shape) + else: + raise InitializeError(err_str + "type") + + self.loss(self._y) + + def loss(self, yhat): + ''' + The loss under a gamma distribution. Defined as the negative + log-likelihood of the gamma distirbution in terms of mean and shape. + See: Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). Princeton University Press. + File "Loss function Calculations.ipnyb" + + Parameters + ---------- + yhat: array like + prediction + + + Returns + ------- + negative log-likelihood, :math:`\\mathcal{L}(\\hat{y}; y,a)` + + ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() + + return -gamma_mu_shape(x=self._y, mu=yhat,shape=self._shape,log=True).sum() + + def diff_loss(self, yhat): + ''' + Derivative of the loss function with respect to yhat which is + See: + File "Loss function Calculations.ipnyb" + + Parameters + ---------- + yhat: array like + prediction + + + Returns + ------- + first_deriv_yhat: array like + :math:`\\mathcal\\frac{a \\left(\\hat{y} - y\\right)}{\\hat{y}^{2}}` + + ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() + + return self._shape*(yhat-self._y)/yhat**2 + + def diff2Loss(self, yhat): + ''' + Twice derivative of the loss function with respect to yhat. + See: + Jupiter notebook "Loss function Calculations.ipnyb" + + Parameters + ---------- + yhat: array like + observation + + + Returns + ------- + scnd_deriv_yhat: array like + :math:`\\mathcal\\frac{a \\left(- \\hat{y} + 2 y\\right)}{\\hat{y}^{3}}` + + ''' + y = self._y + shape = self._shape + + return shape*(-yhat+2*y)/yhat**3 + + def residual(self, yhat): + ''' + Raw residuals + + Parameters + ---------- + yhat: array like + observation + + Returns + ------- + r: array like + residuals + + ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() + return self._y - yhat class Poisson(object): ''' @@ -344,3 +473,139 @@ def residual(self, yhat): yhat = yhat.ravel() return self._y - yhat +class NegBinom(object): + ''' + Negative Binomial distribution loss object + + Parameters + ---------- + y: array like + observation + k: float + Overdispersion parameter (k=mean+mean(mean/variance)) + ''' + + def __init__(self, y, k=1.0): + err_str = "k (the overdispersion parameter) is not of the correct " + self._y = check_array_type(y) + if isinstance(k, np.ndarray): + if len(k.shape) > 1: + if 1 in k.shape: + k = k.flatten() + + if y.shape == k.shape: + self._k = k + else: + raise InitializeError(err_str + "size") + else: + if y.shape == k.shape: + self._k = k + else: + raise InitializeError(err_str + "size") + elif k is None or k == 1.0: + self._k = np.ones(self._y.shape) + else: + raise InitializeError(err_str + "type") + + self.loss(self._y) + + def loss(self, yhat): + ''' + The loss under a Negative Binomial distribution. Defined as the + negative log-likelihood of the Negative Binomial 2 distribution. + + Parameters + ---------- + yhat: array like + observation + + Returns + ------- + negative log-likelihood, :math:`\\mathcal{L}(\\hat{y}; y,k)` + + ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() + + return (-dnbinom(self._y, mu=yhat,size=self._k,log=True)).sum() + + def diff_loss(self, yhat): + ''' + Derivative of the loss function with respect to yhat which is + See: + Jupiter notebook "Loss function Calculations.ipnyb" + Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press + + Parameters + ---------- + yhat: array like + observation + + k: array like + observation + + Returns + ------- + first_deriv_yhat: array like + :math:`\\frac{k(\\hat{y}-y)}{\\hat{y}(k + \\hat{y})}` + + ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() + + y = self._y + k = self._k + first_derivs_yhat = (k*(yhat-y))/(yhat*(k+yhat)) + return first_derivs_yhat + + def diff2Loss(self, yhat): + ''' + Twice derivative of the loss function with respect to yhat. + See: + Jupiter notebook "Loss function Calculations.ipnyb" + Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press + + Parameters + ---------- + yhat: array like + observation + + k: array like + observation + + Returns + ------- + scnd_deriv_yhat: array like + :math:`\\frac{k(\\hat{y}(k + \\hat{y}) + \\hat{y}(y -\\hat{y}) + (k + \\hat{y})(y - \\hat{y})}{\\hat{y}^{2}(k + \\hat{y})^{2}}` + + ''' + y = self._y + k = self._k + scnd_derivs_yhat_p1= k + scnd_derivs_yhat_p2= yhat**(-2) + scnd_derivs_yhat_p3= (k + yhat)**(-2) + scnd_derivs_yhat_p4= yhat*(k + yhat) - yhat*(yhat - x) - (k + yhat)*(yhat - x) + scnd_derivs_yhat= scnd_derivs_yhat_p1*scnd_derivs_yhat_p2*scnd_derivs_yhat_p3*scnd_derivs_yhat_p4 + return scnd_derivs_yhat + + def residual(self, yhat): + ''' + Raw residuals + + Parameters + ---------- + yhat: array like + observation + + Returns + ------- + r: array like + residuals + + ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() + return self._y - yhat diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index cdc19dfb..af461878 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -10,11 +10,13 @@ __all__ = [ 'SquareLoss', 'NormalLoss', - 'PoissonLoss' + 'PoissonLoss', + 'GammaLoss', + 'NegBinomLoss' ] from pygom.loss.base_loss import BaseLoss -from pygom.loss.loss_type import Normal, Square, Poisson +from pygom.loss.loss_type import Normal, Square, Poisson, Gamma, NegBinom from pygom.model.ode_utils import check_array_type class SquareLoss(BaseLoss): @@ -64,6 +66,22 @@ def _setLossType(self): return Normal(self._y, 1.0/self._stateWeight) else: return Normal(self._y, 1.0/self._stateWeight) + +class GammaLoss(BaseLoss): + ''' + Realizations from a Gamma distribution taking parameters mean and shape. + ''' + def __init__(self, theta, ode, x0, t0, t, y, state_name, + shape=2, target_param=None, target_state=None): + super(GammaLoss, self).__init__(theta, ode, x0, t0, t, y, + state_name, shape, + target_param, target_state) + + def __repr__(self): + return "GammaLoss" + self._get_model_str() + + def _setLossType(self): + return Gamma(self._y) class PoissonLoss(BaseLoss): ''' @@ -77,4 +95,20 @@ def __repr__(self): return "PoissonLoss" + self._get_model_str() def _setLossType(self): - return Poisson(self._y) \ No newline at end of file + return Poisson(self._y) + +class NegBinomLoss(BaseLoss): + ''' + Realizations from a Negative Binomial distribution + ''' + def __init__(self, theta, ode, x0, t0, t, y, state_name, + k=1, target_param=None, target_state=None): + super(NegBinomLoss, self).__init__(theta, ode, x0, t0, t, y, + state_name, k, + target_param, target_state) + + def __repr__(self): + return "NegBinomLoss" + self._get_model_str() + + def _setLossType(self): + return NegBinom(self._y) diff --git a/pygom/utilR/distn.py b/pygom/utilR/distn.py index 71d9ad55..8ebdca96 100644 --- a/pygom/utilR/distn.py +++ b/pygom/utilR/distn.py @@ -11,6 +11,7 @@ import scipy.stats as st import numpy as np +from scipy.special import gammaln ############################################################### # @@ -80,6 +81,38 @@ def dgamma(x, shape, rate=1.0, log=False): return st.gamma.logpdf(x, a=shape, scale=1.0/rate) else: return st.gamma.pdf(x, a=shape, scale=1.0/rate) + +def gamma_mu_shape(x, mu,shape,log=False): + ''' + The probability density function (pdf) of gamma distrbution in terms of mean and shape. + + Parameters + ---------- + x: array like observation. + mu: mean or prediction. + shape: shape (a in latex equation below). + log: if True the natural log of the pmf is given. + See: Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). Princeton University Press. + Jupyter notebook titled "Loss function Calculations.ipnyb" + + + Returns + ------- + pdf, :math:`\\mathcal\\{p}(x; \\mu,a) = \\exp(- a \\ln{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\ln{\\left(x \\right)} - \\ln{\\left(\\Gamma\\left(a\\right) \\right)})` +` + + ''' + + logpdf_p1= -gammaln(shape) + logpdf_p2= (shape - 1)*np.log(x) + logpdf_p3= -shape*np.log(mu/shape) + logpdf_p4= -shape*x/mu + logpdf = logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4 + if log: + ans = logpdf + else: + ans = np.exp(logpdf) + return ans def pgamma(q, shape, rate=1.0, log=False): ''' @@ -381,6 +414,73 @@ def rbinom(n, size, prob, seed=None): else: return rvs(n=size, p=prob, size=n)[0] +##### Negative Binomial distribution +def nb2pmf(x, mu,k,log=False): + ''' + The probability mass function (pmf) of Negative Binomial 2 distribution. + This definition of the negative binomial distribution is often refered to as + negative binomial 2, or the ecological parameterisation. This parameterisation + takes the mean and k (an overdispersion parameter). The variance = mean(1+mean/k), + some notation uses alpha (k=1/alpha). + See: Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press. + Jupyter notebook titled "Loss function Calculations.ipnyb" + + Parameters + ---------- + x: array like observation. + mu: mean or prediction. + k: overdispersion parameter (variance = mean(1+mean/k)). Note some notation uses $\alpha$, ($k=\alpha^{-1}$). + log: if True the natural log of the pmf is given. + See: + Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press. + File "Loss function Calculations.ipnyb" + + Returns + ------- + log pmf: + math:`\\mathcal\\p(x; \\mu,k)) = \\exp(\\ln(\\frac{\\Gamma \\left(k+x\\right)}{\\Gamma \\left(k\\right)x!}(\\frac{k}{k+\\mu})^{k}(\\frac{\\mu}{k+\\mu})^{x}))` + + ''' + # note that we input k the overdispersion parameter here + + + logpmf_p1= -gammaln(x+1) + logpmf_p2= -gammaln(k) + logpmf_p3= k*(np.log(k) - np.log(k + mu)) + logpmf_p4= x*(np.log(mu) - np.log(k + mu)) + logpmf_p5= gammaln(k+x) + logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5 + if log: + ans= logpmf + else: + ans= np.exp(logpmf) + return ans + +def dnbinom(x, size, prob=None, mu=None, log =False): + ''' + See + https://stat.ethz.ch/R-manual/R-devel/library/stats/html/NegBinomial.html + ''' + if mu is None and prob is None: + raise Exception("Neither 'prob' or 'mu' were specified") + + if mu is not None: + if prob is not None: + raise Exception("'prob' and 'mu' both specified") + + if log: + ans =nb2pmf(x=x, mu=mu,k=size,log=True) + else: + ans =nb2pmf(x=x, mu=mu,k=size,log=False) + + else: + if log: + ans= st.nbinom.logpmf(x, n=size, p=prob) + else: + ans= st.nbinom.pmf(x, n=size, p=prob) + + return ans + def test_seed(seed): ''' Test the input type of `seed` and return a new random generator if From 1abe96f16c323419e28958ad4a8b991dff215fd4 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Thu, 18 Jun 2020 11:04:20 +0100 Subject: [PATCH 02/16] Fixed confusion with disrpersion and weighting. --- notebooks/Loss function Calculations.ipynb | 2 +- pygom/loss/loss_type.py | 4 ++-- pygom/loss/ode_loss.py | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/notebooks/Loss function Calculations.ipynb b/notebooks/Loss function Calculations.ipynb index 3f46b706..b870605a 100644 --- a/notebooks/Loss function Calculations.ipynb +++ b/notebooks/Loss function Calculations.ipynb @@ -650,7 +650,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.1" + "version": "3.7.3" } }, "nbformat": 4, diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index 457371c1..b13c3602 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -485,7 +485,7 @@ class NegBinom(object): Overdispersion parameter (k=mean+mean(mean/variance)) ''' - def __init__(self, y, k=1.0): + def __init__(self, y, k=1.0,): err_str = "k (the overdispersion parameter) is not of the correct " self._y = check_array_type(y) if isinstance(k, np.ndarray): @@ -586,7 +586,7 @@ def diff2Loss(self, yhat): scnd_derivs_yhat_p1= k scnd_derivs_yhat_p2= yhat**(-2) scnd_derivs_yhat_p3= (k + yhat)**(-2) - scnd_derivs_yhat_p4= yhat*(k + yhat) - yhat*(yhat - x) - (k + yhat)*(yhat - x) + scnd_derivs_yhat_p4= yhat*(k + yhat) - yhat*(yhat - y) - (k + yhat)*(yhat - y) scnd_derivs_yhat= scnd_derivs_yhat_p1*scnd_derivs_yhat_p2*scnd_derivs_yhat_p3*scnd_derivs_yhat_p4 return scnd_derivs_yhat diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index af461878..7927e9f9 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -72,16 +72,16 @@ class GammaLoss(BaseLoss): Realizations from a Gamma distribution taking parameters mean and shape. ''' def __init__(self, theta, ode, x0, t0, t, y, state_name, - shape=2, target_param=None, target_state=None): + shape=2,state_weight=None, target_param=None, target_state=None): super(GammaLoss, self).__init__(theta, ode, x0, t0, t, y, - state_name, shape, + state_name, state_weight, target_param, target_state) def __repr__(self): return "GammaLoss" + self._get_model_str() def _setLossType(self): - return Gamma(self._y) + return Gamma(self._y,self._shape) class PoissonLoss(BaseLoss): ''' @@ -102,13 +102,13 @@ class NegBinomLoss(BaseLoss): Realizations from a Negative Binomial distribution ''' def __init__(self, theta, ode, x0, t0, t, y, state_name, - k=1, target_param=None, target_state=None): + k=1,state_weight=None, target_param=None, target_state=None): super(NegBinomLoss, self).__init__(theta, ode, x0, t0, t, y, - state_name, k, + state_name, state_weight, target_param, target_state) def __repr__(self): return "NegBinomLoss" + self._get_model_str() def _setLossType(self): - return NegBinom(self._y) + return NegBinom(self._y,self._k) From ffb938712f30a41ac0fc7d2309c55cc8315b1c97 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Thu, 18 Jun 2020 12:03:01 +0100 Subject: [PATCH 03/16] Allows for different over dispersion parameters than default in neg binom and gamma loss. --- pygom/loss/loss_type.py | 6 +++++- pygom/loss/ode_loss.py | 10 ++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index b13c3602..a9621668 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -287,6 +287,8 @@ def __init__(self, y, shape=2.0): raise InitializeError(err_str + "size") elif shape is None or shape == 2.0: self._shape = 2*np.ones(self._y.shape) + elif isinstance(shape, (int, float)) and shape !=2: + self._shape = shape*np.ones(self._y.shape) else: raise InitializeError(err_str + "type") @@ -485,7 +487,7 @@ class NegBinom(object): Overdispersion parameter (k=mean+mean(mean/variance)) ''' - def __init__(self, y, k=1.0,): + def __init__(self, y, k=1.0): err_str = "k (the overdispersion parameter) is not of the correct " self._y = check_array_type(y) if isinstance(k, np.ndarray): @@ -504,6 +506,8 @@ def __init__(self, y, k=1.0,): raise InitializeError(err_str + "size") elif k is None or k == 1.0: self._k = np.ones(self._y.shape) + elif isinstance(k, (int, float)) and k >1: + self._k = k*np.ones(self._y.shape) else: raise InitializeError(err_str + "type") diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index 7927e9f9..c371107c 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -71,8 +71,9 @@ class GammaLoss(BaseLoss): ''' Realizations from a Gamma distribution taking parameters mean and shape. ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name, - shape=2,state_weight=None, target_param=None, target_state=None): + def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, + shape=2, target_param=None, target_state=None): + self._shape = shape super(GammaLoss, self).__init__(theta, ode, x0, t0, t, y, state_name, state_weight, target_param, target_state) @@ -101,8 +102,9 @@ class NegBinomLoss(BaseLoss): ''' Realizations from a Negative Binomial distribution ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name, - k=1,state_weight=None, target_param=None, target_state=None): + def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, + k=1, target_param=None, target_state=None): + self._k = k super(NegBinomLoss, self).__init__(theta, ode, x0, t0, t, y, state_name, state_weight, target_param, target_state) From 4de2bf01f7707addae93b6e1fff6c74025880254 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Thu, 18 Jun 2020 15:21:08 +0100 Subject: [PATCH 04/16] Weighted residuals can now be applied in neg binom, Poisson and gamma loss functions. --- pygom/loss/loss_type.py | 133 ++++++++++++++++++++++++++++++++++++---- pygom/loss/ode_loss.py | 8 +-- 2 files changed, 124 insertions(+), 17 deletions(-) diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index a9621668..d0ec6a95 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -154,7 +154,9 @@ def __init__(self, y, sigma=1.0): err_str = "Standard deviation not of the correct " self._y = check_array_type(y) if isinstance(sigma, np.ndarray): - if len(sigma.shape) > 1: + if np.any(sigma<0): + raise InitializeError('No elements in numpy array of sigma values should be negative') + elif len(sigma.shape) > 1: if 1 in sigma.shape: sigma = sigma.flatten() @@ -169,6 +171,11 @@ def __init__(self, y, sigma=1.0): raise InitializeError(err_str + "size") elif sigma is None or sigma == 1.0: self._sigma = np.ones(self._y.shape) + elif isinstance(sigma, (int, float)): + if sigma <0: + raise InitializeError('Sigma should not be negative') + else: + self._sigma = sigma*np.ones(self._y.shape) else: raise InitializeError(err_str + "type") @@ -268,11 +275,13 @@ class Gamma(object): shape (a in latex equations) ''' - def __init__(self, y, shape=2.0): + def __init__(self, y, shape=2.0, weights=None): err_str = "Shape is not of the correct " self._y = check_array_type(y) if isinstance(shape, np.ndarray): - if len(shape.shape) > 1: + if np.any(shape<0): + raise InitializeError('No elements in numpy array of shape values should be negative') + elif len(shape.shape) > 1: if 1 in shape.shape: shape = shape.flatten() @@ -287,11 +296,27 @@ def __init__(self, y, shape=2.0): raise InitializeError(err_str + "size") elif shape is None or shape == 2.0: self._shape = 2*np.ones(self._y.shape) - elif isinstance(shape, (int, float)) and shape !=2: - self._shape = shape*np.ones(self._y.shape) + elif isinstance(shape, (int, float)): + if shape <0: + raise InitializeError('Shape should not be negative') + else: + self._shape = shape*np.ones(self._y.shape) else: raise InitializeError(err_str + "type") + + if weights is None: + self._numVar = 0 + self._w = np.ones(self._y.shape) + else: + self._w = check_array_type(weights) + + if len(self._w.shape) > 1: + if self._w.shape[1] == 1: + self._w = self._w.flatten() + assert self._y.shape == self._w.shape, \ + "Input weight not of the same size as y" + self.loss(self._y) def loss(self, yhat): @@ -383,7 +408,24 @@ def residual(self, yhat): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - return self._y - yhat + return self._weightedResidual(yhat) + + def _weightedResidual(self, yhat): + ''' + Find the weighted residuals. + ''' + # resid = self._y - yhat + # print "In weighted resid" + # print self._y.shape + if len(yhat.shape) > 1: + if 1 in yhat.shape: + resid = self._y - yhat.ravel() + else: + resid = self._y - yhat + else: + resid = self._y - yhat + + return resid * self._w class Poisson(object): ''' @@ -395,8 +437,21 @@ class Poisson(object): observation ''' - def __init__(self, y): + def __init__(self, y, weights=None): self._y = check_array_type(y) + if weights is None: + self._numVar = 0 + self._w = np.ones(self._y.shape) + else: + self._w = check_array_type(weights) + + if len(self._w.shape) > 1: + if self._w.shape[1] == 1: + self._w = self._w.flatten() + + assert self._y.shape == self._w.shape, \ + "Input weight not of the same size as y" + self.loss(self._y) def loss(self, yhat): @@ -473,7 +528,24 @@ def residual(self, yhat): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - return self._y - yhat + return self._weightedResidual(yhat) + + def _weightedResidual(self, yhat): + ''' + Find the weighted residuals. + ''' + # resid = self._y - yhat + # print "In weighted resid" + # print self._y.shape + if len(yhat.shape) > 1: + if 1 in yhat.shape: + resid = self._y - yhat.ravel() + else: + resid = self._y - yhat + else: + resid = self._y - yhat + + return resid * self._w class NegBinom(object): ''' @@ -487,11 +559,13 @@ class NegBinom(object): Overdispersion parameter (k=mean+mean(mean/variance)) ''' - def __init__(self, y, k=1.0): + def __init__(self, y, k=1.0, weights=None): err_str = "k (the overdispersion parameter) is not of the correct " self._y = check_array_type(y) if isinstance(k, np.ndarray): - if len(k.shape) > 1: + if np.any(k<0): + raise InitializeError('No elements in numpy array of shape values should be negative') + elif len(k.shape) > 1: if 1 in k.shape: k = k.flatten() @@ -506,10 +580,26 @@ def __init__(self, y, k=1.0): raise InitializeError(err_str + "size") elif k is None or k == 1.0: self._k = np.ones(self._y.shape) - elif isinstance(k, (int, float)) and k >1: - self._k = k*np.ones(self._y.shape) + elif isinstance(k, (int, float)): + if k <0: + raise InitializeError('k should not be negative') + else: + self._k = k*np.ones(self._y.shape) else: raise InitializeError(err_str + "type") + + if weights is None: + self._numVar = 0 + self._w = np.ones(self._y.shape) + else: + self._w = check_array_type(weights) + + if len(self._w.shape) > 1: + if self._w.shape[1] == 1: + self._w = self._w.flatten() + + assert self._y.shape == self._w.shape, \ + "Input weight not of the same size as y" self.loss(self._y) @@ -612,4 +702,21 @@ def residual(self, yhat): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - return self._y - yhat + return self._weightedResidual(yhat) + + def _weightedResidual(self, yhat): + ''' + Find the weighted residuals. + ''' + # resid = self._y - yhat + # print "In weighted resid" + # print self._y.shape + if len(yhat.shape) > 1: + if 1 in yhat.shape: + resid = self._y - yhat.ravel() + else: + resid = self._y - yhat + else: + resid = self._y - yhat + + return resid * self._w diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index c371107c..cf590fee 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -82,13 +82,13 @@ def __repr__(self): return "GammaLoss" + self._get_model_str() def _setLossType(self): - return Gamma(self._y,self._shape) + return Gamma(self._y,self._shape,self._state_weight)) class PoissonLoss(BaseLoss): ''' Realizations from a Poisson distribution ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name, + def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, target_param=None, target_state=None): super(PoissonLoss, self).__init__(theta, ode, x0, t0, t, y, state_name, None, target_param, target_state) @@ -96,7 +96,7 @@ def __repr__(self): return "PoissonLoss" + self._get_model_str() def _setLossType(self): - return Poisson(self._y) + return Poisson(self._y,self._state_weight)) class NegBinomLoss(BaseLoss): ''' @@ -113,4 +113,4 @@ def __repr__(self): return "NegBinomLoss" + self._get_model_str() def _setLossType(self): - return NegBinom(self._y,self._k) + return NegBinom(self._y,self._k,self._state_weight) From 793219dae06757ecc01af278934f9d5d67ab5d21 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Mon, 22 Jun 2020 14:26:40 +0100 Subject: [PATCH 05/16] Weighted residuals taken account of in gamma, nomral, Posson, nb loss functions. --- notebooks/Loss function Calculations.ipynb | 1055 ++++++++++++++++---- pygom/loss/loss_type.py | 410 +++----- pygom/loss/ode_loss.py | 58 +- 3 files changed, 1050 insertions(+), 473 deletions(-) diff --git a/notebooks/Loss function Calculations.ipynb b/notebooks/Loss function Calculations.ipynb index b870605a..ab5c2eb3 100644 --- a/notebooks/Loss function Calculations.ipynb +++ b/notebooks/Loss function Calculations.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -17,299 +17,441 @@ "import numpy as np" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1. Negative binomial loss class ##" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.1 Logliklihood function" - ] - }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 23, "metadata": {}, "outputs": [], "source": [ - " x, mu , k = sym.symbols('x mu k')" + "# Setting up residual for replacement, so that weighted residuals can be applied in code.\n", + "r ,y, yhat = sym.symbols('r,y yhat')\n", + "r_eq = y-yhat\n", + "minus_r_eq = yhat-y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Probability mass function (PMF) of negative binomial ${p}(x; \\mu,k) = \\frac{\\Gamma \\left(k+x\\right)}{\\Gamma \\left(k\\right)x!}(\\frac{k}{k+\\mu})^{k}(\\frac{\\mu}{k+\\mu})^{x}$ \n", - "This definition of the negative binomial distribution is often refered to as negative binomial 2. This parameterisation takes the mean (usually refered as $\\mu$, but in pygom $\\hat{y}$ as we are looking at a prediction) and $k$ (an overdispersion parameter). The variance = $\\mu+\\frac{\\mu^2}{k}$, some notation uses $\\alpha$, ($k=\\alpha^{-1}$). \n", - "See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press." + "# 1. Square Loss class" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle \\frac{\\left(\\frac{k}{k + \\mu}\\right)^{k} \\left(\\frac{\\mu}{k + \\mu}\\right)^{x} \\Gamma\\left(k + x\\right)}{x! \\Gamma\\left(k\\right)}$" + "$\\displaystyle \\left(y - \\hat{y}\\right)^{2}$" ], "text/plain": [ - "(k/(k + mu))**k*(mu/(k + mu))**x*gamma(k + x)/(factorial(x)*gamma(k))" + "(y - yhat)**2" ] }, - "execution_count": 3, "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nbpmf = (sym.gamma(k+x)/(sym.gamma(k)*sym.factorial(x)))*(k/(k+mu))**k*(mu/(k+mu))**x\n", - "nbpmf" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Due to the this PMF containing gamma functions and a factorial it is easier to calculate the sum of it's logged terms than to log it as one object (you end up with infinities otherwise). " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ + "output_type": "display_data" + }, { "data": { + "text/latex": [ + "$\\displaystyle r^{2}$" + ], "text/plain": [ - "((k/(k + mu))**k, (mu/(k + mu))**x, 1/factorial(x), 1/gamma(k), gamma(k + x))" + "r**2" ] }, - "execution_count": 4, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle r^{2}$" + ], + "text/plain": [ + "r**2" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "nbpmf.args" + "square_loss=(y-yhat)**2\n", + "display(square_loss,square_loss.subs(r_eq,r),square_loss.subs(minus_r_eq,-r))" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle k \\left(\\log{\\left(k \\right)} - \\log{\\left(k + \\mu \\right)}\\right) + x \\left(\\log{\\left(\\mu \\right)} - \\log{\\left(k + \\mu \\right)}\\right) - \\log{\\left(x! \\right)} - \\log{\\left(\\Gamma\\left(k\\right) \\right)} + \\Gamma\\left(k + x\\right)$" + "$\\displaystyle - 2 y + 2 \\hat{y}$" ], "text/plain": [ - "k*(log(k) - log(k + mu)) + x*(log(mu) - log(k + mu)) - log(factorial(x)) - log(gamma(k)) + gamma(k + x)" + "-2*y + 2*yhat" ] }, - "execution_count": 5, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - 2 y + 2 \\hat{y}$" + ], + "text/plain": [ + "-2*y + 2*yhat" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - 2 y + 2 \\hat{y}$" + ], + "text/plain": [ + "-2*y + 2*yhat" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "logpmf_p1= k*(sym.ln(k)-sym.ln(k+mu))\n", - "logpmf_p2= x*(sym.ln(mu)-sym.ln(k+mu))\n", - "logpmf_p3= -sym.ln(sym.factorial(x))\n", - "logpmf_p4= -sym.ln(sym.gamma(k))\n", - "logpmf_p5= sym.gamma(k+x)\n", - "logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5\n", - "logpmf" + "first_derv = sym.diff(square_loss,yhat).simplify()\n", + "display(first_derv,first_derv.simplify().subs(r_eq,r),first_derv.subs(minus_r_eq,-r))" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { + "text/latex": [ + "$\\displaystyle 2$" + ], "text/plain": [ - "(-log(factorial(x)),\n", - " -log(gamma(k)),\n", - " k*(log(k) - log(k + mu)),\n", - " x*(log(mu) - log(k + mu)),\n", - " gamma(k + x))" + "2" ] }, - "execution_count": 6, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "logpmf.args" + "scnd_derv= sym.diff(first_derv,yhat).simplify()\n", + "scnd_derv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2. Normal Loss\n", + "## 2.1 Logliklihood function" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ - "from scipy.special import gammaln\n", - "def nb2logpmf(x, mu,k):\n", - " '''\n", - " The log probability mass function (pmf) of Negative Binomial 2 distribution. \n", - "\n", - " Parameters\n", - " ----------\n", - " x: array like observation.\n", - " mu: mean or prediction.\n", - " k: overdispersion parameter (variance = mean(1+mean/k)). Note some notation uses $\\alpha$, ($k=\\alpha^{-1}$).\n", - " See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press.\n", - "\n", - " Returns\n", - " -------\n", - " log pmf:\n", - " math:`\\\\mathcal\\\\ln({p}(x; \\\\mu,k)) = \\\\ln(\\\\frac{\\\\Gamma \\\\left(k+x\\\\right)}{\\\\Gamma \\\\left(k\\\\right)x!}(\\\\frac{k}{k+\\\\mu})^{k}(\\\\frac{\\\\mu}{k+\\\\mu})^{x})`\n", - "\n", - " '''\n", - " # note that we input k the overdispersion parameter here\n", - "\n", - "\n", - " logpmf_p1= -gammaln(x+1) \n", - " logpmf_p2= -gammaln(k)\n", - " logpmf_p3= k*(np.log(k) - np.log(k + mu)) \n", - " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", - " logpmf_p5= gammaln(k+x)\n", - " logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5\n", - " return logpmf" + "sigma, pi = sym.symbols('sigma pi')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Our loss function is the negative of the logliklihood above." + "Probability density function (PDF) of the normal distribution ${p}(y; \\hat{y},k) = \\frac{1}{\\sqrt {2 \\pi} \\sigma}e^{-\\frac {(y-\\hat{y}) ^{2}}{2 \\sigma ^{2}}$.\n", + "See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 129–130). Princeton University Press." ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 30, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{\\sqrt{2} e^{- \\frac{\\left(y - \\hat{y}\\right)^{2}}{2 \\sigma^{2}}}}{2 \\sqrt{\\pi} \\sigma}$" + ], + "text/plain": [ + "sqrt(2)*exp(-(y - yhat)**2/(2*sigma**2))/(2*sqrt(pi)*sigma)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{\\sqrt{2} e^{- \\frac{r^{2}}{2 \\sigma^{2}}}}{2 \\sqrt{\\pi} \\sigma}$" + ], + "text/plain": [ + "sqrt(2)*exp(-r**2/(2*sigma**2))/(2*sqrt(pi)*sigma)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{\\sqrt{2} e^{- \\frac{r^{2}}{2 \\sigma^{2}}}}{2 \\sqrt{\\pi} \\sigma}$" + ], + "text/plain": [ + "sqrt(2)*exp(-r**2/(2*sigma**2))/(2*sqrt(pi)*sigma)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "negloglikli=-logpmf" + "normpdf=1/(sym.sqrt(2*pi)*sigma) * sym.E**(-((y-yhat)**2/(2*sigma**2)))\n", + "display(normpdf,normpdf.subs(r_eq,r),normpdf.subs(minus_r_eq,-r))" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 41, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1/2, sqrt(2), 1/sqrt(pi), 1/sigma, exp(-(y - yhat)**2/(2*sigma**2)))" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "1st derivative of -Loglikelihood of negative binomial loss with respect to $\\mu$." + "normpdf.args" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[-log(2),\n", + " log(2)/2,\n", + " -log(pi)/2,\n", + " log(1/sigma),\n", + " log(exp(-(y - yhat)**2/(2*sigma**2)))]" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Our loss function is the negative of the logliklihood.\n", + "loglike_args= []\n", + "for arg in normpdf.args:\n", + " loglike_args.append(sym.ln(arg).simplify())\n", + " \n", + "loglike_args" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle \\frac{k \\left(\\mu - x\\right)}{\\mu \\left(k + \\mu\\right)}$" + "$\\displaystyle - \\frac{r^{2}}{2 \\sigma^{2}}$" ], "text/plain": [ - "k*(mu - x)/(mu*(k + mu))" + "-r**2/(2*sigma**2)" ] }, - "execution_count": 9, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "nbfirstderv= sym.diff(negloglikli,mu).simplify()\n", - "nbfirstderv" + "logpdf_p1= loglike_args[0]\n", + "logpdf_p2= loglike_args[1]\n", + "logpdf_p3= loglike_args[2]\n", + "logpdf_p4= loglike_args[3]\n", + "logpdf_p5= -(y - yhat)**2/(2*sigma**2)\n", + "# logpdf_p5 has residual in:\n", + "logpdf_p5_alt= -(r)**2/(2*sigma**2)\n", + "logpdf_p5_alt" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 50, "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{\\log{\\left(\\pi \\right)}}{2} + \\log{\\left(\\frac{1}{\\sigma} \\right)} - \\frac{\\log{\\left(2 \\right)}}{2} - \\frac{\\left(y - \\hat{y}\\right)^{2}}{2 \\sigma^{2}}$" + ], + "text/plain": [ + "-log(pi)/2 + log(1/sigma) - log(2)/2 - (y - yhat)**2/(2*sigma**2)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{r^{2}}{2 \\sigma^{2}} - \\frac{\\log{\\left(\\pi \\right)}}{2} + \\log{\\left(\\frac{1}{\\sigma} \\right)} - \\frac{\\log{\\left(2 \\right)}}{2}$" + ], + "text/plain": [ + "-r**2/(2*sigma**2) - log(pi)/2 + log(1/sigma) - log(2)/2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "1st derivative of -Loglikelihood of negative binomial loss with respect to yhat: \n", - "$\\frac{k(\\mu-y)}{\\mu(k + \\mu)} $" + "logpdf = logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4+logpdf_p5\n", + "logpdf_alt = logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4+logpdf_p5_alt\n", + "display(logpdf,logpdf_alt)" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle - \\frac{k \\left(- \\mu \\left(k + \\mu\\right) + \\mu \\left(\\mu - x\\right) + \\left(k + \\mu\\right) \\left(\\mu - x\\right)\\right)}{\\mu^{2} \\left(k + \\mu\\right)^{2}}$" + "$\\displaystyle \\frac{\\log{\\left(\\pi \\right)}}{2} - \\log{\\left(\\frac{1}{\\sigma} \\right)} + \\frac{\\log{\\left(2 \\right)}}{2} + \\frac{\\left(y - \\hat{y}\\right)^{2}}{2 \\sigma^{2}}$" ], "text/plain": [ - "-k*(-mu*(k + mu) + mu*(mu - x) + (k + mu)*(mu - x))/(mu**2*(k + mu)**2)" + "log(pi)/2 - log(1/sigma) + log(2)/2 + (y - yhat)**2/(2*sigma**2)" ] }, - "execution_count": 10, + "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "nbsecderv = sym.diff(nbfirstderv,mu).simplify()\n", - "nbsecderv.simplify()" + "normloss=-logpdf\n", + "normloss" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 54, "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{- y + \\hat{y}}{\\sigma^{2}}$" + ], + "text/plain": [ + "(-y + yhat)/sigma**2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{r}{\\sigma^{2}}$" + ], + "text/plain": [ + "-r/sigma**2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{r}{\\sigma^{2}}$" + ], + "text/plain": [ + "-r/sigma**2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "2nd derivative of -Loglikelihood of negative binomial loss with respect to yhat: \n", - "$\\frac{k(\\mu(k + \\mu) + \\mu(y -\\mu) + (k + \\mu)(y - \\mu)}{\\mu^{2}(k + \\mu)^{2}} $" + "first_derv = sym.diff(normloss,yhat).simplify()\n", + "display(first_derv,first_derv.subs(r_eq,r),first_derv.subs(minus_r_eq,-r))" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 56, "metadata": {}, "outputs": [ { "data": { + "text/latex": [ + "$\\displaystyle \\frac{1}{\\sigma^{2}}$" + ], "text/plain": [ - "(k, mu**(-2), (k + mu)**(-2), mu*(k + mu) - mu*(mu - x) - (k + mu)*(mu - x))" + "sigma**(-2)" ] }, - "execution_count": 11, + "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "nbsecderv.args" + "scnd_derv = sym.diff(first_derv,yhat).simplify()\n", + "scnd_derv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "# 2. Gamma loss class in terms of mean and shape" + "# 3. Gamma loss class in terms of mean and shape" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 57, "metadata": {}, "outputs": [], "source": [ - " a, s, x, mu= sym.symbols('a s x mu')" + " a, s, y, yhat= sym.symbols('a s y yhat')" ] }, { @@ -323,40 +465,40 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle \\frac{s^{- a} x^{a - 1} e^{- \\frac{x}{s}}}{\\Gamma\\left(a\\right)}$" + "$\\displaystyle \\frac{s^{- a} y^{a - 1} e^{- \\frac{y}{s}}}{\\Gamma\\left(a\\right)}$" ], "text/plain": [ - "s**(-a)*x**(a - 1)*exp(-x/s)/gamma(a)" + "s**(-a)*y**(a - 1)*exp(-y/s)/gamma(a)" ] }, - "execution_count": 13, + "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "pdf_gamma = 1/(s**a*sym.gamma(a))*(x**(a-1)*sym.E**(-x/s))\n", + "pdf_gamma = 1/(s**a*sym.gamma(a))*(y**(a-1)*sym.E**(-y/s))\n", "pdf_gamma" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(s**(-a), x**(a - 1), 1/gamma(a), exp(-x/s))" + "(s**(-a), y**(a - 1), 1/gamma(a), exp(-y/s))" ] }, - "execution_count": 14, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } @@ -367,69 +509,69 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle - a \\log{\\left(s \\right)} + \\left(a - 1\\right) \\log{\\left(x \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)} - \\frac{x}{s}$" + "$\\displaystyle - a \\log{\\left(s \\right)} + \\left(a - 1\\right) \\log{\\left(y \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)} - \\frac{y}{s}$" ], "text/plain": [ - "-a*log(s) + (a - 1)*log(x) - log(gamma(a)) - x/s" + "-a*log(s) + (a - 1)*log(y) - log(gamma(a)) - y/s" ] }, - "execution_count": 15, + "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "log_pdf_gamma_p1 = -a*sym.ln(s)\n", - "log_pdf_gamma_p2 = (a-1)*sym.ln(x)\n", + "log_pdf_gamma_p2 = (a-1)*sym.ln(y)\n", "log_pdf_gamma_p3 = -sym.ln(sym.gamma(a))\n", - "log_pdf_gamma_p4 = -x/s\n", + "log_pdf_gamma_p4 = -y/s\n", "log_pdf_gamma= log_pdf_gamma_p1+log_pdf_gamma_p2+log_pdf_gamma_p3+log_pdf_gamma_p4\n", "log_pdf_gamma" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle - a \\log{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\log{\\left(x \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)}$" + "$\\displaystyle - \\frac{a y}{\\hat{y}} - a \\log{\\left(\\frac{\\hat{y}}{a} \\right)} + \\left(a - 1\\right) \\log{\\left(y \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)}$" ], "text/plain": [ - "-a*log(mu/a) - a*x/mu + (a - 1)*log(x) - log(gamma(a))" + "-a*y/yhat - a*log(yhat/a) + (a - 1)*log(y) - log(gamma(a))" ] }, - "execution_count": 16, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "s_in_terms_mu_a = mu/a\n", + "s_in_terms_mu_a = yhat/a\n", "log_pdf_mu_a_gamma = log_pdf_gamma.subs(s,s_in_terms_mu_a) \n", "log_pdf_mu_a_gamma" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(-log(gamma(a)), (a - 1)*log(x), -a*log(mu/a), -a*x/mu)" + "(-log(gamma(a)), (a - 1)*log(y), -a*log(yhat/a), -a*y/yhat)" ] }, - "execution_count": 17, + "execution_count": 63, "metadata": {}, "output_type": "execute_result" } @@ -440,14 +582,14 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "- a \\log{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\log{\\left(x \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)}\n" + "- \\frac{a y}{\\hat{y}} - a \\log{\\left(\\frac{\\hat{y}}{a} \\right)} + \\left(a - 1\\right) \\log{\\left(y \\right)} - \\log{\\left(\\Gamma\\left(a\\right) \\right)}\n" ] } ], @@ -457,7 +599,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 65, "metadata": {}, "outputs": [], "source": [ @@ -491,19 +633,19 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle a \\log{\\left(\\frac{\\mu}{a} \\right)} + \\frac{a x}{\\mu} - \\left(a - 1\\right) \\log{\\left(x \\right)} + \\log{\\left(\\Gamma\\left(a\\right) \\right)}$" + "$\\displaystyle \\frac{a y}{\\hat{y}} + a \\log{\\left(\\frac{\\hat{y}}{a} \\right)} - \\left(a - 1\\right) \\log{\\left(y \\right)} + \\log{\\left(\\Gamma\\left(a\\right) \\right)}$" ], "text/plain": [ - "a*log(mu/a) + a*x/mu - (a - 1)*log(x) + log(gamma(a))" + "a*y/yhat + a*log(yhat/a) - (a - 1)*log(y) + log(gamma(a))" ] }, - "execution_count": 20, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } @@ -522,7 +664,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 67, "metadata": { "scrolled": true }, @@ -530,10 +672,10 @@ { "data": { "text/latex": [ - "$\\displaystyle \\frac{a}{\\mu} - \\frac{a x}{\\mu^{2}}$" + "$\\displaystyle - \\frac{a y}{\\hat{y}^{2}} + \\frac{a}{\\hat{y}}$" ], "text/plain": [ - "a/mu - a*x/mu**2" + "-a*y/yhat**2 + a/yhat" ] }, "metadata": {}, @@ -542,10 +684,10 @@ { "data": { "text/latex": [ - "$\\displaystyle \\frac{a \\left(\\mu - x\\right)}{\\mu^{2}}$" + "$\\displaystyle \\frac{a \\left(- y + \\hat{y}\\right)}{\\hat{y}^{2}}$" ], "text/plain": [ - "a*(mu - x)/mu**2" + "a*(-y + yhat)/yhat**2" ] }, "metadata": {}, @@ -553,19 +695,43 @@ } ], "source": [ - "gammafirstderv= sym.diff(negloglikli_gamma_mu_a,mu)\n", + "gammafirstderv= sym.diff(negloglikli_gamma_mu_a,yhat)\n", "display(gammafirstderv,gammafirstderv.simplify())" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 69, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{a r}{\\hat{y}^{2}}$" + ], + "text/plain": [ + "-a*r/yhat**2" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gammafirstderv=gammafirstderv.simplify()\n", + "gammafirstderv.subs(r_eq,r)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ "\\frac{a \\left(\\mu - x\\right)}{\\mu^{2}}\n" ] } @@ -583,16 +749,16 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle \\frac{a \\left(- \\mu + 2 x\\right)}{\\mu^{3}}$" + "$\\displaystyle \\frac{a \\left(2 y - \\hat{y}\\right)}{\\hat{y}^{3}}$" ], "text/plain": [ - "a*(-mu + 2*x)/mu**3" + "a*(2*y - yhat)/yhat**3" ] }, "metadata": {}, @@ -601,10 +767,10 @@ { "data": { "text/latex": [ - "$\\displaystyle \\frac{a \\left(- \\mu + 2 x\\right)}{\\mu^{3}}$" + "$\\displaystyle \\frac{a \\left(2 y - \\hat{y}\\right)}{\\hat{y}^{3}}$" ], "text/plain": [ - "a*(-mu + 2*x)/mu**3" + "a*(2*y - yhat)/yhat**3" ] }, "metadata": {}, @@ -612,10 +778,33 @@ } ], "source": [ - "gammasecderv = sym.diff(gammafirstderv,mu).simplify()\n", + "gammasecderv = sym.diff(gammafirstderv,yhat).simplify()\n", "display(gammasecderv,gammasecderv.simplify())" ] }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a \\left(2 y - \\hat{y}\\right)}{\\hat{y}^{3}}$" + ], + "text/plain": [ + "a*(2*y - yhat)/yhat**3" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gammasecderv.subs(r_eq,r)" + ] + }, { "cell_type": "code", "execution_count": 24, @@ -632,6 +821,524 @@ "source": [ "sym.print_latex(gammasecderv)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 4. Poisson" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Probability density function (PDF) of the normal distribution ${p}(n;\\lambda) = \\frac{e^{-\\lambda}\\lambda^n}{n!}$.\n", + "See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 1222-123). Princeton University Press." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{\\hat{y}^{y} e^{- \\hat{y}}}{y!}$" + ], + "text/plain": [ + "yhat**y*exp(-yhat)/factorial(y)" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "poissonpmf = (sym.E**-yhat*yhat**y)/sym.factorial(y)\n", + "poissonpmf " + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(yhat**y, 1/factorial(y), exp(-yhat))" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "poissonpmf.args" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\hat{y} + \\log{\\left(\\hat{y}^{y} \\right)} - y!$" + ], + "text/plain": [ + "-yhat + log(yhat**y) - factorial(y)" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logpmf_p1 = sym.ln(yhat**y)\n", + "logpmf_p2 = -yhat\n", + "logpmf_p3 = -sym.factorial(y)\n", + "logpmf = logpmf_p1+logpmf_p2+logpmf_p3\n", + "logpmf" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [], + "source": [ + "possonloss=-logpmf" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{y}{\\hat{y}} + 1$" + ], + "text/plain": [ + "-y/yhat + 1" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{- y + \\hat{y}}{\\hat{y}}$" + ], + "text/plain": [ + "(-y + yhat)/yhat" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "possonfirstderv= sym.diff(possonloss,yhat)\n", + "display(possonfirstderv,possonfirstderv.simplify())" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{r}{\\hat{y}}$" + ], + "text/plain": [ + "-r/yhat" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "possonfirstderv.simplify().subs(r_eq,r)" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{y}{\\hat{y}^{2}}$" + ], + "text/plain": [ + "y/yhat**2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{y}{\\hat{y}^{2}}$" + ], + "text/plain": [ + "y/yhat**2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "possonsecderv= sym.diff(possonfirstderv,yhat)\n", + "display(possonsecderv,possonsecderv.simplify())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 5. Negative binomial loss class ##" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "k = sym.symbols('k')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Probability mass function (PMF) of negative binomial distribution ${p}(x; \\mu,k) = \\frac{\\Gamma \\left(k+x\\right)}{\\Gamma \\left(k\\right)x!}(\\frac{k}{k+\\mu})^{k}(\\frac{\\mu}{k+\\mu})^{x}$ \n", + "This definition of the negative binomial distribution is often refered to as negative binomial 2. This parameterisation takes the mean (usually refered as $\\mu$, but in pygom $\\hat{y}$ as we are looking at a prediction) and $k$ (an overdispersion parameter). The variance = $\\mu+\\frac{\\mu^2}{k}$, some notation uses $\\alpha$, ($k=\\alpha^{-1}$). \n", + "See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press." + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{\\left(\\frac{k}{k + \\hat{y}}\\right)^{k} \\left(\\frac{\\hat{y}}{k + \\hat{y}}\\right)^{y} \\Gamma\\left(k + y\\right)}{y! \\Gamma\\left(k\\right)}$" + ], + "text/plain": [ + "(k/(k + yhat))**k*(yhat/(k + yhat))**y*gamma(k + y)/(factorial(y)*gamma(k))" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbpmf = (sym.gamma(k+y)/(sym.gamma(k)*sym.factorial(y)))*(k/(k+yhat))**k*(yhat/(k+yhat))**y\n", + "nbpmf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Due to the this PMF containing gamma functions and a factorial it is easier to calculate the sum of it's logged terms than to log it as one object (you end up with infinities otherwise). " + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "((k/(k + yhat))**k,\n", + " (yhat/(k + yhat))**y,\n", + " 1/factorial(y),\n", + " 1/gamma(k),\n", + " gamma(k + y))" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbpmf.args" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle k \\left(\\log{\\left(k \\right)} - \\log{\\left(k + \\hat{y} \\right)}\\right) + y \\left(\\log{\\left(\\hat{y} \\right)} - \\log{\\left(k + \\hat{y} \\right)}\\right) - \\log{\\left(y! \\right)} - \\log{\\left(\\Gamma\\left(k\\right) \\right)} + \\Gamma\\left(k + y\\right)$" + ], + "text/plain": [ + "k*(log(k) - log(k + yhat)) + y*(log(yhat) - log(k + yhat)) - log(factorial(y)) - log(gamma(k)) + gamma(k + y)" + ] + }, + "execution_count": 89, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logpmf_p1= k*(sym.ln(k)-sym.ln(k+yhat))\n", + "logpmf_p2= y*(sym.ln(yhat)-sym.ln(k+yhat))\n", + "logpmf_p3= -sym.ln(sym.factorial(y))\n", + "logpmf_p4= -sym.ln(sym.gamma(k))\n", + "logpmf_p5= sym.gamma(k+y)\n", + "logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5\n", + "logpmf" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(-log(factorial(y)),\n", + " -log(gamma(k)),\n", + " k*(log(k) - log(k + yhat)),\n", + " y*(log(yhat) - log(k + yhat)),\n", + " gamma(k + y))" + ] + }, + "execution_count": 90, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logpmf.args" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.special import gammaln\n", + "def nb2logpmf(x, mu,k):\n", + " '''\n", + " The log probability mass function (pmf) of Negative Binomial 2 distribution. \n", + "\n", + " Parameters\n", + " ----------\n", + " x: array like observation.\n", + " mu: mean or prediction.\n", + " k: overdispersion parameter (variance = mean(1+mean/k)). Note some notation uses $\\alpha$, ($k=\\alpha^{-1}$).\n", + " See Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press.\n", + "\n", + " Returns\n", + " -------\n", + " log pmf:\n", + " math:`\\\\mathcal\\\\ln({p}(x; \\\\mu,k)) = \\\\ln(\\\\frac{\\\\Gamma \\\\left(k+x\\\\right)}{\\\\Gamma \\\\left(k\\\\right)x!}(\\\\frac{k}{k+\\\\mu})^{k}(\\\\frac{\\\\mu}{k+\\\\mu})^{x})`\n", + "\n", + " '''\n", + " # note that we input k the overdispersion parameter here\n", + "\n", + "\n", + " logpmf_p1= -gammaln(x+1) \n", + " logpmf_p2= -gammaln(k)\n", + " logpmf_p3= k*(np.log(k) - np.log(k + mu)) \n", + " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", + " logpmf_p5= gammaln(k+x)\n", + " logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5\n", + " return logpmf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our loss function is the negative of the logliklihood above." + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [], + "source": [ + "negloglikli=-logpmf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1st derivative of -Loglikelihood of negative binomial loss with respect to $\\mu$." + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{k \\left(- y + \\hat{y}\\right)}{\\hat{y} \\left(k + \\hat{y}\\right)}$" + ], + "text/plain": [ + "k*(-y + yhat)/(yhat*(k + yhat))" + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbfirstderv= sym.diff(negloglikli,yhat).simplify()\n", + "nbfirstderv" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\frac{k r}{\\hat{y} \\left(k + \\hat{y}\\right)}$" + ], + "text/plain": [ + "-k*r/(yhat*(k + yhat))" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbfirstderv.subs(r_eq,r)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1st derivative of -Loglikelihood of negative binomial loss with respect to yhat: \n", + "$\\frac{k(\\mu-y)}{\\mu(k + \\mu)} $" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{k \\left(\\hat{y} \\left(k + \\hat{y}\\right) + \\hat{y} \\left(y - \\hat{y}\\right) + \\left(k + \\hat{y}\\right) \\left(y - \\hat{y}\\right)\\right)}{\\hat{y}^{2} \\left(k + \\hat{y}\\right)^{2}}$" + ], + "text/plain": [ + "k*(yhat*(k + yhat) + yhat*(y - yhat) + (k + yhat)*(y - yhat))/(yhat**2*(k + yhat)**2)" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbsecderv = sym.diff(nbfirstderv,yhat).simplify()\n", + "nbsecderv.simplify()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2nd derivative of -Loglikelihood of negative binomial loss with respect to yhat: \n", + "$\\frac{k(\\mu(k + \\mu) + \\mu(y -\\mu) + (k + \\mu)(y - \\mu)}{\\mu^{2}(k + \\mu)^{2}} $" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{k \\left(r \\hat{y} + r \\left(k + \\hat{y}\\right) + \\hat{y} \\left(k + \\hat{y}\\right)\\right)}{\\hat{y}^{2} \\left(k + \\hat{y}\\right)^{2}}$" + ], + "text/plain": [ + "k*(r*yhat + r*(k + yhat) + yhat*(k + yhat))/(yhat**2*(k + yhat)**2)" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbsecderv_alt=nbsecderv.simplify().subs(r_eq,r)\n", + "nbsecderv_alt" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(k, yhat**(-2), (k + yhat)**(-2), r*yhat + r*(k + yhat) + yhat*(k + yhat))" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nbsecderv_alt.args" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -650,7 +1357,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.8.1" } }, "nbformat": 4, diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index d0ec6a95..214a6662 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -26,36 +26,88 @@ class InputError(Exception): ''' pass -class Square(object): +class baseloss_type(object): ''' - Square loss object + This baseloss_type class provides common feature to be inherited by the + loss type objects, such as Square, Normal , etc. Parameters ---------- y: array like observations + state_weight: array like + weight for the observations ''' - def __init__(self, y, weights=None): + # There may be some some overlapp with these checks on weights and y within + # the base loss class object in base_loss.py, thus these checks maybe redundent (unless this + # module is being used without base_loss.py. + #Checks o n y: self._y = check_array_type(y) - self._numObv = len(self._y) - + #Checks on weights. if weights is None: self._numVar = 0 self._w = np.ones(self._y.shape) else: self._w = check_array_type(weights) - + if np.any(weights<0): + raise ValueError('No elements in numpy array of weights should be negative') if len(self._w.shape) > 1: - if self._w.shape[1] == 1: + if 1 in self._w.shape: self._w = self._w.flatten() - assert self._y.shape == self._w.shape, \ "Input weight not of the same size as y" + + def residual(self, yhat, weighting_applied = True): + ''' + Raw residuals returned if weighting_applied = False, else + the weighted residuals. + + Parameters + ---------- + yhat: array like + observation + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals returned. + + Returns + ------- + :math:`y_{i} - \\hat{y}_{i}` + + ''' + if isinstance(weighting_applied,bool)=False: + raise TypeError('weighting_applied should be boolean') + + if len(yhat.shape) > 1: + if 1 in yhat.shape: + resid = self._y - yhat.ravel() + else: + resid = self._y - yhat + else: + resid = self._y - yhat + if weighting_applied = True: + resid *= self._w + + return resid + + + +class Square(baseloss_type): + ''' + Square loss object + Parameters + ---------- + y: array like + observations + ''' + + def __init__(self, y, weights=None): + super().__init__(y, weights=None) self.loss(self._y) - def loss(self, yhat): + def loss(self, yhat, weighting_applied = True): ''' Loss under square loss. Not really saying much here @@ -63,14 +115,18 @@ def loss(self, yhat): ---------- yhat: array like observation + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. + Returns ------- - :math:`\\sum_{i=1}^{n} (\\hat{y} - y)^{2}` + :math:`\\sum_{i=1}^{n} (y-\\hat{y})^{2}` ''' - return (self.residual(yhat)**2).sum() + return (self.residual(yhat,weighting_applied)**2).sum() - def diff_loss(self, yhat): + def diff_loss(self, yhat,weighting_applied=True): ''' Derivative under square loss. Assuming that we are solving the minimization problem i.e. our objective function is the @@ -80,12 +136,15 @@ def diff_loss(self, yhat): ---------- yhat: array like observation + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- :math:`-2(y_{i} - \\hat{y}_{i})` ''' - return -2*self.residual(yhat) + return -2*self.residual(yhat,weighting_applied)) def diff2Loss(self, yhat): ''' @@ -102,43 +161,12 @@ def diff2Loss(self, yhat): either a scalar, vector or matrix depending on the shape of of the input yhat ''' - return self._weightedResidual(2*np.ones(yhat.shape)) - - def residual(self, yhat): - ''' - Raw residuals if no weights was initialized, else - the weighted residuals - - Parameters - ---------- - yhat: array like - observation - - Returns - ------- - :math:`y_{i} - \\hat{y}_{i}` - - ''' - return self._weightedResidual(yhat) - - def _weightedResidual(self, yhat): - ''' - Find the weighted residuals. - ''' - # resid = self._y - yhat - # print "In weighted resid" - # print self._y.shape if len(yhat.shape) > 1: if 1 in yhat.shape: - resid = self._y - yhat.ravel() - else: - resid = self._y - yhat - else: - resid = self._y - yhat - - return resid * self._w + yhat = yhat.ravel() + return 2*np.ones(yhat.shape) -class Normal(object): +class Normal(baseloss_type): ''' Normal distribution loss object @@ -148,18 +176,16 @@ class Normal(object): observation sigma: float standard deviation - ''' - - def __init__(self, y, sigma=1.0): + ''' + def __init__(self, y, sigma=1.0,weight=None): + super().__init__(y, weights=None) err_str = "Standard deviation not of the correct " - self._y = check_array_type(y) if isinstance(sigma, np.ndarray): if np.any(sigma<0): - raise InitializeError('No elements in numpy array of sigma values should be negative') + raise ValueError('No elements in numpy array of sigma values should be negative') elif len(sigma.shape) > 1: if 1 in sigma.shape: sigma = sigma.flatten() - if y.shape == sigma.shape: self._sigma = sigma else: @@ -173,16 +199,16 @@ def __init__(self, y, sigma=1.0): self._sigma = np.ones(self._y.shape) elif isinstance(sigma, (int, float)): if sigma <0: - raise InitializeError('Sigma should not be negative') + raise ValueError('Sigma should not be negative') else: self._sigma = sigma*np.ones(self._y.shape) else: - raise InitializeError(err_str + "type") + raise TypeError(err_str + "type") self._sigma2 = self._sigma**2 self.loss(self._y) - def loss(self, yhat): + def loss(self, yhat,weighting_applied=True): ''' The loss under a normal distribution. Defined as the negative log-likelihood here. @@ -191,19 +217,28 @@ def loss(self, yhat): ---------- yhat: array like observation + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- - negative log-likelihood, :math:`\\mathcal{L}(\\hat{y},y)` + negative log-likelihood, :math:`\\mathcal\\frac{1}{\\sqrt{2\\pi}\\sigma}e^{-\\frac{(y-\\hat{y})^{2}}{2\\sigma^{2}}` ''' - # note that we input the standard deviation here if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - return (-dnorm(self._y, yhat, self._sigma, True)).sum() + + # Calculate negative likelihood (depending on weighting of residuals). + logpdf_p1= -np.log(2) + logpdf_p2= np.log(2)/2 + logpdf_p3= -np.log(pi)/2 + logpdf_p4= np.log(1/self._sigma) + logpdf_p5_alt=-self.residual(yhat,weighting_applied)**2/(2*sigma**2) + return (-(logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4+logpdf_p5_alt)).sum() - def diff_loss(self, yhat): + def diff_loss(self, yhat,weighting_applied=True): ''' Derivative of the loss function which is :math:`\\sigma^{-1}(y - \\hat{y})` @@ -212,6 +247,9 @@ def diff_loss(self, yhat): ---------- yhat: array like observation + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- @@ -219,7 +257,7 @@ def diff_loss(self, yhat): :math:`\\nabla \\mathcal{L}(\\hat{y}, y)` ''' - r = self.residual(yhat) + r = self.residual(yhat,weighting_applied) return -r/self._sigma2 def diff2Loss(self, yhat): @@ -236,34 +274,12 @@ def diff2Loss(self, yhat): s: array like inverse of the variance with shape = yhat.shape ''' - return np.ones(yhat.shape)/self._sigma2 - - def residual(self, yhat): - ''' - Residuals under a normal loss - - Parameters - ---------- - yhat: array like - observation - - Returns - ------- - r: array like - residuals - - ''' if len(yhat.shape) > 1: if 1 in yhat.shape: - resid = self._y - yhat.ravel() - else: - resid = self._y - yhat - else: - resid = self._y - yhat - - return resid + yhat = yhat.ravel() + return np.ones(yhat.shape)/self._sigma2 -class Gamma(object): +class Gamma(baseloss_type): ''' Gamma distribution loss object @@ -276,15 +292,14 @@ class Gamma(object): ''' def __init__(self, y, shape=2.0, weights=None): + super().__init__(y, weights=None) err_str = "Shape is not of the correct " - self._y = check_array_type(y) if isinstance(shape, np.ndarray): if np.any(shape<0): - raise InitializeError('No elements in numpy array of shape values should be negative') + raise ValueError('No elements in numpy array of shape values should be negative') elif len(shape.shape) > 1: if 1 in shape.shape: shape = shape.flatten() - if y.shape == shape.shape: self._shape = shape else: @@ -298,25 +313,11 @@ def __init__(self, y, shape=2.0, weights=None): self._shape = 2*np.ones(self._y.shape) elif isinstance(shape, (int, float)): if shape <0: - raise InitializeError('Shape should not be negative') + raise ValueError('Shape should not be negative') else: self._shape = shape*np.ones(self._y.shape) else: - raise InitializeError(err_str + "type") - - if weights is None: - self._numVar = 0 - self._w = np.ones(self._y.shape) - else: - self._w = check_array_type(weights) - - if len(self._w.shape) > 1: - if self._w.shape[1] == 1: - self._w = self._w.flatten() - - assert self._y.shape == self._w.shape, \ - "Input weight not of the same size as y" - + raise TypeError(err_str + "type") self.loss(self._y) def loss(self, yhat): @@ -343,7 +344,7 @@ def loss(self, yhat): return -gamma_mu_shape(x=self._y, mu=yhat,shape=self._shape,log=True).sum() - def diff_loss(self, yhat): + def diff_loss(self, yhat,weighting_applied=True): ''' Derivative of the loss function with respect to yhat which is See: @@ -353,19 +354,17 @@ def diff_loss(self, yhat): ---------- yhat: array like prediction + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. - Returns ------- first_deriv_yhat: array like :math:`\\mathcal\\frac{a \\left(\\hat{y} - y\\right)}{\\hat{y}^{2}}` ''' - if len(yhat.shape) > 1: - if 1 in yhat.shape: - yhat = yhat.ravel() - - return self._shape*(yhat-self._y)/yhat**2 + return self._shape*-self.residual(yhat,weighting_applied)/yhat**2 def diff2Loss(self, yhat): ''' @@ -385,49 +384,15 @@ def diff2Loss(self, yhat): :math:`\\mathcal\\frac{a \\left(- \\hat{y} + 2 y\\right)}{\\hat{y}^{3}}` ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() y = self._y shape = self._shape return shape*(-yhat+2*y)/yhat**3 - - def residual(self, yhat): - ''' - Raw residuals - - Parameters - ---------- - yhat: array like - observation - - Returns - ------- - r: array like - residuals - - ''' - if len(yhat.shape) > 1: - if 1 in yhat.shape: - yhat = yhat.ravel() - return self._weightedResidual(yhat) - - def _weightedResidual(self, yhat): - ''' - Find the weighted residuals. - ''' - # resid = self._y - yhat - # print "In weighted resid" - # print self._y.shape - if len(yhat.shape) > 1: - if 1 in yhat.shape: - resid = self._y - yhat.ravel() - else: - resid = self._y - yhat - else: - resid = self._y - yhat - - return resid * self._w -class Poisson(object): +class Poisson(baseloss_type): ''' Poisson distribution loss object @@ -438,20 +403,7 @@ class Poisson(object): ''' def __init__(self, y, weights=None): - self._y = check_array_type(y) - if weights is None: - self._numVar = 0 - self._w = np.ones(self._y.shape) - else: - self._w = check_array_type(weights) - - if len(self._w.shape) > 1: - if self._w.shape[1] == 1: - self._w = self._w.flatten() - - assert self._y.shape == self._w.shape, \ - "Input weight not of the same size as y" - + super().__init__(y, weights=None) self.loss(self._y) def loss(self, yhat): @@ -475,7 +427,7 @@ def loss(self, yhat): # note that we input the standard deviation here return (-dpois(self._y, yhat, True)).sum() - def diff_loss(self, yhat): + def diff_loss(self, yhat,weighting_applied=True): ''' Derivative of the loss function, :math:`1 - y\\hat{y}^{-1}` @@ -483,16 +435,22 @@ def diff_loss(self, yhat): ---------- yhat: array like observation + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- :math:`\\nabla \\mathcal{L}(\\hat{y},y)` ''' + if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - return 1 - self._y/yhat + + r = self.residual(yhat,weighting_applied) + return -r/yhat def diff2Loss(self, yhat): ''' @@ -508,46 +466,12 @@ def diff2Loss(self, yhat): s: array like :math:`\\frac{y}{\\hat{y}^{2}}` with shape = yhat.shape ''' - return self.y/(yhat**2) - - def residual(self, yhat): - ''' - Raw residuals - - Parameters - ---------- - yhat: array like - observation - - Returns - ------- - r: array like - residuals - - ''' if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - return self._weightedResidual(yhat) + return self._y/(yhat**2) - def _weightedResidual(self, yhat): - ''' - Find the weighted residuals. - ''' - # resid = self._y - yhat - # print "In weighted resid" - # print self._y.shape - if len(yhat.shape) > 1: - if 1 in yhat.shape: - resid = self._y - yhat.ravel() - else: - resid = self._y - yhat - else: - resid = self._y - yhat - - return resid * self._w - -class NegBinom(object): +class NegBinom(baseloss_type): ''' Negative Binomial distribution loss object @@ -560,15 +484,14 @@ class NegBinom(object): ''' def __init__(self, y, k=1.0, weights=None): + super().__init__(y, weights=None) err_str = "k (the overdispersion parameter) is not of the correct " - self._y = check_array_type(y) if isinstance(k, np.ndarray): if np.any(k<0): - raise InitializeError('No elements in numpy array of shape values should be negative') + raise ValueError('No elements in numpy array of shape values should be negative') elif len(k.shape) > 1: if 1 in k.shape: k = k.flatten() - if y.shape == k.shape: self._k = k else: @@ -582,25 +505,12 @@ def __init__(self, y, k=1.0, weights=None): self._k = np.ones(self._y.shape) elif isinstance(k, (int, float)): if k <0: - raise InitializeError('k should not be negative') + raise ValueError('k should not be negative') else: self._k = k*np.ones(self._y.shape) else: - raise InitializeError(err_str + "type") + raise TypeError(err_str + "type") - if weights is None: - self._numVar = 0 - self._w = np.ones(self._y.shape) - else: - self._w = check_array_type(weights) - - if len(self._w.shape) > 1: - if self._w.shape[1] == 1: - self._w = self._w.flatten() - - assert self._y.shape == self._w.shape, \ - "Input weight not of the same size as y" - self.loss(self._y) def loss(self, yhat): @@ -624,7 +534,7 @@ def loss(self, yhat): return (-dnbinom(self._y, mu=yhat,size=self._k,log=True)).sum() - def diff_loss(self, yhat): + def diff_loss(self, yhat,weighting_applied=True): ''' Derivative of the loss function with respect to yhat which is See: @@ -638,6 +548,10 @@ def diff_loss(self, yhat): k: array like observation + + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- @@ -651,10 +565,11 @@ def diff_loss(self, yhat): y = self._y k = self._k - first_derivs_yhat = (k*(yhat-y))/(yhat*(k+yhat)) + r = self.residual(yhat,weighting_applied) + first_derivs_yhat = k*-r/(yhat*(k+yhat)) return first_derivs_yhat - def diff2Loss(self, yhat): + def diff2Loss(self, yhat,weighting_applied=True): ''' Twice derivative of the loss function with respect to yhat. See: @@ -668,6 +583,10 @@ def diff2Loss(self, yhat): k: array like observation + + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- @@ -675,48 +594,15 @@ def diff2Loss(self, yhat): :math:`\\frac{k(\\hat{y}(k + \\hat{y}) + \\hat{y}(y -\\hat{y}) + (k + \\hat{y})(y - \\hat{y})}{\\hat{y}^{2}(k + \\hat{y})^{2}}` ''' + if len(yhat.shape) > 1: + if 1 in yhat.shape: + yhat = yhat.ravel() y = self._y k = self._k + r = self.residual(yhat,weighting_applied) scnd_derivs_yhat_p1= k scnd_derivs_yhat_p2= yhat**(-2) scnd_derivs_yhat_p3= (k + yhat)**(-2) - scnd_derivs_yhat_p4= yhat*(k + yhat) - yhat*(yhat - y) - (k + yhat)*(yhat - y) + scnd_derivs_yhat_p4= r*yhat + r*(k + yhat) + yhat*(k + yhat) scnd_derivs_yhat= scnd_derivs_yhat_p1*scnd_derivs_yhat_p2*scnd_derivs_yhat_p3*scnd_derivs_yhat_p4 - return scnd_derivs_yhat - - def residual(self, yhat): - ''' - Raw residuals - - Parameters - ---------- - yhat: array like - observation - - Returns - ------- - r: array like - residuals - - ''' - if len(yhat.shape) > 1: - if 1 in yhat.shape: - yhat = yhat.ravel() - return self._weightedResidual(yhat) - - def _weightedResidual(self, yhat): - ''' - Find the weighted residuals. - ''' - # resid = self._y - yhat - # print "In weighted resid" - # print self._y.shape - if len(yhat.shape) > 1: - if 1 in yhat.shape: - resid = self._y - yhat.ravel() - else: - resid = self._y - yhat - else: - resid = self._y - yhat - - return resid * self._w + return scnd_derivs_yhat \ No newline at end of file diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index cf590fee..3f70d32c 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -25,9 +25,8 @@ class SquareLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None, target_param=None, target_state=None): - super(SquareLoss, self).__init__(theta, ode, x0, t0, t, y, - state_name, state_weight, - target_param, target_state) + super().__init__(theta, ode, x0, t0, t, y, + state_name, state_weight,target_param, target_state) def __repr__(self): return "SquareLoss" + self._get_model_str() @@ -40,32 +39,18 @@ class NormalLoss(BaseLoss): ''' Realizations from a Normal distribution ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name, - sigma=None, target_param=None, target_state=None): - if sigma is None: - super(NormalLoss, self).__init__(theta, ode, x0, t0, t, y, - state_name, sigma, - target_param, target_state) - else: - sigma = check_array_type(sigma) - super(NormalLoss, self).__init__(theta, ode, x0, t0, t, y, - state_name, 1.0/sigma, - target_param, target_state) + def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, + sigma=1.0, target_param=None, target_state=None): + self._sigma=sigma + super().__init__(theta, ode, x0, t0, t, y, + state_name, state_weight,target_param, target_state) def __repr__(self): return "NormalLoss" + self._get_model_str() def _setLossType(self): - if self._stateWeight is None: - return Normal(self._y, 1.0) - else: - if len(self._stateWeight.shape) > 1: - if 1 in self._stateWeight.shape: - return Normal(self._y, 1.0/self._stateWeight.flatten()) - else: - return Normal(self._y, 1.0/self._stateWeight) - else: - return Normal(self._y, 1.0/self._stateWeight) + self._lossObj = Normal(self._y,self._sigma, self._stateWeight) + return self._lossObj class GammaLoss(BaseLoss): ''' @@ -73,16 +58,15 @@ class GammaLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, shape=2, target_param=None, target_state=None): - self._shape = shape - super(GammaLoss, self).__init__(theta, ode, x0, t0, t, y, - state_name, state_weight, - target_param, target_state) + self._shape=shape + super().__init__(theta, ode, x0, t0, t, y, + state_name, state_weight,target_param, target_state) def __repr__(self): return "GammaLoss" + self._get_model_str() def _setLossType(self): - return Gamma(self._y,self._shape,self._state_weight)) + return Gamma(self._y,self._shape,self._stateWeight)) class PoissonLoss(BaseLoss): ''' @@ -90,13 +74,14 @@ class PoissonLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, target_param=None, target_state=None): - super(PoissonLoss, self).__init__(theta, ode, x0, t0, t, y, state_name, - None, target_param, target_state) + super().__init__(theta, ode, x0, t0, t, y, + state_name, state_weight,target_param, target_state) + def __repr__(self): return "PoissonLoss" + self._get_model_str() def _setLossType(self): - return Poisson(self._y,self._state_weight)) + return Poisson(self._y,self._stateWeight)) class NegBinomLoss(BaseLoss): ''' @@ -104,13 +89,12 @@ class NegBinomLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, k=1, target_param=None, target_state=None): - self._k = k - super(NegBinomLoss, self).__init__(theta, ode, x0, t0, t, y, - state_name, state_weight, - target_param, target_state) + self._k=k + super().__init__(theta, ode, x0, t0, t, y, + state_name, state_weight,target_param, target_state) def __repr__(self): return "NegBinomLoss" + self._get_model_str() def _setLossType(self): - return NegBinom(self._y,self._k,self._state_weight) + return NegBinom(self._y,self._k,self._stateWeight) From d82e8a5418ba0cf584d2de96806314b13f4ccb97 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Tue, 23 Jun 2020 10:02:24 +0100 Subject: [PATCH 06/16] Gama loss functions 2nd derivative takes weighted residuals --- notebooks/Loss function Calculations.ipynb | 245 ++++++++++----------- pygom/loss/loss_type.py | 9 +- tests/test_loss_types.py | 91 +++++++- 3 files changed, 213 insertions(+), 132 deletions(-) diff --git a/notebooks/Loss function Calculations.ipynb b/notebooks/Loss function Calculations.ipynb index ab5c2eb3..8af4da95 100644 --- a/notebooks/Loss function Calculations.ipynb +++ b/notebooks/Loss function Calculations.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -19,14 +19,13 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Setting up residual for replacement, so that weighted residuals can be applied in code.\n", "r ,y, yhat = sym.symbols('r,y yhat')\n", - "r_eq = y-yhat\n", - "minus_r_eq = yhat-y" + "r_eq = y-yhat" ] }, { @@ -38,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -53,18 +52,6 @@ "metadata": {}, "output_type": "display_data" }, - { - "data": { - "text/latex": [ - "$\\displaystyle r^{2}$" - ], - "text/plain": [ - "r**2" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "data": { "text/latex": [ @@ -80,12 +67,12 @@ ], "source": [ "square_loss=(y-yhat)**2\n", - "display(square_loss,square_loss.subs(r_eq,r),square_loss.subs(minus_r_eq,-r))" + "display(square_loss,square_loss.subs(r_eq,r))" ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -111,28 +98,39 @@ }, "metadata": {}, "output_type": "display_data" - }, + } + ], + "source": [ + "first_derv = sym.diff(square_loss,yhat).simplify()\n", + "display(first_derv,first_derv.simplify().subs(r_eq,r))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle - 2 y + 2 \\hat{y}$" + "$\\displaystyle - 2 r$" ], "text/plain": [ - "-2*y + 2*yhat" + "-2*r" ] }, + "execution_count": 5, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" } ], "source": [ - "first_derv = sym.diff(square_loss,yhat).simplify()\n", - "display(first_derv,first_derv.simplify().subs(r_eq,r),first_derv.subs(minus_r_eq,-r))" + "-2*r" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -144,7 +142,7 @@ "2" ] }, - "execution_count": 13, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -164,7 +162,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -181,7 +179,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -196,18 +194,6 @@ "metadata": {}, "output_type": "display_data" }, - { - "data": { - "text/latex": [ - "$\\displaystyle \\frac{\\sqrt{2} e^{- \\frac{r^{2}}{2 \\sigma^{2}}}}{2 \\sqrt{\\pi} \\sigma}$" - ], - "text/plain": [ - "sqrt(2)*exp(-r**2/(2*sigma**2))/(2*sqrt(pi)*sigma)" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "data": { "text/latex": [ @@ -223,12 +209,12 @@ ], "source": [ "normpdf=1/(sym.sqrt(2*pi)*sigma) * sym.E**(-((y-yhat)**2/(2*sigma**2)))\n", - "display(normpdf,normpdf.subs(r_eq,r),normpdf.subs(minus_r_eq,-r))" + "display(normpdf,normpdf.subs(r_eq,r))" ] }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -237,7 +223,7 @@ "(1/2, sqrt(2), 1/sqrt(pi), 1/sigma, exp(-(y - yhat)**2/(2*sigma**2)))" ] }, - "execution_count": 41, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -248,7 +234,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 11, "metadata": { "scrolled": true }, @@ -263,7 +249,7 @@ " log(exp(-(y - yhat)**2/(2*sigma**2)))]" ] }, - "execution_count": 47, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -279,7 +265,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -291,7 +277,7 @@ "-r**2/(2*sigma**2)" ] }, - "execution_count": 48, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -309,7 +295,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -345,7 +331,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -357,7 +343,7 @@ "log(pi)/2 - log(1/sigma) + log(2)/2 + (y - yhat)**2/(2*sigma**2)" ] }, - "execution_count": 51, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -369,7 +355,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -384,18 +370,6 @@ "metadata": {}, "output_type": "display_data" }, - { - "data": { - "text/latex": [ - "$\\displaystyle - \\frac{r}{\\sigma^{2}}$" - ], - "text/plain": [ - "-r/sigma**2" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "data": { "text/latex": [ @@ -411,12 +385,12 @@ ], "source": [ "first_derv = sym.diff(normloss,yhat).simplify()\n", - "display(first_derv,first_derv.subs(r_eq,r),first_derv.subs(minus_r_eq,-r))" + "display(first_derv,first_derv.subs(r_eq,r))" ] }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -428,7 +402,7 @@ "sigma**(-2)" ] }, - "execution_count": 56, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -447,7 +421,7 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -465,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -477,7 +451,7 @@ "s**(-a)*y**(a - 1)*exp(-y/s)/gamma(a)" ] }, - "execution_count": 58, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -489,7 +463,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -498,7 +472,7 @@ "(s**(-a), y**(a - 1), 1/gamma(a), exp(-y/s))" ] }, - "execution_count": 59, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -509,7 +483,7 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -521,7 +495,7 @@ "-a*log(s) + (a - 1)*log(y) - log(gamma(a)) - y/s" ] }, - "execution_count": 61, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -537,7 +511,7 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -549,7 +523,7 @@ "-a*y/yhat - a*log(yhat/a) + (a - 1)*log(y) - log(gamma(a))" ] }, - "execution_count": 62, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -562,7 +536,7 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -571,7 +545,7 @@ "(-log(gamma(a)), (a - 1)*log(y), -a*log(yhat/a), -a*y/yhat)" ] }, - "execution_count": 63, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -582,7 +556,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -599,7 +573,7 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ @@ -633,7 +607,7 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -645,7 +619,7 @@ "a*y/yhat + a*log(yhat/a) - (a - 1)*log(y) + log(gamma(a))" ] }, - "execution_count": 66, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -664,7 +638,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 26, "metadata": { "scrolled": true }, @@ -701,7 +675,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -713,7 +687,7 @@ "-a*r/yhat**2" ] }, - "execution_count": 69, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -725,14 +699,14 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\\frac{a \\left(\\mu - x\\right)}{\\mu^{2}}\n" + "- \\frac{a \\left(y - \\hat{y}\\right)}{\\hat{y}^{2}}\n" ] } ], @@ -749,7 +723,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -784,7 +758,7 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 30, "metadata": {}, "outputs": [ { @@ -796,7 +770,7 @@ "a*(2*y - yhat)/yhat**3" ] }, - "execution_count": 72, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -807,14 +781,37 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{a \\left(r + y\\right)}{y^{3}}$" + ], + "text/plain": [ + "a*(r + y)/y**3" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a*(y+r)/y**3" + ] + }, + { + "cell_type": "code", + "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\\frac{a \\left(- \\mu + 2 x\\right)}{\\mu^{3}}\n" + "\\frac{a \\left(2 y - \\hat{y}\\right)}{\\hat{y}^{3}}\n" ] } ], @@ -839,7 +836,7 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": 33, "metadata": {}, "outputs": [ { @@ -851,7 +848,7 @@ "yhat**y*exp(-yhat)/factorial(y)" ] }, - "execution_count": 74, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -863,7 +860,7 @@ }, { "cell_type": "code", - "execution_count": 76, + "execution_count": 34, "metadata": {}, "outputs": [ { @@ -872,7 +869,7 @@ "(yhat**y, 1/factorial(y), exp(-yhat))" ] }, - "execution_count": 76, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -883,7 +880,7 @@ }, { "cell_type": "code", - "execution_count": 78, + "execution_count": 35, "metadata": {}, "outputs": [ { @@ -895,7 +892,7 @@ "-yhat + log(yhat**y) - factorial(y)" ] }, - "execution_count": 78, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } @@ -910,7 +907,7 @@ }, { "cell_type": "code", - "execution_count": 79, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -919,7 +916,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": 37, "metadata": {}, "outputs": [ { @@ -954,7 +951,7 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 38, "metadata": {}, "outputs": [ { @@ -966,7 +963,7 @@ "-r/yhat" ] }, - "execution_count": 81, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } @@ -977,7 +974,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": 39, "metadata": {}, "outputs": [ { @@ -1019,7 +1016,7 @@ }, { "cell_type": "code", - "execution_count": 84, + "execution_count": 40, "metadata": {}, "outputs": [], "source": [ @@ -1037,7 +1034,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 41, "metadata": {}, "outputs": [ { @@ -1049,7 +1046,7 @@ "(k/(k + yhat))**k*(yhat/(k + yhat))**y*gamma(k + y)/(factorial(y)*gamma(k))" ] }, - "execution_count": 86, + "execution_count": 41, "metadata": {}, "output_type": "execute_result" } @@ -1068,7 +1065,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 42, "metadata": {}, "outputs": [ { @@ -1081,7 +1078,7 @@ " gamma(k + y))" ] }, - "execution_count": 87, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } @@ -1092,7 +1089,7 @@ }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 43, "metadata": {}, "outputs": [ { @@ -1104,7 +1101,7 @@ "k*(log(k) - log(k + yhat)) + y*(log(yhat) - log(k + yhat)) - log(factorial(y)) - log(gamma(k)) + gamma(k + y)" ] }, - "execution_count": 89, + "execution_count": 43, "metadata": {}, "output_type": "execute_result" } @@ -1121,7 +1118,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 44, "metadata": {}, "outputs": [ { @@ -1134,7 +1131,7 @@ " gamma(k + y))" ] }, - "execution_count": 90, + "execution_count": 44, "metadata": {}, "output_type": "execute_result" } @@ -1145,7 +1142,7 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 45, "metadata": {}, "outputs": [], "source": [ @@ -1188,7 +1185,7 @@ }, { "cell_type": "code", - "execution_count": 92, + "execution_count": 46, "metadata": {}, "outputs": [], "source": [ @@ -1204,7 +1201,7 @@ }, { "cell_type": "code", - "execution_count": 94, + "execution_count": 47, "metadata": {}, "outputs": [ { @@ -1216,7 +1213,7 @@ "k*(-y + yhat)/(yhat*(k + yhat))" ] }, - "execution_count": 94, + "execution_count": 47, "metadata": {}, "output_type": "execute_result" } @@ -1228,7 +1225,7 @@ }, { "cell_type": "code", - "execution_count": 95, + "execution_count": 48, "metadata": {}, "outputs": [ { @@ -1240,7 +1237,7 @@ "-k*r/(yhat*(k + yhat))" ] }, - "execution_count": 95, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } @@ -1259,7 +1256,7 @@ }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 49, "metadata": {}, "outputs": [ { @@ -1271,7 +1268,7 @@ "k*(yhat*(k + yhat) + yhat*(y - yhat) + (k + yhat)*(y - yhat))/(yhat**2*(k + yhat)**2)" ] }, - "execution_count": 97, + "execution_count": 49, "metadata": {}, "output_type": "execute_result" } @@ -1291,7 +1288,7 @@ }, { "cell_type": "code", - "execution_count": 98, + "execution_count": 50, "metadata": {}, "outputs": [ { @@ -1303,7 +1300,7 @@ "k*(r*yhat + r*(k + yhat) + yhat*(k + yhat))/(yhat**2*(k + yhat)**2)" ] }, - "execution_count": 98, + "execution_count": 50, "metadata": {}, "output_type": "execute_result" } @@ -1315,7 +1312,7 @@ }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 51, "metadata": {}, "outputs": [ { @@ -1324,7 +1321,7 @@ "(k, yhat**(-2), (k + yhat)**(-2), r*yhat + r*(k + yhat) + yhat*(k + yhat))" ] }, - "execution_count": 100, + "execution_count": 51, "metadata": {}, "output_type": "execute_result" } diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index 214a6662..5e0e6445 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -52,6 +52,8 @@ def __init__(self, y, weights=None): self._w = check_array_type(weights) if np.any(weights<0): raise ValueError('No elements in numpy array of weights should be negative') + if np.all(weights==0.0): + raise ValueError('All elements in numpy array of weights should not be 0.0') if len(self._w.shape) > 1: if 1 in self._w.shape: self._w = self._w.flatten() @@ -366,7 +368,7 @@ def diff_loss(self, yhat,weighting_applied=True): ''' return self._shape*-self.residual(yhat,weighting_applied)/yhat**2 - def diff2Loss(self, yhat): + def diff2Loss(self, yhat,weighting_applied=True): ''' Twice derivative of the loss function with respect to yhat. See: @@ -376,6 +378,9 @@ def diff2Loss(self, yhat): ---------- yhat: array like observation + weighting_applied: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns @@ -390,7 +395,7 @@ def diff2Loss(self, yhat): y = self._y shape = self._shape - return shape*(-yhat+2*y)/yhat**3 + return shape*(self.residual(yhat,weighting_applied)+y)/yhat**3 class Poisson(baseloss_type): ''' diff --git a/tests/test_loss_types.py b/tests/test_loss_types.py index 0d9bb29d..c0345fa3 100644 --- a/tests/test_loss_types.py +++ b/tests/test_loss_types.py @@ -2,10 +2,10 @@ import numpy as np -from pygom import SquareLoss, NormalLoss +from pygom import SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss from pygom.model import common_models -class TestLossTypes(TestCase): +class Test_Square_loss_class(TestCase): def setUp(self): # initial values @@ -49,6 +49,85 @@ def test_FH_Square_vector_weight(self): self.assertTrue(np.allclose(obj.cost(), s)) + + def test_FH_Square_1State_Fail(self): + ## totalFail = 0 + ## expectedFail = 4 + w_list = list() + + w_list.append([-1.]) + w_list.append([0]) + w_list.append([2.0, 3.0]) + w_list.append(np.random.rand(30)) + + for w in w_list: + self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,:], + 'R', w) + + def test_FH_Square_2State_Fail(self): + ## totalFail = 0 + ## expectedFail = 8 + w_list = list() + + w_list.append([-2.0]) + w_list.append([2.0, 3.0, 4.0]) + w_list.append([0.0, 0.0]) + w_list.append([1.0, -1.0]) + w_list.append(np.random.rand(30)) + w_list.append([np.random.rand(30), np.random.rand(31)]) + w_list.append([np.random.rand(31), np.random.rand(31)]) + w_list.append([np.random.rand(30), np.random.rand(30), np.random.rand(30)]) + + for w in w_list: + self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,:], + 'R', w) + +class Test_Normal_loss_class(TestCase): + + def setUp(self): + # initial values + self.x0 = [-1.0, 1.0] + # params + self.param_eval = [('a', 0.2), ('b', 0.2),('c', 3.0)] + # the time points for our observations + self.t = np.linspace(0, 20, 30).astype('float64') + self.ode = common_models.FitzHugh(self.param_eval) + self.ode.initial_values = (self.x0, self.t[0]) + + # Standard. Find the solution which we will be used as + # "observations later" + self.solution = self.ode.integrate(self.t[1::]) + # initial guess + self.theta = [0.5, 0.5, 0.5] + + obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], + self.t[1::], self.solution[1::,:], ['V', 'R']) + self.r = obj.residual() + + def test_FH_Normal_scalar_weight(self): + # weight for each component + w = [2.0, 3.0] + + s = 0 + for i in range(2): s += ((self.r[:,i]*w[i])**2).sum() + + obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], + self.t[1::], self.solution[1::,:], ['V', 'R'], w) + + self.assertTrue(np.allclose(obj.cost(), s)) + + def test_FH_Normal_vector_weight(self): + # now the weight is a vector + w = np.random.rand(29, 2) + obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], + self.t[1::], self.solution[1::,:], ['V', 'R'], w) + + s = ((self.r * np.array(w))**2).sum() + + self.assertTrue(np.allclose(obj.cost(), s)) + def test_FH_Normal(self): objFH = NormalLoss(self.theta, self.ode, self.x0, self.t[0], self.t[1::], self.solution[1::,:], ['V', 'R']) @@ -65,7 +144,7 @@ def test_FH_Normal(self): self.assertFalse(np.allclose(objFH.cost(), objFH1.cost())) self.assertFalse(np.allclose(objFH1.cost(), objFH2.cost())) - def test_FH_Square_1State_Fail(self): + def test_FH_Normal_1State_Fail(self): ## totalFail = 0 ## expectedFail = 4 w_list = list() @@ -76,11 +155,11 @@ def test_FH_Square_1State_Fail(self): w_list.append(np.random.rand(30)) for w in w_list: - self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, + self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, self.x0, self.t[0], self.t[1::], self.solution[1::,:], 'R', w) - def test_FH_Square_2State_Fail(self): + def test_FH_Normal_2State_Fail(self): ## totalFail = 0 ## expectedFail = 8 w_list = list() @@ -95,7 +174,7 @@ def test_FH_Square_2State_Fail(self): w_list.append([np.random.rand(30), np.random.rand(30), np.random.rand(30)]) for w in w_list: - self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, + self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, self.x0, self.t[0], self.t[1::], self.solution[1::,:], 'R', w) From 126fc99b4fdd3c90e42e22e1c88e00d1b1688588 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Wed, 24 Jun 2020 10:53:12 +0100 Subject: [PATCH 07/16] Corrected typo --- pygom/loss/ode_loss.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index 3f70d32c..d8882249 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -66,8 +66,9 @@ def __repr__(self): return "GammaLoss" + self._get_model_str() def _setLossType(self): - return Gamma(self._y,self._shape,self._stateWeight)) - + self._lossObj = Gamma(self._y,self._shape,self._stateWeight) + return self._lossObj + class PoissonLoss(BaseLoss): ''' Realizations from a Poisson distribution @@ -81,7 +82,8 @@ def __repr__(self): return "PoissonLoss" + self._get_model_str() def _setLossType(self): - return Poisson(self._y,self._stateWeight)) + self._lossObj = Poisson(self._y,self._stateWeight) + return self._lossObj class NegBinomLoss(BaseLoss): ''' @@ -97,4 +99,5 @@ def __repr__(self): return "NegBinomLoss" + self._get_model_str() def _setLossType(self): - return NegBinom(self._y,self._k,self._stateWeight) + self._lossObj = NegBinom(self._y,self._k,self._stateWeight) + return self._lossObj \ No newline at end of file From 3f90a1da510de787ba1f01a0081cfdacd8558058 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Wed, 24 Jun 2020 12:14:06 +0100 Subject: [PATCH 08/16] Bugs in base_loss_type's handling of weights fixed --- ...s functions fitted to simulated data.ipynb | 1448 +++++++++-------- pygom/loss/base_loss.py | 2 +- pygom/loss/loss_type.py | 43 +- pygom/loss/ode_loss.py | 7 +- 4 files changed, 769 insertions(+), 731 deletions(-) diff --git a/notebooks/Testing loss functions fitted to simulated data.ipynb b/notebooks/Testing loss functions fitted to simulated data.ipynb index c73591c1..776f5847 100644 --- a/notebooks/Testing loss functions fitted to simulated data.ipynb +++ b/notebooks/Testing loss functions fitted to simulated data.ipynb @@ -87,7 +87,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -175,210 +175,210 @@ { "data": { "text/plain": [ - "array([[ 0. , 0. , nan],\n", - " [-0.26594371, 0.0481614 , 0.14354852],\n", - " [ 0.18044689, -0.21459589, -0.23607263],\n", - " [-0.22631835, -0.25986512, 0.00977265],\n", - " [ 0.08317535, -0.24033984, -0.13717155],\n", - " [ 0.01893378, -0.30765339, -0.20936384],\n", - " [-0.1927195 , -0.20495292, 0.14883087],\n", - " [-0.31513136, 0.29092017, 0.20333613],\n", - " [-0.0144959 , -0.15434097, 0.15017585],\n", - " [-0.06943103, -0.04553612, 0.24527238],\n", - " [ 0.1423363 , -0.26289285, -0.27731679],\n", - " [ 0.22902387, -0.11970823, -0.0786823 ],\n", - " [ 0.24507763, 0.13939913, 0.19873885],\n", - " [ 0.0851626 , 0.33156697, -0.02946794],\n", - " [-0.18589297, 0.28048003, 0.15186529],\n", - " [ 0.10976604, -0.27140908, -0.29451267],\n", - " [-0.02481169, -0.01567338, 0.12217416],\n", - " [-0.00554871, -0.31163176, 0.09909475],\n", - " [ 0.20449806, -0.13271217, -0.21380146],\n", - " [ 0.23288222, -0.26931907, 0.17116807],\n", - " [-0.16775002, -0.08171666, 0.3285523 ],\n", - " [-0.13957109, -0.00980709, -0.0315168 ],\n", - " [ 0.06701958, 0.12872299, -0.03394576],\n", - " [-0.10946453, 0.20814074, -0.19773507],\n", - " [ 0.01024636, -0.18041067, -0.23682284],\n", - " [-0.07439538, 0.25262383, -0.17858645],\n", - " [ 0.29102576, 0.1511979 , -0.14440452],\n", - " [-0.11485163, 0.04940554, 0.06448306],\n", - " [ 0.10676958, 0.21332199, -0.10266298],\n", - " [ 0.05285174, 0.14572103, -0.30224747],\n", - " [ 0.21323456, -0.11097107, -0.09723039],\n", - " [-0.26727707, 0.18230789, -0.04970821],\n", - " [ 0.16396675, 0.30519932, 0.19783618],\n", - " [-0.29474402, 0.26031346, 0.15008278],\n", - " [ 0.1983954 , -0.09186773, 0.1033981 ],\n", - " [ 0.01819894, -0.30503091, -0.00801638],\n", - " [ 0.18546865, 0.17688293, 0.07902597],\n", - " [ 0.0076256 , -0.30361511, -0.15894734],\n", - " [-0.14879804, -0.19371648, -0.20285748],\n", - " [ 0.02042512, -0.03584361, 0.02819072],\n", - " [ 0.23491568, -0.06869137, -0.17772354],\n", - " [-0.06566397, -0.06776337, -0.12467524],\n", - " [-0.24064783, -0.02981388, -0.20090267],\n", - " [-0.2546167 , -0.09699615, 0.33171511],\n", - " [-0.28714369, -0.15456429, 0.17458153],\n", - " [ 0.30123993, 0.18002521, 0.1692988 ],\n", - " [ 0.02128767, -0.15262815, -0.32506278],\n", - " [ 0.33296938, 0.237988 , -0.30015583],\n", - " [-0.2934129 , 0.08130536, -0.09999738],\n", - " [-0.3235725 , 0.13686141, -0.2596026 ],\n", - " [ 0.15582601, -0.02119342, 0.0201688 ],\n", - " [-0.09663488, -0.00329313, -0.0186065 ],\n", - " [-0.13049885, -0.2873186 , 0.15998342],\n", - " [ 0.1820132 , 0.15728375, -0.17590421],\n", - " [ 0.32023337, -0.29931336, -0.07075369],\n", - " [-0.2687179 , 0.11859697, 0.19943461],\n", - " [-0.15646938, 0.32058394, 0.11942069],\n", - " [ 0.01135593, 0.20676602, -0.19312968],\n", - " [-0.12103279, 0.27442481, -0.06271944],\n", - " [ 0.16266687, 0.31851177, 0.00352883],\n", - " [-0.08580615, 0.18960581, 0.16840495],\n", - " [-0.08982207, 0.03192396, 0.1188008 ],\n", - " [-0.20494301, -0.01120558, 0.25235198],\n", - " [-0.1467698 , 0.22918715, -0.1282447 ],\n", - " [ 0.17906087, -0.10461238, 0.13495474],\n", - " [ 0.17601782, -0.03623687, -0.25142906],\n", - " [ 0.30978103, 0.00397469, 0.22194208],\n", - " [ 0.25752416, 0.1042392 , 0.25591297],\n", - " [-0.13772319, -0.11275306, 0.01176822],\n", - " [-0.1576899 , -0.07936526, -0.14969428],\n", - " [ 0.22779235, 0.15750085, -0.28242108],\n", - " [-0.0992169 , -0.24829993, -0.24564635],\n", - " [ 0.2802134 , -0.26679643, 0.14145995],\n", - " [-0.19666873, 0.10925674, -0.15420511],\n", - " [-0.15718523, -0.04667504, 0.10463 ],\n", - " [ 0.23934475, 0.23012487, 0.19921085],\n", - " [-0.05472834, -0.01380446, -0.2970063 ],\n", - " [ 0.10511899, -0.21625187, -0.00291365],\n", - " [-0.25868477, -0.10864835, -0.10815295],\n", - " [-0.0549668 , -0.26682451, 0.30208219],\n", - " [-0.2252228 , -0.28258864, 0.24447319],\n", - " [ 0.32262681, 0.24986113, -0.26776005],\n", - " [-0.28439645, 0.17894896, 0.04479451],\n", - " [ 0.23324145, 0.14693671, 0.03221976],\n", - " [ 0.19536078, 0.29770609, 0.28112025],\n", - " [ 0.26628981, -0.05904756, 0.25696101],\n", - " [ 0.26286499, -0.21866198, 0.25475143],\n", - " [-0.17818083, 0.21188372, 0.2483309 ],\n", - " [ 0.17844389, 0.08694361, 0.28079217],\n", - " [-0.2312997 , 0.06568179, 0.13610579],\n", - " [ 0.2905747 , -0.25361048, -0.05708808],\n", - " [ 0.22593571, 0.09708349, 0.07385119],\n", - " [ 0.01186936, -0.15807059, -0.08762729],\n", - " [-0.00639177, 0.0221159 , -0.03221789],\n", - " [-0.11634133, -0.23084855, -0.08819899],\n", - " [ 0.10440324, -0.2578205 , 0.04979053],\n", - " [ 0.19253324, 0.08374047, -0.32555527],\n", - " [-0.31328116, -0.31449333, -0.29090413],\n", - " [ 0.11266601, 0.02762068, 0.05099049],\n", - " [-0.009882 , 0.11925011, 0.29849163],\n", - " [ 0.07112188, -0.17385365, 0.06267588],\n", - " [-0.23180648, -0.02778307, -0.30315784],\n", - " [-0.10563222, 0.06910103, 0.2532015 ],\n", - " [ 0.07369744, 0.26329815, 0.15720732],\n", - " [ 0.12417477, 0.245335 , -0.04359579],\n", - " [-0.01950269, -0.22894254, 0.27712502],\n", - " [ 0.04573258, -0.04995886, 0.31596549],\n", - " [ 0.16523415, -0.17750199, -0.154256 ],\n", - " [-0.06935528, -0.11561912, -0.32852905],\n", - " [ 0.17573865, -0.16438354, 0.08092944],\n", - " [-0.14557532, -0.16221617, 0.20846123],\n", - " [-0.1530618 , 0.00607467, 0.1679275 ],\n", - " [ 0.2915459 , 0.03303514, 0.01665417],\n", - " [ 0.25416671, -0.13892646, -0.32628175],\n", - " [ 0.18898644, 0.21485992, -0.16411458],\n", - " [-0.31186503, -0.23293792, 0.24676476],\n", - " [ 0.01727794, -0.16295204, 0.29225053],\n", - " [-0.30057741, -0.19557768, 0.28403295],\n", - " [-0.08805621, -0.21801336, -0.14952844],\n", - " [ 0.17080778, -0.19999893, 0.10857179],\n", - " [-0.01016595, 0.03945573, -0.23341481],\n", - " [ 0.0889063 , -0.22661675, 0.27247754],\n", - " [-0.10284494, -0.21721198, -0.01215395],\n", - " [ 0.04750522, -0.05609498, -0.11760032],\n", - " [-0.12049032, 0.16369776, 0.22946754],\n", - " [-0.3259247 , 0.14942894, 0.01034819],\n", - " [ 0.30482666, 0.10876203, 0.18606517],\n", - " [-0.22421853, -0.1229635 , 0.31979197],\n", - " [-0.31666275, 0.18239926, -0.31941235],\n", - " [-0.15058556, 0.2803648 , 0.29741955],\n", - " [ 0.27943625, -0.31952391, -0.11504683],\n", - " [ 0.02835105, -0.15542857, -0.12654592],\n", - " [ 0.25274379, 0.06784749, -0.02814774],\n", - " [ 0.18619024, -0.15448604, -0.27449163],\n", - " [-0.19728779, 0.02537731, -0.00569949],\n", - " [-0.21443474, -0.01553967, 0.091896 ],\n", - " [-0.26827219, -0.05445831, -0.02413247],\n", - " [ 0.00827749, 0.1737784 , -0.02126288],\n", - " [ 0.23937747, 0.25076279, -0.00298444],\n", - " [-0.12216854, 0.29956893, 0.2265178 ],\n", - " [ 0.15886145, 0.1952358 , -0.10230103],\n", - " [-0.16707728, -0.11592906, 0.23063125],\n", - " [ 0.08048473, -0.28616788, 0.27649409],\n", - " [-0.2399056 , 0.17466809, 0.2670509 ],\n", - " [ 0.01100893, -0.22544906, 0.03502344],\n", - " [-0.24534992, -0.0282792 , 0.04012958],\n", - " [-0.32417314, 0.30503388, 0.07024417],\n", - " [-0.30165476, -0.03131702, -0.11390332],\n", - " [ 0.11602546, 0.17258092, 0.27320442],\n", - " [-0.01679539, 0.17988321, 0.07326227],\n", - " [ 0.32585914, -0.31318578, 0.21703063],\n", - " [-0.25118099, 0.08755176, 0.1418994 ],\n", - " [ 0.25308867, 0.27702219, -0.26432973],\n", - " [ 0.1694537 , 0.15167072, -0.24991087],\n", - " [ 0.32780948, -0.30710299, -0.16902237],\n", - " [ 0.25018489, -0.24231413, 0.03174931],\n", - " [ 0.05986629, 0.03359792, -0.30558626],\n", - " [-0.30815473, -0.11973154, 0.01174757],\n", - " [-0.13523555, -0.02621417, 0.18494329],\n", - " [ 0.19637621, -0.06536179, 0.16160518],\n", - " [ 0.16124011, 0.12639132, -0.02431527],\n", - " [ 0.19221785, 0.24196546, 0.00068597],\n", - " [ 0.08134284, 0.31422214, -0.20704816],\n", - " [ 0.1727692 , 0.02115635, -0.13793911],\n", - " [-0.28248369, 0.05719562, -0.09881328],\n", - " [-0.15519892, 0.30149671, 0.30585306],\n", - " [ 0.18343869, -0.18022277, 0.23596179],\n", - " [-0.09597099, 0.31572377, -0.02601189],\n", - " [-0.23722386, -0.20593368, -0.01834659],\n", - " [ 0.21902069, 0.24623962, -0.19736678],\n", - " [ 0.02226348, 0.21272945, -0.30751679],\n", - " [-0.24202336, -0.2567437 , 0.14965649],\n", - " [-0.25945811, 0.28880295, 0.33275319],\n", - " [ 0.28975049, 0.04492393, 0.24388337],\n", - " [-0.09991367, 0.11365879, -0.30462007],\n", - " [-0.33098441, -0.20249934, -0.32534145],\n", - " [-0.00702099, -0.2097019 , -0.11255923],\n", - " [ 0.23478388, 0.14543586, 0.32737759],\n", - " [-0.32148961, 0.03430904, -0.23725884],\n", - " [-0.15295436, -0.23766421, 0.16057446],\n", - " [ 0.24874516, 0.02814334, 0.05567249],\n", - " [ 0.18373544, 0.05456167, -0.00065203],\n", - " [ 0.29179694, -0.02776448, -0.27429118],\n", - " [ 0.19373542, -0.10868194, 0.10012632],\n", - " [-0.05908267, -0.20556755, -0.06223371],\n", - " [-0.08392523, -0.13577942, -0.14284998],\n", - " [ 0.10779361, 0.11329162, 0.17968936],\n", - " [-0.04555323, 0.22342669, 0.302655 ],\n", - " [ 0.31417606, 0.32366651, -0.24461707],\n", - " [ 0.25052832, 0.04730799, 0.0135891 ],\n", - " [ 0.24008863, 0.11260373, 0.10348191],\n", - " [ 0.26464085, -0.16812188, -0.23981266],\n", - " [-0.23031692, 0.25901614, 0.25404338],\n", - " [-0.08783901, 0.21082491, 0.09234899],\n", - " [-0.12828791, 0.23402825, -0.13942016],\n", - " [ 0.17317795, 0.06544127, -0.32470743],\n", - " [-0.01350832, -0.20846687, 0.06141013],\n", - " [ 0.08516377, -0.27381567, 0.19523863],\n", - " [-0.2885919 , 0.04913673, 0.27292814],\n", - " [-0.14942594, -0.11490962, -0.27067257],\n", - " [ 0.0428627 , 0.22205546, 0.16590721],\n", - " [ 0.16898513, -0.03668338, -0.06368085],\n", - " [ 0.30915912, -0.13559047, -0.05790722],\n", - " [ 0.28353642, -0.20041566, -0.00223925]])" + "array([[ 0.00000000e+00, 0.00000000e+00, nan],\n", + " [-3.21943456e-01, 1.85865527e-01, -1.13217774e-01],\n", + " [-2.10940831e-01, -1.40000086e-01, 3.21150841e-01],\n", + " [ 1.81602995e-01, 1.28076820e-02, 2.49787871e-01],\n", + " [-1.99910787e-01, -3.21987422e-01, 6.59265374e-02],\n", + " [-3.07353570e-01, -2.27188132e-01, 2.17562011e-01],\n", + " [-5.63337347e-02, -1.89013740e-01, 2.84964767e-02],\n", + " [ 2.31501967e-01, 6.14997028e-02, -2.35895637e-01],\n", + " [ 2.23927782e-01, -1.01405449e-01, -1.98699260e-01],\n", + " [ 2.48735438e-01, -3.53640373e-02, 1.67031470e-01],\n", + " [ 4.94412026e-02, -1.52057161e-01, 2.09835766e-01],\n", + " [-2.06776227e-01, 3.13201462e-01, -4.29291297e-02],\n", + " [ 2.46433170e-02, -2.84114224e-01, 3.25711119e-03],\n", + " [ 1.92155506e-01, 2.17675626e-01, 5.62946687e-02],\n", + " [-1.44069462e-01, 1.35347749e-01, -1.82909871e-01],\n", + " [-8.29226910e-02, 3.23393603e-01, -2.81718008e-01],\n", + " [-3.76928728e-02, 3.23038547e-02, -2.86446432e-01],\n", + " [-3.11282664e-01, 1.27084504e-01, -2.59438059e-02],\n", + " [-2.62325766e-02, 2.69860578e-01, 1.18361484e-01],\n", + " [ 1.06221765e-01, -9.70804044e-02, -2.74947371e-01],\n", + " [-2.71437837e-02, -2.18447494e-01, -5.67370795e-02],\n", + " [-3.12189987e-01, 2.22512900e-01, -1.66663625e-01],\n", + " [-1.28018641e-01, -2.34923267e-01, 1.41683585e-02],\n", + " [ 2.32254315e-01, -3.26165428e-01, 2.34238143e-01],\n", + " [ 8.69678367e-02, 1.64301394e-01, -2.47656180e-01],\n", + " [ 1.40965168e-01, 6.32849105e-02, -9.45633773e-02],\n", + " [ 3.07096765e-01, -1.42502266e-01, -3.77726686e-02],\n", + " [-6.09429143e-02, 1.63808739e-01, 3.28916009e-01],\n", + " [ 3.82767127e-02, 3.20843549e-02, -7.79089580e-02],\n", + " [ 9.56398819e-02, 4.18597131e-02, 4.03213450e-02],\n", + " [ 1.27231497e-01, -8.30499409e-02, -7.31856628e-02],\n", + " [ 4.95710698e-02, 2.76706458e-01, 2.05492090e-01],\n", + " [-2.08266620e-01, 2.39049966e-01, 2.01173560e-01],\n", + " [-2.93349546e-01, -2.57007747e-01, 9.98727121e-03],\n", + " [-3.22996838e-01, 1.46160366e-01, 1.80225707e-01],\n", + " [-1.87518084e-01, -3.77615176e-02, -6.75263992e-02],\n", + " [ 1.79662877e-01, -1.35008808e-01, 2.83698888e-01],\n", + " [ 1.35604549e-02, -2.62201419e-01, -2.72549801e-01],\n", + " [ 3.88544297e-02, -5.52991492e-02, 1.35833062e-02],\n", + " [ 9.16412350e-04, -9.24962534e-02, 2.09220178e-01],\n", + " [ 3.25720195e-01, -1.13579915e-01, 6.44327795e-02],\n", + " [ 1.85011815e-01, 2.56123076e-01, -4.11627271e-02],\n", + " [-2.82554284e-01, 2.64315337e-01, -8.83167048e-02],\n", + " [-1.86349157e-01, 3.56996669e-02, 2.01663352e-01],\n", + " [-1.57759231e-01, 1.39231206e-01, -1.85782649e-01],\n", + " [ 7.03547306e-02, 1.01422084e-01, 1.23427057e-01],\n", + " [ 2.76699346e-02, -3.91221695e-02, 2.16061024e-01],\n", + " [ 1.59004020e-01, -2.21259419e-01, 3.27064373e-01],\n", + " [ 1.47263354e-01, -1.04940533e-01, 2.44662128e-01],\n", + " [-1.02896184e-01, -1.55783920e-01, 2.95573231e-01],\n", + " [-2.68855926e-01, 3.19496258e-01, -2.91857351e-01],\n", + " [ 1.13792396e-01, -1.79844552e-01, 3.31017884e-01],\n", + " [-2.88347996e-01, -2.13458276e-01, 7.44025583e-02],\n", + " [ 7.94402079e-02, -4.94810671e-02, -5.15517506e-02],\n", + " [ 2.73209861e-01, 4.98005575e-02, 3.17599430e-01],\n", + " [-1.26001530e-01, 1.86226792e-01, -2.41490855e-01],\n", + " [ 2.20762784e-01, 2.08149383e-01, -1.95067777e-01],\n", + " [ 7.66135816e-02, -2.49310855e-01, -9.13035120e-02],\n", + " [ 1.97046212e-01, -2.14907322e-02, 3.29487704e-01],\n", + " [ 1.55059587e-01, -2.26415078e-01, 1.59962712e-01],\n", + " [ 2.11096333e-01, -2.65176253e-01, -4.05930821e-03],\n", + " [ 2.79075501e-01, 1.92098721e-01, -8.23100303e-02],\n", + " [-3.08439506e-01, -7.98957238e-02, -5.01829836e-02],\n", + " [-2.03697278e-01, 2.05995436e-01, -9.14985961e-02],\n", + " [ 1.20521659e-01, 3.00440276e-01, 1.47263752e-02],\n", + " [-2.27957751e-01, -8.21201620e-02, -1.19488396e-02],\n", + " [ 1.59556225e-01, -2.82204036e-02, -2.21599601e-01],\n", + " [ 2.15680392e-01, 3.03996830e-01, -2.71423977e-01],\n", + " [ 1.77769288e-01, 2.09960478e-01, 8.39473619e-02],\n", + " [ 1.13717062e-01, -1.79358977e-01, -4.59715825e-03],\n", + " [-1.84322552e-01, -2.26755373e-01, -2.39767730e-01],\n", + " [ 1.86058326e-01, -3.21698703e-01, -2.46524540e-01],\n", + " [ 2.86200529e-01, -2.17887930e-01, 3.57893365e-02],\n", + " [-1.18158603e-01, -6.54001442e-02, -2.87505412e-01],\n", + " [-1.50315173e-01, 1.42851125e-01, 2.20421926e-01],\n", + " [-2.23556346e-01, -1.92795329e-01, 1.74674105e-01],\n", + " [-2.31639431e-01, -4.84220495e-02, -8.52286090e-02],\n", + " [ 1.20174394e-01, -1.96588635e-01, 2.49598607e-01],\n", + " [ 1.96578388e-01, -6.38269970e-02, 9.43425551e-02],\n", + " [-3.81314176e-02, 3.18781466e-01, 1.77470481e-01],\n", + " [ 4.32925130e-02, -2.00318211e-01, 4.17754219e-02],\n", + " [ 2.36790925e-01, -1.03921195e-01, -3.30797879e-02],\n", + " [ 1.99476702e-01, -1.43344835e-01, 5.64405904e-02],\n", + " [ 3.31310790e-01, 1.50853809e-01, 1.35732696e-01],\n", + " [-2.41321604e-01, 3.19392547e-01, -4.54542545e-02],\n", + " [-6.91929812e-03, -2.13076727e-01, -1.63392477e-01],\n", + " [-1.22865716e-01, -1.78234910e-01, 2.03967351e-01],\n", + " [ 3.30704049e-01, 9.71682583e-02, -3.08190158e-01],\n", + " [ 2.00774222e-01, -1.42644728e-01, -2.98044193e-01],\n", + " [-2.23396056e-01, -2.40914551e-01, 2.12421125e-01],\n", + " [ 7.12265936e-02, 2.47778623e-02, -2.88177768e-01],\n", + " [-2.60885258e-01, 3.13300871e-01, 1.71580578e-01],\n", + " [-1.36024349e-01, -6.65814427e-02, -6.26423574e-02],\n", + " [ 1.55892372e-01, 2.48340883e-01, -2.95586414e-01],\n", + " [-1.77048639e-01, 3.20849855e-02, 3.03433400e-01],\n", + " [ 1.31558930e-01, 2.33285122e-01, -2.34144482e-02],\n", + " [-9.99275328e-02, -8.26120829e-02, 2.48214915e-01],\n", + " [ 1.06138964e-01, 1.75757064e-01, -3.19240383e-01],\n", + " [ 1.62623817e-01, 2.72537446e-02, -5.92349069e-02],\n", + " [-1.50942703e-01, 8.10263676e-02, -2.45111595e-01],\n", + " [ 1.80449990e-01, 2.72827791e-01, 1.08298678e-01],\n", + " [-2.32438202e-01, 2.88886019e-01, -1.84345430e-01],\n", + " [ 2.49503066e-01, 3.10983987e-01, -2.86543276e-01],\n", + " [ 1.20511488e-01, 5.13694112e-03, 1.36225876e-01],\n", + " [ 2.68332086e-01, 3.15883069e-01, 4.00702873e-02],\n", + " [-2.69552790e-01, 1.13927547e-01, -1.31478459e-01],\n", + " [ 1.53144584e-01, 2.49076716e-01, -2.26674703e-01],\n", + " [-1.03603484e-01, -2.10210157e-02, -2.41978432e-01],\n", + " [ 1.96105677e-01, -2.68912665e-01, 2.84057482e-01],\n", + " [ 1.07999685e-01, 9.50813469e-02, 1.44150697e-01],\n", + " [ 1.18566775e-02, 1.67907743e-01, 8.67410283e-02],\n", + " [-1.40939249e-01, 2.15215929e-01, 1.36839282e-01],\n", + " [-9.05791123e-02, -1.79494555e-01, -3.22292115e-01],\n", + " [-1.62777658e-01, -1.38902568e-01, -1.04280378e-01],\n", + " [-2.48846862e-01, 5.49497354e-02, -2.55146872e-01],\n", + " [-1.92560097e-01, 2.75780669e-01, 1.38053097e-02],\n", + " [ 7.22306638e-02, 2.51954666e-01, 2.00025665e-01],\n", + " [-1.48601712e-01, -6.24716939e-02, 1.22190401e-01],\n", + " [ 2.96343742e-01, -9.16466617e-02, -2.79057616e-01],\n", + " [-9.44903089e-02, 2.02212337e-01, 1.30955098e-01],\n", + " [ 2.59779211e-01, -3.17918046e-01, 1.04952796e-01],\n", + " [-9.19699690e-02, 3.24716030e-01, 1.02188300e-01],\n", + " [-1.56266425e-01, 2.22184605e-01, 9.96280301e-02],\n", + " [-8.09897738e-02, 1.34471312e-01, -7.32451926e-02],\n", + " [-1.40359625e-01, -2.11776854e-02, -3.10384400e-01],\n", + " [-2.73853206e-01, -1.95512118e-01, 3.98482839e-02],\n", + " [-1.27223980e-01, -2.32593176e-01, 1.70883648e-01],\n", + " [ 4.92405598e-02, 8.50372783e-02, 4.05976680e-02],\n", + " [ 1.29315076e-01, 1.81514925e-01, 2.69971751e-01],\n", + " [ 5.07861648e-02, -7.40873609e-02, 1.65365118e-01],\n", + " [ 2.68151227e-01, -1.45063285e-01, -2.16386660e-02],\n", + " [-3.17820212e-01, 1.62066777e-01, -2.07795803e-01],\n", + " [-3.16812154e-01, 2.96508501e-01, 1.92175410e-01],\n", + " [ 1.96337705e-01, 8.81620255e-02, -1.02653817e-01],\n", + " [-1.93525139e-01, -2.03936400e-01, 1.70445013e-01],\n", + " [-2.87456720e-02, -1.07611842e-01, 2.49101875e-01],\n", + " [ 8.09404791e-02, -3.21299706e-02, 1.23033680e-01],\n", + " [ 2.59498758e-01, -2.55703800e-02, -2.66267193e-01],\n", + " [ 2.35573590e-01, -1.56838315e-01, 2.56689692e-01],\n", + " [ 1.30542822e-01, 2.69746313e-01, -2.57985160e-01],\n", + " [ 1.74263648e-01, 2.29095931e-01, 7.48744349e-02],\n", + " [ 2.86189769e-01, 2.79547063e-01, 6.85199411e-02],\n", + " [-1.05937815e-01, 1.79938630e-01, 7.44842201e-02],\n", + " [ 2.15354490e-01, 1.79798390e-01, 1.86155500e-01],\n", + " [-2.40897200e-01, -1.23944817e-01, 6.86891899e-05],\n", + " [ 1.92303073e-01, 2.93842299e-01, 1.69436631e-01],\n", + " [ 6.00638743e-02, -1.92023781e-01, -2.35632974e-01],\n", + " [ 1.08886035e-01, -3.11263490e-01, 6.42473250e-02],\n", + " [-2.28977828e-01, -2.88312273e-01, -4.60168657e-02],\n", + " [ 1.88477181e-03, -1.41546947e-01, 3.28242664e-01],\n", + " [-1.73354229e-01, 3.13080313e-01, 2.87096208e-01],\n", + " [ 4.29327556e-02, -1.06010816e-01, 2.17850274e-01],\n", + " [ 6.71826155e-02, 6.18062750e-03, -1.61497479e-01],\n", + " [ 1.03828416e-01, 1.42508637e-01, 3.30062436e-01],\n", + " [ 2.68190801e-01, -2.61865575e-02, -4.02513191e-02],\n", + " [-2.31829458e-01, -1.09360422e-01, -3.29300076e-01],\n", + " [-1.81418170e-01, -5.11671925e-02, -9.01593327e-02],\n", + " [-3.11486686e-01, 3.11728877e-02, -3.05828061e-01],\n", + " [ 1.86347159e-01, 2.36229401e-01, 3.01929479e-01],\n", + " [-2.92591029e-01, 9.08584343e-02, -1.40299446e-01],\n", + " [-1.05944855e-02, 1.61865581e-01, -2.50704225e-01],\n", + " [-2.45622639e-02, -3.16306034e-01, -2.69959629e-01],\n", + " [ 8.84372993e-02, -2.81337428e-01, 1.35729306e-01],\n", + " [-6.21876036e-02, -5.41408363e-02, 1.77717783e-01],\n", + " [ 2.05371132e-01, 1.73047469e-02, 3.20133765e-01],\n", + " [ 1.28758414e-01, 4.28390061e-03, 8.84307448e-02],\n", + " [ 2.02100596e-01, -6.90202732e-03, -1.15680333e-01],\n", + " [ 4.91767073e-02, 2.68686316e-01, 1.27224288e-01],\n", + " [ 1.53107746e-01, -2.24791872e-01, -2.82729565e-01],\n", + " [ 1.27456089e-01, 2.89267392e-02, -2.31685444e-01],\n", + " [ 1.21530019e-01, -1.50701614e-01, -2.20018436e-01],\n", + " [ 2.40944283e-01, -5.44516998e-02, 1.78625669e-01],\n", + " [-2.20691466e-01, 2.27806142e-01, -3.19788277e-01],\n", + " [ 5.43321208e-02, -1.68073613e-01, 2.88610851e-01],\n", + " [-5.14881733e-02, -2.17052746e-01, 8.46518610e-02],\n", + " [-3.26344726e-01, -2.65734801e-01, -3.29900167e-01],\n", + " [ 2.91065837e-01, -8.86418051e-02, 1.43952139e-01],\n", + " [-3.18629385e-01, 2.42564945e-01, -1.50746165e-01],\n", + " [ 1.31558589e-02, -1.37399607e-01, -3.10027779e-02],\n", + " [-2.82888143e-01, -1.97311938e-01, -1.71934170e-01],\n", + " [-3.26726159e-01, -1.46398217e-01, -2.67336805e-01],\n", + " [-2.50764400e-01, 2.40030847e-01, 1.90164020e-01],\n", + " [-1.86402443e-01, -1.59800689e-01, -1.24289238e-01],\n", + " [-3.23243518e-01, 1.64399910e-01, 1.89434490e-02],\n", + " [ 1.62444666e-01, 1.72003606e-01, 3.15533874e-01],\n", + " [ 4.11196377e-02, -8.77415417e-02, 1.23995207e-01],\n", + " [ 1.28272258e-01, -2.32939686e-02, 4.35417997e-02],\n", + " [-1.75479288e-01, 9.41603764e-02, 2.52966436e-01],\n", + " [-1.12455732e-01, 1.64264689e-01, -3.33227910e-01],\n", + " [-2.10629561e-02, 2.63683701e-01, -2.22926132e-01],\n", + " [ 4.89649368e-02, 1.17222997e-01, 2.04754960e-01],\n", + " [-1.00714628e-01, 7.93490662e-02, -7.47079386e-02],\n", + " [ 2.92136018e-03, 1.29087068e-01, -1.48908029e-01],\n", + " [ 1.13242124e-01, -1.04279228e-01, 2.47219125e-01],\n", + " [-2.18469863e-01, -1.99858094e-01, -3.11419043e-01],\n", + " [ 2.82152105e-01, -5.74810426e-02, 6.78507853e-02],\n", + " [ 1.90039518e-01, -2.49188273e-01, -2.24943614e-01],\n", + " [-1.39040280e-01, -1.70893861e-01, -9.90695495e-02],\n", + " [-1.54891812e-01, 2.19340978e-01, -2.86544108e-03],\n", + " [ 1.54253118e-01, 1.73852897e-01, -1.74464629e-01],\n", + " [-9.57521372e-02, 1.46961351e-01, 3.27614130e-01],\n", + " [ 3.20980053e-01, -1.54030722e-01, -3.70355927e-03],\n", + " [ 1.10411322e-01, -1.66169988e-01, -2.91024643e-01],\n", + " [ 2.03023170e-01, 2.57521968e-01, -1.37497649e-01]])" ] }, "execution_count": 8, @@ -400,7 +400,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -436,209 +436,209 @@ { "data": { "text/plain": [ - "array([[4.90464096e+00, 1.80229297e-01],\n", - " [8.59843745e+00, 4.02088747e-01],\n", - " [1.89574734e+01, 1.40262775e+00],\n", - " [4.55221314e+01, 2.94002911e+00],\n", - " [9.70595088e+01, 6.42741549e+00],\n", - " [2.60715165e+02, 2.20294695e+01],\n", - " [9.89941096e+02, 5.41627913e+01],\n", - " [1.51549915e+03, 1.21234960e+02],\n", - " [3.99119374e+03, 3.06882053e+02],\n", - " [7.16646079e+03, 4.15491759e+02],\n", - " [1.97356855e+04, 1.23045676e+03],\n", - " [5.78166023e+04, 3.68388673e+03],\n", - " [1.46862042e+05, 6.72234947e+03],\n", - " [2.83221926e+05, 1.72384073e+04],\n", - " [2.82099064e+05, 2.11595297e+04],\n", - " [5.58399812e+05, 6.05232963e+04],\n", - " [4.82619234e+05, 9.44362098e+04],\n", - " [6.65765758e+05, 9.66241419e+04],\n", - " [5.72747123e+05, 1.89549046e+05],\n", - " [7.09146912e+05, 2.66809758e+05],\n", - " [7.40234990e+05, 2.31329292e+05],\n", - " [8.09839926e+05, 2.66144343e+05],\n", - " [8.28408036e+05, 2.49165951e+05],\n", - " [5.35922195e+05, 2.62582973e+05],\n", - " [7.80220803e+05, 3.08835399e+05],\n", - " [6.82617907e+05, 3.47689342e+05],\n", - " [5.92186788e+05, 4.63366922e+05],\n", - " [6.51475912e+05, 4.15308489e+05],\n", - " [5.85276935e+05, 3.41209635e+05],\n", - " [4.32046981e+05, 4.63958279e+05],\n", - " [5.46589709e+05, 5.10905271e+05],\n", - " [5.74001575e+05, 6.71000810e+05],\n", - " [5.27246397e+05, 6.68918229e+05],\n", - " [3.61392141e+05, 6.64278025e+05],\n", - " [2.63079400e+05, 6.16456105e+05],\n", - " [4.23783943e+05, 6.90468622e+05],\n", - " [2.38533388e+05, 5.52959981e+05],\n", - " [2.62709237e+05, 5.37407391e+05],\n", - " [2.98828587e+05, 7.09511325e+05],\n", - " [2.74571172e+05, 5.79847948e+05],\n", - " [2.61441068e+05, 6.29842262e+05],\n", - " [2.58814617e+05, 5.85922250e+05],\n", - " [2.29144409e+05, 9.93779854e+05],\n", - " [2.04073231e+05, 8.91056939e+05],\n", - " [2.70945802e+05, 9.00814781e+05],\n", - " [1.85076291e+05, 5.27522223e+05],\n", - " [2.57204604e+05, 5.54443973e+05],\n", - " [2.13695888e+05, 7.22136698e+05],\n", - " [2.13717852e+05, 6.01210232e+05],\n", - " [1.75031250e+05, 8.37740727e+05],\n", - " [1.69539766e+05, 8.14458217e+05],\n", - " [1.15314773e+05, 9.72293020e+05],\n", - " [1.78120848e+05, 6.97256650e+05],\n", - " [1.02585057e+05, 7.93198444e+05],\n", - " [1.55782711e+05, 1.03239372e+06],\n", - " [1.74943163e+05, 9.71126263e+05],\n", - " [1.52068538e+05, 7.05193833e+05],\n", - " [1.52762181e+05, 8.24930915e+05],\n", - " [1.50338761e+05, 8.89104794e+05],\n", - " [1.29025441e+05, 1.04167885e+06],\n", - " [1.06464615e+05, 1.00337291e+06],\n", - " [9.70395803e+04, 1.12944693e+06],\n", - " [1.14748290e+05, 7.90374269e+05],\n", - " [7.95105215e+04, 1.03417055e+06],\n", - " [8.14083834e+04, 6.85339633e+05],\n", - " [8.06690402e+04, 1.12375935e+06],\n", - " [8.43980836e+04, 1.15992224e+06],\n", - " [6.45058699e+04, 9.38209174e+05],\n", - " [6.36689048e+04, 7.91500558e+05],\n", - " [7.61459197e+04, 6.70373122e+05],\n", - " [4.70386884e+04, 7.07148873e+05],\n", - " [4.36435911e+04, 1.07351504e+06],\n", - " [6.28077554e+04, 7.97904695e+05],\n", - " [5.13460989e+04, 1.04513457e+06],\n", - " [6.30232768e+04, 1.13777135e+06],\n", - " [4.80618082e+04, 6.68733585e+05],\n", - " [3.63328010e+04, 9.50863634e+05],\n", - " [3.93058078e+04, 8.52519368e+05],\n", - " [3.07539481e+04, 1.24746471e+06],\n", - " [2.86250646e+04, 1.19481806e+06],\n", - " [4.74378807e+04, 7.04448109e+05],\n", - " [4.25641347e+04, 1.00707379e+06],\n", - " [3.93888722e+04, 9.96770546e+05],\n", - " [4.23931532e+04, 1.23926888e+06],\n", - " [2.92396611e+04, 1.21790150e+06],\n", - " [2.30955819e+04, 1.21766218e+06],\n", - " [3.40750253e+04, 1.21323104e+06],\n", - " [2.90715064e+04, 1.24653594e+06],\n", - " [2.71127364e+04, 1.10720133e+06],\n", - " [1.80632805e+04, 9.20092600e+05],\n", - " [2.52555051e+04, 1.04913048e+06],\n", - " [1.84364518e+04, 8.92393680e+05],\n", - " [2.12905604e+04, 9.47623291e+05],\n", - " [1.52399694e+04, 8.93734566e+05],\n", - " [1.39883494e+04, 1.03000441e+06],\n", - " [1.94297894e+04, 6.62352965e+05],\n", - " [1.16906798e+04, 6.97002881e+05],\n", - " [1.66704070e+04, 1.03394095e+06],\n", - " [1.72713306e+04, 1.27845437e+06],\n", - " [1.21266522e+04, 1.04707729e+06],\n", - " [1.35747674e+04, 6.87112352e+05],\n", - " [1.41995065e+04, 1.23655680e+06],\n", - " [1.59604690e+04, 1.14258717e+06],\n", - " [1.49661903e+04, 9.44910315e+05],\n", - " [8.81448811e+03, 1.26252531e+06],\n", - " [1.03308974e+04, 1.30165545e+06],\n", - " [8.50777068e+03, 8.36995757e+05],\n", - " [8.70172886e+03, 6.64864104e+05],\n", - " [7.82093131e+03, 1.07081249e+06],\n", - " [7.45879620e+03, 1.19770227e+06],\n", - " [8.52024863e+03, 1.15803653e+06],\n", - " [8.32189873e+03, 1.00846421e+06],\n", - " [6.59831222e+03, 6.68555612e+05],\n", - " [8.85531680e+03, 8.29792492e+05],\n", - " [5.31855548e+03, 1.23812008e+06],\n", - " [5.52075923e+03, 1.28372745e+06],\n", - " [5.04682049e+03, 1.27597711e+06],\n", - " [4.66679110e+03, 8.45396050e+05],\n", - " [4.54145355e+03, 1.10227862e+06],\n", - " [5.61300707e+03, 7.62445652e+05],\n", - " [3.97255243e+03, 1.26594133e+06],\n", - " [3.82476121e+03, 9.83019339e+05],\n", - " [4.38706165e+03, 8.78298467e+05],\n", - " [5.14482874e+03, 1.22403191e+06],\n", - " [4.83390522e+03, 1.00609917e+06],\n", - " [4.43546984e+03, 1.18132044e+06],\n", - " [3.33736908e+03, 1.31476977e+06],\n", - " [4.27992342e+03, 6.78124116e+05],\n", - " [4.40850014e+03, 1.29295231e+06],\n", - " [2.22871884e+03, 8.82054729e+05],\n", - " [2.63126192e+03, 8.70732818e+05],\n", - " [3.16462468e+03, 9.68972110e+05],\n", - " [2.38352132e+03, 7.23463131e+05],\n", - " [2.74958560e+03, 9.91634243e+05],\n", - " [2.51111756e+03, 1.08911082e+06],\n", - " [2.29421855e+03, 9.73499719e+05],\n", - " [2.70910290e+03, 9.76478163e+05],\n", - " [2.74599424e+03, 9.94826643e+05],\n", - " [2.71399644e+03, 1.22395635e+06],\n", - " [2.37437235e+03, 8.95915646e+05],\n", - " [1.67058137e+03, 1.22830577e+06],\n", - " [1.28310408e+03, 1.27419959e+06],\n", - " [2.00847418e+03, 1.26488445e+06],\n", - " [1.25975575e+03, 1.03334003e+06],\n", - " [1.50336053e+03, 1.03852036e+06],\n", - " [1.92056369e+03, 1.06866912e+06],\n", - " [1.35604430e+03, 8.84856232e+05],\n", - " [1.56142207e+03, 1.27150899e+06],\n", - " [1.49452022e+03, 1.07190279e+06],\n", - " [8.27536828e+02, 1.21556422e+06],\n", - " [1.24647414e+03, 1.14059062e+06],\n", - " [1.39224948e+03, 7.34868209e+05],\n", - " [1.19435169e+03, 7.49311234e+05],\n", - " [6.83530459e+02, 8.30157875e+05],\n", - " [7.10990264e+02, 1.03078113e+06],\n", - " [9.22595586e+02, 6.93793896e+05],\n", - " [7.47412178e+02, 1.01088851e+06],\n", - " [7.86491010e+02, 1.18398624e+06],\n", - " [7.18057337e+02, 1.16071273e+06],\n", - " [8.23171200e+02, 9.74971676e+05],\n", - " [8.63367455e+02, 9.99990314e+05],\n", - " [8.69040904e+02, 7.92427482e+05],\n", - " [6.42316325e+02, 8.61518628e+05],\n", - " [6.32553637e+02, 9.00647496e+05],\n", - " [7.40747779e+02, 1.30510982e+06],\n", - " [4.43821580e+02, 1.23529263e+06],\n", - " [6.77583106e+02, 9.73486505e+05],\n", - " [3.88991313e+02, 9.81172515e+05],\n", - " [5.80724252e+02, 8.02259191e+05],\n", - " [5.37548455e+02, 6.92176252e+05],\n", - " [3.13384546e+02, 1.14917174e+06],\n", - " [5.16905055e+02, 1.33221864e+06],\n", - " [3.98652245e+02, 1.24340879e+06],\n", - " [4.04154080e+02, 6.95127565e+05],\n", - " [2.75303132e+02, 6.74425641e+05],\n", - " [2.59511329e+02, 8.87149341e+05],\n", - " [3.57784433e+02, 1.32696295e+06],\n", - " [3.07316774e+02, 7.62514516e+05],\n", - " [2.15460438e+02, 1.16024642e+06],\n", - " [2.76414090e+02, 1.05538866e+06],\n", - " [2.69689336e+02, 9.99092387e+05],\n", - " [2.36509482e+02, 7.25532274e+05],\n", - " [2.06250526e+02, 1.09987173e+06],\n", - " [1.74865694e+02, 9.37559865e+05],\n", - " [1.80949557e+02, 8.56970535e+05],\n", - " [2.21731370e+02, 1.17945438e+06],\n", - " [2.31782922e+02, 1.30240818e+06],\n", - " [2.38543368e+02, 7.55246791e+05],\n", - " [1.79534727e+02, 1.01341533e+06],\n", - " [1.81426132e+02, 1.10330196e+06],\n", - " [1.29034045e+02, 7.60069418e+05],\n", - " [1.85763844e+02, 1.25385833e+06],\n", - " [1.69940356e+02, 1.09219566e+06],\n", - " [1.64750052e+02, 8.60464933e+05],\n", - " [1.35305439e+02, 6.75206798e+05],\n", - " [9.56181015e+01, 1.06128189e+06],\n", - " [8.34455489e+01, 1.19510127e+06],\n", - " [1.14676301e+02, 1.27278898e+06],\n", - " [9.20268352e+01, 7.29251586e+05],\n", - " [1.20865697e+02, 1.16579188e+06],\n", - " [9.06288530e+01, 9.36231050e+05],\n", - " [7.73574703e+01, 9.42008457e+05],\n", - " [6.80663206e+01, 9.97675798e+05]])" + "array([[5.54899714e+00, 1.39761571e-01],\n", + " [9.41509648e+00, 6.95380093e-01],\n", + " [2.59415887e+01, 1.73602161e+00],\n", + " [4.06294543e+01, 3.63207199e+00],\n", + " [1.08339867e+02, 9.89807619e+00],\n", + " [2.65942008e+02, 1.97219908e+01],\n", + " [8.14010192e+02, 3.43927387e+01],\n", + " [1.61036450e+03, 8.44615745e+01],\n", + " [4.03372942e+03, 2.87600545e+02],\n", + " [8.24405119e+03, 6.95570046e+02],\n", + " [2.94412965e+04, 1.27820655e+03],\n", + " [3.63262375e+04, 3.08314488e+03],\n", + " [1.34300664e+05, 7.31638055e+03],\n", + " [2.51120961e+05, 1.22282810e+04],\n", + " [5.12397402e+05, 2.15432773e+04],\n", + " [5.85616873e+05, 3.84847695e+04],\n", + " [7.90205922e+05, 8.36926709e+04],\n", + " [9.74797129e+05, 1.37447113e+05],\n", + " [7.07757082e+05, 1.17346978e+05],\n", + " [6.03556137e+05, 1.89433078e+05],\n", + " [9.13909621e+05, 1.99048484e+05],\n", + " [5.48929799e+05, 2.79399602e+05],\n", + " [4.62040519e+05, 3.83327390e+05],\n", + " [7.61326355e+05, 2.58855593e+05],\n", + " [6.62287422e+05, 3.40426427e+05],\n", + " [5.08464539e+05, 3.91021455e+05],\n", + " [6.56745303e+05, 5.78473948e+05],\n", + " [5.54162951e+05, 4.26765230e+05],\n", + " [5.32220707e+05, 5.08730031e+05],\n", + " [4.45615989e+05, 4.76315527e+05],\n", + " [5.90230868e+05, 6.48108582e+05],\n", + " [5.44910361e+05, 6.72870334e+05],\n", + " [3.10827425e+05, 5.87435017e+05],\n", + " [4.56115660e+05, 7.10530498e+05],\n", + " [3.64253784e+05, 5.79474331e+05],\n", + " [3.11474802e+05, 8.21438803e+05],\n", + " [2.52718860e+05, 4.78270705e+05],\n", + " [3.07809391e+05, 6.83324686e+05],\n", + " [2.81269787e+05, 8.34432164e+05],\n", + " [2.61336999e+05, 7.50610280e+05],\n", + " [3.52273390e+05, 6.89933915e+05],\n", + " [3.37278880e+05, 6.68473671e+05],\n", + " [2.62817027e+05, 8.96729957e+05],\n", + " [2.74990268e+05, 6.17678724e+05],\n", + " [2.52897724e+05, 8.65475700e+05],\n", + " [2.09867373e+05, 9.50457602e+05],\n", + " [1.61791280e+05, 1.05135240e+06],\n", + " [1.76888541e+05, 9.98681754e+05],\n", + " [1.58703643e+05, 1.05201866e+06],\n", + " [2.35953746e+05, 5.81511546e+05],\n", + " [1.39508382e+05, 1.10461141e+06],\n", + " [1.27265676e+05, 9.00559518e+05],\n", + " [1.46297085e+05, 8.02469639e+05],\n", + " [1.53697592e+05, 1.12469407e+06],\n", + " [1.65201257e+05, 6.52874344e+05],\n", + " [1.60048497e+05, 6.98299422e+05],\n", + " [9.45967979e+04, 7.94188534e+05],\n", + " [1.17291509e+05, 1.17012509e+06],\n", + " [8.82053548e+04, 1.02770182e+06],\n", + " [7.96994745e+04, 8.87920192e+05],\n", + " [1.22990003e+05, 8.23010899e+05],\n", + " [9.02983786e+04, 8.56602566e+05],\n", + " [1.12583275e+05, 8.23690011e+05],\n", + " [1.15479244e+05, 9.24618482e+05],\n", + " [7.75326545e+04, 9.04591116e+05],\n", + " [7.80821749e+04, 7.15856130e+05],\n", + " [9.96657551e+04, 6.72890200e+05],\n", + " [8.79682412e+04, 1.00514064e+06],\n", + " [5.67535777e+04, 9.26563100e+05],\n", + " [5.08677148e+04, 7.10220532e+05],\n", + " [4.24456569e+04, 7.06325639e+05],\n", + " [4.65548460e+04, 9.74134427e+05],\n", + " [5.29184248e+04, 6.72152061e+05],\n", + " [6.15539817e+04, 1.15468993e+06],\n", + " [4.13557069e+04, 1.11449170e+06],\n", + " [4.63747352e+04, 8.70190374e+05],\n", + " [3.72443444e+04, 1.19166998e+06],\n", + " [4.12822885e+04, 1.04608545e+06],\n", + " [5.53179116e+04, 1.12807999e+06],\n", + " [3.19076952e+04, 1.00020804e+06],\n", + " [3.40102420e+04, 9.30221189e+05],\n", + " [3.09282140e+04, 1.01829940e+06],\n", + " [3.95233957e+04, 1.09672857e+06],\n", + " [4.31016012e+04, 9.23362846e+05],\n", + " [2.44532763e+04, 8.10610309e+05],\n", + " [2.42905662e+04, 1.16837923e+06],\n", + " [3.08495243e+04, 6.72357927e+05],\n", + " [2.29309129e+04, 6.83181207e+05],\n", + " [1.93124101e+04, 1.18157506e+06],\n", + " [2.48005224e+04, 6.94595493e+05],\n", + " [3.02329559e+04, 1.14461008e+06],\n", + " [2.04398683e+04, 9.16831496e+05],\n", + " [2.60028015e+04, 6.89740714e+05],\n", + " [2.04497354e+04, 1.27760714e+06],\n", + " [2.32445428e+04, 9.58179175e+05],\n", + " [1.64473455e+04, 1.22583633e+06],\n", + " [2.00514453e+04, 6.69149880e+05],\n", + " [1.66644545e+04, 9.25503667e+05],\n", + " [1.66814938e+04, 7.43239584e+05],\n", + " [1.86832999e+04, 1.09203041e+06],\n", + " [1.79963211e+04, 8.04265819e+05],\n", + " [1.74121296e+04, 7.03980774e+05],\n", + " [1.26988684e+04, 1.12187081e+06],\n", + " [1.58140231e+04, 1.02757091e+06],\n", + " [1.27340719e+04, 8.58592858e+05],\n", + " [1.35826575e+04, 7.64916022e+05],\n", + " [1.01263816e+04, 7.50180716e+05],\n", + " [7.19342074e+03, 1.27142317e+06],\n", + " [1.02493864e+04, 1.13344203e+06],\n", + " [1.03978921e+04, 1.07706574e+06],\n", + " [1.02914248e+04, 1.12721159e+06],\n", + " [6.60980734e+03, 6.72248410e+05],\n", + " [6.59849528e+03, 8.88855805e+05],\n", + " [7.68970477e+03, 7.39423756e+05],\n", + " [8.84584242e+03, 1.00677590e+06],\n", + " [8.25728105e+03, 1.19211086e+06],\n", + " [5.88190675e+03, 1.11514993e+06],\n", + " [5.42093057e+03, 7.16639885e+05],\n", + " [6.82473026e+03, 1.12453486e+06],\n", + " [3.68320721e+03, 1.09898609e+06],\n", + " [6.80452270e+03, 1.09652679e+06],\n", + " [5.97168604e+03, 1.09425515e+06],\n", + " [5.27277158e+03, 9.22447441e+05],\n", + " [4.32747516e+03, 6.86566727e+05],\n", + " [3.38326107e+03, 1.03547520e+06],\n", + " [3.06991919e+03, 1.16619965e+06],\n", + " [4.12887018e+03, 1.03663789e+06],\n", + " [4.27672242e+03, 1.26537482e+06],\n", + " [3.18806484e+03, 1.16135256e+06],\n", + " [2.80011832e+03, 9.75156955e+05],\n", + " [3.62041856e+03, 7.89736072e+05],\n", + " [3.84227414e+03, 1.18864231e+06],\n", + " [3.06755125e+03, 8.94816531e+05],\n", + " [2.13467277e+03, 1.16730640e+06],\n", + " [2.27626397e+03, 1.24591570e+06],\n", + " [2.34839501e+03, 1.12030879e+06],\n", + " [2.24900213e+03, 7.32039326e+05],\n", + " [1.85112410e+03, 1.25393067e+06],\n", + " [2.65171542e+03, 7.40465218e+05],\n", + " [2.44163654e+03, 1.07273915e+06],\n", + " [2.41789135e+03, 1.06650080e+06],\n", + " [2.12092455e+03, 1.07255283e+06],\n", + " [2.01724608e+03, 1.18412737e+06],\n", + " [1.42484567e+03, 9.98442128e+05],\n", + " [2.00171844e+03, 1.16762736e+06],\n", + " [1.18906475e+03, 7.63242127e+05],\n", + " [9.64151573e+02, 1.06275748e+06],\n", + " [9.47691461e+02, 9.52712785e+05],\n", + " [1.08737495e+03, 1.32656020e+06],\n", + " [1.58211972e+03, 1.28554538e+06],\n", + " [1.02462654e+03, 1.21645444e+06],\n", + " [1.09696954e+03, 8.37588347e+05],\n", + " [1.18485005e+03, 1.32868306e+06],\n", + " [9.60649471e+02, 9.58801891e+05],\n", + " [8.35750134e+02, 6.70070548e+05],\n", + " [8.46933749e+02, 9.09028524e+05],\n", + " [8.75541052e+02, 6.93582525e+05],\n", + " [9.98457029e+02, 1.30087794e+06],\n", + " [8.38077124e+02, 8.59040056e+05],\n", + " [8.49095933e+02, 7.48748175e+05],\n", + " [4.75278209e+02, 7.29532863e+05],\n", + " [4.75221920e+02, 1.13497828e+06],\n", + " [5.94953735e+02, 1.17697697e+06],\n", + " [6.08685663e+02, 1.31934387e+06],\n", + " [5.71588897e+02, 1.08781125e+06],\n", + " [5.37656203e+02, 8.83840889e+05],\n", + " [6.53359338e+02, 1.12664376e+06],\n", + " [3.79753204e+02, 7.16919053e+05],\n", + " [4.79460534e+02, 7.67956524e+05],\n", + " [3.76455799e+02, 7.79635821e+05],\n", + " [3.98678387e+02, 1.17812870e+06],\n", + " [4.92440834e+02, 6.79938898e+05],\n", + " [3.17390876e+02, 1.28811921e+06],\n", + " [2.84136696e+02, 1.08425822e+06],\n", + " [2.53473783e+02, 6.69868499e+05],\n", + " [2.99264007e+02, 1.14357648e+06],\n", + " [3.88123342e+02, 8.48988552e+05],\n", + " [2.56298225e+02, 9.68709296e+05],\n", + " [2.26865279e+02, 8.27831780e+05],\n", + " [2.29488974e+02, 7.32466208e+05],\n", + " [3.17120474e+02, 1.18985963e+06],\n", + " [2.04389883e+02, 8.75497720e+05],\n", + " [2.69441520e+02, 1.01870765e+06],\n", + " [2.57974385e+02, 1.31524429e+06],\n", + " [1.91007675e+02, 1.12375985e+06],\n", + " [1.94527978e+02, 1.04333394e+06],\n", + " [2.07292919e+02, 1.25272904e+06],\n", + " [2.09816912e+02, 6.66651918e+05],\n", + " [2.16626923e+02, 7.76940647e+05],\n", + " [1.82179370e+02, 1.20455849e+06],\n", + " [1.67419689e+02, 9.25148524e+05],\n", + " [1.66593221e+02, 8.50966382e+05],\n", + " [1.25715209e+02, 1.24704406e+06],\n", + " [1.06823665e+02, 6.88489017e+05],\n", + " [1.19694951e+02, 1.06771516e+06],\n", + " [9.06989100e+01, 7.74962746e+05],\n", + " [9.52722524e+01, 9.00826911e+05],\n", + " [1.33280543e+02, 9.97025552e+05],\n", + " [1.22050775e+02, 8.25449524e+05],\n", + " [1.13438619e+02, 1.32748280e+06],\n", + " [7.95888118e+01, 9.96202694e+05],\n", + " [7.46208572e+01, 7.08911899e+05],\n", + " [1.07049236e+02, 8.62428915e+05]])" ] }, "execution_count": 10, @@ -702,7 +702,7 @@ { "data": { "text/plain": [ - "4209072260954.626" + "NormalLoss([3.0, 0.15, 1000000.0], SimulateOde([ODEVariable('S', 'S', None, True), ODEVariable('I', 'I', None, True), ODEVariable('R', 'R', None, True)], [ODEVariable('beta', 'beta', None, True), ODEVariable('gamma', 'gamma', None, True), ODEVariable('N', 'N', None, True)], [], [Transition('S', 'beta*S*I/N', 'T', 'I', None, None), Transition('I', 'gamma*I', 'T', 'R', None, None)], [], []).setParameters({'beta': 3.6, 'gamma': 0.2, 'N': 1000000.0}), [999998.0, 2.0, 0.0], 0.0, [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75, 12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75, 14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75, 16.0, 16.25, 16.5, 16.75, 17.0, 17.25, 17.5, 17.75, 18.0, 18.25, 18.5, 18.75, 19.0, 19.25, 19.5, 19.75, 20.0, 20.25, 20.5, 20.75, 21.0, 21.25, 21.5, 21.75, 22.0, 22.25, 22.5, 22.75, 23.0, 23.25, 23.5, 23.75, 24.0, 24.25, 24.5, 24.75, 25.0, 25.25, 25.5, 25.75, 26.0, 26.25, 26.5, 26.75, 27.0, 27.25, 27.5, 27.75, 28.0, 28.25, 28.5, 28.75, 29.0, 29.25, 29.5, 29.75, 30.0, 30.25, 30.5, 30.75, 31.0, 31.25, 31.5, 31.75, 32.0, 32.25, 32.5, 32.75, 33.0, 33.25, 33.5, 33.75, 34.0, 34.25, 34.5, 34.75, 35.0, 35.25, 35.5, 35.75, 36.0, 36.25, 36.5, 36.75, 37.0, 37.25, 37.5, 37.75, 38.0, 38.25, 38.5, 38.75, 39.0, 39.25, 39.5, 39.75, 40.0, 40.25, 40.5, 40.75, 41.0, 41.25, 41.5, 41.75, 42.0, 42.25, 42.5, 42.75, 43.0, 43.25, 43.5, 43.75, 44.0, 44.25, 44.5, 44.75, 45.0, 45.25, 45.5, 45.75, 46.0, 46.25, 46.5, 46.75, 47.0, 47.25, 47.5, 47.75, 48.0, 48.25, 48.5, 48.75, 49.0, 49.25, 49.5, 49.75, 50.0, 50.25, 50.5, 50.75], [[5.5489971387876365, 0.13976157088347727], [9.415096478582125, 0.6953800925736477], [25.941588724404888, 1.7360216096973626], [40.629454348405005, 3.6320719863452124], [108.33986724048995, 9.898076194201028], [265.94200822963205, 19.72199081288608], [814.0101919108965, 34.39273873132337], [1610.3645021087707, 84.46157450404837], [4033.7294190704292, 287.6005446141324], [8244.051192760833, 695.5700455200907], [29441.296547302398, 1278.206554206765], [36326.23747211643, 3083.1448823639666], [134300.6643766737, 7316.380551470222], [251120.96130046487, 12228.281008380864], [512397.4021229717, 21543.277252460124], [585616.8734093554, 38484.76952026679], [790205.921992304, 83692.67093281484], [974797.1285860298, 137447.11265771437], [707757.0823571573, 117346.97836716496], [603556.1371978847, 189433.07773085634], [913909.6207876124, 199048.48425080228], [548929.798690948, 279399.6024361307], [462040.51907899725, 383327.3895777905], [761326.3551628065, 258855.59336332348], [662287.4219836415, 340426.42697219475], [508464.53921417124, 391021.45531562675], [656745.3025785786, 578473.9477197772], [554162.9505283561, 426765.22955069266], [532220.7074438117, 508730.0308778309], [445615.9890674269, 476315.5274757456], [590230.8684803826, 648108.582432509], [544910.361061262, 672870.3344572515], [310827.4253700613, 587435.0165097215], [456115.65962565545, 710530.4983865325], [364253.7844819528, 579474.3308432746], [311474.8016733622, 821438.8027931447], [252718.85987592736, 478270.7054820163], [307809.39052484394, 683324.6855005894], [281269.7866456109, 834432.1640758143], [261336.99881665388, 750610.2799376069], [352273.3896491518, 689933.9153611241], [337278.8801262164, 668473.671079696], [262817.02738757816, 896729.9572193093], [274990.26820054883, 617678.724452312], [252897.72396917018, 865475.7000908976], [209867.3728636754, 950457.6023080612], [161791.28013060236, 1051352.395139691], [176888.54085288633, 998681.753684348], [158703.64323235105, 1052018.6625758626], [235953.74632457114, 581511.5462198751], [139508.3819811454, 1104611.4054220302], [127265.67567357987, 900559.5183912851], [146297.08454396683, 802469.639043949], [153697.59202897752, 1124694.0709555596], [165201.2568608659, 652874.3435597733], [160048.49667175754, 698299.422082141], [94596.797920066, 794188.5335791365], [117291.50891981134, 1170125.0942029145], [88205.35480368958, 1027701.8237791387], [79699.47446828452, 887920.1922399637], [122990.00315676956, 823010.8990972892], [90298.37858239123, 856602.5660494367], [112583.27458976842, 823690.0110776974], [115479.24360879252, 924618.4818930109], [77532.65451860701, 904591.1155288297], [78082.17487409341, 715856.1296537648], [99665.75506373866, 672890.1996274921], [87968.24120244425, 1005140.6416744539], [56753.577717708846, 926563.1004164796], [50867.71484676358, 710220.5323161592], [42445.65692219467, 706325.639191282], [46554.845983121624, 974134.4267906626], [52918.424828372394, 672152.061469812], [61553.98169533466, 1154689.9304881357], [41355.7068612865, 1114491.7048004952], [46374.73519731653, 870190.3739141857], [37244.34436743515, 1191669.9818033653], [41282.28851948546, 1046085.4493043608], [55317.91156340166, 1128079.994274354], [31907.69520572426, 1000208.0395347421], [34010.24198302409, 930221.1892817259], [30928.214034681547, 1018299.4007833744], [39523.39574481744, 1096728.5680754953], [43101.60123589903, 923362.8464453346], [24453.276252403833, 810610.3090453236], [24290.566238056355, 1168379.2311720226], [30849.52429767078, 672357.9273898688], [22930.91291882195, 683181.2065549527], [19312.410078810557, 1181575.0638825279], [24800.522354204797, 694595.4933711233], [30232.955889418034, 1144610.0789169455], [20439.868327523087, 916831.495611514], [26002.801545608865, 689740.713613447], [20449.735359676568, 1277607.1379225366], [23244.54282457448, 958179.1751528395], [16447.345530964347, 1225836.3266972792], [20051.445282210465, 669149.8800772146], [16664.454488900752, 925503.6673304131], [16681.49384056153, 743239.5841723487], [18683.299901770028, 1092030.4094499706], [17996.321050203427, 804265.8193114839], [17412.129570447687, 703980.773650898], [12698.868359882912, 1121870.8122240496], [15814.023105568453, 1027570.9081003398], [12734.071882360873, 858592.8580763217], [13582.657478279318, 764916.0217322799], [10126.381580399675, 750180.7159839582], [7193.420744583109, 1271423.1734558782], [10249.386414900197, 1133442.0264943778], [10397.892095036967, 1077065.7446887211], [10291.424793271395, 1127211.5938218776], [6609.807342544796, 672248.4104117213], [6598.495277349121, 888855.8050265535], [7689.704772788273, 739423.7561920357], [8845.842419921624, 1006775.9005513749], [8257.28104877651, 1192110.8618185048], [5881.906750996887, 1115149.93372143], [5420.930573114638, 716639.884819933], [6824.730262831377, 1124534.8621694546], [3683.207213311698, 1098986.08982435], [6804.52269756303, 1096526.7921533366], [5971.686041066522, 1094255.1464621811], [5272.7715814587045, 922447.4408174288], [4327.475161388193, 686566.7266654972], [3383.2610693392044, 1035475.2013402083], [3069.919189380042, 1166199.6484807285], [4128.870181022159, 1036637.8860012486], [4276.722417774954, 1265374.8212365832], [3188.0648383580597, 1161352.5607335398], [2800.118318839102, 975156.9553313118], [3620.4185579812274, 789736.0719286054], [3842.2741401842172, 1188642.3134196696], [3067.551247602438, 894816.5312599519], [2134.67276566011, 1167306.4045076708], [2276.263966733917, 1245915.7013382448], [2348.395010917235, 1120308.7855315015], [2249.0021255896513, 732039.3261821142], [1851.1240962192128, 1253930.6660519678], [2651.715415269909, 740465.2182037155], [2441.6365408681636, 1072739.1471042798], [2417.891347145136, 1066500.7995323706], [2120.9245483558825, 1072552.8316071504], [2017.2460815827417, 1184127.366115931], [1424.845670574932, 998442.1280909418], [2001.7184429807262, 1167627.3635968873], [1189.0647524983192, 763242.127352661], [964.1515731483933, 1062757.4849910974], [947.6914614570239, 952712.7846825029], [1087.3749471536023, 1326560.2010915559], [1582.1197247476741, 1285545.3759947247], [1024.6265416882222, 1216454.4422335515], [1096.9695443363794, 837588.3467235877], [1184.8500540757373, 1328683.061242117], [960.6494707281487, 958801.8911654096], [835.7501337173844, 670070.5483600695], [846.9337487099981, 909028.5240620613], [875.541052335431, 693582.5251296596], [998.4570286925696, 1300877.9383268403], [838.0771236697374, 859040.0555225008], [849.0959325990879, 748748.1751257956], [475.2782089274715, 729532.8627678553], [475.2219202114857, 1134978.277195852], [594.9537349672182, 1176976.9695724065], [608.6856630484652, 1319343.8667681955], [571.5888971056904, 1087811.2469301717], [537.6562029971528, 883840.8893521308], [653.3593380671064, 1126643.762739988], [379.7532039608197, 716919.052976874], [479.46053353989157, 767956.5237406924], [376.4557987859823, 779635.8208878567], [398.67838714418235, 1178128.6982785354], [492.4408336280881, 679938.8977216084], [317.3908756903431, 1288119.208934416], [284.13669569600165, 1084258.2171145338], [253.47378339180153, 669868.4988409674], [299.26400701038574, 1143576.4805791376], [388.12334228010513, 848988.5515813607], [256.2982253008446, 968709.2961185345], [226.86527870402017, 827831.7795352405], [229.48897424342212, 732466.208474486], [317.12047386383495, 1189859.6336752367], [204.38988338787306, 875497.7197789245], [269.4415199990759, 1018707.6504033973], [257.97438516355055, 1315244.2862689584], [191.00767526447387, 1123759.8491195813], [194.52797753681182, 1043333.9442222763], [207.29291902341845, 1252729.0376916449], [209.81691238951242, 666651.9180659578], [216.6269232166793, 776940.6467737745], [182.17936999016678, 1204558.48883258], [167.41968911549503, 925148.5235907574], [166.59322132383082, 850966.3818700697], [125.71520857960297, 1247044.057304752], [106.82366473307945, 688489.016953341], [119.69495136675988, 1067715.157561069], [90.69890996414178, 774962.7461366334], [95.27225242575679, 900826.9111966246], [133.28054285317748, 997025.5515197581], [122.05077509682275, 825449.5240761695], [113.43861907585058, 1327482.8035176208], [79.58881177281683, 996202.6939394812], [74.62085718615808, 708911.8992225014], [107.04923637866446, 862428.9150962183]], ['I', 'R'], [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])" ] }, "execution_count": 13, @@ -711,19 +711,39 @@ } ], "source": [ - "objSIR.cost()" + "objSIR" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4909533605860.806" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.cost()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\scipy\\optimize\\_minimize.py:521: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", " warn('Method %s cannot handle constraints nor bounds.' % method,\n" ] }, @@ -731,18 +751,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 3149715468391.5137\n", - " hess_inv: array([[ 1.02285673e-11, -3.28483610e-14, 3.23263121e-06],\n", - " [-3.28483423e-14, 5.00246087e-15, -3.92052034e-09],\n", - " [ 3.23263111e-06, -3.92052576e-09, 1.06428103e+00]])\n", - " jac: array([-1.89198473e+03, 2.05662437e+05, 6.51297284e-03])\n", + " fun: 3257054048571.9863\n", + " hess_inv: array([[ 5.18410500e-11, -2.54658445e-12, 1.27206329e-05],\n", + " [-2.54658442e-12, 1.49261473e-13, -6.12083782e-07],\n", + " [ 1.27206329e-05, -6.12083790e-07, 3.12906462e+00]])\n", + " jac: array([-1.10600741e+00, -4.43260288e+00, 4.08760083e-06])\n", " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 74\n", - " nit: 10\n", - " njev: 62\n", + " nfev: 43\n", + " nit: 12\n", + " njev: 38\n", " status: 2\n", " success: False\n", - " x: array([3.84976144e+00, 2.02859211e-01, 1.11835931e+06])\n" + " x: array([5.52375636e+00, 2.03086137e-01, 1.49373372e+06])\n" ] } ], @@ -758,22 +778,23 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " fun: 3149715468391.6045\n", + " fun: 3257054048571.9043\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([ 2.80002429e+03, 1.18458645e+05, -9.63846812e-03])\n", + " jac: array([-8.79695180e+01, -1.47147132e+03, 3.25305614e-04])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 12\n", + " nfev: 14\n", " nit: 9\n", + " njev: 14\n", " status: 0\n", " success: True\n", - " x: array([3.44232967e+00, 2.02859211e-01, 1.00000000e+06])\n" + " x: array([3.69795251e+00, 2.03086137e-01, 1.00000000e+06])\n" ] } ], @@ -789,7 +810,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -833,7 +854,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 18, "metadata": { "scrolled": false }, @@ -845,16 +866,16 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([-1.17798986e+03, -1.40835509e+04, 3.53396958e-03])" + "array([-5.77968064e+02, -6.98915605e+03, 1.73390419e-03])" ] }, - "execution_count": 18, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -865,16 +886,16 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "5065.797364214306" + "5062.059868394187" ] }, - "execution_count": 19, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -885,14 +906,14 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\scipy\\optimize\\_minimize.py:521: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", " warn('Method %s cannot handle constraints nor bounds.' % method,\n" ] }, @@ -900,18 +921,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4716.804547726841\n", - " hess_inv: array([[ 1.93830562e-03, -1.55181618e-05, 1.36514445e-06],\n", - " [-1.55181618e-05, 1.96280251e-06, 1.90886878e-08],\n", - " [ 1.36514445e-06, 1.90886878e-08, 1.00000000e+00]])\n", - " jac: array([ 8.67860428e-08, -3.11402124e-06, -3.11981179e-13])\n", - " message: 'Optimization terminated successfully.'\n", - " nfev: 15\n", + " fun: 4717.565272474467\n", + " hess_inv: array([[ 3.84423633e-03, -3.01340148e-05, 1.56049513e-06],\n", + " [-3.01340148e-05, 3.82956903e-06, 1.49977083e-08],\n", + " [ 1.56049513e-06, 1.49977083e-08, 1.00000000e+00]])\n", + " jac: array([ 8.12454287e-07, -3.28990725e-04, -2.91902226e-12])\n", + " message: 'Desired error not necessarily achieved due to precision loss.'\n", + " nfev: 57\n", " nit: 10\n", - " njev: 15\n", - " status: 0\n", - " success: True\n", - " x: array([3.59483138e+00, 1.99847237e-01, 1.00000000e+06])\n" + " njev: 46\n", + " status: 2\n", + " success: False\n", + " x: array([3.59284491e+00, 1.99665537e-01, 1.00000000e+06])\n" ] } ], @@ -927,14 +948,14 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", " logpdf_p3= -shape*np.log(mu/shape)\n" ] }, @@ -942,15 +963,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4716.804547726802\n", + " fun: 4717.565272489127\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([-9.16923207e-05, -1.70890676e-03, 3.29618418e-10])\n", + " jac: array([ 1.06976387e-03, -7.18401978e-02, -3.84350237e-09])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 15\n", + " nfev: 17\n", " nit: 10\n", + " njev: 17\n", " status: 0\n", " success: True\n", - " x: array([3.59483123e+00, 1.99847235e-01, 1.00000000e+06])\n" + " x: array([3.59285115e+00, 1.99665226e-01, 1.00000000e+06])\n" ] } ], @@ -966,7 +988,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -1017,218 +1039,218 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[5.000000e+00, 0.000000e+00],\n", - " [9.000000e+00, 0.000000e+00],\n", - " [1.900000e+01, 1.000000e+00],\n", - " [4.600000e+01, 3.000000e+00],\n", - " [9.700000e+01, 6.000000e+00],\n", - " [2.610000e+02, 2.200000e+01],\n", - " [9.900000e+02, 5.400000e+01],\n", - " [1.515000e+03, 1.210000e+02],\n", - " [3.991000e+03, 3.070000e+02],\n", - " [7.166000e+03, 4.150000e+02],\n", - " [1.973600e+04, 1.230000e+03],\n", - " [5.781700e+04, 3.684000e+03],\n", - " [1.468620e+05, 6.722000e+03],\n", - " [2.832220e+05, 1.723800e+04],\n", - " [2.820990e+05, 2.116000e+04],\n", - " [5.584000e+05, 6.052300e+04],\n", - " [4.826190e+05, 9.443600e+04],\n", - " [6.657660e+05, 9.662400e+04],\n", - " [5.727470e+05, 1.895490e+05],\n", - " [7.091470e+05, 2.668100e+05],\n", - " [7.402350e+05, 2.313290e+05],\n", - " [8.098400e+05, 2.661440e+05],\n", - " [8.284080e+05, 2.491660e+05],\n", - " [5.359220e+05, 2.625830e+05],\n", - " [7.802210e+05, 3.088350e+05],\n", - " [6.826180e+05, 3.476890e+05],\n", - " [5.921870e+05, 4.633670e+05],\n", - " [6.514760e+05, 4.153080e+05],\n", - " [5.852770e+05, 3.412100e+05],\n", - " [4.320470e+05, 4.639580e+05],\n", - " [5.465900e+05, 5.109050e+05],\n", - " [5.740020e+05, 6.710010e+05],\n", - " [5.272460e+05, 6.689180e+05],\n", - " [3.613920e+05, 6.642780e+05],\n", - " [2.630790e+05, 6.164560e+05],\n", - " [4.237840e+05, 6.904690e+05],\n", - " [2.385330e+05, 5.529600e+05],\n", - " [2.627090e+05, 5.374070e+05],\n", - " [2.988290e+05, 7.095110e+05],\n", - " [2.745710e+05, 5.798480e+05],\n", - " [2.614410e+05, 6.298420e+05],\n", - " [2.588150e+05, 5.859220e+05],\n", - " [2.291440e+05, 9.937800e+05],\n", - " [2.040730e+05, 8.910570e+05],\n", - " [2.709460e+05, 9.008150e+05],\n", - " [1.850760e+05, 5.275220e+05],\n", - " [2.572050e+05, 5.544440e+05],\n", - " [2.136960e+05, 7.221370e+05],\n", - " [2.137180e+05, 6.012100e+05],\n", - " [1.750310e+05, 8.377410e+05],\n", - " [1.695400e+05, 8.144580e+05],\n", - " [1.153150e+05, 9.722930e+05],\n", - " [1.781210e+05, 6.972570e+05],\n", - " [1.025850e+05, 7.931980e+05],\n", - " [1.557830e+05, 1.032394e+06],\n", - " [1.749430e+05, 9.711260e+05],\n", - " [1.520690e+05, 7.051940e+05],\n", - " [1.527620e+05, 8.249310e+05],\n", - " [1.503390e+05, 8.891050e+05],\n", - " [1.290250e+05, 1.041679e+06],\n", - " [1.064650e+05, 1.003373e+06],\n", - " [9.704000e+04, 1.129447e+06],\n", - " [1.147480e+05, 7.903740e+05],\n", - " [7.951100e+04, 1.034171e+06],\n", - " [8.140800e+04, 6.853400e+05],\n", - " [8.066900e+04, 1.123759e+06],\n", - " [8.439800e+04, 1.159922e+06],\n", - " [6.450600e+04, 9.382090e+05],\n", - " [6.366900e+04, 7.915010e+05],\n", - " [7.614600e+04, 6.703730e+05],\n", - " [4.703900e+04, 7.071490e+05],\n", - " [4.364400e+04, 1.073515e+06],\n", - " [6.280800e+04, 7.979050e+05],\n", - " [5.134600e+04, 1.045135e+06],\n", - " [6.302300e+04, 1.137771e+06],\n", - " [4.806200e+04, 6.687340e+05],\n", - " [3.633300e+04, 9.508640e+05],\n", - " [3.930600e+04, 8.525190e+05],\n", - " [3.075400e+04, 1.247465e+06],\n", - " [2.862500e+04, 1.194818e+06],\n", - " [4.743800e+04, 7.044480e+05],\n", - " [4.256400e+04, 1.007074e+06],\n", - " [3.938900e+04, 9.967710e+05],\n", - " [4.239300e+04, 1.239269e+06],\n", - " [2.924000e+04, 1.217901e+06],\n", - " [2.309600e+04, 1.217662e+06],\n", - " [3.407500e+04, 1.213231e+06],\n", - " [2.907200e+04, 1.246536e+06],\n", - " [2.711300e+04, 1.107201e+06],\n", - " [1.806300e+04, 9.200930e+05],\n", - " [2.525600e+04, 1.049130e+06],\n", - " [1.843600e+04, 8.923940e+05],\n", - " [2.129100e+04, 9.476230e+05],\n", - " [1.524000e+04, 8.937350e+05],\n", - " [1.398800e+04, 1.030004e+06],\n", - " [1.943000e+04, 6.623530e+05],\n", - " [1.169100e+04, 6.970030e+05],\n", - " [1.667000e+04, 1.033941e+06],\n", - " [1.727100e+04, 1.278454e+06],\n", - " [1.212700e+04, 1.047077e+06],\n", - " [1.357500e+04, 6.871120e+05],\n", - " [1.420000e+04, 1.236557e+06],\n", - " [1.596000e+04, 1.142587e+06],\n", - " [1.496600e+04, 9.449100e+05],\n", - " [8.814000e+03, 1.262525e+06],\n", - " [1.033100e+04, 1.301655e+06],\n", - " [8.508000e+03, 8.369960e+05],\n", - " [8.702000e+03, 6.648640e+05],\n", - " [7.821000e+03, 1.070812e+06],\n", - " [7.459000e+03, 1.197702e+06],\n", - " [8.520000e+03, 1.158037e+06],\n", - " [8.322000e+03, 1.008464e+06],\n", - " [6.598000e+03, 6.685560e+05],\n", - " [8.855000e+03, 8.297920e+05],\n", - " [5.319000e+03, 1.238120e+06],\n", - " [5.521000e+03, 1.283727e+06],\n", - " [5.047000e+03, 1.275977e+06],\n", - " [4.667000e+03, 8.453960e+05],\n", - " [4.541000e+03, 1.102279e+06],\n", - " [5.613000e+03, 7.624460e+05],\n", - " [3.973000e+03, 1.265941e+06],\n", - " [3.825000e+03, 9.830190e+05],\n", - " [4.387000e+03, 8.782980e+05],\n", - " [5.145000e+03, 1.224032e+06],\n", - " [4.834000e+03, 1.006099e+06],\n", - " [4.435000e+03, 1.181320e+06],\n", - " [3.337000e+03, 1.314770e+06],\n", - " [4.280000e+03, 6.781240e+05],\n", - " [4.409000e+03, 1.292952e+06],\n", - " [2.229000e+03, 8.820550e+05],\n", - " [2.631000e+03, 8.707330e+05],\n", - " [3.165000e+03, 9.689720e+05],\n", - " [2.384000e+03, 7.234630e+05],\n", - " [2.750000e+03, 9.916340e+05],\n", - " [2.511000e+03, 1.089111e+06],\n", - " [2.294000e+03, 9.735000e+05],\n", - " [2.709000e+03, 9.764780e+05],\n", - " [2.746000e+03, 9.948270e+05],\n", - " [2.714000e+03, 1.223956e+06],\n", - " [2.374000e+03, 8.959160e+05],\n", - " [1.671000e+03, 1.228306e+06],\n", - " [1.283000e+03, 1.274200e+06],\n", - " [2.008000e+03, 1.264884e+06],\n", - " [1.260000e+03, 1.033340e+06],\n", - " [1.503000e+03, 1.038520e+06],\n", - " [1.921000e+03, 1.068669e+06],\n", - " [1.356000e+03, 8.848560e+05],\n", - " [1.561000e+03, 1.271509e+06],\n", - " [1.495000e+03, 1.071903e+06],\n", - " [8.280000e+02, 1.215564e+06],\n", - " [1.246000e+03, 1.140591e+06],\n", - " [1.392000e+03, 7.348680e+05],\n", - " [1.194000e+03, 7.493110e+05],\n", - " [6.840000e+02, 8.301580e+05],\n", - " [7.110000e+02, 1.030781e+06],\n", - " [9.230000e+02, 6.937940e+05],\n", - " [7.470000e+02, 1.010889e+06],\n", - " [7.860000e+02, 1.183986e+06],\n", - " [7.180000e+02, 1.160713e+06],\n", - " [8.230000e+02, 9.749720e+05],\n", - " [8.630000e+02, 9.999900e+05],\n", - " [8.690000e+02, 7.924270e+05],\n", - " [6.420000e+02, 8.615190e+05],\n", - " [6.330000e+02, 9.006470e+05],\n", - " [7.410000e+02, 1.305110e+06],\n", - " [4.440000e+02, 1.235293e+06],\n", - " [6.780000e+02, 9.734870e+05],\n", - " [3.890000e+02, 9.811730e+05],\n", - " [5.810000e+02, 8.022590e+05],\n", - " [5.380000e+02, 6.921760e+05],\n", - " [3.130000e+02, 1.149172e+06],\n", - " [5.170000e+02, 1.332219e+06],\n", - " [3.990000e+02, 1.243409e+06],\n", - " [4.040000e+02, 6.951280e+05],\n", - " [2.750000e+02, 6.744260e+05],\n", - " [2.600000e+02, 8.871490e+05],\n", - " [3.580000e+02, 1.326963e+06],\n", - " [3.070000e+02, 7.625150e+05],\n", - " [2.150000e+02, 1.160246e+06],\n", - " [2.760000e+02, 1.055389e+06],\n", - " [2.700000e+02, 9.990920e+05],\n", - " [2.370000e+02, 7.255320e+05],\n", - " [2.060000e+02, 1.099872e+06],\n", - " [1.750000e+02, 9.375600e+05],\n", - " [1.810000e+02, 8.569710e+05],\n", - " [2.220000e+02, 1.179454e+06],\n", - " [2.320000e+02, 1.302408e+06],\n", - " [2.390000e+02, 7.552470e+05],\n", - " [1.800000e+02, 1.013415e+06],\n", - " [1.810000e+02, 1.103302e+06],\n", - " [1.290000e+02, 7.600690e+05],\n", - " [1.860000e+02, 1.253858e+06],\n", - " [1.700000e+02, 1.092196e+06],\n", - " [1.650000e+02, 8.604650e+05],\n", - " [1.350000e+02, 6.752070e+05],\n", - " [9.600000e+01, 1.061282e+06],\n", - " [8.300000e+01, 1.195101e+06],\n", - " [1.150000e+02, 1.272789e+06],\n", - " [9.200000e+01, 7.292520e+05],\n", - " [1.210000e+02, 1.165792e+06],\n", - " [9.100000e+01, 9.362310e+05],\n", - " [7.700000e+01, 9.420080e+05],\n", - " [6.800000e+01, 9.976760e+05]])" + "array([[6.000000e+00, 0.000000e+00],\n", + " [9.000000e+00, 1.000000e+00],\n", + " [2.600000e+01, 2.000000e+00],\n", + " [4.100000e+01, 4.000000e+00],\n", + " [1.080000e+02, 1.000000e+01],\n", + " [2.660000e+02, 2.000000e+01],\n", + " [8.140000e+02, 3.400000e+01],\n", + " [1.610000e+03, 8.400000e+01],\n", + " [4.034000e+03, 2.880000e+02],\n", + " [8.244000e+03, 6.960000e+02],\n", + " [2.944100e+04, 1.278000e+03],\n", + " [3.632600e+04, 3.083000e+03],\n", + " [1.343010e+05, 7.316000e+03],\n", + " [2.511210e+05, 1.222800e+04],\n", + " [5.123970e+05, 2.154300e+04],\n", + " [5.856170e+05, 3.848500e+04],\n", + " [7.902060e+05, 8.369300e+04],\n", + " [9.747970e+05, 1.374470e+05],\n", + " [7.077570e+05, 1.173470e+05],\n", + " [6.035560e+05, 1.894330e+05],\n", + " [9.139100e+05, 1.990480e+05],\n", + " [5.489300e+05, 2.794000e+05],\n", + " [4.620410e+05, 3.833270e+05],\n", + " [7.613260e+05, 2.588560e+05],\n", + " [6.622870e+05, 3.404260e+05],\n", + " [5.084650e+05, 3.910210e+05],\n", + " [6.567450e+05, 5.784740e+05],\n", + " [5.541630e+05, 4.267650e+05],\n", + " [5.322210e+05, 5.087300e+05],\n", + " [4.456160e+05, 4.763160e+05],\n", + " [5.902310e+05, 6.481090e+05],\n", + " [5.449100e+05, 6.728700e+05],\n", + " [3.108270e+05, 5.874350e+05],\n", + " [4.561160e+05, 7.105300e+05],\n", + " [3.642540e+05, 5.794740e+05],\n", + " [3.114750e+05, 8.214390e+05],\n", + " [2.527190e+05, 4.782710e+05],\n", + " [3.078090e+05, 6.833250e+05],\n", + " [2.812700e+05, 8.344320e+05],\n", + " [2.613370e+05, 7.506100e+05],\n", + " [3.522730e+05, 6.899340e+05],\n", + " [3.372790e+05, 6.684740e+05],\n", + " [2.628170e+05, 8.967300e+05],\n", + " [2.749900e+05, 6.176790e+05],\n", + " [2.528980e+05, 8.654760e+05],\n", + " [2.098670e+05, 9.504580e+05],\n", + " [1.617910e+05, 1.051352e+06],\n", + " [1.768890e+05, 9.986820e+05],\n", + " [1.587040e+05, 1.052019e+06],\n", + " [2.359540e+05, 5.815120e+05],\n", + " [1.395080e+05, 1.104611e+06],\n", + " [1.272660e+05, 9.005600e+05],\n", + " [1.462970e+05, 8.024700e+05],\n", + " [1.536980e+05, 1.124694e+06],\n", + " [1.652010e+05, 6.528740e+05],\n", + " [1.600480e+05, 6.982990e+05],\n", + " [9.459700e+04, 7.941890e+05],\n", + " [1.172920e+05, 1.170125e+06],\n", + " [8.820500e+04, 1.027702e+06],\n", + " [7.969900e+04, 8.879200e+05],\n", + " [1.229900e+05, 8.230110e+05],\n", + " [9.029800e+04, 8.566030e+05],\n", + " [1.125830e+05, 8.236900e+05],\n", + " [1.154790e+05, 9.246180e+05],\n", + " [7.753300e+04, 9.045910e+05],\n", + " [7.808200e+04, 7.158560e+05],\n", + " [9.966600e+04, 6.728900e+05],\n", + " [8.796800e+04, 1.005141e+06],\n", + " [5.675400e+04, 9.265630e+05],\n", + " [5.086800e+04, 7.102210e+05],\n", + " [4.244600e+04, 7.063260e+05],\n", + " [4.655500e+04, 9.741340e+05],\n", + " [5.291800e+04, 6.721520e+05],\n", + " [6.155400e+04, 1.154690e+06],\n", + " [4.135600e+04, 1.114492e+06],\n", + " [4.637500e+04, 8.701900e+05],\n", + " [3.724400e+04, 1.191670e+06],\n", + " [4.128200e+04, 1.046085e+06],\n", + " [5.531800e+04, 1.128080e+06],\n", + " [3.190800e+04, 1.000208e+06],\n", + " [3.401000e+04, 9.302210e+05],\n", + " [3.092800e+04, 1.018299e+06],\n", + " [3.952300e+04, 1.096729e+06],\n", + " [4.310200e+04, 9.233630e+05],\n", + " [2.445300e+04, 8.106100e+05],\n", + " [2.429100e+04, 1.168379e+06],\n", + " [3.085000e+04, 6.723580e+05],\n", + " [2.293100e+04, 6.831810e+05],\n", + " [1.931200e+04, 1.181575e+06],\n", + " [2.480100e+04, 6.945950e+05],\n", + " [3.023300e+04, 1.144610e+06],\n", + " [2.044000e+04, 9.168310e+05],\n", + " [2.600300e+04, 6.897410e+05],\n", + " [2.045000e+04, 1.277607e+06],\n", + " [2.324500e+04, 9.581790e+05],\n", + " [1.644700e+04, 1.225836e+06],\n", + " [2.005100e+04, 6.691500e+05],\n", + " [1.666400e+04, 9.255040e+05],\n", + " [1.668100e+04, 7.432400e+05],\n", + " [1.868300e+04, 1.092030e+06],\n", + " [1.799600e+04, 8.042660e+05],\n", + " [1.741200e+04, 7.039810e+05],\n", + " [1.269900e+04, 1.121871e+06],\n", + " [1.581400e+04, 1.027571e+06],\n", + " [1.273400e+04, 8.585930e+05],\n", + " [1.358300e+04, 7.649160e+05],\n", + " [1.012600e+04, 7.501810e+05],\n", + " [7.193000e+03, 1.271423e+06],\n", + " [1.024900e+04, 1.133442e+06],\n", + " [1.039800e+04, 1.077066e+06],\n", + " [1.029100e+04, 1.127212e+06],\n", + " [6.610000e+03, 6.722480e+05],\n", + " [6.598000e+03, 8.888560e+05],\n", + " [7.690000e+03, 7.394240e+05],\n", + " [8.846000e+03, 1.006776e+06],\n", + " [8.257000e+03, 1.192111e+06],\n", + " [5.882000e+03, 1.115150e+06],\n", + " [5.421000e+03, 7.166400e+05],\n", + " [6.825000e+03, 1.124535e+06],\n", + " [3.683000e+03, 1.098986e+06],\n", + " [6.805000e+03, 1.096527e+06],\n", + " [5.972000e+03, 1.094255e+06],\n", + " [5.273000e+03, 9.224470e+05],\n", + " [4.327000e+03, 6.865670e+05],\n", + " [3.383000e+03, 1.035475e+06],\n", + " [3.070000e+03, 1.166200e+06],\n", + " [4.129000e+03, 1.036638e+06],\n", + " [4.277000e+03, 1.265375e+06],\n", + " [3.188000e+03, 1.161353e+06],\n", + " [2.800000e+03, 9.751570e+05],\n", + " [3.620000e+03, 7.897360e+05],\n", + " [3.842000e+03, 1.188642e+06],\n", + " [3.068000e+03, 8.948170e+05],\n", + " [2.135000e+03, 1.167306e+06],\n", + " [2.276000e+03, 1.245916e+06],\n", + " [2.348000e+03, 1.120309e+06],\n", + " [2.249000e+03, 7.320390e+05],\n", + " [1.851000e+03, 1.253931e+06],\n", + " [2.652000e+03, 7.404650e+05],\n", + " [2.442000e+03, 1.072739e+06],\n", + " [2.418000e+03, 1.066501e+06],\n", + " [2.121000e+03, 1.072553e+06],\n", + " [2.017000e+03, 1.184127e+06],\n", + " [1.425000e+03, 9.984420e+05],\n", + " [2.002000e+03, 1.167627e+06],\n", + " [1.189000e+03, 7.632420e+05],\n", + " [9.640000e+02, 1.062757e+06],\n", + " [9.480000e+02, 9.527130e+05],\n", + " [1.087000e+03, 1.326560e+06],\n", + " [1.582000e+03, 1.285545e+06],\n", + " [1.025000e+03, 1.216454e+06],\n", + " [1.097000e+03, 8.375880e+05],\n", + " [1.185000e+03, 1.328683e+06],\n", + " [9.610000e+02, 9.588020e+05],\n", + " [8.360000e+02, 6.700710e+05],\n", + " [8.470000e+02, 9.090290e+05],\n", + " [8.760000e+02, 6.935830e+05],\n", + " [9.980000e+02, 1.300878e+06],\n", + " [8.380000e+02, 8.590400e+05],\n", + " [8.490000e+02, 7.487480e+05],\n", + " [4.750000e+02, 7.295330e+05],\n", + " [4.750000e+02, 1.134978e+06],\n", + " [5.950000e+02, 1.176977e+06],\n", + " [6.090000e+02, 1.319344e+06],\n", + " [5.720000e+02, 1.087811e+06],\n", + " [5.380000e+02, 8.838410e+05],\n", + " [6.530000e+02, 1.126644e+06],\n", + " [3.800000e+02, 7.169190e+05],\n", + " [4.790000e+02, 7.679570e+05],\n", + " [3.760000e+02, 7.796360e+05],\n", + " [3.990000e+02, 1.178129e+06],\n", + " [4.920000e+02, 6.799390e+05],\n", + " [3.170000e+02, 1.288119e+06],\n", + " [2.840000e+02, 1.084258e+06],\n", + " [2.530000e+02, 6.698680e+05],\n", + " [2.990000e+02, 1.143576e+06],\n", + " [3.880000e+02, 8.489890e+05],\n", + " [2.560000e+02, 9.687090e+05],\n", + " [2.270000e+02, 8.278320e+05],\n", + " [2.290000e+02, 7.324660e+05],\n", + " [3.170000e+02, 1.189860e+06],\n", + " [2.040000e+02, 8.754980e+05],\n", + " [2.690000e+02, 1.018708e+06],\n", + " [2.580000e+02, 1.315244e+06],\n", + " [1.910000e+02, 1.123760e+06],\n", + " [1.950000e+02, 1.043334e+06],\n", + " [2.070000e+02, 1.252729e+06],\n", + " [2.100000e+02, 6.666520e+05],\n", + " [2.170000e+02, 7.769410e+05],\n", + " [1.820000e+02, 1.204558e+06],\n", + " [1.670000e+02, 9.251490e+05],\n", + " [1.670000e+02, 8.509660e+05],\n", + " [1.260000e+02, 1.247044e+06],\n", + " [1.070000e+02, 6.884890e+05],\n", + " [1.200000e+02, 1.067715e+06],\n", + " [9.100000e+01, 7.749630e+05],\n", + " [9.500000e+01, 9.008270e+05],\n", + " [1.330000e+02, 9.970260e+05],\n", + " [1.220000e+02, 8.254500e+05],\n", + " [1.130000e+02, 1.327483e+06],\n", + " [8.000000e+01, 9.962030e+05],\n", + " [7.500000e+01, 7.089120e+05],\n", + " [1.070000e+02, 8.624290e+05]])" ] }, - "execution_count": 23, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -1247,7 +1269,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "metadata": { "scrolled": false }, @@ -1266,16 +1288,16 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "8329023.1484972015" + "9745677.652607694" ] }, - "execution_count": 25, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -1286,25 +1308,33 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 27, "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + " warn('Method %s cannot handle constraints nor bounds.' % method,\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ - " fun: 3557908.6464113127\n", - " hess_inv: array([[ 1.27472646e-07, -3.23818317e-09, 2.26214178e-06],\n", - " [-3.23818317e-09, 9.56376557e-10, 2.13419691e-08],\n", - " [ 2.26214178e-06, 2.13419691e-08, 1.00001208e+00]])\n", - " jac: array([-6.34498993e-04, 1.86534335e-03, 2.25490671e-09])\n", + " fun: 3692407.814497117\n", + " hess_inv: array([[ 1.13964289e-07, -2.49061166e-09, 2.20264892e-06],\n", + " [-2.49061166e-09, 9.27756704e-10, 9.40250405e-09],\n", + " [ 2.20264892e-06, 9.40250405e-09, 1.00000987e+00]])\n", + " jac: array([ 1.33293688e-02, -2.07506277e-02, -4.87274588e-08])\n", " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 109\n", - " nit: 11\n", - " njev: 97\n", + " nfev: 54\n", + " nit: 10\n", + " njev: 42\n", " status: 2\n", " success: False\n", - " x: array([3.55378376e+00, 1.99169650e-01, 1.00000147e+06])\n" + " x: array([3.65564294e+00, 2.00162197e-01, 9.99999090e+05])\n" ] } ], @@ -1320,22 +1350,23 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " fun: 3557908.646411574\n", + " fun: 3692407.8145229938\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([-2.83986623e-01, -4.04398552e-01, 1.00922556e-06])\n", + " jac: array([ 9.92225896e-02, -2.34421856e+02, -3.62722747e-07])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 15\n", - " nit: 11\n", + " nfev: 14\n", + " nit: 10\n", + " njev: 14\n", " status: 0\n", " success: True\n", - " x: array([3.55377851e+00, 1.99169650e-01, 1.00000000e+06])\n" + " x: array([3.65564687e+00, 2.00161978e-01, 1.00000000e+06])\n" ] } ], @@ -1351,7 +1382,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -1395,7 +1426,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 30, "metadata": { "scrolled": false }, @@ -1404,9 +1435,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] } @@ -1418,16 +1449,16 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([-2.92555910e+02, -3.50195352e+03, 8.77667731e-04])" + "array([-2.87176322e+02, -3.47833060e+03, 8.61528965e-04])" ] }, - "execution_count": 30, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -1438,16 +1469,16 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "5041.425763395273" + "5041.270821570561" ] }, - "execution_count": 31, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -1458,14 +1489,14 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\scipy\\optimize\\_minimize.py:521: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", " warn('Method %s cannot handle constraints nor bounds.' % method,\n" ] }, @@ -1473,18 +1504,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4867.899797539529\n", - " hess_inv: array([[ 7.67776936e-03, -5.97617430e-05, 1.74660277e-06],\n", - " [-5.97617430e-05, 7.85112146e-06, 1.25323010e-08],\n", - " [ 1.74660277e-06, 1.25323010e-08, 1.00000000e+00]])\n", - " jac: array([ 8.13167572e-09, -3.92696007e-06, -2.92247481e-14])\n", + " fun: 4869.743686474076\n", + " hess_inv: array([[ 7.82577440e-03, -6.12363068e-05, 1.76151491e-06],\n", + " [-6.12363068e-05, 7.85949196e-06, 1.45278667e-08],\n", + " [ 1.76151491e-06, 1.45278667e-08, 1.00000000e+00]])\n", + " jac: array([-2.72469402e-08, 1.25576726e-07, 9.79041863e-14])\n", " message: 'Optimization terminated successfully.'\n", - " nfev: 15\n", - " nit: 10\n", - " njev: 15\n", + " nfev: 16\n", + " nit: 11\n", + " njev: 16\n", " status: 0\n", " success: True\n", - " x: array([3.59393939e+00, 1.99830691e-01, 1.00000000e+06])\n" + " x: array([3.59321800e+00, 1.99662852e-01, 1.00000000e+06])\n" ] } ], @@ -1500,14 +1531,14 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygom_loss_20200410\\lib\\site-packages\\pygom-0.1.7.dev1+gbbd58f3.d20200410-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] }, @@ -1515,15 +1546,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4867.899797547801\n", + " fun: 4869.743686476613\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([ 4.12746856e-04, 1.84890228e-02, -1.48338804e-09])\n", + " jac: array([-1.47841000e-04, -9.54029439e-03, 5.31224858e-10])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 17\n", + " nfev: 18\n", " nit: 12\n", + " njev: 18\n", " status: 0\n", " success: True\n", - " x: array([3.59394146e+00, 1.99830811e-01, 1.00000000e+06])\n" + " x: array([3.59321743e+00, 1.99662786e-01, 1.00000000e+06])\n" ] } ], @@ -1539,7 +1571,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 35, "metadata": {}, "outputs": [ { @@ -1605,7 +1637,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.2" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/pygom/loss/base_loss.py b/pygom/loss/base_loss.py index cca68359..68c582da 100644 --- a/pygom/loss/base_loss.py +++ b/pygom/loss/base_loss.py @@ -65,7 +65,7 @@ def __init__(self, theta, ode, y = ode_utils.check_array_type(y) if state_weight is None: - state_weight = 1.0 + state_weight = np.ones(y.shape) if len(y) == y.size: y = y.flatten() diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index 5e0e6445..b326c7bb 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -18,7 +18,7 @@ from pygom.model._model_errors import InitializeError from pygom.model.ode_utils import check_array_type -from pygom.utilR.distn import dnorm, dpois, gamma_mu_shape, dnbinom +from pygom.utilR.distn import dpois, gamma_mu_shape, dnbinom class InputError(Exception): ''' @@ -50,13 +50,15 @@ def __init__(self, y, weights=None): self._w = np.ones(self._y.shape) else: self._w = check_array_type(weights) - if np.any(weights<0): - raise ValueError('No elements in numpy array of weights should be negative') - if np.all(weights==0.0): - raise ValueError('All elements in numpy array of weights should not be 0.0') if len(self._w.shape) > 1: if 1 in self._w.shape: self._w = self._w.flatten() + + if np.any(self._w<0.0): + raise ValueError('No elements in numpy array of weights should be negative') + if np.all(self._w==0.0): + raise ValueError('All elements in numpy array of weights should not be 0.0') + assert self._y.shape == self._w.shape, \ "Input weight not of the same size as y" @@ -78,7 +80,7 @@ def residual(self, yhat, weighting_applied = True): :math:`y_{i} - \\hat{y}_{i}` ''' - if isinstance(weighting_applied,bool)=False: + if isinstance(weighting_applied,bool)==False: raise TypeError('weighting_applied should be boolean') if len(yhat.shape) > 1: @@ -88,7 +90,7 @@ def residual(self, yhat, weighting_applied = True): resid = self._y - yhat else: resid = self._y - yhat - if weighting_applied = True: + if weighting_applied == True: resid *= self._w return resid @@ -146,7 +148,7 @@ def diff_loss(self, yhat,weighting_applied=True): ------- :math:`-2(y_{i} - \\hat{y}_{i})` ''' - return -2*self.residual(yhat,weighting_applied)) + return -2*self.residual(yhat,weighting_applied) def diff2Loss(self, yhat): ''' @@ -231,13 +233,16 @@ def loss(self, yhat,weighting_applied=True): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - + + r=self.residual(yhat,weighting_applied) + sigma=self._sigma + # Calculate negative likelihood (depending on weighting of residuals). logpdf_p1= -np.log(2) logpdf_p2= np.log(2)/2 - logpdf_p3= -np.log(pi)/2 - logpdf_p4= np.log(1/self._sigma) - logpdf_p5_alt=-self.residual(yhat,weighting_applied)**2/(2*sigma**2) + logpdf_p3= -np.log(np.pi)/2 + logpdf_p4= np.log(1/sigma) + logpdf_p5_alt= -r**2 / (2*sigma**2) return (-(logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4+logpdf_p5_alt)).sum() def diff_loss(self, yhat,weighting_applied=True): @@ -366,7 +371,9 @@ def diff_loss(self, yhat,weighting_applied=True): :math:`\\mathcal\\frac{a \\left(\\hat{y} - y\\right)}{\\hat{y}^{2}}` ''' - return self._shape*-self.residual(yhat,weighting_applied)/yhat**2 + shape = self._shape + r = self.residual(yhat,weighting_applied) + return shape*-r/yhat**2 def diff2Loss(self, yhat,weighting_applied=True): ''' @@ -394,8 +401,8 @@ def diff2Loss(self, yhat,weighting_applied=True): yhat = yhat.ravel() y = self._y shape = self._shape - - return shape*(self.residual(yhat,weighting_applied)+y)/yhat**3 + r = self.residual(yhat,weighting_applied) + return shape*(r+y)/yhat**3 class Poisson(baseloss_type): ''' @@ -474,7 +481,8 @@ def diff2Loss(self, yhat): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - return self._y/(yhat**2) + y=self._y + return y/(yhat**2) class NegBinom(baseloss_type): ''' @@ -568,7 +576,6 @@ def diff_loss(self, yhat,weighting_applied=True): if 1 in yhat.shape: yhat = yhat.ravel() - y = self._y k = self._k r = self.residual(yhat,weighting_applied) first_derivs_yhat = k*-r/(yhat*(k+yhat)) @@ -602,7 +609,7 @@ def diff2Loss(self, yhat,weighting_applied=True): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - y = self._y + k = self._k r = self.residual(yhat,weighting_applied) scnd_derivs_yhat_p1= k diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index d8882249..e4182f54 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -17,7 +17,6 @@ from pygom.loss.base_loss import BaseLoss from pygom.loss.loss_type import Normal, Square, Poisson, Gamma, NegBinom -from pygom.model.ode_utils import check_array_type class SquareLoss(BaseLoss): ''' @@ -66,7 +65,7 @@ def __repr__(self): return "GammaLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = Gamma(self._y,self._shape,self._stateWeight) + self._lossObj = Gamma(self._y,self._shape,self._stateWeight) return self._lossObj class PoissonLoss(BaseLoss): @@ -82,7 +81,7 @@ def __repr__(self): return "PoissonLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = Poisson(self._y,self._stateWeight) + self._lossObj = Poisson(self._y,self._stateWeight) return self._lossObj class NegBinomLoss(BaseLoss): @@ -99,5 +98,5 @@ def __repr__(self): return "NegBinomLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = NegBinom(self._y,self._k,self._stateWeight) + self._lossObj = NegBinom(self._y,self._k,self._stateWeight) return self._lossObj \ No newline at end of file From 9b40b86f275e61aa53c9cc88d301555c8c074d46 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Tue, 30 Jun 2020 13:34:28 +0100 Subject: [PATCH 09/16] Check_array excludes boolean values by default --- ...s functions fitted to simulated data.ipynb | 1610 +++++++++-------- pygom/loss/base_loss.py | 60 +- pygom/loss/loss_type.py | 149 +- .../model/ode_utils/checks_and_conversions.py | 40 +- tests/test_loss_types.py | 273 +-- 5 files changed, 1220 insertions(+), 912 deletions(-) diff --git a/notebooks/Testing loss functions fitted to simulated data.ipynb b/notebooks/Testing loss functions fitted to simulated data.ipynb index 776f5847..573ea491 100644 --- a/notebooks/Testing loss functions fitted to simulated data.ipynb +++ b/notebooks/Testing loss functions fitted to simulated data.ipynb @@ -176,209 +176,209 @@ "data": { "text/plain": [ "array([[ 0.00000000e+00, 0.00000000e+00, nan],\n", - " [-3.21943456e-01, 1.85865527e-01, -1.13217774e-01],\n", - " [-2.10940831e-01, -1.40000086e-01, 3.21150841e-01],\n", - " [ 1.81602995e-01, 1.28076820e-02, 2.49787871e-01],\n", - " [-1.99910787e-01, -3.21987422e-01, 6.59265374e-02],\n", - " [-3.07353570e-01, -2.27188132e-01, 2.17562011e-01],\n", - " [-5.63337347e-02, -1.89013740e-01, 2.84964767e-02],\n", - " [ 2.31501967e-01, 6.14997028e-02, -2.35895637e-01],\n", - " [ 2.23927782e-01, -1.01405449e-01, -1.98699260e-01],\n", - " [ 2.48735438e-01, -3.53640373e-02, 1.67031470e-01],\n", - " [ 4.94412026e-02, -1.52057161e-01, 2.09835766e-01],\n", - " [-2.06776227e-01, 3.13201462e-01, -4.29291297e-02],\n", - " [ 2.46433170e-02, -2.84114224e-01, 3.25711119e-03],\n", - " [ 1.92155506e-01, 2.17675626e-01, 5.62946687e-02],\n", - " [-1.44069462e-01, 1.35347749e-01, -1.82909871e-01],\n", - " [-8.29226910e-02, 3.23393603e-01, -2.81718008e-01],\n", - " [-3.76928728e-02, 3.23038547e-02, -2.86446432e-01],\n", - " [-3.11282664e-01, 1.27084504e-01, -2.59438059e-02],\n", - " [-2.62325766e-02, 2.69860578e-01, 1.18361484e-01],\n", - " [ 1.06221765e-01, -9.70804044e-02, -2.74947371e-01],\n", - " [-2.71437837e-02, -2.18447494e-01, -5.67370795e-02],\n", - " [-3.12189987e-01, 2.22512900e-01, -1.66663625e-01],\n", - " [-1.28018641e-01, -2.34923267e-01, 1.41683585e-02],\n", - " [ 2.32254315e-01, -3.26165428e-01, 2.34238143e-01],\n", - " [ 8.69678367e-02, 1.64301394e-01, -2.47656180e-01],\n", - " [ 1.40965168e-01, 6.32849105e-02, -9.45633773e-02],\n", - " [ 3.07096765e-01, -1.42502266e-01, -3.77726686e-02],\n", - " [-6.09429143e-02, 1.63808739e-01, 3.28916009e-01],\n", - " [ 3.82767127e-02, 3.20843549e-02, -7.79089580e-02],\n", - " [ 9.56398819e-02, 4.18597131e-02, 4.03213450e-02],\n", - " [ 1.27231497e-01, -8.30499409e-02, -7.31856628e-02],\n", - " [ 4.95710698e-02, 2.76706458e-01, 2.05492090e-01],\n", - " [-2.08266620e-01, 2.39049966e-01, 2.01173560e-01],\n", - " [-2.93349546e-01, -2.57007747e-01, 9.98727121e-03],\n", - " [-3.22996838e-01, 1.46160366e-01, 1.80225707e-01],\n", - " [-1.87518084e-01, -3.77615176e-02, -6.75263992e-02],\n", - " [ 1.79662877e-01, -1.35008808e-01, 2.83698888e-01],\n", - " [ 1.35604549e-02, -2.62201419e-01, -2.72549801e-01],\n", - " [ 3.88544297e-02, -5.52991492e-02, 1.35833062e-02],\n", - " [ 9.16412350e-04, -9.24962534e-02, 2.09220178e-01],\n", - " [ 3.25720195e-01, -1.13579915e-01, 6.44327795e-02],\n", - " [ 1.85011815e-01, 2.56123076e-01, -4.11627271e-02],\n", - " [-2.82554284e-01, 2.64315337e-01, -8.83167048e-02],\n", - " [-1.86349157e-01, 3.56996669e-02, 2.01663352e-01],\n", - " [-1.57759231e-01, 1.39231206e-01, -1.85782649e-01],\n", - " [ 7.03547306e-02, 1.01422084e-01, 1.23427057e-01],\n", - " [ 2.76699346e-02, -3.91221695e-02, 2.16061024e-01],\n", - " [ 1.59004020e-01, -2.21259419e-01, 3.27064373e-01],\n", - " [ 1.47263354e-01, -1.04940533e-01, 2.44662128e-01],\n", - " [-1.02896184e-01, -1.55783920e-01, 2.95573231e-01],\n", - " [-2.68855926e-01, 3.19496258e-01, -2.91857351e-01],\n", - " [ 1.13792396e-01, -1.79844552e-01, 3.31017884e-01],\n", - " [-2.88347996e-01, -2.13458276e-01, 7.44025583e-02],\n", - " [ 7.94402079e-02, -4.94810671e-02, -5.15517506e-02],\n", - " [ 2.73209861e-01, 4.98005575e-02, 3.17599430e-01],\n", - " [-1.26001530e-01, 1.86226792e-01, -2.41490855e-01],\n", - " [ 2.20762784e-01, 2.08149383e-01, -1.95067777e-01],\n", - " [ 7.66135816e-02, -2.49310855e-01, -9.13035120e-02],\n", - " [ 1.97046212e-01, -2.14907322e-02, 3.29487704e-01],\n", - " [ 1.55059587e-01, -2.26415078e-01, 1.59962712e-01],\n", - " [ 2.11096333e-01, -2.65176253e-01, -4.05930821e-03],\n", - " [ 2.79075501e-01, 1.92098721e-01, -8.23100303e-02],\n", - " [-3.08439506e-01, -7.98957238e-02, -5.01829836e-02],\n", - " [-2.03697278e-01, 2.05995436e-01, -9.14985961e-02],\n", - " [ 1.20521659e-01, 3.00440276e-01, 1.47263752e-02],\n", - " [-2.27957751e-01, -8.21201620e-02, -1.19488396e-02],\n", - " [ 1.59556225e-01, -2.82204036e-02, -2.21599601e-01],\n", - " [ 2.15680392e-01, 3.03996830e-01, -2.71423977e-01],\n", - " [ 1.77769288e-01, 2.09960478e-01, 8.39473619e-02],\n", - " [ 1.13717062e-01, -1.79358977e-01, -4.59715825e-03],\n", - " [-1.84322552e-01, -2.26755373e-01, -2.39767730e-01],\n", - " [ 1.86058326e-01, -3.21698703e-01, -2.46524540e-01],\n", - " [ 2.86200529e-01, -2.17887930e-01, 3.57893365e-02],\n", - " [-1.18158603e-01, -6.54001442e-02, -2.87505412e-01],\n", - " [-1.50315173e-01, 1.42851125e-01, 2.20421926e-01],\n", - " [-2.23556346e-01, -1.92795329e-01, 1.74674105e-01],\n", - " [-2.31639431e-01, -4.84220495e-02, -8.52286090e-02],\n", - " [ 1.20174394e-01, -1.96588635e-01, 2.49598607e-01],\n", - " [ 1.96578388e-01, -6.38269970e-02, 9.43425551e-02],\n", - " [-3.81314176e-02, 3.18781466e-01, 1.77470481e-01],\n", - " [ 4.32925130e-02, -2.00318211e-01, 4.17754219e-02],\n", - " [ 2.36790925e-01, -1.03921195e-01, -3.30797879e-02],\n", - " [ 1.99476702e-01, -1.43344835e-01, 5.64405904e-02],\n", - " [ 3.31310790e-01, 1.50853809e-01, 1.35732696e-01],\n", - " [-2.41321604e-01, 3.19392547e-01, -4.54542545e-02],\n", - " [-6.91929812e-03, -2.13076727e-01, -1.63392477e-01],\n", - " [-1.22865716e-01, -1.78234910e-01, 2.03967351e-01],\n", - " [ 3.30704049e-01, 9.71682583e-02, -3.08190158e-01],\n", - " [ 2.00774222e-01, -1.42644728e-01, -2.98044193e-01],\n", - " [-2.23396056e-01, -2.40914551e-01, 2.12421125e-01],\n", - " [ 7.12265936e-02, 2.47778623e-02, -2.88177768e-01],\n", - " [-2.60885258e-01, 3.13300871e-01, 1.71580578e-01],\n", - " [-1.36024349e-01, -6.65814427e-02, -6.26423574e-02],\n", - " [ 1.55892372e-01, 2.48340883e-01, -2.95586414e-01],\n", - " [-1.77048639e-01, 3.20849855e-02, 3.03433400e-01],\n", - " [ 1.31558930e-01, 2.33285122e-01, -2.34144482e-02],\n", - " [-9.99275328e-02, -8.26120829e-02, 2.48214915e-01],\n", - " [ 1.06138964e-01, 1.75757064e-01, -3.19240383e-01],\n", - " [ 1.62623817e-01, 2.72537446e-02, -5.92349069e-02],\n", - " [-1.50942703e-01, 8.10263676e-02, -2.45111595e-01],\n", - " [ 1.80449990e-01, 2.72827791e-01, 1.08298678e-01],\n", - " [-2.32438202e-01, 2.88886019e-01, -1.84345430e-01],\n", - " [ 2.49503066e-01, 3.10983987e-01, -2.86543276e-01],\n", - " [ 1.20511488e-01, 5.13694112e-03, 1.36225876e-01],\n", - " [ 2.68332086e-01, 3.15883069e-01, 4.00702873e-02],\n", - " [-2.69552790e-01, 1.13927547e-01, -1.31478459e-01],\n", - " [ 1.53144584e-01, 2.49076716e-01, -2.26674703e-01],\n", - " [-1.03603484e-01, -2.10210157e-02, -2.41978432e-01],\n", - " [ 1.96105677e-01, -2.68912665e-01, 2.84057482e-01],\n", - " [ 1.07999685e-01, 9.50813469e-02, 1.44150697e-01],\n", - " [ 1.18566775e-02, 1.67907743e-01, 8.67410283e-02],\n", - " [-1.40939249e-01, 2.15215929e-01, 1.36839282e-01],\n", - " [-9.05791123e-02, -1.79494555e-01, -3.22292115e-01],\n", - " [-1.62777658e-01, -1.38902568e-01, -1.04280378e-01],\n", - " [-2.48846862e-01, 5.49497354e-02, -2.55146872e-01],\n", - " [-1.92560097e-01, 2.75780669e-01, 1.38053097e-02],\n", - " [ 7.22306638e-02, 2.51954666e-01, 2.00025665e-01],\n", - " [-1.48601712e-01, -6.24716939e-02, 1.22190401e-01],\n", - " [ 2.96343742e-01, -9.16466617e-02, -2.79057616e-01],\n", - " [-9.44903089e-02, 2.02212337e-01, 1.30955098e-01],\n", - " [ 2.59779211e-01, -3.17918046e-01, 1.04952796e-01],\n", - " [-9.19699690e-02, 3.24716030e-01, 1.02188300e-01],\n", - " [-1.56266425e-01, 2.22184605e-01, 9.96280301e-02],\n", - " [-8.09897738e-02, 1.34471312e-01, -7.32451926e-02],\n", - " [-1.40359625e-01, -2.11776854e-02, -3.10384400e-01],\n", - " [-2.73853206e-01, -1.95512118e-01, 3.98482839e-02],\n", - " [-1.27223980e-01, -2.32593176e-01, 1.70883648e-01],\n", - " [ 4.92405598e-02, 8.50372783e-02, 4.05976680e-02],\n", - " [ 1.29315076e-01, 1.81514925e-01, 2.69971751e-01],\n", - " [ 5.07861648e-02, -7.40873609e-02, 1.65365118e-01],\n", - " [ 2.68151227e-01, -1.45063285e-01, -2.16386660e-02],\n", - " [-3.17820212e-01, 1.62066777e-01, -2.07795803e-01],\n", - " [-3.16812154e-01, 2.96508501e-01, 1.92175410e-01],\n", - " [ 1.96337705e-01, 8.81620255e-02, -1.02653817e-01],\n", - " [-1.93525139e-01, -2.03936400e-01, 1.70445013e-01],\n", - " [-2.87456720e-02, -1.07611842e-01, 2.49101875e-01],\n", - " [ 8.09404791e-02, -3.21299706e-02, 1.23033680e-01],\n", - " [ 2.59498758e-01, -2.55703800e-02, -2.66267193e-01],\n", - " [ 2.35573590e-01, -1.56838315e-01, 2.56689692e-01],\n", - " [ 1.30542822e-01, 2.69746313e-01, -2.57985160e-01],\n", - " [ 1.74263648e-01, 2.29095931e-01, 7.48744349e-02],\n", - " [ 2.86189769e-01, 2.79547063e-01, 6.85199411e-02],\n", - " [-1.05937815e-01, 1.79938630e-01, 7.44842201e-02],\n", - " [ 2.15354490e-01, 1.79798390e-01, 1.86155500e-01],\n", - " [-2.40897200e-01, -1.23944817e-01, 6.86891899e-05],\n", - " [ 1.92303073e-01, 2.93842299e-01, 1.69436631e-01],\n", - " [ 6.00638743e-02, -1.92023781e-01, -2.35632974e-01],\n", - " [ 1.08886035e-01, -3.11263490e-01, 6.42473250e-02],\n", - " [-2.28977828e-01, -2.88312273e-01, -4.60168657e-02],\n", - " [ 1.88477181e-03, -1.41546947e-01, 3.28242664e-01],\n", - " [-1.73354229e-01, 3.13080313e-01, 2.87096208e-01],\n", - " [ 4.29327556e-02, -1.06010816e-01, 2.17850274e-01],\n", - " [ 6.71826155e-02, 6.18062750e-03, -1.61497479e-01],\n", - " [ 1.03828416e-01, 1.42508637e-01, 3.30062436e-01],\n", - " [ 2.68190801e-01, -2.61865575e-02, -4.02513191e-02],\n", - " [-2.31829458e-01, -1.09360422e-01, -3.29300076e-01],\n", - " [-1.81418170e-01, -5.11671925e-02, -9.01593327e-02],\n", - " [-3.11486686e-01, 3.11728877e-02, -3.05828061e-01],\n", - " [ 1.86347159e-01, 2.36229401e-01, 3.01929479e-01],\n", - " [-2.92591029e-01, 9.08584343e-02, -1.40299446e-01],\n", - " [-1.05944855e-02, 1.61865581e-01, -2.50704225e-01],\n", - " [-2.45622639e-02, -3.16306034e-01, -2.69959629e-01],\n", - " [ 8.84372993e-02, -2.81337428e-01, 1.35729306e-01],\n", - " [-6.21876036e-02, -5.41408363e-02, 1.77717783e-01],\n", - " [ 2.05371132e-01, 1.73047469e-02, 3.20133765e-01],\n", - " [ 1.28758414e-01, 4.28390061e-03, 8.84307448e-02],\n", - " [ 2.02100596e-01, -6.90202732e-03, -1.15680333e-01],\n", - " [ 4.91767073e-02, 2.68686316e-01, 1.27224288e-01],\n", - " [ 1.53107746e-01, -2.24791872e-01, -2.82729565e-01],\n", - " [ 1.27456089e-01, 2.89267392e-02, -2.31685444e-01],\n", - " [ 1.21530019e-01, -1.50701614e-01, -2.20018436e-01],\n", - " [ 2.40944283e-01, -5.44516998e-02, 1.78625669e-01],\n", - " [-2.20691466e-01, 2.27806142e-01, -3.19788277e-01],\n", - " [ 5.43321208e-02, -1.68073613e-01, 2.88610851e-01],\n", - " [-5.14881733e-02, -2.17052746e-01, 8.46518610e-02],\n", - " [-3.26344726e-01, -2.65734801e-01, -3.29900167e-01],\n", - " [ 2.91065837e-01, -8.86418051e-02, 1.43952139e-01],\n", - " [-3.18629385e-01, 2.42564945e-01, -1.50746165e-01],\n", - " [ 1.31558589e-02, -1.37399607e-01, -3.10027779e-02],\n", - " [-2.82888143e-01, -1.97311938e-01, -1.71934170e-01],\n", - " [-3.26726159e-01, -1.46398217e-01, -2.67336805e-01],\n", - " [-2.50764400e-01, 2.40030847e-01, 1.90164020e-01],\n", - " [-1.86402443e-01, -1.59800689e-01, -1.24289238e-01],\n", - " [-3.23243518e-01, 1.64399910e-01, 1.89434490e-02],\n", - " [ 1.62444666e-01, 1.72003606e-01, 3.15533874e-01],\n", - " [ 4.11196377e-02, -8.77415417e-02, 1.23995207e-01],\n", - " [ 1.28272258e-01, -2.32939686e-02, 4.35417997e-02],\n", - " [-1.75479288e-01, 9.41603764e-02, 2.52966436e-01],\n", - " [-1.12455732e-01, 1.64264689e-01, -3.33227910e-01],\n", - " [-2.10629561e-02, 2.63683701e-01, -2.22926132e-01],\n", - " [ 4.89649368e-02, 1.17222997e-01, 2.04754960e-01],\n", - " [-1.00714628e-01, 7.93490662e-02, -7.47079386e-02],\n", - " [ 2.92136018e-03, 1.29087068e-01, -1.48908029e-01],\n", - " [ 1.13242124e-01, -1.04279228e-01, 2.47219125e-01],\n", - " [-2.18469863e-01, -1.99858094e-01, -3.11419043e-01],\n", - " [ 2.82152105e-01, -5.74810426e-02, 6.78507853e-02],\n", - " [ 1.90039518e-01, -2.49188273e-01, -2.24943614e-01],\n", - " [-1.39040280e-01, -1.70893861e-01, -9.90695495e-02],\n", - " [-1.54891812e-01, 2.19340978e-01, -2.86544108e-03],\n", - " [ 1.54253118e-01, 1.73852897e-01, -1.74464629e-01],\n", - " [-9.57521372e-02, 1.46961351e-01, 3.27614130e-01],\n", - " [ 3.20980053e-01, -1.54030722e-01, -3.70355927e-03],\n", - " [ 1.10411322e-01, -1.66169988e-01, -2.91024643e-01],\n", - " [ 2.03023170e-01, 2.57521968e-01, -1.37497649e-01]])" + " [-1.73465915e-01, -1.17281547e-01, -2.25860015e-02],\n", + " [ 2.18875989e-03, -1.41630417e-01, -1.20285204e-01],\n", + " [ 3.10984783e-01, -1.16333578e-01, 2.95271450e-01],\n", + " [-2.69029696e-01, -1.99213726e-01, -1.90606565e-01],\n", + " [ 1.35684509e-01, 1.78379344e-01, 1.80962883e-01],\n", + " [-8.77803140e-02, 2.49616076e-01, -3.00454033e-02],\n", + " [-3.04094678e-02, -3.10164909e-01, 6.59761925e-02],\n", + " [ 4.77262892e-02, -1.92819030e-01, -1.39817160e-01],\n", + " [ 1.70193324e-01, 1.94346231e-01, 2.65605367e-01],\n", + " [-1.07254972e-01, 3.92049280e-02, -4.60377530e-02],\n", + " [ 2.25368182e-01, 1.68391679e-01, 5.02529134e-02],\n", + " [-2.73480406e-02, -2.43459230e-01, -2.72124777e-01],\n", + " [ 3.25378306e-01, 3.11198994e-01, -3.19891929e-01],\n", + " [-3.02732680e-02, -7.38888142e-02, -1.42714821e-01],\n", + " [ 1.94084991e-01, -2.12622683e-01, -1.15964568e-01],\n", + " [ 2.48373612e-01, 2.61208788e-01, 2.24903683e-01],\n", + " [ 1.37001895e-01, -1.85852789e-01, -1.18528471e-01],\n", + " [ 1.95169073e-01, 2.33950828e-01, 2.61071600e-01],\n", + " [ 2.94426553e-01, 1.78731291e-01, 1.97572440e-01],\n", + " [ 1.04043589e-01, -1.48204811e-01, -2.49256282e-01],\n", + " [-2.09591210e-01, 1.27888057e-01, 4.29371010e-02],\n", + " [-1.43084416e-01, -2.20412193e-01, -3.25009447e-01],\n", + " [ 6.33522507e-02, 1.53844079e-02, 2.99794892e-01],\n", + " [ 2.11100728e-01, -1.74071212e-01, -2.25674301e-01],\n", + " [-2.14296968e-02, -2.65530317e-01, 3.25590647e-02],\n", + " [-1.62179509e-01, -2.81708892e-01, -3.75237265e-02],\n", + " [-1.09534418e-01, -2.96644636e-01, -1.46756635e-01],\n", + " [ 1.97785675e-01, 1.21368330e-01, -8.52835473e-02],\n", + " [ 6.19544052e-02, 2.56309699e-01, 6.11246356e-02],\n", + " [ 2.00808833e-01, -1.42135844e-01, -2.13179622e-01],\n", + " [-2.16077990e-01, -2.86104187e-01, -2.95618164e-01],\n", + " [ 3.21509098e-01, 2.54100768e-01, 1.48586067e-01],\n", + " [-1.77056121e-01, 3.14195690e-01, -7.89813198e-02],\n", + " [ 9.52571895e-02, -2.93934351e-01, 2.32526004e-01],\n", + " [ 3.25502678e-01, 2.31769642e-01, -1.07617135e-02],\n", + " [ 2.35964481e-01, -1.33138709e-01, -1.72244039e-01],\n", + " [-1.66454417e-01, 2.45896187e-02, 3.26641177e-01],\n", + " [ 1.84816860e-01, 2.32456914e-01, 1.99283036e-01],\n", + " [ 8.91630169e-02, -4.65652026e-02, -1.29383851e-02],\n", + " [ 4.91988839e-02, 7.28993711e-02, -6.48891682e-02],\n", + " [-7.55111005e-02, -3.01904206e-01, -5.57502552e-02],\n", + " [ 8.02339702e-03, -2.71726635e-01, -1.62495983e-02],\n", + " [-6.36690889e-02, -2.96569398e-01, -9.48426199e-02],\n", + " [-3.10261981e-01, 2.49488644e-02, 2.99644152e-01],\n", + " [ 1.45286030e-01, 3.06316140e-01, -7.45581102e-03],\n", + " [ 3.07300545e-01, -3.22020626e-01, 1.49929309e-01],\n", + " [ 1.40175328e-01, -1.85315900e-02, -1.02966849e-01],\n", + " [ 1.18323765e-01, 3.24544502e-03, -3.14290184e-01],\n", + " [-2.91429133e-01, 2.87166606e-01, 2.99142261e-02],\n", + " [-5.48979385e-02, 8.98441545e-02, 1.03955500e-01],\n", + " [ 3.04884296e-01, -1.37771353e-01, 1.01023789e-01],\n", + " [-1.33848241e-01, -1.11395555e-01, 4.99581753e-02],\n", + " [-3.78918481e-02, -3.23665755e-01, -1.47739901e-01],\n", + " [ 2.21314141e-01, 2.82572816e-01, 4.72580803e-02],\n", + " [ 5.22709247e-02, -3.23988777e-01, -3.31099138e-02],\n", + " [ 4.41287378e-04, 1.12372308e-01, 1.25004212e-01],\n", + " [ 7.91370306e-02, -1.43266719e-01, 5.20809368e-02],\n", + " [-2.71529409e-01, 9.58139850e-02, -4.10690930e-02],\n", + " [-7.58599886e-02, 2.11473953e-01, 6.59916787e-02],\n", + " [-1.98114673e-02, 3.25925174e-01, -1.88900522e-02],\n", + " [-2.15236733e-01, -6.61674151e-03, -7.97228069e-02],\n", + " [-8.52869474e-02, -4.54868991e-02, 1.81776124e-01],\n", + " [-3.17873872e-01, -5.00410695e-03, 2.74312022e-01],\n", + " [-2.56697406e-01, -2.52524664e-01, 8.48325600e-02],\n", + " [ 6.87283327e-02, 2.55013582e-01, -1.14591512e-01],\n", + " [-2.63254784e-01, 3.03913765e-01, -3.04301181e-01],\n", + " [ 2.49161251e-01, -1.57671710e-01, 8.75571120e-02],\n", + " [-1.98673502e-01, 2.14671912e-01, -1.89495051e-01],\n", + " [-4.59403003e-02, 2.04353868e-01, 2.27361836e-01],\n", + " [ 7.64131802e-02, 2.52120942e-01, -1.75540234e-01],\n", + " [-1.95232206e-01, 1.69610425e-02, -1.35020865e-01],\n", + " [-2.15817787e-01, 1.22040324e-01, -2.56928157e-01],\n", + " [-3.28443088e-01, 3.26392955e-01, 9.71235957e-02],\n", + " [ 6.52615418e-02, 1.62982784e-01, -2.77772468e-01],\n", + " [-1.06954476e-01, -1.82748624e-01, -2.30851985e-01],\n", + " [-1.03560258e-01, 2.49776694e-01, 2.39589555e-01],\n", + " [-2.51361697e-01, -2.62613604e-01, -3.43346629e-02],\n", + " [ 5.52044588e-02, 1.71414602e-01, -1.18827697e-01],\n", + " [ 2.04645160e-01, -1.57695147e-01, -7.46836992e-02],\n", + " [-2.54150013e-01, 2.00084150e-01, -2.77762288e-01],\n", + " [ 1.91226654e-01, -1.15839953e-01, 1.95446804e-01],\n", + " [ 3.25631354e-01, -1.55219633e-01, -1.36220152e-01],\n", + " [ 8.59434276e-02, 2.44324599e-01, -1.80598534e-01],\n", + " [-4.41759258e-02, 2.88086579e-01, 2.32770906e-01],\n", + " [-2.27196580e-01, 2.72331912e-01, -1.53109214e-01],\n", + " [ 1.47937296e-01, -1.28297016e-01, -2.28099160e-01],\n", + " [ 9.75527646e-02, 3.31250187e-01, 1.80018836e-01],\n", + " [-2.40869627e-03, -2.62345740e-01, -2.93019352e-01],\n", + " [ 1.42517039e-01, -3.26917253e-01, 3.24664042e-01],\n", + " [ 2.66350592e-01, -1.89474157e-01, -3.76501731e-02],\n", + " [ 3.00491876e-01, 7.70405853e-02, 1.38895227e-01],\n", + " [-2.24919571e-01, 1.38375653e-04, -1.22365187e-01],\n", + " [ 1.89472971e-01, -6.99390524e-02, 1.75359377e-01],\n", + " [ 2.40847084e-01, 2.17245088e-01, -1.29960940e-01],\n", + " [ 1.17031088e-01, 1.25207417e-01, -2.13111306e-01],\n", + " [-1.48790790e-01, 2.42009355e-01, -2.72889122e-01],\n", + " [-6.55964475e-03, -2.67211611e-01, -2.75637870e-01],\n", + " [-1.85542712e-01, -7.13208125e-02, -1.43045237e-01],\n", + " [ 2.14837170e-01, 3.09019053e-01, -1.03940169e-01],\n", + " [-2.08291133e-01, -1.55812903e-01, -2.71145936e-01],\n", + " [-1.55833854e-01, -2.88308172e-01, 2.45174658e-01],\n", + " [-3.11004925e-01, 1.66460354e-01, 1.48310637e-01],\n", + " [ 1.11900762e-01, 1.59711839e-01, -1.06092199e-01],\n", + " [ 2.52702535e-01, 2.63918522e-01, 8.81508771e-02],\n", + " [-2.96912130e-01, 2.00037590e-01, -1.35534414e-01],\n", + " [ 2.57644746e-01, 2.17801439e-01, -1.37936016e-01],\n", + " [-2.21287471e-02, 1.87488209e-01, 6.54050559e-02],\n", + " [-3.13781890e-01, 8.90421404e-02, -2.65601600e-03],\n", + " [ 1.73633876e-02, 4.70498687e-02, 1.99892821e-01],\n", + " [-1.75870723e-01, -2.34269032e-01, -1.44870264e-01],\n", + " [ 2.60912112e-01, 8.12053627e-02, 3.86306769e-02],\n", + " [ 2.07535825e-01, -2.98946883e-01, -2.94085800e-01],\n", + " [-2.28341327e-02, -1.05874587e-01, 3.06311986e-03],\n", + " [ 2.88008753e-01, 1.71295755e-01, -1.44628284e-03],\n", + " [-3.12911107e-01, -1.94018364e-01, 1.04187514e-01],\n", + " [-2.65559378e-01, 1.87606865e-01, -3.14186465e-01],\n", + " [ 3.12564575e-01, -1.41561571e-01, 2.97041688e-01],\n", + " [-1.61079637e-01, -6.04344631e-02, -3.16709214e-01],\n", + " [-9.79493115e-02, 2.56336113e-01, 2.40368610e-01],\n", + " [ 2.07487179e-01, 1.37615049e-01, 3.01609274e-01],\n", + " [ 2.98452807e-01, -1.98587552e-01, -9.27371231e-02],\n", + " [ 1.34487459e-01, 1.37004951e-01, -2.08067897e-01],\n", + " [-3.24649739e-01, 2.79299579e-01, 2.42697497e-01],\n", + " [ 1.48755627e-01, -2.56194465e-02, 2.16687251e-01],\n", + " [ 2.82086858e-01, -2.73028509e-01, 1.49601622e-01],\n", + " [-2.90566692e-01, -1.46843110e-01, -4.20095301e-02],\n", + " [-2.02395486e-01, 2.76415604e-01, 2.92878761e-01],\n", + " [ 1.29300728e-01, -2.25682761e-01, -1.39203475e-01],\n", + " [-2.94574241e-01, -1.60448086e-02, -1.33783822e-01],\n", + " [-1.80234848e-01, 1.27149669e-01, 3.46658132e-02],\n", + " [-3.28310685e-01, 2.48574245e-01, 1.82136367e-01],\n", + " [-2.24348578e-01, 7.15601086e-02, -1.00090791e-01],\n", + " [ 1.35871520e-01, 1.78353047e-01, 1.14648325e-01],\n", + " [-2.93504246e-02, -7.33876121e-02, 2.60776669e-01],\n", + " [-9.32936487e-02, 2.09428551e-02, -2.79570179e-01],\n", + " [ 6.37399122e-02, 2.17366633e-01, 3.02729114e-01],\n", + " [ 9.07693126e-02, 1.59002147e-01, 2.41856391e-02],\n", + " [ 3.29090325e-01, -1.17795784e-01, -2.89107948e-01],\n", + " [-3.24646432e-02, 1.63737182e-01, 2.09973144e-02],\n", + " [ 1.80119330e-01, -6.34746381e-02, 2.19125711e-01],\n", + " [-1.39888719e-01, -8.80666022e-02, -1.42371440e-01],\n", + " [ 3.31763098e-01, 8.68652514e-02, 3.15174893e-01],\n", + " [-2.97656020e-01, 8.69786170e-02, -3.21062047e-01],\n", + " [-5.32967716e-02, -3.10244442e-01, 5.49010428e-02],\n", + " [-5.42176967e-02, -7.62270050e-02, -5.57502908e-02],\n", + " [-8.98274483e-02, -1.12891073e-01, -1.41591575e-01],\n", + " [ 3.26933775e-02, 1.13416765e-01, 9.83869429e-02],\n", + " [-8.30560535e-02, -1.24896527e-01, -2.28530639e-02],\n", + " [-2.50228276e-01, 1.14537667e-02, -3.41017652e-03],\n", + " [-1.38776547e-01, -2.50449609e-01, -6.21100653e-02],\n", + " [ 1.44905560e-01, -2.75800643e-01, 2.65509337e-01],\n", + " [-3.20089696e-01, 3.27402651e-01, -1.72856493e-01],\n", + " [ 1.15474683e-01, -2.45068819e-01, -4.92954020e-02],\n", + " [ 2.05133386e-01, 3.27483684e-01, -1.93659902e-01],\n", + " [-2.17767265e-01, 8.70771976e-02, 1.87124947e-01],\n", + " [ 7.27246238e-02, -1.40465442e-01, -2.69193721e-01],\n", + " [-9.97701910e-03, 1.07729750e-01, -2.68065630e-01],\n", + " [ 3.03733136e-01, 3.22867206e-01, 1.49238218e-01],\n", + " [-2.78795783e-01, -1.14419874e-02, -7.20286782e-02],\n", + " [ 2.27085067e-01, 2.25468966e-03, 3.30907780e-01],\n", + " [ 8.96872448e-02, 1.61653251e-02, 1.85384909e-01],\n", + " [ 2.09636861e-02, 1.59974804e-01, -2.01092462e-01],\n", + " [ 2.89371780e-01, -1.56939225e-01, 3.21132503e-01],\n", + " [-1.60498331e-01, -1.18765721e-01, 1.13698025e-01],\n", + " [ 2.58419878e-01, -2.43509871e-01, -2.62146111e-01],\n", + " [-1.73732340e-01, 2.78540447e-01, -3.26039184e-01],\n", + " [-1.90956096e-02, -2.53887573e-01, -1.00832029e-01],\n", + " [ 1.90229262e-01, -1.72023628e-01, -2.31129213e-01],\n", + " [ 1.64831891e-01, 1.42491962e-01, -1.59541848e-01],\n", + " [-2.63697330e-01, 2.50564149e-01, 1.62164895e-01],\n", + " [-3.05547702e-01, 1.00183246e-01, 7.41942823e-02],\n", + " [ 4.07308835e-02, -2.31988517e-01, -3.25882263e-01],\n", + " [-1.53928260e-01, 2.11032128e-01, 2.48124476e-01],\n", + " [-4.75569094e-02, 1.11467076e-01, 1.61397329e-01],\n", + " [ 3.24990686e-01, -2.25966590e-01, 2.50815594e-01],\n", + " [-1.51945789e-01, 1.08083714e-01, -2.81320222e-01],\n", + " [-1.04216758e-01, -1.04818192e-01, 2.88203609e-01],\n", + " [-3.03459319e-01, 2.11989847e-01, -1.60581341e-01],\n", + " [ 1.34966390e-01, -1.17862102e-01, -2.43005916e-02],\n", + " [ 2.27585955e-01, 2.97513116e-01, 3.23156970e-01],\n", + " [ 1.01935503e-02, 2.84152144e-01, 2.22278818e-01],\n", + " [-1.39242592e-01, -9.10229412e-02, 3.25125351e-01],\n", + " [ 1.61950734e-01, -2.86648561e-01, -4.84271868e-02],\n", + " [-3.14874702e-01, 1.87709580e-01, 9.93054614e-02],\n", + " [ 1.88947588e-01, 1.83665135e-01, -1.59567842e-01],\n", + " [ 8.29825603e-02, 1.67331153e-01, 4.33415390e-02],\n", + " [-4.90594041e-02, -2.91446169e-01, -1.04161328e-01],\n", + " [ 1.60369798e-01, -1.49862405e-01, -2.93917315e-02],\n", + " [ 3.12709890e-01, -4.68877085e-02, -1.28360996e-01],\n", + " [ 2.49744887e-01, 3.28753915e-01, 2.21007900e-01],\n", + " [-9.28652790e-02, -6.89210427e-02, 2.25952258e-01],\n", + " [-2.44509281e-01, 3.04169434e-01, -2.59243410e-01],\n", + " [-2.23974760e-01, -3.15196226e-01, -9.50514355e-02],\n", + " [-8.94209698e-02, 2.46512550e-01, -2.44376339e-02],\n", + " [-1.88389365e-01, -6.98384260e-02, 2.25805610e-01],\n", + " [-1.12387378e-01, 1.24293193e-01, 2.60368640e-01],\n", + " [-7.04497617e-02, 1.72365737e-02, 1.95754470e-01],\n", + " [ 4.28703247e-02, -1.06070454e-01, -1.66811253e-01],\n", + " [ 1.76556407e-01, -1.65162532e-01, 9.66494270e-02],\n", + " [-2.20010409e-01, -4.73485568e-02, -1.48941583e-01],\n", + " [-2.12488717e-01, -5.77153871e-03, 2.86460630e-01],\n", + " [-2.66543889e-01, 3.10357896e-01, 9.10328100e-02],\n", + " [-1.77407989e-02, -2.32471504e-01, -2.99887659e-01]])" ] }, "execution_count": 8, @@ -400,7 +400,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -436,209 +436,209 @@ { "data": { "text/plain": [ - "array([[5.54899714e+00, 1.39761571e-01],\n", - " [9.41509648e+00, 6.95380093e-01],\n", - " [2.59415887e+01, 1.73602161e+00],\n", - " [4.06294543e+01, 3.63207199e+00],\n", - " [1.08339867e+02, 9.89807619e+00],\n", - " [2.65942008e+02, 1.97219908e+01],\n", - " [8.14010192e+02, 3.43927387e+01],\n", - " [1.61036450e+03, 8.44615745e+01],\n", - " [4.03372942e+03, 2.87600545e+02],\n", - " [8.24405119e+03, 6.95570046e+02],\n", - " [2.94412965e+04, 1.27820655e+03],\n", - " [3.63262375e+04, 3.08314488e+03],\n", - " [1.34300664e+05, 7.31638055e+03],\n", - " [2.51120961e+05, 1.22282810e+04],\n", - " [5.12397402e+05, 2.15432773e+04],\n", - " [5.85616873e+05, 3.84847695e+04],\n", - " [7.90205922e+05, 8.36926709e+04],\n", - " [9.74797129e+05, 1.37447113e+05],\n", - " [7.07757082e+05, 1.17346978e+05],\n", - " [6.03556137e+05, 1.89433078e+05],\n", - " [9.13909621e+05, 1.99048484e+05],\n", - " [5.48929799e+05, 2.79399602e+05],\n", - " [4.62040519e+05, 3.83327390e+05],\n", - " [7.61326355e+05, 2.58855593e+05],\n", - " [6.62287422e+05, 3.40426427e+05],\n", - " [5.08464539e+05, 3.91021455e+05],\n", - " [6.56745303e+05, 5.78473948e+05],\n", - " [5.54162951e+05, 4.26765230e+05],\n", - " [5.32220707e+05, 5.08730031e+05],\n", - " [4.45615989e+05, 4.76315527e+05],\n", - " [5.90230868e+05, 6.48108582e+05],\n", - " [5.44910361e+05, 6.72870334e+05],\n", - " [3.10827425e+05, 5.87435017e+05],\n", - " [4.56115660e+05, 7.10530498e+05],\n", - " [3.64253784e+05, 5.79474331e+05],\n", - " [3.11474802e+05, 8.21438803e+05],\n", - " [2.52718860e+05, 4.78270705e+05],\n", - " [3.07809391e+05, 6.83324686e+05],\n", - " [2.81269787e+05, 8.34432164e+05],\n", - " [2.61336999e+05, 7.50610280e+05],\n", - " [3.52273390e+05, 6.89933915e+05],\n", - " [3.37278880e+05, 6.68473671e+05],\n", - " [2.62817027e+05, 8.96729957e+05],\n", - " [2.74990268e+05, 6.17678724e+05],\n", - " [2.52897724e+05, 8.65475700e+05],\n", - " [2.09867373e+05, 9.50457602e+05],\n", - " [1.61791280e+05, 1.05135240e+06],\n", - " [1.76888541e+05, 9.98681754e+05],\n", - " [1.58703643e+05, 1.05201866e+06],\n", - " [2.35953746e+05, 5.81511546e+05],\n", - " [1.39508382e+05, 1.10461141e+06],\n", - " [1.27265676e+05, 9.00559518e+05],\n", - " [1.46297085e+05, 8.02469639e+05],\n", - " [1.53697592e+05, 1.12469407e+06],\n", - " [1.65201257e+05, 6.52874344e+05],\n", - " [1.60048497e+05, 6.98299422e+05],\n", - " [9.45967979e+04, 7.94188534e+05],\n", - " [1.17291509e+05, 1.17012509e+06],\n", - " [8.82053548e+04, 1.02770182e+06],\n", - " [7.96994745e+04, 8.87920192e+05],\n", - " [1.22990003e+05, 8.23010899e+05],\n", - " [9.02983786e+04, 8.56602566e+05],\n", - " [1.12583275e+05, 8.23690011e+05],\n", - " [1.15479244e+05, 9.24618482e+05],\n", - " [7.75326545e+04, 9.04591116e+05],\n", - " [7.80821749e+04, 7.15856130e+05],\n", - " [9.96657551e+04, 6.72890200e+05],\n", - " [8.79682412e+04, 1.00514064e+06],\n", - " [5.67535777e+04, 9.26563100e+05],\n", - " [5.08677148e+04, 7.10220532e+05],\n", - " [4.24456569e+04, 7.06325639e+05],\n", - " [4.65548460e+04, 9.74134427e+05],\n", - " [5.29184248e+04, 6.72152061e+05],\n", - " [6.15539817e+04, 1.15468993e+06],\n", - " [4.13557069e+04, 1.11449170e+06],\n", - " [4.63747352e+04, 8.70190374e+05],\n", - " [3.72443444e+04, 1.19166998e+06],\n", - " [4.12822885e+04, 1.04608545e+06],\n", - " [5.53179116e+04, 1.12807999e+06],\n", - " [3.19076952e+04, 1.00020804e+06],\n", - " [3.40102420e+04, 9.30221189e+05],\n", - " [3.09282140e+04, 1.01829940e+06],\n", - " [3.95233957e+04, 1.09672857e+06],\n", - " [4.31016012e+04, 9.23362846e+05],\n", - " [2.44532763e+04, 8.10610309e+05],\n", - " [2.42905662e+04, 1.16837923e+06],\n", - " [3.08495243e+04, 6.72357927e+05],\n", - " [2.29309129e+04, 6.83181207e+05],\n", - " [1.93124101e+04, 1.18157506e+06],\n", - " [2.48005224e+04, 6.94595493e+05],\n", - " [3.02329559e+04, 1.14461008e+06],\n", - " [2.04398683e+04, 9.16831496e+05],\n", - " [2.60028015e+04, 6.89740714e+05],\n", - " [2.04497354e+04, 1.27760714e+06],\n", - " [2.32445428e+04, 9.58179175e+05],\n", - " [1.64473455e+04, 1.22583633e+06],\n", - " [2.00514453e+04, 6.69149880e+05],\n", - " [1.66644545e+04, 9.25503667e+05],\n", - " [1.66814938e+04, 7.43239584e+05],\n", - " [1.86832999e+04, 1.09203041e+06],\n", - " [1.79963211e+04, 8.04265819e+05],\n", - " [1.74121296e+04, 7.03980774e+05],\n", - " [1.26988684e+04, 1.12187081e+06],\n", - " [1.58140231e+04, 1.02757091e+06],\n", - " [1.27340719e+04, 8.58592858e+05],\n", - " [1.35826575e+04, 7.64916022e+05],\n", - " [1.01263816e+04, 7.50180716e+05],\n", - " [7.19342074e+03, 1.27142317e+06],\n", - " [1.02493864e+04, 1.13344203e+06],\n", - " [1.03978921e+04, 1.07706574e+06],\n", - " [1.02914248e+04, 1.12721159e+06],\n", - " [6.60980734e+03, 6.72248410e+05],\n", - " [6.59849528e+03, 8.88855805e+05],\n", - " [7.68970477e+03, 7.39423756e+05],\n", - " [8.84584242e+03, 1.00677590e+06],\n", - " [8.25728105e+03, 1.19211086e+06],\n", - " [5.88190675e+03, 1.11514993e+06],\n", - " [5.42093057e+03, 7.16639885e+05],\n", - " [6.82473026e+03, 1.12453486e+06],\n", - " [3.68320721e+03, 1.09898609e+06],\n", - " [6.80452270e+03, 1.09652679e+06],\n", - " [5.97168604e+03, 1.09425515e+06],\n", - " [5.27277158e+03, 9.22447441e+05],\n", - " [4.32747516e+03, 6.86566727e+05],\n", - " [3.38326107e+03, 1.03547520e+06],\n", - " [3.06991919e+03, 1.16619965e+06],\n", - " [4.12887018e+03, 1.03663789e+06],\n", - " [4.27672242e+03, 1.26537482e+06],\n", - " [3.18806484e+03, 1.16135256e+06],\n", - " [2.80011832e+03, 9.75156955e+05],\n", - " [3.62041856e+03, 7.89736072e+05],\n", - " [3.84227414e+03, 1.18864231e+06],\n", - " [3.06755125e+03, 8.94816531e+05],\n", - " [2.13467277e+03, 1.16730640e+06],\n", - " [2.27626397e+03, 1.24591570e+06],\n", - " [2.34839501e+03, 1.12030879e+06],\n", - " [2.24900213e+03, 7.32039326e+05],\n", - " [1.85112410e+03, 1.25393067e+06],\n", - " [2.65171542e+03, 7.40465218e+05],\n", - " [2.44163654e+03, 1.07273915e+06],\n", - " [2.41789135e+03, 1.06650080e+06],\n", - " [2.12092455e+03, 1.07255283e+06],\n", - " [2.01724608e+03, 1.18412737e+06],\n", - " [1.42484567e+03, 9.98442128e+05],\n", - " [2.00171844e+03, 1.16762736e+06],\n", - " [1.18906475e+03, 7.63242127e+05],\n", - " [9.64151573e+02, 1.06275748e+06],\n", - " [9.47691461e+02, 9.52712785e+05],\n", - " [1.08737495e+03, 1.32656020e+06],\n", - " [1.58211972e+03, 1.28554538e+06],\n", - " [1.02462654e+03, 1.21645444e+06],\n", - " [1.09696954e+03, 8.37588347e+05],\n", - " [1.18485005e+03, 1.32868306e+06],\n", - " [9.60649471e+02, 9.58801891e+05],\n", - " [8.35750134e+02, 6.70070548e+05],\n", - " [8.46933749e+02, 9.09028524e+05],\n", - " [8.75541052e+02, 6.93582525e+05],\n", - " [9.98457029e+02, 1.30087794e+06],\n", - " [8.38077124e+02, 8.59040056e+05],\n", - " [8.49095933e+02, 7.48748175e+05],\n", - " [4.75278209e+02, 7.29532863e+05],\n", - " [4.75221920e+02, 1.13497828e+06],\n", - " [5.94953735e+02, 1.17697697e+06],\n", - " [6.08685663e+02, 1.31934387e+06],\n", - " [5.71588897e+02, 1.08781125e+06],\n", - " [5.37656203e+02, 8.83840889e+05],\n", - " [6.53359338e+02, 1.12664376e+06],\n", - " [3.79753204e+02, 7.16919053e+05],\n", - " [4.79460534e+02, 7.67956524e+05],\n", - " [3.76455799e+02, 7.79635821e+05],\n", - " [3.98678387e+02, 1.17812870e+06],\n", - " [4.92440834e+02, 6.79938898e+05],\n", - " [3.17390876e+02, 1.28811921e+06],\n", - " [2.84136696e+02, 1.08425822e+06],\n", - " [2.53473783e+02, 6.69868499e+05],\n", - " [2.99264007e+02, 1.14357648e+06],\n", - " [3.88123342e+02, 8.48988552e+05],\n", - " [2.56298225e+02, 9.68709296e+05],\n", - " [2.26865279e+02, 8.27831780e+05],\n", - " [2.29488974e+02, 7.32466208e+05],\n", - " [3.17120474e+02, 1.18985963e+06],\n", - " [2.04389883e+02, 8.75497720e+05],\n", - " [2.69441520e+02, 1.01870765e+06],\n", - " [2.57974385e+02, 1.31524429e+06],\n", - " [1.91007675e+02, 1.12375985e+06],\n", - " [1.94527978e+02, 1.04333394e+06],\n", - " [2.07292919e+02, 1.25272904e+06],\n", - " [2.09816912e+02, 6.66651918e+05],\n", - " [2.16626923e+02, 7.76940647e+05],\n", - " [1.82179370e+02, 1.20455849e+06],\n", - " [1.67419689e+02, 9.25148524e+05],\n", - " [1.66593221e+02, 8.50966382e+05],\n", - " [1.25715209e+02, 1.24704406e+06],\n", - " [1.06823665e+02, 6.88489017e+05],\n", - " [1.19694951e+02, 1.06771516e+06],\n", - " [9.06989100e+01, 7.74962746e+05],\n", - " [9.52722524e+01, 9.00826911e+05],\n", - " [1.33280543e+02, 9.97025552e+05],\n", - " [1.22050775e+02, 8.25449524e+05],\n", - " [1.13438619e+02, 1.32748280e+06],\n", - " [7.95888118e+01, 9.96202694e+05],\n", - " [7.46208572e+01, 7.08911899e+05],\n", - " [1.07049236e+02, 8.62428915e+05]])" + "array([[4.13048703e+00, 1.54045618e-01],\n", + " [9.39724796e+00, 4.63032787e-01],\n", + " [2.26338241e+01, 1.79920071e+00],\n", + " [4.79865867e+01, 2.75795293e+00],\n", + " [1.65196042e+02, 9.60054641e+00],\n", + " [4.09779333e+02, 1.85994178e+01],\n", + " [5.28999484e+02, 4.79801484e+01],\n", + " [1.44654291e+03, 9.06680768e+01],\n", + " [4.99428771e+03, 3.11892868e+02],\n", + " [1.01035804e+04, 5.48460859e+02],\n", + " [2.61947362e+04, 1.40265491e+03],\n", + " [3.83891964e+04, 2.23685907e+03],\n", + " [1.44615604e+05, 4.71073992e+03],\n", + " [2.04841144e+05, 1.28298259e+04],\n", + " [3.04860240e+05, 2.65146845e+04],\n", + " [7.15472624e+05, 6.60639061e+04],\n", + " [5.70803649e+05, 7.57376290e+04],\n", + " [9.47231329e+05, 1.54986248e+05],\n", + " [9.23953166e+05, 1.93822492e+05],\n", + " [6.57801248e+05, 1.50769939e+05],\n", + " [8.43171264e+05, 2.49113150e+05],\n", + " [5.59341253e+05, 1.85957381e+05],\n", + " [6.96237265e+05, 4.03687883e+05],\n", + " [5.40067509e+05, 2.66418801e+05],\n", + " [4.57478544e+05, 3.88221974e+05],\n", + " [4.25920143e+05, 3.91122618e+05],\n", + " [3.96908285e+05, 3.71414788e+05],\n", + " [6.02102705e+05, 4.23352098e+05],\n", + " [6.41769739e+05, 5.18903098e+05],\n", + " [4.16901641e+05, 4.04368759e+05],\n", + " [3.30039331e+05, 3.78696731e+05],\n", + " [5.51529415e+05, 6.43412007e+05],\n", + " [5.49787782e+05, 5.35688557e+05],\n", + " [2.80979529e+05, 7.42016812e+05],\n", + " [4.66284359e+05, 6.14750052e+05],\n", + " [3.12148206e+05, 5.29680965e+05],\n", + " [3.50953671e+05, 8.72215875e+05],\n", + " [4.01568191e+05, 8.08517365e+05],\n", + " [2.95505559e+05, 6.81129851e+05],\n", + " [3.16315375e+05, 6.59415810e+05],\n", + " [1.95777449e+05, 6.79437421e+05],\n", + " [1.94280033e+05, 7.21315446e+05],\n", + " [1.78501110e+05, 6.75465168e+05],\n", + " [2.47404532e+05, 9.85931509e+05],\n", + " [2.99943485e+05, 7.64644995e+05],\n", + " [1.48078919e+05, 8.98769907e+05],\n", + " [2.03910050e+05, 7.10664811e+05],\n", + " [1.98269087e+05, 5.50194199e+05],\n", + " [2.41973630e+05, 8.36300844e+05],\n", + " [1.94887109e+05, 9.06544564e+05],\n", + " [1.46665030e+05, 9.13739364e+05],\n", + " [1.43779842e+05, 8.80070344e+05],\n", + " [1.04096536e+05, 7.21086105e+05],\n", + " [1.87776956e+05, 8.93932501e+05],\n", + " [9.41454910e+04, 8.32234831e+05],\n", + " [1.47360515e+05, 9.75970111e+05],\n", + " [1.07959767e+05, 9.19504617e+05],\n", + " [1.31352538e+05, 8.43986082e+05],\n", + " [1.38134142e+05, 9.44445525e+05],\n", + " [1.43810730e+05, 8.74698002e+05],\n", + " [1.02488333e+05, 8.25331196e+05],\n", + " [9.36752361e+04, 1.06579735e+06],\n", + " [9.28858373e+04, 1.15535109e+06],\n", + " [6.63758943e+04, 9.88499224e+05],\n", + " [1.06010101e+05, 8.10618603e+05],\n", + " [1.04769047e+05, 6.39799600e+05],\n", + " [6.43799763e+04, 1.00443399e+06],\n", + " [8.83107785e+04, 7.51578437e+05],\n", + " [8.32902438e+04, 1.14248035e+06],\n", + " [8.23704800e+04, 7.70222834e+05],\n", + " [6.36377665e+04, 8.10851809e+05],\n", + " [6.67889123e+04, 6.98840815e+05],\n", + " [7.51023290e+04, 1.03500279e+06],\n", + " [6.26382732e+04, 6.83328316e+05],\n", + " [4.18704321e+04, 7.29742044e+05],\n", + " [6.09073205e+04, 1.17917865e+06],\n", + " [3.41835753e+04, 9.20899230e+05],\n", + " [5.16557040e+04, 8.42315342e+05],\n", + " [3.53315137e+04, 8.86502740e+05],\n", + " [4.78839456e+04, 6.93420051e+05],\n", + " [3.35578712e+04, 1.15007416e+06],\n", + " [3.04994928e+04, 8.32594383e+05],\n", + " [4.27334325e+04, 7.91261007e+05],\n", + " [4.20789053e+04, 1.19249901e+06],\n", + " [3.95371249e+04, 8.20574024e+05],\n", + " [2.57666812e+04, 7.49084192e+05],\n", + " [3.74313007e+04, 1.14683974e+06],\n", + " [1.97293773e+04, 6.88071653e+05],\n", + " [1.71243567e+04, 1.29096233e+06],\n", + " [1.96154357e+04, 9.39060095e+05],\n", + " [2.47941056e+04, 1.11267717e+06],\n", + " [2.19008895e+04, 8.58416469e+05],\n", + " [1.93730659e+04, 1.15087675e+06],\n", + " [2.41184982e+04, 8.52800084e+05],\n", + " [2.12075306e+04, 7.72057664e+05],\n", + " [2.22673055e+04, 7.14074890e+05],\n", + " [1.24970257e+04, 7.12008791e+05],\n", + " [1.50653450e+04, 8.43052938e+05],\n", + " [2.01996861e+04, 8.82232568e+05],\n", + " [1.23914648e+04, 7.18155510e+05],\n", + " [9.93713520e+03, 1.22778864e+06],\n", + " [1.54926063e+04, 1.13305907e+06],\n", + " [1.46517627e+04, 8.82614181e+05],\n", + " [1.51895234e+04, 1.07507367e+06],\n", + " [1.37184550e+04, 8.54583269e+05],\n", + " [1.32425652e+04, 8.52689748e+05],\n", + " [1.22831633e+04, 1.05438468e+06],\n", + " [1.07154617e+04, 9.87530754e+05],\n", + " [9.79983700e+03, 1.18866243e+06],\n", + " [6.81730901e+03, 8.47516493e+05],\n", + " [9.15651565e+03, 1.02983470e+06],\n", + " [5.64752625e+03, 7.00227501e+05],\n", + " [6.85158508e+03, 9.95376740e+05],\n", + " [8.53777034e+03, 9.91275075e+05],\n", + " [5.58841086e+03, 1.09653142e+06],\n", + " [7.83287441e+03, 6.81290232e+05],\n", + " [5.38570917e+03, 1.28890423e+06],\n", + " [5.60720078e+03, 6.79212987e+05],\n", + " [7.13198062e+03, 1.23332725e+06],\n", + " [6.14306233e+03, 1.29458063e+06],\n", + " [4.11652692e+03, 9.02602625e+05],\n", + " [5.55549183e+03, 7.88062650e+05],\n", + " [5.94590131e+03, 1.23692169e+06],\n", + " [4.30783767e+03, 1.21130813e+06],\n", + " [3.05726711e+03, 1.14476697e+06],\n", + " [3.41295207e+03, 9.54158128e+05],\n", + " [4.85711821e+03, 1.28795897e+06],\n", + " [2.80279142e+03, 8.57680691e+05],\n", + " [3.38791460e+03, 8.63233644e+05],\n", + " [3.69167961e+03, 1.03127702e+06],\n", + " [3.88993254e+03, 1.17845340e+06],\n", + " [3.17562723e+03, 8.97242264e+05],\n", + " [3.32180160e+03, 1.11150609e+06],\n", + " [2.48474397e+03, 1.25739583e+06],\n", + " [2.60417556e+03, 7.18592169e+05],\n", + " [2.95376202e+03, 1.29956821e+06],\n", + " [2.67499903e+03, 1.02182178e+06],\n", + " [1.93684024e+03, 7.09331309e+05],\n", + " [2.43032785e+03, 1.01886507e+06],\n", + " [1.86043618e+03, 1.21670386e+06],\n", + " [1.72323155e+03, 8.56007932e+05],\n", + " [1.95362634e+03, 1.31281086e+06],\n", + " [1.85854073e+03, 6.77777078e+05],\n", + " [1.12184168e+03, 1.05318530e+06],\n", + " [1.42917993e+03, 9.42788835e+05],\n", + " [1.30552104e+03, 8.57145128e+05],\n", + " [1.55865489e+03, 1.09684931e+06],\n", + " [1.16529772e+03, 9.75845741e+05],\n", + " [1.28117604e+03, 9.95327460e+05],\n", + " [9.03127133e+02, 9.36759864e+05],\n", + " [8.30025571e+02, 1.26405888e+06],\n", + " [1.44717583e+03, 8.26241716e+05],\n", + " [7.82908962e+02, 9.49718646e+05],\n", + " [1.30953881e+03, 8.05544645e+05],\n", + " [1.02008145e+03, 1.18601097e+06],\n", + " [7.67225606e+02, 7.30153946e+05],\n", + " [9.40543417e+02, 7.31312893e+05],\n", + " [1.06843120e+03, 1.14831000e+06],\n", + " [7.59482468e+02, 9.27258372e+05],\n", + " [7.32451666e+02, 1.32993513e+06],\n", + " [7.06399734e+02, 1.18456086e+06],\n", + " [7.67043499e+02, 7.98379241e+05],\n", + " [5.30292644e+02, 1.32030148e+06],\n", + " [5.27270391e+02, 1.11303165e+06],\n", + " [4.30556895e+02, 7.37433928e+05],\n", + " [6.92192735e+02, 6.73595928e+05],\n", + " [3.84239599e+02, 8.98704896e+05],\n", + " [4.05602919e+02, 7.68494127e+05],\n", + " [5.32379794e+02, 8.40066501e+05],\n", + " [5.54318875e+02, 1.16164974e+06],\n", + " [4.63878241e+02, 1.07374135e+06],\n", + " [3.08029258e+02, 6.73847356e+05],\n", + " [4.62024710e+02, 1.24764828e+06],\n", + " [4.03358695e+02, 1.16097583e+06],\n", + " [2.67202064e+02, 1.25038378e+06],\n", + " [3.63863050e+02, 7.18443773e+05],\n", + " [2.79615932e+02, 1.28780121e+06],\n", + " [3.60109790e+02, 8.39169235e+05],\n", + " [2.49320339e+02, 9.75423630e+05],\n", + " [3.48833566e+02, 1.32280122e+06],\n", + " [3.28403876e+02, 1.22196622e+06],\n", + " [2.21121004e+02, 1.32480298e+06],\n", + " [1.65069144e+02, 9.51352605e+05],\n", + " [2.61431490e+02, 1.09906347e+06],\n", + " [2.47834507e+02, 8.40256177e+05],\n", + " [2.32494283e+02, 1.04313372e+06],\n", + " [1.34238266e+02, 8.95668938e+05],\n", + " [1.53206781e+02, 9.70433336e+05],\n", + " [1.63387233e+02, 8.71489570e+05],\n", + " [2.16672546e+02, 1.22080878e+06],\n", + " [1.44421258e+02, 1.22576208e+06],\n", + " [1.92426070e+02, 7.40647282e+05],\n", + " [9.61128200e+01, 9.04821540e+05],\n", + " [1.66416779e+02, 9.75432108e+05],\n", + " [1.18125629e+02, 1.22564992e+06],\n", + " [1.35815896e+02, 1.26021637e+06],\n", + " [1.16890245e+02, 1.19561705e+06],\n", + " [9.77113189e+01, 8.33097662e+05],\n", + " [8.68018133e+01, 1.09653539e+06],\n", + " [9.42206676e+01, 8.50974231e+05],\n", + " [9.35370396e+01, 1.28633958e+06],\n", + " [1.17266143e+02, 1.09093515e+06],\n", + " [6.53374982e+01, 7.00052732e+05]])" ] }, "execution_count": 10, @@ -656,7 +656,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Fitting Normal loss" + "## Fitting Square l loss" ] }, { @@ -691,7 +691,7 @@ "theta = [3, 0.15,1e6]\n", "boxBounds = [(2,5),(0.0,1.0),(1e6,1e6)]\n", "\n", - "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + "objSIR = SquareLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" ] }, { @@ -702,7 +702,7 @@ { "data": { "text/plain": [ - "NormalLoss([3.0, 0.15, 1000000.0], SimulateOde([ODEVariable('S', 'S', None, True), ODEVariable('I', 'I', None, True), ODEVariable('R', 'R', None, True)], [ODEVariable('beta', 'beta', None, True), ODEVariable('gamma', 'gamma', None, True), ODEVariable('N', 'N', None, True)], [], [Transition('S', 'beta*S*I/N', 'T', 'I', None, None), Transition('I', 'gamma*I', 'T', 'R', None, None)], [], []).setParameters({'beta': 3.6, 'gamma': 0.2, 'N': 1000000.0}), [999998.0, 2.0, 0.0], 0.0, [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75, 12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75, 14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75, 16.0, 16.25, 16.5, 16.75, 17.0, 17.25, 17.5, 17.75, 18.0, 18.25, 18.5, 18.75, 19.0, 19.25, 19.5, 19.75, 20.0, 20.25, 20.5, 20.75, 21.0, 21.25, 21.5, 21.75, 22.0, 22.25, 22.5, 22.75, 23.0, 23.25, 23.5, 23.75, 24.0, 24.25, 24.5, 24.75, 25.0, 25.25, 25.5, 25.75, 26.0, 26.25, 26.5, 26.75, 27.0, 27.25, 27.5, 27.75, 28.0, 28.25, 28.5, 28.75, 29.0, 29.25, 29.5, 29.75, 30.0, 30.25, 30.5, 30.75, 31.0, 31.25, 31.5, 31.75, 32.0, 32.25, 32.5, 32.75, 33.0, 33.25, 33.5, 33.75, 34.0, 34.25, 34.5, 34.75, 35.0, 35.25, 35.5, 35.75, 36.0, 36.25, 36.5, 36.75, 37.0, 37.25, 37.5, 37.75, 38.0, 38.25, 38.5, 38.75, 39.0, 39.25, 39.5, 39.75, 40.0, 40.25, 40.5, 40.75, 41.0, 41.25, 41.5, 41.75, 42.0, 42.25, 42.5, 42.75, 43.0, 43.25, 43.5, 43.75, 44.0, 44.25, 44.5, 44.75, 45.0, 45.25, 45.5, 45.75, 46.0, 46.25, 46.5, 46.75, 47.0, 47.25, 47.5, 47.75, 48.0, 48.25, 48.5, 48.75, 49.0, 49.25, 49.5, 49.75, 50.0, 50.25, 50.5, 50.75], [[5.5489971387876365, 0.13976157088347727], [9.415096478582125, 0.6953800925736477], [25.941588724404888, 1.7360216096973626], [40.629454348405005, 3.6320719863452124], [108.33986724048995, 9.898076194201028], [265.94200822963205, 19.72199081288608], [814.0101919108965, 34.39273873132337], [1610.3645021087707, 84.46157450404837], [4033.7294190704292, 287.6005446141324], [8244.051192760833, 695.5700455200907], [29441.296547302398, 1278.206554206765], [36326.23747211643, 3083.1448823639666], [134300.6643766737, 7316.380551470222], [251120.96130046487, 12228.281008380864], [512397.4021229717, 21543.277252460124], [585616.8734093554, 38484.76952026679], [790205.921992304, 83692.67093281484], [974797.1285860298, 137447.11265771437], [707757.0823571573, 117346.97836716496], [603556.1371978847, 189433.07773085634], [913909.6207876124, 199048.48425080228], [548929.798690948, 279399.6024361307], [462040.51907899725, 383327.3895777905], [761326.3551628065, 258855.59336332348], [662287.4219836415, 340426.42697219475], [508464.53921417124, 391021.45531562675], [656745.3025785786, 578473.9477197772], [554162.9505283561, 426765.22955069266], [532220.7074438117, 508730.0308778309], [445615.9890674269, 476315.5274757456], [590230.8684803826, 648108.582432509], [544910.361061262, 672870.3344572515], [310827.4253700613, 587435.0165097215], [456115.65962565545, 710530.4983865325], [364253.7844819528, 579474.3308432746], [311474.8016733622, 821438.8027931447], [252718.85987592736, 478270.7054820163], [307809.39052484394, 683324.6855005894], [281269.7866456109, 834432.1640758143], [261336.99881665388, 750610.2799376069], [352273.3896491518, 689933.9153611241], [337278.8801262164, 668473.671079696], [262817.02738757816, 896729.9572193093], [274990.26820054883, 617678.724452312], [252897.72396917018, 865475.7000908976], [209867.3728636754, 950457.6023080612], [161791.28013060236, 1051352.395139691], [176888.54085288633, 998681.753684348], [158703.64323235105, 1052018.6625758626], [235953.74632457114, 581511.5462198751], [139508.3819811454, 1104611.4054220302], [127265.67567357987, 900559.5183912851], [146297.08454396683, 802469.639043949], [153697.59202897752, 1124694.0709555596], [165201.2568608659, 652874.3435597733], [160048.49667175754, 698299.422082141], [94596.797920066, 794188.5335791365], [117291.50891981134, 1170125.0942029145], [88205.35480368958, 1027701.8237791387], [79699.47446828452, 887920.1922399637], [122990.00315676956, 823010.8990972892], [90298.37858239123, 856602.5660494367], [112583.27458976842, 823690.0110776974], [115479.24360879252, 924618.4818930109], [77532.65451860701, 904591.1155288297], [78082.17487409341, 715856.1296537648], [99665.75506373866, 672890.1996274921], [87968.24120244425, 1005140.6416744539], [56753.577717708846, 926563.1004164796], [50867.71484676358, 710220.5323161592], [42445.65692219467, 706325.639191282], [46554.845983121624, 974134.4267906626], [52918.424828372394, 672152.061469812], [61553.98169533466, 1154689.9304881357], [41355.7068612865, 1114491.7048004952], [46374.73519731653, 870190.3739141857], [37244.34436743515, 1191669.9818033653], [41282.28851948546, 1046085.4493043608], [55317.91156340166, 1128079.994274354], [31907.69520572426, 1000208.0395347421], [34010.24198302409, 930221.1892817259], [30928.214034681547, 1018299.4007833744], [39523.39574481744, 1096728.5680754953], [43101.60123589903, 923362.8464453346], [24453.276252403833, 810610.3090453236], [24290.566238056355, 1168379.2311720226], [30849.52429767078, 672357.9273898688], [22930.91291882195, 683181.2065549527], [19312.410078810557, 1181575.0638825279], [24800.522354204797, 694595.4933711233], [30232.955889418034, 1144610.0789169455], [20439.868327523087, 916831.495611514], [26002.801545608865, 689740.713613447], [20449.735359676568, 1277607.1379225366], [23244.54282457448, 958179.1751528395], [16447.345530964347, 1225836.3266972792], [20051.445282210465, 669149.8800772146], [16664.454488900752, 925503.6673304131], [16681.49384056153, 743239.5841723487], [18683.299901770028, 1092030.4094499706], [17996.321050203427, 804265.8193114839], [17412.129570447687, 703980.773650898], [12698.868359882912, 1121870.8122240496], [15814.023105568453, 1027570.9081003398], [12734.071882360873, 858592.8580763217], [13582.657478279318, 764916.0217322799], [10126.381580399675, 750180.7159839582], [7193.420744583109, 1271423.1734558782], [10249.386414900197, 1133442.0264943778], [10397.892095036967, 1077065.7446887211], [10291.424793271395, 1127211.5938218776], [6609.807342544796, 672248.4104117213], [6598.495277349121, 888855.8050265535], [7689.704772788273, 739423.7561920357], [8845.842419921624, 1006775.9005513749], [8257.28104877651, 1192110.8618185048], [5881.906750996887, 1115149.93372143], [5420.930573114638, 716639.884819933], [6824.730262831377, 1124534.8621694546], [3683.207213311698, 1098986.08982435], [6804.52269756303, 1096526.7921533366], [5971.686041066522, 1094255.1464621811], [5272.7715814587045, 922447.4408174288], [4327.475161388193, 686566.7266654972], [3383.2610693392044, 1035475.2013402083], [3069.919189380042, 1166199.6484807285], [4128.870181022159, 1036637.8860012486], [4276.722417774954, 1265374.8212365832], [3188.0648383580597, 1161352.5607335398], [2800.118318839102, 975156.9553313118], [3620.4185579812274, 789736.0719286054], [3842.2741401842172, 1188642.3134196696], [3067.551247602438, 894816.5312599519], [2134.67276566011, 1167306.4045076708], [2276.263966733917, 1245915.7013382448], [2348.395010917235, 1120308.7855315015], [2249.0021255896513, 732039.3261821142], [1851.1240962192128, 1253930.6660519678], [2651.715415269909, 740465.2182037155], [2441.6365408681636, 1072739.1471042798], [2417.891347145136, 1066500.7995323706], [2120.9245483558825, 1072552.8316071504], [2017.2460815827417, 1184127.366115931], [1424.845670574932, 998442.1280909418], [2001.7184429807262, 1167627.3635968873], [1189.0647524983192, 763242.127352661], [964.1515731483933, 1062757.4849910974], [947.6914614570239, 952712.7846825029], [1087.3749471536023, 1326560.2010915559], [1582.1197247476741, 1285545.3759947247], [1024.6265416882222, 1216454.4422335515], [1096.9695443363794, 837588.3467235877], [1184.8500540757373, 1328683.061242117], [960.6494707281487, 958801.8911654096], [835.7501337173844, 670070.5483600695], [846.9337487099981, 909028.5240620613], [875.541052335431, 693582.5251296596], [998.4570286925696, 1300877.9383268403], [838.0771236697374, 859040.0555225008], [849.0959325990879, 748748.1751257956], [475.2782089274715, 729532.8627678553], [475.2219202114857, 1134978.277195852], [594.9537349672182, 1176976.9695724065], [608.6856630484652, 1319343.8667681955], [571.5888971056904, 1087811.2469301717], [537.6562029971528, 883840.8893521308], [653.3593380671064, 1126643.762739988], [379.7532039608197, 716919.052976874], [479.46053353989157, 767956.5237406924], [376.4557987859823, 779635.8208878567], [398.67838714418235, 1178128.6982785354], [492.4408336280881, 679938.8977216084], [317.3908756903431, 1288119.208934416], [284.13669569600165, 1084258.2171145338], [253.47378339180153, 669868.4988409674], [299.26400701038574, 1143576.4805791376], [388.12334228010513, 848988.5515813607], [256.2982253008446, 968709.2961185345], [226.86527870402017, 827831.7795352405], [229.48897424342212, 732466.208474486], [317.12047386383495, 1189859.6336752367], [204.38988338787306, 875497.7197789245], [269.4415199990759, 1018707.6504033973], [257.97438516355055, 1315244.2862689584], [191.00767526447387, 1123759.8491195813], [194.52797753681182, 1043333.9442222763], [207.29291902341845, 1252729.0376916449], [209.81691238951242, 666651.9180659578], [216.6269232166793, 776940.6467737745], [182.17936999016678, 1204558.48883258], [167.41968911549503, 925148.5235907574], [166.59322132383082, 850966.3818700697], [125.71520857960297, 1247044.057304752], [106.82366473307945, 688489.016953341], [119.69495136675988, 1067715.157561069], [90.69890996414178, 774962.7461366334], [95.27225242575679, 900826.9111966246], [133.28054285317748, 997025.5515197581], [122.05077509682275, 825449.5240761695], [113.43861907585058, 1327482.8035176208], [79.58881177281683, 996202.6939394812], [74.62085718615808, 708911.8992225014], [107.04923637866446, 862428.9150962183]], ['I', 'R'], [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])" + "SquareLoss([3.0, 0.15, 1000000.0], SimulateOde([ODEVariable('S', 'S', None, True), ODEVariable('I', 'I', None, True), ODEVariable('R', 'R', None, True)], [ODEVariable('beta', 'beta', None, True), ODEVariable('gamma', 'gamma', None, True), ODEVariable('N', 'N', None, True)], [], [Transition('S', 'beta*S*I/N', 'T', 'I', None, None), Transition('I', 'gamma*I', 'T', 'R', None, None)], [], []).setParameters({'beta': 3.6, 'gamma': 0.2, 'N': 1000000.0}), [999998.0, 2.0, 0.0], 0.0, [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75, 12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75, 14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75, 16.0, 16.25, 16.5, 16.75, 17.0, 17.25, 17.5, 17.75, 18.0, 18.25, 18.5, 18.75, 19.0, 19.25, 19.5, 19.75, 20.0, 20.25, 20.5, 20.75, 21.0, 21.25, 21.5, 21.75, 22.0, 22.25, 22.5, 22.75, 23.0, 23.25, 23.5, 23.75, 24.0, 24.25, 24.5, 24.75, 25.0, 25.25, 25.5, 25.75, 26.0, 26.25, 26.5, 26.75, 27.0, 27.25, 27.5, 27.75, 28.0, 28.25, 28.5, 28.75, 29.0, 29.25, 29.5, 29.75, 30.0, 30.25, 30.5, 30.75, 31.0, 31.25, 31.5, 31.75, 32.0, 32.25, 32.5, 32.75, 33.0, 33.25, 33.5, 33.75, 34.0, 34.25, 34.5, 34.75, 35.0, 35.25, 35.5, 35.75, 36.0, 36.25, 36.5, 36.75, 37.0, 37.25, 37.5, 37.75, 38.0, 38.25, 38.5, 38.75, 39.0, 39.25, 39.5, 39.75, 40.0, 40.25, 40.5, 40.75, 41.0, 41.25, 41.5, 41.75, 42.0, 42.25, 42.5, 42.75, 43.0, 43.25, 43.5, 43.75, 44.0, 44.25, 44.5, 44.75, 45.0, 45.25, 45.5, 45.75, 46.0, 46.25, 46.5, 46.75, 47.0, 47.25, 47.5, 47.75, 48.0, 48.25, 48.5, 48.75, 49.0, 49.25, 49.5, 49.75, 50.0, 50.25, 50.5, 50.75], [[4.130487025131687, 0.15404561775936773], [9.397247964980085, 0.46303278732171177], [22.633824079261842, 1.7992007113807156], [47.986586672487206, 2.7579529325485836], [165.196041952231, 9.600546411428384], [409.7793329814416, 18.59941777036534], [528.9994837079726, 47.98014835106094], [1446.5429145036974, 90.66807675329977], [4994.287706241389, 311.89286846212264], [10103.580369113544, 548.4608589124192], [26194.736213578377, 1402.654912118046], [38389.19639311862, 2236.8590689690504], [144615.6038613682, 4710.739919896741], [204841.14352293048, 12829.825865082867], [304860.2404249535, 26514.684493267272], [715472.6235634295, 66063.90607297285], [570803.6488074489, 75737.62898047472], [947231.3292945497, 154986.247976831], [923953.16649091, 193822.49178823238], [657801.2480252209, 150769.93914359063], [843171.2637992136, 249113.1495604983], [559341.2527328188, 185957.3813357946], [696237.264525381, 403687.88293160085], [540067.5094137926, 266418.8007305509], [457478.5443022633, 388221.974041893], [425920.1427231567, 391122.61823234084], [396908.2854576274, 371414.7879418473], [602102.7053746057, 423352.09770557744], [641769.7394061629, 518903.09780880454], [416901.64080071973, 404368.7588933208], [330039.3314030553, 378696.7305775569], [551529.4145009269, 643412.0070484518], [549787.7820911882, 535688.556709061], [280979.5285986585, 742016.811538869], [466284.35882357555, 614750.051516308], [312148.2058862273, 529680.9650844566], [350953.6705610238, 872215.874672448], [401568.19082765863, 808517.3646270183], [295505.55911352474, 681129.850659894], [316315.37513281166, 659415.8097179801], [195777.4490952229, 679437.4206703037], [194280.03265693723, 721315.4457581254], [178501.10961662387, 675465.1683738899], [247404.53170668957, 985931.5093514766], [299943.4851962682, 764644.9954514606], [148078.91870689174, 898769.9073671738], [203910.04957668108, 710664.8108294513], [198269.08657707038, 550194.198541208], [241973.63044169324, 836300.8441740677], [194887.10906344195, 906544.5642488404], [146665.03014024382, 913739.3641712739], [143779.84227086403, 880070.3435878769], [104096.5358741194, 721086.1047601945], [187776.95624604076, 893932.5009312815], [94145.49095393051, 832234.8307984242], [147360.51529741898, 975970.1109512364], [107959.76674711499, 919504.6172384012], [131352.53801677615, 843986.0818510734], [138134.14244997536, 944445.5248128581], [143810.73000588483, 874698.002250221], [102488.3325125742, 825331.1957907011], [93675.23614669341, 1065797.3512993983], [92885.83732391837, 1155351.0857456843], [66375.89434895372, 988499.2242781295], [106010.1011427728, 810618.6033656059], [104769.0474474182, 639799.6000771984], [64379.976276675065, 1004433.9910370467], [88310.77848764382, 751578.4374513394], [83290.24377534064, 1142480.3506778087], [82370.47996389655, 770222.8341590352], [63637.766473583026, 810851.8091807761], [66788.91229470367, 698840.8146168891], [75102.3290490617, 1035002.7902780143], [62638.27317992859, 683328.3156147334], [41870.43206330126, 729742.0444708264], [60907.32053788277, 1179178.6549844078], [34183.575255148746, 920899.2296020638], [51655.704042085505, 842315.3424291152], [35331.51366160177, 886502.7398532623], [47883.945613707736, 693420.0510623266], [33557.87124412175, 1150074.1571437381], [30499.492761509304, 832594.3834703927], [42733.43248401154, 791261.006569009], [42078.9053350363, 1192499.0062521168], [39537.12490267918, 820574.0244793433], [25766.68117003718, 749084.1915958913], [37431.3006839491, 1146839.7385431828], [19729.377253022878, 688071.6526254383], [17124.35674302549, 1290962.3295776465], [19615.43572022034, 939060.0950318159], [24794.10562003187, 1112677.165293667], [21900.889529328662, 858416.4692184512], [19373.06594088114, 1150876.7459370985], [24118.498247359745, 852800.0837341312], [21207.530605877277, 772057.6638792764], [22267.30551041926, 714074.8898722631], [12497.025723179937, 712008.7912734993], [15065.344990296639, 843052.9384454926], [20199.686086950154, 882232.5677295076], [12391.464759044167, 718155.5097697747], [9937.135196575824, 1227788.641219967], [15492.606340046807, 1133059.0676593857], [14651.76273816029, 882614.1807004922], [15189.523429391971, 1075073.6739545558], [13718.455011597003, 854583.2693140692], [13242.565179358064, 852689.7481448406], [12283.16329964135, 1054384.679136664], [10715.461680060893, 987530.7540134372], [9799.836999306235, 1188662.432761487], [6817.309005236672, 847516.4934806598], [9156.515653966426, 1029834.6994578489], [5647.526250134233, 700227.501149568], [6851.585075787405, 995376.7395363126], [8537.770338276303, 991275.0750426087], [5588.410860946238, 1096531.4230958493], [7832.874408306464, 681290.2321555684], [5385.709166136957, 1288904.2276863966], [5607.200777069934, 679212.9865083437], [7131.98062301099, 1233327.2530472076], [6143.062328777299, 1294580.6293236036], [4116.526919112113, 902602.6246132584], [5555.49183273859, 788062.6499769951], [5945.901312119126, 1236921.6936202012], [4307.837673987712, 1211308.1303755068], [3057.267111272262, 1144766.9718521282], [3412.952069021781, 954158.1280045257], [4857.118212156462, 1287958.9746543085], [2802.7914200776886, 857680.691013031], [3387.914599774963, 863233.6440396649], [3691.679610334573, 1031277.0232285978], [3889.932537061482, 1178453.4027236914], [3175.6272264942872, 897242.264150536], [3321.8016013704805, 1111506.090775924], [2484.743968904745, 1257395.831926505], [2604.1755637616475, 718592.1692915799], [2953.762015063723, 1299568.2114593633], [2674.99903287432, 1021821.7828949532], [1936.840241672874, 709331.3091161926], [2430.32784824078, 1018865.0657590512], [1860.436184602949, 1216703.8610504132], [1723.2315526850525, 856007.9319208895], [1953.6263447660579, 1312810.8625858119], [1858.5407262503563, 677777.0784941971], [1121.841683026275, 1053185.2996789496], [1429.1799261633125, 942788.834721557], [1305.5210429480653, 857145.1282976748], [1558.6548858562132, 1096849.3108424598], [1165.2977247587564, 975845.740861295], [1281.1760431911907, 995327.4595873987], [903.127132888626, 936759.8641734732], [830.0255705095318, 1264058.880523917], [1447.175826672647, 826241.7163334353], [782.9089616625392, 949718.6455322991], [1309.5388116616314, 805544.6451139126], [1020.0814509483284, 1186010.9653905143], [767.2256057638687, 730153.9456574344], [940.5434165348748, 731312.8929979993], [1068.431197781994, 1148310.00282886], [759.4824678568447, 927258.3721201726], [732.4516659883362, 1329935.1271868325], [706.3997339170826, 1184560.8555669347], [767.0434989984218, 798379.2411034874], [530.2926441714136, 1320301.478595184], [527.2703906339111, 1113031.6474556928], [430.5568953988018, 737433.9280313611], [692.1927353827714, 673595.9280200478], [384.23959921185053, 898704.8958790172], [405.6029193272436, 768494.1267053746], [532.3797944208193, 840066.5011984787], [554.3188745851079, 1161649.7413965538], [463.87824061723234, 1073741.3455026292], [308.0292581421485, 673847.3559565375], [462.02471007201643, 1247648.281420697], [403.35869455867373, 1160975.832082224], [267.2020640147793, 1250383.7841186798], [363.8630500648634, 718443.7734347496], [279.6159322070644, 1287801.210123048], [360.1097904304585, 839169.2354281674], [249.32033940693356, 975423.6296495761], [348.83356604943486, 1322801.2214118955], [328.40387580328803, 1221966.218413916], [221.1210037522975, 1324802.975776162], [165.06914366017043, 951352.6052332598], [261.4314897243031, 1099063.4721241775], [247.83450742057468, 840256.1768109152], [232.49428280316337, 1043133.7234717476], [134.23826614735785, 895668.9384443999], [153.20678095501415, 970433.3364156254], [163.3872329739676, 871489.5702094157], [216.6725459496833, 1220808.7783561496], [144.4212576438835, 1225762.0801782524], [192.42606995989752, 740647.2823234415], [96.11282000434359, 904821.5403045765], [166.41677897191434, 975432.1078972422], [118.12562865687576, 1225649.9201249767], [135.81589553462987, 1260216.3663823903], [116.89024486149172, 1195617.0482448642], [97.71131894635056, 833097.6624037084], [86.8018133066483, 1096535.386700453], [94.22066759538556, 850974.2314776242], [93.53703959337743, 1286339.5796547756], [117.26614306573515, 1090935.1549952293], [65.33749823040989, 700052.7320163958]], ['I', 'R'], [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])" ] }, "execution_count": 13, @@ -722,7 +722,7 @@ { "data": { "text/plain": [ - "4909533605860.806" + "9032988605419.916" ] }, "execution_count": 14, @@ -751,18 +751,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 3257054048571.9863\n", - " hess_inv: array([[ 5.18410500e-11, -2.54658445e-12, 1.27206329e-05],\n", - " [-2.54658442e-12, 1.49261473e-13, -6.12083782e-07],\n", - " [ 1.27206329e-05, -6.12083790e-07, 3.12906462e+00]])\n", - " jac: array([-1.10600741e+00, -4.43260288e+00, 4.08760083e-06])\n", + " fun: 6195089026101.063\n", + " hess_inv: array([[ 8.74144835e-12, -2.58712672e-14, 2.68445022e-06],\n", + " [-2.58712712e-14, 2.36956010e-15, -5.05342211e-09],\n", + " [ 2.68444976e-06, -5.05342099e-09, 8.41021723e-01]])\n", + " jac: array([ 4.61669282e+00, -8.58643370e+01, -1.67724298e-05])\n", " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 43\n", - " nit: 12\n", - " njev: 38\n", + " nfev: 57\n", + " nit: 11\n", + " njev: 46\n", " status: 2\n", " success: False\n", - " x: array([5.52375636e+00, 2.03086137e-01, 1.49373372e+06])\n" + " x: array([4.97711288e+00, 1.97932062e-01, 1.36982257e+06])\n" ] } ], @@ -785,16 +785,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 3257054048571.9043\n", + " fun: 6195089026101.077\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([-8.79695180e+01, -1.47147132e+03, 3.25305614e-04])\n", + " jac: array([ 7.75580656e+04, 3.96915387e+06, -2.81799456e-01])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 14\n", - " nit: 9\n", - " njev: 14\n", + " nfev: 16\n", + " nit: 10\n", + " njev: 16\n", " status: 0\n", " success: True\n", - " x: array([3.69795251e+00, 2.03086137e-01, 1.00000000e+06])\n" + " x: array([3.63339968e+00, 1.97932071e-01, 1.00000000e+06])\n" ] } ], @@ -849,53 +849,76 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Fitting Gamma loss" + "## Fitting Normal loss" ] }, { "cell_type": "code", "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "param_evals" + ] + }, + { + "cell_type": "code", + "execution_count": 19, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Initial guess of parameters, and bounding constraints\n", - "objSIR = GammaLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + "theta = [3, 0.15,1e6]\n", + "boxBounds = [(2,5),(0.0,1.0),(1e6,1e6)]\n", + "\n", + "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([-5.77968064e+02, -6.98915605e+03, 1.73390419e-03])" + "NormalLoss([3.0, 0.15, 1000000.0], SimulateOde([ODEVariable('S', 'S', None, True), ODEVariable('I', 'I', None, True), ODEVariable('R', 'R', None, True)], [ODEVariable('beta', 'beta', None, True), ODEVariable('gamma', 'gamma', None, True), ODEVariable('N', 'N', None, True)], [], [Transition('S', 'beta*S*I/N', 'T', 'I', None, None), Transition('I', 'gamma*I', 'T', 'R', None, None)], [], []).setParameters({'beta': 3.6333996818761123, 'gamma': 0.19793207076619318, 'N': 1000000.0}), [999998.0, 2.0, 0.0], 0.0, [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75, 12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75, 14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75, 16.0, 16.25, 16.5, 16.75, 17.0, 17.25, 17.5, 17.75, 18.0, 18.25, 18.5, 18.75, 19.0, 19.25, 19.5, 19.75, 20.0, 20.25, 20.5, 20.75, 21.0, 21.25, 21.5, 21.75, 22.0, 22.25, 22.5, 22.75, 23.0, 23.25, 23.5, 23.75, 24.0, 24.25, 24.5, 24.75, 25.0, 25.25, 25.5, 25.75, 26.0, 26.25, 26.5, 26.75, 27.0, 27.25, 27.5, 27.75, 28.0, 28.25, 28.5, 28.75, 29.0, 29.25, 29.5, 29.75, 30.0, 30.25, 30.5, 30.75, 31.0, 31.25, 31.5, 31.75, 32.0, 32.25, 32.5, 32.75, 33.0, 33.25, 33.5, 33.75, 34.0, 34.25, 34.5, 34.75, 35.0, 35.25, 35.5, 35.75, 36.0, 36.25, 36.5, 36.75, 37.0, 37.25, 37.5, 37.75, 38.0, 38.25, 38.5, 38.75, 39.0, 39.25, 39.5, 39.75, 40.0, 40.25, 40.5, 40.75, 41.0, 41.25, 41.5, 41.75, 42.0, 42.25, 42.5, 42.75, 43.0, 43.25, 43.5, 43.75, 44.0, 44.25, 44.5, 44.75, 45.0, 45.25, 45.5, 45.75, 46.0, 46.25, 46.5, 46.75, 47.0, 47.25, 47.5, 47.75, 48.0, 48.25, 48.5, 48.75, 49.0, 49.25, 49.5, 49.75, 50.0, 50.25, 50.5, 50.75], [[4.130487025131687, 0.15404561775936773], [9.397247964980085, 0.46303278732171177], [22.633824079261842, 1.7992007113807156], [47.986586672487206, 2.7579529325485836], [165.196041952231, 9.600546411428384], [409.7793329814416, 18.59941777036534], [528.9994837079726, 47.98014835106094], [1446.5429145036974, 90.66807675329977], [4994.287706241389, 311.89286846212264], [10103.580369113544, 548.4608589124192], [26194.736213578377, 1402.654912118046], [38389.19639311862, 2236.8590689690504], [144615.6038613682, 4710.739919896741], [204841.14352293048, 12829.825865082867], [304860.2404249535, 26514.684493267272], [715472.6235634295, 66063.90607297285], [570803.6488074489, 75737.62898047472], [947231.3292945497, 154986.247976831], [923953.16649091, 193822.49178823238], [657801.2480252209, 150769.93914359063], [843171.2637992136, 249113.1495604983], [559341.2527328188, 185957.3813357946], [696237.264525381, 403687.88293160085], [540067.5094137926, 266418.8007305509], [457478.5443022633, 388221.974041893], [425920.1427231567, 391122.61823234084], [396908.2854576274, 371414.7879418473], [602102.7053746057, 423352.09770557744], [641769.7394061629, 518903.09780880454], [416901.64080071973, 404368.7588933208], [330039.3314030553, 378696.7305775569], [551529.4145009269, 643412.0070484518], [549787.7820911882, 535688.556709061], [280979.5285986585, 742016.811538869], [466284.35882357555, 614750.051516308], [312148.2058862273, 529680.9650844566], [350953.6705610238, 872215.874672448], [401568.19082765863, 808517.3646270183], [295505.55911352474, 681129.850659894], [316315.37513281166, 659415.8097179801], [195777.4490952229, 679437.4206703037], [194280.03265693723, 721315.4457581254], [178501.10961662387, 675465.1683738899], [247404.53170668957, 985931.5093514766], [299943.4851962682, 764644.9954514606], [148078.91870689174, 898769.9073671738], [203910.04957668108, 710664.8108294513], [198269.08657707038, 550194.198541208], [241973.63044169324, 836300.8441740677], [194887.10906344195, 906544.5642488404], [146665.03014024382, 913739.3641712739], [143779.84227086403, 880070.3435878769], [104096.5358741194, 721086.1047601945], [187776.95624604076, 893932.5009312815], [94145.49095393051, 832234.8307984242], [147360.51529741898, 975970.1109512364], [107959.76674711499, 919504.6172384012], [131352.53801677615, 843986.0818510734], [138134.14244997536, 944445.5248128581], [143810.73000588483, 874698.002250221], [102488.3325125742, 825331.1957907011], [93675.23614669341, 1065797.3512993983], [92885.83732391837, 1155351.0857456843], [66375.89434895372, 988499.2242781295], [106010.1011427728, 810618.6033656059], [104769.0474474182, 639799.6000771984], [64379.976276675065, 1004433.9910370467], [88310.77848764382, 751578.4374513394], [83290.24377534064, 1142480.3506778087], [82370.47996389655, 770222.8341590352], [63637.766473583026, 810851.8091807761], [66788.91229470367, 698840.8146168891], [75102.3290490617, 1035002.7902780143], [62638.27317992859, 683328.3156147334], [41870.43206330126, 729742.0444708264], [60907.32053788277, 1179178.6549844078], [34183.575255148746, 920899.2296020638], [51655.704042085505, 842315.3424291152], [35331.51366160177, 886502.7398532623], [47883.945613707736, 693420.0510623266], [33557.87124412175, 1150074.1571437381], [30499.492761509304, 832594.3834703927], [42733.43248401154, 791261.006569009], [42078.9053350363, 1192499.0062521168], [39537.12490267918, 820574.0244793433], [25766.68117003718, 749084.1915958913], [37431.3006839491, 1146839.7385431828], [19729.377253022878, 688071.6526254383], [17124.35674302549, 1290962.3295776465], [19615.43572022034, 939060.0950318159], [24794.10562003187, 1112677.165293667], [21900.889529328662, 858416.4692184512], [19373.06594088114, 1150876.7459370985], [24118.498247359745, 852800.0837341312], [21207.530605877277, 772057.6638792764], [22267.30551041926, 714074.8898722631], [12497.025723179937, 712008.7912734993], [15065.344990296639, 843052.9384454926], [20199.686086950154, 882232.5677295076], [12391.464759044167, 718155.5097697747], [9937.135196575824, 1227788.641219967], [15492.606340046807, 1133059.0676593857], [14651.76273816029, 882614.1807004922], [15189.523429391971, 1075073.6739545558], [13718.455011597003, 854583.2693140692], [13242.565179358064, 852689.7481448406], [12283.16329964135, 1054384.679136664], [10715.461680060893, 987530.7540134372], [9799.836999306235, 1188662.432761487], [6817.309005236672, 847516.4934806598], [9156.515653966426, 1029834.6994578489], [5647.526250134233, 700227.501149568], [6851.585075787405, 995376.7395363126], [8537.770338276303, 991275.0750426087], [5588.410860946238, 1096531.4230958493], [7832.874408306464, 681290.2321555684], [5385.709166136957, 1288904.2276863966], [5607.200777069934, 679212.9865083437], [7131.98062301099, 1233327.2530472076], [6143.062328777299, 1294580.6293236036], [4116.526919112113, 902602.6246132584], [5555.49183273859, 788062.6499769951], [5945.901312119126, 1236921.6936202012], [4307.837673987712, 1211308.1303755068], [3057.267111272262, 1144766.9718521282], [3412.952069021781, 954158.1280045257], [4857.118212156462, 1287958.9746543085], [2802.7914200776886, 857680.691013031], [3387.914599774963, 863233.6440396649], [3691.679610334573, 1031277.0232285978], [3889.932537061482, 1178453.4027236914], [3175.6272264942872, 897242.264150536], [3321.8016013704805, 1111506.090775924], [2484.743968904745, 1257395.831926505], [2604.1755637616475, 718592.1692915799], [2953.762015063723, 1299568.2114593633], [2674.99903287432, 1021821.7828949532], [1936.840241672874, 709331.3091161926], [2430.32784824078, 1018865.0657590512], [1860.436184602949, 1216703.8610504132], [1723.2315526850525, 856007.9319208895], [1953.6263447660579, 1312810.8625858119], [1858.5407262503563, 677777.0784941971], [1121.841683026275, 1053185.2996789496], [1429.1799261633125, 942788.834721557], [1305.5210429480653, 857145.1282976748], [1558.6548858562132, 1096849.3108424598], [1165.2977247587564, 975845.740861295], [1281.1760431911907, 995327.4595873987], [903.127132888626, 936759.8641734732], [830.0255705095318, 1264058.880523917], [1447.175826672647, 826241.7163334353], [782.9089616625392, 949718.6455322991], [1309.5388116616314, 805544.6451139126], [1020.0814509483284, 1186010.9653905143], [767.2256057638687, 730153.9456574344], [940.5434165348748, 731312.8929979993], [1068.431197781994, 1148310.00282886], [759.4824678568447, 927258.3721201726], [732.4516659883362, 1329935.1271868325], [706.3997339170826, 1184560.8555669347], [767.0434989984218, 798379.2411034874], [530.2926441714136, 1320301.478595184], [527.2703906339111, 1113031.6474556928], [430.5568953988018, 737433.9280313611], [692.1927353827714, 673595.9280200478], [384.23959921185053, 898704.8958790172], [405.6029193272436, 768494.1267053746], [532.3797944208193, 840066.5011984787], [554.3188745851079, 1161649.7413965538], [463.87824061723234, 1073741.3455026292], [308.0292581421485, 673847.3559565375], [462.02471007201643, 1247648.281420697], [403.35869455867373, 1160975.832082224], [267.2020640147793, 1250383.7841186798], [363.8630500648634, 718443.7734347496], [279.6159322070644, 1287801.210123048], [360.1097904304585, 839169.2354281674], [249.32033940693356, 975423.6296495761], [348.83356604943486, 1322801.2214118955], [328.40387580328803, 1221966.218413916], [221.1210037522975, 1324802.975776162], [165.06914366017043, 951352.6052332598], [261.4314897243031, 1099063.4721241775], [247.83450742057468, 840256.1768109152], [232.49428280316337, 1043133.7234717476], [134.23826614735785, 895668.9384443999], [153.20678095501415, 970433.3364156254], [163.3872329739676, 871489.5702094157], [216.6725459496833, 1220808.7783561496], [144.4212576438835, 1225762.0801782524], [192.42606995989752, 740647.2823234415], [96.11282000434359, 904821.5403045765], [166.41677897191434, 975432.1078972422], [118.12562865687576, 1225649.9201249767], [135.81589553462987, 1260216.3663823903], [116.89024486149172, 1195617.0482448642], [97.71131894635056, 833097.6624037084], [86.8018133066483, 1096535.386700453], [94.22066759538556, 850974.2314776242], [93.53703959337743, 1286339.5796547756], [117.26614306573515, 1090935.1549952293], [65.33749823040989, 700052.7320163958]], ['I', 'R'], [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])" ] }, - "execution_count": 19, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "objSIR.sensitivity()" + "objSIR" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "5062.059868394187" + "4516494303083.047" ] }, - "execution_count": 20, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -906,7 +929,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -921,18 +944,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4717.565272474467\n", - " hess_inv: array([[ 3.84423633e-03, -3.01340148e-05, 1.56049513e-06],\n", - " [-3.01340148e-05, 3.82956903e-06, 1.49977083e-08],\n", - " [ 1.56049513e-06, 1.49977083e-08, 1.00000000e+00]])\n", - " jac: array([ 8.12454287e-07, -3.28990725e-04, -2.91902226e-12])\n", + " fun: 3097544513423.658\n", + " hess_inv: array([[ 1.03645359e-11, -4.61156610e-14, 3.16936003e-06],\n", + " [-4.61156587e-14, 4.75500055e-15, -8.98088545e-09],\n", + " [ 3.16936002e-06, -8.98088607e-09, 1.00244138e+00]])\n", + " jac: array([ 9.35430284e+04, -3.55363991e+05, -3.39879219e-01])\n", " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 57\n", - " nit: 10\n", + " nfev: 55\n", + " nit: 9\n", " njev: 46\n", " status: 2\n", " success: False\n", - " x: array([3.59284491e+00, 1.99665537e-01, 1.00000000e+06])\n" + " x: array([4.54710725e+00, 1.97932059e-01, 1.25147454e+06])\n" ] } ], @@ -948,14 +971,184 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 3097544513423.661\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", + " jac: array([ 3.87782251e+04, 1.98457720e+06, -1.40896750e-01])\n", + " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", + " nfev: 16\n", + " nit: 10\n", + " njev: 16\n", + " status: 0\n", + " success: True\n", + " x: array([3.63339968e+00, 1.97932071e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='L-BFGS-B')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 0.15, 1000000.0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[(2, 5), (0.0, 1.0), (1000000.0, 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(theta,boxBounds,param_evals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fitting Gamma loss" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = GammaLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-5.77039500e+02, -6.96845671e+03, 1.73111850e-03])" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.sensitivity()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5058.726988342257" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objSIR.cost()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", + " warn('Method %s cannot handle constraints nor bounds.' % method,\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " fun: 4717.132458517435\n", + " hess_inv: array([[ 3.86858865e-03, -3.00734373e-05, 3.30190074e-06],\n", + " [-3.00734373e-05, 3.91747625e-06, 2.36516472e-08],\n", + " [ 3.30190074e-06, 2.36516472e-08, 1.00000000e+00]])\n", + " jac: array([ 2.13941642e-10, 3.42940432e-08, -7.68280694e-16])\n", + " message: 'Optimization terminated successfully.'\n", + " nfev: 28\n", + " nit: 12\n", + " njev: 27\n", + " status: 0\n", + " success: True\n", + " x: array([3.59089103e+00, 1.99441546e-01, 1.00000000e+06])\n" + ] + } + ], + "source": [ + "# perform optimization\n", + "res = minimize(fun=objSIR.cost,\n", + " jac=objSIR.sensitivity,\n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='BFGS')\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", " logpdf_p3= -shape*np.log(mu/shape)\n" ] }, @@ -963,16 +1156,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4717.565272489127\n", + " fun: 4717.132458530734\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([ 1.06976387e-03, -7.18401978e-02, -3.84350237e-09])\n", + " jac: array([ 1.00361678e-03, -6.86270665e-02, -3.60388445e-09])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", " nfev: 17\n", " nit: 10\n", " njev: 17\n", " status: 0\n", " success: True\n", - " x: array([3.59285115e+00, 1.99665226e-01, 1.00000000e+06])\n" + " x: array([3.59089697e+00, 1.99441247e-01, 1.00000000e+06])\n" ] } ], @@ -988,7 +1181,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 30, "metadata": {}, "outputs": [ { @@ -1039,218 +1232,218 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[6.000000e+00, 0.000000e+00],\n", - " [9.000000e+00, 1.000000e+00],\n", - " [2.600000e+01, 2.000000e+00],\n", - " [4.100000e+01, 4.000000e+00],\n", - " [1.080000e+02, 1.000000e+01],\n", - " [2.660000e+02, 2.000000e+01],\n", - " [8.140000e+02, 3.400000e+01],\n", - " [1.610000e+03, 8.400000e+01],\n", - " [4.034000e+03, 2.880000e+02],\n", - " [8.244000e+03, 6.960000e+02],\n", - " [2.944100e+04, 1.278000e+03],\n", - " [3.632600e+04, 3.083000e+03],\n", - " [1.343010e+05, 7.316000e+03],\n", - " [2.511210e+05, 1.222800e+04],\n", - " [5.123970e+05, 2.154300e+04],\n", - " [5.856170e+05, 3.848500e+04],\n", - " [7.902060e+05, 8.369300e+04],\n", - " [9.747970e+05, 1.374470e+05],\n", - " [7.077570e+05, 1.173470e+05],\n", - " [6.035560e+05, 1.894330e+05],\n", - " [9.139100e+05, 1.990480e+05],\n", - " [5.489300e+05, 2.794000e+05],\n", - " [4.620410e+05, 3.833270e+05],\n", - " [7.613260e+05, 2.588560e+05],\n", - " [6.622870e+05, 3.404260e+05],\n", - " [5.084650e+05, 3.910210e+05],\n", - " [6.567450e+05, 5.784740e+05],\n", - " [5.541630e+05, 4.267650e+05],\n", - " [5.322210e+05, 5.087300e+05],\n", - " [4.456160e+05, 4.763160e+05],\n", - " [5.902310e+05, 6.481090e+05],\n", - " [5.449100e+05, 6.728700e+05],\n", - " [3.108270e+05, 5.874350e+05],\n", - " [4.561160e+05, 7.105300e+05],\n", - " [3.642540e+05, 5.794740e+05],\n", - " [3.114750e+05, 8.214390e+05],\n", - " [2.527190e+05, 4.782710e+05],\n", - " [3.078090e+05, 6.833250e+05],\n", - " [2.812700e+05, 8.344320e+05],\n", - " [2.613370e+05, 7.506100e+05],\n", - " [3.522730e+05, 6.899340e+05],\n", - " [3.372790e+05, 6.684740e+05],\n", - " [2.628170e+05, 8.967300e+05],\n", - " [2.749900e+05, 6.176790e+05],\n", - " [2.528980e+05, 8.654760e+05],\n", - " [2.098670e+05, 9.504580e+05],\n", - " [1.617910e+05, 1.051352e+06],\n", - " [1.768890e+05, 9.986820e+05],\n", - " [1.587040e+05, 1.052019e+06],\n", - " [2.359540e+05, 5.815120e+05],\n", - " [1.395080e+05, 1.104611e+06],\n", - " [1.272660e+05, 9.005600e+05],\n", - " [1.462970e+05, 8.024700e+05],\n", - " [1.536980e+05, 1.124694e+06],\n", - " [1.652010e+05, 6.528740e+05],\n", - " [1.600480e+05, 6.982990e+05],\n", - " [9.459700e+04, 7.941890e+05],\n", - " [1.172920e+05, 1.170125e+06],\n", - " [8.820500e+04, 1.027702e+06],\n", - " [7.969900e+04, 8.879200e+05],\n", - " [1.229900e+05, 8.230110e+05],\n", - " [9.029800e+04, 8.566030e+05],\n", - " [1.125830e+05, 8.236900e+05],\n", - " [1.154790e+05, 9.246180e+05],\n", - " [7.753300e+04, 9.045910e+05],\n", - " [7.808200e+04, 7.158560e+05],\n", - " [9.966600e+04, 6.728900e+05],\n", - " [8.796800e+04, 1.005141e+06],\n", - " [5.675400e+04, 9.265630e+05],\n", - " [5.086800e+04, 7.102210e+05],\n", - " [4.244600e+04, 7.063260e+05],\n", - " [4.655500e+04, 9.741340e+05],\n", - " [5.291800e+04, 6.721520e+05],\n", - " [6.155400e+04, 1.154690e+06],\n", - " [4.135600e+04, 1.114492e+06],\n", - " [4.637500e+04, 8.701900e+05],\n", - " [3.724400e+04, 1.191670e+06],\n", - " [4.128200e+04, 1.046085e+06],\n", - " [5.531800e+04, 1.128080e+06],\n", - " [3.190800e+04, 1.000208e+06],\n", - " [3.401000e+04, 9.302210e+05],\n", - " [3.092800e+04, 1.018299e+06],\n", - " [3.952300e+04, 1.096729e+06],\n", - " [4.310200e+04, 9.233630e+05],\n", - " [2.445300e+04, 8.106100e+05],\n", - " [2.429100e+04, 1.168379e+06],\n", - " [3.085000e+04, 6.723580e+05],\n", - " [2.293100e+04, 6.831810e+05],\n", - " [1.931200e+04, 1.181575e+06],\n", - " [2.480100e+04, 6.945950e+05],\n", - " [3.023300e+04, 1.144610e+06],\n", - " [2.044000e+04, 9.168310e+05],\n", - " [2.600300e+04, 6.897410e+05],\n", - " [2.045000e+04, 1.277607e+06],\n", - " [2.324500e+04, 9.581790e+05],\n", - " [1.644700e+04, 1.225836e+06],\n", - " [2.005100e+04, 6.691500e+05],\n", - " [1.666400e+04, 9.255040e+05],\n", - " [1.668100e+04, 7.432400e+05],\n", - " [1.868300e+04, 1.092030e+06],\n", - " [1.799600e+04, 8.042660e+05],\n", - " [1.741200e+04, 7.039810e+05],\n", - " [1.269900e+04, 1.121871e+06],\n", - " [1.581400e+04, 1.027571e+06],\n", - " [1.273400e+04, 8.585930e+05],\n", - " [1.358300e+04, 7.649160e+05],\n", - " [1.012600e+04, 7.501810e+05],\n", - " [7.193000e+03, 1.271423e+06],\n", - " [1.024900e+04, 1.133442e+06],\n", - " [1.039800e+04, 1.077066e+06],\n", - " [1.029100e+04, 1.127212e+06],\n", - " [6.610000e+03, 6.722480e+05],\n", - " [6.598000e+03, 8.888560e+05],\n", - " [7.690000e+03, 7.394240e+05],\n", - " [8.846000e+03, 1.006776e+06],\n", - " [8.257000e+03, 1.192111e+06],\n", - " [5.882000e+03, 1.115150e+06],\n", - " [5.421000e+03, 7.166400e+05],\n", - " [6.825000e+03, 1.124535e+06],\n", - " [3.683000e+03, 1.098986e+06],\n", - " [6.805000e+03, 1.096527e+06],\n", - " [5.972000e+03, 1.094255e+06],\n", - " [5.273000e+03, 9.224470e+05],\n", - " [4.327000e+03, 6.865670e+05],\n", - " [3.383000e+03, 1.035475e+06],\n", - " [3.070000e+03, 1.166200e+06],\n", - " [4.129000e+03, 1.036638e+06],\n", - " [4.277000e+03, 1.265375e+06],\n", - " [3.188000e+03, 1.161353e+06],\n", - " [2.800000e+03, 9.751570e+05],\n", - " [3.620000e+03, 7.897360e+05],\n", - " [3.842000e+03, 1.188642e+06],\n", - " [3.068000e+03, 8.948170e+05],\n", - " [2.135000e+03, 1.167306e+06],\n", - " [2.276000e+03, 1.245916e+06],\n", - " [2.348000e+03, 1.120309e+06],\n", - " [2.249000e+03, 7.320390e+05],\n", - " [1.851000e+03, 1.253931e+06],\n", - " [2.652000e+03, 7.404650e+05],\n", - " [2.442000e+03, 1.072739e+06],\n", - " [2.418000e+03, 1.066501e+06],\n", - " [2.121000e+03, 1.072553e+06],\n", - " [2.017000e+03, 1.184127e+06],\n", - " [1.425000e+03, 9.984420e+05],\n", - " [2.002000e+03, 1.167627e+06],\n", - " [1.189000e+03, 7.632420e+05],\n", - " [9.640000e+02, 1.062757e+06],\n", - " [9.480000e+02, 9.527130e+05],\n", - " [1.087000e+03, 1.326560e+06],\n", - " [1.582000e+03, 1.285545e+06],\n", - " [1.025000e+03, 1.216454e+06],\n", - " [1.097000e+03, 8.375880e+05],\n", - " [1.185000e+03, 1.328683e+06],\n", - " [9.610000e+02, 9.588020e+05],\n", - " [8.360000e+02, 6.700710e+05],\n", - " [8.470000e+02, 9.090290e+05],\n", - " [8.760000e+02, 6.935830e+05],\n", - " [9.980000e+02, 1.300878e+06],\n", - " [8.380000e+02, 8.590400e+05],\n", - " [8.490000e+02, 7.487480e+05],\n", - " [4.750000e+02, 7.295330e+05],\n", - " [4.750000e+02, 1.134978e+06],\n", - " [5.950000e+02, 1.176977e+06],\n", - " [6.090000e+02, 1.319344e+06],\n", - " [5.720000e+02, 1.087811e+06],\n", - " [5.380000e+02, 8.838410e+05],\n", - " [6.530000e+02, 1.126644e+06],\n", - " [3.800000e+02, 7.169190e+05],\n", - " [4.790000e+02, 7.679570e+05],\n", - " [3.760000e+02, 7.796360e+05],\n", - " [3.990000e+02, 1.178129e+06],\n", - " [4.920000e+02, 6.799390e+05],\n", - " [3.170000e+02, 1.288119e+06],\n", - " [2.840000e+02, 1.084258e+06],\n", - " [2.530000e+02, 6.698680e+05],\n", - " [2.990000e+02, 1.143576e+06],\n", - " [3.880000e+02, 8.489890e+05],\n", - " [2.560000e+02, 9.687090e+05],\n", - " [2.270000e+02, 8.278320e+05],\n", - " [2.290000e+02, 7.324660e+05],\n", - " [3.170000e+02, 1.189860e+06],\n", - " [2.040000e+02, 8.754980e+05],\n", - " [2.690000e+02, 1.018708e+06],\n", - " [2.580000e+02, 1.315244e+06],\n", - " [1.910000e+02, 1.123760e+06],\n", - " [1.950000e+02, 1.043334e+06],\n", - " [2.070000e+02, 1.252729e+06],\n", - " [2.100000e+02, 6.666520e+05],\n", - " [2.170000e+02, 7.769410e+05],\n", - " [1.820000e+02, 1.204558e+06],\n", - " [1.670000e+02, 9.251490e+05],\n", - " [1.670000e+02, 8.509660e+05],\n", - " [1.260000e+02, 1.247044e+06],\n", - " [1.070000e+02, 6.884890e+05],\n", - " [1.200000e+02, 1.067715e+06],\n", - " [9.100000e+01, 7.749630e+05],\n", - " [9.500000e+01, 9.008270e+05],\n", - " [1.330000e+02, 9.970260e+05],\n", - " [1.220000e+02, 8.254500e+05],\n", - " [1.130000e+02, 1.327483e+06],\n", - " [8.000000e+01, 9.962030e+05],\n", - " [7.500000e+01, 7.089120e+05],\n", - " [1.070000e+02, 8.624290e+05]])" + "array([[4.000000e+00, 0.000000e+00],\n", + " [9.000000e+00, 0.000000e+00],\n", + " [2.300000e+01, 2.000000e+00],\n", + " [4.800000e+01, 3.000000e+00],\n", + " [1.650000e+02, 1.000000e+01],\n", + " [4.100000e+02, 1.900000e+01],\n", + " [5.290000e+02, 4.800000e+01],\n", + " [1.447000e+03, 9.100000e+01],\n", + " [4.994000e+03, 3.120000e+02],\n", + " [1.010400e+04, 5.480000e+02],\n", + " [2.619500e+04, 1.403000e+03],\n", + " [3.838900e+04, 2.237000e+03],\n", + " [1.446160e+05, 4.711000e+03],\n", + " [2.048410e+05, 1.283000e+04],\n", + " [3.048600e+05, 2.651500e+04],\n", + " [7.154730e+05, 6.606400e+04],\n", + " [5.708040e+05, 7.573800e+04],\n", + " [9.472310e+05, 1.549860e+05],\n", + " [9.239530e+05, 1.938220e+05],\n", + " [6.578010e+05, 1.507700e+05],\n", + " [8.431710e+05, 2.491130e+05],\n", + " [5.593410e+05, 1.859570e+05],\n", + " [6.962370e+05, 4.036880e+05],\n", + " [5.400680e+05, 2.664190e+05],\n", + " [4.574790e+05, 3.882220e+05],\n", + " [4.259200e+05, 3.911230e+05],\n", + " [3.969080e+05, 3.714150e+05],\n", + " [6.021030e+05, 4.233520e+05],\n", + " [6.417700e+05, 5.189030e+05],\n", + " [4.169020e+05, 4.043690e+05],\n", + " [3.300390e+05, 3.786970e+05],\n", + " [5.515290e+05, 6.434120e+05],\n", + " [5.497880e+05, 5.356890e+05],\n", + " [2.809800e+05, 7.420170e+05],\n", + " [4.662840e+05, 6.147500e+05],\n", + " [3.121480e+05, 5.296810e+05],\n", + " [3.509540e+05, 8.722160e+05],\n", + " [4.015680e+05, 8.085170e+05],\n", + " [2.955060e+05, 6.811300e+05],\n", + " [3.163150e+05, 6.594160e+05],\n", + " [1.957770e+05, 6.794370e+05],\n", + " [1.942800e+05, 7.213150e+05],\n", + " [1.785010e+05, 6.754650e+05],\n", + " [2.474050e+05, 9.859320e+05],\n", + " [2.999430e+05, 7.646450e+05],\n", + " [1.480790e+05, 8.987700e+05],\n", + " [2.039100e+05, 7.106650e+05],\n", + " [1.982690e+05, 5.501940e+05],\n", + " [2.419740e+05, 8.363010e+05],\n", + " [1.948870e+05, 9.065450e+05],\n", + " [1.466650e+05, 9.137390e+05],\n", + " [1.437800e+05, 8.800700e+05],\n", + " [1.040970e+05, 7.210860e+05],\n", + " [1.877770e+05, 8.939330e+05],\n", + " [9.414500e+04, 8.322350e+05],\n", + " [1.473610e+05, 9.759700e+05],\n", + " [1.079600e+05, 9.195050e+05],\n", + " [1.313530e+05, 8.439860e+05],\n", + " [1.381340e+05, 9.444460e+05],\n", + " [1.438110e+05, 8.746980e+05],\n", + " [1.024880e+05, 8.253310e+05],\n", + " [9.367500e+04, 1.065797e+06],\n", + " [9.288600e+04, 1.155351e+06],\n", + " [6.637600e+04, 9.884990e+05],\n", + " [1.060100e+05, 8.106190e+05],\n", + " [1.047690e+05, 6.398000e+05],\n", + " [6.438000e+04, 1.004434e+06],\n", + " [8.831100e+04, 7.515780e+05],\n", + " [8.329000e+04, 1.142480e+06],\n", + " [8.237000e+04, 7.702230e+05],\n", + " [6.363800e+04, 8.108520e+05],\n", + " [6.678900e+04, 6.988410e+05],\n", + " [7.510200e+04, 1.035003e+06],\n", + " [6.263800e+04, 6.833280e+05],\n", + " [4.187000e+04, 7.297420e+05],\n", + " [6.090700e+04, 1.179179e+06],\n", + " [3.418400e+04, 9.208990e+05],\n", + " [5.165600e+04, 8.423150e+05],\n", + " [3.533200e+04, 8.865030e+05],\n", + " [4.788400e+04, 6.934200e+05],\n", + " [3.355800e+04, 1.150074e+06],\n", + " [3.049900e+04, 8.325940e+05],\n", + " [4.273300e+04, 7.912610e+05],\n", + " [4.207900e+04, 1.192499e+06],\n", + " [3.953700e+04, 8.205740e+05],\n", + " [2.576700e+04, 7.490840e+05],\n", + " [3.743100e+04, 1.146840e+06],\n", + " [1.972900e+04, 6.880720e+05],\n", + " [1.712400e+04, 1.290962e+06],\n", + " [1.961500e+04, 9.390600e+05],\n", + " [2.479400e+04, 1.112677e+06],\n", + " [2.190100e+04, 8.584160e+05],\n", + " [1.937300e+04, 1.150877e+06],\n", + " [2.411800e+04, 8.528000e+05],\n", + " [2.120800e+04, 7.720580e+05],\n", + " [2.226700e+04, 7.140750e+05],\n", + " [1.249700e+04, 7.120090e+05],\n", + " [1.506500e+04, 8.430530e+05],\n", + " [2.020000e+04, 8.822330e+05],\n", + " [1.239100e+04, 7.181560e+05],\n", + " [9.937000e+03, 1.227789e+06],\n", + " [1.549300e+04, 1.133059e+06],\n", + " [1.465200e+04, 8.826140e+05],\n", + " [1.519000e+04, 1.075074e+06],\n", + " [1.371800e+04, 8.545830e+05],\n", + " [1.324300e+04, 8.526900e+05],\n", + " [1.228300e+04, 1.054385e+06],\n", + " [1.071500e+04, 9.875310e+05],\n", + " [9.800000e+03, 1.188662e+06],\n", + " [6.817000e+03, 8.475160e+05],\n", + " [9.157000e+03, 1.029835e+06],\n", + " [5.648000e+03, 7.002280e+05],\n", + " [6.852000e+03, 9.953770e+05],\n", + " [8.538000e+03, 9.912750e+05],\n", + " [5.588000e+03, 1.096531e+06],\n", + " [7.833000e+03, 6.812900e+05],\n", + " [5.386000e+03, 1.288904e+06],\n", + " [5.607000e+03, 6.792130e+05],\n", + " [7.132000e+03, 1.233327e+06],\n", + " [6.143000e+03, 1.294581e+06],\n", + " [4.117000e+03, 9.026030e+05],\n", + " [5.555000e+03, 7.880630e+05],\n", + " [5.946000e+03, 1.236922e+06],\n", + " [4.308000e+03, 1.211308e+06],\n", + " [3.057000e+03, 1.144767e+06],\n", + " [3.413000e+03, 9.541580e+05],\n", + " [4.857000e+03, 1.287959e+06],\n", + " [2.803000e+03, 8.576810e+05],\n", + " [3.388000e+03, 8.632340e+05],\n", + " [3.692000e+03, 1.031277e+06],\n", + " [3.890000e+03, 1.178453e+06],\n", + " [3.176000e+03, 8.972420e+05],\n", + " [3.322000e+03, 1.111506e+06],\n", + " [2.485000e+03, 1.257396e+06],\n", + " [2.604000e+03, 7.185920e+05],\n", + " [2.954000e+03, 1.299568e+06],\n", + " [2.675000e+03, 1.021822e+06],\n", + " [1.937000e+03, 7.093310e+05],\n", + " [2.430000e+03, 1.018865e+06],\n", + " [1.860000e+03, 1.216704e+06],\n", + " [1.723000e+03, 8.560080e+05],\n", + " [1.954000e+03, 1.312811e+06],\n", + " [1.859000e+03, 6.777770e+05],\n", + " [1.122000e+03, 1.053185e+06],\n", + " [1.429000e+03, 9.427890e+05],\n", + " [1.306000e+03, 8.571450e+05],\n", + " [1.559000e+03, 1.096849e+06],\n", + " [1.165000e+03, 9.758460e+05],\n", + " [1.281000e+03, 9.953270e+05],\n", + " [9.030000e+02, 9.367600e+05],\n", + " [8.300000e+02, 1.264059e+06],\n", + " [1.447000e+03, 8.262420e+05],\n", + " [7.830000e+02, 9.497190e+05],\n", + " [1.310000e+03, 8.055450e+05],\n", + " [1.020000e+03, 1.186011e+06],\n", + " [7.670000e+02, 7.301540e+05],\n", + " [9.410000e+02, 7.313130e+05],\n", + " [1.068000e+03, 1.148310e+06],\n", + " [7.590000e+02, 9.272580e+05],\n", + " [7.320000e+02, 1.329935e+06],\n", + " [7.060000e+02, 1.184561e+06],\n", + " [7.670000e+02, 7.983790e+05],\n", + " [5.300000e+02, 1.320301e+06],\n", + " [5.270000e+02, 1.113032e+06],\n", + " [4.310000e+02, 7.374340e+05],\n", + " [6.920000e+02, 6.735960e+05],\n", + " [3.840000e+02, 8.987050e+05],\n", + " [4.060000e+02, 7.684940e+05],\n", + " [5.320000e+02, 8.400670e+05],\n", + " [5.540000e+02, 1.161650e+06],\n", + " [4.640000e+02, 1.073741e+06],\n", + " [3.080000e+02, 6.738470e+05],\n", + " [4.620000e+02, 1.247648e+06],\n", + " [4.030000e+02, 1.160976e+06],\n", + " [2.670000e+02, 1.250384e+06],\n", + " [3.640000e+02, 7.184440e+05],\n", + " [2.800000e+02, 1.287801e+06],\n", + " [3.600000e+02, 8.391690e+05],\n", + " [2.490000e+02, 9.754240e+05],\n", + " [3.490000e+02, 1.322801e+06],\n", + " [3.280000e+02, 1.221966e+06],\n", + " [2.210000e+02, 1.324803e+06],\n", + " [1.650000e+02, 9.513530e+05],\n", + " [2.610000e+02, 1.099063e+06],\n", + " [2.480000e+02, 8.402560e+05],\n", + " [2.320000e+02, 1.043134e+06],\n", + " [1.340000e+02, 8.956690e+05],\n", + " [1.530000e+02, 9.704330e+05],\n", + " [1.630000e+02, 8.714900e+05],\n", + " [2.170000e+02, 1.220809e+06],\n", + " [1.440000e+02, 1.225762e+06],\n", + " [1.920000e+02, 7.406470e+05],\n", + " [9.600000e+01, 9.048220e+05],\n", + " [1.660000e+02, 9.754320e+05],\n", + " [1.180000e+02, 1.225650e+06],\n", + " [1.360000e+02, 1.260216e+06],\n", + " [1.170000e+02, 1.195617e+06],\n", + " [9.800000e+01, 8.330980e+05],\n", + " [8.700000e+01, 1.096535e+06],\n", + " [9.400000e+01, 8.509740e+05],\n", + " [9.400000e+01, 1.286340e+06],\n", + " [1.170000e+02, 1.090935e+06],\n", + " [6.500000e+01, 7.000530e+05]])" ] }, - "execution_count": 24, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -1269,7 +1462,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 32, "metadata": { "scrolled": false }, @@ -1281,23 +1474,16 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 26, + "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "9745677.652607694" + "8999599.052695096" ] }, - "execution_count": 26, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -1308,7 +1494,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 34, "metadata": {}, "outputs": [ { @@ -1323,18 +1509,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 3692407.814497117\n", - " hess_inv: array([[ 1.13964289e-07, -2.49061166e-09, 2.20264892e-06],\n", - " [-2.49061166e-09, 9.27756704e-10, 9.40250405e-09],\n", - " [ 2.20264892e-06, 9.40250405e-09, 1.00000987e+00]])\n", - " jac: array([ 1.33293688e-02, -2.07506277e-02, -4.87274588e-08])\n", + " fun: 3555725.9211099287\n", + " hess_inv: array([[ 1.12854102e-07, -2.48584571e-09, 2.27949584e-06],\n", + " [-2.48584571e-09, 9.25888041e-10, 9.47168312e-09],\n", + " [ 2.27949584e-06, 9.47168312e-09, 1.00000832e+00]])\n", + " jac: array([ 1.48618754e-02, -2.24162553e-02, -5.37171184e-08])\n", " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 54\n", - " nit: 10\n", - " njev: 42\n", + " nfev: 71\n", + " nit: 11\n", + " njev: 60\n", " status: 2\n", " success: False\n", - " x: array([3.65564294e+00, 2.00162197e-01, 9.99999090e+05])\n" + " x: array([3.61442328e+00, 1.98453976e-01, 9.99999326e+05])\n" ] } ], @@ -1350,23 +1536,23 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " fun: 3692407.8145229938\n", + " fun: 3555725.9211287573\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([ 9.92225896e-02, -2.34421856e+02, -3.62722747e-07])\n", + " jac: array([-7.98496027e-01, -2.01665131e+02, 2.88610490e-06])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", " nfev: 14\n", " nit: 10\n", " njev: 14\n", " status: 0\n", " success: True\n", - " x: array([3.65564687e+00, 2.00161978e-01, 1.00000000e+06])\n" + " x: array([3.61442613e+00, 1.98453791e-01, 1.00000000e+06])\n" ] } ], @@ -1382,7 +1568,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 36, "metadata": {}, "outputs": [ { @@ -1426,7 +1612,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 37, "metadata": { "scrolled": false }, @@ -1435,9 +1621,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] } @@ -1449,16 +1635,16 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([-2.87176322e+02, -3.47833060e+03, 8.61528965e-04])" + "array([-2.86825346e+02, -3.46781844e+03, 8.60476039e-04])" ] }, - "execution_count": 31, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } @@ -1469,16 +1655,16 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "5041.270821570561" + "5038.2958154688895" ] }, - "execution_count": 32, + "execution_count": 39, "metadata": {}, "output_type": "execute_result" } @@ -1489,7 +1675,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 40, "metadata": {}, "outputs": [ { @@ -1504,18 +1690,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4869.743686474076\n", - " hess_inv: array([[ 7.82577440e-03, -6.12363068e-05, 1.76151491e-06],\n", - " [-6.12363068e-05, 7.85949196e-06, 1.45278667e-08],\n", - " [ 1.76151491e-06, 1.45278667e-08, 1.00000000e+00]])\n", - " jac: array([-2.72469402e-08, 1.25576726e-07, 9.79041863e-14])\n", + " fun: 4868.230711182974\n", + " hess_inv: array([[ 7.84349281e-03, -6.15336988e-05, 1.77314305e-06],\n", + " [-6.15336988e-05, 7.88477962e-06, 1.39267526e-08],\n", + " [ 1.77314305e-06, 1.39267526e-08, 1.00000000e+00]])\n", + " jac: array([-1.03570668e-08, 1.32455900e-07, 3.71928550e-14])\n", " message: 'Optimization terminated successfully.'\n", " nfev: 16\n", " nit: 11\n", " njev: 16\n", " status: 0\n", " success: True\n", - " x: array([3.59321800e+00, 1.99662852e-01, 1.00000000e+06])\n" + " x: array([3.59106407e+00, 1.99435913e-01, 1.00000000e+06])\n" ] } ], @@ -1531,14 +1717,14 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev7+g126fc99.d20200624-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] }, @@ -1546,16 +1732,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4869.743686476613\n", + " fun: 4868.230711171033\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([-1.47841000e-04, -9.54029439e-03, 5.31224858e-10])\n", + " jac: array([-8.31389989e-04, -6.80463204e-03, 2.98556969e-09])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 18\n", + " nfev: 26\n", " nit: 12\n", - " njev: 18\n", + " njev: 26\n", " status: 0\n", " success: True\n", - " x: array([3.59321743e+00, 1.99662786e-01, 1.00000000e+06])\n" + " x: array([3.59105802e+00, 1.99435910e-01, 1.00000000e+06])\n" ] } ], @@ -1571,7 +1757,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 42, "metadata": {}, "outputs": [ { @@ -1613,6 +1799,20 @@ "outputs": [], "source": [] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/pygom/loss/base_loss.py b/pygom/loss/base_loss.py index 68c582da..9f6df6d3 100644 --- a/pygom/loss/base_loss.py +++ b/pygom/loss/base_loss.py @@ -65,7 +65,7 @@ def __init__(self, theta, ode, y = ode_utils.check_array_type(y) if state_weight is None: - state_weight = np.ones(y.shape) + state_weight = 1.0 if len(y) == y.size: y = y.flatten() @@ -149,9 +149,6 @@ def __init__(self, theta, ode, else: raise InputError("State name should be str or of type list/tuple") - # if self._stateWeight is not None: - if np.any(self._stateWeight <= 0): - raise InputError("Weights should be strictly positive") # finish ordering information # now get the index of target states @@ -918,7 +915,7 @@ def fisher_information(self, theta=None, full_output=False, method=None): # ############################################################ - def cost(self, theta=None): + def cost(self, theta=None, apply_weighting = True): """ Find the cost/loss given time points and the corresponding observations. @@ -927,6 +924,9 @@ def cost(self, theta=None): ---------- theta: array like input value of the parameters + apply_weighting: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- @@ -943,11 +943,11 @@ def cost(self, theta=None): """ yhat = self._getSolution(theta) - c = self._lossObj.loss(yhat) + c = self._lossObj.loss(yhat,apply_weighting = apply_weighting) return np.nan_to_num(c) if c == np.inf else c - def diff_loss(self, theta=None): + def diff_loss(self, theta=None, apply_weighting = True): """ Find the derivative of the loss function given time points and the corresponding observations, with initial conditions @@ -956,6 +956,9 @@ def diff_loss(self, theta=None): ---------- theta: array like input value of the parameters + apply_weighting: boolean + If True multiplies array of residuals by weightings, else raw + residuals are used. Returns ------- @@ -969,13 +972,13 @@ def diff_loss(self, theta=None): try: # the solution does not include the origin solution = self._getSolution(theta) - return self._lossObj.diff_loss(solution) + return self._lossObj.diff_loss(solution,apply_weighting = apply_weighting) except Exception as e: # print(e) # print("parameters = " +str(theta)) return np.nan_to_num((np.ones(self._y.shape)*np.inf)) - def residual(self, theta=None): + def residual(self, theta=None, apply_weighting = True): """ Find the residuals given time points and the corresponding observations, with initial conditions @@ -984,6 +987,9 @@ def residual(self, theta=None): ---------- theta: array like input value of the parameters + apply_weighting: boolean + If True multiplies array of residuals by weightings, else raw + residuals returned. Returns ------- @@ -1003,7 +1009,7 @@ def residual(self, theta=None): try: # the solution does not include the origin solution = self._getSolution(theta) - return self._lossObj.residual(solution) + return self._lossObj.residual(solution, apply_weighting = apply_weighting) except Exception as e: # print(e) return np.nan_to_num((np.ones(self._y.shape)*np.inf)) @@ -1014,7 +1020,7 @@ def residual(self, theta=None): # ############################################################ - def costIV(self, theta=None): + def costIV(self, theta=None, apply_weighting = True): """ Find the cost/loss given the parameters. The input theta here is assumed to include both the parameters as well as the @@ -1024,6 +1030,10 @@ def costIV(self, theta=None): ---------- theta: array like parameters and guess of initial values of the states + apply_weighting: boolean + If True multiplies array of residuals by weightings, else raw + residuals returned. + Returns ------- @@ -1039,9 +1049,9 @@ def costIV(self, theta=None): self._setParamStateInput(theta) solution = self._getSolution() - return self._lossObj.loss(solution) + return self._lossObj.loss(solution, apply_weighting = apply_weighting) - def diff_lossIV(self, theta=None): + def diff_lossIV(self, theta=None, apply_weighting = True): """ Find the derivative of the loss function w.r.t. the parameters given time points and the corresponding observations, with @@ -1051,6 +1061,9 @@ def diff_lossIV(self, theta=None): ---------- theta: array like parameters and initial values of the states + apply_weighting: boolean + If True multiplies array of residuals by weightings, else raw + residuals returned. Returns ------- @@ -1068,13 +1081,13 @@ def diff_lossIV(self, theta=None): try: # the solution does not include the origin solution = self._getSolution() - return self._lossObj.diff_loss(solution) + return self._lossObj.diff_loss(solution, apply_weighting = apply_weighting) except Exception as e: # print(e) # print("parameters = " + str(theta)) return np.nan_to_num((np.ones(self._y.shape)*np.inf)) - def residualIV(self, theta=None): + def residualIV(self, theta=None, apply_weighting = True): """ Find the residuals given time points and the corresponding observations, with initial conditions. @@ -1083,6 +1096,9 @@ def residualIV(self, theta=None): ---------- theta: array like parameters and initial values of the states + apply_weighting: boolean + If True multiplies array of residuals by weightings, else raw + residuals returned. Returns ------- @@ -1105,7 +1121,7 @@ def residualIV(self, theta=None): try: # the solution does not include the origin solution = self._getSolution() - return self._lossObj.residual(solution) + return self._lossObj.residual(solution, apply_weighting = apply_weighting) except Exception as e: # print(e) return np.nan_to_num((np.ones(self._y.shape)*np.inf)) @@ -1571,20 +1587,20 @@ def _setWeight(self, n, p, w): elif m == 1: self._stateWeight = np.ones((n, p))*w else: - raise InputError("Number of input weights is not equal " + - "to the number of observations") + raise AssertionError("Number of input weights is not equal " + + "to the number of observations") elif p == m: if q == 1: self._stateWeight = np.ones((n, p))*w else: - raise InputError("Number of input weights is not equal " + - "to number of states") + raise AssertionError("Number of input weights is not equal " + + "to number of states") else: if q == 1 and m == 1: self._stateWeight = np.ones((n, p))*w else: - raise InputError("Number of input weights differs from " + - "the number of observations") + raise AssertionError("Number of input weights differs from " + + "the number of observations") def _setX0(self, x0): """ diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index b326c7bb..584fe228 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -49,29 +49,28 @@ def __init__(self, y, weights=None): self._numVar = 0 self._w = np.ones(self._y.shape) else: - self._w = check_array_type(weights) + self._w = check_array_type(weights,accept_booleans=True) + if np.any(self._w<0.0): + raise ValueError('No elements in numpy array of weights should be negative') + if np.all(self._w==0.0): + raise ValueError('All elements in numpy array of weights should not be 0.0') if len(self._w.shape) > 1: if 1 in self._w.shape: self._w = self._w.flatten() - if np.any(self._w<0.0): - raise ValueError('No elements in numpy array of weights should be negative') - if np.all(self._w==0.0): - raise ValueError('All elements in numpy array of weights should not be 0.0') - assert self._y.shape == self._w.shape, \ "Input weight not of the same size as y" - def residual(self, yhat, weighting_applied = True): + def residual(self, yhat, apply_weighting = True): ''' - Raw residuals returned if weighting_applied = False, else + Raw residuals returned if apply_weighting = False, else the weighted residuals. Parameters ---------- yhat: array like observation - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals returned. @@ -80,8 +79,8 @@ def residual(self, yhat, weighting_applied = True): :math:`y_{i} - \\hat{y}_{i}` ''' - if isinstance(weighting_applied,bool)==False: - raise TypeError('weighting_applied should be boolean') + if isinstance(apply_weighting,bool)==False: + raise TypeError('apply_weighting should be boolean') if len(yhat.shape) > 1: if 1 in yhat.shape: @@ -90,7 +89,7 @@ def residual(self, yhat, weighting_applied = True): resid = self._y - yhat else: resid = self._y - yhat - if weighting_applied == True: + if apply_weighting == True: resid *= self._w return resid @@ -108,10 +107,10 @@ class Square(baseloss_type): ''' def __init__(self, y, weights=None): - super().__init__(y, weights=None) + super().__init__(y, weights) self.loss(self._y) - def loss(self, yhat, weighting_applied = True): + def loss(self, yhat, apply_weighting = True): ''' Loss under square loss. Not really saying much here @@ -119,18 +118,17 @@ def loss(self, yhat, weighting_applied = True): ---------- yhat: array like observation - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. - Returns ------- :math:`\\sum_{i=1}^{n} (y-\\hat{y})^{2}` ''' - return (self.residual(yhat,weighting_applied)**2).sum() + return (self.residual(yhat, apply_weighting)**2).sum() - def diff_loss(self, yhat,weighting_applied=True): + def diff_loss(self, yhat, apply_weighting=True): ''' Derivative under square loss. Assuming that we are solving the minimization problem i.e. our objective function is the @@ -140,7 +138,7 @@ def diff_loss(self, yhat,weighting_applied=True): ---------- yhat: array like observation - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -148,9 +146,9 @@ def diff_loss(self, yhat,weighting_applied=True): ------- :math:`-2(y_{i} - \\hat{y}_{i})` ''' - return -2*self.residual(yhat,weighting_applied) + return -2*self.residual(yhat, apply_weighting) - def diff2Loss(self, yhat): + def diff2Loss(self, yhat, apply_weighting=True): ''' Twice derivative of the square loss. Which is simply 2. @@ -158,6 +156,11 @@ def diff2Loss(self, yhat): ---------- yhat: array like observations + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. Returns ------- @@ -181,8 +184,8 @@ class Normal(baseloss_type): sigma: float standard deviation ''' - def __init__(self, y, sigma=1.0,weight=None): - super().__init__(y, weights=None) + def __init__(self, y, sigma=1.0, weights=None): + super().__init__(y, weights) err_str = "Standard deviation not of the correct " if isinstance(sigma, np.ndarray): if np.any(sigma<0): @@ -212,7 +215,7 @@ def __init__(self, y, sigma=1.0,weight=None): self._sigma2 = self._sigma**2 self.loss(self._y) - def loss(self, yhat,weighting_applied=True): + def loss(self, yhat, apply_weighting=True): ''' The loss under a normal distribution. Defined as the negative log-likelihood here. @@ -221,7 +224,7 @@ def loss(self, yhat,weighting_applied=True): ---------- yhat: array like observation - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -234,7 +237,7 @@ def loss(self, yhat,weighting_applied=True): if 1 in yhat.shape: yhat = yhat.ravel() - r=self.residual(yhat,weighting_applied) + r=self.residual(yhat, apply_weighting) sigma=self._sigma # Calculate negative likelihood (depending on weighting of residuals). @@ -245,7 +248,7 @@ def loss(self, yhat,weighting_applied=True): logpdf_p5_alt= -r**2 / (2*sigma**2) return (-(logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4+logpdf_p5_alt)).sum() - def diff_loss(self, yhat,weighting_applied=True): + def diff_loss(self, yhat, apply_weighting=True): ''' Derivative of the loss function which is :math:`\\sigma^{-1}(y - \\hat{y})` @@ -254,7 +257,7 @@ def diff_loss(self, yhat,weighting_applied=True): ---------- yhat: array like observation - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -264,10 +267,10 @@ def diff_loss(self, yhat,weighting_applied=True): :math:`\\nabla \\mathcal{L}(\\hat{y}, y)` ''' - r = self.residual(yhat,weighting_applied) + r = self.residual(yhat, apply_weighting) return -r/self._sigma2 - def diff2Loss(self, yhat): + def diff2Loss(self, yhat, apply_weighting=True): ''' Twice derivative of the normal loss. @@ -275,6 +278,11 @@ def diff2Loss(self, yhat): ---------- yhat: array like observations + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. Returns ------- @@ -299,7 +307,7 @@ class Gamma(baseloss_type): ''' def __init__(self, y, shape=2.0, weights=None): - super().__init__(y, weights=None) + super().__init__(y, weights) err_str = "Shape is not of the correct " if isinstance(shape, np.ndarray): if np.any(shape<0): @@ -327,7 +335,7 @@ def __init__(self, y, shape=2.0, weights=None): raise TypeError(err_str + "type") self.loss(self._y) - def loss(self, yhat): + def loss(self, yhat, apply_weighting=True): ''' The loss under a gamma distribution. Defined as the negative log-likelihood of the gamma distirbution in terms of mean and shape. @@ -338,7 +346,11 @@ def loss(self, yhat): ---------- yhat: array like prediction - + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. Returns ------- @@ -351,7 +363,7 @@ def loss(self, yhat): return -gamma_mu_shape(x=self._y, mu=yhat,shape=self._shape,log=True).sum() - def diff_loss(self, yhat,weighting_applied=True): + def diff_loss(self, yhat, apply_weighting=True): ''' Derivative of the loss function with respect to yhat which is See: @@ -361,7 +373,7 @@ def diff_loss(self, yhat,weighting_applied=True): ---------- yhat: array like prediction - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -372,10 +384,10 @@ def diff_loss(self, yhat,weighting_applied=True): ''' shape = self._shape - r = self.residual(yhat,weighting_applied) + r = self.residual(yhat, apply_weighting) return shape*-r/yhat**2 - def diff2Loss(self, yhat,weighting_applied=True): + def diff2Loss(self, yhat, apply_weighting=True): ''' Twice derivative of the loss function with respect to yhat. See: @@ -385,7 +397,7 @@ def diff2Loss(self, yhat,weighting_applied=True): ---------- yhat: array like observation - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -401,7 +413,7 @@ def diff2Loss(self, yhat,weighting_applied=True): yhat = yhat.ravel() y = self._y shape = self._shape - r = self.residual(yhat,weighting_applied) + r = self.residual(yhat, apply_weighting) return shape*(r+y)/yhat**3 class Poisson(baseloss_type): @@ -415,10 +427,10 @@ class Poisson(baseloss_type): ''' def __init__(self, y, weights=None): - super().__init__(y, weights=None) + super().__init__(y, weights) self.loss(self._y) - def loss(self, yhat): + def loss(self, yhat,apply_weighting=True): ''' The loss under a normal distribution. Defined as the negative log-likelihood here. @@ -427,6 +439,11 @@ def loss(self, yhat): ---------- yhat: array like observation + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. Returns ------- @@ -439,7 +456,7 @@ def loss(self, yhat): # note that we input the standard deviation here return (-dpois(self._y, yhat, True)).sum() - def diff_loss(self, yhat,weighting_applied=True): + def diff_loss(self, yhat, apply_weighting=True): ''' Derivative of the loss function, :math:`1 - y\\hat{y}^{-1}` @@ -447,7 +464,7 @@ def diff_loss(self, yhat,weighting_applied=True): ---------- yhat: array like observation - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -461,10 +478,10 @@ def diff_loss(self, yhat,weighting_applied=True): if 1 in yhat.shape: yhat = yhat.ravel() - r = self.residual(yhat,weighting_applied) + r = self.residual(yhat, apply_weighting) return -r/yhat - def diff2Loss(self, yhat): + def diff2Loss(self, yhat, apply_weighting=True): ''' Twice derivative of the Poisson loss. @@ -472,6 +489,11 @@ def diff2Loss(self, yhat): ---------- yhat: array like observations + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. Returns ------- @@ -497,7 +519,7 @@ class NegBinom(baseloss_type): ''' def __init__(self, y, k=1.0, weights=None): - super().__init__(y, weights=None) + super().__init__(y, weights) err_str = "k (the overdispersion parameter) is not of the correct " if isinstance(k, np.ndarray): if np.any(k<0): @@ -526,7 +548,7 @@ def __init__(self, y, k=1.0, weights=None): self.loss(self._y) - def loss(self, yhat): + def loss(self, yhat, apply_weighting=True): ''' The loss under a Negative Binomial distribution. Defined as the negative log-likelihood of the Negative Binomial 2 distribution. @@ -535,6 +557,11 @@ def loss(self, yhat): ---------- yhat: array like observation + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. Returns ------- @@ -547,7 +574,7 @@ def loss(self, yhat): return (-dnbinom(self._y, mu=yhat,size=self._k,log=True)).sum() - def diff_loss(self, yhat,weighting_applied=True): + def diff_loss(self, yhat, apply_weighting=True): ''' Derivative of the loss function with respect to yhat which is See: @@ -558,11 +585,13 @@ def diff_loss(self, yhat,weighting_applied=True): ---------- yhat: array like observation + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. - k: array like - observation - - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -577,11 +606,11 @@ def diff_loss(self, yhat,weighting_applied=True): yhat = yhat.ravel() k = self._k - r = self.residual(yhat,weighting_applied) + r = self.residual(yhat, apply_weighting) first_derivs_yhat = k*-r/(yhat*(k+yhat)) return first_derivs_yhat - def diff2Loss(self, yhat,weighting_applied=True): + def diff2Loss(self, yhat, apply_weighting=True): ''' Twice derivative of the loss function with respect to yhat. See: @@ -592,11 +621,13 @@ def diff2Loss(self, yhat,weighting_applied=True): ---------- yhat: array like observation - - k: array like - observation + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. - weighting_applied: boolean + apply_weighting: boolean If True multiplies array of residuals by weightings, else raw residuals are used. @@ -611,7 +642,7 @@ def diff2Loss(self, yhat,weighting_applied=True): yhat = yhat.ravel() k = self._k - r = self.residual(yhat,weighting_applied) + r = self.residual(yhat, apply_weighting) scnd_derivs_yhat_p1= k scnd_derivs_yhat_p2= yhat**(-2) scnd_derivs_yhat_p3= (k + yhat)**(-2) diff --git a/pygom/model/ode_utils/checks_and_conversions.py b/pygom/model/ode_utils/checks_and_conversions.py index 9a2a06db..b9817d85 100644 --- a/pygom/model/ode_utils/checks_and_conversions.py +++ b/pygom/model/ode_utils/checks_and_conversions.py @@ -4,12 +4,10 @@ @author: edwin.tye ''' import numpy as np -from numbers import Number -from pygom.model._model_errors import InputError, ArrayError -def check_array_type(x): +def check_array_type(x,accept_booleans=False): ''' Check to see if the type of input is suitable. Only operate on one or two dimension arrays @@ -18,32 +16,52 @@ def check_array_type(x): ---------- x: array like which can be either a :class:`numpy.ndarray` or list or tuple + accept_boolean: boolean + If true boolean elements are accepted, else they are not. Returns ------- x: :class:`numpy.ndarray` checked and converted array ''' - + accepted_types = (int,float,complex) + if accept_booleans==True: + type_error_message = 'Expecting elements/sub-elements to be of type float, int, complex or boolean' + if accept_booleans==False: + type_error_message = 'Expecting elements/sub-elements to be of type float, int or complex' + + if isinstance(x, np.ndarray): pass elif isinstance(x, (list, tuple)): - if isinstance(x[0], Number): - x = np.array(x) + if all(isinstance(item, accepted_types) for item in x): + if accept_booleans==True: + x = np.array(x) + elif accept_booleans==False and all(not isinstance(item, bool) for item in x): + x = np.array(x) + else: + TypeError(type_error_message) elif isinstance(x[0], (list, tuple, np.ndarray)): - if isinstance(x[0][0], Number): + sub_items_accepted = [] + for item in x: + if accept_booleans==False: + sub_items_accepted.append(all(isinstance(sub_item, accepted_types) for sub_item in item)*all(not isinstance(sub_item, bool) for sub_item in item)) + if accept_booleans==True: + sub_items_accepted.append(all(isinstance(sub_item, accepted_types) for sub_item in item)) + if all(sub_items_accepted): x = np.array(x) else: - raise ArrayError("Expecting elements of float or int") + raise TypeError(type_error_message) else: - raise ArrayError("Expecting elements of float or int") - elif isinstance(x, Number): + raise TypeError(type_error_message) + elif isinstance(x, accepted_types): x = np.array([x]) else: - raise ArrayError("Expecting an array like object, got %s" % type(x)) + raise TypeError("Expecting an array like object, got %s" % type(x)) return x + def check_dimension(x, y): ''' Compare the length of two array like objects. Converting both to a numpy diff --git a/tests/test_loss_types.py b/tests/test_loss_types.py index c0345fa3..c4d7fc88 100644 --- a/tests/test_loss_types.py +++ b/tests/test_loss_types.py @@ -27,7 +27,7 @@ def setUp(self): self.t[1::], self.solution[1::,:], ['V', 'R']) self.r = obj.residual() - def test_FH_Square_scalar_weight(self): + def test_FH_scalar_weights_for_two_states(self): # weight for each component w = [2.0, 3.0] @@ -39,10 +39,10 @@ def test_FH_Square_scalar_weight(self): self.assertTrue(np.allclose(obj.cost(), s)) - def test_FH_Square_vector_weight(self): + def test_FH_vector_weights_for_two_states(self): # now the weight is a vector w = np.random.rand(29, 2) - obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], + obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], self.t[1::], self.solution[1::,:], ['V', 'R'], w) s = ((self.r * np.array(w))**2).sum() @@ -50,133 +50,176 @@ def test_FH_Square_vector_weight(self): self.assertTrue(np.allclose(obj.cost(), s)) - def test_FH_Square_1State_Fail(self): - ## totalFail = 0 - ## expectedFail = 4 + def test_FH_1State_weights_Failures_TypeErrors(self): w_list = list() - - w_list.append([-1.]) - w_list.append([0]) - w_list.append([2.0, 3.0]) - w_list.append(np.random.rand(30)) - + w_list.append(['a']) + w_list.append([True]) + test_weight=np.ones(len(self.solution[1::,-1])) + test_weight[-1]=False + w_list.append(test_weight) for w in w_list: - self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,:], - 'R', w) - - def test_FH_Square_2State_Fail(self): - ## totalFail = 0 - ## expectedFail = 8 + with self.subTest('Weightings',w=w): + self.assertRaises(TypeError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', w) + + def test_FH_1State_weights_Failures_ValueErrors(self): w_list = list() - - w_list.append([-2.0]) - w_list.append([2.0, 3.0, 4.0]) - w_list.append([0.0, 0.0]) - w_list.append([1.0, -1.0]) - w_list.append(np.random.rand(30)) - w_list.append([np.random.rand(30), np.random.rand(31)]) - w_list.append([np.random.rand(31), np.random.rand(31)]) - w_list.append([np.random.rand(30), np.random.rand(30), np.random.rand(30)]) - + test_weight=np.ones(len(self.solution[1::,-1])) + w_list.append(-test_weight) + test_weight[-1]=-1 + w_list.append(test_weight) + w_list.append(np.zeros(len(self.solution[1::,-1]))) for w in w_list: - self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,:], - 'R', w) - -class Test_Normal_loss_class(TestCase): - - def setUp(self): - # initial values - self.x0 = [-1.0, 1.0] - # params - self.param_eval = [('a', 0.2), ('b', 0.2),('c', 3.0)] - # the time points for our observations - self.t = np.linspace(0, 20, 30).astype('float64') - self.ode = common_models.FitzHugh(self.param_eval) - self.ode.initial_values = (self.x0, self.t[0]) - - # Standard. Find the solution which we will be used as - # "observations later" - self.solution = self.ode.integrate(self.t[1::]) - # initial guess - self.theta = [0.5, 0.5, 0.5] - - obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R']) - self.r = obj.residual() - - def test_FH_Normal_scalar_weight(self): - # weight for each component - w = [2.0, 3.0] - - s = 0 - for i in range(2): s += ((self.r[:,i]*w[i])**2).sum() - - obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R'], w) - - self.assertTrue(np.allclose(obj.cost(), s)) - - def test_FH_Normal_vector_weight(self): - # now the weight is a vector - w = np.random.rand(29, 2) - obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R'], w) - - s = ((self.r * np.array(w))**2).sum() - - self.assertTrue(np.allclose(obj.cost(), s)) - - def test_FH_Normal(self): - objFH = NormalLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R']) - - w = [2.0, 3.0] - objFH1 = NormalLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R'], w) - - # now the weight is a vector - w = np.random.rand(29, 2) - objFH2 = NormalLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R'], w) - - self.assertFalse(np.allclose(objFH.cost(), objFH1.cost())) - self.assertFalse(np.allclose(objFH1.cost(), objFH2.cost())) - - def test_FH_Normal_1State_Fail(self): - ## totalFail = 0 - ## expectedFail = 4 - w_list = list() - - w_list.append([-1.]) - w_list.append([0]) + with self.subTest('Weightings',w=w): + self.assertRaises(ValueError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', w) + + def test_FH_1State_weights_Failures_ShapeErrors(self): + w_list = list() w_list.append([2.0, 3.0]) w_list.append(np.random.rand(30)) - for w in w_list: - self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,:], - 'R', w) + with self.subTest('Weightings',w=w): + self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', w) - def test_FH_Normal_2State_Fail(self): - ## totalFail = 0 - ## expectedFail = 8 + def test_FH_2State_weights_Failures_TypeErrors(self): w_list = list() - - w_list.append([-2.0]) - w_list.append([2.0, 3.0, 4.0]) - w_list.append([0.0, 0.0]) + w_list.append(['a','b']) + w_list.append([True,False]) + test_weight=np.ones(self.solution[1::,:].shape) + test_weight[-1,-1]=False + w_list.append(test_weight) + for w in w_list: + with self.subTest('Weightings',w=w): + self.assertRaises(TypeError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,:], + ['V', 'R'], w) + + def test_FH_2State_weights_Failures_ValueErrors(self): + w_list = list() + test_weight=np.ones(self.solution[1::,:].shape) + w_list.append(-test_weight) + test_weight[-1,-1]=-1 + w_list.append(test_weight) + w_list.append(np.zeros(self.solution[1::,:].shape)) w_list.append([1.0, -1.0]) + w_list.append([0, 0]) + for w in w_list: + with self.subTest('Weightings',w=w): + self.assertRaises(ValueError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,:], + ['V', 'R'], w) + + def test_FH_2State_weights_Failures_ShapeErrors(self): + w_list = list() + w_list.append([2.0, 3.0, 4.0]) w_list.append(np.random.rand(30)) w_list.append([np.random.rand(30), np.random.rand(31)]) w_list.append([np.random.rand(31), np.random.rand(31)]) w_list.append([np.random.rand(30), np.random.rand(30), np.random.rand(30)]) - for w in w_list: - self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,:], - 'R', w) + with self.subTest('Weightings',w=w): + self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, + self.x0, self.t[0], self.t[1::], self.solution[1::,:], + ['V', 'R'], w) + +# class Test_Normal_loss_class(TestCase): + +# def setUp(self): +# # initial values +# self.x0 = [-1.0, 1.0] +# # params +# self.param_eval = [('a', 0.2), ('b', 0.2),('c', 3.0)] +# # the time points for our observations +# self.t = np.linspace(0, 20, 30).astype('float64') +# self.ode = common_models.FitzHugh(self.param_eval) +# self.ode.initial_values = (self.x0, self.t[0]) + +# # Standard. Find the solution which we will be used as +# # "observations later" +# self.solution = self.ode.integrate(self.t[1::]) +# # initial guess +# self.theta = [0.5, 0.5, 0.5] + +# obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], +# self.t[1::], self.solution[1::,:], ['V', 'R']) +# self.r = obj.residual() + +# def test_FH_Normal_scalar_weight(self): +# # weight for each component +# w = [2.0, 3.0] + +# s = 0 +# for i in range(2): s += ((self.r[:,i]*w[i])**2).sum() + +# obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], +# self.t[1::], self.solution[1::,:], ['V', 'R'], w) + +# self.assertTrue(np.allclose(obj.cost(), s)) + +# def test_FH_Normal_vector_weight(self): +# # now the weight is a vector +# w = np.random.rand(29, 2) +# obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], +# self.t[1::], self.solution[1::,:], ['V', 'R'], w) + +# s = ((self.r * np.array(w))**2).sum() + +# self.assertTrue(np.allclose(obj.cost(), s)) + +# def test_FH_Normal(self): +# objFH = NormalLoss(self.theta, self.ode, self.x0, self.t[0], +# self.t[1::], self.solution[1::,:], ['V', 'R']) + +# w = [2.0, 3.0] +# objFH1 = NormalLoss(self.theta, self.ode, self.x0, self.t[0], +# self.t[1::], self.solution[1::,:], ['V', 'R'], w) + +# # now the weight is a vector +# w = np.random.rand(29, 2) +# objFH2 = NormalLoss(self.theta, self.ode, self.x0, self.t[0], +# self.t[1::], self.solution[1::,:], ['V', 'R'], w) + +# self.assertFalse(np.allclose(objFH.cost(), objFH1.cost())) +# self.assertFalse(np.allclose(objFH1.cost(), objFH2.cost())) + +# def test_FH_Normal_1State_Fail(self): +# ## totalFail = 0 +# ## expectedFail = 4 +# w_list = list() + +# w_list.append([-1.]) +# w_list.append([0]) +# w_list.append([2.0, 3.0]) +# w_list.append(np.random.rand(30)) + +# for w in w_list: +# self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, +# self.x0, self.t[0], self.t[1::], self.solution[1::,:], +# 'R', w) + +# def test_FH_Normal_2State_Fail(self): +# ## totalFail = 0 +# ## expectedFail = 8 +# w_list = list() + +# w_list.append([-2.0]) +# w_list.append([2.0, 3.0, 4.0]) +# w_list.append([0.0, 0.0]) +# w_list.append([1.0, -1.0]) +# w_list.append(np.random.rand(30)) +# w_list.append([np.random.rand(30), np.random.rand(31)]) +# w_list.append([np.random.rand(31), np.random.rand(31)]) +# w_list.append([np.random.rand(30), np.random.rand(30), np.random.rand(30)]) + +# for w in w_list: +# self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, +# self.x0, self.t[0], self.t[1::], self.solution[1::,:], +# 'R', w) if __name__ == '__main__': From 9708ace03726b7e6e9007ff71bf2f771976c87d9 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Tue, 30 Jun 2020 17:11:26 +0100 Subject: [PATCH 10/16] Square loss and residuals Weights Unit tested ok --- ...s functions fitted to simulated data.ipynb | 1707 +++++++---------- pygom/loss/loss_type.py | 31 +- tests/test_loss_types.py | 171 +- 3 files changed, 778 insertions(+), 1131 deletions(-) diff --git a/notebooks/Testing loss functions fitted to simulated data.ipynb b/notebooks/Testing loss functions fitted to simulated data.ipynb index 573ea491..150ab517 100644 --- a/notebooks/Testing loss functions fitted to simulated data.ipynb +++ b/notebooks/Testing loss functions fitted to simulated data.ipynb @@ -51,7 +51,7 @@ "source": [ "# initial conditions \n", "N = 1e6\n", - "in_inf = 2\n", + "in_inf = 1\n", "init_state = [N - in_inf, in_inf, 0.0]\n", "# time \n", "t = np.arange (0 , 51 , 0.25)\n", @@ -87,7 +87,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -125,6 +125,15 @@ "execution_count": 6, "metadata": {}, "outputs": [], + "source": [ + "np.random.seed(42)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], "source": [ "def runif_noise(x,noise_prop):\n", " '''\n", @@ -141,16 +150,16 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([9.99998e+05, 2.00000e+00, 0.00000e+00])" + "array([9.99999e+05, 1.00000e+00, 0.00000e+00])" ] }, - "execution_count": 7, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -161,227 +170,227 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - ":4: RuntimeWarning: invalid value encountered in true_divide\n", + ":4: RuntimeWarning: invalid value encountered in true_divide\n", " (noised_data-data)/data\n" ] }, { "data": { "text/plain": [ - "array([[ 0.00000000e+00, 0.00000000e+00, nan],\n", - " [-1.73465915e-01, -1.17281547e-01, -2.25860015e-02],\n", - " [ 2.18875989e-03, -1.41630417e-01, -1.20285204e-01],\n", - " [ 3.10984783e-01, -1.16333578e-01, 2.95271450e-01],\n", - " [-2.69029696e-01, -1.99213726e-01, -1.90606565e-01],\n", - " [ 1.35684509e-01, 1.78379344e-01, 1.80962883e-01],\n", - " [-8.77803140e-02, 2.49616076e-01, -3.00454033e-02],\n", - " [-3.04094678e-02, -3.10164909e-01, 6.59761925e-02],\n", - " [ 4.77262892e-02, -1.92819030e-01, -1.39817160e-01],\n", - " [ 1.70193324e-01, 1.94346231e-01, 2.65605367e-01],\n", - " [-1.07254972e-01, 3.92049280e-02, -4.60377530e-02],\n", - " [ 2.25368182e-01, 1.68391679e-01, 5.02529134e-02],\n", - " [-2.73480406e-02, -2.43459230e-01, -2.72124777e-01],\n", - " [ 3.25378306e-01, 3.11198994e-01, -3.19891929e-01],\n", - " [-3.02732680e-02, -7.38888142e-02, -1.42714821e-01],\n", - " [ 1.94084991e-01, -2.12622683e-01, -1.15964568e-01],\n", - " [ 2.48373612e-01, 2.61208788e-01, 2.24903683e-01],\n", - " [ 1.37001895e-01, -1.85852789e-01, -1.18528471e-01],\n", - " [ 1.95169073e-01, 2.33950828e-01, 2.61071600e-01],\n", - " [ 2.94426553e-01, 1.78731291e-01, 1.97572440e-01],\n", - " [ 1.04043589e-01, -1.48204811e-01, -2.49256282e-01],\n", - " [-2.09591210e-01, 1.27888057e-01, 4.29371010e-02],\n", - " [-1.43084416e-01, -2.20412193e-01, -3.25009447e-01],\n", - " [ 6.33522507e-02, 1.53844079e-02, 2.99794892e-01],\n", - " [ 2.11100728e-01, -1.74071212e-01, -2.25674301e-01],\n", - " [-2.14296968e-02, -2.65530317e-01, 3.25590647e-02],\n", - " [-1.62179509e-01, -2.81708892e-01, -3.75237265e-02],\n", - " [-1.09534418e-01, -2.96644636e-01, -1.46756635e-01],\n", - " [ 1.97785675e-01, 1.21368330e-01, -8.52835473e-02],\n", - " [ 6.19544052e-02, 2.56309699e-01, 6.11246356e-02],\n", - " [ 2.00808833e-01, -1.42135844e-01, -2.13179622e-01],\n", - " [-2.16077990e-01, -2.86104187e-01, -2.95618164e-01],\n", - " [ 3.21509098e-01, 2.54100768e-01, 1.48586067e-01],\n", - " [-1.77056121e-01, 3.14195690e-01, -7.89813198e-02],\n", - " [ 9.52571895e-02, -2.93934351e-01, 2.32526004e-01],\n", - " [ 3.25502678e-01, 2.31769642e-01, -1.07617135e-02],\n", - " [ 2.35964481e-01, -1.33138709e-01, -1.72244039e-01],\n", - " [-1.66454417e-01, 2.45896187e-02, 3.26641177e-01],\n", - " [ 1.84816860e-01, 2.32456914e-01, 1.99283036e-01],\n", - " [ 8.91630169e-02, -4.65652026e-02, -1.29383851e-02],\n", - " [ 4.91988839e-02, 7.28993711e-02, -6.48891682e-02],\n", - " [-7.55111005e-02, -3.01904206e-01, -5.57502552e-02],\n", - " [ 8.02339702e-03, -2.71726635e-01, -1.62495983e-02],\n", - " [-6.36690889e-02, -2.96569398e-01, -9.48426199e-02],\n", - " [-3.10261981e-01, 2.49488644e-02, 2.99644152e-01],\n", - " [ 1.45286030e-01, 3.06316140e-01, -7.45581102e-03],\n", - " [ 3.07300545e-01, -3.22020626e-01, 1.49929309e-01],\n", - " [ 1.40175328e-01, -1.85315900e-02, -1.02966849e-01],\n", - " [ 1.18323765e-01, 3.24544502e-03, -3.14290184e-01],\n", - " [-2.91429133e-01, 2.87166606e-01, 2.99142261e-02],\n", - " [-5.48979385e-02, 8.98441545e-02, 1.03955500e-01],\n", - " [ 3.04884296e-01, -1.37771353e-01, 1.01023789e-01],\n", - " [-1.33848241e-01, -1.11395555e-01, 4.99581753e-02],\n", - " [-3.78918481e-02, -3.23665755e-01, -1.47739901e-01],\n", - " [ 2.21314141e-01, 2.82572816e-01, 4.72580803e-02],\n", - " [ 5.22709247e-02, -3.23988777e-01, -3.31099138e-02],\n", - " [ 4.41287378e-04, 1.12372308e-01, 1.25004212e-01],\n", - " [ 7.91370306e-02, -1.43266719e-01, 5.20809368e-02],\n", - " [-2.71529409e-01, 9.58139850e-02, -4.10690930e-02],\n", - " [-7.58599886e-02, 2.11473953e-01, 6.59916787e-02],\n", - " [-1.98114673e-02, 3.25925174e-01, -1.88900522e-02],\n", - " [-2.15236733e-01, -6.61674151e-03, -7.97228069e-02],\n", - " [-8.52869474e-02, -4.54868991e-02, 1.81776124e-01],\n", - " [-3.17873872e-01, -5.00410695e-03, 2.74312022e-01],\n", - " [-2.56697406e-01, -2.52524664e-01, 8.48325600e-02],\n", - " [ 6.87283327e-02, 2.55013582e-01, -1.14591512e-01],\n", - " [-2.63254784e-01, 3.03913765e-01, -3.04301181e-01],\n", - " [ 2.49161251e-01, -1.57671710e-01, 8.75571120e-02],\n", - " [-1.98673502e-01, 2.14671912e-01, -1.89495051e-01],\n", - " [-4.59403003e-02, 2.04353868e-01, 2.27361836e-01],\n", - " [ 7.64131802e-02, 2.52120942e-01, -1.75540234e-01],\n", - " [-1.95232206e-01, 1.69610425e-02, -1.35020865e-01],\n", - " [-2.15817787e-01, 1.22040324e-01, -2.56928157e-01],\n", - " [-3.28443088e-01, 3.26392955e-01, 9.71235957e-02],\n", - " [ 6.52615418e-02, 1.62982784e-01, -2.77772468e-01],\n", - " [-1.06954476e-01, -1.82748624e-01, -2.30851985e-01],\n", - " [-1.03560258e-01, 2.49776694e-01, 2.39589555e-01],\n", - " [-2.51361697e-01, -2.62613604e-01, -3.43346629e-02],\n", - " [ 5.52044588e-02, 1.71414602e-01, -1.18827697e-01],\n", - " [ 2.04645160e-01, -1.57695147e-01, -7.46836992e-02],\n", - " [-2.54150013e-01, 2.00084150e-01, -2.77762288e-01],\n", - " [ 1.91226654e-01, -1.15839953e-01, 1.95446804e-01],\n", - " [ 3.25631354e-01, -1.55219633e-01, -1.36220152e-01],\n", - " [ 8.59434276e-02, 2.44324599e-01, -1.80598534e-01],\n", - " [-4.41759258e-02, 2.88086579e-01, 2.32770906e-01],\n", - " [-2.27196580e-01, 2.72331912e-01, -1.53109214e-01],\n", - " [ 1.47937296e-01, -1.28297016e-01, -2.28099160e-01],\n", - " [ 9.75527646e-02, 3.31250187e-01, 1.80018836e-01],\n", - " [-2.40869627e-03, -2.62345740e-01, -2.93019352e-01],\n", - " [ 1.42517039e-01, -3.26917253e-01, 3.24664042e-01],\n", - " [ 2.66350592e-01, -1.89474157e-01, -3.76501731e-02],\n", - " [ 3.00491876e-01, 7.70405853e-02, 1.38895227e-01],\n", - " [-2.24919571e-01, 1.38375653e-04, -1.22365187e-01],\n", - " [ 1.89472971e-01, -6.99390524e-02, 1.75359377e-01],\n", - " [ 2.40847084e-01, 2.17245088e-01, -1.29960940e-01],\n", - " [ 1.17031088e-01, 1.25207417e-01, -2.13111306e-01],\n", - " [-1.48790790e-01, 2.42009355e-01, -2.72889122e-01],\n", - " [-6.55964475e-03, -2.67211611e-01, -2.75637870e-01],\n", - " [-1.85542712e-01, -7.13208125e-02, -1.43045237e-01],\n", - " [ 2.14837170e-01, 3.09019053e-01, -1.03940169e-01],\n", - " [-2.08291133e-01, -1.55812903e-01, -2.71145936e-01],\n", - " [-1.55833854e-01, -2.88308172e-01, 2.45174658e-01],\n", - " [-3.11004925e-01, 1.66460354e-01, 1.48310637e-01],\n", - " [ 1.11900762e-01, 1.59711839e-01, -1.06092199e-01],\n", - " [ 2.52702535e-01, 2.63918522e-01, 8.81508771e-02],\n", - " [-2.96912130e-01, 2.00037590e-01, -1.35534414e-01],\n", - " [ 2.57644746e-01, 2.17801439e-01, -1.37936016e-01],\n", - " [-2.21287471e-02, 1.87488209e-01, 6.54050559e-02],\n", - " [-3.13781890e-01, 8.90421404e-02, -2.65601600e-03],\n", - " [ 1.73633876e-02, 4.70498687e-02, 1.99892821e-01],\n", - " [-1.75870723e-01, -2.34269032e-01, -1.44870264e-01],\n", - " [ 2.60912112e-01, 8.12053627e-02, 3.86306769e-02],\n", - " [ 2.07535825e-01, -2.98946883e-01, -2.94085800e-01],\n", - " [-2.28341327e-02, -1.05874587e-01, 3.06311986e-03],\n", - " [ 2.88008753e-01, 1.71295755e-01, -1.44628284e-03],\n", - " [-3.12911107e-01, -1.94018364e-01, 1.04187514e-01],\n", - " [-2.65559378e-01, 1.87606865e-01, -3.14186465e-01],\n", - " [ 3.12564575e-01, -1.41561571e-01, 2.97041688e-01],\n", - " [-1.61079637e-01, -6.04344631e-02, -3.16709214e-01],\n", - " [-9.79493115e-02, 2.56336113e-01, 2.40368610e-01],\n", - " [ 2.07487179e-01, 1.37615049e-01, 3.01609274e-01],\n", - " [ 2.98452807e-01, -1.98587552e-01, -9.27371231e-02],\n", - " [ 1.34487459e-01, 1.37004951e-01, -2.08067897e-01],\n", - " [-3.24649739e-01, 2.79299579e-01, 2.42697497e-01],\n", - " [ 1.48755627e-01, -2.56194465e-02, 2.16687251e-01],\n", - " [ 2.82086858e-01, -2.73028509e-01, 1.49601622e-01],\n", - " [-2.90566692e-01, -1.46843110e-01, -4.20095301e-02],\n", - " [-2.02395486e-01, 2.76415604e-01, 2.92878761e-01],\n", - " [ 1.29300728e-01, -2.25682761e-01, -1.39203475e-01],\n", - " [-2.94574241e-01, -1.60448086e-02, -1.33783822e-01],\n", - " [-1.80234848e-01, 1.27149669e-01, 3.46658132e-02],\n", - " [-3.28310685e-01, 2.48574245e-01, 1.82136367e-01],\n", - " [-2.24348578e-01, 7.15601086e-02, -1.00090791e-01],\n", - " [ 1.35871520e-01, 1.78353047e-01, 1.14648325e-01],\n", - " [-2.93504246e-02, -7.33876121e-02, 2.60776669e-01],\n", - " [-9.32936487e-02, 2.09428551e-02, -2.79570179e-01],\n", - " [ 6.37399122e-02, 2.17366633e-01, 3.02729114e-01],\n", - " [ 9.07693126e-02, 1.59002147e-01, 2.41856391e-02],\n", - " [ 3.29090325e-01, -1.17795784e-01, -2.89107948e-01],\n", - " [-3.24646432e-02, 1.63737182e-01, 2.09973144e-02],\n", - " [ 1.80119330e-01, -6.34746381e-02, 2.19125711e-01],\n", - " [-1.39888719e-01, -8.80666022e-02, -1.42371440e-01],\n", - " [ 3.31763098e-01, 8.68652514e-02, 3.15174893e-01],\n", - " [-2.97656020e-01, 8.69786170e-02, -3.21062047e-01],\n", - " [-5.32967716e-02, -3.10244442e-01, 5.49010428e-02],\n", - " [-5.42176967e-02, -7.62270050e-02, -5.57502908e-02],\n", - " [-8.98274483e-02, -1.12891073e-01, -1.41591575e-01],\n", - " [ 3.26933775e-02, 1.13416765e-01, 9.83869429e-02],\n", - " [-8.30560535e-02, -1.24896527e-01, -2.28530639e-02],\n", - " [-2.50228276e-01, 1.14537667e-02, -3.41017652e-03],\n", - " [-1.38776547e-01, -2.50449609e-01, -6.21100653e-02],\n", - " [ 1.44905560e-01, -2.75800643e-01, 2.65509337e-01],\n", - " [-3.20089696e-01, 3.27402651e-01, -1.72856493e-01],\n", - " [ 1.15474683e-01, -2.45068819e-01, -4.92954020e-02],\n", - " [ 2.05133386e-01, 3.27483684e-01, -1.93659902e-01],\n", - " [-2.17767265e-01, 8.70771976e-02, 1.87124947e-01],\n", - " [ 7.27246238e-02, -1.40465442e-01, -2.69193721e-01],\n", - " [-9.97701910e-03, 1.07729750e-01, -2.68065630e-01],\n", - " [ 3.03733136e-01, 3.22867206e-01, 1.49238218e-01],\n", - " [-2.78795783e-01, -1.14419874e-02, -7.20286782e-02],\n", - " [ 2.27085067e-01, 2.25468966e-03, 3.30907780e-01],\n", - " [ 8.96872448e-02, 1.61653251e-02, 1.85384909e-01],\n", - " [ 2.09636861e-02, 1.59974804e-01, -2.01092462e-01],\n", - " [ 2.89371780e-01, -1.56939225e-01, 3.21132503e-01],\n", - " [-1.60498331e-01, -1.18765721e-01, 1.13698025e-01],\n", - " [ 2.58419878e-01, -2.43509871e-01, -2.62146111e-01],\n", - " [-1.73732340e-01, 2.78540447e-01, -3.26039184e-01],\n", - " [-1.90956096e-02, -2.53887573e-01, -1.00832029e-01],\n", - " [ 1.90229262e-01, -1.72023628e-01, -2.31129213e-01],\n", - " [ 1.64831891e-01, 1.42491962e-01, -1.59541848e-01],\n", - " [-2.63697330e-01, 2.50564149e-01, 1.62164895e-01],\n", - " [-3.05547702e-01, 1.00183246e-01, 7.41942823e-02],\n", - " [ 4.07308835e-02, -2.31988517e-01, -3.25882263e-01],\n", - " [-1.53928260e-01, 2.11032128e-01, 2.48124476e-01],\n", - " [-4.75569094e-02, 1.11467076e-01, 1.61397329e-01],\n", - " [ 3.24990686e-01, -2.25966590e-01, 2.50815594e-01],\n", - " [-1.51945789e-01, 1.08083714e-01, -2.81320222e-01],\n", - " [-1.04216758e-01, -1.04818192e-01, 2.88203609e-01],\n", - " [-3.03459319e-01, 2.11989847e-01, -1.60581341e-01],\n", - " [ 1.34966390e-01, -1.17862102e-01, -2.43005916e-02],\n", - " [ 2.27585955e-01, 2.97513116e-01, 3.23156970e-01],\n", - " [ 1.01935503e-02, 2.84152144e-01, 2.22278818e-01],\n", - " [-1.39242592e-01, -9.10229412e-02, 3.25125351e-01],\n", - " [ 1.61950734e-01, -2.86648561e-01, -4.84271868e-02],\n", - " [-3.14874702e-01, 1.87709580e-01, 9.93054614e-02],\n", - " [ 1.88947588e-01, 1.83665135e-01, -1.59567842e-01],\n", - " [ 8.29825603e-02, 1.67331153e-01, 4.33415390e-02],\n", - " [-4.90594041e-02, -2.91446169e-01, -1.04161328e-01],\n", - " [ 1.60369798e-01, -1.49862405e-01, -2.93917315e-02],\n", - " [ 3.12709890e-01, -4.68877085e-02, -1.28360996e-01],\n", - " [ 2.49744887e-01, 3.28753915e-01, 2.21007900e-01],\n", - " [-9.28652790e-02, -6.89210427e-02, 2.25952258e-01],\n", - " [-2.44509281e-01, 3.04169434e-01, -2.59243410e-01],\n", - " [-2.23974760e-01, -3.15196226e-01, -9.50514355e-02],\n", - " [-8.94209698e-02, 2.46512550e-01, -2.44376339e-02],\n", - " [-1.88389365e-01, -6.98384260e-02, 2.25805610e-01],\n", - " [-1.12387378e-01, 1.24293193e-01, 2.60368640e-01],\n", - " [-7.04497617e-02, 1.72365737e-02, 1.95754470e-01],\n", - " [ 4.28703247e-02, -1.06070454e-01, -1.66811253e-01],\n", - " [ 1.76556407e-01, -1.65162532e-01, 9.66494270e-02],\n", - " [-2.20010409e-01, -4.73485568e-02, -1.48941583e-01],\n", - " [-2.12488717e-01, -5.77153871e-03, 2.86460630e-01],\n", - " [-2.66543889e-01, 3.10357896e-01, 9.10328100e-02],\n", - " [-1.77407989e-02, -2.32471504e-01, -2.99887659e-01]])" + "array([[ 0. , 0. , nan],\n", + " [ 0.06577232, -0.22932091, -0.22933699],\n", + " [-0.29461093, 0.24411743, 0.06741001],\n", + " [ 0.13871505, -0.31961034, 0.31327323],\n", + " [ 0.22162843, -0.19177393, -0.21211669],\n", + " [-0.21106366, -0.13050517, 0.01650429],\n", + " [-0.04536999, -0.13918057, 0.0745686 ],\n", + " [-0.24033743, -0.13857023, -0.0890921 ],\n", + " [-0.02928668, 0.19011731, -0.20021748],\n", + " [ 0.00948963, 0.06160971, -0.30236639],\n", + " [ 0.07169657, -0.21965058, -0.2899656 ],\n", + " [ 0.29925702, 0.31042136, 0.20559823],\n", + " [-0.13025749, -0.26821859, 0.12282202],\n", + " [-0.03989834, -0.25197451, -0.00321539],\n", + " [-0.31040765, 0.27288027, -0.16081335],\n", + " [ 0.10834819, -0.12552595, 0.01337868],\n", + " [ 0.03114019, -0.21009703, 0.31305642],\n", + " [ 0.18342188, 0.29299929, 0.26321823],\n", + " [ 0.06526665, 0.28124949, -0.27433833],\n", + " [-0.20267809, -0.30318181, -0.11644645],\n", + " [-0.07421514, -0.15243398, 0.21915834],\n", + " [-0.09549778, -0.14604366, 0.02846406],\n", + " [-0.23938385, 0.20146465, -0.2836329 ],\n", + " [ 0.32459129, 0.18149651, -0.20085621],\n", + " [-0.32965192, 0.21030762, 0.1379049 ],\n", + " [ 0.15267145, 0.1808469 , -0.28397023],\n", + " [-0.09435618, -0.25608729, 0.24206895],\n", + " [ 0.08219875, -0.11273465, -0.2909611 ],\n", + " [-0.12601179, -0.11654445, 0.15307079],\n", + " [ 0.09170498, 0.25814183, -0.01852338],\n", + " [-0.25360384, 0.14216319, 0.1738567 ],\n", + " [ 0.04085147, 0.18064479, -0.00413627],\n", + " [ 0.01515522, -0.04830599, -0.31638725],\n", + " [-0.26140572, -0.31238054, 0.09094027],\n", + " [-0.12376268, 0.00571379, 0.27171098],\n", + " [-0.16713851, -0.05974472, 0.17036743],\n", + " [-0.18080122, -0.28201339, -0.1401657 ],\n", + " [-0.22585248, 0.2864651 , 0.20541359],\n", + " [ 0.08893584, 0.24764039, 0.20244805],\n", + " [-0.20895329, 0.261706 , 0.02622816],\n", + " [ 0.2049601 , 0.26406087, -0.12133102],\n", + " [-0.25996538, -0.18137656, -0.04859481],\n", + " [ 0.21200984, 0.24048706, -0.32869858],\n", + " [ 0.00716487, -0.05505933, -0.18526146],\n", + " [-0.25342309, -0.10825655, 0.29527314],\n", + " [-0.11786471, 0.01252708, 0.13534597],\n", + " [-0.0909136 , 0.31452139, 0.3082982 ],\n", + " [-0.16547847, -0.00183433, -0.13274779],\n", + " [-0.14343967, -0.30874204, 0.07304289],\n", + " [ 0.00178602, -0.29901417, -0.14756902],\n", + " [ 0.27217726, -0.17362541, -0.23673675],\n", + " [-0.00703149, 0.32376697, -0.17196315],\n", + " [ 0.11475703, 0.17441308, -0.1749083 ],\n", + " [ 0.15214423, -0.08814458, 0.08820389],\n", + " [ 0.08901981, 0.02384979, -0.27314015],\n", + " [ 0.223535 , -0.11947996, -0.20898766],\n", + " [-0.30614991, 0.0605953 , 0.11837624],\n", + " [-0.32227478, 0.00806204, -0.18233615],\n", + " [ 0.09678186, -0.21708905, 0.12729183],\n", + " [-0.07550977, 0.29115333, -0.2416527 ],\n", + " [-0.10595577, -0.25768432, 0.28312908],\n", + " [ 0.25155957, -0.16137225, 0.10665603],\n", + " [ 0.21148147, 0.03680054, 0.01976705],\n", + " [-0.17209847, -0.27126482, 0.26481051],\n", + " [ 0.26694537, 0.0887343 , -0.10731347],\n", + " [-0.10052695, 0.15063712, 0.26474017],\n", + " [ 0.25805762, 0.1865837 , 0.09468776],\n", + " [-0.27724002, -0.22558086, 0.26570279],\n", + " [ 0.07095271, -0.32720197, -0.26568564],\n", + " [ 0.10900118, -0.32995894, -0.22612797],\n", + " [ 0.03248919, 0.12793013, 0.10130751],\n", + " [-0.18382046, 0.14145281, -0.17516728],\n", + " [-0.1164002 , 0.1643276 , 0.09975527],\n", + " [ 0.23281561, 0.10507526, 0.04553907],\n", + " [-0.27088349, -0.08818946, -0.15653175],\n", + " [-0.17067357, 0.31534037, -0.07126818],\n", + " [ 0.26136437, 0.08742575, 0.19654087],\n", + " [ 0.00175806, 0.05126926, -0.0049882 ],\n", + " [-0.20317134, 0.14830141, -0.14615176],\n", + " [-0.31712269, 0.09698153, -0.21525955],\n", + " [ 0.29363906, 0.30261905, 0.27657626],\n", + " [-0.08656087, -0.32302892, 0.28554571],\n", + " [-0.04787723, 0.31110321, 0.30907998],\n", + " [ 0.23533964, -0.13703407, -0.07660151],\n", + " [ 0.23409111, -0.122052 , -0.22033817],\n", + " [ 0.03786751, 0.29076985, 0.13068653],\n", + " [ 0.04670745, -0.268549 , 0.07667148],\n", + " [ 0.32670257, -0.23994399, 0.01221977],\n", + " [ 0.25158205, 0.16051241, 0.13134383],\n", + " [ 0.13498939, -0.09367257, -0.13760544],\n", + " [ 0.20624077, 0.20674226, 0.24471488],\n", + " [ 0.2754937 , 0.0075616 , 0.00101086],\n", + " [ 0.19886345, 0.09997595, 0.13464458],\n", + " [ 0.19719511, 0.26000356, -0.10800323],\n", + " [-0.0829447 , -0.27067871, 0.05218676],\n", + " [-0.30937182, -0.02293465, 0.02842976],\n", + " [-0.14230583, 0.06055551, -0.31299983],\n", + " [-0.30843454, 0.21506704, -0.09320624],\n", + " [-0.24862632, 0.01482884, 0.1799957 ],\n", + " [-0.18945265, 0.08192698, -0.27643502],\n", + " [-0.29887885, 0.02090309, 0.02709008],\n", + " [ 0.09161993, 0.15072756, 0.31723472],\n", + " [ 0.0108669 , -0.11802902, 0.1967908 ],\n", + " [-0.1527785 , -0.04068572, -0.28102908],\n", + " [-0.31643284, 0.30843228, 0.22398675],\n", + " [ 0.13064947, -0.06069804, -0.21780379],\n", + " [-0.22904197, -0.16650473, 0.03281778],\n", + " [ 0.14306395, 0.10679825, -0.14671074],\n", + " [ 0.30324352, 0.15859794, 0.03623604],\n", + " [ 0.0744805 , -0.05359996, -0.16817934],\n", + " [-0.09601821, 0.17189741, -0.32373767],\n", + " [-0.25595157, -0.30266491, -0.3061808 ],\n", + " [ 0.23697372, 0.13577191, -0.01721745],\n", + " [-0.26811056, -0.00558942, -0.01768549],\n", + " [-0.21786542, -0.0440989 , -0.06766351],\n", + " [ 0.0772334 , 0.09006243, -0.30313066],\n", + " [-0.08359159, 0.08390661, 0.00209084],\n", + " [ 0.23765989, 0.10579575, -0.22471038],\n", + " [-0.2862875 , 0.09494619, -0.31565913],\n", + " [ 0.05718372, 0.29348683, 0.05031612],\n", + " [-0.07455338, 0.09552548, -0.02783141],\n", + " [ 0.03041119, 0.29430987, -0.07593157],\n", + " [ 0.30746038, 0.27023376, -0.20280591],\n", + " [-0.28709247, -0.266148 , -0.32118545],\n", + " [-0.27037136, 0.12200452, -0.28587423],\n", + " [-0.12068291, 0.22991687, -0.31781871],\n", + " [ 0.20964566, -0.14543015, -0.25455678],\n", + " [ 0.13115811, 0.0859619 , 0.25164801],\n", + " [ 0.15671403, 0.20232062, -0.14531028],\n", + " [-0.2150403 , 0.1670765 , 0.20455649],\n", + " [ 0.32700343, -0.05825488, -0.08532128],\n", + " [ 0.18427531, -0.10613097, 0.28717155],\n", + " [ 0.23894183, -0.04733732, 0.16724738],\n", + " [ 0.16969525, -0.26458409, 0.2683686 ],\n", + " [ 0.00350158, 0.21763831, -0.11996693],\n", + " [ 0.26368215, -0.07386555, -0.32610823],\n", + " [ 0.27025465, -0.27247555, -0.12045757],\n", + " [ 0.30004131, 0.30040476, 0.04895859],\n", + " [ 0.08789147, -0.03436965, -0.13785949],\n", + " [-0.11422364, 0.1150123 , 0.16824969],\n", + " [ 0.19438603, 0.19307876, -0.27252926],\n", + " [-0.0037198 , -0.29496083, 0.03301925],\n", + " [-0.03897967, 0.25846946, -0.09938999],\n", + " [-0.25528866, -0.23800555, 0.17434042],\n", + " [ 0.07881204, -0.26591822, -0.27726213],\n", + " [ 0.13397942, -0.28482466, 0.21457337],\n", + " [ 0.13749482, -0.27910081, -0.27677486],\n", + " [ 0.32442639, -0.08381947, -0.08623857],\n", + " [ 0.20853304, 0.29816572, 0.32400071],\n", + " [ 0.16891879, -0.08249361, -0.27766619],\n", + " [ 0.18476461, 0.03893617, -0.05051866],\n", + " [ 0.27090292, -0.25920168, -0.0049166 ],\n", + " [-0.32576424, -0.02089291, -0.29579782],\n", + " [-0.25412139, -0.2549825 , 0.09947353],\n", + " [ 0.16402992, 0.05557918, 0.30811503],\n", + " [-0.08341961, -0.14285861, 0.24573275],\n", + " [-0.18426944, 0.30881503, -0.32523035],\n", + " [ 0.31325255, -0.30456006, 0.26076208],\n", + " [ 0.01846741, 0.3286432 , -0.28413562],\n", + " [ 0.03590286, 0.31286836, 0.01539856],\n", + " [ 0.08626576, 0.13049913, -0.03030596],\n", + " [ 0.08503872, 0.05620954, 0.26743867],\n", + " [-0.30303575, -0.14602454, 0.30027432],\n", + " [ 0.26017586, -0.02956216, 0.0800884 ],\n", + " [-0.14841254, -0.20791923, -0.02420106],\n", + " [-0.09776518, 0.05577074, -0.28151024],\n", + " [ 0.31626321, 0.3241405 , 0.13210781],\n", + " [ 0.02406424, -0.12698159, 0.20919668],\n", + " [ 0.12315412, -0.22492204, 0.27395146],\n", + " [ 0.21502483, 0.29986661, 0.15047967],\n", + " [ 0.07561013, -0.05450464, 0.28848566],\n", + " [ 0.24404259, -0.30318755, -0.31575535],\n", + " [-0.08235776, 0.20703555, 0.32485075],\n", + " [-0.23305541, 0.06275381, -0.0794061 ],\n", + " [ 0.31327627, 0.22807928, 0.22555247],\n", + " [-0.02087123, -0.056787 , -0.15106195],\n", + " [-0.29574967, 0.24314825, 0.20860067],\n", + " [ 0.33314512, 0.33109122, 0.03695447],\n", + " [ 0.17932494, 0.29651049, 0.23309826],\n", + " [-0.1684346 , -0.03297058, -0.24722706],\n", + " [ 0.30270068, 0.07078309, -0.1809048 ],\n", + " [ 0.11446712, 0.07875216, -0.09455819],\n", + " [-0.25762827, 0.11438213, 0.01353847],\n", + " [ 0.18154559, 0.01344233, 0.23478767],\n", + " [ 0.03460456, 0.04062531, 0.2511024 ],\n", + " [-0.06434476, -0.24398985, -0.31414488],\n", + " [ 0.1700915 , 0.08020637, 0.13605318],\n", + " [-0.19135723, -0.24241902, -0.32363689],\n", + " [-0.09960829, 0.05994512, -0.0718373 ],\n", + " [-0.04168339, 0.26943913, -0.10116302],\n", + " [ 0.00932633, 0.18910201, -0.06897148],\n", + " [ 0.08139113, 0.24157581, 0.29968042],\n", + " [-0.23528435, 0.28439175, -0.0052558 ],\n", + " [-0.16117041, -0.02724283, 0.32002172],\n", + " [-0.00492127, -0.11416559, 0.0889339 ],\n", + " [-0.17323625, -0.28275778, -0.24741352],\n", + " [-0.24796944, -0.23206487, -0.24078188],\n", + " [ 0.0939165 , -0.21207994, -0.10288848],\n", + " [ 0.26452561, -0.01735891, 0.11170516],\n", + " [-0.21845342, -0.20514065, -0.30608759],\n", + " [-0.22070996, -0.14760644, -0.21532634],\n", + " [-0.27419831, -0.25290942, -0.02614749],\n", + " [-0.19577752, -0.09048676, 0.00227818],\n", + " [ 0.12692989, -0.30712524, 0.19960693]])" ] }, - "execution_count": 8, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -395,12 +404,12 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -430,268 +439,252 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[4.13048703e+00, 1.54045618e-01],\n", - " [9.39724796e+00, 4.63032787e-01],\n", - " [2.26338241e+01, 1.79920071e+00],\n", - " [4.79865867e+01, 2.75795293e+00],\n", - " [1.65196042e+02, 9.60054641e+00],\n", - " [4.09779333e+02, 1.85994178e+01],\n", - " [5.28999484e+02, 4.79801484e+01],\n", - " [1.44654291e+03, 9.06680768e+01],\n", - " [4.99428771e+03, 3.11892868e+02],\n", - " [1.01035804e+04, 5.48460859e+02],\n", - " [2.61947362e+04, 1.40265491e+03],\n", - " [3.83891964e+04, 2.23685907e+03],\n", - " [1.44615604e+05, 4.71073992e+03],\n", - " [2.04841144e+05, 1.28298259e+04],\n", - " [3.04860240e+05, 2.65146845e+04],\n", - " [7.15472624e+05, 6.60639061e+04],\n", - " [5.70803649e+05, 7.57376290e+04],\n", - " [9.47231329e+05, 1.54986248e+05],\n", - " [9.23953166e+05, 1.93822492e+05],\n", - " [6.57801248e+05, 1.50769939e+05],\n", - " [8.43171264e+05, 2.49113150e+05],\n", - " [5.59341253e+05, 1.85957381e+05],\n", - " [6.96237265e+05, 4.03687883e+05],\n", - " [5.40067509e+05, 2.66418801e+05],\n", - " [4.57478544e+05, 3.88221974e+05],\n", - " [4.25920143e+05, 3.91122618e+05],\n", - " [3.96908285e+05, 3.71414788e+05],\n", - " [6.02102705e+05, 4.23352098e+05],\n", - " [6.41769739e+05, 5.18903098e+05],\n", - " [4.16901641e+05, 4.04368759e+05],\n", - " [3.30039331e+05, 3.78696731e+05],\n", - " [5.51529415e+05, 6.43412007e+05],\n", - " [5.49787782e+05, 5.35688557e+05],\n", - " [2.80979529e+05, 7.42016812e+05],\n", - " [4.66284359e+05, 6.14750052e+05],\n", - " [3.12148206e+05, 5.29680965e+05],\n", - " [3.50953671e+05, 8.72215875e+05],\n", - " [4.01568191e+05, 8.08517365e+05],\n", - " [2.95505559e+05, 6.81129851e+05],\n", - " [3.16315375e+05, 6.59415810e+05],\n", - " [1.95777449e+05, 6.79437421e+05],\n", - " [1.94280033e+05, 7.21315446e+05],\n", - " [1.78501110e+05, 6.75465168e+05],\n", - " [2.47404532e+05, 9.85931509e+05],\n", - " [2.99943485e+05, 7.64644995e+05],\n", - " [1.48078919e+05, 8.98769907e+05],\n", - " [2.03910050e+05, 7.10664811e+05],\n", - " [1.98269087e+05, 5.50194199e+05],\n", - " [2.41973630e+05, 8.36300844e+05],\n", - " [1.94887109e+05, 9.06544564e+05],\n", - " [1.46665030e+05, 9.13739364e+05],\n", - " [1.43779842e+05, 8.80070344e+05],\n", - " [1.04096536e+05, 7.21086105e+05],\n", - " [1.87776956e+05, 8.93932501e+05],\n", - " [9.41454910e+04, 8.32234831e+05],\n", - " [1.47360515e+05, 9.75970111e+05],\n", - " [1.07959767e+05, 9.19504617e+05],\n", - " [1.31352538e+05, 8.43986082e+05],\n", - " [1.38134142e+05, 9.44445525e+05],\n", - " [1.43810730e+05, 8.74698002e+05],\n", - " [1.02488333e+05, 8.25331196e+05],\n", - " [9.36752361e+04, 1.06579735e+06],\n", - " [9.28858373e+04, 1.15535109e+06],\n", - " [6.63758943e+04, 9.88499224e+05],\n", - " [1.06010101e+05, 8.10618603e+05],\n", - " [1.04769047e+05, 6.39799600e+05],\n", - " [6.43799763e+04, 1.00443399e+06],\n", - " [8.83107785e+04, 7.51578437e+05],\n", - " [8.32902438e+04, 1.14248035e+06],\n", - " [8.23704800e+04, 7.70222834e+05],\n", - " [6.36377665e+04, 8.10851809e+05],\n", - " [6.67889123e+04, 6.98840815e+05],\n", - " [7.51023290e+04, 1.03500279e+06],\n", - " [6.26382732e+04, 6.83328316e+05],\n", - " [4.18704321e+04, 7.29742044e+05],\n", - " [6.09073205e+04, 1.17917865e+06],\n", - " [3.41835753e+04, 9.20899230e+05],\n", - " [5.16557040e+04, 8.42315342e+05],\n", - " [3.53315137e+04, 8.86502740e+05],\n", - " [4.78839456e+04, 6.93420051e+05],\n", - " [3.35578712e+04, 1.15007416e+06],\n", - " [3.04994928e+04, 8.32594383e+05],\n", - " [4.27334325e+04, 7.91261007e+05],\n", - " [4.20789053e+04, 1.19249901e+06],\n", - " [3.95371249e+04, 8.20574024e+05],\n", - " [2.57666812e+04, 7.49084192e+05],\n", - " [3.74313007e+04, 1.14683974e+06],\n", - " [1.97293773e+04, 6.88071653e+05],\n", - " [1.71243567e+04, 1.29096233e+06],\n", - " [1.96154357e+04, 9.39060095e+05],\n", - " [2.47941056e+04, 1.11267717e+06],\n", - " [2.19008895e+04, 8.58416469e+05],\n", - " [1.93730659e+04, 1.15087675e+06],\n", - " [2.41184982e+04, 8.52800084e+05],\n", - " [2.12075306e+04, 7.72057664e+05],\n", - " [2.22673055e+04, 7.14074890e+05],\n", - " [1.24970257e+04, 7.12008791e+05],\n", - " [1.50653450e+04, 8.43052938e+05],\n", - " [2.01996861e+04, 8.82232568e+05],\n", - " [1.23914648e+04, 7.18155510e+05],\n", - " [9.93713520e+03, 1.22778864e+06],\n", - " [1.54926063e+04, 1.13305907e+06],\n", - " [1.46517627e+04, 8.82614181e+05],\n", - " [1.51895234e+04, 1.07507367e+06],\n", - " [1.37184550e+04, 8.54583269e+05],\n", - " [1.32425652e+04, 8.52689748e+05],\n", - " [1.22831633e+04, 1.05438468e+06],\n", - " [1.07154617e+04, 9.87530754e+05],\n", - " [9.79983700e+03, 1.18866243e+06],\n", - " [6.81730901e+03, 8.47516493e+05],\n", - " [9.15651565e+03, 1.02983470e+06],\n", - " [5.64752625e+03, 7.00227501e+05],\n", - " [6.85158508e+03, 9.95376740e+05],\n", - " [8.53777034e+03, 9.91275075e+05],\n", - " [5.58841086e+03, 1.09653142e+06],\n", - " [7.83287441e+03, 6.81290232e+05],\n", - " [5.38570917e+03, 1.28890423e+06],\n", - " [5.60720078e+03, 6.79212987e+05],\n", - " [7.13198062e+03, 1.23332725e+06],\n", - " [6.14306233e+03, 1.29458063e+06],\n", - " [4.11652692e+03, 9.02602625e+05],\n", - " [5.55549183e+03, 7.88062650e+05],\n", - " [5.94590131e+03, 1.23692169e+06],\n", - " [4.30783767e+03, 1.21130813e+06],\n", - " [3.05726711e+03, 1.14476697e+06],\n", - " [3.41295207e+03, 9.54158128e+05],\n", - " [4.85711821e+03, 1.28795897e+06],\n", - " [2.80279142e+03, 8.57680691e+05],\n", - " [3.38791460e+03, 8.63233644e+05],\n", - " [3.69167961e+03, 1.03127702e+06],\n", - " [3.88993254e+03, 1.17845340e+06],\n", - " [3.17562723e+03, 8.97242264e+05],\n", - " [3.32180160e+03, 1.11150609e+06],\n", - " [2.48474397e+03, 1.25739583e+06],\n", - " [2.60417556e+03, 7.18592169e+05],\n", - " [2.95376202e+03, 1.29956821e+06],\n", - " [2.67499903e+03, 1.02182178e+06],\n", - " [1.93684024e+03, 7.09331309e+05],\n", - " [2.43032785e+03, 1.01886507e+06],\n", - " [1.86043618e+03, 1.21670386e+06],\n", - " [1.72323155e+03, 8.56007932e+05],\n", - " [1.95362634e+03, 1.31281086e+06],\n", - " [1.85854073e+03, 6.77777078e+05],\n", - " [1.12184168e+03, 1.05318530e+06],\n", - " [1.42917993e+03, 9.42788835e+05],\n", - " [1.30552104e+03, 8.57145128e+05],\n", - " [1.55865489e+03, 1.09684931e+06],\n", - " [1.16529772e+03, 9.75845741e+05],\n", - " [1.28117604e+03, 9.95327460e+05],\n", - " [9.03127133e+02, 9.36759864e+05],\n", - " [8.30025571e+02, 1.26405888e+06],\n", - " [1.44717583e+03, 8.26241716e+05],\n", - " [7.82908962e+02, 9.49718646e+05],\n", - " [1.30953881e+03, 8.05544645e+05],\n", - " [1.02008145e+03, 1.18601097e+06],\n", - " [7.67225606e+02, 7.30153946e+05],\n", - " [9.40543417e+02, 7.31312893e+05],\n", - " [1.06843120e+03, 1.14831000e+06],\n", - " [7.59482468e+02, 9.27258372e+05],\n", - " [7.32451666e+02, 1.32993513e+06],\n", - " [7.06399734e+02, 1.18456086e+06],\n", - " [7.67043499e+02, 7.98379241e+05],\n", - " [5.30292644e+02, 1.32030148e+06],\n", - " [5.27270391e+02, 1.11303165e+06],\n", - " [4.30556895e+02, 7.37433928e+05],\n", - " [6.92192735e+02, 6.73595928e+05],\n", - " [3.84239599e+02, 8.98704896e+05],\n", - " [4.05602919e+02, 7.68494127e+05],\n", - " [5.32379794e+02, 8.40066501e+05],\n", - " [5.54318875e+02, 1.16164974e+06],\n", - " [4.63878241e+02, 1.07374135e+06],\n", - " [3.08029258e+02, 6.73847356e+05],\n", - " [4.62024710e+02, 1.24764828e+06],\n", - " [4.03358695e+02, 1.16097583e+06],\n", - " [2.67202064e+02, 1.25038378e+06],\n", - " [3.63863050e+02, 7.18443773e+05],\n", - " [2.79615932e+02, 1.28780121e+06],\n", - " [3.60109790e+02, 8.39169235e+05],\n", - " [2.49320339e+02, 9.75423630e+05],\n", - " [3.48833566e+02, 1.32280122e+06],\n", - " [3.28403876e+02, 1.22196622e+06],\n", - " [2.21121004e+02, 1.32480298e+06],\n", - " [1.65069144e+02, 9.51352605e+05],\n", - " [2.61431490e+02, 1.09906347e+06],\n", - " [2.47834507e+02, 8.40256177e+05],\n", - " [2.32494283e+02, 1.04313372e+06],\n", - " [1.34238266e+02, 8.95668938e+05],\n", - " [1.53206781e+02, 9.70433336e+05],\n", - " [1.63387233e+02, 8.71489570e+05],\n", - " [2.16672546e+02, 1.22080878e+06],\n", - " [1.44421258e+02, 1.22576208e+06],\n", - " [1.92426070e+02, 7.40647282e+05],\n", - " [9.61128200e+01, 9.04821540e+05],\n", - " [1.66416779e+02, 9.75432108e+05],\n", - " [1.18125629e+02, 1.22564992e+06],\n", - " [1.35815896e+02, 1.26021637e+06],\n", - " [1.16890245e+02, 1.19561705e+06],\n", - " [9.77113189e+01, 8.33097662e+05],\n", - " [8.68018133e+01, 1.09653539e+06],\n", - " [9.42206676e+01, 8.50974231e+05],\n", - " [9.35370396e+01, 1.28633958e+06],\n", - " [1.17266143e+02, 1.09093515e+06],\n", - " [6.53374982e+01, 7.00052732e+05]])" + "array([[1.80311437e+00, 6.07303299e-02],\n", + " [6.81020026e+00, 2.80913227e-01],\n", + " [8.71370750e+00, 9.12109018e-01],\n", + " [2.42169873e+01, 1.34235092e+00],\n", + " [6.09515924e+01, 4.13195572e+00],\n", + " [1.41167502e+02, 1.03036634e+01],\n", + " [3.30434916e+02, 2.05046119e+01],\n", + " [1.06747087e+03, 4.21719281e+01],\n", + " [2.22482987e+03, 8.60625179e+01],\n", + " [3.81422589e+03, 2.04668918e+02],\n", + " [1.48765175e+04, 8.10186678e+02],\n", + " [1.91106445e+04, 1.75057103e+03],\n", + " [4.39774187e+04, 3.56615139e+03],\n", + " [1.60839355e+05, 6.72761840e+03],\n", + " [2.17044554e+05, 1.73587509e+04],\n", + " [3.32782784e+05, 4.42793038e+04],\n", + " [7.71699789e+05, 7.49162385e+04],\n", + " [9.20245905e+05, 6.71030358e+04],\n", + " [5.39115320e+05, 1.14872807e+05],\n", + " [6.63856042e+05, 2.06130817e+05],\n", + " [6.56161244e+05, 2.13853805e+05],\n", + " [8.91814913e+05, 1.76033244e+05],\n", + " [8.40842445e+05, 2.25430023e+05],\n", + " [8.22754076e+05, 3.60576445e+05],\n", + " [7.65299910e+05, 2.50661953e+05],\n", + " [4.59188090e+05, 4.74099529e+05],\n", + " [5.21338606e+05, 2.91994510e+05],\n", + " [4.93992370e+05, 5.07905133e+05],\n", + " [6.69362638e+05, 4.59090307e+05],\n", + " [5.78114721e+05, 5.79537815e+05],\n", + " [5.68504538e+05, 5.16246775e+05],\n", + " [4.35938773e+05, 3.70433217e+05],\n", + " [2.99626522e+05, 6.15526472e+05],\n", + " [4.16873583e+05, 7.44546487e+05],\n", + " [3.70740213e+05, 7.08873040e+05],\n", + " [2.69297057e+05, 5.37322869e+05],\n", + " [4.58989639e+05, 7.75330500e+05],\n", + " [4.23431065e+05, 7.94346373e+05],\n", + " [4.07323106e+05, 6.94920369e+05],\n", + " [3.88182427e+05, 6.08833786e+05],\n", + " [2.39132524e+05, 6.73482288e+05],\n", + " [3.44693419e+05, 4.84765764e+05],\n", + " [2.49764871e+05, 5.99386996e+05],\n", + " [2.24208791e+05, 9.69604078e+05],\n", + " [2.42161516e+05, 8.63809138e+05],\n", + " [2.99055510e+05, 1.01065728e+06],\n", + " [2.16009266e+05, 6.79572780e+05],\n", + " [1.42296901e+05, 8.52154097e+05],\n", + " [1.37261908e+05, 6.85513749e+05],\n", + " [1.53922890e+05, 6.21095325e+05],\n", + " [2.34543405e+05, 6.81325991e+05],\n", + " [1.97932893e+05, 6.86032368e+05],\n", + " [1.46186905e+05, 9.13744839e+05],\n", + " [1.56136380e+05, 6.16014054e+05],\n", + " [1.27729870e+05, 6.76266460e+05],\n", + " [1.46348499e+05, 9.64054512e+05],\n", + " [1.32315639e+05, 7.10339257e+05],\n", + " [9.77510931e+04, 9.86542568e+05],\n", + " [1.53345982e+05, 6.68280814e+05],\n", + " [8.38626423e+04, 1.13816824e+06],\n", + " [9.01227543e+04, 9.87729621e+05],\n", + " [1.05985330e+05, 9.15522846e+05],\n", + " [7.08607245e+04, 1.14182280e+06],\n", + " [1.00703153e+05, 8.10116863e+05],\n", + " [1.01238301e+05, 1.15346247e+06],\n", + " [9.93093522e+04, 1.00306943e+06],\n", + " [6.16528494e+04, 1.16493792e+06],\n", + " [5.09503401e+04, 6.78705406e+05],\n", + " [4.82668644e+04, 7.18125591e+05],\n", + " [7.72885514e+04, 1.02584315e+06],\n", + " [7.44005640e+04, 7.71069604e+05],\n", + " [7.21902844e+04, 1.03156852e+06],\n", + " [6.51749505e+04, 9.83875388e+05],\n", + " [5.11539002e+04, 7.96148412e+05],\n", + " [7.01936114e+04, 8.79169672e+05],\n", + " [5.52006691e+04, 1.13580118e+06],\n", + " [5.07626146e+04, 9.46965648e+05],\n", + " [5.27437746e+04, 8.14629259e+05],\n", + " [4.79291706e+04, 7.50453652e+05],\n", + " [5.41381377e+04, 1.22352045e+06],\n", + " [2.67634003e+04, 1.23472286e+06],\n", + " [4.93052703e+04, 1.25985076e+06],\n", + " [3.08699126e+04, 8.90366760e+05],\n", + " [2.98741690e+04, 7.53132050e+05],\n", + " [4.17792978e+04, 1.09408874e+06],\n", + " [2.25207498e+04, 1.04352166e+06],\n", + " [2.22601709e+04, 9.82574315e+05],\n", + " [3.23309132e+04, 1.09982550e+06],\n", + " [2.40180970e+04, 8.39540686e+05],\n", + " [3.04195844e+04, 1.21333805e+06],\n", + " [2.41599286e+04, 9.77007989e+05],\n", + " [2.50895294e+04, 1.10876427e+06],\n", + " [2.73379775e+04, 8.72643324e+05],\n", + " [1.50521586e+04, 1.03047109e+06],\n", + " [1.91817748e+04, 1.00823957e+06],\n", + " [1.98054113e+04, 6.74170724e+05],\n", + " [2.15842015e+04, 8.90685644e+05],\n", + " [1.71480141e+04, 1.16005677e+06],\n", + " [1.73901876e+04, 7.11934851e+05],\n", + " [1.56090372e+04, 1.01138643e+06],\n", + " [1.67359124e+04, 1.29807714e+06],\n", + " [1.22015909e+04, 1.18023382e+06],\n", + " [1.26243306e+04, 7.09509434e+05],\n", + " [1.63788717e+04, 1.20866494e+06],\n", + " [1.11846718e+04, 7.72882252e+05],\n", + " [9.44074866e+03, 1.02111934e+06],\n", + " [1.19249632e+04, 8.44095665e+05],\n", + " [1.18742618e+04, 1.02561582e+06],\n", + " [9.22643440e+03, 8.23711242e+05],\n", + " [1.08676095e+04, 6.69990984e+05],\n", + " [6.15136129e+03, 6.87698842e+05],\n", + " [9.53029004e+03, 9.74535983e+05],\n", + " [7.93717611e+03, 9.74473869e+05],\n", + " [7.25769181e+03, 9.25257696e+05],\n", + " [7.87267307e+03, 6.91836383e+05],\n", + " [7.44642794e+03, 9.95206467e+05],\n", + " [7.22630565e+03, 7.70223136e+05],\n", + " [6.80643132e+03, 6.80086846e+05],\n", + " [7.64845973e+03, 1.04410552e+06],\n", + " [6.16197226e+03, 9.66700447e+05],\n", + " [6.92501634e+03, 9.19124316e+05],\n", + " [6.46474610e+03, 7.93136825e+05],\n", + " [3.55272495e+03, 6.75528262e+05],\n", + " [5.16693491e+03, 7.10837138e+05],\n", + " [5.38765066e+03, 6.79192984e+05],\n", + " [3.56087326e+03, 7.42337048e+05],\n", + " [4.30436231e+03, 1.24668691e+06],\n", + " [4.53314708e+03, 8.51467238e+05],\n", + " [4.18566167e+03, 1.20023639e+06],\n", + " [3.21279826e+03, 9.11558249e+05],\n", + " [2.90074298e+03, 1.28299446e+06],\n", + " [2.94076146e+03, 1.16364420e+06],\n", + " [2.15942909e+03, 1.26464423e+06],\n", + " [3.40102255e+03, 8.77575006e+05],\n", + " [2.46065388e+03, 6.72101289e+05],\n", + " [1.83869361e+03, 8.77319518e+05],\n", + " [3.12626369e+03, 1.04643681e+06],\n", + " [2.20822459e+03, 8.60168939e+05],\n", + " [2.42547765e+03, 1.16570838e+06],\n", + " [2.46872102e+03, 7.25965440e+05],\n", + " [1.38771867e+03, 1.03098596e+06],\n", + " [2.35622165e+03, 8.98923790e+05],\n", + " [1.35709596e+03, 1.17224893e+06],\n", + " [1.24362223e+03, 7.21513455e+05],\n", + " [1.15250240e+03, 1.21261607e+06],\n", + " [1.10506832e+03, 7.22116498e+05],\n", + " [1.33592148e+03, 9.12429023e+05],\n", + " [1.80059190e+03, 1.32216426e+06],\n", + " [1.21054109e+03, 7.21380766e+05],\n", + " [1.30390090e+03, 9.48289693e+05],\n", + " [8.84384233e+02, 9.93895431e+05],\n", + " [1.11187632e+03, 7.03402479e+05],\n", + " [8.04781600e+02, 1.09828585e+06],\n", + " [1.08464511e+03, 1.30677088e+06],\n", + " [8.37788890e+02, 1.24451513e+06],\n", + " [1.21687420e+03, 6.74142270e+05],\n", + " [6.15052691e+02, 1.25964703e+06],\n", + " [1.11775428e+03, 7.15262127e+05],\n", + " [1.05061703e+03, 1.01458598e+06],\n", + " [8.60555272e+02, 9.68955881e+05],\n", + " [7.64793005e+02, 1.26652091e+06],\n", + " [5.88199287e+02, 1.29937870e+06],\n", + " [6.35816955e+02, 1.07938072e+06],\n", + " [4.93649996e+02, 9.75190773e+05],\n", + " [6.25899451e+02, 7.18063800e+05],\n", + " [7.46714007e+02, 1.13146937e+06],\n", + " [4.68305129e+02, 1.20854802e+06],\n", + " [3.95490614e+02, 1.27330139e+06],\n", + " [6.30920826e+02, 1.14992124e+06],\n", + " [4.36536697e+02, 1.28789074e+06],\n", + " [3.06028969e+02, 6.83944130e+05],\n", + " [5.04257056e+02, 1.32429726e+06],\n", + " [4.22327998e+02, 9.20228055e+05],\n", + " [4.64225390e+02, 1.22508918e+06],\n", + " [3.39154470e+02, 8.48632779e+05],\n", + " [4.25202659e+02, 1.20818727e+06],\n", + " [4.33078028e+02, 1.03661708e+06],\n", + " [4.01254251e+02, 1.23271661e+06],\n", + " [2.84687620e+02, 7.52551320e+05],\n", + " [2.99858028e+02, 8.18865815e+05],\n", + " [2.87356573e+02, 9.05200608e+05],\n", + " [2.82370211e+02, 1.01328163e+06],\n", + " [2.44269399e+02, 1.23449003e+06],\n", + " [2.38588600e+02, 1.25081554e+06],\n", + " [1.64880089e+02, 6.85705527e+05],\n", + " [2.24095224e+02, 1.13581748e+06],\n", + " [1.49499663e+02, 6.76229628e+05],\n", + " [1.98966432e+02, 9.27988454e+05],\n", + " [2.26669764e+02, 8.98676469e+05],\n", + " [2.01969647e+02, 9.30870372e+05],\n", + " [2.00597500e+02, 1.29947041e+06],\n", + " [1.97394508e+02, 9.94591301e+05],\n", + " [1.42209065e+02, 1.31982872e+06],\n", + " [1.23185805e+02, 1.08878246e+06],\n", + " [9.48766296e+01, 7.52486918e+05],\n", + " [9.66280510e+01, 7.59122572e+05],\n", + " [9.43074761e+01, 8.97004132e+05],\n", + " [1.11877865e+02, 1.11157857e+06],\n", + " [8.60844711e+01, 6.93837248e+05],\n", + " [8.78132340e+01, 7.84592807e+05],\n", + " [7.32113399e+01, 9.73757064e+05],\n", + " [8.47811693e+01, 1.00218474e+06],\n", + " [6.14370563e+01, 1.19950055e+06]])" ] }, - "execution_count": 10, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "data_to_fit = noised_data[:,1:3]\n", - "data_to_fit = data_to_fit[1::,:]\n", + "data_to_fit = noised_data[1::,1:3]\n", "data_to_fit" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fitting Square l loss" - ] - }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" + "406" ] }, - "execution_count": 11, + "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "param_evals" + "np.prod(data_to_fit.shape)" ] }, { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "scrolled": false - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "# Initial guess of parameters, and bounding constraints\n", - "theta = [3, 0.15,1e6]\n", - "boxBounds = [(2,5),(0.0,1.0),(1e6,1e6)]\n", - "\n", - "objSIR = SquareLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + "## Fitting Square l loss" ] }, { @@ -702,7 +695,7 @@ { "data": { "text/plain": [ - "SquareLoss([3.0, 0.15, 1000000.0], SimulateOde([ODEVariable('S', 'S', None, True), ODEVariable('I', 'I', None, True), ODEVariable('R', 'R', None, True)], [ODEVariable('beta', 'beta', None, True), ODEVariable('gamma', 'gamma', None, True), ODEVariable('N', 'N', None, True)], [], [Transition('S', 'beta*S*I/N', 'T', 'I', None, None), Transition('I', 'gamma*I', 'T', 'R', None, None)], [], []).setParameters({'beta': 3.6, 'gamma': 0.2, 'N': 1000000.0}), [999998.0, 2.0, 0.0], 0.0, [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75, 12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75, 14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75, 16.0, 16.25, 16.5, 16.75, 17.0, 17.25, 17.5, 17.75, 18.0, 18.25, 18.5, 18.75, 19.0, 19.25, 19.5, 19.75, 20.0, 20.25, 20.5, 20.75, 21.0, 21.25, 21.5, 21.75, 22.0, 22.25, 22.5, 22.75, 23.0, 23.25, 23.5, 23.75, 24.0, 24.25, 24.5, 24.75, 25.0, 25.25, 25.5, 25.75, 26.0, 26.25, 26.5, 26.75, 27.0, 27.25, 27.5, 27.75, 28.0, 28.25, 28.5, 28.75, 29.0, 29.25, 29.5, 29.75, 30.0, 30.25, 30.5, 30.75, 31.0, 31.25, 31.5, 31.75, 32.0, 32.25, 32.5, 32.75, 33.0, 33.25, 33.5, 33.75, 34.0, 34.25, 34.5, 34.75, 35.0, 35.25, 35.5, 35.75, 36.0, 36.25, 36.5, 36.75, 37.0, 37.25, 37.5, 37.75, 38.0, 38.25, 38.5, 38.75, 39.0, 39.25, 39.5, 39.75, 40.0, 40.25, 40.5, 40.75, 41.0, 41.25, 41.5, 41.75, 42.0, 42.25, 42.5, 42.75, 43.0, 43.25, 43.5, 43.75, 44.0, 44.25, 44.5, 44.75, 45.0, 45.25, 45.5, 45.75, 46.0, 46.25, 46.5, 46.75, 47.0, 47.25, 47.5, 47.75, 48.0, 48.25, 48.5, 48.75, 49.0, 49.25, 49.5, 49.75, 50.0, 50.25, 50.5, 50.75], [[4.130487025131687, 0.15404561775936773], [9.397247964980085, 0.46303278732171177], [22.633824079261842, 1.7992007113807156], [47.986586672487206, 2.7579529325485836], [165.196041952231, 9.600546411428384], [409.7793329814416, 18.59941777036534], [528.9994837079726, 47.98014835106094], [1446.5429145036974, 90.66807675329977], [4994.287706241389, 311.89286846212264], [10103.580369113544, 548.4608589124192], [26194.736213578377, 1402.654912118046], [38389.19639311862, 2236.8590689690504], [144615.6038613682, 4710.739919896741], [204841.14352293048, 12829.825865082867], [304860.2404249535, 26514.684493267272], [715472.6235634295, 66063.90607297285], [570803.6488074489, 75737.62898047472], [947231.3292945497, 154986.247976831], [923953.16649091, 193822.49178823238], [657801.2480252209, 150769.93914359063], [843171.2637992136, 249113.1495604983], [559341.2527328188, 185957.3813357946], [696237.264525381, 403687.88293160085], [540067.5094137926, 266418.8007305509], [457478.5443022633, 388221.974041893], [425920.1427231567, 391122.61823234084], [396908.2854576274, 371414.7879418473], [602102.7053746057, 423352.09770557744], [641769.7394061629, 518903.09780880454], [416901.64080071973, 404368.7588933208], [330039.3314030553, 378696.7305775569], [551529.4145009269, 643412.0070484518], [549787.7820911882, 535688.556709061], [280979.5285986585, 742016.811538869], [466284.35882357555, 614750.051516308], [312148.2058862273, 529680.9650844566], [350953.6705610238, 872215.874672448], [401568.19082765863, 808517.3646270183], [295505.55911352474, 681129.850659894], [316315.37513281166, 659415.8097179801], [195777.4490952229, 679437.4206703037], [194280.03265693723, 721315.4457581254], [178501.10961662387, 675465.1683738899], [247404.53170668957, 985931.5093514766], [299943.4851962682, 764644.9954514606], [148078.91870689174, 898769.9073671738], [203910.04957668108, 710664.8108294513], [198269.08657707038, 550194.198541208], [241973.63044169324, 836300.8441740677], [194887.10906344195, 906544.5642488404], [146665.03014024382, 913739.3641712739], [143779.84227086403, 880070.3435878769], [104096.5358741194, 721086.1047601945], [187776.95624604076, 893932.5009312815], [94145.49095393051, 832234.8307984242], [147360.51529741898, 975970.1109512364], [107959.76674711499, 919504.6172384012], [131352.53801677615, 843986.0818510734], [138134.14244997536, 944445.5248128581], [143810.73000588483, 874698.002250221], [102488.3325125742, 825331.1957907011], [93675.23614669341, 1065797.3512993983], [92885.83732391837, 1155351.0857456843], [66375.89434895372, 988499.2242781295], [106010.1011427728, 810618.6033656059], [104769.0474474182, 639799.6000771984], [64379.976276675065, 1004433.9910370467], [88310.77848764382, 751578.4374513394], [83290.24377534064, 1142480.3506778087], [82370.47996389655, 770222.8341590352], [63637.766473583026, 810851.8091807761], [66788.91229470367, 698840.8146168891], [75102.3290490617, 1035002.7902780143], [62638.27317992859, 683328.3156147334], [41870.43206330126, 729742.0444708264], [60907.32053788277, 1179178.6549844078], [34183.575255148746, 920899.2296020638], [51655.704042085505, 842315.3424291152], [35331.51366160177, 886502.7398532623], [47883.945613707736, 693420.0510623266], [33557.87124412175, 1150074.1571437381], [30499.492761509304, 832594.3834703927], [42733.43248401154, 791261.006569009], [42078.9053350363, 1192499.0062521168], [39537.12490267918, 820574.0244793433], [25766.68117003718, 749084.1915958913], [37431.3006839491, 1146839.7385431828], [19729.377253022878, 688071.6526254383], [17124.35674302549, 1290962.3295776465], [19615.43572022034, 939060.0950318159], [24794.10562003187, 1112677.165293667], [21900.889529328662, 858416.4692184512], [19373.06594088114, 1150876.7459370985], [24118.498247359745, 852800.0837341312], [21207.530605877277, 772057.6638792764], [22267.30551041926, 714074.8898722631], [12497.025723179937, 712008.7912734993], [15065.344990296639, 843052.9384454926], [20199.686086950154, 882232.5677295076], [12391.464759044167, 718155.5097697747], [9937.135196575824, 1227788.641219967], [15492.606340046807, 1133059.0676593857], [14651.76273816029, 882614.1807004922], [15189.523429391971, 1075073.6739545558], [13718.455011597003, 854583.2693140692], [13242.565179358064, 852689.7481448406], [12283.16329964135, 1054384.679136664], [10715.461680060893, 987530.7540134372], [9799.836999306235, 1188662.432761487], [6817.309005236672, 847516.4934806598], [9156.515653966426, 1029834.6994578489], [5647.526250134233, 700227.501149568], [6851.585075787405, 995376.7395363126], [8537.770338276303, 991275.0750426087], [5588.410860946238, 1096531.4230958493], [7832.874408306464, 681290.2321555684], [5385.709166136957, 1288904.2276863966], [5607.200777069934, 679212.9865083437], [7131.98062301099, 1233327.2530472076], [6143.062328777299, 1294580.6293236036], [4116.526919112113, 902602.6246132584], [5555.49183273859, 788062.6499769951], [5945.901312119126, 1236921.6936202012], [4307.837673987712, 1211308.1303755068], [3057.267111272262, 1144766.9718521282], [3412.952069021781, 954158.1280045257], [4857.118212156462, 1287958.9746543085], [2802.7914200776886, 857680.691013031], [3387.914599774963, 863233.6440396649], [3691.679610334573, 1031277.0232285978], [3889.932537061482, 1178453.4027236914], [3175.6272264942872, 897242.264150536], [3321.8016013704805, 1111506.090775924], [2484.743968904745, 1257395.831926505], [2604.1755637616475, 718592.1692915799], [2953.762015063723, 1299568.2114593633], [2674.99903287432, 1021821.7828949532], [1936.840241672874, 709331.3091161926], [2430.32784824078, 1018865.0657590512], [1860.436184602949, 1216703.8610504132], [1723.2315526850525, 856007.9319208895], [1953.6263447660579, 1312810.8625858119], [1858.5407262503563, 677777.0784941971], [1121.841683026275, 1053185.2996789496], [1429.1799261633125, 942788.834721557], [1305.5210429480653, 857145.1282976748], [1558.6548858562132, 1096849.3108424598], [1165.2977247587564, 975845.740861295], [1281.1760431911907, 995327.4595873987], [903.127132888626, 936759.8641734732], [830.0255705095318, 1264058.880523917], [1447.175826672647, 826241.7163334353], [782.9089616625392, 949718.6455322991], [1309.5388116616314, 805544.6451139126], [1020.0814509483284, 1186010.9653905143], [767.2256057638687, 730153.9456574344], [940.5434165348748, 731312.8929979993], [1068.431197781994, 1148310.00282886], [759.4824678568447, 927258.3721201726], [732.4516659883362, 1329935.1271868325], [706.3997339170826, 1184560.8555669347], [767.0434989984218, 798379.2411034874], [530.2926441714136, 1320301.478595184], [527.2703906339111, 1113031.6474556928], [430.5568953988018, 737433.9280313611], [692.1927353827714, 673595.9280200478], [384.23959921185053, 898704.8958790172], [405.6029193272436, 768494.1267053746], [532.3797944208193, 840066.5011984787], [554.3188745851079, 1161649.7413965538], [463.87824061723234, 1073741.3455026292], [308.0292581421485, 673847.3559565375], [462.02471007201643, 1247648.281420697], [403.35869455867373, 1160975.832082224], [267.2020640147793, 1250383.7841186798], [363.8630500648634, 718443.7734347496], [279.6159322070644, 1287801.210123048], [360.1097904304585, 839169.2354281674], [249.32033940693356, 975423.6296495761], [348.83356604943486, 1322801.2214118955], [328.40387580328803, 1221966.218413916], [221.1210037522975, 1324802.975776162], [165.06914366017043, 951352.6052332598], [261.4314897243031, 1099063.4721241775], [247.83450742057468, 840256.1768109152], [232.49428280316337, 1043133.7234717476], [134.23826614735785, 895668.9384443999], [153.20678095501415, 970433.3364156254], [163.3872329739676, 871489.5702094157], [216.6725459496833, 1220808.7783561496], [144.4212576438835, 1225762.0801782524], [192.42606995989752, 740647.2823234415], [96.11282000434359, 904821.5403045765], [166.41677897191434, 975432.1078972422], [118.12562865687576, 1225649.9201249767], [135.81589553462987, 1260216.3663823903], [116.89024486149172, 1195617.0482448642], [97.71131894635056, 833097.6624037084], [86.8018133066483, 1096535.386700453], [94.22066759538556, 850974.2314776242], [93.53703959337743, 1286339.5796547756], [117.26614306573515, 1090935.1549952293], [65.33749823040989, 700052.7320163958]], ['I', 'R'], [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])" + "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" ] }, "execution_count": 13, @@ -711,21 +704,36 @@ } ], "source": [ - "objSIR" + "param_evals" ] }, { "cell_type": "code", "execution_count": 14, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "theta = [3, 0.15,N]\n", + "boxBounds = [(2,5),(0.0,1.0),(N,N)]\n", + "\n", + "objSIR = SquareLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "9032988605419.916" + "9494886226076.777" ] }, - "execution_count": 14, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -734,48 +742,6 @@ "objSIR.cost()" ] }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", - " warn('Method %s cannot handle constraints nor bounds.' % method,\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " fun: 6195089026101.063\n", - " hess_inv: array([[ 8.74144835e-12, -2.58712672e-14, 2.68445022e-06],\n", - " [-2.58712712e-14, 2.36956010e-15, -5.05342211e-09],\n", - " [ 2.68444976e-06, -5.05342099e-09, 8.41021723e-01]])\n", - " jac: array([ 4.61669282e+00, -8.58643370e+01, -1.67724298e-05])\n", - " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 57\n", - " nit: 11\n", - " njev: 46\n", - " status: 2\n", - " success: False\n", - " x: array([4.97711288e+00, 1.97932062e-01, 1.36982257e+06])\n" - ] - } - ], - "source": [ - "# perform optimization\n", - "res = minimize(fun=objSIR.cost,\n", - " jac=objSIR.sensitivity,\n", - " x0=theta,\n", - " bounds=boxBounds,\n", - " method='BFGS')\n", - "print(res)" - ] - }, { "cell_type": "code", "execution_count": 16, @@ -785,16 +751,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 6195089026101.077\n", + " fun: 6793822783898.12\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([ 7.75580656e+04, 3.96915387e+06, -2.81799456e-01])\n", + " jac: array([ 3.71447419e+06, 1.99495082e+07, -1.34416872e+01])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 16\n", - " nit: 10\n", - " njev: 16\n", + " nfev: 13\n", + " nit: 9\n", + " njev: 13\n", " status: 0\n", " success: True\n", - " x: array([3.63339968e+00, 1.97932071e-01, 1.00000000e+06])\n" + " x: array([3.61873217e+00, 1.95448280e-01, 1.00000000e+06])\n" ] } ], @@ -855,70 +821,27 @@ { "cell_type": "code", "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "param_evals" - ] - }, - { - "cell_type": "code", - "execution_count": 19, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Initial guess of parameters, and bounding constraints\n", - "theta = [3, 0.15,1e6]\n", - "boxBounds = [(2,5),(0.0,1.0),(1e6,1e6)]\n", - "\n", "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" ] }, { "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "NormalLoss([3.0, 0.15, 1000000.0], SimulateOde([ODEVariable('S', 'S', None, True), ODEVariable('I', 'I', None, True), ODEVariable('R', 'R', None, True)], [ODEVariable('beta', 'beta', None, True), ODEVariable('gamma', 'gamma', None, True), ODEVariable('N', 'N', None, True)], [], [Transition('S', 'beta*S*I/N', 'T', 'I', None, None), Transition('I', 'gamma*I', 'T', 'R', None, None)], [], []).setParameters({'beta': 3.6333996818761123, 'gamma': 0.19793207076619318, 'N': 1000000.0}), [999998.0, 2.0, 0.0], 0.0, [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75, 12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75, 14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75, 16.0, 16.25, 16.5, 16.75, 17.0, 17.25, 17.5, 17.75, 18.0, 18.25, 18.5, 18.75, 19.0, 19.25, 19.5, 19.75, 20.0, 20.25, 20.5, 20.75, 21.0, 21.25, 21.5, 21.75, 22.0, 22.25, 22.5, 22.75, 23.0, 23.25, 23.5, 23.75, 24.0, 24.25, 24.5, 24.75, 25.0, 25.25, 25.5, 25.75, 26.0, 26.25, 26.5, 26.75, 27.0, 27.25, 27.5, 27.75, 28.0, 28.25, 28.5, 28.75, 29.0, 29.25, 29.5, 29.75, 30.0, 30.25, 30.5, 30.75, 31.0, 31.25, 31.5, 31.75, 32.0, 32.25, 32.5, 32.75, 33.0, 33.25, 33.5, 33.75, 34.0, 34.25, 34.5, 34.75, 35.0, 35.25, 35.5, 35.75, 36.0, 36.25, 36.5, 36.75, 37.0, 37.25, 37.5, 37.75, 38.0, 38.25, 38.5, 38.75, 39.0, 39.25, 39.5, 39.75, 40.0, 40.25, 40.5, 40.75, 41.0, 41.25, 41.5, 41.75, 42.0, 42.25, 42.5, 42.75, 43.0, 43.25, 43.5, 43.75, 44.0, 44.25, 44.5, 44.75, 45.0, 45.25, 45.5, 45.75, 46.0, 46.25, 46.5, 46.75, 47.0, 47.25, 47.5, 47.75, 48.0, 48.25, 48.5, 48.75, 49.0, 49.25, 49.5, 49.75, 50.0, 50.25, 50.5, 50.75], [[4.130487025131687, 0.15404561775936773], [9.397247964980085, 0.46303278732171177], [22.633824079261842, 1.7992007113807156], [47.986586672487206, 2.7579529325485836], [165.196041952231, 9.600546411428384], [409.7793329814416, 18.59941777036534], [528.9994837079726, 47.98014835106094], [1446.5429145036974, 90.66807675329977], [4994.287706241389, 311.89286846212264], [10103.580369113544, 548.4608589124192], [26194.736213578377, 1402.654912118046], [38389.19639311862, 2236.8590689690504], [144615.6038613682, 4710.739919896741], [204841.14352293048, 12829.825865082867], [304860.2404249535, 26514.684493267272], [715472.6235634295, 66063.90607297285], [570803.6488074489, 75737.62898047472], [947231.3292945497, 154986.247976831], [923953.16649091, 193822.49178823238], [657801.2480252209, 150769.93914359063], [843171.2637992136, 249113.1495604983], [559341.2527328188, 185957.3813357946], [696237.264525381, 403687.88293160085], [540067.5094137926, 266418.8007305509], [457478.5443022633, 388221.974041893], [425920.1427231567, 391122.61823234084], [396908.2854576274, 371414.7879418473], [602102.7053746057, 423352.09770557744], [641769.7394061629, 518903.09780880454], [416901.64080071973, 404368.7588933208], [330039.3314030553, 378696.7305775569], [551529.4145009269, 643412.0070484518], [549787.7820911882, 535688.556709061], [280979.5285986585, 742016.811538869], [466284.35882357555, 614750.051516308], [312148.2058862273, 529680.9650844566], [350953.6705610238, 872215.874672448], [401568.19082765863, 808517.3646270183], [295505.55911352474, 681129.850659894], [316315.37513281166, 659415.8097179801], [195777.4490952229, 679437.4206703037], [194280.03265693723, 721315.4457581254], [178501.10961662387, 675465.1683738899], [247404.53170668957, 985931.5093514766], [299943.4851962682, 764644.9954514606], [148078.91870689174, 898769.9073671738], [203910.04957668108, 710664.8108294513], [198269.08657707038, 550194.198541208], [241973.63044169324, 836300.8441740677], [194887.10906344195, 906544.5642488404], [146665.03014024382, 913739.3641712739], [143779.84227086403, 880070.3435878769], [104096.5358741194, 721086.1047601945], [187776.95624604076, 893932.5009312815], [94145.49095393051, 832234.8307984242], [147360.51529741898, 975970.1109512364], [107959.76674711499, 919504.6172384012], [131352.53801677615, 843986.0818510734], [138134.14244997536, 944445.5248128581], [143810.73000588483, 874698.002250221], [102488.3325125742, 825331.1957907011], [93675.23614669341, 1065797.3512993983], [92885.83732391837, 1155351.0857456843], [66375.89434895372, 988499.2242781295], [106010.1011427728, 810618.6033656059], [104769.0474474182, 639799.6000771984], [64379.976276675065, 1004433.9910370467], [88310.77848764382, 751578.4374513394], [83290.24377534064, 1142480.3506778087], [82370.47996389655, 770222.8341590352], [63637.766473583026, 810851.8091807761], [66788.91229470367, 698840.8146168891], [75102.3290490617, 1035002.7902780143], [62638.27317992859, 683328.3156147334], [41870.43206330126, 729742.0444708264], [60907.32053788277, 1179178.6549844078], [34183.575255148746, 920899.2296020638], [51655.704042085505, 842315.3424291152], [35331.51366160177, 886502.7398532623], [47883.945613707736, 693420.0510623266], [33557.87124412175, 1150074.1571437381], [30499.492761509304, 832594.3834703927], [42733.43248401154, 791261.006569009], [42078.9053350363, 1192499.0062521168], [39537.12490267918, 820574.0244793433], [25766.68117003718, 749084.1915958913], [37431.3006839491, 1146839.7385431828], [19729.377253022878, 688071.6526254383], [17124.35674302549, 1290962.3295776465], [19615.43572022034, 939060.0950318159], [24794.10562003187, 1112677.165293667], [21900.889529328662, 858416.4692184512], [19373.06594088114, 1150876.7459370985], [24118.498247359745, 852800.0837341312], [21207.530605877277, 772057.6638792764], [22267.30551041926, 714074.8898722631], [12497.025723179937, 712008.7912734993], [15065.344990296639, 843052.9384454926], [20199.686086950154, 882232.5677295076], [12391.464759044167, 718155.5097697747], [9937.135196575824, 1227788.641219967], [15492.606340046807, 1133059.0676593857], [14651.76273816029, 882614.1807004922], [15189.523429391971, 1075073.6739545558], [13718.455011597003, 854583.2693140692], [13242.565179358064, 852689.7481448406], [12283.16329964135, 1054384.679136664], [10715.461680060893, 987530.7540134372], [9799.836999306235, 1188662.432761487], [6817.309005236672, 847516.4934806598], [9156.515653966426, 1029834.6994578489], [5647.526250134233, 700227.501149568], [6851.585075787405, 995376.7395363126], [8537.770338276303, 991275.0750426087], [5588.410860946238, 1096531.4230958493], [7832.874408306464, 681290.2321555684], [5385.709166136957, 1288904.2276863966], [5607.200777069934, 679212.9865083437], [7131.98062301099, 1233327.2530472076], [6143.062328777299, 1294580.6293236036], [4116.526919112113, 902602.6246132584], [5555.49183273859, 788062.6499769951], [5945.901312119126, 1236921.6936202012], [4307.837673987712, 1211308.1303755068], [3057.267111272262, 1144766.9718521282], [3412.952069021781, 954158.1280045257], [4857.118212156462, 1287958.9746543085], [2802.7914200776886, 857680.691013031], [3387.914599774963, 863233.6440396649], [3691.679610334573, 1031277.0232285978], [3889.932537061482, 1178453.4027236914], [3175.6272264942872, 897242.264150536], [3321.8016013704805, 1111506.090775924], [2484.743968904745, 1257395.831926505], [2604.1755637616475, 718592.1692915799], [2953.762015063723, 1299568.2114593633], [2674.99903287432, 1021821.7828949532], [1936.840241672874, 709331.3091161926], [2430.32784824078, 1018865.0657590512], [1860.436184602949, 1216703.8610504132], [1723.2315526850525, 856007.9319208895], [1953.6263447660579, 1312810.8625858119], [1858.5407262503563, 677777.0784941971], [1121.841683026275, 1053185.2996789496], [1429.1799261633125, 942788.834721557], [1305.5210429480653, 857145.1282976748], [1558.6548858562132, 1096849.3108424598], [1165.2977247587564, 975845.740861295], [1281.1760431911907, 995327.4595873987], [903.127132888626, 936759.8641734732], [830.0255705095318, 1264058.880523917], [1447.175826672647, 826241.7163334353], [782.9089616625392, 949718.6455322991], [1309.5388116616314, 805544.6451139126], [1020.0814509483284, 1186010.9653905143], [767.2256057638687, 730153.9456574344], [940.5434165348748, 731312.8929979993], [1068.431197781994, 1148310.00282886], [759.4824678568447, 927258.3721201726], [732.4516659883362, 1329935.1271868325], [706.3997339170826, 1184560.8555669347], [767.0434989984218, 798379.2411034874], [530.2926441714136, 1320301.478595184], [527.2703906339111, 1113031.6474556928], [430.5568953988018, 737433.9280313611], [692.1927353827714, 673595.9280200478], [384.23959921185053, 898704.8958790172], [405.6029193272436, 768494.1267053746], [532.3797944208193, 840066.5011984787], [554.3188745851079, 1161649.7413965538], [463.87824061723234, 1073741.3455026292], [308.0292581421485, 673847.3559565375], [462.02471007201643, 1247648.281420697], [403.35869455867373, 1160975.832082224], [267.2020640147793, 1250383.7841186798], [363.8630500648634, 718443.7734347496], [279.6159322070644, 1287801.210123048], [360.1097904304585, 839169.2354281674], [249.32033940693356, 975423.6296495761], [348.83356604943486, 1322801.2214118955], [328.40387580328803, 1221966.218413916], [221.1210037522975, 1324802.975776162], [165.06914366017043, 951352.6052332598], [261.4314897243031, 1099063.4721241775], [247.83450742057468, 840256.1768109152], [232.49428280316337, 1043133.7234717476], [134.23826614735785, 895668.9384443999], [153.20678095501415, 970433.3364156254], [163.3872329739676, 871489.5702094157], [216.6725459496833, 1220808.7783561496], [144.4212576438835, 1225762.0801782524], [192.42606995989752, 740647.2823234415], [96.11282000434359, 904821.5403045765], [166.41677897191434, 975432.1078972422], [118.12562865687576, 1225649.9201249767], [135.81589553462987, 1260216.3663823903], [116.89024486149172, 1195617.0482448642], [97.71131894635056, 833097.6624037084], [86.8018133066483, 1096535.386700453], [94.22066759538556, 850974.2314776242], [93.53703959337743, 1286339.5796547756], [117.26614306573515, 1090935.1549952293], [65.33749823040989, 700052.7320163958]], ['I', 'R'], [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "objSIR" - ] - }, - { - "cell_type": "code", - "execution_count": 21, + "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "4516494303083.047" + "4747443113411.479" ] }, - "execution_count": 21, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -929,65 +852,23 @@ }, { "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", - " warn('Method %s cannot handle constraints nor bounds.' % method,\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " fun: 3097544513423.658\n", - " hess_inv: array([[ 1.03645359e-11, -4.61156610e-14, 3.16936003e-06],\n", - " [-4.61156587e-14, 4.75500055e-15, -8.98088545e-09],\n", - " [ 3.16936002e-06, -8.98088607e-09, 1.00244138e+00]])\n", - " jac: array([ 9.35430284e+04, -3.55363991e+05, -3.39879219e-01])\n", - " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 55\n", - " nit: 9\n", - " njev: 46\n", - " status: 2\n", - " success: False\n", - " x: array([4.54710725e+00, 1.97932059e-01, 1.25147454e+06])\n" - ] - } - ], - "source": [ - "# perform optimization\n", - "res = minimize(fun=objSIR.cost,\n", - " jac=objSIR.sensitivity,\n", - " x0=theta,\n", - " bounds=boxBounds,\n", - " method='BFGS')\n", - "print(res)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, + "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " fun: 3097544513423.661\n", + " fun: 3396911392322.0205\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([ 3.87782251e+04, 1.98457720e+06, -1.40896750e-01])\n", + " jac: array([ 1.85722536e+06, 9.97472077e+06, -6.72080114e+00])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 16\n", - " nit: 10\n", - " njev: 16\n", + " nfev: 13\n", + " nit: 9\n", + " njev: 13\n", " status: 0\n", " success: True\n", - " x: array([3.63339968e+00, 1.97932071e-01, 1.00000000e+06])\n" + " x: array([3.61873217e+00, 1.95448280e-01, 1.00000000e+06])\n" ] } ], @@ -1003,7 +884,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -1047,7 +928,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 22, "metadata": { "scrolled": false }, @@ -1059,36 +940,16 @@ }, { "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([-5.77039500e+02, -6.96845671e+03, 1.73111850e-03])" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "objSIR.sensitivity()" - ] - }, - { - "cell_type": "code", - "execution_count": 27, + "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "5058.726988342257" + "5066.230498539779" ] }, - "execution_count": 27, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -1099,56 +960,14 @@ }, { "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", - " warn('Method %s cannot handle constraints nor bounds.' % method,\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " fun: 4717.132458517435\n", - " hess_inv: array([[ 3.86858865e-03, -3.00734373e-05, 3.30190074e-06],\n", - " [-3.00734373e-05, 3.91747625e-06, 2.36516472e-08],\n", - " [ 3.30190074e-06, 2.36516472e-08, 1.00000000e+00]])\n", - " jac: array([ 2.13941642e-10, 3.42940432e-08, -7.68280694e-16])\n", - " message: 'Optimization terminated successfully.'\n", - " nfev: 28\n", - " nit: 12\n", - " njev: 27\n", - " status: 0\n", - " success: True\n", - " x: array([3.59089103e+00, 1.99441546e-01, 1.00000000e+06])\n" - ] - } - ], - "source": [ - "# perform optimization\n", - "res = minimize(fun=objSIR.cost,\n", - " jac=objSIR.sensitivity,\n", - " x0=theta,\n", - " bounds=boxBounds,\n", - " method='BFGS')\n", - "print(res)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, + "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", " logpdf_p3= -shape*np.log(mu/shape)\n" ] }, @@ -1156,16 +975,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4717.132458530734\n", + " fun: 4699.518465235284\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([ 1.00361678e-03, -6.86270665e-02, -3.60388445e-09])\n", + " jac: array([-2.55035382e-03, 1.18874416e-01, 9.14788362e-09])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", " nfev: 17\n", " nit: 10\n", " njev: 17\n", " status: 0\n", " success: True\n", - " x: array([3.59089697e+00, 1.99441247e-01, 1.00000000e+06])\n" + " x: array([3.58690764e+00, 1.99822701e-01, 1.00000000e+06])\n" ] } ], @@ -1181,7 +1000,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -1232,218 +1051,218 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[4.000000e+00, 0.000000e+00],\n", - " [9.000000e+00, 0.000000e+00],\n", - " [2.300000e+01, 2.000000e+00],\n", - " [4.800000e+01, 3.000000e+00],\n", - " [1.650000e+02, 1.000000e+01],\n", - " [4.100000e+02, 1.900000e+01],\n", - " [5.290000e+02, 4.800000e+01],\n", - " [1.447000e+03, 9.100000e+01],\n", - " [4.994000e+03, 3.120000e+02],\n", - " [1.010400e+04, 5.480000e+02],\n", - " [2.619500e+04, 1.403000e+03],\n", - " [3.838900e+04, 2.237000e+03],\n", - " [1.446160e+05, 4.711000e+03],\n", - " [2.048410e+05, 1.283000e+04],\n", - " [3.048600e+05, 2.651500e+04],\n", - " [7.154730e+05, 6.606400e+04],\n", - " [5.708040e+05, 7.573800e+04],\n", - " [9.472310e+05, 1.549860e+05],\n", - " [9.239530e+05, 1.938220e+05],\n", - " [6.578010e+05, 1.507700e+05],\n", - " [8.431710e+05, 2.491130e+05],\n", - " [5.593410e+05, 1.859570e+05],\n", - " [6.962370e+05, 4.036880e+05],\n", - " [5.400680e+05, 2.664190e+05],\n", - " [4.574790e+05, 3.882220e+05],\n", - " [4.259200e+05, 3.911230e+05],\n", - " [3.969080e+05, 3.714150e+05],\n", - " [6.021030e+05, 4.233520e+05],\n", - " [6.417700e+05, 5.189030e+05],\n", - " [4.169020e+05, 4.043690e+05],\n", - " [3.300390e+05, 3.786970e+05],\n", - " [5.515290e+05, 6.434120e+05],\n", - " [5.497880e+05, 5.356890e+05],\n", - " [2.809800e+05, 7.420170e+05],\n", - " [4.662840e+05, 6.147500e+05],\n", - " [3.121480e+05, 5.296810e+05],\n", - " [3.509540e+05, 8.722160e+05],\n", - " [4.015680e+05, 8.085170e+05],\n", - " [2.955060e+05, 6.811300e+05],\n", - " [3.163150e+05, 6.594160e+05],\n", - " [1.957770e+05, 6.794370e+05],\n", - " [1.942800e+05, 7.213150e+05],\n", - " [1.785010e+05, 6.754650e+05],\n", - " [2.474050e+05, 9.859320e+05],\n", - " [2.999430e+05, 7.646450e+05],\n", - " [1.480790e+05, 8.987700e+05],\n", - " [2.039100e+05, 7.106650e+05],\n", - " [1.982690e+05, 5.501940e+05],\n", - " [2.419740e+05, 8.363010e+05],\n", - " [1.948870e+05, 9.065450e+05],\n", - " [1.466650e+05, 9.137390e+05],\n", - " [1.437800e+05, 8.800700e+05],\n", - " [1.040970e+05, 7.210860e+05],\n", - " [1.877770e+05, 8.939330e+05],\n", - " [9.414500e+04, 8.322350e+05],\n", - " [1.473610e+05, 9.759700e+05],\n", - " [1.079600e+05, 9.195050e+05],\n", - " [1.313530e+05, 8.439860e+05],\n", - " [1.381340e+05, 9.444460e+05],\n", - " [1.438110e+05, 8.746980e+05],\n", - " [1.024880e+05, 8.253310e+05],\n", - " [9.367500e+04, 1.065797e+06],\n", - " [9.288600e+04, 1.155351e+06],\n", - " [6.637600e+04, 9.884990e+05],\n", - " [1.060100e+05, 8.106190e+05],\n", - " [1.047690e+05, 6.398000e+05],\n", - " [6.438000e+04, 1.004434e+06],\n", - " [8.831100e+04, 7.515780e+05],\n", - " [8.329000e+04, 1.142480e+06],\n", - " [8.237000e+04, 7.702230e+05],\n", - " [6.363800e+04, 8.108520e+05],\n", - " [6.678900e+04, 6.988410e+05],\n", - " [7.510200e+04, 1.035003e+06],\n", - " [6.263800e+04, 6.833280e+05],\n", - " [4.187000e+04, 7.297420e+05],\n", - " [6.090700e+04, 1.179179e+06],\n", - " [3.418400e+04, 9.208990e+05],\n", - " [5.165600e+04, 8.423150e+05],\n", - " [3.533200e+04, 8.865030e+05],\n", - " [4.788400e+04, 6.934200e+05],\n", - " [3.355800e+04, 1.150074e+06],\n", - " [3.049900e+04, 8.325940e+05],\n", - " [4.273300e+04, 7.912610e+05],\n", - " [4.207900e+04, 1.192499e+06],\n", - " [3.953700e+04, 8.205740e+05],\n", - " [2.576700e+04, 7.490840e+05],\n", - " [3.743100e+04, 1.146840e+06],\n", - " [1.972900e+04, 6.880720e+05],\n", - " [1.712400e+04, 1.290962e+06],\n", - " [1.961500e+04, 9.390600e+05],\n", - " [2.479400e+04, 1.112677e+06],\n", - " [2.190100e+04, 8.584160e+05],\n", - " [1.937300e+04, 1.150877e+06],\n", - " [2.411800e+04, 8.528000e+05],\n", - " [2.120800e+04, 7.720580e+05],\n", - " [2.226700e+04, 7.140750e+05],\n", - " [1.249700e+04, 7.120090e+05],\n", - " [1.506500e+04, 8.430530e+05],\n", - " [2.020000e+04, 8.822330e+05],\n", - " [1.239100e+04, 7.181560e+05],\n", - " [9.937000e+03, 1.227789e+06],\n", - " [1.549300e+04, 1.133059e+06],\n", - " [1.465200e+04, 8.826140e+05],\n", - " [1.519000e+04, 1.075074e+06],\n", - " [1.371800e+04, 8.545830e+05],\n", - " [1.324300e+04, 8.526900e+05],\n", - " [1.228300e+04, 1.054385e+06],\n", - " [1.071500e+04, 9.875310e+05],\n", - " [9.800000e+03, 1.188662e+06],\n", - " [6.817000e+03, 8.475160e+05],\n", - " [9.157000e+03, 1.029835e+06],\n", - " [5.648000e+03, 7.002280e+05],\n", - " [6.852000e+03, 9.953770e+05],\n", - " [8.538000e+03, 9.912750e+05],\n", - " [5.588000e+03, 1.096531e+06],\n", - " [7.833000e+03, 6.812900e+05],\n", - " [5.386000e+03, 1.288904e+06],\n", - " [5.607000e+03, 6.792130e+05],\n", - " [7.132000e+03, 1.233327e+06],\n", - " [6.143000e+03, 1.294581e+06],\n", - " [4.117000e+03, 9.026030e+05],\n", - " [5.555000e+03, 7.880630e+05],\n", - " [5.946000e+03, 1.236922e+06],\n", - " [4.308000e+03, 1.211308e+06],\n", - " [3.057000e+03, 1.144767e+06],\n", - " [3.413000e+03, 9.541580e+05],\n", - " [4.857000e+03, 1.287959e+06],\n", - " [2.803000e+03, 8.576810e+05],\n", - " [3.388000e+03, 8.632340e+05],\n", - " [3.692000e+03, 1.031277e+06],\n", - " [3.890000e+03, 1.178453e+06],\n", - " [3.176000e+03, 8.972420e+05],\n", - " [3.322000e+03, 1.111506e+06],\n", - " [2.485000e+03, 1.257396e+06],\n", - " [2.604000e+03, 7.185920e+05],\n", - " [2.954000e+03, 1.299568e+06],\n", - " [2.675000e+03, 1.021822e+06],\n", - " [1.937000e+03, 7.093310e+05],\n", - " [2.430000e+03, 1.018865e+06],\n", - " [1.860000e+03, 1.216704e+06],\n", - " [1.723000e+03, 8.560080e+05],\n", - " [1.954000e+03, 1.312811e+06],\n", - " [1.859000e+03, 6.777770e+05],\n", - " [1.122000e+03, 1.053185e+06],\n", - " [1.429000e+03, 9.427890e+05],\n", - " [1.306000e+03, 8.571450e+05],\n", - " [1.559000e+03, 1.096849e+06],\n", - " [1.165000e+03, 9.758460e+05],\n", - " [1.281000e+03, 9.953270e+05],\n", - " [9.030000e+02, 9.367600e+05],\n", - " [8.300000e+02, 1.264059e+06],\n", - " [1.447000e+03, 8.262420e+05],\n", - " [7.830000e+02, 9.497190e+05],\n", - " [1.310000e+03, 8.055450e+05],\n", - " [1.020000e+03, 1.186011e+06],\n", - " [7.670000e+02, 7.301540e+05],\n", - " [9.410000e+02, 7.313130e+05],\n", - " [1.068000e+03, 1.148310e+06],\n", - " [7.590000e+02, 9.272580e+05],\n", - " [7.320000e+02, 1.329935e+06],\n", - " [7.060000e+02, 1.184561e+06],\n", - " [7.670000e+02, 7.983790e+05],\n", - " [5.300000e+02, 1.320301e+06],\n", - " [5.270000e+02, 1.113032e+06],\n", - " [4.310000e+02, 7.374340e+05],\n", - " [6.920000e+02, 6.735960e+05],\n", - " [3.840000e+02, 8.987050e+05],\n", - " [4.060000e+02, 7.684940e+05],\n", - " [5.320000e+02, 8.400670e+05],\n", - " [5.540000e+02, 1.161650e+06],\n", - " [4.640000e+02, 1.073741e+06],\n", - " [3.080000e+02, 6.738470e+05],\n", - " [4.620000e+02, 1.247648e+06],\n", - " [4.030000e+02, 1.160976e+06],\n", - " [2.670000e+02, 1.250384e+06],\n", - " [3.640000e+02, 7.184440e+05],\n", - " [2.800000e+02, 1.287801e+06],\n", - " [3.600000e+02, 8.391690e+05],\n", - " [2.490000e+02, 9.754240e+05],\n", - " [3.490000e+02, 1.322801e+06],\n", - " [3.280000e+02, 1.221966e+06],\n", - " [2.210000e+02, 1.324803e+06],\n", - " [1.650000e+02, 9.513530e+05],\n", - " [2.610000e+02, 1.099063e+06],\n", - " [2.480000e+02, 8.402560e+05],\n", - " [2.320000e+02, 1.043134e+06],\n", - " [1.340000e+02, 8.956690e+05],\n", - " [1.530000e+02, 9.704330e+05],\n", - " [1.630000e+02, 8.714900e+05],\n", - " [2.170000e+02, 1.220809e+06],\n", - " [1.440000e+02, 1.225762e+06],\n", - " [1.920000e+02, 7.406470e+05],\n", - " [9.600000e+01, 9.048220e+05],\n", - " [1.660000e+02, 9.754320e+05],\n", - " [1.180000e+02, 1.225650e+06],\n", - " [1.360000e+02, 1.260216e+06],\n", - " [1.170000e+02, 1.195617e+06],\n", - " [9.800000e+01, 8.330980e+05],\n", - " [8.700000e+01, 1.096535e+06],\n", - " [9.400000e+01, 8.509740e+05],\n", - " [9.400000e+01, 1.286340e+06],\n", - " [1.170000e+02, 1.090935e+06],\n", - " [6.500000e+01, 7.000530e+05]])" + "array([[2.000000e+00, 0.000000e+00],\n", + " [7.000000e+00, 0.000000e+00],\n", + " [9.000000e+00, 1.000000e+00],\n", + " [2.400000e+01, 1.000000e+00],\n", + " [6.100000e+01, 4.000000e+00],\n", + " [1.410000e+02, 1.000000e+01],\n", + " [3.300000e+02, 2.100000e+01],\n", + " [1.067000e+03, 4.200000e+01],\n", + " [2.225000e+03, 8.600000e+01],\n", + " [3.814000e+03, 2.050000e+02],\n", + " [1.487700e+04, 8.100000e+02],\n", + " [1.911100e+04, 1.751000e+03],\n", + " [4.397700e+04, 3.566000e+03],\n", + " [1.608390e+05, 6.728000e+03],\n", + " [2.170450e+05, 1.735900e+04],\n", + " [3.327830e+05, 4.427900e+04],\n", + " [7.717000e+05, 7.491600e+04],\n", + " [9.202460e+05, 6.710300e+04],\n", + " [5.391150e+05, 1.148730e+05],\n", + " [6.638560e+05, 2.061310e+05],\n", + " [6.561610e+05, 2.138540e+05],\n", + " [8.918150e+05, 1.760330e+05],\n", + " [8.408420e+05, 2.254300e+05],\n", + " [8.227540e+05, 3.605760e+05],\n", + " [7.653000e+05, 2.506620e+05],\n", + " [4.591880e+05, 4.741000e+05],\n", + " [5.213390e+05, 2.919950e+05],\n", + " [4.939920e+05, 5.079050e+05],\n", + " [6.693630e+05, 4.590900e+05],\n", + " [5.781150e+05, 5.795380e+05],\n", + " [5.685050e+05, 5.162470e+05],\n", + " [4.359390e+05, 3.704330e+05],\n", + " [2.996270e+05, 6.155260e+05],\n", + " [4.168740e+05, 7.445460e+05],\n", + " [3.707400e+05, 7.088730e+05],\n", + " [2.692970e+05, 5.373230e+05],\n", + " [4.589900e+05, 7.753300e+05],\n", + " [4.234310e+05, 7.943460e+05],\n", + " [4.073230e+05, 6.949200e+05],\n", + " [3.881820e+05, 6.088340e+05],\n", + " [2.391330e+05, 6.734820e+05],\n", + " [3.446930e+05, 4.847660e+05],\n", + " [2.497650e+05, 5.993870e+05],\n", + " [2.242090e+05, 9.696040e+05],\n", + " [2.421620e+05, 8.638090e+05],\n", + " [2.990560e+05, 1.010657e+06],\n", + " [2.160090e+05, 6.795730e+05],\n", + " [1.422970e+05, 8.521540e+05],\n", + " [1.372620e+05, 6.855140e+05],\n", + " [1.539230e+05, 6.210950e+05],\n", + " [2.345430e+05, 6.813260e+05],\n", + " [1.979330e+05, 6.860320e+05],\n", + " [1.461870e+05, 9.137450e+05],\n", + " [1.561360e+05, 6.160140e+05],\n", + " [1.277300e+05, 6.762660e+05],\n", + " [1.463480e+05, 9.640550e+05],\n", + " [1.323160e+05, 7.103390e+05],\n", + " [9.775100e+04, 9.865430e+05],\n", + " [1.533460e+05, 6.682810e+05],\n", + " [8.386300e+04, 1.138168e+06],\n", + " [9.012300e+04, 9.877300e+05],\n", + " [1.059850e+05, 9.155230e+05],\n", + " [7.086100e+04, 1.141823e+06],\n", + " [1.007030e+05, 8.101170e+05],\n", + " [1.012380e+05, 1.153462e+06],\n", + " [9.930900e+04, 1.003069e+06],\n", + " [6.165300e+04, 1.164938e+06],\n", + " [5.095000e+04, 6.787050e+05],\n", + " [4.826700e+04, 7.181260e+05],\n", + " [7.728900e+04, 1.025843e+06],\n", + " [7.440100e+04, 7.710700e+05],\n", + " [7.219000e+04, 1.031569e+06],\n", + " [6.517500e+04, 9.838750e+05],\n", + " [5.115400e+04, 7.961480e+05],\n", + " [7.019400e+04, 8.791700e+05],\n", + " [5.520100e+04, 1.135801e+06],\n", + " [5.076300e+04, 9.469660e+05],\n", + " [5.274400e+04, 8.146290e+05],\n", + " [4.792900e+04, 7.504540e+05],\n", + " [5.413800e+04, 1.223520e+06],\n", + " [2.676300e+04, 1.234723e+06],\n", + " [4.930500e+04, 1.259851e+06],\n", + " [3.087000e+04, 8.903670e+05],\n", + " [2.987400e+04, 7.531320e+05],\n", + " [4.177900e+04, 1.094089e+06],\n", + " [2.252100e+04, 1.043522e+06],\n", + " [2.226000e+04, 9.825740e+05],\n", + " [3.233100e+04, 1.099825e+06],\n", + " [2.401800e+04, 8.395410e+05],\n", + " [3.042000e+04, 1.213338e+06],\n", + " [2.416000e+04, 9.770080e+05],\n", + " [2.509000e+04, 1.108764e+06],\n", + " [2.733800e+04, 8.726430e+05],\n", + " [1.505200e+04, 1.030471e+06],\n", + " [1.918200e+04, 1.008240e+06],\n", + " [1.980500e+04, 6.741710e+05],\n", + " [2.158400e+04, 8.906860e+05],\n", + " [1.714800e+04, 1.160057e+06],\n", + " [1.739000e+04, 7.119350e+05],\n", + " [1.560900e+04, 1.011386e+06],\n", + " [1.673600e+04, 1.298077e+06],\n", + " [1.220200e+04, 1.180234e+06],\n", + " [1.262400e+04, 7.095090e+05],\n", + " [1.637900e+04, 1.208665e+06],\n", + " [1.118500e+04, 7.728820e+05],\n", + " [9.441000e+03, 1.021119e+06],\n", + " [1.192500e+04, 8.440960e+05],\n", + " [1.187400e+04, 1.025616e+06],\n", + " [9.226000e+03, 8.237110e+05],\n", + " [1.086800e+04, 6.699910e+05],\n", + " [6.151000e+03, 6.876990e+05],\n", + " [9.530000e+03, 9.745360e+05],\n", + " [7.937000e+03, 9.744740e+05],\n", + " [7.258000e+03, 9.252580e+05],\n", + " [7.873000e+03, 6.918360e+05],\n", + " [7.446000e+03, 9.952060e+05],\n", + " [7.226000e+03, 7.702230e+05],\n", + " [6.806000e+03, 6.800870e+05],\n", + " [7.648000e+03, 1.044106e+06],\n", + " [6.162000e+03, 9.667000e+05],\n", + " [6.925000e+03, 9.191240e+05],\n", + " [6.465000e+03, 7.931370e+05],\n", + " [3.553000e+03, 6.755280e+05],\n", + " [5.167000e+03, 7.108370e+05],\n", + " [5.388000e+03, 6.791930e+05],\n", + " [3.561000e+03, 7.423370e+05],\n", + " [4.304000e+03, 1.246687e+06],\n", + " [4.533000e+03, 8.514670e+05],\n", + " [4.186000e+03, 1.200236e+06],\n", + " [3.213000e+03, 9.115580e+05],\n", + " [2.901000e+03, 1.282994e+06],\n", + " [2.941000e+03, 1.163644e+06],\n", + " [2.159000e+03, 1.264644e+06],\n", + " [3.401000e+03, 8.775750e+05],\n", + " [2.461000e+03, 6.721010e+05],\n", + " [1.839000e+03, 8.773200e+05],\n", + " [3.126000e+03, 1.046437e+06],\n", + " [2.208000e+03, 8.601690e+05],\n", + " [2.425000e+03, 1.165708e+06],\n", + " [2.469000e+03, 7.259650e+05],\n", + " [1.388000e+03, 1.030986e+06],\n", + " [2.356000e+03, 8.989240e+05],\n", + " [1.357000e+03, 1.172249e+06],\n", + " [1.244000e+03, 7.215130e+05],\n", + " [1.153000e+03, 1.212616e+06],\n", + " [1.105000e+03, 7.221160e+05],\n", + " [1.336000e+03, 9.124290e+05],\n", + " [1.801000e+03, 1.322164e+06],\n", + " [1.211000e+03, 7.213810e+05],\n", + " [1.304000e+03, 9.482900e+05],\n", + " [8.840000e+02, 9.938950e+05],\n", + " [1.112000e+03, 7.034020e+05],\n", + " [8.050000e+02, 1.098286e+06],\n", + " [1.085000e+03, 1.306771e+06],\n", + " [8.380000e+02, 1.244515e+06],\n", + " [1.217000e+03, 6.741420e+05],\n", + " [6.150000e+02, 1.259647e+06],\n", + " [1.118000e+03, 7.152620e+05],\n", + " [1.051000e+03, 1.014586e+06],\n", + " [8.610000e+02, 9.689560e+05],\n", + " [7.650000e+02, 1.266521e+06],\n", + " [5.880000e+02, 1.299379e+06],\n", + " [6.360000e+02, 1.079381e+06],\n", + " [4.940000e+02, 9.751910e+05],\n", + " [6.260000e+02, 7.180640e+05],\n", + " [7.470000e+02, 1.131469e+06],\n", + " [4.680000e+02, 1.208548e+06],\n", + " [3.950000e+02, 1.273301e+06],\n", + " [6.310000e+02, 1.149921e+06],\n", + " [4.370000e+02, 1.287891e+06],\n", + " [3.060000e+02, 6.839440e+05],\n", + " [5.040000e+02, 1.324297e+06],\n", + " [4.220000e+02, 9.202280e+05],\n", + " [4.640000e+02, 1.225089e+06],\n", + " [3.390000e+02, 8.486330e+05],\n", + " [4.250000e+02, 1.208187e+06],\n", + " [4.330000e+02, 1.036617e+06],\n", + " [4.010000e+02, 1.232717e+06],\n", + " [2.850000e+02, 7.525510e+05],\n", + " [3.000000e+02, 8.188660e+05],\n", + " [2.870000e+02, 9.052010e+05],\n", + " [2.820000e+02, 1.013282e+06],\n", + " [2.440000e+02, 1.234490e+06],\n", + " [2.390000e+02, 1.250816e+06],\n", + " [1.650000e+02, 6.857060e+05],\n", + " [2.240000e+02, 1.135817e+06],\n", + " [1.490000e+02, 6.762300e+05],\n", + " [1.990000e+02, 9.279880e+05],\n", + " [2.270000e+02, 8.986760e+05],\n", + " [2.020000e+02, 9.308700e+05],\n", + " [2.010000e+02, 1.299470e+06],\n", + " [1.970000e+02, 9.945910e+05],\n", + " [1.420000e+02, 1.319829e+06],\n", + " [1.230000e+02, 1.088782e+06],\n", + " [9.500000e+01, 7.524870e+05],\n", + " [9.700000e+01, 7.591230e+05],\n", + " [9.400000e+01, 8.970040e+05],\n", + " [1.120000e+02, 1.111579e+06],\n", + " [8.600000e+01, 6.938370e+05],\n", + " [8.800000e+01, 7.845930e+05],\n", + " [7.300000e+01, 9.737570e+05],\n", + " [8.500000e+01, 1.002185e+06],\n", + " [6.100000e+01, 1.199501e+06]])" ] }, - "execution_count": 31, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -1462,7 +1281,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 27, "metadata": { "scrolled": false }, @@ -1474,16 +1293,16 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "8999599.052695096" + "9531545.662791345" ] }, - "execution_count": 33, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -1494,65 +1313,23 @@ }, { "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", - " warn('Method %s cannot handle constraints nor bounds.' % method,\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " fun: 3555725.9211099287\n", - " hess_inv: array([[ 1.12854102e-07, -2.48584571e-09, 2.27949584e-06],\n", - " [-2.48584571e-09, 9.25888041e-10, 9.47168312e-09],\n", - " [ 2.27949584e-06, 9.47168312e-09, 1.00000832e+00]])\n", - " jac: array([ 1.48618754e-02, -2.24162553e-02, -5.37171184e-08])\n", - " message: 'Desired error not necessarily achieved due to precision loss.'\n", - " nfev: 71\n", - " nit: 11\n", - " njev: 60\n", - " status: 2\n", - " success: False\n", - " x: array([3.61442328e+00, 1.98453976e-01, 9.99999326e+05])\n" - ] - } - ], - "source": [ - "# perform optimization\n", - "res = minimize(fun=objSIR.cost,\n", - " jac=objSIR.sensitivity,\n", - " x0=theta,\n", - " bounds=boxBounds,\n", - " method='BFGS')\n", - "print(res)" - ] - }, - { - "cell_type": "code", - "execution_count": 35, + "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " fun: 3555725.9211287573\n", + " fun: 3907922.0850938573\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([-7.98496027e-01, -2.01665131e+02, 2.88610490e-06])\n", + " jac: array([-1.00647944e-01, -9.22317346e+01, 3.62277449e-07])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", " nfev: 14\n", " nit: 10\n", " njev: 14\n", " status: 0\n", " success: True\n", - " x: array([3.61442613e+00, 1.98453791e-01, 1.00000000e+06])\n" + " x: array([3.59945214e+00, 1.98189223e-01, 1.00000000e+06])\n" ] } ], @@ -1568,7 +1345,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 30, "metadata": {}, "outputs": [ { @@ -1612,7 +1389,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 31, "metadata": { "scrolled": false }, @@ -1621,9 +1398,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] } @@ -1635,36 +1412,16 @@ }, { "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([-2.86825346e+02, -3.46781844e+03, 8.60476039e-04])" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "objSIR.sensitivity()" - ] - }, - { - "cell_type": "code", - "execution_count": 39, + "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "5038.2958154688895" + "5033.73795866175" ] }, - "execution_count": 39, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -1675,56 +1432,14 @@ }, { "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Local\\Continuum\\anaconda3\\envs\\pygomloss20200624\\lib\\site-packages\\scipy\\optimize\\_minimize.py:533: RuntimeWarning: Method BFGS cannot handle constraints nor bounds.\n", - " warn('Method %s cannot handle constraints nor bounds.' % method,\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " fun: 4868.230711182974\n", - " hess_inv: array([[ 7.84349281e-03, -6.15336988e-05, 1.77314305e-06],\n", - " [-6.15336988e-05, 7.88477962e-06, 1.39267526e-08],\n", - " [ 1.77314305e-06, 1.39267526e-08, 1.00000000e+00]])\n", - " jac: array([-1.03570668e-08, 1.32455900e-07, 3.71928550e-14])\n", - " message: 'Optimization terminated successfully.'\n", - " nfev: 16\n", - " nit: 11\n", - " njev: 16\n", - " status: 0\n", - " success: True\n", - " x: array([3.59106407e+00, 1.99435913e-01, 1.00000000e+06])\n" - ] - } - ], - "source": [ - "# perform optimization\n", - "res = minimize(fun=objSIR.cost,\n", - " jac=objSIR.sensitivity,\n", - " x0=theta,\n", - " bounds=boxBounds,\n", - " method='BFGS')\n", - "print(res)" - ] - }, - { - "cell_type": "code", - "execution_count": 41, + "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev8+g3f90a1d.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] }, @@ -1732,16 +1447,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " fun: 4868.230711171033\n", + " fun: 4851.585921020361\n", " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n", - " jac: array([-8.31389989e-04, -6.80463204e-03, 2.98556969e-09])\n", + " jac: array([-1.51180907e-03, -1.39068296e-02, 5.42136740e-09])\n", " message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", - " nfev: 26\n", - " nit: 12\n", - " njev: 26\n", + " nfev: 17\n", + " nit: 11\n", + " njev: 17\n", " status: 0\n", " success: True\n", - " x: array([3.59105802e+00, 1.99435910e-01, 1.00000000e+06])\n" + " x: array([3.58601328e+00, 1.99815114e-01, 1.00000000e+06])\n" ] } ], @@ -1757,7 +1472,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 34, "metadata": {}, "outputs": [ { diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index 584fe228..9363e735 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -16,7 +16,6 @@ import numpy as np -from pygom.model._model_errors import InitializeError from pygom.model.ode_utils import check_array_type from pygom.utilR.distn import dpois, gamma_mu_shape, dnbinom @@ -50,16 +49,14 @@ def __init__(self, y, weights=None): self._w = np.ones(self._y.shape) else: self._w = check_array_type(weights,accept_booleans=True) - if np.any(self._w<0.0): + if (self._w<0).any(): raise ValueError('No elements in numpy array of weights should be negative') - if np.all(self._w==0.0): + if (self._w==0).all(): raise ValueError('All elements in numpy array of weights should not be 0.0') if len(self._w.shape) > 1: if 1 in self._w.shape: - self._w = self._w.flatten() - - assert self._y.shape == self._w.shape, \ - "Input weight not of the same size as y" + self._w = self._w.flatten() + assert self._y.shape == self._w.shape, "Input weight not of the same size as y" def residual(self, yhat, apply_weighting = True): ''' @@ -188,7 +185,7 @@ def __init__(self, y, sigma=1.0, weights=None): super().__init__(y, weights) err_str = "Standard deviation not of the correct " if isinstance(sigma, np.ndarray): - if np.any(sigma<0): + if (sigma<0).any(): raise ValueError('No elements in numpy array of sigma values should be negative') elif len(sigma.shape) > 1: if 1 in sigma.shape: @@ -196,12 +193,12 @@ def __init__(self, y, sigma=1.0, weights=None): if y.shape == sigma.shape: self._sigma = sigma else: - raise InitializeError(err_str + "size") + raise AssertionError(err_str + "size") else: if y.shape == sigma.shape: self._sigma = sigma else: - raise InitializeError(err_str + "size") + raise AssertionError(err_str + "size") elif sigma is None or sigma == 1.0: self._sigma = np.ones(self._y.shape) elif isinstance(sigma, (int, float)): @@ -310,7 +307,7 @@ def __init__(self, y, shape=2.0, weights=None): super().__init__(y, weights) err_str = "Shape is not of the correct " if isinstance(shape, np.ndarray): - if np.any(shape<0): + if (shape<0).any(): raise ValueError('No elements in numpy array of shape values should be negative') elif len(shape.shape) > 1: if 1 in shape.shape: @@ -318,12 +315,12 @@ def __init__(self, y, shape=2.0, weights=None): if y.shape == shape.shape: self._shape = shape else: - raise InitializeError(err_str + "size") + raise AssertionError(err_str + "size") else: if y.shape == shape.shape: self._shape = shape else: - raise InitializeError(err_str + "size") + raise AssertionError(err_str + "size") elif shape is None or shape == 2.0: self._shape = 2*np.ones(self._y.shape) elif isinstance(shape, (int, float)): @@ -522,20 +519,20 @@ def __init__(self, y, k=1.0, weights=None): super().__init__(y, weights) err_str = "k (the overdispersion parameter) is not of the correct " if isinstance(k, np.ndarray): - if np.any(k<0): - raise ValueError('No elements in numpy array of shape values should be negative') + if (k<0).any(): + raise ValueError('No elements in numpy array of k values should be negative') elif len(k.shape) > 1: if 1 in k.shape: k = k.flatten() if y.shape == k.shape: self._k = k else: - raise InitializeError(err_str + "size") + raise AssertionError(err_str + "size") else: if y.shape == k.shape: self._k = k else: - raise InitializeError(err_str + "size") + raise AssertionError(err_str + "size") elif k is None or k == 1.0: self._k = np.ones(self._y.shape) elif isinstance(k, (int, float)): diff --git a/tests/test_loss_types.py b/tests/test_loss_types.py index c4d7fc88..6b073328 100644 --- a/tests/test_loss_types.py +++ b/tests/test_loss_types.py @@ -2,48 +2,58 @@ import numpy as np -from pygom import SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss + +from pygom import Transition, TransitionType, SimulateOde, SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss from pygom.model import common_models class Test_Square_loss_class(TestCase): def setUp(self): # initial values - self.x0 = [-1.0, 1.0] + N = 1e6 + in_inf = 1 + self.init_state = [N - in_inf, in_inf, 0.0] # params - self.param_eval = [('a', 0.2), ('b', 0.2),('c', 3.0)] + self.param_eval = [('beta', 3.6), ('gamma', 0.2), ('N', N)] # the time points for our observations - self.t = np.linspace(0, 20, 30).astype('float64') - self.ode = common_models.FitzHugh(self.param_eval) - self.ode.initial_values = (self.x0, self.t[0]) + self.t = np.arange (0 , 51 , 0.25) + states = ['S', 'I', 'R'] + params = ['beta', 'gamma', 'N'] + transitions = [Transition(origin='S', destination='I', equation='beta*S*I/N', + transition_type=TransitionType.T), + Transition(origin='I', destination='R', equation='gamma*I', + transition_type=TransitionType.T)] + self.ode = SimulateOde(states, params, transition=transitions) + self.ode.parameters = self.param_eval + self.ode.initial_values = (self.init_state, self.t[0]) # Standard. Find the solution which we will be used as # "observations later" - self.solution = self.ode.integrate(self.t[1::]) + self.solution = self.ode.integrate(self.t[1:]) # initial guess - self.theta = [0.5, 0.5, 0.5] + self.theta = [3, 0.15,N] - obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R']) + obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R']) self.r = obj.residual() def test_FH_scalar_weights_for_two_states(self): # weight for each component w = [2.0, 3.0] - + s = 0 for i in range(2): s += ((self.r[:,i]*w[i])**2).sum() - obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R'], w) + obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) self.assertTrue(np.allclose(obj.cost(), s)) def test_FH_vector_weights_for_two_states(self): # now the weight is a vector - w = np.random.rand(29, 2) - obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], - self.t[1::], self.solution[1::,:], ['V', 'R'], w) + w = np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]) + obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) s = ((self.r * np.array(w))**2).sum() @@ -52,15 +62,14 @@ def test_FH_vector_weights_for_two_states(self): def test_FH_1State_weights_Failures_TypeErrors(self): w_list = list() - w_list.append(['a']) - w_list.append([True]) - test_weight=np.ones(len(self.solution[1::,-1])) - test_weight[-1]=False + w_list.append('a') + test_weight=np.ones(len(self.solution[1::,-1])).tolist() + test_weight[-1]='b' w_list.append(test_weight) for w in w_list: with self.subTest('Weightings',w=w): self.assertRaises(TypeError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,-1], + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], 'R', w) def test_FH_1State_weights_Failures_ValueErrors(self): @@ -73,153 +82,79 @@ def test_FH_1State_weights_Failures_ValueErrors(self): for w in w_list: with self.subTest('Weightings',w=w): self.assertRaises(ValueError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,-1], + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], 'R', w) def test_FH_1State_weights_Failures_ShapeErrors(self): w_list = list() w_list.append([2.0, 3.0]) - w_list.append(np.random.rand(30)) + w_list.append(np.random.rand(self.solution[1::,-1].shape[0]+1).tolist()) for w in w_list: with self.subTest('Weightings',w=w): self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,-1], + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], 'R', w) def test_FH_2State_weights_Failures_TypeErrors(self): w_list = list() w_list.append(['a','b']) - w_list.append([True,False]) - test_weight=np.ones(self.solution[1::,:].shape) - test_weight[-1,-1]=False + test_weight=np.ones(self.solution[1::,1:3].shape).tolist() + test_weight[-1][-1]='c' w_list.append(test_weight) for w in w_list: with self.subTest('Weightings',w=w): self.assertRaises(TypeError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,:], - ['V', 'R'], w) + self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], + ['I', 'R'], w) def test_FH_2State_weights_Failures_ValueErrors(self): w_list = list() - test_weight=np.ones(self.solution[1::,:].shape) + test_weight=np.ones(self.solution[1::,1:3].shape) w_list.append(-test_weight) test_weight[-1,-1]=-1 w_list.append(test_weight) - w_list.append(np.zeros(self.solution[1::,:].shape)) + w_list.append(np.zeros(self.solution[1::,1:3].shape)) w_list.append([1.0, -1.0]) w_list.append([0, 0]) for w in w_list: with self.subTest('Weightings',w=w): self.assertRaises(ValueError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,:], - ['V', 'R'], w) + self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], + ['I', 'R'], w) def test_FH_2State_weights_Failures_ShapeErrors(self): w_list = list() w_list.append([2.0, 3.0, 4.0]) - w_list.append(np.random.rand(30)) - w_list.append([np.random.rand(30), np.random.rand(31)]) - w_list.append([np.random.rand(31), np.random.rand(31)]) - w_list.append([np.random.rand(30), np.random.rand(30), np.random.rand(30)]) + w_list.append(np.random.rand(self.solution[1::,1:3].shape[0])) + w_list.append(np.random.rand(self.solution[1::,1:3].shape[0]+1,self.solution[1::,1:3].shape[1]).tolist()) + w_list.append(np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]+1).tolist()) for w in w_list: with self.subTest('Weightings',w=w): self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, - self.x0, self.t[0], self.t[1::], self.solution[1::,:], - ['V', 'R'], w) + self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], + ['I', 'R'], w) # class Test_Normal_loss_class(TestCase): -# def setUp(self): -# # initial values -# self.x0 = [-1.0, 1.0] -# # params -# self.param_eval = [('a', 0.2), ('b', 0.2),('c', 3.0)] -# # the time points for our observations -# self.t = np.linspace(0, 20, 30).astype('float64') -# self.ode = common_models.FitzHugh(self.param_eval) -# self.ode.initial_values = (self.x0, self.t[0]) - -# # Standard. Find the solution which we will be used as -# # "observations later" -# self.solution = self.ode.integrate(self.t[1::]) -# # initial guess -# self.theta = [0.5, 0.5, 0.5] - -# obj = SquareLoss(self.theta, self.ode, self.x0, self.t[0], -# self.t[1::], self.solution[1::,:], ['V', 'R']) -# self.r = obj.residual() - -# def test_FH_Normal_scalar_weight(self): -# # weight for each component -# w = [2.0, 3.0] - -# s = 0 -# for i in range(2): s += ((self.r[:,i]*w[i])**2).sum() - -# obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], -# self.t[1::], self.solution[1::,:], ['V', 'R'], w) -# self.assertTrue(np.allclose(obj.cost(), s)) - -# def test_FH_Normal_vector_weight(self): -# # now the weight is a vector -# w = np.random.rand(29, 2) -# obj = NormalLoss(self.theta, self.ode, self.x0, self.t[0], -# self.t[1::], self.solution[1::,:], ['V', 'R'], w) - -# s = ((self.r * np.array(w))**2).sum() - -# self.assertTrue(np.allclose(obj.cost(), s)) # def test_FH_Normal(self): -# objFH = NormalLoss(self.theta, self.ode, self.x0, self.t[0], -# self.t[1::], self.solution[1::,:], ['V', 'R']) +# objFH = NormalLoss(self.theta, self.ode, self.init_state, self.t[0], +# self.t[1::], self.solution[1::,1:3], ['I', 'R']) # w = [2.0, 3.0] -# objFH1 = NormalLoss(self.theta, self.ode, self.x0, self.t[0], -# self.t[1::], self.solution[1::,:], ['V', 'R'], w) +# objFH1 = NormalLoss(self.theta, self.ode, self.init_state, self.t[0], +# self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) # # now the weight is a vector # w = np.random.rand(29, 2) -# objFH2 = NormalLoss(self.theta, self.ode, self.x0, self.t[0], -# self.t[1::], self.solution[1::,:], ['V', 'R'], w) +# objFH2 = NormalLoss(self.theta, self.ode, self.init_state, self.t[0], +# self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) # self.assertFalse(np.allclose(objFH.cost(), objFH1.cost())) # self.assertFalse(np.allclose(objFH1.cost(), objFH2.cost())) -# def test_FH_Normal_1State_Fail(self): -# ## totalFail = 0 -# ## expectedFail = 4 -# w_list = list() - -# w_list.append([-1.]) -# w_list.append([0]) -# w_list.append([2.0, 3.0]) -# w_list.append(np.random.rand(30)) - -# for w in w_list: -# self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, -# self.x0, self.t[0], self.t[1::], self.solution[1::,:], -# 'R', w) - -# def test_FH_Normal_2State_Fail(self): -# ## totalFail = 0 -# ## expectedFail = 8 -# w_list = list() - -# w_list.append([-2.0]) -# w_list.append([2.0, 3.0, 4.0]) -# w_list.append([0.0, 0.0]) -# w_list.append([1.0, -1.0]) -# w_list.append(np.random.rand(30)) -# w_list.append([np.random.rand(30), np.random.rand(31)]) -# w_list.append([np.random.rand(31), np.random.rand(31)]) -# w_list.append([np.random.rand(30), np.random.rand(30), np.random.rand(30)]) - -# for w in w_list: -# self.assertRaises(AssertionError, NormalLoss, self.theta, self.ode, -# self.x0, self.t[0], self.t[1::], self.solution[1::,:], -# 'R', w) + if __name__ == '__main__': From 990f8769fb802566f0bd3218e7c36fada5830813 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Wed, 1 Jul 2020 17:12:37 +0100 Subject: [PATCH 11/16] Unittests for weightings and comparison of costs done --- pygom/loss/base_loss.py | 51 ++- pygom/loss/loss_type.py | 6 +- pygom/loss/ode_loss.py | 27 +- .../model/ode_utils/checks_and_conversions.py | 7 +- tests/test_loss_types.py | 337 ++++++++++++++---- 5 files changed, 314 insertions(+), 114 deletions(-) diff --git a/pygom/loss/base_loss.py b/pygom/loss/base_loss.py index 9f6df6d3..e908c33d 100644 --- a/pygom/loss/base_loss.py +++ b/pygom/loss/base_loss.py @@ -44,8 +44,12 @@ class BaseLoss(object): observations state_name: str the state which the observations came from - state_weight: array like + state_weight: array like or none weight for the observations + spread_param: array like or none + spead parameter for obsevations + (e.g. normal, negative binomial and gamma distributions sigma, k and + shape, respectivly). target_param: str or array like parameters that are not fixed target_state: str or array like @@ -55,7 +59,7 @@ class BaseLoss(object): def __init__(self, theta, ode, x0, t0, t, y, - state_name, state_weight=None, + state_name, state_weight=None,spread_param=None, target_param=None, target_state=None): ### Execute all the checks first @@ -136,7 +140,9 @@ def __init__(self, theta, ode, # then if if solution.shape[1] == p: state_name = [str(i) for i in self._ode._iterStateList()] - self._setWeight(n, p, state_weight) + self._weight = self._setWeight_or_spread(n, p, state_weight,is_weights= True) + if spread_param is not None: + self._spread_param = self._setWeight_or_spread(n, p, spread_param,is_weights= False) else: raise InputError("Expecting the name of states " + "for the observations") @@ -145,7 +151,9 @@ def __init__(self, theta, ode, state_name = [state_name] assert p == len(state_name), "len(state_name) and len(y[0]) not equal" - self._setWeight(n, p, state_weight) + self._weight = self._setWeight_or_spread(n, p, state_weight,is_weights= True) + if spread_param is not None: + self._spread_param = self._setWeight_or_spread(n, p, spread_param,is_weights= False) else: raise InputError("State name should be str or of type list/tuple") @@ -1570,37 +1578,46 @@ def _setParam(self, theta): theta = ode_utils.check_array_type(theta) self._theta = np.copy(theta) - def _setWeight(self, n, p, w): + def _setWeight_or_spread(self, n, p, x,is_weights): # note that we NEVER scale the weights # also note that we can use the weights as a control # with normalized input - - w = ode_utils.check_array_type(w) - if len(w) == w.size: - m, q = len(w), 1 + x = ode_utils.check_array_type(x,accept_booleans=is_weights) + + if is_weights== True: + object_type='weights' + else: + object_type='spread parameter values' + + if len(x) == x.size: + m, q = len(x), 1 else: - m, q = w.shape + m, q = x.shape if p == q: if n == m: - self._stateWeight = w + x = x elif m == 1: - self._stateWeight = np.ones((n, p))*w + x = np.ones((n, p))*x else: - raise AssertionError("Number of input weights is not equal " + + raise AssertionError("Number of input " + object_type + + " is not equal " + "to the number of observations") elif p == m: if q == 1: - self._stateWeight = np.ones((n, p))*w + x = np.ones((n, p))*x else: - raise AssertionError("Number of input weights is not equal " + + raise AssertionError("Number of input " + object_type + + " is not equal " + "to number of states") else: if q == 1 and m == 1: - self._stateWeight = np.ones((n, p))*w + x = np.ones((n, p))*x else: - raise AssertionError("Number of input weights differs from " + + raise AssertionError("Number of input " + object_type + + " differs from " + "the number of observations") + return x def _setX0(self, x0): """ diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index 9363e735..745fd4ea 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -181,7 +181,7 @@ class Normal(baseloss_type): sigma: float standard deviation ''' - def __init__(self, y, sigma=1.0, weights=None): + def __init__(self, y, weights=None, sigma=1.0): super().__init__(y, weights) err_str = "Standard deviation not of the correct " if isinstance(sigma, np.ndarray): @@ -303,7 +303,7 @@ class Gamma(baseloss_type): shape (a in latex equations) ''' - def __init__(self, y, shape=2.0, weights=None): + def __init__(self, y, weights=None, shape=2.0): super().__init__(y, weights) err_str = "Shape is not of the correct " if isinstance(shape, np.ndarray): @@ -515,7 +515,7 @@ class NegBinom(baseloss_type): Overdispersion parameter (k=mean+mean(mean/variance)) ''' - def __init__(self, y, k=1.0, weights=None): + def __init__(self, y, weights=None, k=1.0): super().__init__(y, weights) err_str = "k (the overdispersion parameter) is not of the correct " if isinstance(k, np.ndarray): diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index e4182f54..ae0992ff 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -24,14 +24,14 @@ class SquareLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None, target_param=None, target_state=None): - super().__init__(theta, ode, x0, t0, t, y, - state_name, state_weight,target_param, target_state) + super().__init__(theta, ode, x0, t0, t, y, state_name, state_weight, + None, target_param, target_state) def __repr__(self): return "SquareLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = Square(self._y, self._stateWeight) + self._lossObj = Square(self._y, self._weight) return self._lossObj class NormalLoss(BaseLoss): @@ -40,15 +40,14 @@ class NormalLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, sigma=1.0, target_param=None, target_state=None): - self._sigma=sigma super().__init__(theta, ode, x0, t0, t, y, - state_name, state_weight,target_param, target_state) + state_name, state_weight, sigma, target_param, target_state) def __repr__(self): return "NormalLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = Normal(self._y,self._sigma, self._stateWeight) + self._lossObj = Normal(self._y, self._weight, self._spread_param) return self._lossObj class GammaLoss(BaseLoss): @@ -57,15 +56,14 @@ class GammaLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, shape=2, target_param=None, target_state=None): - self._shape=shape super().__init__(theta, ode, x0, t0, t, y, - state_name, state_weight,target_param, target_state) + state_name, state_weight, shape,target_param, target_state) def __repr__(self): return "GammaLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = Gamma(self._y,self._shape,self._stateWeight) + self._lossObj = Gamma(self._y, self._weight, self._spread_param) return self._lossObj class PoissonLoss(BaseLoss): @@ -74,14 +72,14 @@ class PoissonLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, target_param=None, target_state=None): - super().__init__(theta, ode, x0, t0, t, y, - state_name, state_weight,target_param, target_state) + super().__init__(theta, ode, x0, t0, t, y, state_name, state_weight, + None,target_param, target_state) def __repr__(self): return "PoissonLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = Poisson(self._y,self._stateWeight) + self._lossObj = Poisson(self._y,self._weight) return self._lossObj class NegBinomLoss(BaseLoss): @@ -90,13 +88,12 @@ class NegBinomLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, k=1, target_param=None, target_state=None): - self._k=k super().__init__(theta, ode, x0, t0, t, y, - state_name, state_weight,target_param, target_state) + state_name, state_weight, k, target_param, target_state) def __repr__(self): return "NegBinomLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = NegBinom(self._y,self._k,self._stateWeight) + self._lossObj = NegBinom(self._y, self._weight,self._spread_param) return self._lossObj \ No newline at end of file diff --git a/pygom/model/ode_utils/checks_and_conversions.py b/pygom/model/ode_utils/checks_and_conversions.py index b9817d85..9d24c5a3 100644 --- a/pygom/model/ode_utils/checks_and_conversions.py +++ b/pygom/model/ode_utils/checks_and_conversions.py @@ -55,7 +55,12 @@ def check_array_type(x,accept_booleans=False): else: raise TypeError(type_error_message) elif isinstance(x, accepted_types): - x = np.array([x]) + if accept_booleans==True: + x = np.array(x) + elif accept_booleans==False and not isinstance(x, bool): + x = np.array(x) + else: + TypeError("Not expecting Boolean value") else: raise TypeError("Expecting an array like object, got %s" % type(x)) diff --git a/tests/test_loss_types.py b/tests/test_loss_types.py index 6b073328..0a923a9a 100644 --- a/tests/test_loss_types.py +++ b/tests/test_loss_types.py @@ -4,9 +4,8 @@ from pygom import Transition, TransitionType, SimulateOde, SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss -from pygom.model import common_models -class Test_Square_loss_class(TestCase): +class Test_loss_classes(TestCase): def setUp(self): # initial values @@ -32,83 +31,170 @@ def setUp(self): self.solution = self.ode.integrate(self.t[1:]) # initial guess self.theta = [3, 0.15,N] + + def test_all_Loss_functions_produce_different_costs(self): + Square_obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R']) + Normal_obj = NormalLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R']) + Gamma_obj = GammaLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R']) + Poisson_obj = PoissonLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R']) + NegBinom_obj = NegBinomLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R']) + + comparisons = [[Square_obj.cost(),Normal_obj.cost(),'SquareLoss compared to NormalLoss'], + [Square_obj.cost(),Gamma_obj.cost(),'SquareLoss compared to GammaLoss'], + [Square_obj.cost(),Poisson_obj.cost(),'SquareLoss compared to PossionLoss'], + [Square_obj.cost(),NegBinom_obj.cost(),'SquareLoss compared to NegBinomLoss'], + [Normal_obj.cost(),Gamma_obj.cost(),'NormalLoss compared to GammaLoss'], + [Normal_obj.cost(),Poisson_obj.cost(),'NormalLoss compared to PossionLoss'], + [Normal_obj.cost(),NegBinom_obj.cost(),'NormalLoss compared to NegBinomLoss'], + [Gamma_obj.cost(),Poisson_obj.cost(),'GammaLoss compared to PossionLoss'], + [Gamma_obj.cost(),NegBinom_obj.cost(),'GammaLoss compared to NegBinomLoss'], + [Poisson_obj.cost(),NegBinom_obj.cost(),'PoissonLoss compared to NegBinomLoss'] + ] + + for comparison in comparisons: + message = comparison[-1] + with self.subTest(message): + self.assertNotAlmostEqual(comparison[0],comparison[1],places=2) - obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], - self.t[1::], self.solution[1::,1:3], ['I', 'R']) - self.r = obj.residual() - def test_FH_scalar_weights_for_two_states(self): + def test_Square_and_Normal_Loss_cost_scalar_weights_for_two_states(self): + loss_functions = [SquareLoss, NormalLoss] # weight for each component w = [2.0, 3.0] - s = 0 - for i in range(2): s += ((self.r[:,i]*w[i])**2).sum() - obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], - self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - - self.assertTrue(np.allclose(obj.cost(), s)) + self.t[1::], self.solution[1::,1:3], ['I', 'R']) + self.r = obj.residual() + residual = [] + for i in range(2): + residual.append(self.r[:,i]*w[i]) + + residual = np.array(residual) + + square_cost = (residual**2).sum() + sigma= 1 + norm_logpdf_p1= -np.log(2) + norm_logpdf_p2= np.log(2)/2 + norm_logpdf_p3= -np.log(np.pi)/2 + norm_logpdf_p4= np.log(1/sigma) + norm_logpdf_p5_alt= -residual**2 / (2*sigma**2) + norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + test_answers=[square_cost,norm_cost] + + for loss_function_index in range(len(loss_functions)): + loss_function= loss_functions[loss_function_index] + message = str(loss_function) + with self.subTest(message): + obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=2) - def test_FH_vector_weights_for_two_states(self): + def test_Square_and_Normal_Loss_cost_vector_weights_for_two_states(self): + loss_functions = [SquareLoss, NormalLoss] + obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R']) + self.r = obj.residual() # now the weight is a vector w = np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]) - obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], - self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - - s = ((self.r * np.array(w))**2).sum() - - self.assertTrue(np.allclose(obj.cost(), s)) - + + residual = self.r* np.array(w) + square_cost = (residual**2).sum() + sigma= 1 + norm_logpdf_p1= -np.log(2) + norm_logpdf_p2= np.log(2)/2 + norm_logpdf_p3= -np.log(np.pi)/2 + norm_logpdf_p4= np.log(1/sigma) + norm_logpdf_p5_alt= -residual**2 / (2*sigma**2) + norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + + test_answers=[square_cost,norm_cost] - def test_FH_1State_weights_Failures_TypeErrors(self): + for loss_function_index in range(len(loss_functions)): + loss_function= loss_functions[loss_function_index] + message = str(loss_function) + with self.subTest(message): + obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=2) + + + def test_All_Loss_functions_1State_weights_Failures_TypeErrors(self): + loss_functions = [SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss] w_list = list() w_list.append('a') test_weight=np.ones(len(self.solution[1::,-1])).tolist() test_weight[-1]='b' w_list.append(test_weight) - for w in w_list: - with self.subTest('Weightings',w=w): - self.assertRaises(TypeError, SquareLoss, self.theta, self.ode, - self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], - 'R', w) + for loss_function in loss_functions: + for weight_index in range(len(w_list)): + w = w_list[weight_index] + message = str(loss_function)+' with weighting '+str(weight_index) + with self.subTest(message): + self.assertRaises(TypeError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', w) - def test_FH_1State_weights_Failures_ValueErrors(self): + def test_AllLoss_1State_weights_Failures_ValueErrors(self): + loss_functions = [SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss] w_list = list() + w_list.append(-1) + w_list.append(0) test_weight=np.ones(len(self.solution[1::,-1])) w_list.append(-test_weight) test_weight[-1]=-1 w_list.append(test_weight) w_list.append(np.zeros(len(self.solution[1::,-1]))) - for w in w_list: - with self.subTest('Weightings',w=w): - self.assertRaises(ValueError, SquareLoss, self.theta, self.ode, - self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], - 'R', w) + for loss_function in loss_functions: + for weight_index in range(len(w_list)): + w = w_list[weight_index] + message = str(loss_function)+' with weighting '+str(weight_index) + with self.subTest(message): + self.assertRaises(ValueError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', w) - def test_FH_1State_weights_Failures_ShapeErrors(self): + def test_AllLoss_1State_weights_Failures_ShapeErrors(self): + loss_functions = [SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss] w_list = list() w_list.append([2.0, 3.0]) w_list.append(np.random.rand(self.solution[1::,-1].shape[0]+1).tolist()) - for w in w_list: - with self.subTest('Weightings',w=w): - self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, - self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], - 'R', w) + for loss_function in loss_functions: + for weight_index in range(len(w_list)): + w = w_list[weight_index] + message = str(loss_function)+' with weighting '+str(weight_index) + with self.subTest(message): + self.assertRaises(AssertionError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', w) - def test_FH_2State_weights_Failures_TypeErrors(self): + def test_AllLoss_2State_weights_Failures_TypeErrors(self): + loss_functions = [SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss] w_list = list() w_list.append(['a','b']) test_weight=np.ones(self.solution[1::,1:3].shape).tolist() test_weight[-1][-1]='c' w_list.append(test_weight) - for w in w_list: - with self.subTest('Weightings',w=w): - self.assertRaises(TypeError, SquareLoss, self.theta, self.ode, - self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], - ['I', 'R'], w) + for loss_function in loss_functions: + for weight_index in range(len(w_list)): + w = w_list[weight_index] + message = str(loss_function)+' with weighting '+str(weight_index) + with self.subTest(message): + self.assertRaises(TypeError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], + self.solution[1::,1:3],['I', 'R'], w) - def test_FH_2State_weights_Failures_ValueErrors(self): + def test_AllLoss_2State_weights_Failures_ValueErrors(self): + loss_functions = [SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss] w_list = list() + w_list.append(-1) + w_list.append(0) test_weight=np.ones(self.solution[1::,1:3].shape) w_list.append(-test_weight) test_weight[-1,-1]=-1 @@ -116,46 +202,141 @@ def test_FH_2State_weights_Failures_ValueErrors(self): w_list.append(np.zeros(self.solution[1::,1:3].shape)) w_list.append([1.0, -1.0]) w_list.append([0, 0]) - for w in w_list: - with self.subTest('Weightings',w=w): - self.assertRaises(ValueError, SquareLoss, self.theta, self.ode, - self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], - ['I', 'R'], w) + for loss_function in loss_functions: + for weight_index in range(len(w_list)): + w = w_list[weight_index] + message = str(loss_function)+' with weighting '+str(weight_index) + with self.subTest(message): + self.assertRaises(ValueError, loss_function, self.theta, + self.ode,self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], + ['I', 'R'], w) - def test_FH_2State_weights_Failures_ShapeErrors(self): + def test_AllLoss_2State_weights_Failures_ShapeErrors(self): + loss_functions = [SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss] w_list = list() w_list.append([2.0, 3.0, 4.0]) w_list.append(np.random.rand(self.solution[1::,1:3].shape[0])) w_list.append(np.random.rand(self.solution[1::,1:3].shape[0]+1,self.solution[1::,1:3].shape[1]).tolist()) w_list.append(np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]+1).tolist()) - for w in w_list: - with self.subTest('Weightings',w=w): - self.assertRaises(AssertionError, SquareLoss, self.theta, self.ode, - self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], - ['I', 'R'], w) - -# class Test_Normal_loss_class(TestCase): - - - -# def test_FH_Normal(self): -# objFH = NormalLoss(self.theta, self.ode, self.init_state, self.t[0], -# self.t[1::], self.solution[1::,1:3], ['I', 'R']) - -# w = [2.0, 3.0] -# objFH1 = NormalLoss(self.theta, self.ode, self.init_state, self.t[0], -# self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - -# # now the weight is a vector -# w = np.random.rand(29, 2) -# objFH2 = NormalLoss(self.theta, self.ode, self.init_state, self.t[0], -# self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - -# self.assertFalse(np.allclose(objFH.cost(), objFH1.cost())) -# self.assertFalse(np.allclose(objFH1.cost(), objFH2.cost())) - - + for loss_function in loss_functions: + for weight_index in range(len(w_list)): + w = w_list[weight_index] + message = str(loss_function)+' with weighting '+str(weight_index) + with self.subTest(message): + self.assertRaises(AssertionError, loss_function, self.theta, + self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], + ['I', 'R'], w) + + + def test_Applicable_Loss_functions_1State_spread_param_Failures_TypeErrors(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + spread_param_list = list() + spread_param_list.append('a') + spread_param_list.append(True) + test_spread_param=np.ones(len(self.solution[1::,-1])).tolist() + test_spread_param[-1]='b' + spread_param_list.append(test_spread_param) + test_spread_param[-1]=False + spread_param_list.append(test_spread_param) + for loss_function in loss_functions: + for spread_param_index in range(len(spread_param_list)): + spread_param = spread_param_list[spread_param_index] + message = str(loss_function)+' with spread params '+str(spread_param_index) + with self.subTest(message): + self.assertRaises(TypeError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', None,spread_param) + + def test_Applicable_Loss_functionss_1State_spread_param_Failures_ValueErrors(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + spread_param_list = list() + spread_param_list.append(-1) + test_spread_param=np.ones(len(self.solution[1::,-1])) + spread_param_list.append(-test_spread_param) + test_spread_param[-1]=-1 + spread_param_list.append(test_spread_param) + for loss_function in loss_functions: + for spread_param_index in range(len(spread_param_list)): + spread_param = spread_param_list[spread_param_index] + message = str(loss_function)+' with spread params'+str(spread_param_index) + with self.subTest(message): + self.assertRaises(ValueError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', None,spread_param) + + def test_Applicable_Loss_functions_1State_spread_param_Failures_ShapeErrors(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + spread_param_list = list() + spread_param_list.append([2.0, 3.0]) + spread_param_list.append(np.random.rand(self.solution[1::,-1].shape[0]+1).tolist()) + for loss_function in loss_functions: + for spread_param_index in range(len(spread_param_list)): + spread_param = spread_param_list[spread_param_index] + message = str(loss_function)+' with spread params'+str(spread_param_index) + with self.subTest(message): + self.assertRaises(AssertionError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], + 'R', None,spread_param) + def test_Applicable_Loss_functions_2State_spread_param_Failures_TypeErrors(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + spread_param_list = list() + spread_param_list.append('a') + spread_param_list.append(True) + spread_param_list.append(['a','b']) + spread_param_list.append([True,False]) + test_spread_param=np.ones(self.solution[1::,1:3].shape).tolist() + test_spread_param[-1][-1]='c' + spread_param_list.append(test_spread_param) + test_spread_param[-1][-1]=False + spread_param_list.append(test_spread_param) + for loss_function in loss_functions: + for spread_param_index in range(len(spread_param_list)): + spread_param = spread_param_list[spread_param_index] + message = str(loss_function)+' with spread params'+str(spread_param_index) + with self.subTest(message): + self.assertRaises(TypeError, loss_function, self.theta, self.ode, + self.init_state, self.t[0], self.t[1::], + self.solution[1::,1:3],['I', 'R'], None,spread_param) + + def test_Applicable_Loss_functions_2State_spread_param_Failures_ValueErrors(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + spread_param_list = list() + spread_param_list.append(-1) + test_spread_param=np.ones(self.solution[1::,1:3].shape) + spread_param_list.append(-test_spread_param) + test_spread_param[-1,-1]=-1 + spread_param_list.append(test_spread_param) + spread_param_list.append([1.0, -1.0]) + spread_param_list.append([-1.0, -1.0]) + for loss_function in loss_functions: + for spread_param_index in range(len(spread_param_list)): + spread_param = spread_param_list[spread_param_index] + message = str(loss_function)+' with spread params'+str(spread_param_index) + with self.subTest(message): + self.assertRaises(ValueError, loss_function, self.theta, + self.ode,self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], + ['I', 'R'], None,spread_param) + + def test_Applicable_Loss_functions_2State_spread_param_Failures_ShapeErrors(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + spread_param_list = list() + spread_param_list.append([2.0, 3.0, 4.0]) + spread_param_list.append(np.random.rand(self.solution[1::,1:3].shape[0])) + spread_param_list.append(np.random.rand(self.solution[1::,1:3].shape[0]+1,self.solution[1::,1:3].shape[1]).tolist()) + spread_param_list.append(np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]+1).tolist()) + for loss_function in loss_functions: + for spread_param_index in range(len(spread_param_list)): + spread_param = spread_param_list[spread_param_index] + message = str(loss_function)+' with spread params'+str(spread_param_index) + with self.subTest(message): + self.assertRaises(AssertionError, loss_function, self.theta, + self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], + ['I', 'R'], None,spread_param) if __name__ == '__main__': main() From 2395c5544640d4de1fa9513c1a405b1ba40f1414 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Thu, 2 Jul 2020 13:28:11 +0100 Subject: [PATCH 12/16] Finished unittesting new loss functions, leading to several bug fixes and improvements --- ...s functions fitted to simulated data.ipynb | 294 ++++++++++-------- pygom/loss/base_loss.py | 23 +- .../model/ode_utils/checks_and_conversions.py | 28 +- tests/test_loss_types.py | 171 ++++++---- 4 files changed, 302 insertions(+), 214 deletions(-) diff --git a/notebooks/Testing loss functions fitted to simulated data.ipynb b/notebooks/Testing loss functions fitted to simulated data.ipynb index 150ab517..dc0c813b 100644 --- a/notebooks/Testing loss functions fitted to simulated data.ipynb +++ b/notebooks/Testing loss functions fitted to simulated data.ipynb @@ -660,26 +660,6 @@ "data_to_fit" ] }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "406" - ] - }, - "execution_count": 54, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.prod(data_to_fit.shape)" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -689,7 +669,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -698,7 +678,7 @@ "[('beta', 3.6), ('gamma', 0.2), ('N', 1000000.0)]" ] }, - "execution_count": 13, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -709,22 +689,7 @@ }, { "cell_type": "code", - "execution_count": 14, - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "# Initial guess of parameters, and bounding constraints\n", - "theta = [3, 0.15,N]\n", - "boxBounds = [(2,5),(0.0,1.0),(N,N)]\n", - "\n", - "objSIR = SquareLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" - ] - }, - { - "cell_type": "code", - "execution_count": 15, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -733,18 +698,24 @@ "9494886226076.777" ] }, - "execution_count": 15, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "theta = [3, 0.15,N]\n", + "boxBounds = [(2,5),(0.0,1.0),(N,N)]\n", + "\n", + "objSIR = SquareLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])\n", + "\n", "objSIR.cost()" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -776,7 +747,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -820,19 +791,7 @@ }, { "cell_type": "code", - "execution_count": 18, - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "# Initial guess of parameters, and bounding constraints\n", - "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" - ] - }, - { - "cell_type": "code", - "execution_count": 19, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -841,18 +800,21 @@ "4747443113411.479" ] }, - "execution_count": 19, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])\n", + "\n", "objSIR.cost()" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -884,7 +846,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -920,27 +882,61 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 20, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "18989772452245.23" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "## Fitting Gamma loss" + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'],sigma=0.5)\n", + "\n", + "objSIR.cost()" ] }, { "cell_type": "code", - "execution_count": 22, - "metadata": { - "scrolled": false - }, - "outputs": [], + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5804367986465.104" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Initial guess of parameters, and bounding constraints\n", - "objSIR = GammaLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])" + "objSIR = NormalLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'],sigma=[0.5,1.5])\n", + "\n", + "objSIR.cost()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fitting Gamma loss" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -949,25 +945,28 @@ "5066.230498539779" ] }, - "execution_count": 23, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = GammaLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'])\n", + "\n", "objSIR.cost()" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev11+g990f876.d20200702-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:108: RuntimeWarning: invalid value encountered in log\n", " logpdf_p3= -shape*np.log(mu/shape)\n" ] }, @@ -1000,7 +999,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -1035,6 +1034,52 @@ "display(theta,boxBounds,param_evals)" ] }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5105.389439344021" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = GammaLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'],shape=0.5)\n", + "\n", + "objSIR.cost()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5044.423929863387" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = GammaLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=data_to_fit, state_name=['I','R'],shape=[0.5,1])\n", + "\n", + "objSIR.cost()" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1051,7 +1096,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -1262,7 +1307,7 @@ " [6.100000e+01, 1.199501e+06]])" ] }, - "execution_count": 26, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -1279,18 +1324,6 @@ "## Poisson loss" ] }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "# Initial guess of parameters, and bounding constraints\n", - "objSIR = PoissonLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'])" - ] - }, { "cell_type": "code", "execution_count": 28, @@ -1308,6 +1341,9 @@ } ], "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = PoissonLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'])\n", + "\n", "objSIR.cost()" ] }, @@ -1390,56 +1426,46 @@ { "cell_type": "code", "execution_count": 31, - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev11+g990f876.d20200702-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: divide by zero encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n", - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev11+g990f876.d20200702-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in multiply\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] - } - ], - "source": [ - "# Initial guess of parameters, and bounding constraints\n", - "objSIR = NegBinomLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'])" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ + }, { "data": { "text/plain": [ "5033.73795866175" ] }, - "execution_count": 32, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = NegBinomLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'])\n", + "\n", "objSIR.cost()" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev9+g9b40b86.d20200630-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", + "C:\\Users\\martin.grunnill\\AppData\\Roaming\\Python\\Python38\\site-packages\\pygom-0.1.7.dev11+g990f876.d20200702-py3.8-win-amd64.egg\\pygom\\utilR\\distn.py:450: RuntimeWarning: invalid value encountered in log\n", " logpmf_p4= x*(np.log(mu) - np.log(k + mu))\n" ] }, @@ -1472,7 +1498,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 33, "metadata": {}, "outputs": [ { @@ -1509,31 +1535,49 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, + "execution_count": 34, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/plain": [ + "5107.155188410919" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = NegBinomLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'],k=0.5)\n", + "\n", + "objSIR.cost()" + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/plain": [ + "5024.382571986069" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Initial guess of parameters, and bounding constraints\n", + "objSIR = NegBinomLoss(theta, model, x0=data[0,:], t0=t[0], t=t[1::], y=int_data_to_fit, state_name=['I','R'],k=[0.5,1.5])\n", + "\n", + "objSIR.cost()" + ] } ], "metadata": { diff --git a/pygom/loss/base_loss.py b/pygom/loss/base_loss.py index e908c33d..826ad453 100644 --- a/pygom/loss/base_loss.py +++ b/pygom/loss/base_loss.py @@ -207,8 +207,8 @@ def _get_model_str(self): self._observeT.tolist(), self._y.tolist(), self._stateName) - if self._stateWeight is not None: - model_str += ", %s" % self._stateWeight.tolist() + if self._weight is not None: + model_str += ", %s" % self._weight.tolist() if self._targetParam is not None: model_str += ", %s" % self._targetParam if self._targetState is not None: @@ -1169,7 +1169,7 @@ def sens_to_grad(self, sens, diff_loss): sens = np.reshape(sens, (n, num_s, num_out), 'F') for j in range(num_out): - sens[:, :, j] *= self._stateWeight + sens[:, :, j] *= self._weight grad = functools.reduce(np.add,map(np.dot, diff_loss, sens)).ravel() @@ -1209,7 +1209,7 @@ def sens_to_jtj(self, sens, resid=None): sens = np.reshape(sens, (n, num_s, num_out), 'F') for j in range(num_out): - sens[:,:,j] *= self._stateWeight + sens[:,:,j] *= self._weight for i, s in enumerate(sens): if resid is None: @@ -1581,13 +1581,12 @@ def _setParam(self, theta): def _setWeight_or_spread(self, n, p, x,is_weights): # note that we NEVER scale the weights # also note that we can use the weights as a control - # with normalized input + # with normalized input x = ode_utils.check_array_type(x,accept_booleans=is_weights) - if is_weights== True: - object_type='weights' + object_contents='weights' else: - object_type='spread parameter values' + object_contents='spread parameter values' if len(x) == x.size: m, q = len(x), 1 @@ -1600,21 +1599,21 @@ def _setWeight_or_spread(self, n, p, x,is_weights): elif m == 1: x = np.ones((n, p))*x else: - raise AssertionError("Number of input " + object_type + + raise AssertionError("Number of input " + object_contents + " is not equal " + "to the number of observations") elif p == m: if q == 1: x = np.ones((n, p))*x else: - raise AssertionError("Number of input " + object_type + + raise AssertionError("Number of input " + object_contents + " is not equal " + "to number of states") else: if q == 1 and m == 1: x = np.ones((n, p))*x else: - raise AssertionError("Number of input " + object_type + + raise AssertionError("Number of input " + object_contents + " differs from " + "the number of observations") return x @@ -1633,7 +1632,7 @@ def _setLossType(self): be override in the module odeLoss. Basically, all other operations remains but this will change. """ - self._lossObj = Square(self._y, self._stateWeight) + self._lossObj = Square(self._y, self._weight) return self._lossObj def _unrollParam(self, theta): diff --git a/pygom/model/ode_utils/checks_and_conversions.py b/pygom/model/ode_utils/checks_and_conversions.py index 9d24c5a3..8ca427fc 100644 --- a/pygom/model/ode_utils/checks_and_conversions.py +++ b/pygom/model/ode_utils/checks_and_conversions.py @@ -37,28 +37,26 @@ def check_array_type(x,accept_booleans=False): if all(isinstance(item, accepted_types) for item in x): if accept_booleans==True: x = np.array(x) - elif accept_booleans==False and all(not isinstance(item, bool) for item in x): + elif accept_booleans==False: + if any(isinstance(item, bool) for item in x): + raise TypeError('No elements of array type object should be Boolean values') x = np.array(x) else: TypeError(type_error_message) elif isinstance(x[0], (list, tuple, np.ndarray)): - sub_items_accepted = [] for item in x: - if accept_booleans==False: - sub_items_accepted.append(all(isinstance(sub_item, accepted_types) for sub_item in item)*all(not isinstance(sub_item, bool) for sub_item in item)) - if accept_booleans==True: - sub_items_accepted.append(all(isinstance(sub_item, accepted_types) for sub_item in item)) - if all(sub_items_accepted): - x = np.array(x) - else: - raise TypeError(type_error_message) + if any(not isinstance(sub_item, accepted_types) for sub_item in item): + raise TypeError(type_error_message) + if accept_booleans==False and any(isinstance(sub_item, bool) for sub_item in item): + raise TypeError('No elements of array type object should be Boolean values') + x = np.array(x) else: raise TypeError(type_error_message) elif isinstance(x, accepted_types): if accept_booleans==True: - x = np.array(x) + x = np.array([x]) elif accept_booleans==False and not isinstance(x, bool): - x = np.array(x) + x = np.array([x]) else: TypeError("Not expecting Boolean value") else: @@ -91,8 +89,8 @@ def check_dimension(x, y): x = check_array_type(x) if len(y) != len(x): - raise InputError("The number of observations and time points " + - "should have the same length") + raise AssertionError("The number of observations and time points " + + "should have the same length") return (x, y) @@ -137,7 +135,7 @@ def str_or_list(x): elif isinstance(x, str): return [x] else: - raise InputError("Expecting a string or list") + raise TypeError("Expecting a string or list") def none_or_empty_list(x): diff --git a/tests/test_loss_types.py b/tests/test_loss_types.py index 0a923a9a..8de89766 100644 --- a/tests/test_loss_types.py +++ b/tests/test_loss_types.py @@ -4,6 +4,8 @@ from pygom import Transition, TransitionType, SimulateOde, SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss +from pygom.utilR.distn import gamma_mu_shape, dnbinom +import copy class Test_loss_classes(TestCase): @@ -30,7 +32,10 @@ def setUp(self): # "observations later" self.solution = self.ode.integrate(self.t[1:]) # initial guess - self.theta = [3, 0.15,N] + self.theta = [3.6, 0.2,N] + self.yhat_ode=copy.deepcopy(self.ode) + self.yhat_ode.parameters = [('beta', self.theta[0]), ('gamma', self.theta[1]), ('N', N)] + self.yhat= self.yhat_ode.integrate(self.t[1:]) def test_all_Loss_functions_produce_different_costs(self): Square_obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], @@ -45,34 +50,31 @@ def test_all_Loss_functions_produce_different_costs(self): self.t[1::], self.solution[1::,1:3], ['I', 'R']) comparisons = [[Square_obj.cost(),Normal_obj.cost(),'SquareLoss compared to NormalLoss'], - [Square_obj.cost(),Gamma_obj.cost(),'SquareLoss compared to GammaLoss'], - [Square_obj.cost(),Poisson_obj.cost(),'SquareLoss compared to PossionLoss'], - [Square_obj.cost(),NegBinom_obj.cost(),'SquareLoss compared to NegBinomLoss'], - [Normal_obj.cost(),Gamma_obj.cost(),'NormalLoss compared to GammaLoss'], - [Normal_obj.cost(),Poisson_obj.cost(),'NormalLoss compared to PossionLoss'], - [Normal_obj.cost(),NegBinom_obj.cost(),'NormalLoss compared to NegBinomLoss'], - [Gamma_obj.cost(),Poisson_obj.cost(),'GammaLoss compared to PossionLoss'], - [Gamma_obj.cost(),NegBinom_obj.cost(),'GammaLoss compared to NegBinomLoss'], - [Poisson_obj.cost(),NegBinom_obj.cost(),'PoissonLoss compared to NegBinomLoss'] - ] + [Square_obj.cost(),Gamma_obj.cost(),'SquareLoss compared to GammaLoss'], + [Square_obj.cost(),Poisson_obj.cost(),'SquareLoss compared to PossionLoss'], + [Square_obj.cost(),NegBinom_obj.cost(),'SquareLoss compared to NegBinomLoss'], + [Normal_obj.cost(),Gamma_obj.cost(),'NormalLoss compared to GammaLoss'], + [Normal_obj.cost(),Poisson_obj.cost(),'NormalLoss compared to PossionLoss'], + [Normal_obj.cost(),NegBinom_obj.cost(),'NormalLoss compared to NegBinomLoss'], + [Gamma_obj.cost(),Poisson_obj.cost(),'GammaLoss compared to PossionLoss'], + [Gamma_obj.cost(),NegBinom_obj.cost(),'GammaLoss compared to NegBinomLoss'], + [Poisson_obj.cost(),NegBinom_obj.cost(),'PoissonLoss compared to NegBinomLoss'] + ] for comparison in comparisons: message = comparison[-1] with self.subTest(message): - self.assertNotAlmostEqual(comparison[0],comparison[1],places=2) + self.assertNotAlmostEqual(comparison[0],comparison[1],places=0) def test_Square_and_Normal_Loss_cost_scalar_weights_for_two_states(self): loss_functions = [SquareLoss, NormalLoss] # weight for each component w = [2.0, 3.0] - - obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], - self.t[1::], self.solution[1::,1:3], ['I', 'R']) - self.r = obj.residual() + r = self.solution[1::,1:3]-self.yhat[1::,1:3] residual = [] for i in range(2): - residual.append(self.r[:,i]*w[i]) + residual.append(r[:,i]*w[i]) residual = np.array(residual) @@ -84,7 +86,7 @@ def test_Square_and_Normal_Loss_cost_scalar_weights_for_two_states(self): norm_logpdf_p4= np.log(1/sigma) norm_logpdf_p5_alt= -residual**2 / (2*sigma**2) norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ - norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() test_answers=[square_cost,norm_cost] for loss_function_index in range(len(loss_functions)): @@ -93,17 +95,15 @@ def test_Square_and_Normal_Loss_cost_scalar_weights_for_two_states(self): with self.subTest(message): obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=2) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) def test_Square_and_Normal_Loss_cost_vector_weights_for_two_states(self): loss_functions = [SquareLoss, NormalLoss] - obj = SquareLoss(self.theta, self.ode, self.init_state, self.t[0], - self.t[1::], self.solution[1::,1:3], ['I', 'R']) - self.r = obj.residual() + r = self.solution[1::,1:3]-self.yhat[1::,1:3] # now the weight is a vector w = np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]) - residual = self.r* np.array(w) + residual = r* w square_cost = (residual**2).sum() sigma= 1 norm_logpdf_p1= -np.log(2) @@ -112,7 +112,7 @@ def test_Square_and_Normal_Loss_cost_vector_weights_for_two_states(self): norm_logpdf_p4= np.log(1/sigma) norm_logpdf_p5_alt= -residual**2 / (2*sigma**2) norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ - norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() test_answers=[square_cost,norm_cost] @@ -122,7 +122,7 @@ def test_Square_and_Normal_Loss_cost_vector_weights_for_two_states(self): with self.subTest(message): obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=2) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) def test_All_Loss_functions_1State_weights_Failures_TypeErrors(self): @@ -133,9 +133,8 @@ def test_All_Loss_functions_1State_weights_Failures_TypeErrors(self): test_weight[-1]='b' w_list.append(test_weight) for loss_function in loss_functions: - for weight_index in range(len(w_list)): - w = w_list[weight_index] - message = str(loss_function)+' with weighting '+str(weight_index) + for w in w_list: + message = str(loss_function)+' with weighting '+str(w) with self.subTest(message): self.assertRaises(TypeError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], @@ -152,9 +151,8 @@ def test_AllLoss_1State_weights_Failures_ValueErrors(self): w_list.append(test_weight) w_list.append(np.zeros(len(self.solution[1::,-1]))) for loss_function in loss_functions: - for weight_index in range(len(w_list)): - w = w_list[weight_index] - message = str(loss_function)+' with weighting '+str(weight_index) + for w in w_list: + message = str(loss_function)+' with weighting '+str(w) with self.subTest(message): self.assertRaises(ValueError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], @@ -166,9 +164,8 @@ def test_AllLoss_1State_weights_Failures_ShapeErrors(self): w_list.append([2.0, 3.0]) w_list.append(np.random.rand(self.solution[1::,-1].shape[0]+1).tolist()) for loss_function in loss_functions: - for weight_index in range(len(w_list)): - w = w_list[weight_index] - message = str(loss_function)+' with weighting '+str(weight_index) + for w in w_list: + message = str(loss_function)+' with weighting '+str(w) with self.subTest(message): self.assertRaises(AssertionError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], @@ -182,9 +179,8 @@ def test_AllLoss_2State_weights_Failures_TypeErrors(self): test_weight[-1][-1]='c' w_list.append(test_weight) for loss_function in loss_functions: - for weight_index in range(len(w_list)): - w = w_list[weight_index] - message = str(loss_function)+' with weighting '+str(weight_index) + for w in w_list: + message = str(loss_function)+' with weighting '+str(w) with self.subTest(message): self.assertRaises(TypeError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], @@ -203,9 +199,8 @@ def test_AllLoss_2State_weights_Failures_ValueErrors(self): w_list.append([1.0, -1.0]) w_list.append([0, 0]) for loss_function in loss_functions: - for weight_index in range(len(w_list)): - w = w_list[weight_index] - message = str(loss_function)+' with weighting '+str(weight_index) + for w in w_list: + message = str(loss_function)+' with weighting '+str(w) with self.subTest(message): self.assertRaises(ValueError, loss_function, self.theta, self.ode,self.init_state, self.t[0], @@ -220,15 +215,73 @@ def test_AllLoss_2State_weights_Failures_ShapeErrors(self): w_list.append(np.random.rand(self.solution[1::,1:3].shape[0]+1,self.solution[1::,1:3].shape[1]).tolist()) w_list.append(np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]+1).tolist()) for loss_function in loss_functions: - for weight_index in range(len(w_list)): - w = w_list[weight_index] - message = str(loss_function)+' with weighting '+str(weight_index) + for w in w_list: + message = str(loss_function)+' with weighting '+str(w) with self.subTest(message): self.assertRaises(AssertionError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - + + def test_Applicable_Loss_functions_cost_scalar_spread_params_for_two_states(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + # weight for each component + spread_params = [0.5, 1.5] + spread_params_unraveled = np.array([spread_params[0]* + np.ones(self.solution[1::,1:3].shape[0]), + spread_params[1]* + np.ones(self.solution[1::,1:3].shape[0])]).transpose().flatten() + y=self.solution[1::,1:3].flatten() + yhat = self.yhat[1::,1:3].flatten() + residual = y-yhat + norm_logpdf_p1= -np.log(2) + norm_logpdf_p2= np.log(2)/2 + norm_logpdf_p3= -np.log(np.pi)/2 + norm_logpdf_p4= np.log(1/spread_params_unraveled) + norm_logpdf_p5_alt= -residual**2 / (2*spread_params_unraveled**2) + norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + + gamma_cost=(-gamma_mu_shape(x=y, mu=yhat,shape=spread_params_unraveled,log=True)).sum() + NegBinom_cost=(-dnbinom(x=y, mu=yhat,size=spread_params_unraveled,log=True)).sum() + + test_answers=[norm_cost,gamma_cost,NegBinom_cost] + + for loss_function_index in range(len(loss_functions)): + loss_function= loss_functions[loss_function_index] + message = str(loss_function) + with self.subTest(message): + obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R'], None,spread_params) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) + + def test_Applicable_Loss_functions_cost_vector_spread_params_for_two_states(self): + loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] + y=self.solution[1::,1:3].flatten() + yhat = self.yhat[1::,1:3].flatten() + residual = y-yhat + # now the weight is a vector + spread_params = np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]) + spread_params_unraveled=spread_params.flatten() + norm_logpdf_p1= -np.log(2) + norm_logpdf_p2= np.log(2)/2 + norm_logpdf_p3= -np.log(np.pi)/2 + norm_logpdf_p4= np.log(1/spread_params_unraveled) + norm_logpdf_p5_alt= -residual**2 / (2*spread_params_unraveled**2) + norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + gamma_cost=(-gamma_mu_shape(x=y, mu=yhat,shape=spread_params_unraveled,log=True)).sum() + NegBinom_cost=(-dnbinom(x=y, mu=yhat,size=spread_params_unraveled,log=True)).sum() + + test_answers=[norm_cost,gamma_cost,NegBinom_cost] + + for loss_function_index in range(len(loss_functions)): + loss_function= loss_functions[loss_function_index] + message = str(loss_function) + with self.subTest(message): + obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], + self.t[1::], self.solution[1::,1:3], ['I', 'R'], None,spread_params) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) def test_Applicable_Loss_functions_1State_spread_param_Failures_TypeErrors(self): loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] @@ -241,9 +294,8 @@ def test_Applicable_Loss_functions_1State_spread_param_Failures_TypeErrors(self) test_spread_param[-1]=False spread_param_list.append(test_spread_param) for loss_function in loss_functions: - for spread_param_index in range(len(spread_param_list)): - spread_param = spread_param_list[spread_param_index] - message = str(loss_function)+' with spread params '+str(spread_param_index) + for spread_param in spread_param_list: + message = str(loss_function)+' with spread params '+str(spread_param) with self.subTest(message): self.assertRaises(TypeError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], @@ -258,9 +310,8 @@ def test_Applicable_Loss_functionss_1State_spread_param_Failures_ValueErrors(sel test_spread_param[-1]=-1 spread_param_list.append(test_spread_param) for loss_function in loss_functions: - for spread_param_index in range(len(spread_param_list)): - spread_param = spread_param_list[spread_param_index] - message = str(loss_function)+' with spread params'+str(spread_param_index) + for spread_param in spread_param_list: + message = str(loss_function)+' with spread params '+str(spread_param) with self.subTest(message): self.assertRaises(ValueError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], @@ -272,9 +323,8 @@ def test_Applicable_Loss_functions_1State_spread_param_Failures_ShapeErrors(self spread_param_list.append([2.0, 3.0]) spread_param_list.append(np.random.rand(self.solution[1::,-1].shape[0]+1).tolist()) for loss_function in loss_functions: - for spread_param_index in range(len(spread_param_list)): - spread_param = spread_param_list[spread_param_index] - message = str(loss_function)+' with spread params'+str(spread_param_index) + for spread_param in spread_param_list: + message = str(loss_function)+' with spread params '+str(spread_param) with self.subTest(message): self.assertRaises(AssertionError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], @@ -293,9 +343,8 @@ def test_Applicable_Loss_functions_2State_spread_param_Failures_TypeErrors(self) test_spread_param[-1][-1]=False spread_param_list.append(test_spread_param) for loss_function in loss_functions: - for spread_param_index in range(len(spread_param_list)): - spread_param = spread_param_list[spread_param_index] - message = str(loss_function)+' with spread params'+str(spread_param_index) + for spread_param in spread_param_list: + message = str(loss_function)+' with spread params '+str(spread_param) with self.subTest(message): self.assertRaises(TypeError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], @@ -312,9 +361,8 @@ def test_Applicable_Loss_functions_2State_spread_param_Failures_ValueErrors(self spread_param_list.append([1.0, -1.0]) spread_param_list.append([-1.0, -1.0]) for loss_function in loss_functions: - for spread_param_index in range(len(spread_param_list)): - spread_param = spread_param_list[spread_param_index] - message = str(loss_function)+' with spread params'+str(spread_param_index) + for spread_param in spread_param_list: + message = str(loss_function)+' with spread params '+str(spread_param) with self.subTest(message): self.assertRaises(ValueError, loss_function, self.theta, self.ode,self.init_state, self.t[0], @@ -329,9 +377,8 @@ def test_Applicable_Loss_functions_2State_spread_param_Failures_ShapeErrors(self spread_param_list.append(np.random.rand(self.solution[1::,1:3].shape[0]+1,self.solution[1::,1:3].shape[1]).tolist()) spread_param_list.append(np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]+1).tolist()) for loss_function in loss_functions: - for spread_param_index in range(len(spread_param_list)): - spread_param = spread_param_list[spread_param_index] - message = str(loss_function)+' with spread params'+str(spread_param_index) + for spread_param in spread_param_list: + message = str(loss_function)+' with spread params '+str(spread_param) with self.subTest(message): self.assertRaises(AssertionError, loss_function, self.theta, self.ode, self.init_state, self.t[0], From 9844fd34e1189790df5373d6612d9c1e6e13a274 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Thu, 2 Jul 2020 14:55:42 +0100 Subject: [PATCH 13/16] Unittest hopefully finished --- tests/test_loss_types.py | 64 +++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/tests/test_loss_types.py b/tests/test_loss_types.py index 8de89766..32657b6c 100644 --- a/tests/test_loss_types.py +++ b/tests/test_loss_types.py @@ -69,15 +69,13 @@ def test_all_Loss_functions_produce_different_costs(self): def test_Square_and_Normal_Loss_cost_scalar_weights_for_two_states(self): loss_functions = [SquareLoss, NormalLoss] - # weight for each component + y=self.solution[1::,1:3].flatten() + yhat = self.yhat[1::,1:3].flatten() + residual = y-yhat w = [2.0, 3.0] - r = self.solution[1::,1:3]-self.yhat[1::,1:3] - residual = [] - for i in range(2): - residual.append(r[:,i]*w[i]) - - residual = np.array(residual) - + w_unraveled = np.array([w[0]*np.ones(self.solution[1::,1:3].shape[0]), + w[1]*np.ones(self.solution[1::,1:3].shape[0])]).transpose().flatten() + residual =residual*w_unraveled square_cost = (residual**2).sum() sigma= 1 norm_logpdf_p1= -np.log(2) @@ -95,15 +93,17 @@ def test_Square_and_Normal_Loss_cost_scalar_weights_for_two_states(self): with self.subTest(message): obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=1) def test_Square_and_Normal_Loss_cost_vector_weights_for_two_states(self): loss_functions = [SquareLoss, NormalLoss] - r = self.solution[1::,1:3]-self.yhat[1::,1:3] - # now the weight is a vector - w = np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]) - - residual = r* w + y=self.solution[1::,1:3].flatten() + yhat = self.yhat[1::,1:3].flatten() + residual = y-yhat + w = [2.0, 3.0] + w = np.array([w[0]*np.ones(self.solution[1::,1:3].shape[0]), + w[1]*np.ones(self.solution[1::,1:3].shape[0])]).transpose() + residual = residual*w.flatten() square_cost = (residual**2).sum() sigma= 1 norm_logpdf_p1= -np.log(2) @@ -122,7 +122,7 @@ def test_Square_and_Normal_Loss_cost_vector_weights_for_two_states(self): with self.subTest(message): obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=1) def test_All_Loss_functions_1State_weights_Failures_TypeErrors(self): @@ -170,7 +170,7 @@ def test_AllLoss_1State_weights_Failures_ShapeErrors(self): self.assertRaises(AssertionError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], 'R', w) - + def test_AllLoss_2State_weights_Failures_TypeErrors(self): loss_functions = [SquareLoss, NormalLoss, GammaLoss, PoissonLoss, NegBinomLoss] w_list = list() @@ -222,25 +222,25 @@ def test_AllLoss_2State_weights_Failures_ShapeErrors(self): self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], w) - + def test_Applicable_Loss_functions_cost_scalar_spread_params_for_two_states(self): loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] - # weight for each component + y=self.solution[1::,1:3].flatten() + yhat = self.yhat[1::,1:3].flatten() + residual = y-yhat + # spread parameter for each component spread_params = [0.5, 1.5] spread_params_unraveled = np.array([spread_params[0]* np.ones(self.solution[1::,1:3].shape[0]), spread_params[1]* np.ones(self.solution[1::,1:3].shape[0])]).transpose().flatten() - y=self.solution[1::,1:3].flatten() - yhat = self.yhat[1::,1:3].flatten() - residual = y-yhat norm_logpdf_p1= -np.log(2) norm_logpdf_p2= np.log(2)/2 norm_logpdf_p3= -np.log(np.pi)/2 norm_logpdf_p4= np.log(1/spread_params_unraveled) norm_logpdf_p5_alt= -residual**2 / (2*spread_params_unraveled**2) norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ - norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() gamma_cost=(-gamma_mu_shape(x=y, mu=yhat,shape=spread_params_unraveled,log=True)).sum() NegBinom_cost=(-dnbinom(x=y, mu=yhat,size=spread_params_unraveled,log=True)).sum() @@ -253,15 +253,19 @@ def test_Applicable_Loss_functions_cost_scalar_spread_params_for_two_states(self with self.subTest(message): obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], None,spread_params) - self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) - + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=1) + def test_Applicable_Loss_functions_cost_vector_spread_params_for_two_states(self): loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] y=self.solution[1::,1:3].flatten() yhat = self.yhat[1::,1:3].flatten() residual = y-yhat - # now the weight is a vector - spread_params = np.random.rand(self.solution[1::,1:3].shape[0],self.solution[1::,1:3].shape[1]) + # now the spread parameter is a vector + spread_params = [0.5, 1.5] + spread_params = np.array([spread_params[0]* + np.ones(self.solution[1::,1:3].shape[0]), + spread_params[1]* + np.ones(self.solution[1::,1:3].shape[0])]).transpose() spread_params_unraveled=spread_params.flatten() norm_logpdf_p1= -np.log(2) norm_logpdf_p2= np.log(2)/2 @@ -269,19 +273,19 @@ def test_Applicable_Loss_functions_cost_vector_spread_params_for_two_states(self norm_logpdf_p4= np.log(1/spread_params_unraveled) norm_logpdf_p5_alt= -residual**2 / (2*spread_params_unraveled**2) norm_cost = (-(norm_logpdf_p1+norm_logpdf_p2+norm_logpdf_p3+ - norm_logpdf_p4+norm_logpdf_p5_alt)).sum() + norm_logpdf_p4+norm_logpdf_p5_alt)).sum() gamma_cost=(-gamma_mu_shape(x=y, mu=yhat,shape=spread_params_unraveled,log=True)).sum() NegBinom_cost=(-dnbinom(x=y, mu=yhat,size=spread_params_unraveled,log=True)).sum() test_answers=[norm_cost,gamma_cost,NegBinom_cost] - + for loss_function_index in range(len(loss_functions)): loss_function= loss_functions[loss_function_index] message = str(loss_function) with self.subTest(message): obj = loss_function(self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,1:3], ['I', 'R'], None,spread_params) - self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=0) + self.assertAlmostEqual(obj.cost(), test_answers[loss_function_index],places=1) def test_Applicable_Loss_functions_1State_spread_param_Failures_TypeErrors(self): loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] @@ -329,7 +333,7 @@ def test_Applicable_Loss_functions_1State_spread_param_Failures_ShapeErrors(self self.assertRaises(AssertionError, loss_function, self.theta, self.ode, self.init_state, self.t[0], self.t[1::], self.solution[1::,-1], 'R', None,spread_param) - + def test_Applicable_Loss_functions_2State_spread_param_Failures_TypeErrors(self): loss_functions = [NormalLoss, GammaLoss, NegBinomLoss] spread_param_list = list() From a2f01fe3cbdb1da5d1f94e93b049136ac107a472 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Thu, 2 Jul 2020 16:41:02 +0100 Subject: [PATCH 14/16] odeloss.py and lossype.py files checked with pylint --- pygom/loss/loss_type.py | 280 +++++++++++++++++++--------------------- pygom/loss/ode_loss.py | 35 ++--- 2 files changed, 153 insertions(+), 162 deletions(-) diff --git a/pygom/loss/loss_type.py b/pygom/loss/loss_type.py index 745fd4ea..f1385e65 100644 --- a/pygom/loss/loss_type.py +++ b/pygom/loss/loss_type.py @@ -19,16 +19,10 @@ from pygom.model.ode_utils import check_array_type from pygom.utilR.distn import dpois, gamma_mu_shape, dnbinom -class InputError(Exception): +class Baseloss_Type(object): ''' - As the name suggest. - ''' - pass - -class baseloss_type(object): - ''' - This baseloss_type class provides common feature to be inherited by the - loss type objects, such as Square, Normal , etc. + This Baseloss_Type class provides common feature to be inherited by the + loss type objects, such as Square, Normal , etc. Parameters ---------- @@ -43,22 +37,22 @@ def __init__(self, y, weights=None): # module is being used without base_loss.py. #Checks o n y: self._y = check_array_type(y) - #Checks on weights. + #Checks on weights. if weights is None: self._numVar = 0 self._w = np.ones(self._y.shape) else: - self._w = check_array_type(weights,accept_booleans=True) - if (self._w<0).any(): + self._w = check_array_type(weights, accept_booleans=True) + if (self._w < 0).any(): raise ValueError('No elements in numpy array of weights should be negative') - if (self._w==0).all(): + if (self._w == 0).all(): raise ValueError('All elements in numpy array of weights should not be 0.0') if len(self._w.shape) > 1: if 1 in self._w.shape: - self._w = self._w.flatten() + self._w = self._w.flatten() assert self._y.shape == self._w.shape, "Input weight not of the same size as y" - - def residual(self, yhat, apply_weighting = True): + + def residual(self, yhat, apply_weighting=True): ''' Raw residuals returned if apply_weighting = False, else the weighted residuals. @@ -68,7 +62,7 @@ def residual(self, yhat, apply_weighting = True): yhat: array like observation apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals returned. Returns @@ -76,9 +70,9 @@ def residual(self, yhat, apply_weighting = True): :math:`y_{i} - \\hat{y}_{i}` ''' - if isinstance(apply_weighting,bool)==False: + if not isinstance(apply_weighting, bool): raise TypeError('apply_weighting should be boolean') - + if len(yhat.shape) > 1: if 1 in yhat.shape: resid = self._y - yhat.ravel() @@ -86,14 +80,12 @@ def residual(self, yhat, apply_weighting = True): resid = self._y - yhat else: resid = self._y - yhat - if apply_weighting == True: + if apply_weighting: resid *= self._w - + return resid - - -class Square(baseloss_type): +class Square(Baseloss_Type): ''' Square loss object @@ -107,7 +99,7 @@ def __init__(self, y, weights=None): super().__init__(y, weights) self.loss(self._y) - def loss(self, yhat, apply_weighting = True): + def loss(self, yhat, apply_weighting=True): ''' Loss under square loss. Not really saying much here @@ -116,7 +108,7 @@ def loss(self, yhat, apply_weighting = True): yhat: array like observation apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. Returns @@ -136,7 +128,7 @@ def diff_loss(self, yhat, apply_weighting=True): yhat: array like observation apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. Returns @@ -154,9 +146,9 @@ def diff2Loss(self, yhat, apply_weighting=True): yhat: array like observations apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so without it missing arguments errors could occur. Returns @@ -170,7 +162,7 @@ def diff2Loss(self, yhat, apply_weighting=True): yhat = yhat.ravel() return 2*np.ones(yhat.shape) -class Normal(baseloss_type): +class Normal(Baseloss_Type): ''' Normal distribution loss object @@ -180,14 +172,14 @@ class Normal(baseloss_type): observation sigma: float standard deviation - ''' + ''' def __init__(self, y, weights=None, sigma=1.0): super().__init__(y, weights) err_str = "Standard deviation not of the correct " if isinstance(sigma, np.ndarray): - if (sigma<0).any(): + if (sigma < 0).any(): raise ValueError('No elements in numpy array of sigma values should be negative') - elif len(sigma.shape) > 1: + if len(sigma.shape) > 1: if 1 in sigma.shape: sigma = sigma.flatten() if y.shape == sigma.shape: @@ -202,10 +194,9 @@ def __init__(self, y, weights=None, sigma=1.0): elif sigma is None or sigma == 1.0: self._sigma = np.ones(self._y.shape) elif isinstance(sigma, (int, float)): - if sigma <0: + if sigma < 0: raise ValueError('Sigma should not be negative') - else: - self._sigma = sigma*np.ones(self._y.shape) + self._sigma = sigma*np.ones(self._y.shape) else: raise TypeError(err_str + "type") @@ -222,27 +213,28 @@ def loss(self, yhat, apply_weighting=True): yhat: array like observation apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. Returns ------- - negative log-likelihood, :math:`\\mathcal\\frac{1}{\\sqrt{2\\pi}\\sigma}e^{-\\frac{(y-\\hat{y})^{2}}{2\\sigma^{2}}` + negative log-likelihood, :math: + `\\mathcal\\frac{1}{\\sqrt{2\\pi}\\sigma}e^{-\\frac{(y-\\hat{y})^{2}}{2\\sigma^{2}}` ''' if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - - r=self.residual(yhat, apply_weighting) - sigma=self._sigma - + + residual = self.residual(yhat, apply_weighting) + sigma = self._sigma + # Calculate negative likelihood (depending on weighting of residuals). - logpdf_p1= -np.log(2) - logpdf_p2= np.log(2)/2 - logpdf_p3= -np.log(np.pi)/2 - logpdf_p4= np.log(1/sigma) - logpdf_p5_alt= -r**2 / (2*sigma**2) + logpdf_p1 = -np.log(2) + logpdf_p2 = np.log(2)/2 + logpdf_p3 = -np.log(np.pi)/2 + logpdf_p4 = np.log(1/sigma) + logpdf_p5_alt = -residual**2 / (2*sigma**2) return (-(logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4+logpdf_p5_alt)).sum() def diff_loss(self, yhat, apply_weighting=True): @@ -255,7 +247,7 @@ def diff_loss(self, yhat, apply_weighting=True): yhat: array like observation apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. Returns @@ -264,8 +256,8 @@ def diff_loss(self, yhat, apply_weighting=True): :math:`\\nabla \\mathcal{L}(\\hat{y}, y)` ''' - r = self.residual(yhat, apply_weighting) - return -r/self._sigma2 + residual = self.residual(yhat, apply_weighting) + return -residual/self._sigma2 def diff2Loss(self, yhat, apply_weighting=True): ''' @@ -276,9 +268,9 @@ def diff2Loss(self, yhat, apply_weighting=True): yhat: array like observations apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so without it missing arguments errors could occur. Returns @@ -290,8 +282,8 @@ def diff2Loss(self, yhat, apply_weighting=True): if 1 in yhat.shape: yhat = yhat.ravel() return np.ones(yhat.shape)/self._sigma2 - -class Gamma(baseloss_type): + +class Gamma(Baseloss_Type): ''' Gamma distribution loss object @@ -299,17 +291,17 @@ class Gamma(baseloss_type): ---------- y: array like observation - Shape: float + Shape: float shape (a in latex equations) ''' - + def __init__(self, y, weights=None, shape=2.0): super().__init__(y, weights) err_str = "Shape is not of the correct " if isinstance(shape, np.ndarray): - if (shape<0).any(): + if (shape < 0).any(): raise ValueError('No elements in numpy array of shape values should be negative') - elif len(shape.shape) > 1: + if len(shape.shape) > 1: if 1 in shape.shape: shape = shape.flatten() if y.shape == shape.shape: @@ -324,19 +316,19 @@ def __init__(self, y, weights=None, shape=2.0): elif shape is None or shape == 2.0: self._shape = 2*np.ones(self._y.shape) elif isinstance(shape, (int, float)): - if shape <0: + if shape < 0: raise ValueError('Shape should not be negative') - else: - self._shape = shape*np.ones(self._y.shape) + self._shape = shape*np.ones(self._y.shape) else: raise TypeError(err_str + "type") self.loss(self._y) - + def loss(self, yhat, apply_weighting=True): ''' - The loss under a gamma distribution. Defined as the negative + The loss under a gamma distribution. Defined as the negative log-likelihood of the gamma distirbution in terms of mean and shape. - See: Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). Princeton University Press. + See: Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). + Princeton University Press. File "Loss function Calculations.ipnyb" Parameters @@ -344,10 +336,10 @@ def loss(self, yhat, apply_weighting=True): yhat: array like prediction apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so - without it missing arguments errors could occur. + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur. Returns ------- @@ -357,23 +349,23 @@ def loss(self, yhat, apply_weighting=True): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - - return -gamma_mu_shape(x=self._y, mu=yhat,shape=self._shape,log=True).sum() - + + return -gamma_mu_shape(x=self._y, mu=yhat, shape=self._shape, log=True).sum() + def diff_loss(self, yhat, apply_weighting=True): ''' Derivative of the loss function with respect to yhat which is - See: + See: File "Loss function Calculations.ipnyb" - + Parameters ---------- yhat: array like prediction apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. - + Returns ------- first_deriv_yhat: array like @@ -381,23 +373,22 @@ def diff_loss(self, yhat, apply_weighting=True): ''' shape = self._shape - r = self.residual(yhat, apply_weighting) - return shape*-r/yhat**2 + residual = self.residual(yhat, apply_weighting) + return shape*-residual/yhat**2 def diff2Loss(self, yhat, apply_weighting=True): ''' Twice derivative of the loss function with respect to yhat. - See: + See: Jupiter notebook "Loss function Calculations.ipnyb" - + Parameters ---------- yhat: array like observation apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. - Returns ------- @@ -408,12 +399,11 @@ def diff2Loss(self, yhat, apply_weighting=True): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - y = self._y shape = self._shape - r = self.residual(yhat, apply_weighting) - return shape*(r+y)/yhat**3 + residual = self.residual(yhat, apply_weighting) + return shape*(residual+self._y)/yhat**3 -class Poisson(baseloss_type): +class Poisson(Baseloss_Type): ''' Poisson distribution loss object @@ -427,7 +417,7 @@ def __init__(self, y, weights=None): super().__init__(y, weights) self.loss(self._y) - def loss(self, yhat,apply_weighting=True): + def loss(self, yhat, apply_weighting=True): ''' The loss under a normal distribution. Defined as the negative log-likelihood here. @@ -437,9 +427,9 @@ def loss(self, yhat,apply_weighting=True): yhat: array like observation apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so without it missing arguments errors could occur. Returns @@ -462,7 +452,7 @@ def diff_loss(self, yhat, apply_weighting=True): yhat: array like observation apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. Returns @@ -470,13 +460,12 @@ def diff_loss(self, yhat, apply_weighting=True): :math:`\\nabla \\mathcal{L}(\\hat{y},y)` ''' - if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - - r = self.residual(yhat, apply_weighting) - return -r/yhat + + residual = self.residual(yhat, apply_weighting) + return -residual/yhat def diff2Loss(self, yhat, apply_weighting=True): ''' @@ -487,9 +476,9 @@ def diff2Loss(self, yhat, apply_weighting=True): yhat: array like observations apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so without it missing arguments errors could occur. Returns @@ -500,10 +489,9 @@ def diff2Loss(self, yhat, apply_weighting=True): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - y=self._y - return y/(yhat**2) + return self._y/(yhat**2) -class NegBinom(baseloss_type): +class NegBinom(Baseloss_Type): ''' Negative Binomial distribution loss object @@ -511,17 +499,16 @@ class NegBinom(baseloss_type): ---------- y: array like observation - k: float + k: float Overdispersion parameter (k=mean+mean(mean/variance)) ''' - - def __init__(self, y, weights=None, k=1.0): + def __init__(self, y, weights=None, k=1.0): super().__init__(y, weights) err_str = "k (the overdispersion parameter) is not of the correct " if isinstance(k, np.ndarray): - if (k<0).any(): + if (k < 0).any(): raise ValueError('No elements in numpy array of k values should be negative') - elif len(k.shape) > 1: + if len(k.shape) > 1: if 1 in k.shape: k = k.flatten() if y.shape == k.shape: @@ -536,15 +523,14 @@ def __init__(self, y, weights=None, k=1.0): elif k is None or k == 1.0: self._k = np.ones(self._y.shape) elif isinstance(k, (int, float)): - if k <0: + if k < 0: raise ValueError('k should not be negative') - else: - self._k = k*np.ones(self._y.shape) + self._k = k*np.ones(self._y.shape) else: raise TypeError(err_str + "type") - + self.loss(self._y) - + def loss(self, yhat, apply_weighting=True): ''' The loss under a Negative Binomial distribution. Defined as the @@ -555,9 +541,9 @@ def loss(self, yhat, apply_weighting=True): yhat: array like observation apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so without it missing arguments errors could occur. Returns @@ -568,28 +554,29 @@ def loss(self, yhat, apply_weighting=True): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - - return (-dnbinom(self._y, mu=yhat,size=self._k,log=True)).sum() - + + return (-dnbinom(self._y, mu=yhat, size=self._k, log=True)).sum() + def diff_loss(self, yhat, apply_weighting=True): ''' Derivative of the loss function with respect to yhat which is - See: + See: Jupiter notebook "Loss function Calculations.ipnyb" - Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press + Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). + Princeton University Press Parameters ---------- yhat: array like observation + apply_weighting: boolean + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so + without it missing arguments errors could occur + apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so - without it missing arguments errors could occur. - - apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. Returns @@ -601,37 +588,40 @@ def diff_loss(self, yhat, apply_weighting=True): if len(yhat.shape) > 1: if 1 in yhat.shape: yhat = yhat.ravel() - + k = self._k - r = self.residual(yhat, apply_weighting) - first_derivs_yhat = k*-r/(yhat*(k+yhat)) + residual = self.residual(yhat, apply_weighting) + first_derivs_yhat = k*-residual/(yhat*(k+yhat)) return first_derivs_yhat def diff2Loss(self, yhat, apply_weighting=True): ''' Twice derivative of the loss function with respect to yhat. - See: + See: Jupiter notebook "Loss function Calculations.ipnyb" - Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press + Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). + Princeton University Press Parameters ---------- yhat: array like observation apply_weighting: boolean - Residuals are not used in calculation, as such True or False - argument makes no difference. Argument has been kept as the equivalent - calculation is made with residuals for other loss functions, so + Residuals are not used in calculation, as such True or False + argument makes no difference. Argument has been kept as the equivalent + calculation is made with residuals for other loss functions, so without it missing arguments errors could occur. - + apply_weighting: boolean - If True multiplies array of residuals by weightings, else raw + If True multiplies array of residuals by weightings, else raw residuals are used. Returns ------- scnd_deriv_yhat: array like - :math:`\\frac{k(\\hat{y}(k + \\hat{y}) + \\hat{y}(y -\\hat{y}) + (k + \\hat{y})(y - \\hat{y})}{\\hat{y}^{2}(k + \\hat{y})^{2}}` + :math: + `\\frac{k(\\hat{y}(k + \\hat{y}) + \\hat{y}(y -\\hat{y}) + (k + + \\hat{y})(y - \\hat{y})}{\\hat{y}^{2}(k + \\hat{y})^{2}}` ''' if len(yhat.shape) > 1: @@ -639,10 +629,10 @@ def diff2Loss(self, yhat, apply_weighting=True): yhat = yhat.ravel() k = self._k - r = self.residual(yhat, apply_weighting) - scnd_derivs_yhat_p1= k - scnd_derivs_yhat_p2= yhat**(-2) - scnd_derivs_yhat_p3= (k + yhat)**(-2) - scnd_derivs_yhat_p4= r*yhat + r*(k + yhat) + yhat*(k + yhat) - scnd_derivs_yhat= scnd_derivs_yhat_p1*scnd_derivs_yhat_p2*scnd_derivs_yhat_p3*scnd_derivs_yhat_p4 - return scnd_derivs_yhat \ No newline at end of file + residual = self.residual(yhat, apply_weighting) + scnd_derivs_yhat_p1 = k + scnd_derivs_yhat_p2 = yhat**(-2) + scnd_derivs_yhat_p3 = (k + yhat)**(-2) + scnd_derivs_yhat_p4 = residual*yhat + residual*(k + yhat) + yhat*(k + yhat) + scnd_derivs_yhat = scnd_derivs_yhat_p1*scnd_derivs_yhat_p2*scnd_derivs_yhat_p3*scnd_derivs_yhat_p4 + return scnd_derivs_yhat diff --git a/pygom/loss/ode_loss.py b/pygom/loss/ode_loss.py index ae0992ff..a4a950f0 100644 --- a/pygom/loss/ode_loss.py +++ b/pygom/loss/ode_loss.py @@ -24,7 +24,7 @@ class SquareLoss(BaseLoss): ''' def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None, target_param=None, target_state=None): - super().__init__(theta, ode, x0, t0, t, y, state_name, state_weight, + super().__init__(theta, ode, x0, t0, t, y, state_name, state_weight, None, target_param, target_state) def __repr__(self): @@ -38,7 +38,7 @@ class NormalLoss(BaseLoss): ''' Realizations from a Normal distribution ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, + def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None, sigma=1.0, target_param=None, target_state=None): super().__init__(theta, ode, x0, t0, t, y, state_name, state_weight, sigma, target_param, target_state) @@ -49,51 +49,52 @@ def __repr__(self): def _setLossType(self): self._lossObj = Normal(self._y, self._weight, self._spread_param) return self._lossObj - + class GammaLoss(BaseLoss): ''' Realizations from a Gamma distribution taking parameters mean and shape. ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, + def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None, shape=2, target_param=None, target_state=None): super().__init__(theta, ode, x0, t0, t, y, - state_name, state_weight, shape,target_param, target_state) - + state_name, state_weight, shape, target_param, target_state) + def __repr__(self): return "GammaLoss" + self._get_model_str() def _setLossType(self): self._lossObj = Gamma(self._y, self._weight, self._spread_param) return self._lossObj - + class PoissonLoss(BaseLoss): ''' Realizations from a Poisson distribution ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, + def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None, target_param=None, target_state=None): super().__init__(theta, ode, x0, t0, t, y, state_name, state_weight, - None,target_param, target_state) - + None, target_param, target_state) + def __repr__(self): return "PoissonLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = Poisson(self._y,self._weight) - return self._lossObj - + self._lossObj = Poisson(self._y, self._weight) + return self._lossObj + class NegBinomLoss(BaseLoss): ''' Realizations from a Negative Binomial distribution ''' - def __init__(self, theta, ode, x0, t0, t, y, state_name,state_weight=None, + def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None, k=1, target_param=None, target_state=None): super().__init__(theta, ode, x0, t0, t, y, state_name, state_weight, k, target_param, target_state) - + def __repr__(self): return "NegBinomLoss" + self._get_model_str() def _setLossType(self): - self._lossObj = NegBinom(self._y, self._weight,self._spread_param) - return self._lossObj \ No newline at end of file + self._lossObj = NegBinom(self._y, self._weight, self._spread_param) + return self._lossObj + \ No newline at end of file From bf82f04b25597bce313036d7c38f120f3b40c970 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Fri, 3 Jul 2020 12:11:07 +0100 Subject: [PATCH 15/16] Update approximate_bayesian_computation.py --- .../approximate_bayesian_computation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py b/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py index 1012fc2c..6c65b92d 100644 --- a/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py +++ b/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py @@ -159,10 +159,10 @@ def create_loss(loss_type, parameters, ode, x0, t0, t, y, state_name, return SquareLoss(theta, ode, x0, t0, t, y, state_name, state_weight, target_param, target_state) elif loss_type == NormalLoss: - return NormalLoss(theta, ode, x0, t0, t, y, state_name, sigma, target_param, target_state) + return NormalLoss(theta, ode, x0, t0, t, y, state_name, state_weight, sigma, target_param, target_state) elif loss_type == PoissonLoss: - return PoissonLoss(theta, ode, x0, t0, t, y, state_name, target_param, target_state) + return PoissonLoss(theta, ode, x0, t0, t, y, state_name, state_weight, target_param, target_state) #%% """ ABC class and methods for obtaining an approximate posterior sample/plotting the results """ From fdd17e1d5b241c1c1693ff797a86501f3d5e7052 Mon Sep 17 00:00:00 2001 From: MGrunnill Date: Fri, 3 Jul 2020 15:28:58 +0100 Subject: [PATCH 16/16] Merged with ABC fitting, fixed resulting mismatching arguments causing test_abc.py to fail. Double checked changes should not affect ABC with Jonty. --- pygom/loss/base_loss.py | 4 + .../model/ode_utils/checks_and_conversions.py | 46 +-- pygom/utilR/distn.py | 97 ++--- ...el.ode_utils.checks_and_conversions1.stats | Bin 0 -> 834 bytes tests/.pylint.d/pygom.utilR.distn1.stats | Bin 0 -> 918 bytes tests/.pylint.d/test_loss_types1.stats | Bin 0 -> 969 bytes tests/test_abc.py | 12 +- tests/test_loss_types.py | 377 +++++++++--------- 8 files changed, 269 insertions(+), 267 deletions(-) create mode 100644 tests/.pylint.d/pygom.model.ode_utils.checks_and_conversions1.stats create mode 100644 tests/.pylint.d/pygom.utilR.distn1.stats create mode 100644 tests/.pylint.d/test_loss_types1.stats diff --git a/pygom/loss/base_loss.py b/pygom/loss/base_loss.py index 826ad453..db45e02c 100644 --- a/pygom/loss/base_loss.py +++ b/pygom/loss/base_loss.py @@ -143,6 +143,8 @@ def __init__(self, theta, ode, self._weight = self._setWeight_or_spread(n, p, state_weight,is_weights= True) if spread_param is not None: self._spread_param = self._setWeight_or_spread(n, p, spread_param,is_weights= False) + else: + self._spread_param = None else: raise InputError("Expecting the name of states " + "for the observations") @@ -154,6 +156,8 @@ def __init__(self, theta, ode, self._weight = self._setWeight_or_spread(n, p, state_weight,is_weights= True) if spread_param is not None: self._spread_param = self._setWeight_or_spread(n, p, spread_param,is_weights= False) + else: + self._spread_param = None else: raise InputError("State name should be str or of type list/tuple") diff --git a/pygom/model/ode_utils/checks_and_conversions.py b/pygom/model/ode_utils/checks_and_conversions.py index 8ca427fc..87944e60 100644 --- a/pygom/model/ode_utils/checks_and_conversions.py +++ b/pygom/model/ode_utils/checks_and_conversions.py @@ -7,7 +7,7 @@ -def check_array_type(x,accept_booleans=False): +def check_array_type(x, accept_booleans=False): ''' Check to see if the type of input is suitable. Only operate on one or two dimension arrays @@ -24,41 +24,35 @@ def check_array_type(x,accept_booleans=False): x: :class:`numpy.ndarray` checked and converted array ''' - accepted_types = (int,float,complex) - if accept_booleans==True: + accepted_types = (int, float, complex) + if accept_booleans: type_error_message = 'Expecting elements/sub-elements to be of type float, int, complex or boolean' - if accept_booleans==False: + if not accept_booleans: type_error_message = 'Expecting elements/sub-elements to be of type float, int or complex' - - + if isinstance(x, np.ndarray): pass - elif isinstance(x, (list, tuple)): - if all(isinstance(item, accepted_types) for item in x): - if accept_booleans==True: - x = np.array(x) - elif accept_booleans==False: - if any(isinstance(item, bool) for item in x): - raise TypeError('No elements of array type object should be Boolean values') - x = np.array(x) - else: - TypeError(type_error_message) - elif isinstance(x[0], (list, tuple, np.ndarray)): + + elif isinstance(x, (list, tuple)): # If list or tuple + if all(isinstance(item, accepted_types) for item in x):# Check for accepted types + if not accept_booleans and any(isinstance(item, bool) for item in x): # + raise TypeError('No elements of array type object should be Boolean values') + x = np.array(x) + + elif isinstance(x[0], (list, tuple, np.ndarray)):# If tuple/list of tuples/lists. for item in x: - if any(not isinstance(sub_item, accepted_types) for sub_item in item): + if any(not isinstance(sub_item, accepted_types) for sub_item in item): # Check for accepted types raise TypeError(type_error_message) - if accept_booleans==False and any(isinstance(sub_item, bool) for sub_item in item): + if not accept_booleans and any(isinstance(sub_item, bool) for sub_item in item): raise TypeError('No elements of array type object should be Boolean values') x = np.array(x) else: raise TypeError(type_error_message) - elif isinstance(x, accepted_types): - if accept_booleans==True: - x = np.array([x]) - elif accept_booleans==False and not isinstance(x, bool): - x = np.array([x]) - else: - TypeError("Not expecting Boolean value") + + elif isinstance(x, accepted_types): # If x is a single element of accepted type. + if not accept_booleans and isinstance(x, bool): + raise TypeError("Not expecting Boolean value") + x = np.array([x]) else: raise TypeError("Expecting an array like object, got %s" % type(x)) diff --git a/pygom/utilR/distn.py b/pygom/utilR/distn.py index 25cf2628..a47c2c9b 100644 --- a/pygom/utilR/distn.py +++ b/pygom/utilR/distn.py @@ -81,10 +81,10 @@ def dgamma(x, shape, rate=1.0, log=False): return st.gamma.logpdf(x, a=shape, scale=1.0/rate) else: return st.gamma.pdf(x, a=shape, scale=1.0/rate) - -def gamma_mu_shape(x, mu,shape,log=False): + +def gamma_mu_shape(x, mu, shape, log=False): ''' - The probability density function (pdf) of gamma distrbution in terms of mean and shape. + The probability density function (pdf) of gamma distrbution in terms of mean and shape. Parameters ---------- @@ -92,21 +92,21 @@ def gamma_mu_shape(x, mu,shape,log=False): mu: mean or prediction. shape: shape (a in latex equation below). log: if True the natural log of the pmf is given. - See: Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). Princeton University Press. + See: Bolker, B. M. (2008). Gamma. In Ecological Models in R (pp. 131–133). + Princeton University Press. Jupyter notebook titled "Loss function Calculations.ipnyb" Returns ------- - pdf, :math:`\\mathcal\\{p}(x; \\mu,a) = \\exp(- a \\ln{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\ln{\\left(x \\right)} - \\ln{\\left(\\Gamma\\left(a\\right) \\right)})` -` + pdf, :math: + `\\mathcal\\{p}(x; \\mu,a) = \\exp(- a \\ln{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\ln{\\left(x \\right)} - \\ln{\\left(\\Gamma\\left(a\\right) \\right)})` ''' - - logpdf_p1= -gammaln(shape) - logpdf_p2= (shape - 1)*np.log(x) - logpdf_p3= -shape*np.log(mu/shape) - logpdf_p4= -shape*x/mu + logpdf_p1 = -gammaln(shape) + logpdf_p2 = (shape - 1)*np.log(x) + logpdf_p3 = -shape*np.log(mu/shape) + logpdf_p4 = -shape*x/mu logpdf = logpdf_p1+logpdf_p2+logpdf_p3+logpdf_p4 if log: ans = logpdf @@ -457,47 +457,40 @@ def rbinom(n, size, prob, seed=None): return rvs(n=size, p=prob, size=n)[0] ##### Negitive binomial -def dnbinom(x, size, prob, mu, log=True): - ''' - See - https://stat.ethz.ch/R-manual/R-devel/library/stats/html/NegBinomial.html - ''' - -def pnbinom(q, size, prob, mu, lower_tail = True, log=True): +def pnbinom(q, size, prob, mu, lower_tail=True, log=True): ''' See https://stat.ethz.ch/R-manual/R-devel/library/stats/html/NegBinomial.html ''' - -def qnbinom(p, size, prob, mu, lower_tail = True, log=True): + +def qnbinom(p, size, prob, mu, lower_tail=True, log=True): ''' See https://stat.ethz.ch/R-manual/R-devel/library/stats/html/NegBinomial.html ''' - -def rnbinom(n, size, prob, mu, seed=None): - pass - ##### Negative Binomial distribution -def nb2pmf(x, mu,k,log=False): +def nb2pmf(x, mu, k, log=False): ''' The probability mass function (pmf) of Negative Binomial 2 distribution. - This definition of the negative binomial distribution is often refered to as - negative binomial 2, or the ecological parameterisation. This parameterisation - takes the mean and k (an overdispersion parameter). The variance = mean(1+mean/k), - some notation uses alpha (k=1/alpha). - See: Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press. + This definition of the negative binomial distribution is often refered to as + negative binomial 2, or the ecological parameterisation. This parameterisation + takes the mean and k (an overdispersion parameter). The variance = mean(1+mean/k), + some notation uses alpha (k=1/alpha). + See: Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). + Princeton University Press. Jupyter notebook titled "Loss function Calculations.ipnyb" - + Parameters ---------- x: array like observation. mu: mean or prediction. - k: overdispersion parameter (variance = mean(1+mean/k)). Note some notation uses $\alpha$, ($k=\alpha^{-1}$). + k: overdispersion parameter (variance = mean(1+mean/k)). Note some notation + uses $\alpha$, ($k=\alpha^{-1}$). log: if True the natural log of the pmf is given. - See: - Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). Princeton University Press. + See: + Bolker, B. M. (2008). Negative Binomial. In Ecological Models in R (pp. 124–126). + Princeton University Press. File "Loss function Calculations.ipnyb" Returns @@ -506,44 +499,40 @@ def nb2pmf(x, mu,k,log=False): math:`\\mathcal\\p(x; \\mu,k)) = \\exp(\\ln(\\frac{\\Gamma \\left(k+x\\right)}{\\Gamma \\left(k\\right)x!}(\\frac{k}{k+\\mu})^{k}(\\frac{\\mu}{k+\\mu})^{x}))` ''' - # note that we input k the overdispersion parameter here - - - logpmf_p1= -gammaln(x+1) - logpmf_p2= -gammaln(k) - logpmf_p3= k*(np.log(k) - np.log(k + mu)) - logpmf_p4= x*(np.log(mu) - np.log(k + mu)) - logpmf_p5= gammaln(k+x) + logpmf_p1 = -gammaln(x+1) + logpmf_p2 = -gammaln(k) + logpmf_p3 = k*(np.log(k) - np.log(k + mu)) + logpmf_p4 = x*(np.log(mu) - np.log(k + mu)) + logpmf_p5 = gammaln(k+x) logpmf = logpmf_p1+logpmf_p2+logpmf_p3+logpmf_p4+logpmf_p5 if log: - ans= logpmf + ans = logpmf else: - ans= np.exp(logpmf) + ans = np.exp(logpmf) return ans -def dnbinom(x, size, prob=None, mu=None, log =False): +def dnbinom(x, size, prob=None, mu=None, log=False): ''' See https://stat.ethz.ch/R-manual/R-devel/library/stats/html/NegBinomial.html ''' if mu is None and prob is None: raise Exception("Neither 'prob' or 'mu' were specified") - + if mu is not None: if prob is not None: raise Exception("'prob' and 'mu' both specified") - if log: - ans =nb2pmf(x=x, mu=mu,k=size,log=True) + ans = nb2pmf(x=x, mu=mu, k=size, log=True) else: - ans =nb2pmf(x=x, mu=mu,k=size,log=False) - + ans = nb2pmf(x=x, mu=mu, k=size, log=False) + else: if log: - ans= st.nbinom.logpmf(x, n=size, p=prob) + ans = st.nbinom.logpmf(x, n=size, p=prob) else: - ans= st.nbinom.pmf(x, n=size, p=prob) - + ans = st.nbinom.pmf(x, n=size, p=prob) + return ans def test_seed(seed): @@ -578,4 +567,4 @@ def test_seed(seed): rvs.set_state(state) return rvs else: - raise RuntimeError("seed must be (bool, int or np.random.RandomState") \ No newline at end of file + raise RuntimeError("seed must be (bool, int or np.random.RandomState") diff --git a/tests/.pylint.d/pygom.model.ode_utils.checks_and_conversions1.stats b/tests/.pylint.d/pygom.model.ode_utils.checks_and_conversions1.stats new file mode 100644 index 0000000000000000000000000000000000000000..233d76c68fa4ecf4b6940028c86c996f57ce4f1d GIT binary patch literal 834 zcmZWn%Wm5+5R~oMu@fg~;ud{;K@OF#?XkBU^bLhTk!y)4wG{YpphJLu0D<`(m#r3FL41zkbJy3p-4Xz5OMj(zQrRtUfd8;1 zLs4>#doWgNv?L(Cb<9Bv=wk6TTu9vMSY+X9;GrX4EH+_jV8^)ACKl6h`NRxLtP^hz z#w3(ZJLZ_8leb}!in8_az>Sg!xzjpVI%%e1;|!C8*7;K-9oUX>h{YtVCGMG$B1hH| zunKQ2krX(MIoEB+jI^noMYv0LEyF&q3`0t1ll~TU4$4Aqz!-=-kss643pQ2W03nZ#jy_?tV-cKB{{8~C{wLN z6F+odIBntomyd^K&$6%<&;bfSE=fe|K1bhnef$+4n%Qq!JKl3eH{WA3r)9pbm9Cg7 OQB$_ZZyygne)|`qjx$LB literal 0 HcmV?d00001 diff --git a/tests/.pylint.d/pygom.utilR.distn1.stats b/tests/.pylint.d/pygom.utilR.distn1.stats new file mode 100644 index 0000000000000000000000000000000000000000..ed59ac47bb92bf54aaef00ba6461be5027136f00 GIT binary patch literal 918 zcmZWoJ#X7E5LFY)u@fha69h?qLDNBAvv%{qt$Sfm3vtwWD;{MBmHjGh!)FOKm#%K!UH53YqSCfQ}6h3jSWOo$VW4It1XbVLP&bQ>{HjG=4KzbmH(kty0 zp@Z<&qqhX{cH!4)T!yREbu={Gr?y6IkS7#Jq zf7jMv?oq6>d`CFA%E***E;P5KnRVWioy~(0bWU+}(3W($L3VQcm0Q`-hR2_qSL+zTIrHfSQT_lme z;h&1Fk*kA>Z4TF1&ZKX&5;VGUmU`_%ylbEpG_?O8PS;zJWnmcH znxs9j@oRjjj=zN*ech}!f9J1^285y!Uvqrui literal 0 HcmV?d00001 diff --git a/tests/.pylint.d/test_loss_types1.stats b/tests/.pylint.d/test_loss_types1.stats new file mode 100644 index 0000000000000000000000000000000000000000..c22a86406e23e68ae9cab2b2308b3ae202093970 GIT binary patch literal 969 zcmZWoJ#X7E5S0_lu@k4QW27|1&Gk4dm&IHEfJtdfgcGp1jyEfKs&HN ze@%Z@=N@HCv0F{z-FtWM-jPq^pTAF&?t2VtKP%e2R@4a=9)o{rnX$Q0#^knbn1L8T zjK!AKOxp1I{m75G+^Ucz{+uXz4^ggU$nN}9vn?i8>5!%V>;Y@ZWf^fP(>g{^e7eOJ z3y3-6C$X_9yAGFvONOjcNT|q}`Bw#|2