From 48c3b985f9d66d53076cf6ce87767f1d58ee88ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Louf?= Date: Mon, 23 Aug 2021 22:50:08 +0200 Subject: [PATCH] Use aeppl to build the logprob --- aehmc/trajectory.py | 9 +- examples/HMC.ipynb | 1154 ++++++------------------------------------- 2 files changed, 147 insertions(+), 1016 deletions(-) diff --git a/aehmc/trajectory.py b/aehmc/trajectory.py index f30d1b0..f28b1fd 100644 --- a/aehmc/trajectory.py +++ b/aehmc/trajectory.py @@ -35,15 +35,14 @@ def static_integration( integrator: Callable, step_size: float, num_integration_steps: int, - direction: int = 1, ) -> Callable: """Generate a trajectory by integrating several times in one direction.""" - directed_step_size = direction * step_size - def integrate(q_init, p_init, energy_init, energy_grad_init) -> IntegratorStateType: - def one_step(q, p, energy, energy_grad): - new_state = integrator(q, p, energy, energy_grad, directed_step_size) + def one_step(q, p, potential_energy, potential_energy_grad): + new_state = integrator( + q, p, potential_energy, potential_energy_grad, step_size + ) return new_state [q, p, energy, energy_grad], _ = aesara.scan( diff --git a/examples/HMC.ipynb b/examples/HMC.ipynb index f5713aa..e7d9985 100644 --- a/examples/HMC.ipynb +++ b/examples/HMC.ipynb @@ -18,20 +18,24 @@ "name": "stderr", "output_type": "stream", "text": [ - "WARNING (aesara.tensor.blas): Using NumPy C-API based implementation for BLAS functions.\n", - "WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.\n" + "WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.\n", + "WARNING (aesara.tensor.blas): Using NumPy C-API based implementation for BLAS functions.\n" ] } ], "source": [ - "import aesara\n", - "from aesara.tensor.random.utils import RandomStream\n", - "import aesara.tensor as aet\n", - "from aeppl.logpdf import logpdf\n", "import numpy as np\n", "import pymc3 as pm\n", "\n", - "import aehmc.hmc as hmc" + "import aesara\n", + "import aesara.tensor as aet\n", + "from aesara.tensor.random.utils import RandomStream\n", + "from aeppl.transforms import TransformValuesOpt, LogTransform\n", + "\n", + "from aeppl import joint_logprob\n", + "\n", + "import aehmc.hmc as hmc\n", + "from aehmc.utils import RaveledParamsMap" ] }, { @@ -41,9 +45,12 @@ "metadata": {}, "outputs": [], "source": [ - "NUM_INTEGRATION_STEPS = 10\n", - "STEP_SIZE = 0.0001\n", - "NUM_SAMPLES = 4_000" + "NUM_INTEGRATION_STEPS = 1024\n", + "STEP_SIZE = 5e-5\n", + "PATH_LENGTH = STEP_SIZE * NUM_INTEGRATION_STEPS\n", + "\n", + "NUM_SAMPLES = 1_000\n", + "BURNIN = 100" ] }, { @@ -53,18 +60,18 @@ "source": [ "## The model: a simple linear regression\n", "\n", - "We consider a simple one-dimensional regression problem. To make it a little challenging, we create a dataset with 100,000 points:" + "We consider a simple one-dimensional regression problem. To make it a little challenging, we create a dataset with 10,000 points:" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "id": "eb721064", "metadata": {}, "outputs": [], "source": [ - "X = np.random.normal(0, 1, size=(100_000,))\n", - "y = 3 * X + np.random.normal(0,1)" + "X_val = np.random.normal(0, 1, size=(10_000,))\n", + "y_val = 3 * X_val + np.random.normal(0,1)" ] }, { @@ -77,10 +84,22 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "id": "287315f9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'X' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m y_observed = pm.Normal(\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\"y_observed\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mmu\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mX\u001b[0m \u001b[0;34m@\u001b[0m \u001b[0mweights\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0msigma\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnoise\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mobserved\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'X' is not defined" + ] + } + ], "source": [ "with pm.Model() as pymc3_model:\n", " weights = pm.Normal(\"weights\", mu=0, sigma=1)\n", @@ -100,88 +119,87 @@ "source": [ "### Aeppl implementation\n", "\n", - "We can implement the logpdf of this model directly using `aesara` and `aeppl`:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "4521e461", - "metadata": {}, - "outputs": [], - "source": [ - "def aeppl_model_logpdf(position, X, y):\n", - " weights = position[0]\n", - " noise = position[1]\n", - " l = 0\n", - " l += aet.sum(logpdf(aet.random.normal(0, 1), weights))\n", - " l += aet.sum(logpdf(aet.random.gamma(2, 1), noise))\n", - " mu = aet.dot(X, weights)\n", - " l += aet.sum(logpdf(aet.random.normal(mu, noise), y))\n", - " return l" - ] - }, - { - "cell_type": "markdown", - "id": "8694e9fd", - "metadata": {}, - "source": [ - "Let us condition the model on the data:" + "We can implement the posterior log-probability density function of this model directly using `aesara` and `aeppl`:" ] }, { "cell_type": "code", - "execution_count": 6, - "id": "8b2e9c26", + "execution_count": 9, + "id": "c3d77c35", "metadata": {}, "outputs": [], "source": [ - "aeppl_loglikelihood = lambda position: aeppl_model_logpdf(position, aet.as_tensor(X), aet.as_tensor(y))" - ] - }, - { - "cell_type": "markdown", - "id": "27dfdeb3", - "metadata": {}, - "source": [ - "We can check that the loglikelihood returns the same values as the logpdf produced by PyMC3:" + "X_at = aet.as_tensor(X_val)\n", + "\n", + "N_rv = aet.random.gamma(2.0, 1.0, name=\"N\")\n", + "W_rv = aet.random.normal(0, 1.0, name=\"W\")\n", + "Y_rv = aet.random.normal(X_at.dot(W_rv), N_rv, name=\"Y\")\n", + "\n", + "\n", + "# `aehmc` kernels take a vector as an input. We use a `RaveledParamsMap` to unravel this vector\n", + "# and retrieve ta values for `W_rv` and `Y_rv`.\n", + "rp_map = RaveledParamsMap((W_rv, N_rv))\n", + "\n", + "\n", + "def aeppl_logprob(q):\n", + " uraveled_params = rp_map.unravel_params(q)\n", + " N_vv = uraveled_params[N_rv]\n", + " W_vv = uraveled_params[W_rv]\n", + " \n", + " # The gamma distribution's support is the positive real numbers; algorithms like HMC however prefer to \n", + " # with parameters on the real line. We thus apply a log transform to `N_vv`. PyMC3 applies this \n", + " # transform automatically.\n", + " transforms_op = TransformValuesOpt({N_vv: LogTransform()})\n", + "\n", + " logprob = joint_logprob(Y_rv, {Y_rv: aet.as_tensor(y_val), N_rv: N_vv, W_rv: W_vv}, extra_rewrites=transforms_op)\n", + " return logprob" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "e2b01601", + "execution_count": 10, + "id": "5f79145d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array(-323256.47056254)" + "array(-32227.18839188)" ] }, - "execution_count": 7, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "q = aet.vector(\"q\")\n", - "aeppl_loglikelihood(q).eval({q: np.array([3, 10])})" + "q = aet.vector('q')\n", + "\n", + "logprob_fn = aesara.function((q,), aeppl_logprob(q))\n", + "logprob_fn([3., np.log(10.)])" + ] + }, + { + "cell_type": "markdown", + "id": "27dfdeb3", + "metadata": {}, + "source": [ + "We can check that the loglikelihood returns the same values as the logpdf produced by PyMC3:" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, "id": "97d5859b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array(-323254.16797744)" + "array(-10.81376835)" ] }, - "execution_count": 8, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -198,24 +216,6 @@ "## Sampling with aehmc" ] }, - { - "cell_type": "markdown", - "id": "8fa1bf47", - "metadata": {}, - "source": [ - "`aehmc`'s HMC algorithm takes a potential function as an input, which here can be taken as minus the loglikelihood:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "b4d42a80", - "metadata": {}, - "outputs": [], - "source": [ - "potential = lambda q: -aeppl_loglikelihood(q)" - ] - }, { "cell_type": "markdown", "id": "0b543da1", @@ -234,14 +234,14 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 12, "id": "4d853e81", "metadata": {}, "outputs": [], "source": [ - "srng = RandomStream(seed=59)\n", - "inverse_mass_matrix = aet.as_tensor(np.array([1, 1]))\n", - "kernel = hmc.kernel(srng, potential, STEP_SIZE, inverse_mass_matrix, NUM_INTEGRATION_STEPS)" + "srng = RandomStream(seed=1)\n", + "inverse_mass_matrix = aet.as_tensor(np.array([1., 1.]))\n", + "kernel = hmc.kernel(srng, aeppl_logprob, STEP_SIZE, inverse_mass_matrix, NUM_INTEGRATION_STEPS)" ] }, { @@ -254,13 +254,13 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 13, "id": "6729c9d3", "metadata": {}, "outputs": [], "source": [ "q = aet.vector(\"q\")\n", - "potential_energy = potential(q)\n", + "potential_energy = -aeppl_logprob(q)\n", "potential_energy_grad = aesara.grad(potential_energy, wrt=q)\n", "\n", "next_step = kernel(q, potential_energy, potential_energy_grad)\n", @@ -277,25 +277,25 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 14, "id": "34be0a4a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[array([1.01084087, 2.99503283]),\n", - " array(235786.64172406),\n", - " array([-22079.25441109, 10555.51460628])]" + "[array([ 3.00280254, -1.64604608]),\n", + " array(-4196.38241395),\n", + " array([1703.66049661, 3868.43841482])]" ] }, - "execution_count": 12, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "kernel_fn(np.array([1., 3.]))" + "kernel_fn(np.array([3., np.log(.21)]))" ] }, { @@ -316,15 +316,15 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 15, "id": "865b2355", "metadata": {}, "outputs": [], "source": [ - "def build_trajectory_generator(srng, kernel_generator, potential_fn, num_samples):\n", + "def build_trajectory_generator(srng, kernel_generator, logprob_fn, num_samples):\n", " \"\"\"Builds a function which, given an initial position, returns the full trajectory.\"\"\"\n", " q = aet.vector(\"q\")\n", - " potential_energy = potential_fn(q)\n", + " potential_energy = -logprob_fn(q)\n", " potential_energy_grad = aesara.grad(potential_energy, wrt=q)\n", "\n", " step_size = aet.scalar(\"step_size\")\n", @@ -332,7 +332,7 @@ " num_integration_steps = aet.scalar(\"num_integration_steps\", dtype=\"int32\")\n", "\n", " kernel = kernel_generator(\n", - " srng, potential_fn, step_size, inverse_mass_matrix, num_integration_steps\n", + " srng, logprob_fn, step_size, inverse_mass_matrix, num_integration_steps\n", " )\n", "\n", " trajectory, updates = aesara.scan(\n", @@ -348,7 +348,7 @@ " (q, step_size, inverse_mass_matrix, num_integration_steps),\n", " trajectory,\n", " updates=updates,\n", - " profile=True\n", + " mode='FAST_RUN'\n", " )\n", "\n", " return trajectory_generator" @@ -364,7 +364,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 16, "id": "bb7f49e7", "metadata": {}, "outputs": [ @@ -372,19 +372,19 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 16.7 s, sys: 92.3 ms, total: 16.8 s\n", - "Wall time: 17.3 s\n" + "CPU times: user 47.3 s, sys: 39.5 ms, total: 47.4 s\n", + "Wall time: 47.8 s\n" ] } ], "source": [ "%%time\n", "trajectory_generator = build_trajectory_generator(\n", - " srng, hmc.kernel, potential, num_samples=NUM_SAMPLES\n", + " srng, hmc.kernel, aeppl_logprob, num_samples=NUM_SAMPLES\n", ")\n", "\n", - "initial_position = np.array([1., 3.])\n", - "inverse_mass_matrix = np.array([1, 1])\n", + "initial_position = np.array([3., np.log(1.5)])\n", + "inverse_mass_matrix = np.array([1., 1.])\n", "position, *_ = trajectory_generator(initial_position, STEP_SIZE, inverse_mass_matrix, NUM_INTEGRATION_STEPS)" ] }, @@ -398,25 +398,15 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 17, "id": "db1f3960", "metadata": {}, "outputs": [ { "data": { + "image/png": "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\n", "text/plain": [ - "Text(0.5, 0, 'noise')" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" + "
" ] }, "metadata": { @@ -426,13 +416,10 @@ } ], "source": [ - "from matplotlib import pyplot as plt\n", + "import arviz as az\n", "\n", - "fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,5))\n", - "ax1.hist(position[1000:, 0], density=True)\n", - "ax1.set_xlabel(\"weights\")\n", - "ax2.hist(position[1000:, 1], density=True)\n", - "ax2.set_xlabel(\"noise\")" + "aehmc_trace = az.from_dict(posterior={\"W\": position[BURNIN:, 0], \"N\": np.exp(position[BURNIN:, 1])})\n", + "az.plot_trace(aehmc_trace);" ] }, { @@ -447,904 +434,49 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "c02b9965", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - ":3: FutureWarning: In v4.0, pm.sample will return an `arviz.InferenceData` object instead of a `MultiTrace` by default. You can pass return_inferencedata=True or return_inferencedata=False to be safe and silence this warning.\n", - "Sequential sampling (1 chains in 1 job)\n", - "HamiltonianMC: [noise, weights]\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "
\n", - " \n", - " \n", - " 9.60% [384/4000 03:45<35:23 Sampling chain 0, 0 divergences]\n", - "
\n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Sampling 1 chain for 0 tune and 384 draw iterations (0 + 384 draws total) took 226 seconds.\n", - "The acceptance probability does not match the target. It is 0.9999081203429263, but should be close to 0.65. Try to increase the number of tuning steps.\n", - "Only one chain was sampled, this makes it impossible to run some convergence checks\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CPU times: user 3min 46s, sys: 290 ms, total: 3min 46s\n", - "Wall time: 3min 47s\n" - ] - } - ], - "source": [ - "%%time\n", - "with pymc3_model:\n", - " step = pm.step_methods.hmc.hmc.HamiltonianMC([weights, noise], path_length=NUM_INTEGRATION_STEPS, step_scale=STEP_SIZE)\n", - " posterior = pm.sample(tune=0, draws=NUM_SAMPLES, step=[step], chains=1)" - ] - }, - { - "cell_type": "markdown", - "id": "0ceb7c22", - "metadata": {}, - "source": [ - "`aehmc`'s kernel is orders of magnitude faster than PyMC3's." - ] - }, - { - "cell_type": "markdown", - "id": "85de7daa", - "metadata": {}, - "source": [ - "## Profiling `aehmc`'s generated trajectory" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "0ea2e2f6", - "metadata": {}, "outputs": [], "source": [ - "aesara.config.profile = True\n", - "aesara.config.profile_optimizer = True" + "import time \n", + "\n", + "with pymc3_model:\n", + " step = pm.step_methods.hmc.hmc.HamiltonianMC(\n", + " [weights, noise],\n", + " path_length=PATH_LENGTH,\n", + " step_scale=STEP_SIZE,\n", + " adapt_step_size=False,\n", + " )\n", + " \n", + " # Set initial values\n", + " weights.tag.test_value = initial_position[0]\n", + " noise.tag.test_value = initial_position[1]\n", + " \n", + "with pymc3_model:\n", + " start = time.perf_counter()\n", + " posterior = pm.sample(\n", + " tune=0,\n", + " draws=NUM_SAMPLES,\n", + " step=[step],\n", + " chains=1,\n", + " cores=1,\n", + " return_inferencedata=False,\n", + " compute_convergence_checks=False\n", + " )\n", + " end = time.perf_counter()\n", + " print(end - start)" ] }, { "cell_type": "code", - "execution_count": 18, - "id": "c541cfc2", + "execution_count": null, + "id": "ec971367", "metadata": {}, "outputs": [], "source": [ - "trajectory_generator = build_trajectory_generator(\n", - " srng, hmc.kernel, potential, num_samples=NUM_SAMPLES\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "5be43ffe", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Function profiling\n", - "==================\n", - " Message: :24\n", - " Time in 0 calls to Function.__call__: 0.000000e+00s\n", - " Total compile time: 7.750485e-01s\n", - " Number of Apply nodes: 44\n", - " Aesara Optimizer time: 2.904701e-01s\n", - " Aesara validate time: 2.713919e-03s\n", - " Aesara Linker time (includes C, CUDA code generation/compiling): 0.4756960868835449s\n", - " Import time 0.000000e+00s\n", - " Node make_thunk time 4.746168e-01s\n", - " Node forall_inplace,cpu,scan_fn}(TensorConstant{4000}, IncSubtensor{Set;:int64:}.0, IncSubtensor{InplaceSet;:int64:}.0, IncSubtensor{InplaceSet;:int64:}.0, RandomStateSharedVariable(), RandomStateSharedVariable(), inverse_mass_matrix, num_integration_steps, step_size, Elemwise{Composite{sqrt(reciprocal(i0))}}.0, InplaceDimShuffle{x}.0) time 4.592261e-01s\n", - " Node Elemwise{Composite{(i0 - (i1 * i2))}}(TensorConstant{[-3.669986...70107078]}, TensorConstant{[-0.730944...05940817]}, InplaceDimShuffle{x}.0) time 1.163006e-03s\n", - " Node Shape_i{0}(inverse_mass_matrix) time 8.831024e-04s\n", - " Node Elemwise{mul,no_inplace}(Elemwise{true_div,no_inplace}.0, TensorConstant{[-0.730944...05940817]}) time 6.392002e-04s\n", - " Node Elemwise{Composite{(i0 + (i1 * sqr(i2)) + Switch(i3, (Switch(i4, i5, i6) - i7), i8) + i9)}}[(0, 6)](TensorConstant{(1,) of -0..5332046727}, TensorConstant{(1,) of -0.5}, InplaceDimShuffle{x}.0, InplaceDimShuffle{x}.0, InplaceDimShuffle{x}.0, TensorConstant{(1,) of -inf}, InplaceDimShuffle{x}.0, InplaceDimShuffle{x}.0, TensorConstant{(1,) of -inf}, InplaceDimShuffle{x}.0) time 6.022453e-04s\n", - "\n", - "Time in all call to aesara.grad() 1.597838e-01s\n", - "Time since aesara import 251.709s\n", - "Optimizer Profile\n", - "-----------------\n", - " SeqOptimizer OPT_FAST_RUN time 0.290s for 162/44 nodes before/after optimization\n", - " 0.050s for callback\n", - " 0.003s for fgraph.validate()\n", - " time - (name, class, index, nodes before, nodes after) - validate time\n", - " 0.073859s - ('canonicalize', 'EquilibriumOptimizer', 7, 146, 69) - 0.001s\n", - " EquilibriumOptimizer canonicalize\n", - " time 0.074s for 4 passes\n", - " nb nodes (start, end, max) 146 69 146\n", - " time io_toposort 0.000s\n", - " time in local optimizers 0.047s\n", - " time in global optimizers 0.000s\n", - " time in final optimizers 0.021s\n", - " time in cleanup optimizers 0.003s\n", - " 0 - 0.052s 101 (0.018s in global opts, 0.000s io_toposort) - 146 nodes - ('MergeOptimizer', 29) ('local_dimshuffle_lift', 16) ('local_neg_to_mul', 10) ('local_upcast_elemwise_constant_inputs', 9) ('local_mul_canonizer', 7) ...\n", - " 1 - 0.013s 31 (0.003s in global opts, 0.000s io_toposort) - 88 nodes - ('MergeOptimizer', 7) ('local_mul_canonizer', 6) ('local_subtensor_make_vector', 3) ('local_add_canonizer', 3) ('local_div_switch_sink', 2) ...\n", - " 2 - 0.004s 3 (0.000s in global opts, 0.000s io_toposort) - 70 nodes - ('local_sum_prod_all_to_none', 1) ('local_sum_prod_div_dimshuffle', 1) ('local_mul_canonizer', 1)\n", - " 3 - 0.004s 0 (0.000s in global opts, 0.000s io_toposort) - 69 nodes - \n", - " times - times applied - nb node created - name:\n", - " 0.021s - 2 - 0 - topo_constant_folding\n", - " 0.007s - 14 - 15 - local_mul_canonizer\n", - " 0.006s - 10 - 18 - local_add_canonizer\n", - " 0.006s - 17 - 22 - local_dimshuffle_lift\n", - " 0.005s - 5 - 20 - local_greedy_distributor\n", - " 0.005s - 10 - 30 - local_upcast_elemwise_constant_inputs\n", - " 0.003s - 10 - 16 - local_neg_to_mul\n", - " 0.003s - 36 - 0 - MergeOptimizer\n", - " 0.002s - 4 - 6 - local_fill_sink\n", - " 0.001s - 2 - 4 - local_div_switch_sink\n", - " 0.001s - 3 - 6 - local_sum_prod_div_dimshuffle\n", - " 0.001s - 6 - 6 - local_sum_prod_all_to_none\n", - " 0.001s - 4 - 6 - local_shape_to_shape_i\n", - " 0.001s - 1 - 2 - local_mul_switch_sink\n", - " 0.000s - 6 - 0 - local_useless_fill\n", - " 0.000s - 3 - 0 - local_subtensor_make_vector\n", - " 0.000s - 2 - 0 - local_pow_canonicalize\n", - " 0.008s - in 73 optimization that were not used (display only those with a runtime > 0)\n", - " 0.001s - local_func_inv\n", - " 0.001s - local_mul_zero\n", - " 0.001s - local_useless_elemwise\n", - " 0.001s - local_useless_elemwise_comparison\n", - " 0.001s - local_merge_switch_same_cond\n", - " 0.000s - local_one_minus_erf2\n", - " 0.000s - local_track_shape_i\n", - " 0.000s - local_view_op\n", - " 0.000s - local_one_minus_erf\n", - " 0.000s - local_useless_switch\n", - " 0.000s - local_exp_log\n", - " 0.000s - local_useless_composite\n", - " 0.000s - local_cast_cast\n", - " 0.000s - local_expm1\n", - " 0.000s - local_useless_subtensor\n", - " 0.000s - local_IncSubtensor_serialize\n", - " 0.000s - local_useless_rebroadcast\n", - " 0.000s - local_useless_slice\n", - " 0.000s - local_useless_inc_subtensor\n", - " 0.000s - local_zero_div\n", - " 0.000s - local_setsubtensor_of_constants\n", - " 0.000s - local_subtensor_remove_broadcastable_index\n", - " 0.000s - local_incsubtensor_of_zeros\n", - " 0.000s - local_subtensor_lift\n", - " 0.000s - local_lift_transpose_through_dot\n", - " 0.000s - local_op_of_op\n", - " 0.000s - local_subtensor_inc_subtensor\n", - " 0.000s - local_useless_inc_subtensor_alloc\n", - " 0.000s - local_sumsqr2dot\n", - " 0.000s - local_reduce_broadcastable\n", - " 0.000s - local_subtensor_merge\n", - " 0.000s - local_subtensor_of_alloc\n", - " 0.000s - local_reduce_join\n", - " 0.000s - local_subtensor_of_dot\n", - " 0.000s - local_useless_reduce\n", - " 0.000s - local_rebroadcast_lift\n", - " 0.000s - local_incsubtensor_of_zeros_to_setsubtensor\n", - " 0.000s - local_scalar_tensor_scalar\n", - "\n", - " Global, final and clean up optimizers\n", - " Iter 0\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (130, 90, 40)\n", - " init io_toposort 0.00015473365783691406\n", - " loop time 0.017719030380249023\n", - " callback_time 0.002961397171020508\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 55 constant= 34\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " Iter 1\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (75, 70, 5)\n", - " init io_toposort 9.5367431640625e-05\n", - " loop time 0.0024902820587158203\n", - " callback_time 0.00038123130798339844\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 11 constant= 10\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " Iter 2\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (69, 69, 0)\n", - " init io_toposort 8.654594421386719e-05\n", - " loop time 4.9114227294921875e-05\n", - " callback_time 0.0\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 0 constant= 0\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " Iter 3\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (69, 69, 0)\n", - " init io_toposort 8.726119995117188e-05\n", - " loop time 4.9591064453125e-05\n", - " callback_time 0.0\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 0 constant= 0\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " 0.057521s - ('scan_eqopt1', 'EquilibriumOptimizer', 2, 153, 159) - 0.000s\n", - " EquilibriumOptimizer scan_eqopt1\n", - " time 0.058s for 3 passes\n", - " nb nodes (start, end, max) 153 159 165\n", - " time io_toposort 0.001s\n", - " time in local optimizers 0.000s\n", - " time in global optimizers 0.056s\n", - " time in final optimizers 0.000s\n", - " time in cleanup optimizers 0.000s\n", - " 0 - 0.023s 1 (0.022s in global opts, 0.000s io_toposort) - 165 nodes - ('SeqOpt([, , , , ])', 1)\n", - " 1 - 0.020s 1 (0.020s in global opts, 0.000s io_toposort) - 159 nodes - ('SeqOpt([, , , , ])', 1)\n", - " 2 - 0.014s 0 (0.014s in global opts, 0.000s io_toposort) - 159 nodes - \n", - " times - times applied - nb node created - name:\n", - " 0.056s - 2 - 14 - SeqOpt([, , , , ])\n", - " 0.000s - in 0 optimization that were not used (display only those with a runtime > 0)\n", - "\n", - " Global, final and clean up optimizers\n", - " Iter 0\n", - " SeqOptimizer all_pushout_opt time 0.022s for 153/165 nodes before/after optimization\n", - " 0.000s for callback\n", - " 0.000s for fgraph.validate()\n", - " 0.012066s - ('scanOp_pushout_nonseqs_ops', 'PushOutNonSeqScan', 1, 153, 165) - 0.000s\n", - " 0.005079s - ('scanOp_pushout_output', 'PushOutScanOutput', 4, 165, 165) - 0.000s\n", - " 0.004303s - ('scanOp_pushout_seqs_ops', 'PushOutSeqScan', 2, 165, 165) - 0.000s\n", - " 0.000423s - ('remove_constants_and_unused_inputs_scan', 'TopoOptimizer', 0, 153, 153) - 0.000s\n", - " TopoOptimizer scanOp_remove_constants_and_unused_inputs0\n", - " nb_node (start, end, changed) (153, 153, 0)\n", - " init io_toposort 0.00017571449279785156\n", - " loop time 0.00024318695068359375\n", - " callback_time 0.0\n", - " 0.000234s - ('scan_pushout_dot1', 'PushOutDot1', 3, 165, 165) - 0.000s\n", - "\n", - " Iter 1\n", - " SeqOptimizer all_pushout_opt time 0.020s for 165/159 nodes before/after optimization\n", - " 0.000s for callback\n", - " 0.000s for fgraph.validate()\n", - " 0.006255s - ('remove_constants_and_unused_inputs_scan', 'TopoOptimizer', 0, 165, 159) - 0.000s\n", - " TopoOptimizer scanOp_remove_constants_and_unused_inputs0\n", - " nb_node (start, end, changed) (165, 159, 1)\n", - " init io_toposort 0.0001823902130126953\n", - " loop time 0.006066799163818359\n", - " callback_time 7.271766662597656e-05\n", - " 0.004653s - ('scanOp_pushout_nonseqs_ops', 'PushOutNonSeqScan', 1, 159, 159) - 0.000s\n", - " 0.004620s - ('scanOp_pushout_output', 'PushOutScanOutput', 4, 159, 159) - 0.000s\n", - " 0.004264s - ('scanOp_pushout_seqs_ops', 'PushOutSeqScan', 2, 159, 159) - 0.000s\n", - " 0.000224s - ('scan_pushout_dot1', 'PushOutDot1', 3, 159, 159) - 0.000s\n", - "\n", - " Iter 2\n", - " SeqOptimizer all_pushout_opt time 0.014s for 159/159 nodes before/after optimization\n", - " 0.000s for callback\n", - " 0.000s for fgraph.validate()\n", - " 0.004682s - ('scanOp_pushout_nonseqs_ops', 'PushOutNonSeqScan', 1, 159, 159) - 0.000s\n", - " 0.004488s - ('scanOp_pushout_output', 'PushOutScanOutput', 4, 159, 159) - 0.000s\n", - " 0.004261s - ('scanOp_pushout_seqs_ops', 'PushOutSeqScan', 2, 159, 159) - 0.000s\n", - " 0.000419s - ('remove_constants_and_unused_inputs_scan', 'TopoOptimizer', 0, 159, 159) - 0.000s\n", - " TopoOptimizer scanOp_remove_constants_and_unused_inputs0\n", - " nb_node (start, end, changed) (159, 159, 0)\n", - " init io_toposort 0.00017571449279785156\n", - " loop time 0.00023865699768066406\n", - " callback_time 0.0\n", - " 0.000225s - ('scan_pushout_dot1', 'PushOutDot1', 3, 159, 159) - 0.000s\n", - "\n", - " 0.048995s - ('specialize', 'EquilibriumOptimizer', 16, 141, 68) - 0.000s\n", - " EquilibriumOptimizer specialize\n", - " time 0.049s for 4 passes\n", - " nb nodes (start, end, max) 141 68 141\n", - " time io_toposort 0.000s\n", - " time in local optimizers 0.018s\n", - " time in global optimizers 0.001s\n", - " time in final optimizers 0.028s\n", - " time in cleanup optimizers 0.000s\n", - " 0 - 0.033s 20 (0.023s in global opts, 0.000s io_toposort) - 141 nodes - ('local_shape_to_shape_i', 5) ('local_add_specialize', 3) ('local_useless_slice', 3) ('local_sum_prod_mul_by_scalar', 2) ('local_pow_specialize', 2) ...\n", - " 1 - 0.011s 14 (0.004s in global opts, 0.000s io_toposort) - 83 nodes - ('local_subtensor_make_vector', 4) ('local_useless_subtensor', 4) ('local_mul_specialize', 2) ('local_dimshuffle_lift', 2) ('topo_constant_folding', 1) ...\n", - " 2 - 0.002s 2 (0.000s in global opts, 0.000s io_toposort) - 70 nodes - ('local_useless_subtensor', 2)\n", - " 3 - 0.002s 0 (0.000s in global opts, 0.000s io_toposort) - 68 nodes - \n", - " times - times applied - nb node created - name:\n", - " 0.028s - 2 - 0 - topo_constant_folding\n", - " 0.003s - 3 - 6 - local_add_specialize\n", - " 0.003s - 2 - 15 - local_dimshuffle_lift\n", - " 0.001s - 2 - 8 - local_sum_prod_mul_by_scalar\n", - " 0.001s - 5 - 5 - local_shape_to_shape_i\n", - " 0.001s - 3 - 3 - local_mul_specialize\n", - " 0.000s - 6 - 0 - local_useless_subtensor\n", - " 0.000s - 3 - 3 - local_useless_slice\n", - " 0.000s - 1 - 1 - local_div_to_reciprocal\n", - " 0.000s - 2 - 2 - local_pow_specialize\n", - " 0.000s - 4 - 0 - local_subtensor_make_vector\n", - " 0.000s - 1 - 2 - local_rebroadcast_lift\n", - " 0.000s - 2 - 0 - local_remove_useless_assert\n", - " 0.007s - in 65 optimization that were not used (display only those with a runtime > 0)\n", - " 0.001s - local_func_inv\n", - " 0.001s - local_one_minus_erf\n", - " 0.001s - local_one_minus_erf2\n", - " 0.001s - local_elemwise_alloc\n", - " 0.001s - local_useless_elemwise\n", - " 0.001s - crossentropy_to_crossentropy_with_softmax_with_bias\n", - " 0.000s - local_useless_elemwise_comparison\n", - " 0.000s - local_track_shape_i\n", - " 0.000s - local_useless_switch\n", - " 0.000s - local_exp_log\n", - " 0.000s - local_abs_merge\n", - " 0.000s - local_expm1\n", - " 0.000s - local_cast_cast\n", - " 0.000s - local_logsoftmax\n", - " 0.000s - local_elemwise_sub_zeros\n", - " 0.000s - local_alloc_unary\n", - " 0.000s - local_useless_rebroadcast\n", - " 0.000s - local_useless_inc_subtensor\n", - " 0.000s - local_mul_switch_sink\n", - " 0.000s - local_subtensor_remove_broadcastable_index\n", - " 0.000s - local_grad_log_erfc_neg\n", - " 0.000s - local_zero_div\n", - " 0.000s - local_mul_to_sqr\n", - " 0.000s - local_subtensor_inc_subtensor\n", - " 0.000s - local_sum_prod_div_dimshuffle\n", - " 0.000s - local_useless_inc_subtensor_alloc\n", - " 0.000s - local_reduce_broadcastable\n", - " 0.000s - local_subtensor_merge\n", - " 0.000s - local_subtensor_of_alloc\n", - " 0.000s - local_scalar_tensor_scalar\n", - " 0.000s - local_incsubtensor_of_zeros_to_setsubtensor\n", - " 0.000s - local_subtensor_of_dot\n", - " 0.000s - local_neg_neg\n", - " 0.000s - local_canonicalize_alloc\n", - " 0.000s - local_advanced_indexing_crossentropy_onehot\n", - " 0.000s - local_sumsqr2dot\n", - " 0.000s - local_opt_alloc\n", - " 0.000s - local_log1p\n", - " 0.000s - local_neg_div_neg\n", - " 0.000s - local_log_erfc\n", - " 0.000s - local_log_add\n", - " 0.000s - local_useless_alloc\n", - " 0.000s - local_merge_alloc\n", - "\n", - " Global, final and clean up optimizers\n", - " Iter 0\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (146, 83, 63)\n", - " init io_toposort 0.0001766681671142578\n", - " loop time 0.022988557815551758\n", - " callback_time 0.0035560131072998047\n", - " Iter 1\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (78, 70, 8)\n", - " init io_toposort 9.369850158691406e-05\n", - " loop time 0.004173994064331055\n", - " callback_time 0.0006353855133056641\n", - " Iter 2\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (68, 68, 0)\n", - " init io_toposort 8.392333984375e-05\n", - " loop time 4.863739013671875e-05\n", - " callback_time 0.0\n", - " Iter 3\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (68, 68, 0)\n", - " init io_toposort 8.416175842285156e-05\n", - " loop time 4.887580871582031e-05\n", - " callback_time 0.0\n", - " 0.023798s - ('scan_eqopt2', 'EquilibriumOptimizer', 13, 67, 67) - 0.000s\n", - " EquilibriumOptimizer scan_eqopt2\n", - " time 0.024s for 2 passes\n", - " nb nodes (start, end, max) 67 67 67\n", - " time io_toposort 0.000s\n", - " time in local optimizers 0.000s\n", - " time in global optimizers 0.023s\n", - " time in final optimizers 0.000s\n", - " time in cleanup optimizers 0.000s\n", - " 0 - 0.019s 1 (0.018s in global opts, 0.000s io_toposort) - 67 nodes - ('remove_constants_and_unused_inputs_scan', 1)\n", - " 1 - 0.005s 0 (0.005s in global opts, 0.000s io_toposort) - 67 nodes - \n", - " times - times applied - nb node created - name:\n", - " 0.014s - 1 - 1 - remove_constants_and_unused_inputs_scan\n", - " 0.009s - in 5 optimization that were not used (display only those with a runtime > 0)\n", - " 0.008s - scan_merge_inouts\n", - " 0.001s - remove_constants_and_unused_inputs_scan\n", - " 0.000s - remove_constants_and_unused_inputs_scan\n", - " 0.000s - constant_folding\n", - " 0.000s - \n", - "\n", - " Global, final and clean up optimizers\n", - " Iter 0\n", - " TopoOptimizer constant_folding_for_scan2\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.058547973632812e-05\n", - " loop time 5.14984130859375e-05\n", - " callback_time 0.0\n", - " TopoOptimizer scanOp_remove_constants_and_unused_inputs1\n", - " nb_node (start, end, changed) (67, 67, 1)\n", - " init io_toposort 7.748603820800781e-05\n", - " loop time 0.013595104217529297\n", - " callback_time 0.00722956657409668\n", - " TopoOptimizer scanop_remove_constants_and_unused_inputs2\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.0108642578125e-05\n", - " loop time 0.00016832351684570312\n", - " callback_time 0.0\n", - " TopoOptimizer scanOp_merge_inouts\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.249282836914062e-05\n", - " loop time 0.003879547119140625\n", - " callback_time 0.0\n", - " TopoOptimizer scanOp_remove_constants_and_unused_inputs3\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.702278137207031e-05\n", - " loop time 0.00017213821411132812\n", - " callback_time 0.0\n", - " Iter 1\n", - " TopoOptimizer constant_folding_for_scan2\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.20159912109375e-05\n", - " loop time 4.792213439941406e-05\n", - " callback_time 0.0\n", - " TopoOptimizer scanOp_remove_constants_and_unused_inputs1\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 7.891654968261719e-05\n", - " loop time 0.0001666545867919922\n", - " callback_time 0.0\n", - " TopoOptimizer scanop_remove_constants_and_unused_inputs2\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 7.605552673339844e-05\n", - " loop time 0.00016427040100097656\n", - " callback_time 0.0\n", - " TopoOptimizer scanOp_merge_inouts\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 7.939338684082031e-05\n", - " loop time 0.003902912139892578\n", - " callback_time 0.0\n", - " TopoOptimizer scanOp_remove_constants_and_unused_inputs3\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.630752563476562e-05\n", - " loop time 0.0001811981201171875\n", - " callback_time 0.0\n", - " 0.022581s - ('scanOp_save_mem', 'ScanSaveMem', 14, 67, 141) - 0.000s\n", - " 0.010699s - ('scanOp_make_inplace', 'ScanInplaceOptimizer', 49, 44, 44) - 0.000s\n", - " 0.010460s - ('ShapeOpt', 'ShapeOptimizer', 3, 159, 159) - 0.000s\n", - " 0.009874s - ('BlasOpt', 'SeqOptimizer', 15, 141, 141) - 0.000s\n", - " SeqOptimizer BlasOpt time 0.010s for 141/141 nodes before/after optimization\n", - " 0.000s for callback\n", - " 0.000s for fgraph.validate()\n", - " 0.006044s - ('use_c_blas', 'TopoOptimizer', 4, 141, 141) - 0.000s\n", - " TopoOptimizer use_c_blas\n", - " nb_node (start, end, changed) (141, 141, 0)\n", - " init io_toposort 0.00017404556274414062\n", - " loop time 0.005860805511474609\n", - " callback_time 0.0\n", - " 0.002404s - ('gemm_optimizer', 'GemmOptimizer', 1, 141, 141) - 0.000s\n", - " GemmOptimizer\n", - " nb_iter 1\n", - " nb_replacement 0\n", - " nb_replacement_didn_t_remove 0\n", - " nb_inconsistency_make 0\n", - " nb_inconsistency_replace 0\n", - " time_canonicalize 0.001386880874633789\n", - " time_factor_can 0\n", - " time_factor_list 0\n", - " time_toposort 0.00017309188842773438\n", - " validate_time 0.0\n", - " callback_time 0.0\n", - " 0.000430s - ('local_dot22_to_dot22scalar', 'TopoOptimizer', 2, 141, 141) - 0.000s\n", - " TopoOptimizer local_dot22_to_dot22scalar\n", - " nb_node (start, end, changed) (141, 141, 0)\n", - " init io_toposort 0.00017309188842773438\n", - " loop time 0.0002491474151611328\n", - " callback_time 0.0\n", - " 0.000421s - ('local_gemm_to_gemv', 'EquilibriumOptimizer', 3, 141, 141) - 0.000s\n", - " EquilibriumOptimizer local_gemm_to_gemv\n", - " time 0.000s for 1 passes\n", - " nb nodes (start, end, max) 141 141 141\n", - " time io_toposort 0.000s\n", - " time in local optimizers 0.000s\n", - " time in global optimizers 0.000s\n", - " time in final optimizers 0.000s\n", - " time in cleanup optimizers 0.000s\n", - " 0 - 0.000s 0 (0.000s in global opts, 0.000s io_toposort) - 141 nodes - \n", - " 0.000282s - ('local_dot_to_dot22', 'TopoOptimizer', 0, 141, 141) - 0.000s\n", - " TopoOptimizer local_dot_to_dot22\n", - " nb_node (start, end, changed) (141, 141, 0)\n", - " init io_toposort 0.0001773834228515625\n", - " loop time 9.584426879882812e-05\n", - " callback_time 0.0\n", - " 0.000279s - ('use_scipy_ger', 'TopoOptimizer', 5, 141, 141) - 0.000s\n", - " TopoOptimizer scipy_blas\n", - " nb_node (start, end, changed) (141, 141, 0)\n", - " init io_toposort 0.00018358230590820312\n", - " loop time 8.749961853027344e-05\n", - " callback_time 0.0\n", - "\n", - " 0.009009s - ('elemwise_fusion', 'SeqOptimizer', 21, 68, 47) - 0.000s\n", - " SeqOptimizer elemwise_fusion time 0.009s for 68/47 nodes before/after optimization\n", - " 0.001s for callback\n", - " 0.000s for fgraph.validate()\n", - " 0.008479s - ('composite_elemwise_fusion', 'FusionOptimizer', 1, 67, 47) - 0.000s\n", - " FusionOptimizer\n", - " nb_iter 2\n", - " nb_replacement 6\n", - " nb_inconsistency_replace 0\n", - " validate_time 2.4080276489257812e-05\n", - " callback_time 0.00044274330139160156\n", - " time_toposort 0.00014829635620117188\n", - " 0.000519s - ('local_add_mul_fusion', 'FusionOptimizer', 0, 68, 67) - 0.000s\n", - " FusionOptimizer\n", - " nb_iter 2\n", - " nb_replacement 1\n", - " nb_inconsistency_replace 0\n", - " validate_time 4.0531158447265625e-06\n", - " callback_time 0.0001246929168701172\n", - " time_toposort 0.00016832351684570312\n", - "\n", - " 0.006206s - ('inplace_elemwise_opt', 'InplaceElemwiseOptimizer', 48, 44, 44) - 0.001s\n", - " InplaceElemwiseOptimizer \n", - " node_before 44\n", - " nb_call_replace 10\n", - " nb_call_validate 10\n", - " nb_inconsistent 5\n", - " ndim nb\n", - " 0 5\n", - " 1 5\n", - " 0.004699s - ('stabilize', 'EquilibriumOptimizer', 9, 69, 67) - 0.000s\n", - " EquilibriumOptimizer stabilize\n", - " time 0.005s for 2 passes\n", - " nb nodes (start, end, max) 69 67 69\n", - " time io_toposort 0.000s\n", - " time in local optimizers 0.002s\n", - " time in global optimizers 0.000s\n", - " time in final optimizers 0.002s\n", - " time in cleanup optimizers 0.000s\n", - " 0 - 0.003s 3 (0.002s in global opts, 0.000s io_toposort) - 69 nodes - ('local_fill_to_alloc', 2) ('topo_constant_folding', 1)\n", - " 1 - 0.001s 0 (0.000s in global opts, 0.000s io_toposort) - 67 nodes - \n", - " times - times applied - nb node created - name:\n", - " 0.002s - 1 - 0 - topo_constant_folding\n", - " 0.000s - 2 - 2 - local_fill_to_alloc\n", - " 0.002s - in 40 optimization that were not used (display only those with a runtime > 0)\n", - " 0.001s - local_greedy_distributor\n", - " 0.000s - local_one_minus_erf2\n", - " 0.000s - local_sigm_times_exp\n", - " 0.000s - crossentropy_to_crossentropy_with_softmax_with_bias\n", - " 0.000s - local_useless_elemwise_comparison\n", - " 0.000s - local_one_minus_erf\n", - " 0.000s - local_expm1\n", - " 0.000s - local_exp_over_1_plus_exp\n", - " 0.000s - local_setsubtensor_of_constants\n", - " 0.000s - local_grad_log_erfc_neg\n", - " 0.000s - local_incsubtensor_of_zeros\n", - " 0.000s - Elemwise{log,no_inplace}(Elemwise{sigmoid,no_inplace}(x)) -> Elemwise{neg,no_inplace}(Elemwise{softplus,no_inplace}(Elemwise{neg,no_inplace}(x)))\n", - " 0.000s - local_useless_inc_subtensor_alloc\n", - " 0.000s - Elemwise{log,no_inplace}(Elemwise{sub,no_inplace}(y subject to , Elemwise{sigmoid,no_inplace}(x))) -> Elemwise{neg,no_inplace}(Elemwise{softplus,no_inplace}(x))\n", - " 0.000s - local_subtensor_of_dot\n", - " 0.000s - local_log1p\n", - " 0.000s - local_log_add\n", - " 0.000s - local_log_erfc\n", - " 0.000s - local_canonicalize_alloc\n", - " 0.000s - local_useless_alloc\n", - " 0.000s - local_merge_alloc\n", - "\n", - " Global, final and clean up optimizers\n", - " Iter 0\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (69, 67, 2)\n", - " init io_toposort 8.678436279296875e-05\n", - " loop time 0.0013842582702636719\n", - " callback_time 0.00018548965454101562\n", - " Iter 1\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.487701416015625e-05\n", - " loop time 4.792213439941406e-05\n", - " callback_time 0.0\n", - " 0.002686s - ('useless', 'TopoOptimizer', 4, 159, 146) - 0.000s\n", - " TopoOptimizer useless\n", - " nb_node (start, end, changed) (159, 146, 13)\n", - " init io_toposort 0.00017905235290527344\n", - " loop time 0.0024917125701904297\n", - " callback_time 0.0003857612609863281\n", - " LocalOptGroup\n", - " ---------------------\n", - " time taken - times applied - times tried - name - node_created:\n", - " -0.000s - 0 - 5 - local_useless_inc_subtensor_alloc - 0\n", - " -0.000s - 0 - 11 - local_subtensor_of_alloc - 0\n", - " -0.000s - 0 - 11 - local_subtensor_make_vector - 0\n", - " -0.000s - 6 - 10 - local_useless_reduce - 0\n", - " -0.000s - 4 - 6 - local_useless_fill - 0\n", - " -0.000s - 0 - 5 - local_useless_inc_subtensor - 0\n", - " -0.000s - 0 - 3 - local_useless_rebroadcast - 0\n", - " -0.000s - 0 - 11 - local_useless_slice - 0\n", - " -0.000s - 0 - 94 - local_useless_switch - 0\n", - " -0.000s - 0 - 157 - local_view_op - 0\n", - " -0.000s - 0 - 94 - local_useless_elemwise_comparison - 0\n", - " -0.000s - 3 - 97 - local_useless_elemwise - 0\n", - " 0.000s - in 9 optimization that were not used (display those with runtime greater than 0)\n", - "\n", - " 0.002225s - ('merge1', 'MergeOptimizer', 1, 162, 153) - 0.000s\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 42 constant= 33\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " 0.001299s - ('local_inplace_setsubtensor', 'TopoOptimizer', 37, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_setsubtensor\n", - " nb_node (start, end, changed) (44, 44, 4)\n", - " init io_toposort 5.125999450683594e-05\n", - " loop time 0.001239776611328125\n", - " callback_time 0.0007669925689697266\n", - " 0.000679s - ('local_IncSubtensor_serialize', 'TopoOptimizer', 6, 146, 146) - 0.000s\n", - " TopoOptimizer pre_local_IncSubtensor_serialize\n", - " nb_node (start, end, changed) (146, 146, 1)\n", - " init io_toposort 0.00016379356384277344\n", - " loop time 0.0005068778991699219\n", - " callback_time 7.82012939453125e-05\n", - " 0.000599s - ('blas_opt_inplace', 'TopoOptimizer', 42, 44, 44) - 0.000s\n", - " TopoOptimizer InplaceBlasOpt\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.054473876953125e-05\n", - " loop time 0.0005350112915039062\n", - " callback_time 0.0\n", - " 0.000420s - ('uncanonicalize', 'EquilibriumOptimizer', 18, 68, 68) - 0.000s\n", - " EquilibriumOptimizer uncanonicalize\n", - " time 0.000s for 1 passes\n", - " nb nodes (start, end, max) 68 68 68\n", - " time io_toposort 0.000s\n", - " time in local optimizers 0.000s\n", - " time in global optimizers 0.000s\n", - " time in final optimizers 0.000s\n", - " time in cleanup optimizers 0.000s\n", - " 0 - 0.000s 0 (0.000s in global opts, 0.000s io_toposort) - 68 nodes - \n", - " Global, final and clean up optimizers\n", - " Iter 0\n", - " TopoOptimizer topo_constant_folding\n", - " nb_node (start, end, changed) (68, 68, 0)\n", - " init io_toposort 7.963180541992188e-05\n", - " loop time 4.887580871582031e-05\n", - " callback_time 0.0\n", - " 0.000415s - ('merge2', 'MergeOptimizer', 23, 47, 44) - 0.000s\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 10 constant= 7\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " 0.000296s - ('inline_ofg_expansion', 'TopoOptimizer', 0, 162, 162) - 0.000s\n", - " TopoOptimizer inline_ofg_expansion\n", - " nb_node (start, end, changed) (162, 162, 0)\n", - " init io_toposort 0.00018310546875\n", - " loop time 0.00010323524475097656\n", - " callback_time 0.0\n", - " 0.000284s - ('c_blas_destructive', 'TopoOptimizer', 44, 44, 44) - 0.000s\n", - " TopoOptimizer c_blas_destructive\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.53131103515625e-05\n", - " loop time 0.00022101402282714844\n", - " callback_time 0.0\n", - " 0.000249s - ('gpuablas_opt_inplace', 'TopoOptimizer', 43, 44, 44) - 0.000s\n", - " TopoOptimizer InplaceGpuaBlasOpt\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.888938903808594e-05\n", - " loop time 0.0001709461212158203\n", - " callback_time 0.0\n", - " 0.000241s - ('local_dnna_conv_inplace', 'TopoOptimizer', 45, 44, 44) - 0.000s\n", - " TopoOptimizer local_dnna_conv_inplace\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.7697296142578125e-05\n", - " loop time 0.00016760826110839844\n", - " callback_time 0.0\n", - " 0.000212s - ('specialize_device', 'EquilibriumOptimizer', 19, 68, 68) - 0.000s\n", - " EquilibriumOptimizer specialize_device\n", - " time 0.000s for 1 passes\n", - " nb nodes (start, end, max) 68 68 68\n", - " time io_toposort 0.000s\n", - " time in local optimizers 0.000s\n", - " time in global optimizers 0.000s\n", - " time in final optimizers 0.000s\n", - " time in cleanup optimizers 0.000s\n", - " 0 - 0.000s 0 (0.000s in global opts, 0.000s io_toposort) - 68 nodes - \n", - " 0.000201s - ('local_elemwise_alloc', 'TopoOptimizer', 11, 67, 67) - 0.000s\n", - " TopoOptimizer local_elemwise_alloc\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.153915405273438e-05\n", - " loop time 0.00011348724365234375\n", - " callback_time 0.0\n", - " 0.000200s - ('add_destroy_handler', 'AddDestroyHandler', 24, 44, 44) - 0.000s\n", - " 0.000200s - ('AbstractConvCheck', 'TopoOptimizer', 20, 68, 68) - 0.000s\n", - " TopoOptimizer AbstractConvCheck\n", - " nb_node (start, end, changed) (68, 68, 0)\n", - " init io_toposort 8.106231689453125e-05\n", - " loop time 0.00011086463928222656\n", - " callback_time 0.0\n", - " 0.000167s - ('local_log_sum_exp', 'TopoOptimizer', 12, 67, 67) - 0.000s\n", - " TopoOptimizer local_log_sum_exp\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 7.939338684082031e-05\n", - " loop time 8.416175842285156e-05\n", - " callback_time 0.0\n", - " 0.000165s - ('local_fill_to_alloc', 'TopoOptimizer', 10, 67, 67) - 0.000s\n", - " TopoOptimizer local_fill_to_alloc\n", - " nb_node (start, end, changed) (67, 67, 0)\n", - " init io_toposort 8.082389831542969e-05\n", - " loop time 7.700920104980469e-05\n", - " callback_time 0.0\n", - " 0.000108s - ('local_advincsub1_gpua_inplace', 'TopoOptimizer', 25, 44, 44) - 0.000s\n", - " TopoOptimizer local_advincsub1_gpua_inplace\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.698204040527344e-05\n", - " loop time 4.2438507080078125e-05\n", - " callback_time 0.0\n", - " 0.000103s - ('local_inplace_sparse_block_gemv', 'TopoOptimizer', 38, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_sparse_block_gemv\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 6.031990051269531e-05\n", - " loop time 3.170967102050781e-05\n", - " callback_time 0.0\n", - " 0.000099s - ('crossentropy_to_crossentropy_with_softmax', 'FromFunctionOptimizer', 17, 68, 68) - 0.000s\n", - " 0.000098s - ('make_ger_destructive', 'TopoOptimizer', 46, 44, 44) - 0.000s\n", - " TopoOptimizer make_scipy_blas_destructive\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 6.198883056640625e-05\n", - " loop time 3.0040740966796875e-05\n", - " callback_time 0.0\n", - " 0.000097s - ('cond_make_inplace', 'TopoOptimizer', 50, 44, 44) - 0.000s\n", - " TopoOptimizer cond_make_inplace\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.888938903808594e-05\n", - " loop time 3.314018249511719e-05\n", - " callback_time 0.0\n", - " 0.000096s - ('local_inplace_gpu_magma_cholesky', 'TopoOptimizer', 34, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_gpu_magma_cholesky\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.650520324707031e-05\n", - " loop time 3.170967102050781e-05\n", - " callback_time 0.0\n", - " 0.000095s - ('local_batch_norm_inference_inplace', 'TopoOptimizer', 26, 44, 44) - 0.000s\n", - " TopoOptimizer local_batch_norm_inference_inplace\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.2928924560546875e-05\n", - " loop time 3.170967102050781e-05\n", - " callback_time 0.0\n", - " 0.000095s - ('local_inplace_DiagonalSubtensor', 'TopoOptimizer', 32, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_DiagonalSubtensor\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.030632019042969e-05\n", - " loop time 4.00543212890625e-05\n", - " callback_time 0.0\n", - " 0.000093s - ('local_inplace_sparseblockouter', 'TopoOptimizer', 41, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_sparseblockouter\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.459785461425781e-05\n", - " loop time 3.123283386230469e-05\n", - " callback_time 0.0\n", - " 0.000093s - ('local_batch_norm_inplace_output', 'TopoOptimizer', 27, 44, 44) - 0.000s\n", - " TopoOptimizer local_batch_norm_inplace_output\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.1975250244140625e-05\n", - " loop time 3.170967102050781e-05\n", - " callback_time 0.0\n", - " 0.000092s - ('local_inplace_sparseblockgemv', 'TopoOptimizer', 40, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_sparseblockgemv\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.221366882324219e-05\n", - " loop time 3.0994415283203125e-05\n", - " callback_time 0.0\n", - " 0.000091s - ('local_inplace_sparse_block_outer', 'TopoOptimizer', 39, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_sparse_block_outer\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.340576171875e-05\n", - " loop time 3.0040740966796875e-05\n", - " callback_time 0.0\n", - " 0.000091s - ('local_inplace_gpu_cholesky', 'TopoOptimizer', 33, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_gpu_cholesky\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.054473876953125e-05\n", - " loop time 3.123283386230469e-05\n", - " callback_time 0.0\n", - " 0.000090s - ('local_inplace_gpu_solve', 'TopoOptimizer', 36, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_gpu_solve\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.078315734863281e-05\n", - " loop time 3.170967102050781e-05\n", - " callback_time 0.0\n", - " 0.000090s - ('random_make_inplace', 'TopoOptimizer', 51, 44, 44) - 0.000s\n", - " TopoOptimizer random_make_inplace\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.3882598876953125e-05\n", - " loop time 3.1948089599609375e-05\n", - " callback_time 0.0\n", - " 0.000089s - ('local_inplace_AdvancedIncSubtensor1', 'TopoOptimizer', 31, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_AdvancedIncSubtensor1\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.030632019042969e-05\n", - " loop time 3.147125244140625e-05\n", - " callback_time 0.0\n", - " 0.000089s - ('local_inplace_AdvancedIncSubtensor', 'TopoOptimizer', 30, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_AdvancedIncSubtensor\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.078315734863281e-05\n", - " loop time 3.0994415283203125e-05\n", - " callback_time 0.0\n", - " 0.000089s - ('local_batch_norm_inplace_running_mean', 'TopoOptimizer', 28, 44, 44) - 0.000s\n", - " TopoOptimizer local_batch_norm_inplace_running_mean\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.14984130859375e-05\n", - " loop time 2.9087066650390625e-05\n", - " callback_time 0.0\n", - " 0.000087s - ('local_inplace_gpu_magma_matrix_inverse', 'TopoOptimizer', 35, 44, 44) - 0.000s\n", - " TopoOptimizer local_inplace_gpu_magma_matrix_inverse\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.125999450683594e-05\n", - " loop time 3.123283386230469e-05\n", - " callback_time 0.0\n", - " 0.000087s - ('mrg_random_make_inplace', 'TopoOptimizer', 52, 44, 44) - 0.000s\n", - " TopoOptimizer random_make_inplace_mrg\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.1975250244140625e-05\n", - " loop time 3.0994415283203125e-05\n", - " callback_time 0.0\n", - " 0.000087s - ('local_batch_norm_inplace_running_var', 'TopoOptimizer', 29, 44, 44) - 0.000s\n", - " TopoOptimizer local_batch_norm_inplace_running_var\n", - " nb_node (start, end, changed) (44, 44, 0)\n", - " init io_toposort 5.030632019042969e-05\n", - " loop time 2.8848648071289062e-05\n", - " callback_time 0.0\n", - " 0.000079s - ('gpua_elemwise_fusion', 'FusionOptimizer', 22, 47, 47) - 0.000s\n", - " FusionOptimizer\n", - " nb_iter 1\n", - " nb_replacement 0\n", - " nb_inconsistency_replace 0\n", - " validate_time 0.0\n", - " callback_time 0.0\n", - " time_toposort 6.0558319091796875e-05\n", - " 0.000072s - ('gpua_inplace_opt', 'InplaceElemwiseOptimizer', 47, 44, 44) - 0.000s\n", - " InplaceElemwiseOptimizer \n", - " node_before 44\n", - " nb_call_replace 0\n", - " nb_call_validate 0\n", - " nb_inconsistent 0\n", - " 0.000036s - ('merge1.1', 'MergeOptimizer', 5, 146, 146) - 0.000s\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 1 constant= 1\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " 0.000009s - ('merge3', 'MergeOptimizer', 53, 44, 44) - 0.000s\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 0 constant= 0\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - " 0.000003s - ('merge1.2', 'MergeOptimizer', 8, 69, 69) - 0.000s\n", - " MergeOptimizer\n", - " nb fail= 0 merged= 0 constant= 0\n", - " time replace=0.00 validate=0.00 callback=0.00\n", - "\n", - "Here are tips to potentially make your code run faster\n", - " (if you think of new ones, suggest them on the mailing list).\n", - " Test them first, as they are not guaranteed to always provide a speedup.\n", - " - Try the Aesara flag floatX=float32\n" - ] - } - ], - "source": [ - "trajectory_generator.profile.summary()" + "posterior_trace = az.from_pymc3(posterior[BURNIN:], model=pymc3_model)\n", + "az.plot_trace(posterior_trace);" ] } ], @@ -1364,7 +496,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.5" + "version": "3.9.6" } }, "nbformat": 4,