diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..79ec5c2 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,18 @@ +# This file has been mostly taken verbatim from https://github.com/pymc-devs/pymc/blob/main/.github/release.yml +changelog: + exclude: + labels: + - no releasenotes + categories: + - title: New Features 🎉 + labels: + - enhancement + - title: Bugfixes 🐛 + labels: + - bug + - title: Documentation 📖 + labels: + - docs + - title: Maintenance 🔧 + labels: + - "*" \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..e691f77 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,14 @@ +name: Python package +on: + push: + tags: + - "v*.*.*" +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build and publish to pypi + uses: JRubics/poetry-publish@v1.17 + with: + pypi_token: ${{ secrets.PYPI_TOKEN }} diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml deleted file mode 100644 index 6555e23..0000000 --- a/.github/workflows/python-publish.yml +++ /dev/null @@ -1,39 +0,0 @@ -# This workflow will upload a Python Package using Twine when a release is created -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -name: Upload Python Package - -on: - release: - types: [published] - -permissions: - contents: read - -jobs: - deploy: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build - - name: Build package - run: python -m build - - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} diff --git a/conjugate/distributions.py b/conjugate/distributions.py index 25cc37f..e555738 100644 --- a/conjugate/distributions.py +++ b/conjugate/distributions.py @@ -279,7 +279,6 @@ class BetaNegativeBinomial(SliceMixin): n: number of successes alpha: shape parameter - """ n: NUMERIC @@ -369,7 +368,15 @@ def dist(self): @dataclass class NormalInverseGamma: - """Normal inverse gamma distribution.""" + """Normal inverse gamma distribution. + + Args: + mu: mean + delta_inverse: covariance matrix + alpha: shape + beta: scale + + """ mu: NUMERIC delta_inverse: NUMERIC @@ -433,3 +440,23 @@ def sample_beta( return beta, variance return beta + + +@dataclass +class StudentT(ContinuousPlotDistMixin, SliceMixin): + """StudentT distribution. + + Args: + mu: mean + sigma: standard deviation + nu: degrees of freedom + + """ + + mu: NUMERIC + sigma: NUMERIC + nu: NUMERIC + + @property + def dist(self): + return stats.t(self.nu, self.mu, self.sigma) diff --git a/conjugate/models.py b/conjugate/models.py index 2c6c298..5b4bda0 100644 --- a/conjugate/models.py +++ b/conjugate/models.py @@ -14,7 +14,9 @@ NegativeBinomial, BetaNegativeBinomial, BetaBinomial, + InverseGamma, NormalInverseGamma, + StudentT, ) from conjugate._typing import NUMERIC @@ -193,6 +195,54 @@ def exponetial_gamma(x_total: NUMERIC, n: NUMERIC, gamma_prior: Gamma) -> Gamma: return Gamma(alpha=alpha_post, beta=beta_post) +def normal_known_mean( + x_total: NUMERIC, + x2_total: NUMERIC, + n: NUMERIC, + mu: NUMERIC, + inverse_gamma_prior: InverseGamma, +) -> InverseGamma: + """Posterior distribution for a normal likelihood with a known mean and a variance prior. + + Args: + x_total: sum of all outcomes + x2_total: sum of all outcomes squared + n: total number of samples in x_total + mu: known mean + inverse_gamma_prior: InverseGamma prior for variance + + Returns: + InverseGamma posterior distribution for the variance + + """ + alpha_post = inverse_gamma_prior.alpha + (n / 2) + beta_post = inverse_gamma_prior.beta + ( + 0.5 * (x2_total - (2 * mu * x_total) + (n * (mu**2))) + ) + + return InverseGamma(alpha=alpha_post, beta=beta_post) + + +def normal_known_mean_posterior_predictive( + mu: NUMERIC, inverse_gamma: InverseGamma +) -> StudentT: + """Posterior predictive distribution for a normal likelihood with a known mean and a variance prior. + + Args: + mu: known mean + inverse_gamma: InverseGamma prior + + Returns: + StudentT posterior predictive distribution + + """ + return StudentT( + n=2 * inverse_gamma.alpha, + mu=mu, + sigma=(inverse_gamma.beta / inverse_gamma.alpha) ** 0.5, + ) + + def linear_regression( X: NUMERIC, y: NUMERIC, diff --git a/pyproject.toml b/pyproject.toml index a19665b..711285b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "conjugate-models" -version = "0.1.5" +version = "0.1.6" description = "Bayesian Conjugate Models in Python" authors = ["Will Dean "] license = "MIT"