From a83e9c0281dce92c09621f9fac9581920b776822 Mon Sep 17 00:00:00 2001 From: Divya Tiwari Date: Tue, 6 Feb 2024 09:37:25 +0530 Subject: [PATCH 1/3] draft_PR --- examples/howto/howto_debugging.ipynb | 99 +++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/examples/howto/howto_debugging.ipynb b/examples/howto/howto_debugging.ipynb index 8c6c34bc0..f55b966fc 100644 --- a/examples/howto/howto_debugging.ipynb +++ b/examples/howto/howto_debugging.ipynb @@ -28,7 +28,15 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING (pytensor.tensor.blas): Using NumPy C-API based implementation for BLAS functions.\n" + ] + } + ], "source": [ "import arviz as az\n", "import matplotlib.pyplot as plt\n", @@ -135,6 +143,95 @@ "`Print` reveals the root cause: $(x-y)$ takes a zero value when $x=1, y=1$, causing the `inf` output." ] }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def print_value(var, name=None):\n", + " \"\"\"Print value of variable when it is computed during sampling.\n", + "\n", + " This is likely to affect sampling performance.\n", + " \"\"\"\n", + " if name is None:\n", + " name = var.name\n", + " return Print(name)(var)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x - y = __str__ = [0. 2. 4.]\n" + ] + }, + { + "data": { + "text/plain": [ + "array([ inf, 0.5 , 0.25])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z_with_print = print_value(x-y, 'x - y = ')\n", + "func_with_print = function([x,y],1/z_with_print)\n", + "func_with_print([1,2,3],[1,0,-1])" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'jax'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[9], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mjax\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mjax\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mnumpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnp\u001b[39;00m\n\u001b[0;32m 4\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mprint_op\u001b[39m(x, name\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m):\n", + "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'jax'" + ] + } + ], + "source": [ + "import jax\n", + "import jax.numpy as np\n", + "\n", + "def print_op(x, name=None):\n", + " if name is None:\n", + " name = \"Variable\"\n", + " print(f\"{name}: {x}\")\n", + " return x\n", + "\n", + "# Define a function that uses the print_op\n", + "def my_function(x, y):\n", + " result = x + y\n", + " result = print_op(result, name=\"Result\")\n", + " return result\n", + "\n", + "# Use jax.vmap to vectorize the my_function along the first axis (axis 0)\n", + "vectorized_function = jax.vmap(my_function, in_axes=(0, 0))\n", + "\n", + "# Example usage\n", + "x = np.array([1, 2, 3])\n", + "y = np.array([4, 5, 6])\n", + "\n", + "# Call the vectorized function\n", + "result = vectorized_function(x, y)\n" + ] + }, { "cell_type": "markdown", "metadata": {}, From 117c5ac55ebb58addf23fbaaf67918ce43e5953f Mon Sep 17 00:00:00 2001 From: Divya Tiwari Date: Fri, 9 Feb 2024 22:26:51 +0530 Subject: [PATCH 2/3] updated print_value --- examples/howto/howto_debugging.ipynb | 292 +++++++------------------ examples/howto/howto_debugging.myst.md | 22 +- 2 files changed, 90 insertions(+), 224 deletions(-) diff --git a/examples/howto/howto_debugging.ipynb b/examples/howto/howto_debugging.ipynb index f55b966fc..be2a39ccc 100644 --- a/examples/howto/howto_debugging.ipynb +++ b/examples/howto/howto_debugging.ipynb @@ -21,7 +21,7 @@ "## Introduction\n", "There are various levels on which to debug a model. One of the simplest is to just print out the values that different variables are taking on.\n", "\n", - "Because `PyMC` uses `PyTensor` expressions to build the model, and not functions, there is no way to place a `print` statement into a likelihood function. Instead, you can use the {class}`pytensor.printing.Print` class to print intermediate values." + "Because `PyMC` uses `PyTensor` expressions to build the model, and not functions, there is no way to place a `print` statement into a likelihood function. Instead, you can use the {class}`pytensor.printing.Print` class to print intermediate values. In PyMC we have `print_values` helper function to print intermediate values. " ] }, { @@ -62,7 +62,7 @@ "metadata": {}, "source": [ "### How to print intermediate values of `PyTensor` functions\n", - "Since `PyTensor` functions are compiled to C, you have to use `pytensor.printing.Print` class to print intermediate values (imported below as `Print`). Python `print` function will not work. Below is a simple example of using `Print`. For more information, see {ref}`Debugging PyTensor `." + "Since `PyTensor` functions are compiled to C, you have to use `pymc.model.core.print_value` function to print intermediate values. Python `print` function will not work. Below is a simple example of using `print_value`. For more information, see {ref}`Debugging PyTensor `." ] }, { @@ -73,8 +73,8 @@ "source": [ "import pytensor.tensor as pt\n", "\n", - "from pytensor import function\n", - "from pytensor.printing import Print" + "from pymc.model.core import print_value\n", + "from pytensor import function" ] }, { @@ -104,7 +104,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `Print`. `Print` class simply passes along its caller but prints out its value along a user-define message:" + "To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `print_value`. `print_value` is based on the `Print` class that simply passes along its caller but prints out its value along a user-define message:" ] }, { @@ -131,7 +131,7 @@ } ], "source": [ - "z_with_print = Print(\"x - y = \")(x - y)\n", + "z_with_print = print_value(x - y, \"x - y = \")\n", "func_with_print = function([x, y], 1 / z_with_print)\n", "func_with_print([1, 2, 3], [1, 0, -1])" ] @@ -140,105 +140,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`Print` reveals the root cause: $(x-y)$ takes a zero value when $x=1, y=1$, causing the `inf` output." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def print_value(var, name=None):\n", - " \"\"\"Print value of variable when it is computed during sampling.\n", - "\n", - " This is likely to affect sampling performance.\n", - " \"\"\"\n", - " if name is None:\n", - " name = var.name\n", - " return Print(name)(var)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "x - y = __str__ = [0. 2. 4.]\n" - ] - }, - { - "data": { - "text/plain": [ - "array([ inf, 0.5 , 0.25])" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "z_with_print = print_value(x-y, 'x - y = ')\n", - "func_with_print = function([x,y],1/z_with_print)\n", - "func_with_print([1,2,3],[1,0,-1])" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'jax'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[9], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mjax\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mjax\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mnumpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnp\u001b[39;00m\n\u001b[0;32m 4\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mprint_op\u001b[39m(x, name\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m):\n", - "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'jax'" - ] - } - ], - "source": [ - "import jax\n", - "import jax.numpy as np\n", - "\n", - "def print_op(x, name=None):\n", - " if name is None:\n", - " name = \"Variable\"\n", - " print(f\"{name}: {x}\")\n", - " return x\n", - "\n", - "# Define a function that uses the print_op\n", - "def my_function(x, y):\n", - " result = x + y\n", - " result = print_op(result, name=\"Result\")\n", - " return result\n", - "\n", - "# Use jax.vmap to vectorize the my_function along the first axis (axis 0)\n", - "vectorized_function = jax.vmap(my_function, in_axes=(0, 0))\n", - "\n", - "# Example usage\n", - "x = np.array([1, 2, 3])\n", - "y = np.array([4, 5, 6])\n", - "\n", - "# Call the vectorized function\n", - "result = vectorized_function(x, y)\n" + "`print_value` reveals the root cause: $(x-y)$ takes a zero value when $x=1, y=1$, causing the `inf` output." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### How to capture `Print` output for further analysis\n", + "### How to capture `print_values` output for further analysis\n", "\n", - "When we expect many rows of output from `Print`, it can be desirable to redirect the output to a string buffer and access the values later on (thanks to **Lindley Lentati** for inspiring this example). Here is a toy example using Python `print` function:" + "When we expect many rows of output from `print_values`, it can be desirable to redirect the output to a string buffer and access the values later on (thanks to **Lindley Lentati** for inspiring this example). Here is a toy example using Python `print` function:" ] }, { @@ -300,8 +211,8 @@ " sd = pm.Normal(\"sd\", mu=0, sigma=1)\n", "\n", " # setting out printing for mu and sd\n", - " mu_print = Print(\"mu\")(mu)\n", - " sd_print = Print(\"sd\")(sd)\n", + " mu_print = print_value(mu)\n", + " sd_print = print_value(sd)\n", "\n", " # likelihood\n", " obs = pm.Normal(\"obs\", mu=mu_print, sigma=sd_print, observed=x)" @@ -315,57 +226,62 @@ { "data": { "image/svg+xml": [ - "\r\n", - "\r\n", - "\r\n", - "\r\n", - "\r\n", - "\r\n", - "%3\r\n", - "\r\n", - "cluster100\r\n", - "\r\n", - "100\r\n", - "\r\n", - "\r\n", - "sd\r\n", - "\r\n", - "sd\r\n", - "~\r\n", - "Normal\r\n", - "\r\n", - "\r\n", - "obs\r\n", - "\r\n", - "obs\r\n", - "~\r\n", - "Normal\r\n", - "\r\n", - "\r\n", - "sd->obs\r\n", - "\r\n", - "\r\n", - "\r\n", - "\r\n", - "mu\r\n", - "\r\n", - "mu\r\n", - "~\r\n", - "Normal\r\n", - "\r\n", - "\r\n", - "mu->obs\r\n", - "\r\n", - "\r\n", - "\r\n", - "\r\n", - "\r\n" + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "cluster100\n", + "\n", + "100\n", + "\n", + "\n", + "\n", + "sd\n", + "\n", + "sd\n", + "~\n", + "Normal\n", + "\n", + "\n", + "\n", + "obs\n", + "\n", + "obs\n", + "~\n", + "Normal\n", + "\n", + "\n", + "\n", + "sd->obs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "mu\n", + "\n", + "mu\n", + "~\n", + "Normal\n", + "\n", + "\n", + "\n", + "mu->obs\n", + "\n", + "\n", + "\n", + "\n", + "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 8, @@ -383,31 +299,14 @@ "metadata": {}, "outputs": [ { - "name": "stderr", - "output_type": "stream", - "text": [ - "Only 5 samples in chain.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sd __str__ = 0.0\n", - "mu __str__ = 0.0\n" - ] - }, - { - "ename": "SamplingError", - "evalue": "Initial evaluation of model at starting point failed!\nStarting values:\n{'mu': array(0.), 'sd': array(0.)}\n\nInitial evaluation results:\n{'mu': -0.92, 'sd': -0.92, 'obs': -inf}", + "ename": "TypeError", + "evalue": "sample() takes from 0 to 1 positional arguments but 2 positional arguments (and 4 keyword-only arguments) were given", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mSamplingError\u001b[0m Traceback (most recent call last)", - "Input \u001b[1;32mIn [9]\u001b[0m, in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m model:\n\u001b[0;32m 2\u001b[0m step \u001b[38;5;241m=\u001b[39m pm\u001b[38;5;241m.\u001b[39mMetropolis()\n\u001b[1;32m----> 3\u001b[0m trace \u001b[38;5;241m=\u001b[39m \u001b[43mpm\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msample\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m5\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtune\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mchains\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogressbar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrandom_seed\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mRANDOM_SEED\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32mc:\\users\\igork\\pycharmprojects\\pymc\\pymc\\sampling.py:558\u001b[0m, in \u001b[0;36msample\u001b[1;34m(draws, step, init, n_init, initvals, trace, chain_idx, chains, cores, tune, progressbar, model, random_seed, discard_tuned_samples, compute_convergence_checks, callback, jitter_max_retries, return_inferencedata, idata_kwargs, mp_ctx, **kwargs)\u001b[0m\n\u001b[0;32m 556\u001b[0m \u001b[38;5;66;03m# One final check that shapes and logps at the starting points are okay.\u001b[39;00m\n\u001b[0;32m 557\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m ip \u001b[38;5;129;01min\u001b[39;00m initial_points:\n\u001b[1;32m--> 558\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcheck_start_vals\u001b[49m\u001b[43m(\u001b[49m\u001b[43mip\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 559\u001b[0m _check_start_shape(model, ip)\n\u001b[0;32m 561\u001b[0m sample_args \u001b[38;5;241m=\u001b[39m {\n\u001b[0;32m 562\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdraws\u001b[39m\u001b[38;5;124m\"\u001b[39m: draws,\n\u001b[0;32m 563\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstep\u001b[39m\u001b[38;5;124m\"\u001b[39m: step,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 573\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdiscard_tuned_samples\u001b[39m\u001b[38;5;124m\"\u001b[39m: discard_tuned_samples,\n\u001b[0;32m 574\u001b[0m }\n", - "File \u001b[1;32mc:\\users\\igork\\pycharmprojects\\pymc\\pymc\\model.py:1794\u001b[0m, in \u001b[0;36mModel.check_start_vals\u001b[1;34m(self, start)\u001b[0m\n\u001b[0;32m 1791\u001b[0m initial_eval \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpoint_logps(point\u001b[38;5;241m=\u001b[39melem)\n\u001b[0;32m 1793\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mall\u001b[39m(np\u001b[38;5;241m.\u001b[39misfinite(v) \u001b[38;5;28;01mfor\u001b[39;00m v \u001b[38;5;129;01min\u001b[39;00m initial_eval\u001b[38;5;241m.\u001b[39mvalues()):\n\u001b[1;32m-> 1794\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m SamplingError(\n\u001b[0;32m 1795\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInitial evaluation of model at starting point failed!\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1796\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mStarting values:\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00melem\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1797\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInitial evaluation results:\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00minitial_eval\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1798\u001b[0m )\n", - "\u001b[1;31mSamplingError\u001b[0m: Initial evaluation of model at starting point failed!\nStarting values:\n{'mu': array(0.), 'sd': array(0.)}\n\nInitial evaluation results:\n{'mu': -0.92, 'sd': -0.92, 'obs': -inf}" + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[9], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m model:\n\u001b[0;32m 2\u001b[0m step \u001b[38;5;241m=\u001b[39m pm\u001b[38;5;241m.\u001b[39mMetropolis()\n\u001b[1;32m----> 3\u001b[0m trace \u001b[38;5;241m=\u001b[39m \u001b[43mpm\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msample\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m5\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtune\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mchains\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogressbar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrandom_seed\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mRANDOM_SEED\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[1;31mTypeError\u001b[0m: sample() takes from 0 to 1 positional arguments but 2 positional arguments (and 4 keyword-only arguments) were given" ] } ], @@ -447,11 +346,8 @@ "Initializing NUTS using jitter+adapt_diag...\n", "Sequential sampling (1 chains in 1 job)\n", "NUTS: [mu, a, b]\n", - "Sampling 1 chain for 0 tune and 10 draw iterations (0 + 10 draws total) took 1 seconds.\n", - "The chain contains only diverging samples. The model is probably misspecified.\n", - "The acceptance probability does not match the target. It is 0, but should be close to 0.8. Try to increase the number of tuning steps.\n", - "C:\\Users\\igork\\AppData\\Local\\Temp\\ipykernel_14804\\1992602661.py:15: UserWarning: The number of samples is too small to check convergence reliably.\n", - " trace = pm.sample(draws=10, tune=0, chains=1, progressbar=False, random_seed=RANDOM_SEED)\n" + "Sampling 1 chain for 0 tune and 10 draw iterations (0 + 10 draws total) took 0 seconds.\n", + "The number of samples is too small to check convergence reliably.\n" ] } ], @@ -466,7 +362,7 @@ " mu = pm.Normal(\"mu\", mu=0, sigma=10)\n", " a = pm.Normal(\"a\", mu=0, sigma=10, initval=0.1)\n", " b = pm.Normal(\"b\", mu=0, sigma=10, initval=0.1)\n", - " sd_print = Print(\"Delta\")(a / b)\n", + " sd_print = print_value(a / b, name=\"Delta\")\n", " obs = pm.Normal(\"obs\", mu=mu, sigma=sd_print, observed=y)\n", "\n", " # limiting number of samples and chains to simplify output\n", @@ -486,7 +382,7 @@ { "data": { "text/plain": [ - "'Delta __str__ = -85.74093608165128\\nDelta __str__ = -9.182002291671038\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.315734173890055\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.312485782438435\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.314669656412736\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.31581619157038\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.315114719133609\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.31511040479387\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.314077394936474\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.313673830463395\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.31561025339713\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.31526569370057\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\n'" + "'Delta __str__ = -85.74093608165128\\nDelta __str__ = -9.182002291671038\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.315734173890057\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.312485782438435\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.314669656412734\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.31581619157038\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.31511471913361\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.315110404793872\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.314077394936474\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.313673830463394\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.315610253397129\\nDelta __str__ = 0.10737295473067673\\nDelta __str__ = -9.315265693700571\\n'" ] }, "execution_count": 11, @@ -540,10 +436,7 @@ " 0.10737295, -9.31466966, 0.10737295, -9.31581619,\n", " 0.10737295, -9.31511472, 0.10737295, -9.3151104 ,\n", " 0.10737295, -9.31407739, 0.10737295, -9.31367383,\n", - " 0.10737295, -9.31561025, 0.10737295, -9.31526569,\n", - " 0.10737295, 0.10737295, 0.10737295, 0.10737295,\n", - " 0.10737295, 0.10737295, 0.10737295, 0.10737295,\n", - " 0.10737295, 0.10737295])" + " 0.10737295, -9.31561025, 0.10737295, -9.31526569])" ] }, "execution_count": 13, @@ -570,7 +463,7 @@ { "data": { "text/plain": [ - "(34,)" + "(24,)" ] }, "execution_count": 14, @@ -601,36 +494,9 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Last updated: Tue Aug 02 2022\n", - "\n", - "Python implementation: CPython\n", - "Python version : 3.10.5\n", - "IPython version : 8.4.0\n", - "\n", - "pytensor: 2.7.5\n", - "xarray: 2022.3.0\n", - "\n", - "matplotlib: 3.5.2\n", - "pytensor : 2.7.5\n", - "numpy : 1.23.0\n", - "arviz : 0.12.1\n", - "sys : 3.10.5 | packaged by conda-forge | (main, Jun 14 2022, 06:57:19) [MSC v.1929 64 bit (AMD64)]\n", - "re : 2.2.1\n", - "pandas : 1.4.3\n", - "pymc : 4.1.2\n", - "\n", - "Watermark: 2.3.1\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "%load_ext watermark\n", "%watermark -n -u -v -iv -w -p pytensor,xarray" @@ -661,7 +527,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/examples/howto/howto_debugging.myst.md b/examples/howto/howto_debugging.myst.md index 8ca1d9430..f3a8c69b3 100644 --- a/examples/howto/howto_debugging.myst.md +++ b/examples/howto/howto_debugging.myst.md @@ -24,7 +24,7 @@ kernelspec: ## Introduction There are various levels on which to debug a model. One of the simplest is to just print out the values that different variables are taking on. -Because `PyMC` uses `PyTensor` expressions to build the model, and not functions, there is no way to place a `print` statement into a likelihood function. Instead, you can use the {class}`pytensor.printing.Print` class to print intermediate values. +Because `PyMC` uses `PyTensor` expressions to build the model, and not functions, there is no way to place a `print` statement into a likelihood function. Instead, you can use the {class}`pytensor.printing.Print` class to print intermediate values. In PyMC we have `print_values` helper function to print intermediate values. ```{code-cell} ipython3 import arviz as az @@ -42,13 +42,13 @@ RANDOM_SEED = 8927 ``` ### How to print intermediate values of `PyTensor` functions -Since `PyTensor` functions are compiled to C, you have to use `pytensor.printing.Print` class to print intermediate values (imported below as `Print`). Python `print` function will not work. Below is a simple example of using `Print`. For more information, see {ref}`Debugging PyTensor `. +Since `PyTensor` functions are compiled to C, you have to use `pymc.model.core.print_value` function to print intermediate values. Python `print` function will not work. Below is a simple example of using `print_value`. For more information, see {ref}`Debugging PyTensor `. ```{code-cell} ipython3 import pytensor.tensor as pt +from pymc.model.core import print_value from pytensor import function -from pytensor.printing import Print ``` ```{code-cell} ipython3 @@ -58,21 +58,21 @@ func = function([x, y], 1 / (x - y)) func([1, 2, 3], [1, 0, -1]) ``` -To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `Print`. `Print` class simply passes along its caller but prints out its value along a user-define message: +To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `print_value`. `print_value` is based on the `Print` class that simply passes along its caller but prints out its value along a user-define message: ```{code-cell} ipython3 -z_with_print = Print("x - y = ")(x - y) +z_with_print = print_value(x - y, "x - y = ") func_with_print = function([x, y], 1 / z_with_print) func_with_print([1, 2, 3], [1, 0, -1]) ``` -`Print` reveals the root cause: $(x-y)$ takes a zero value when $x=1, y=1$, causing the `inf` output. +`print_value` reveals the root cause: $(x-y)$ takes a zero value when $x=1, y=1$, causing the `inf` output. +++ -### How to capture `Print` output for further analysis +### How to capture `print_values` output for further analysis -When we expect many rows of output from `Print`, it can be desirable to redirect the output to a string buffer and access the values later on (thanks to **Lindley Lentati** for inspiring this example). Here is a toy example using Python `print` function: +When we expect many rows of output from `print_values`, it can be desirable to redirect the output to a string buffer and access the values later on (thanks to **Lindley Lentati** for inspiring this example). Here is a toy example using Python `print` function: ```{code-cell} ipython3 import sys @@ -102,8 +102,8 @@ with pm.Model() as model: sd = pm.Normal("sd", mu=0, sigma=1) # setting out printing for mu and sd - mu_print = Print("mu")(mu) - sd_print = Print("sd")(sd) + mu_print = print_value(mu) + sd_print = print_value(sd) # likelihood obs = pm.Normal("obs", mu=mu_print, sigma=sd_print, observed=x) @@ -136,7 +136,7 @@ with pm.Model() as model: mu = pm.Normal("mu", mu=0, sigma=10) a = pm.Normal("a", mu=0, sigma=10, initval=0.1) b = pm.Normal("b", mu=0, sigma=10, initval=0.1) - sd_print = Print("Delta")(a / b) + sd_print = print_value(a / b, name="Delta") obs = pm.Normal("obs", mu=mu, sigma=sd_print, observed=y) # limiting number of samples and chains to simplify output From 2561af06f79d785e6dc82419aa6962ed2a496bd4 Mon Sep 17 00:00:00 2001 From: Divya Tiwari Date: Mon, 12 Feb 2024 20:36:11 +0530 Subject: [PATCH 3/3] importing print_value from pymc.pytensorf --- examples/howto/howto_debugging.ipynb | 39 ++++++++++++++++++++++---- examples/howto/howto_debugging.myst.md | 6 ++-- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/examples/howto/howto_debugging.ipynb b/examples/howto/howto_debugging.ipynb index be2a39ccc..b18f23f37 100644 --- a/examples/howto/howto_debugging.ipynb +++ b/examples/howto/howto_debugging.ipynb @@ -62,7 +62,7 @@ "metadata": {}, "source": [ "### How to print intermediate values of `PyTensor` functions\n", - "Since `PyTensor` functions are compiled to C, you have to use `pymc.model.core.print_value` function to print intermediate values. Python `print` function will not work. Below is a simple example of using `print_value`. For more information, see {ref}`Debugging PyTensor `." + "Since `PyTensor` functions are compiled to C, you have to use `pymc.pytensorf.print_value` function to print intermediate values. Python `print` function will not work. Below is a simple example of using `print_value`. For more information, see {ref}`Debugging PyTensor `." ] }, { @@ -73,7 +73,7 @@ "source": [ "import pytensor.tensor as pt\n", "\n", - "from pymc.model.core import print_value\n", + "from pymc.pytensorf import print_value\n", "from pytensor import function" ] }, @@ -104,7 +104,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `print_value`. `print_value` is based on the `Print` class that simply passes along its caller but prints out its value along a user-define message:" + "To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `print_value`. `print_value` is based on the {class}`pytensor.prinitng.Print` class that simply passes along its caller but prints out its value along a user-define message:" ] }, { @@ -281,7 +281,7 @@ "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 8, @@ -494,9 +494,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Last updated: Mon Feb 12 2024\n", + "\n", + "Python implementation: CPython\n", + "Python version : 3.11.7\n", + "IPython version : 8.21.0\n", + "\n", + "pytensor: 2.18.6\n", + "xarray : 2024.1.1\n", + "\n", + "pandas : 2.2.0\n", + "re : 2.2.1\n", + "arviz : 0.17.0\n", + "sys : 3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:27:59) [MSC v.1937 64 bit (AMD64)]\n", + "pymc : 0+untagged.9733.g94020c9.dirty\n", + "pytensor : 2.18.6\n", + "matplotlib: 3.8.2\n", + "numpy : 1.26.4\n", + "\n", + "Watermark: 2.4.3\n", + "\n" + ] + } + ], "source": [ "%load_ext watermark\n", "%watermark -n -u -v -iv -w -p pytensor,xarray" diff --git a/examples/howto/howto_debugging.myst.md b/examples/howto/howto_debugging.myst.md index f3a8c69b3..7e393c80a 100644 --- a/examples/howto/howto_debugging.myst.md +++ b/examples/howto/howto_debugging.myst.md @@ -42,12 +42,12 @@ RANDOM_SEED = 8927 ``` ### How to print intermediate values of `PyTensor` functions -Since `PyTensor` functions are compiled to C, you have to use `pymc.model.core.print_value` function to print intermediate values. Python `print` function will not work. Below is a simple example of using `print_value`. For more information, see {ref}`Debugging PyTensor `. +Since `PyTensor` functions are compiled to C, you have to use `pymc.pytensorf.print_value` function to print intermediate values. Python `print` function will not work. Below is a simple example of using `print_value`. For more information, see {ref}`Debugging PyTensor `. ```{code-cell} ipython3 import pytensor.tensor as pt -from pymc.model.core import print_value +from pymc.pytensorf import print_value from pytensor import function ``` @@ -58,7 +58,7 @@ func = function([x, y], 1 / (x - y)) func([1, 2, 3], [1, 0, -1]) ``` -To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `print_value`. `print_value` is based on the `Print` class that simply passes along its caller but prints out its value along a user-define message: +To see what causes the `inf` value in the output, we can print intermediate values of $(x-y)$ using `print_value`. `print_value` is based on the {class}`pytensor.prinitng.Print` class that simply passes along its caller but prints out its value along a user-define message: ```{code-cell} ipython3 z_with_print = print_value(x - y, "x - y = ")