{"id":38681987,"url":"https://github.com/malmgrek/gammy","last_synced_at":"2026-01-17T10:16:02.206Z","repository":{"id":57433014,"uuid":"233842911","full_name":"malmgrek/gammy","owner":"malmgrek","description":":octopus: Generalized additive models in Python with a Bayesian twist","archived":false,"fork":false,"pushed_at":"2025-08-20T10:50:20.000Z","size":7131,"stargazers_count":78,"open_issues_count":2,"forks_count":6,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2025-09-22T05:39:57.494Z","etag":null,"topics":["bayesian-inference","machine-learning","mathematical-modelling","statistics"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/malmgrek.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-01-14T13:03:15.000Z","updated_at":"2025-08-20T10:49:48.000Z","dependencies_parsed_at":"2023-12-25T21:40:55.024Z","dependency_job_id":"7fa9b385-ef75-4b25-8add-b30910c5a646","html_url":"https://github.com/malmgrek/gammy","commit_stats":{"total_commits":161,"total_committers":3,"mean_commits":"53.666666666666664","dds":0.07453416149068326,"last_synced_commit":"39c24700739c3d0af15af10d2d02b67cf577d6e8"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/malmgrek/gammy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/malmgrek%2Fgammy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/malmgrek%2Fgammy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/malmgrek%2Fgammy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/malmgrek%2Fgammy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/malmgrek","download_url":"https://codeload.github.com/malmgrek/gammy/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/malmgrek%2Fgammy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28506000,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T06:57:29.758Z","status":"ssl_error","status_checked_at":"2026-01-17T06:56:03.931Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bayesian-inference","machine-learning","mathematical-modelling","statistics"],"created_at":"2026-01-17T10:15:59.182Z","updated_at":"2026-01-17T10:16:02.197Z","avatar_url":"https://github.com/malmgrek.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gammy – Generalized additive models in Python with a Bayesian twist\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/cover.png)\n\nA Generalized additive model is a predictive mathematical model defined as a sum\nof terms that are calibrated (fitted) with observation data.\n\nGeneralized additive models form a surprisingly general framework for building\nmodels for both production software and scientific research. This Python package\noffers tools for building the model terms as decompositions of various basis\nfunctions. It is possible to model the terms e.g. as Gaussian processes (with\nreduced dimensionality) of various kernels, as piecewise linear functions, and\nas B-splines, among others. Of course, very simple terms like lines and\nconstants are also supported (these are just very simple basis functions).\n\nThe uncertainty in the weight parameter distributions is modeled using Bayesian\nstatistical analysis with the help of the superb package\n[BayesPy](http://www.bayespy.org/index.html). Alternatively, it is possible to\nfit models using just NumPy.\n\n\u003c!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc --\u003e\n**Table of Contents**\n\n- [Installation](#installation)\n- [Examples](#examples)\n    - [Polynomial regression on 'roids](#polynomial-regression-on-roids)\n        - [Predicting with model](#predicting-with-model)\n        - [Plotting results](#plotting-results)\n        - [Saving model on hard disk](#saving-model-on-hard-disk)\n    - [Gaussian process regression](#gaussian-process-regression)\n        - [More covariance kernels](#more-covariance-kernels)\n        - [Defining custom kernels](#defining-custom-kernels)\n    - [Spline regression](#spline-regression)\n    - [Non-linear manifold regression](#non-linear-manifold-regression)\n- [Testing](#testing)\n- [Package documentation](#package-documentation)\n\n\u003c!-- markdown-toc end --\u003e\n\n## Installation\n\nThe package is found in PyPi.\n\n``` shell\npip install gammy\n```\n\n## Examples\n\nIn this overview, we demonstrate the package's most important features through\ncommon usage examples.\n\n### Polynomial regression on 'roids\n\nA typical simple (but sometimes non-trivial) modeling task is to estimate an\nunknown function from noisy data. First we import the bare minimum dependencies to be used in the below examples:\n\n```python\n\u003e\u003e\u003e import numpy as np\n\n\u003e\u003e\u003e import gammy\n\u003e\u003e\u003e from gammy.models.bayespy import GAM\n\n\u003e\u003e\u003e gammy.__version__\n'0.5.6'\n\n```\n\nLet's simulate a dataset:\n\n```python\n\u003e\u003e\u003e np.random.seed(42)\n\n\u003e\u003e\u003e n = 30\n\u003e\u003e\u003e input_data = 10 * np.random.rand(n)\n\u003e\u003e\u003e y = 5 * input_data + 2.0 * input_data ** 2 + 7 + 10 * np.random.randn(n)\n\n```\n\nThe object `x` is just a convenience tool for defining input data maps\nas if they were just Numpy arrays:\n\n```python\n\u003e\u003e\u003e from gammy.arraymapper import x\n\n```\n\nDefine and fit the model:\n\n```python\n\u003e\u003e\u003e a = gammy.formulae.Scalar(prior=(0, 1e-6))\n\u003e\u003e\u003e b = gammy.formulae.Scalar(prior=(0, 1e-6))\n\u003e\u003e\u003e bias = gammy.formulae.Scalar(prior=(0, 1e-6))\n\u003e\u003e\u003e formula = a * x + b * x ** 2 + bias\n\u003e\u003e\u003e model = GAM(formula).fit(input_data, y)\n\n```\n\nThe model attribute `model.theta` characterizes the Gaussian posterior\ndistribution of the model parameters vector.\n\n``` python\n\u003e\u003e\u003e model.mean_theta\n[array([3.20130444]), array([2.0420961]), array([11.93437195])]\n\n```\n\nVariance of additive zero-mean normally distributed noise is estimated\nautomagically:\n\n``` python\n\u003e\u003e\u003e round(model.inv_mean_tau, 8)\n74.51660744\n\n```\n\n#### Predicting with model\n\n```python\n\u003e\u003e\u003e model.predict(input_data[:2])\narray([ 52.57112684, 226.9460579 ])\n\n```\n\nPredictions with uncertainty, that is, posterior predictive mean and variance\ncan be calculated as follows:\n\n```python\n\u003e\u003e\u003e model.predict_variance(input_data[:2])\n(array([ 52.57112684, 226.9460579 ]), array([79.35827362, 95.16358131]))\n\n```\n\n#### Plotting results\n\n```python\n\u003e\u003e\u003e fig = gammy.plot.validation_plot(\n...     model,\n...     input_data,\n...     y,\n...     grid_limits=[0, 10],\n...     input_maps=[x, x, x],\n...     titles=[\"a\", \"b\", \"bias\"]\n... )\n\n```\n\nThe grey band in the top figure is two times the prediction standard deviation\nand, in the partial residual plots, two times the respective marginal posterior\nstandard deviation.\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/polynomial-validation.png)\n\nIt is also possible to plot the estimated Γ-distribution of the noise precision\n(inverse variance) as well as the 1-D Normal distributions of each individual\nmodel parameter.\n\nPlot (prior or posterior) probability density functions of all model parameters:\n\n```python\n\u003e\u003e\u003e fig = gammy.plot.gaussian1d_density_plot(model)\n\n```\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/polynomial-density.png)\n\n#### Saving model on hard disk\n\nSaving:\n\n\u003c!-- NOTE: To skip doctests, one \u003e has been removed --\u003e\n```python\n\u003e\u003e model.save(\"/home/foobar/test.hdf5\")\n```\n\nLoading:\n\n\u003c!-- NOTE: To skip doctests, one \u003e has been removed --\u003e\n```python\n\u003e\u003e model = GAM(formula).load(\"/home/foobar/test.hdf5\")\n```\n\n### Gaussian process regression\n\nCreate fake dataset:\n\n```python\n\u003e\u003e\u003e n = 50\n\u003e\u003e\u003e input_data = np.vstack((2 * np.pi * np.random.rand(n), np.random.rand(n))).T\n\u003e\u003e\u003e y = (\n...     np.abs(np.cos(input_data[:, 0])) * input_data[:, 1] +\n...     1 + 0.1 * np.random.randn(n)\n... )\n\n```\n\nDefine model:\n\n``` python\n\u003e\u003e\u003e a = gammy.formulae.ExpSineSquared1d(\n...     np.arange(0, 2 * np.pi, 0.1),\n...     corrlen=1.0,\n...     sigma=1.0,\n...     period=2 * np.pi,\n...     energy=0.99\n... )\n\u003e\u003e\u003e bias = gammy.Scalar(prior=(0, 1e-6))\n\u003e\u003e\u003e formula = a(x[:, 0]) * x[:, 1] + bias\n\u003e\u003e\u003e model = gammy.models.bayespy.GAM(formula).fit(input_data, y)\n\n\u003e\u003e\u003e round(model.mean_theta[0][0], 8)\n0.8343458\n\n```\n\nPlot predictions and partial residuals:\n\n``` python\n\u003e\u003e\u003e fig = gammy.plot.validation_plot(\n...     model,\n...     input_data,\n...     y,\n...     grid_limits=[[0, 2 * np.pi], [0, 1]],\n...     input_maps=[x[:, 0:2], x[:, 1]],\n...     titles=[\"Surface estimate\", \"intercept\"]\n... )\n\n```\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/gp-simple-validation.png)\n\nPlot parameter probability density functions\n\n``` python\n\u003e\u003e\u003e fig = gammy.plot.gaussian1d_density_plot(model)\n\n```\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/gp-simple-density.png)\n\n#### More covariance kernels\n\nThe package contains covariance functions for many well-known options such as\nthe _Exponential squared_, _Periodic exponential squared_, _Rational quadratic_,\nand the _Ornstein-Uhlenbeck_ kernels. Please see the documentation section [More\non Gaussian Process\nkernels](https://malmgrek.github.io/gammy/features.html#more-on-gaussian-process-kernels)\nfor a gallery of kernels.\n\n#### Defining custom kernels\n\nPlease read the documentation section: [Customize Gaussian Process\nkernels](https://malmgrek.github.io/gammy/features.html#customize-gaussian-process-kernels)\n\n### Spline regression\n\nConstructing B-Spline based 1-D basis functions is also supported. Let's define\ndummy data:\n\n```python\n\u003e\u003e\u003e n = 30\n\u003e\u003e\u003e input_data = 10 * np.random.rand(n)\n\u003e\u003e\u003e y = 2.0 * input_data ** 2 + 7 + 10 * np.random.randn(n)\n\n```\n\nDefine model:\n\n``` python\n\u003e\u003e\u003e grid = np.arange(0, 11, 2.0)\n\u003e\u003e\u003e order = 2\n\u003e\u003e\u003e N = len(grid) + order - 2\n\u003e\u003e\u003e sigma = 10 ** 2\n\u003e\u003e\u003e formula = gammy.BSpline1d(\n...     grid,\n...     order=order,\n...     prior=(np.zeros(N), np.identity(N) / sigma),\n...     extrapolate=True\n... )(x)\n\u003e\u003e\u003e model = gammy.models.bayespy.GAM(formula).fit(input_data, y)\n\n\u003e\u003e\u003e round(model.mean_theta[0][0], 8)\n-49.00019115\n\n```\n\nPlot validation figure:\n\n``` python\n\u003e\u003e\u003e fig = gammy.plot.validation_plot(\n...     model,\n...     input_data,\n...     y,\n...     grid_limits=[-2, 12],\n...     input_maps=[x],\n...     titles=[\"a\"]\n... )\n\n```\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/spline-validation.png)\n\nPlot parameter probability densities:\n\n ``` python\n\u003e\u003e\u003e fig = gammy.plot.gaussian1d_density_plot(model)\n\n ```\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/spline-density.png)\n\n### Non-linear manifold regression\n\nIn this example we try estimating the bivariate \"MATLAB function\" using a\nGaussian process model with Kronecker tensor structure (see e.g.\n[PyMC3](https://docs.pymc.io/en/v3/pymc-examples/examples/gaussian_processes/GP-Kron.html)). The main point in the\nbelow example is that it is quite straightforward to build models that can learn\narbitrary 2D-surfaces.\n\nLet us first create some artificial data using the MATLAB function!\n\n```python\n\u003e\u003e\u003e n = 100\n\u003e\u003e\u003e input_data = np.vstack((\n...     6 * np.random.rand(n) - 3, 6 * np.random.rand(n) - 3\n... )).T\n\u003e\u003e\u003e y = (\n...     gammy.utils.peaks(input_data[:, 0], input_data[:, 1]) +\n...     4 + 0.3 * np.random.randn(n)\n... )\n\n```\n\nThere is support for forming two-dimensional basis functions given two\none-dimensional formulas. The new combined basis is essentially the outer\nproduct of the given bases. The underlying weight prior distribution priors and\ncovariances are constructed using the Kronecker product.\n\n```python\n\u003e\u003e\u003e a = gammy.ExpSquared1d(\n...     np.arange(-3, 3, 0.1),\n...     corrlen=0.5,\n...     sigma=4.0,\n...     energy=0.99\n... )(x[:, 0])  # NOTE: Input map is defined here!\n\u003e\u003e\u003e b = gammy.ExpSquared1d(\n...     np.arange(-3, 3, 0.1),\n...     corrlen=0.5,\n...     sigma=4.0,\n...     energy=0.99\n... )(x[:, 1]) # NOTE: Input map is defined here!\n\u003e\u003e\u003e A = gammy.formulae.Kron(a, b)\n\u003e\u003e\u003e bias = gammy.formulae.Scalar(prior=(0, 1e-6))\n\u003e\u003e\u003e formula = A + bias\n\u003e\u003e\u003e model = GAM(formula).fit(input_data, y)\n\n\u003e\u003e\u003e round(model.mean_theta[0][0], 8)\n0.37426986\n\n```\n\nNote that same logic could be used to construct higher dimensional bases,\nthat is, one could define a 3D-formula:\n\n\u003c!-- NOTE: To skip doctests, one \u003e has been removed --\u003e\n```python\n\u003e\u003e formula_3d = gammy.Kron(gammy.Kron(a, b), c)\n\n```\n\nPlot predictions and partial residuals:\n\n```python\n\u003e\u003e\u003e fig = gammy.plot.validation_plot(\n...     model,\n...     input_data,\n...     y,\n...     grid_limits=[[-3, 3], [-3, 3]],\n...     input_maps=[x, x[:, 0]],\n...     titles=[\"Surface estimate\", \"intercept\"]\n... )\n\n```\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/gp-kron-validation.png)\n\nPlot parameter probability density functions:\n\n```\n\u003e\u003e\u003e fig = gammy.plot.gaussian1d_density_plot(model)\n\n```\n\n![](https://raw.githubusercontent.com/malmgrek/gammy/develop/doc/resources/gp-kron-density.png)\n\n## Testing\n\nThe package's unit tests can be ran with PyTest (`cd` to repository root):\n\n``` shell\npytest -v\n```\n\nRunning this documentation as a Doctest:\n\n``` shell\npython -m doctest -v README.md\n```\n\n## Package documentation\n\nDocumentation of the package with code examples:\n\u003chttps://malmgrek.github.io/gammy\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmalmgrek%2Fgammy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmalmgrek%2Fgammy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmalmgrek%2Fgammy/lists"}