Skip to content

Commit c028fd7

Browse files
authored
Test using StableRNGs (#55)
* switched tests to StableRNGs * WIP need to instantiate a new StableRNG at fit() * Made rng=StableRNG() in fit * Bumped version and moved extras to test/ * updated travis-ci urls * bump compat versions * fix doc tests * CI github action instead of travis * limit GLMNet imports to avoid clash with GLM.coef * don't test on julia 1.0 which doesn't support test/Project.toml * updated badges * increased rtol in CV tests
1 parent 81ec2a4 commit c028fd7

File tree

15 files changed

+145
-101
lines changed

15 files changed

+145
-101
lines changed

.github/workflows/ci.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: CI
2+
on:
3+
push:
4+
branches: [master]
5+
tags: ["*"]
6+
pull_request:
7+
jobs:
8+
test:
9+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
version:
15+
- '1' # automatically expands to the latest stable 1.x release of Julia
16+
- 'nightly'
17+
os:
18+
- ubuntu-latest
19+
- macOS-latest
20+
- windows-latest
21+
arch:
22+
- x64
23+
- x86
24+
exclude:
25+
- os: macOS-latest
26+
arch: x86
27+
steps:
28+
- uses: actions/checkout@v2
29+
- uses: julia-actions/setup-julia@v1
30+
with:
31+
version: ${{ matrix.version }}
32+
arch: ${{ matrix.arch }}
33+
- uses: actions/cache@v1
34+
env:
35+
cache-name: cache-artifacts
36+
with:
37+
path: ~/.julia/artifacts
38+
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
39+
restore-keys: |
40+
${{ runner.os }}-test-${{ env.cache-name }}-
41+
${{ runner.os }}-test-
42+
${{ runner.os }}-
43+
- uses: julia-actions/julia-buildpkg@v1
44+
- uses: julia-actions/julia-runtest@v1
45+
- uses: julia-actions/julia-processcoverage@v1
46+
- uses: codecov/codecov-action@v1
47+
with:
48+
file: lcov.info
49+
docs:
50+
name: Documentation
51+
runs-on: ubuntu-latest
52+
steps:
53+
- uses: actions/checkout@v2
54+
- uses: julia-actions/setup-julia@v1
55+
with:
56+
version: '1'
57+
- run: |
58+
julia --project=docs -e '
59+
using Pkg
60+
Pkg.develop(PackageSpec(path=pwd()))
61+
Pkg.instantiate()'
62+
- run: julia --project=docs docs/make.jl
63+
env:
64+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65+
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}

.travis.yml

Lines changed: 0 additions & 33 deletions
This file was deleted.

Project.toml

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Lasso"
22
uuid = "b4fcebef-c861-5a0f-a7e2-ba9dc32b180a"
3-
version = "0.5.2"
3+
version = "0.6.0"
44

55
[deps]
66
DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2"
@@ -16,22 +16,10 @@ StatsModels = "3eaba693-59b7-5ba5-a881-562e759f1c8d"
1616

1717
[compat]
1818
DSP = "0.6"
19-
Distributions = "0.23"
19+
Distributions = "0.24"
2020
GLM = "1.3"
2121
MLBase = "0.8"
2222
Reexport = "0.2"
23-
StatsBase = "0.32"
23+
StatsBase = "0.33"
2424
StatsModels = "0.6"
2525
julia = "0.7, 1"
26-
27-
[extras]
28-
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
29-
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
30-
GLMNet = "8d5ece8b-de18-5317-b113-243142960cc6"
31-
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
32-
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
33-
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
34-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
35-
36-
[targets]
37-
test = ["CSV", "LinearAlgebra", "GLMNet", "DataFrames", "Random", "SparseArrays", "Test"]

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
| **Documentation** | **Build Status** |
44
|:-------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------:|
5-
| [![][docs-stable-img]][docs-stable-url] [![][docs-dev-img]][docs-dev-url] | [![][travis-img]][travis-url] [![][codecov-img]][codecov-url] |
5+
| [![][docs-stable-img]][docs-stable-url] [![][docs-dev-img]][docs-dev-url] | [![][actions-img]][actions-url] [![][codecov-img]][codecov-url] |
66

77
[docs-dev-img]: https://img.shields.io/badge/docs-dev-blue.svg
88
[docs-dev-url]: https://juliastats.github.io/Lasso.jl/latest
99

