{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Cox Processes (w/ Pyro/QPyTorch Low-Level Interface)\n", "\n", "## Introduction\n", "\n", "This is a more in-depth example that shows off the power of the Pyro/QPyTorch low-level interface.\n", "\n", "A Cox process is an inhomogeneous Poisson process, where the arrival rate of events (the intensity function) varies with time. We will use a QP to model this latent intensity function." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import math\n", "import torch\n", "import qpytorch\n", "import pyro\n", "import tqdm\n", "import matplotlib.pyplot as plt\n", "\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create sample training set\n", "\n", "Here we're going to construct an artificial training set that follows a non-homogeneous intensity function.\n", "\n", "#### Intensity function\n", "\n", "We're going to assume points arrive following a sinusoidal itensity function.\n", "This will give us points in time where there are lots of arrivals, and points in time when there are few." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "intensity_max = 50\n", "true_intensity_function = lambda times: torch.cos(times * 2 * math.pi).add(1).mul(intensity_max / 2.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Determine how many arrivals there are" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of sampled arrivals: 53\n" ] } ], "source": [ "max_time = 2\n", "\n", "times = torch.linspace(0, max_time, 128)\n", "num_samples = int(pyro.distributions.Poisson(true_intensity_function(times).mean() * max_time).sample().item())\n", "print(f\"Number of sampled arrivals: {num_samples}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Determine when the arrivals occur\n", "\n", "We'll sample the arrivals using rejection sampling. See https://en.wikipedia.org/wiki/Poisson_point_process#Inhomogeneous_case for more details." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def log_prob_accept(val):\n", " intensities = true_intensity_function(val)\n", " res = torch.log(intensities / (true_intensity_function(times).mean() * max_time))\n", " return res\n", "\n", "arrival_times = pyro.distributions.Rejector(\n", " propose=pyro.distributions.Uniform(times.min(), times.max()),\n", " log_prob_accept=log_prob_accept,\n", " log_scale=0.\n", ")(torch.Size([num_samples]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### The result\n", "\n", "Here's a plot of the intensity function and the sampled arrivals" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(1, 1)\n", "ax.plot(times, true_intensity_function(times), \"--\", label=r\"True $\\lambda$\")\n", "ax.set_xlabel(\"Time\")\n", "ax.set_ylabel(\"Intensity ($\\lambda$)\")\n", "ax.scatter(arrival_times, torch.zeros_like(arrival_times), label=r\"Observed Arrivals\")\n", "ax.legend(loc=\"best\")\n", "None" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parameterizing the intensity function using a QEP\n", "\n", "When using a QEP to parameterize an intensity function $\\lambda(t)$, we have to keep two concerns in mind:\n", "\n", "1. The intensity function is non-negative, whereas the output of the QEP can be negative\n", "2. The intensity function can take on large values (e.g. 900), whereas QEP inference works best when latent function values are fairly normal (e.g. $\\mathbb{E}[f] = 0$ and $\\mathbb{E}[f^2] = 1$).\n", "\n", "As a result, we will use the following transform to convert QEP latent function samples into intensity function samples:\n", "\n", "```python\n", "# function_samples = \n", "# self.mean_intensity = E[ \\lambda (t) ] - computed from data\n", "intensity_samples = function_samples.exp() * self.mean_intensity\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Cox process likelihood\n", "\n", "Given an intensity function $\\lambda$, the likelihood of a Cox process is\n", "\n", "$$\n", "\\log p(t_1, \\ldots, t_n | \\lambda) = \\left[ \\sum_{i=1}^n \\log \\lambda( t_i ) \\right] - \\int_0^T \\lambda(\\tau) d\\tau\n", "$$\n", "\n", "The first term, which are the arrival log intensities, is easy to compute, given the `arrival_times`:\n", "\n", "```python\n", "# arrival_intensity_samples = \n", "arrival_log_intensities = arrival_intensity_samples.log().sum(dim=-1)\n", "```\n", "\n", "The second term, which is the estimated number of arrivals, can be computed analytically.\n", "However, it is much easier to compute this integral using quadrature.\n", "Using a grid of `quadrature_times` evenly spaced from $0$ to $T$, we can approximate this second term:\n", "\n", "```python\n", "# quadrature_intensity_samples = \n", "# max_time = T\n", "est_num_arrivals = quadrature_intensity_samples.mean(dim=-1).mul(self.max_time)\n", "```\n", "\n", "Putting this together, we have\n", "\n", "```python\n", "log_likelihood = arrival_log_intensities - est_num_arrivals\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using the low-level Pyro/QPyTorch interface\n", "\n", "Unfortunately, this is not a likelihood function that is easily written as a QPyTorch Likelihood object.\n", "Because of this, we will be using the low-level interface for the Pyro/QPyTorch integration.\n", "This is the more logical choice anyways: we're simply trying to perform inference on the intensity function rather than constructing a predictive model.\n", "\n", "Here's how it will work. We'll use a `qpytorch.models.ApproximateQEP` object to model the non-homogeneous intensity function. This object needs to define 3 functions:\n", "\n", "- `forward(times)` - which computes the prior QEP mean and covariance at the supplied times.\n", "- `guide(arrival_times, quadrature_times)` - which defines the approximate QEP posterior at both arrival times and quadrature times.\n", "- `model(arrival_times, quadrature_times)` - which does the following 3 things\n", "\n", " - Computes the QEP prior at arrival time and quadrature times\n", " - Converts QEP function samples into intensity function samples, using the transformation defined above.\n", " - Computes the likelihood of the arrivals (observations). We will use `pyro.factor` rather than a QPyTorch likelihood or a `pyro.sample` call (given that we have defined a simple function for directly computing the log likelihood).\n", " \n", "Putting it all together, we have:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "POWER = 1.0\n", "class QEPModel(qpytorch.models.ApproximateQEP):\n", " def __init__(self, num_arrivals, max_time, num_inducing=32, name_prefix=\"cox_qep_model\"):\n", " self.power = torch.tensor(POWER)\n", " self.name_prefix = name_prefix\n", " self.max_time = max_time\n", " self.mean_intensity = (num_arrivals / max_time)\n", " \n", " # Define the variational distribution and strategy of the QEP\n", " # We will initialize the inducing points to lie on a grid from 0 to T\n", " inducing_points = torch.linspace(0, max_time, num_inducing).unsqueeze(-1)\n", " variational_distribution = qpytorch.variational.CholeskyVariationalDistribution(num_inducing_points=num_inducing, power=self.power)\n", " variational_strategy = qpytorch.variational.VariationalStrategy(self, inducing_points, variational_distribution)\n", "\n", " # Define model\n", " super().__init__(variational_strategy=variational_strategy)\n", "\n", " # Define mean and kernel\n", " self.mean_module = qpytorch.means.ZeroMean()\n", " self.covar_module = qpytorch.kernels.ScaleKernel(qpytorch.kernels.RBFKernel())\n", " \n", " def forward(self, times):\n", " mean = self.mean_module(times)\n", " covar = self.covar_module(times)\n", " return qpytorch.distributions.MultivariateQExponential(mean, covar, power=self.power)\n", "\n", " def guide(self, arrival_times, quadrature_times):\n", " function_distribution = self.pyro_guide(torch.cat([arrival_times, quadrature_times], -1))\n", "\n", " # Draw samples from q(f) at arrival_times\n", " # Also draw samples from q(f) at evenly-spaced points (quadrature_times)\n", " with pyro.plate(self.name_prefix + \".times_plate\", dim=-1):\n", " pyro.sample(\n", " self.name_prefix + \".function_samples\",\n", " function_distribution\n", " )\n", "\n", " def model(self, arrival_times, quadrature_times):\n", " pyro.module(self.name_prefix + \".gp\", self)\n", " function_distribution = self.pyro_model(torch.cat([arrival_times, quadrature_times], -1))\n", " \n", " # Draw samples from p(f) at arrival times\n", " # Also draw samples from p(f) at evenly-spaced points (quadrature_times)\n", " with pyro.plate(self.name_prefix + \".times_plate\", dim=-1):\n", " function_samples = pyro.sample(\n", " self.name_prefix + \".function_samples\",\n", " function_distribution\n", " )\n", " \n", " ####\n", " # Convert function samples into intensity samples, using the function above\n", " ####\n", " intensity_samples = function_samples.exp() * self.mean_intensity\n", " \n", " # Divide the intensity samples into arrival_intensity_samples and quadrature_intensity_samples\n", " arrival_intensity_samples, quadrature_intensity_samples = intensity_samples.split([\n", " arrival_times.size(-1), quadrature_times.size(-1)\n", " ], dim=-1)\n", "\n", " ####\n", " # Compute the log_likelihood, using the method described above\n", " ####\n", " arrival_log_intensities = arrival_intensity_samples.log().sum(dim=-1)\n", " est_num_arrivals = quadrature_intensity_samples.mean(dim=-1).mul(self.max_time)\n", " log_likelihood = arrival_log_intensities - est_num_arrivals\n", " pyro.factor(self.name_prefix + \".log_likelihood\", log_likelihood)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "model = QEPModel(arrival_times.numel(), max_time)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Performing inference\n", "\n", "We'll use Pyro to perform inference. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Defining the quadrature times\n", "\n", "We'll use 128 quadrature points." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "quadrature_times = torch.linspace(0, max_time, 64)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The Pyro SVI inference loop\n", "\n", "Now we'll use Pyro to perform inference." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "pyro.clear_param_store() # so that notebook supports repeated runs" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "194e196c69e349f1ad879686de1506ce", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/200 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Get the average predicted intensity function, and the intensity confidence region\n", "model.eval()\n", "with torch.no_grad():\n", " function_dist = model(quadrature_times)\n", " intensity_samples = function_dist(torch.Size([1000])).exp() * model.mean_intensity\n", " lower, mean, upper = percentiles_from_samples(intensity_samples)\n", "\n", "# Plot the predicted intensity function\n", "fig, ax = plt.subplots(1, 1)\n", "line, = ax.plot(quadrature_times, mean, label=r\"Pred $\\lambda$\")\n", "ax.fill_between(quadrature_times, lower, upper, color=line.get_color(), alpha=0.5)\n", "ax.plot(quadrature_times, true_intensity_function(quadrature_times), \"--\", color=\"k\", label=r\"True. $\\lambda$\")\n", "ax.legend(loc=\"best\")\n", "ax.set_xlabel(\"Time\")\n", "ax.set_ylabel(\"Intensity ($\\lambda$)\")\n", "ax.scatter(arrival_times, torch.zeros_like(arrival_times), label=r\"Observed Arrivals\")\n", "None" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.12.12" } }, "nbformat": 4, "nbformat_minor": 4 }