Models with mean structures
To make use of mean structures in your model, you have to
- Specify your model with a mean structure. The sections Graph interface and RAMMatrices interface both explain how this works.
- Build your model with a meanstructure. We explain how that works in the following.
Lets say you specified A first model as a graph with a meanstructure:
using StructuralEquationModels
observed_vars = [:x1, :x2, :x3, :y1, :y2, :y3, :y4, :y5, :y6, :y7, :y8]
latent_vars = [:ind60, :dem60, :dem65]
graph = @StenoGraph begin
# loadings
ind60 → fixed(1)*x1 + x2 + x3
dem60 → fixed(1)*y1 + y2 + y3 + y4
dem65 → fixed(1)*y5 + y6 + y7 + y8
# latent regressions
dem60 ← ind60
dem65 ← dem60
dem65 ← ind60
# variances
_(observed_vars) ↔ _(observed_vars)
_(latent_vars) ↔ _(latent_vars)
# covariances
y1 ↔ y5
y2 ↔ y4 + y6
y3 ↔ y7
y8 ↔ y4 + y6
# means
Symbol("1") → _(observed_vars)
end
partable = ParameterTable(
latent_vars = latent_vars,
observed_vars = observed_vars,
graph = graph)
that is, all observed variable means are estimated freely.
To build the model with a meanstructure, we proceed as usual, but pass the argument meanstructure = true
. For our example,
data = example_data("political_democracy")
model = Sem(
specification = partable,
data = data,
meanstructure = true
)
sem_fit(model)
Fitted Structural Equation Model
===============================================
--------------------- Model -------------------
Structural Equation Model
- Loss Functions
SemML
- Fields
observed: SemObservedData
imply: RAM
optimizer: SemOptimizerOptim
------------- Optimization result -------------
* Status: success
* Candidate solution
Final objective value: 2.120543e+01
* Found with
Algorithm: L-BFGS
* Convergence measures
|x - x'| = 4.36e-05 ≰ 1.5e-08
|x - x'|/|x'| = 5.84e-06 ≰ 0.0e+00
|f(x) - f(x')| = 1.86e-09 ≰ 0.0e+00
|f(x) - f(x')|/|f(x')| = 8.77e-11 ≤ 1.0e-10
|g(x)| = 9.70e-05 ≰ 1.0e-08
* Work counters
Seconds run: 0 (vs limit Inf)
Iterations: 187
f(x) calls: 558
∇f(x) calls: 558
If we build the model by parts, we have to pass the meanstructure = true
argument to every part that requires it (when in doubt, simply comsult the documentation for the respective part).
For our example,
observed = SemObservedData(specification = partable, data = data, meanstructure = true)
imply_ram = RAM(specification = partable, meanstructure = true)
ml = SemML(observed = observed, meanstructure = true)
model = Sem(observed, imply_ram, SemLoss(ml), SemOptimizerOptim())
sem_fit(model)
Fitted Structural Equation Model
===============================================
--------------------- Model -------------------
Structural Equation Model
- Loss Functions
SemML
- Fields
observed: SemObservedData
imply: RAM
optimizer: SemOptimizerOptim
------------- Optimization result -------------
* Status: success
* Candidate solution
Final objective value: 2.120543e+01
* Found with
Algorithm: L-BFGS
* Convergence measures
|x - x'| = 4.36e-05 ≰ 1.5e-08
|x - x'|/|x'| = 5.84e-06 ≰ 0.0e+00
|f(x) - f(x')| = 1.86e-09 ≰ 0.0e+00
|f(x) - f(x')|/|f(x')| = 8.77e-11 ≤ 1.0e-10
|g(x)| = 9.70e-05 ≰ 1.0e-08
* Work counters
Seconds run: 0 (vs limit Inf)
Iterations: 187
f(x) calls: 558
∇f(x) calls: 558