1010
[docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg
1111
[docs-stable-url]: https://juliastats.github.io/Lasso.jl/stable
1212

13-
[travis-img]: https://travis-ci.org/JuliaStats/Lasso.jl.svg?branch=master
14-
[travis-url]: https://travis-ci.org/JuliaStats/Lasso.jl
13+
[actions-img]: https://github.com/JuliaStats/Lasso.jl/workflows/CI/badge.svg
14+
[actions-url]: https://github.com/JuliaStats/Lasso.jl/actions?query=workflow%3ACI+branch%3Amaster
1515

16-
[codecov-img]: https://coveralls.io/repos/JuliaStats/Lasso.jl/badge.svg?branch=master
17-
[codecov-url]: https://coveralls.io/r/JuliaStats/Lasso.jl?branch=master
16+
[codecov-img]: http://codecov.io/github/JuliaStats/Lasso.jl/coverage.svg?branch=master
17+
[codecov-url]: http://codecov.io/github/JuliaStats/Lasso.jl?branch=master
1818

1919
Lasso.jl is a pure Julia implementation of the glmnet coordinate
2020
descent algorithm for fitting linear and generalized linear Lasso and

docs/src/index.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ julia> using DataFrames, Lasso
3434
3535
julia> data = DataFrame(X=[1,2,3], Y=[2,4,7])
3636
3×2 DataFrames.DataFrame
37-
Row │ X │ Y │
38-
│ Int64 Int64
39-
─────┼──────────────
40-
│ 1 1 │ 2
41-
│ 2 2 │ 4
42-
│ 3 3 │ 7
37+
Row │ X Y
38+
│ Int64 Int64
39+
─────┼──────────────
40+
11 2
41+
22 4
42+
33 7
4343
```
4444

4545
Let's fit this to a model

docs/src/lasso.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ julia> Random.seed!(124); # because CV folds are random
7575
7676
julia> data = DataFrame(X=[1,2,3], Y=[2,4,7])
7777
3×2 DataFrames.DataFrame
78-
Row │ X │ Y │
79-
│ Int64 Int64
80-
─────┼──────────────
81-
│ 1 1 │ 2
82-
│ 2 2 │ 4
83-
│ 3 3 │ 7
78+
Row │ X Y
79+
│ Int64 Int64
80+
─────┼──────────────
81+
11 2
82+
22 4
83+
33 7
8484
8585
julia> m = fit(LassoModel, @formula(Y ~ X), data; select=MinCVmse(Kfold(3,2)))
8686
LassoModel using MinCVmse(Kfold([3, 1, 2], 2, 1.5)) segment of the regularization path.
@@ -95,7 +95,7 @@ x2 0.0
9595
9696
julia> coef(m)
9797
2-element Array{Float64,1}:
98-
4.333333333333335
98+
4.333333333333333
9999
0.0
100100
101101
```

src/Lasso.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,14 @@ end
124124

125125
## COEFFICIENT ITERATION IN SEQUENTIAL OR RANDOM ORDER
126126
struct RandomCoefficientIterator
127-
rng::MersenneTwister
127+
rng::AbstractRNG
128128
rg::Sampler
129129
coeforder::Vector{Int}
130130
end
131131
const RANDOMIZE_DEFAULT = true
132132

133-
function RandomCoefficientIterator()
134-
rng = MersenneTwister(1337)
133+
RandomCoefficientIterator(::Nothing) = RandomCoefficientIterator(MersenneTwister(1337))
134+
function RandomCoefficientIterator(rng)
135135
RandomCoefficientIterator(rng, Sampler(rng, 1:2), Int[])
136136
end
137137

@@ -425,6 +425,7 @@ fit(LassoPath, X, y, Binomial(), Logit();
425425
- `randomize=true`: Whether to randomize the order in which coefficients are
426426
updated by coordinate descent. This can drastically speed
427427
convergence if coefficients are highly correlated.
428+
- `rng=RNG_DEFAULT`: Random number generator to be used for coefficient iteration.
428429
- `maxncoef=min(size(X, 2), 2*size(X, 1))`: maximum number of coefficients
429430
allowed in the model. If exceeded, an error will be thrown.
430431
- `dofit=true`: Whether to fit the model upon construction. If `false`, the
@@ -463,6 +464,7 @@ function StatsBase.fit(::Type{LassoPath},
463464
algorithm::Type=defaultalgorithm(d, l, size(X, 1), size(X, 2)),
464465
dofit::Bool=true,
465466
irls_tol::Real=1e-7, randomize::Bool=RANDOMIZE_DEFAULT,
467+
rng::Union{AbstractRNG, Nothing}=nothing,
466468
maxncoef::Int=min(size(X, 2), 2*size(X, 1)),
467469
penalty_factor::Union{Vector,Nothing}=nothing,
468470
standardizeω::Bool=true,
@@ -477,7 +479,7 @@ function StatsBase.fit(::Type{LassoPath},
477479
α = convert(T, α)
478480
0 < α <= 1 || error("α must satisfy 0 < α <= 1")
479481
λminratio = convert(T, λminratio)
480-
coefitr = randomize ? RandomCoefficientIterator() : (1:0)
482+
coefitr = randomize ? RandomCoefficientIterator(rng) : (1:0)
481483

482484
# penalty_factor (ω) defaults to a vector of ones
483485
ω = initpenaltyfactor(penalty_factor, size(X, 2), standardizeω)

src/gammalasso.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ function StatsBase.fit(::Type{GammaLassoPath},
6565
algorithm::Type=defaultalgorithm(d, l, size(X, 1), size(X, 2)),
6666
dofit::Bool=true,
6767
irls_tol::Real=1e-7, randomize::Bool=RANDOMIZE_DEFAULT,
68+
rng::Union{AbstractRNG, Nothing}=nothing,
6869
maxncoef::Int=min(size(X, 2), 2*size(X, 1)),
6970
penalty_factor::Union{Vector,Nothing}=nothing,
7071
standardizeω::Bool=true,
@@ -92,7 +93,7 @@ function StatsBase.fit(::Type{GammaLassoPath},
9293
# Lasso initialization
9394
α = convert(T, α)
9495
λminratio = convert(T, λminratio)
95-
coefitr = randomize ? RandomCoefficientIterator() : (1:0)
96+
coefitr = randomize ? RandomCoefficientIterator(rng) : (1:0)
9697
cd = algorithm{T,intercept,typeof(X),typeof(coefitr),typeof(ω)}(X, α, maxncoef, 1e-7, coefitr, ω)
9798

9899
# GLM response initialization

test/Project.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[deps]
2+
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
3+
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
4+
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
5+
GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
6+
GLMNet = "8d5ece8b-de18-5317-b113-243142960cc6"
7+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
8+
MLBase = "f0e99cf1-93fa-52ec-9ecc-5026115318e0"
9+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
10+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
11+
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
12+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

test/cross_validation.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ path = fit(LassoPath, X, y; offset=offset)
1414

1515
coefsAICc = coef(path, MinAICc())
1616
segminAICc = minAICc(path)
17-
@test segminAICc == 71
17+
@test segminAICc == 72
1818
@test coefsAICc == β[:,segminAICc]
1919

2020
coefsBIC = coef(path, MinBIC())
@@ -24,26 +24,26 @@ segminBIC = Lasso.minBIC(path)
2424

2525
coefsAIC = coef(path, MinAIC())
2626
segminAIC = Lasso.minAIC(path)
27-
@test segminAIC == 71
27+
@test segminAIC == 72
2828
@test coefsAIC == β[:,segminAIC]
2929

3030
Random.seed!(13)
3131
gen = Kfold(length(y),10)
32-
segCVmin = cross_validate_path(path,MinCVmse(gen))
32+
segCVmin = cross_validate_path(path, MinCVmse(gen))
3333
coefsCVmin = coef(path, MinCVmse(path))
34-
@test segCVmin == 71
34+
@test segCVmin == 72
3535
@test coefsCVmin == β[:,segCVmin]
3636

3737
Random.seed!(13)
3838
gen = Kfold(length(y),10)
3939
segCVmin = cross_validate_path(path,X,y, MinCVmse(gen), offset=offset)
4040
coefsCVmin = coef(path, MinCVmse(path))
41-
@test segCVmin == 71
41+
@test segCVmin == 72
4242
@test coefsCVmin == β[:,segCVmin]
4343

4444
Random.seed!(13)
4545
coefsCV1se = coef(path, MinCV1se(path, 20))
46-
Random.seed!(13)
46+
Random.seed!( 13)
4747
segCV1se = cross_validate_path(path,X,y, MinCV1se(path, 20),offset=offset)
4848
@test segCV1se == 42
4949
@test coefsCV1se == β[:,segCV1se]

0 commit comments

Comments
 (0)