Convergence, bootstrap, p-values#316
Conversation
|
@alyst this is a relatively big PR - would you like to review it before I merge? |
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
@Maximilian-Stefan-Ernst Please proceed as you planned, I think these are nice changes. As I have mentioned before, I am finishing preparing the PR that potentially enhances the support for multi-group and "multi-regularization" SEMs. Because of those changes, I also have to update |
…bserved, fix bs + tests
| observed = observed, | ||
| gradient_required = !isnothing(implied.∇A), | ||
| meanstructure = MeanStruct(implied) == HasMeanStruct, | ||
| kwargs...) |
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| kwargs...) | |
| kwargs..., | |
| ) |
| observed = observed, | ||
| vech = implied.Σ isa Vector, | ||
| gradient = !isnothing(implied.∇Σ), | ||
| hessian = !isnothing(implied.∇²Σ), | ||
| meanstructure = MeanStruct(implied) == HasMeanStruct, | ||
| approximate_hessian = isnothing(implied.∇²Σ), | ||
| kwargs...) |
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| observed = observed, | |
| vech = implied.Σ isa Vector, | |
| gradient = !isnothing(implied.∇Σ), | |
| hessian = !isnothing(implied.∇²Σ), | |
| meanstructure = MeanStruct(implied) == HasMeanStruct, | |
| approximate_hessian = isnothing(implied.∇²Σ), | |
| kwargs...) | |
| observed = observed, | |
| vech = implied.Σ isa Vector, | |
| gradient = !isnothing(implied.∇Σ), | |
| hessian = !isnothing(implied.∇²Σ), | |
| meanstructure = MeanStruct(implied) == HasMeanStruct, | |
| approximate_hessian = isnothing(implied.∇²Σ), | |
| kwargs..., | |
| ) |
| observed = observed, | ||
| approximate_hessian = HessianEval(lossfun) == ApproxHessian, | ||
| kwargs...) |
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| observed = observed, | |
| approximate_hessian = HessianEval(lossfun) == ApproxHessian, | |
| kwargs...) | |
| observed = observed, | |
| approximate_hessian = HessianEval(lossfun) == ApproxHessian, | |
| kwargs..., | |
| ) |
| update_observed(lossfun::SemWLS, observed::SemObserved; kwargs...) = SemWLS(; | ||
| observed = observed, | ||
| meanstructure = MeanStruct(kwargs[:implied]) == HasMeanStruct, | ||
| kwargs...) |
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| kwargs...) | |
| kwargs..., | |
| ) |
| model_fit, | ||
| spec; | ||
| compare_hessian = true, | ||
| rtol_hessian = 0.2, | ||
| compare_bs = true, | ||
| rtol_bs = 0.1, | ||
| n_boot = 500) |
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| model_fit, | |
| spec; | |
| compare_hessian = true, | |
| rtol_hessian = 0.2, | |
| compare_bs = true, | |
| rtol_bs = 0.1, | |
| n_boot = 500) | |
| model_fit, | |
| spec; | |
| compare_hessian = true, | |
| rtol_hessian = 0.2, | |
| compare_bs = true, | |
| rtol_bs = 0.1, | |
| n_boot = 500, | |
| ) |
| if compare_bs | ||
| bs_samples = bootstrap(model_fit, spec; n_boot = n_boot) | ||
| @test bs_samples[:n_converged] > 0.95*n_boot | ||
| bs_samples = cat(bs_samples[:samples][BitVector(bs_samples[:converged])]..., dims = 2) |
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| bs_samples = cat(bs_samples[:samples][BitVector(bs_samples[:converged])]..., dims = 2) | |
| bs_samples = | |
| cat(bs_samples[:samples][BitVector(bs_samples[:converged])]..., dims = 2) |
| ) | ||
|
|
||
| model_ls_multigroup = SemEnsemble(model_ls_g1, model_ls_g2; optimizer = semoptimizer) | ||
| model_ls_multigroup = SemEnsemble(model_ls_g1, model_ls_g2; groups = [:Pasteur, :Grant_White], optimizer = semoptimizer) |
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| model_ls_multigroup = SemEnsemble(model_ls_g1, model_ls_g2; groups = [:Pasteur, :Grant_White], optimizer = semoptimizer) | |
| model_ls_multigroup = SemEnsemble( | |
| model_ls_g1, | |
| model_ls_g2; | |
| groups = [:Pasteur, :Grant_White], | |
| optimizer = semoptimizer, | |
| ) |
| lav_groups = Dict(:Pasteur => 1, :Grant_White => 2), | ||
| ) | ||
|
|
||
|
|
There was a problem hiding this comment.
[JuliaFormatter] reported by reviewdog 🐶
| ) | ||
| ``` | ||
| """ | ||
| function se_bootstrap( |
There was a problem hiding this comment.
It should be possible to make se_bootstrap() a wrapper around bootstrap()
| lock(lk) do | ||
| n_failed[] += 1 | ||
| end |
There was a problem hiding this comment.
To avoid locking, you can also use Threads.@atomic n_failed[] += 1, where Threads.atomic_add!(n_failed, 1) (see atomic operations)
| put!(model_pool, thread_model) | ||
| end | ||
| end | ||
| return Dict( |
There was a problem hiding this comment.
I think it's better to use NamedTuple here.
Also, while it might be fragile to use Base.return_types() to infer the result of statistic() before it is called, here it should be in principle possible to use T = mapreduce(typeof, promote_type, out) and Vector{T}(out) to help with the type inference and faster code generation downstream.
| data = prepare_data_bootstrap(data, fitted.model) | ||
| start = solution(fitted) | ||
| # pre-allocations | ||
| out = [] |
There was a problem hiding this comment.
You can also preallocate out = Vector{Any}(nothing, n_boot) and conv = fill(false, n_boot) (or conv = Vector{Union{Missing, Bool}}(missing, n_boot)), then you can avoid locks and just set the results directly out[i] = ....
The failed iterations should have out[i] === nothing, you can filter them out when generating the result.
If you are using conv with true/false/missing logic, you also don't have to count failed iterations as they will have conv[i] === missing.
convergedforSemFitobjectsconvergedreturns whether the model is converged in generalconvergencereturns the convergence flags and can be used to inspect why the model converged (or not)parallel = truebootstrapfunction that can be used to boostrap any statistic that can be extracted from a fitted modelz_testto compute p-values for individual parametersnormal_CIto compute a normal theory confidence interval