diff --git a/examples/howto/howto_debugging.ipynb b/examples/howto/howto_debugging.ipynb index 8c6c34bc0..b18f23f37 100644 --- a/examples/howto/howto_debugging.ipynb +++ b/examples/howto/howto_debugging.ipynb @@ -21,14 +21,22 @@ "## 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. " ] }, { "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", @@ -54,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.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 `." ] }, { @@ -65,8 +73,8 @@ "source": [ "import pytensor.tensor as pt\n", "\n", - "from pytensor import function\n", - "from pytensor.printing import Print" + "from pymc.pytensorf import print_value\n", + "from pytensor import function" ] }, { @@ -96,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 {class}`pytensor.prinitng.Print` class that simply passes along its caller but prints out its value along a user-define message:" ] }, { @@ -123,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])" ] @@ -132,16 +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." + "`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:" ] }, { @@ -203,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)" @@ -218,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, @@ -286,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" ] } ], @@ -350,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" ] } ], @@ -369,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", @@ -389,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, @@ -443,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, @@ -473,7 +463,7 @@ { "data": { "text/plain": [ - "(34,)" + "(24,)" ] }, "execution_count": 14, @@ -511,25 +501,25 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last updated: Tue Aug 02 2022\n", + "Last updated: Mon Feb 12 2024\n", "\n", "Python implementation: CPython\n", - "Python version : 3.10.5\n", - "IPython version : 8.4.0\n", + "Python version : 3.11.7\n", + "IPython version : 8.21.0\n", "\n", - "pytensor: 2.7.5\n", - "xarray: 2022.3.0\n", + "pytensor: 2.18.6\n", + "xarray : 2024.1.1\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", + "pandas : 2.2.0\n", "re : 2.2.1\n", - "pandas : 1.4.3\n", - "pymc : 4.1.2\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.3.1\n", + "Watermark: 2.4.3\n", "\n" ] } @@ -564,7 +554,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..7e393c80a 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.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.pytensorf 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 {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("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