diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index be32b73..ed8f72f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,7 +16,7 @@ jobs: matrix: version: - '1' - - '1.6' + - 'lts' os: - ubuntu-latest arch: @@ -27,29 +27,18 @@ jobs: arch: x64 coverage: true steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@v1 + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v1 - env: - cache-name: cache-artifacts - with: - path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} - restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test- - ${{ runner.os }}- + include-all-prereleases: false + - uses: julia-actions/cache@v2 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - with: - coverage: ${{ matrix.coverage || false }} - uses: julia-actions/julia-processcoverage@v1 - if: matrix.coverage - - name: Send coverage - if: matrix.coverage - uses: codecov/codecov-action@v2 + - uses: codecov/codecov-action@v5 with: - file: lcov.info + files: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false diff --git a/Project.toml b/Project.toml index 387dfa3..a149933 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "BayesianLinearRegressors" uuid = "f579363c-4606-5e5c-a623-c4549f609c4b" -authors = ["Will Tebbutt "] -version = "0.3.8" +authors = ["Will Tebbutt"] +version = "0.3.9" [deps] AbstractGPs = "99985d1d-32ba-4be9-9821-2ec096f28918" @@ -11,6 +11,14 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [compat] -AbstractGPs = "0.3, 0.4, 0.5" +AbstractGPs = "0.5" +LinearAlgebra = "1" PDMats = "0.11" -julia = "1.3" +Test = "1" +julia = "1.10" + +[extras] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Test"] diff --git a/src/BayesianLinearRegressors.jl b/src/BayesianLinearRegressors.jl index 31ee895..e0af207 100644 --- a/src/BayesianLinearRegressors.jl +++ b/src/BayesianLinearRegressors.jl @@ -1,10 +1,6 @@ module BayesianLinearRegressors -using AbstractGPs -using LinearAlgebra -using Random -using Statistics -using PDMats +using AbstractGPs, LinearAlgebra, PDMats, Random using AbstractGPs: AbstractGP, _cholesky, FiniteGP diff --git a/test/Project.toml b/test/Project.toml deleted file mode 100644 index 12b1d03..0000000 --- a/test/Project.toml +++ /dev/null @@ -1,13 +0,0 @@ -[deps] -AbstractGPs = "99985d1d-32ba-4be9-9821-2ec096f28918" -Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" -FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[compat] -FiniteDifferences = "0.12" -Zygote = "0.6" diff --git a/test/bayesian_linear_regression.jl b/test/bayesian_linear_regression.jl index 423106f..560d875 100644 --- a/test/bayesian_linear_regression.jl +++ b/test/bayesian_linear_regression.jl @@ -18,39 +18,13 @@ Σ_empirical = (Y .- mean(Y; dims=2)) * (Y .- mean(Y; dims=2))' ./ samples @test mean(f(X, Σy)) ≈ m_empirical atol = 1e-2 rtol = 1e-2 @test cov(f(X, Σy)) ≈ Σ_empirical atol = 1e-2 rtol = 1e-2 - - @testset "Zygote (everything dense)" begin - function rand_blr(X, A_Σy, mw, A_Λw) - Σy, Λw = Symmetric(A_Σy * A_Σy' + I), Symmetric(A_Λw * A_Λw' + I) - f = BayesianLinearRegressor(mw, Λw) - return rand(MersenneTwister(123456), f(X, Σy), 3) - end - mw, A_Σy, A_Λw = f.mw, 0.1 .* randn(rng, N, N), 0.1 .* randn(rng, D, D) - - # Run the model forwards and check that output agrees with non-Zygote output - z, back = Zygote.pullback(rand_blr, X, A_Σy, mw, A_Λw) - @test z == rand_blr(X, A_Σy, mw, A_Λw) - - # Compute adjoints using Zygote. - z̄ = randn(rng, size(z)) - dX, dA_Σy, dmw, dA_Λw = back(z̄) - - # Verify adjoints via finite differencing. - fdm = central_fdm(5, 1) - @test dX ≈ first(j′vp(fdm, X -> rand_blr(X, A_Σy, mw, A_Λw), z̄, X)) - @test dA_Σy ≈ - first(j′vp(fdm, A_Σy -> rand_blr(X, A_Σy, mw, A_Λw), z̄, A_Σy)) - @test dmw ≈ first(j′vp(fdm, mw -> rand_blr(X, A_Σy, mw, A_Λw), z̄, mw)) - @test dA_Λw ≈ - first(j′vp(fdm, A_Λw -> rand_blr(X, A_Σy, mw, A_Λw), z̄, A_Λw)) - end end @testset "logpdf" begin rng, N, D = MersenneTwister(123456), 13, 7 X, f, Σy = generate_toy_problem(rng, N, D, Tx) y = rand(rng, f(X, Σy)) - # Construct MvNormal using a naive but simple computation for the mean / cov. + # Compute logpdf using a naive but simple computation for the mean / cov. function naive_normal_stats(X::Matrix) return (X' * f.mw, Symmetric(X' * (cholesky(f.Λw) \ X) + Σy)) end @@ -59,33 +33,8 @@ m, Σ = naive_normal_stats(X) # Check that logpdf agrees between distributions and BLR. - @test logpdf(f(X, Σy), y) ≈ logpdf(MvNormal(m, Σ), y) - - @testset "Zygote (everything dense)" begin - function logpdf_blr(X, A_Σy, y, mw, A_Λw) - Σy, Λw = Symmetric(A_Σy * A_Σy' + I), Symmetric(A_Λw * A_Λw' + I) - f = BayesianLinearRegressor(mw, Λw) - return logpdf(f(X, Σy), y) - end - mw, A_Σy, A_Λw = f.mw, 0.1 .* randn(rng, N, N), 0.1 .* randn(rng, D, D) - - z, back = Zygote.pullback(logpdf_blr, X, A_Σy, y, mw, A_Λw) - @test z == logpdf_blr(X, A_Σy, y, mw, A_Λw) - - # Compute gradients using Zygote. - z̄ = randn(rng) - dX, dA_Σy, dy, dmw, dA_Λw = back(z̄) - - # Check correctness via finite differencing. - fdm = central_fdm(5, 1) - @test dX ≈ first(j′vp(fdm, X -> logpdf_blr(X, A_Σy, y, mw, A_Λw), z̄, X)) - @test dA_Σy ≈ - first(j′vp(fdm, A_Σy -> logpdf_blr(X, A_Σy, y, mw, A_Λw), z̄, A_Σy)) - @test dy ≈ first(j′vp(fdm, y -> logpdf_blr(X, A_Σy, y, mw, A_Λw), z̄, y)) - @test dmw ≈ first(j′vp(fdm, mw -> logpdf_blr(X, A_Σy, y, mw, A_Λw), z̄, mw)) - @test dA_Λw ≈ - first(j′vp(fdm, A_Λw -> logpdf_blr(X, A_Σy, y, mw, A_Λw), z̄, A_Λw)) - end + δ = y - m + @test logpdf(f(X, Σy), y) ≈ -(N * log(2π) + logdet(Σ) + δ' * (Σ \ δ)) / 2 end @testset "posterior" begin @testset "low noise" begin diff --git a/test/runtests.jl b/test/runtests.jl index a48250d..70b97e5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,15 +1,6 @@ -using AbstractGPs -using BayesianLinearRegressors -using Distributions -using FiniteDifferences -using LinearAlgebra -using Random -using Test -using Zygote -using PDMats +using AbstractGPs, BayesianLinearRegressors, LinearAlgebra, PDMats, Random, Test using BayesianLinearRegressors: BayesianLinearRegressor, posterior, marginals, cov, mean -using FiniteDifferences: j′vp include("test_utils.jl") diff --git a/test/sampling_functions.jl b/test/sampling_functions.jl index 46d0820..357d310 100644 --- a/test/sampling_functions.jl +++ b/test/sampling_functions.jl @@ -44,46 +44,6 @@ @test mean(f(X, Σy)) ≈ m_empirical atol = 1e-3 rtol = 1e-3 @test cov(f(X, Σy)) ≈ Σ_empirical + Σy atol = 1e-2 rtol = 1e-2 end - - @testset "Zygote (everything dense)" begin - function test_rand_funcs_adjoints(sample_function) - rng, N, D = MersenneTwister(123456), 11, 5 - X, f, _ = generate_toy_problem(rng, N, D, Tx) - mw, A_Λw = f.mw, 0.1 .* randn(rng, D, D) - - # Run the model forwards and check that output agrees with non-Zygote. - z, back = Zygote.pullback(sample_function, X, mw, A_Λw) - @test z == sample_function(X, mw, A_Λw) - - # Compute adjoints using Zygote. - z̄ = randn(rng, size(z)) - dX, dmw, dA_Λw = back(z̄) - - # Verify adjoints via finite differencing. - fdm = central_fdm(5, 1) - @test dX ≈ first(j′vp(fdm, X -> sample_function(X, mw, A_Λw), z̄, X)) - @test dmw ≈ first(j′vp(fdm, mw -> sample_function(X, mw, A_Λw), z̄, mw)) - @test dA_Λw ≈ - first(j′vp(fdm, A_Λw -> sample_function(X, mw, A_Λw), z̄, A_Λw)) - end - - function rand_funcs_single(X, mw, A_Λw) - Λw = Symmetric(A_Λw * A_Λw' + I) - f = BayesianLinearRegressor(mw, Λw) - g = rand(MersenneTwister(123456), f) - return g(X) - end - - function rand_funcs_multi(X, mw, A_Λw) - Λw = Symmetric(A_Λw * A_Λw' + I) - f = BayesianLinearRegressor(mw, Λw) - gs = rand(MersenneTwister(123456), f, 1, 1) - return reduce(hcat, map(h -> h(X), reshape(gs, :))) - end - - test_rand_funcs_adjoints(rand_funcs_single) - test_rand_funcs_adjoints(rand_funcs_multi) - end end @testset "basis_function_regression" begin