You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -31,11 +31,9 @@ function update!(targets::EvaluationTargets, implied::MyImplied, model::Abstract
31
31
end
32
32
```
33
33
34
-
As you can see, `update` gets passed as a first argument `targets`, which is telling us whether the objective value, gradient, and/or hessian are needed.
34
+
As you can see, `update!` gets passed as a first argument `targets`, which is telling us whether the objective value, gradient, and/or hessian are needed.
35
35
We can then use the functions `is_..._required` and conditional on what the optimizer needs, we can compute and store things we want to make available to the loss functions. For example, as we have seen in [Second example - maximum likelihood](@ref), the `RAM` implied type computes the model-implied covariance matrix and makes it available via `implied.Σ`.
36
36
37
-
38
-
39
37
Just as described in [Custom loss functions](@ref), you may define a constructor. Typically, this will depend on the `specification = ...` argument that can be a `ParameterTable` or a `RAMMatrices` object.
40
38
41
39
We implement an `ImpliedEmpty` type in our package that does nothing but serving as an `implied` field in case you are using a loss function that does not need any implied type at all. You may use it as a template for defining your own implied type, as it also shows how to handle the specification objects:
@@ -56,7 +54,7 @@ Empty placeholder for models that don't need an implied part.
56
54
- `specification`: either a `RAMMatrices` or `ParameterTable` object
57
55
58
56
# Examples
59
-
A multigroup model with ridge regularization could be specified as a `SemEnsemble` with one
57
+
A multigroup model with ridge regularization could be specified as a `Sem` with one
60
58
model per group and an additional model with `ImpliedEmpty` and `SemRidge` for the regularization part.
The function `evaluate!` recognizes by the types of the arguments `objective`, `gradient` and `hessian` whether it should compute the objective value, gradient or hessian of the model w.r.t. the parameters.
@@ -98,7 +98,7 @@ function evaluate!(objective, gradient, hessian::Nothing, ridge::Ridge, model::A
98
98
gradient[ridge.I] .= 2 * ridge.α * par[ridge.I]
99
99
end
100
100
# compute objective
101
-
if !isnothing(objective)
101
+
if !isnothing(objective)
102
102
return ridge.α * sum(i -> par[i]^2, ridge.I)
103
103
end
104
104
end
@@ -166,17 +166,6 @@ end
166
166
167
167
## Additional functionality
168
168
169
-
### Update observed data
170
-
171
-
If you are planing a simulation study where you have to fit the **same model** to many **different datasets**, it is computationally beneficial to not build the whole model completely new everytime you change your data.
172
-
Therefore, we provide a function to update the data of your model, `replace_observed(model(semfit); data = new_data)`. However, we can not know beforehand in what way your loss function depends on the specific datasets. The solution is to provide a method for `update_observed`. Since `Ridge` does not depend on the data at all, this is quite easy:
The abstract supertype for all models is `AbstractSem`, which has two subtypes, `AbstractSemSingle{O, I, L}` and `AbstractSemCollection`. Currently, there are 2 subtypes of `AbstractSemSingle`: `Sem`, `SemFiniteDiff`. All subtypes of `AbstractSemSingle` should have at least observed, implied, loss and optimizer fields, and share their types (`{O, I, L}`) with the parametric abstract supertype. For example, the `SemFiniteDiff` type is implemented as
3
+
The abstract supertype for all models is [`AbstractSem`](@ref). Currently, there are 2 concrete subtypes:
4
+
`Sem{L <: Tuple}` and `SemFiniteDiff{S <: AbstractSem}`.
5
+
A `Sem` model holds a tuple of `LossTerm`s (each wrapping an `AbstractLoss`) and a vector of parameter labels. Both single-group and multigroup models are represented as `Sem`.
6
+
7
+
`SemFiniteDiff` wraps any `AbstractSem` and substitutes dedicated gradient/hessian evaluation with finite difference approximation:
4
8
5
9
```julia
6
-
struct SemFiniteDiff{O <:SemObserved, I <:SemImplied, L <:SemLoss} <:
Copy file name to clipboardExpand all lines: docs/src/performance/mixed_differentiation.md
+8-10Lines changed: 8 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,22 +2,20 @@
2
2
3
3
This way of specifying our model is not ideal, however, because now also the maximum likelihood loss function lives inside a `SemFiniteDiff` model, and this means even though we have defined analytical gradients for it, we do not make use of them.
4
4
5
-
A more efficient way is therefore to specify our model as an ensemble model:
5
+
A more efficient way is therefore to specify our model as a combined model with multiple loss terms:
So you just construct the individual models (however you like) and pass them to `SemEnsemble`.
22
-
You may also pass a vector of weigths to `SemEnsemble`. By default, those are set to ``N_{model}/N_{total}``, i.e. each model is weighted by the number of observations in it's data (which matches the formula for multigroup models).
38
+
`Sem` support assigning unique identifier to each loss term, which is essential for complex multi-term model.
39
+
The syntax is `id => loss`, or `id => loss => weight`:
23
40
24
-
Multigroup models can also be specified via the graph interface; for an example, see [Multigroup models](@ref).
Copy file name to clipboardExpand all lines: docs/src/tutorials/collection/multigroup.md
+9-8Lines changed: 9 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,19 +4,20 @@
4
4
using StructuralEquationModels
5
5
```
6
6
7
-
As an example, we will fit the model from [the `lavaan` tutorial](https://lavaan.ugent.be/tutorial/groups.html) with loadings constrained to equality across groups.
7
+
As an example, we will fit the model from [the `lavaan` tutorial](https://lavaan.ugent.be/tutorial/groups.html)
8
+
with loadings constrained to equality across groups.
8
9
9
-
We first load the example data.
10
+
We first load the example data.
10
11
We have to make sure that the column indicating the group (here called `school`) is a vector of `Symbol`s, not strings - so we convert it.
0 commit comments