Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation and Tutorials #23

Merged
merged 8 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
test:
name: Julia CI
runs-on: ${{ matrix.os }}
timeout-minutes: 60
continue-on-error: ${{ matrix.version == 'nightly' }}
strategy:
fail-fast: false
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
*.jl.cov
*.jl.mem
**/Manifest.toml

# Generated files.
/docs/build/
/docs/src/tutorials/*.html
/docs/src/tutorials/*.md

.vscode/
.DS_Store
8 changes: 8 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
PlutoStaticHTML = "359b1769-a58e-495b-9770-312e911026ad"
TuringGLM = "0004c1f4-53c5-4d43-a221-a1dac6cf6b74"

[compat]
CSV = "0.9, 1"
CategoricalArrays = "0.10"
DataFrames = "1"
Documenter = "0.27"
PlutoStaticHTML = "3"
50 changes: 47 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,63 @@
using TuringGLM
using Documenter
using PlutoStaticHTML

DocMeta.setdocmeta!(TuringGLM, :DocTestSetup, :(using TuringGLM); recursive=true)

# PlutoStaticHTML opens the notebook in a tempdir, so this is a hack to pass the correct dir in again.
ENV["PKGDIR"] = string(pkgdir(TuringGLM))

# Run all Pluto notebooks (".jl" files) in `tutorials_dir` and write outputs to HTML files.
tutorials_dir = joinpath(pkgdir(TuringGLM), "docs", "src", "tutorials")
parallel_build(BuildOptions(tutorials_dir))

tutorials = [
"Linear Regression",
"Logistic Regression",
"Poisson Regression",
"Negative Binomial Regression",
"Robust Regression",
"Hierarchical Models",
"Custom Priors",
]

# Generate tutorials Markdown files which can be read by Documenter.jl
md_files = map(tutorials) do tutorial
file = lowercase(replace(tutorial, " " => '_'))

from = joinpath(tutorials_dir, "$file.html")
html = read(from, String)

md = """
# $tutorial

```@eval
# Auto generated file. Do not modify.
```

```@raw html
$html
```
"""

to = joinpath(tutorials_dir, "$file.md")
println("Writing $to")
write(to, md)

return joinpath("tutorials", "$file.md")
end

makedocs(;
modules=[TuringGLM],
authors="Jose Storopoli <[email protected]> and contributors",
authors="Jose Storopoli <[email protected]>, Rik Huijzer <[email protected]>, and contributors",
repo="https://github.com/TuringLang/TuringGLM.jl/blob/{commit}{path}#{line}",
sitename="TuringGLM.jl",
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", "false") == "true",
canonical="https://TuringLang.github.io/TuringGLM.jl",
assets=String[],
assets=["assets/favicon.ico"],
),
pages=["Home" => "index.md"],
pages=["Home" => "index.md", "Tutorials" => md_files, "API reference" => "api.md"],
)

deploydocs(; repo="github.com/TuringLang/TuringGLM.jl", devbranch="main")
14 changes: 14 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```@meta
CurrentModule = TuringGLM
```

# TuringGLM

Documentation for [TuringGLM](https://github.com/TuringLang/TuringGLM.jl).

```@index
```

```@autodocs
Modules = [TuringGLM]
```
Binary file added docs/src/assets/favicon.ico
Binary file not shown.
Binary file added docs/src/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 67 additions & 7 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,74 @@
```@meta
CurrentModule = TuringGLM
```

# TuringGLM

Documentation for [TuringGLM](https://github.com/TuringLang/TuringGLM.jl).
Please [file an issue](https://github.com/TuringLang/TuringGLM.jl/issues/new)
if you run into any problems.

## Getting Started

TuringGLM makes easy to specify Bayesian **G**eneralized **L**inear **M**odels using the formula syntax and returns an instantiated [Turing](https://github.com/TuringLang/Turing.jl) model.

Heavily inspired by [brms](https://github.com/paul-buerkner/brms/) (uses RStan or CmdStanR) and [bambi](https://github.com/bambinos/bambi) (uses PyMC3).

### `@formula`

The `@formula` macro is extended from [`StatsModels.jl`](https://github.com/JuliaStats/StatsModels.jl) along with [`MixedModels.jl`](https://github.com/JuliaStats/MixedModels.jl) for the random-effects (a.k.a. group-level predictors).

The syntax is done by using the `@formula` macro and then specifying the dependent variable followed by a tilde `~` then the independent variables separated by a plus sign `+`.

Example:

```julia
@formula(y ~ x1 + x2 + x3)
```

```@index
Moderations/interactions can be specified with the asterisk sign `*`, e.g. `x1 * x2`.
This will be expanded to `x1 + x2 + x1:x2`, which, following the principle of hierarchy,
the main effects must also be added along with the interaction effects. Here `x1:x2`
means that the values of `x1` will be multiplied (interacted) with the values of `x2`.

Random-effects (a.k.a. group-level effects) can be specified with the `(term | group)` inside
the `@formula`, where `term` is the independent variable and `group` is the **categorical**
representation (i.e., either a column of `String`s or a `CategoricalArray` in `data`).
You can specify a random-intercept with `(1 | group)`.

Example:

```julia
@formula(y ~ (1 | group) + x1)
```

```@autodocs
Modules = [TuringGLM]
### Data

TuringGLM supports any `Tables.jl`-compatible data interface.
The most popular ones are `DataFrame`s and `NamedTuple`s.

### Supported Models

TuringGLM supports non-hiearchical and hierarchical models.
For hierarchical models, only single random-intercept hierarchical models are supported.

For likelihoods, `TuringGLM.jl` supports:

* `Gaussian()` (the default if not specified): linear regression
* `Student()`: robust linear regression
* `Logistic()`: logistic regression
* `Pois()`: Poisson count data regression
* `NegBin()`: negative binomial robust count data regression

## Tutorials

Take a look at the tutorials for all supported likelihood and models:

```@contents
Pages = [
"tutorials/linear_regression.md",
"tutorials/logistic_regression.md",
"tutorials/poisson_regression.md",
"tutorials/negativebinomial_regression.md",
"tutorials/robust_regression.md",
"tutorials/hierarchical_models.md",
"tutorials/custom_priors.md"
]
Depth = 1
```
104 changes: 104 additions & 0 deletions docs/src/tutorials/custom_priors.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
### A Pluto.jl notebook ###
# v0.17.5

using Markdown
using InteractiveUtils

# ╔═╡ 587f852c-f357-4260-ae87-a60eaf101d36
# hideall
let
pkg_dir = if "PKGDIR" in keys(ENV)
ENV["PKGDIR"]
else
dirname(dirname(dirname(@__DIR__)))
end
docs_dir = joinpath(pkg_dir, "docs")

using Pkg: Pkg
Pkg.activate(docs_dir)
Pkg.develop(; path=pkg_dir)
Pkg.instantiate()
end

# ╔═╡ 206214e5-ab7a-4cae-bc85-7a77ed909c39
using CSV

# ╔═╡ 7f497bba-b0cc-40ef-a32f-4f69fa1cc355
using DataFrames

# ╔═╡ 178595bd-d701-47c6-a33c-4a33bad90a4f
using TuringGLM

# ╔═╡ 27c478b2-730f-11ec-1fbd-0b63384eaaf4
md"""
Let's cover the **Linear Regression** example with the `kidiq` dataset (Gelman & Hill, 2007), which is data from a survey of adult American women and their respective children.
Dated from 2007, it has 434 observations and 4 variables:

* `kid_score`: child's IQ
* `mom_hs`: binary/dummy (0 or 1) if the child's mother has a high school diploma
* `mom_iq`: mother's IQ
* `mom_age`: mother's age
"""

# ╔═╡ 041e7dca-b554-450c-9f43-79494e54e48e
url = "https://github.com/TuringLang/TuringGLM.jl/raw/main/data/kidiq.csv"

# ╔═╡ c0c65854-57af-488d-b80b-d37601e8024b
kidiq = CSV.read(download(url), DataFrame)

# ╔═╡ 31287120-a04c-46b2-ba06-6168c3435a78
md"""
Using `kid_score` as dependent variable and `mom_hs` along with `mom_iq` as independent variables with a moderation (interaction) effect:
"""

# ╔═╡ 1e4c7e9e-b32a-4eca-8621-d3b748d45d9e
fm = @formula(kid_score ~ mom_hs * mom_iq)

# ╔═╡ 0cd3dfce-3001-4c6e-b550-ca6964f19e35
md"""
Let's create our CustomPrior object.
No need for the third (auxiliary) prior for this model so we leave it as `nothing`:
"""

# ╔═╡ 9766b37c-55a0-4f74-924e-66b92eab7429
priors = CustomPrior(Normal(0, 2.5), Normal(10, 20), nothing);

# ╔═╡ 56498ac7-3476-42eb-9c12-078562fff51d
md"""
We instantiate our model with `turing_model` without specifying any model, thus the default model will be used: `Gaussian()`.
Notice that we are specifying the `priors` keyword argument:
"""

# ╔═╡ 99cbb309-393f-4a13-9454-1dee747c88a6
model = turing_model(fm, kidiq; priors);

# ╔═╡ 3e227e48-259c-40db-90e4-cd62afc307b2
chn = sample(model, NUTS(), 2_000);

# ╔═╡ 954f928a-5fcb-4c14-a74c-09bfe92f50bd
describe(chn)[1]

# ╔═╡ 9bb7a28f-a980-4cbc-9931-b38df79ae94b
md"""
## References

Gelman, A., & Hill, J. (2007). Data analysis using regression and multilevel/hierarchical models. Cambridge university press.
"""

# ╔═╡ Cell order:
# ╠═587f852c-f357-4260-ae87-a60eaf101d36
# ╠═27c478b2-730f-11ec-1fbd-0b63384eaaf4
# ╠═206214e5-ab7a-4cae-bc85-7a77ed909c39
# ╠═7f497bba-b0cc-40ef-a32f-4f69fa1cc355
# ╠═041e7dca-b554-450c-9f43-79494e54e48e
# ╠═c0c65854-57af-488d-b80b-d37601e8024b
# ╠═178595bd-d701-47c6-a33c-4a33bad90a4f
# ╠═31287120-a04c-46b2-ba06-6168c3435a78
# ╠═1e4c7e9e-b32a-4eca-8621-d3b748d45d9e
# ╠═0cd3dfce-3001-4c6e-b550-ca6964f19e35
# ╠═9766b37c-55a0-4f74-924e-66b92eab7429
# ╠═56498ac7-3476-42eb-9c12-078562fff51d
# ╠═99cbb309-393f-4a13-9454-1dee747c88a6
# ╠═3e227e48-259c-40db-90e4-cd62afc307b2
# ╠═954f928a-5fcb-4c14-a74c-09bfe92f50bd
# ╠═9bb7a28f-a980-4cbc-9931-b38df79ae94b
Loading