Skip to content

Commit 24261d5

Browse files
author
Alexey Stukalov
committed
CFI: sync with Sem refactor
1 parent 84c6653 commit 24261d5

1 file changed

Lines changed: 22 additions & 25 deletions

File tree

  • src/frontend/fit/fitmeasures

src/frontend/fit/fitmeasures/CFI.jl

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
66
Calculate the Comparative Fit Index (CFI).
77
8-
The CFI ranges from 0-1 and measures how much better the model
8+
The CFI ranges from 0-1 and measures how much better the model
99
fits the data compared to a baseline model.
1010
If no baseline model is provided, a model with unconstrained
1111
variances (and means) is compaired against.
12-
For multigroup models, variances (and means) per group are free
12+
For multigroup models, variances (and means) per group are free
1313
without any equality constraints between groups.
1414
"""
1515
function CFI end
@@ -35,34 +35,31 @@ function CFI(χ², dof, χ²₀, dof₀)
3535
end
3636

3737
###
38-
function χ²_varonly(model::AbstractSemSingle)
39-
check_single_lossfun(model; throw_error = true)
40-
return χ²_varonly(model.loss.functions[1], model)
41-
end
42-
43-
function χ²_varonly(model::SemEnsemble)
44-
check_single_lossfun(model; throw_error = true)
45-
return sum(χ²_varonly, model.sems)
38+
function χ²_varonly(model::AbstractSem)
39+
check_same_semterm_type(model; throw_error = true)
40+
return sum(sem_terms(model)) do semterm
41+
χ²_varonly(_unwrap(loss(semterm)))
42+
end
4643
end
4744

48-
function χ²_varonly(::SemML, model::AbstractSemSingle)
49-
N⁻ = (nsamples(model) - 1)
50-
S = obs_cov(observed(model))
45+
function χ²_varonly(loss::SemML)
46+
N⁻ = (nsamples(loss) - 1)
47+
S = obs_cov(observed(loss))
5148
Σ₀ = Diagonal(S)
52-
p = nobserved_vars(model)
49+
p = nobserved_vars(loss)
5350
return N⁻*(logdet(Σ₀) + tr(inv(Σ₀)*S) - logdet(S) - p)
5451
end
5552

5653
# for the optimal variance only model, we have to solve 1/2 tr((I-XS⁻¹)^2) with X diagonal
57-
function χ²_varonly(::SemWLS, model)
58-
N⁻ = (nsamples(model) - 1)
59-
S⁻¹ = inv((obs_cov(observed(model))))
54+
function χ²_varonly(loss::SemWLS)
55+
N⁻ = (nsamples(loss) - 1)
56+
S⁻¹ = inv((obs_cov(observed(loss))))
6057
Σ₀ = Diagonal(inv(S⁻¹ .* S⁻¹)*diag(S⁻¹))
6158
return N⁻*0.5*tr((I - Σ₀*S⁻¹)^2)
6259
end
6360

6461
# For FIML, an explicit bl model has to be passed
65-
function χ²_varonly(::SemFIML, model)
62+
function χ²_varonly(loss::SemFIML)
6663
"""
6764
Computing the CFI with FIML requires explicitely passing a fitted baseline model as
6865
CFI(fit::SemFit, fit_baseline::SemFit)
@@ -71,12 +68,12 @@ function χ²_varonly(::SemFIML, model)
7168
throw
7269
end
7370

74-
function dof_varonly(model::AbstractSemSingle)
75-
nparams_varonly = nobserved_vars(model)
76-
if MeanStruct(model.implied) === HasMeanStruct
77-
nparams_varonly *= 2
71+
function dof_varonly(model::AbstractSem)
72+
return sum(sem_terms(model)) do semterm
73+
nparams_varonly = nobserved_vars(semterm)
74+
if MeanStruct(implied(semterm)) === HasMeanStruct
75+
nparams_varonly *= 2
76+
end
77+
return n_dp(loss(semterm)) - nparams_varonly
7878
end
79-
return n_dp(model) - nparams_varonly
8079
end
81-
82-
dof_varonly(model::SemEnsemble) = sum(dof_varonly, model.sems)

0 commit comments

Comments
 (0)