| net-controls | R Documentation |
netest(), netdx(), and control.net() pass control
settings to the ergm and tergm packages, which estimate and
simulate the network model, through their set.control.ergm,
set.control.tergm, and set.control.ergm.ego arguments. This
page lists the control function that each argument takes, the
defaults that EpiModel sets, how to use netdx() to find the
stage that needs adjusting, and the settings most often changed.
The worked examples are in the Improving Model Estimation and Simulation appendix of the Network Modeling for Epidemics course materials, which covers full STERGM estimation for short partnership durations, the estimation settings for large and slow ERGM fits, and the simulation settings for diagnostics and epidemic models.
Each argument takes an object built by a specific control function. Passing an object from another one stops with an error that names the right function.
Estimation in netest():
set.control.ergm takes ergm::control.ergm(), for the ERGM fit with
the edges dissolution approximation (edapprox = TRUE).
set.control.ergm.ego takes ergm.ego::control.ergm.ego(), for the
same fit when nw is an egor object.
set.control.tergm takes tergm::control.tergm(), for the full STERGM
fit (edapprox = FALSE).
Simulation in netdx() and control.net():
set.control.ergm takes ergm::control.simulate.formula(), for the
cross-sectional network that the dynamic simulation starts from, and
for the static diagnostics of netdx(dynamic = FALSE). It is used only
for fits with edapprox = TRUE; a full STERGM fit starts from the
network saved by netest().
set.control.tergm takes tergm::control.simulate.formula.tergm(),
for each time step of the dynamic network simulation, both in the
diagnostics and in the epidemic model.
In a model with several network layers, control.net() takes one control
object per layer through multilayer().
Three defaults differ from those of the control functions themselves:
set.control.tergm in netest() is
control.tergm(MCMC.maxchanges = .Machine$integer.max).
set.control.tergm in netdx() and control.net() is
control.simulate.formula.tergm(MCMC.maxchanges = .Machine$integer.max).
This raises the number of network changes that tergm can record in one
simulation above its default limit of 1e6, which a long netdx() run
can exceed.
set.control.ergm in control.net() is
control.simulate.formula(MCMC.burnin = 2e5), a longer burn-in for the
starting network than the ergm default.
A control object passed to one of these arguments replaces the default as a whole, not only the settings it names, so restate these settings alongside any others (see the examples).
An error or a stalled fit in netest() calls for the estimation settings
below. When the fit succeeds but the dynamic diagnostics of netdx() miss
the formation targets, the cause can lie in the simulation, in the edges
dissolution approximation, or in the cross-sectional fit:
The per-step burn-in of the simulation. By default, tergm sets
the number of proposals in each time step adaptively. With short
partnership durations it can end a time step before the network has
replaced the partnerships that dissolved, so statistics such as the edge
count settle below their targets. This applies to fits with and without
the approximation. Setting MCMC.burnin.min and MCMC.burnin.max in
set.control.tergm to the same value (such as 1e4) fixes the number of
proposals per time step and is quick to try.
The edges dissolution approximation. For fits with
edapprox = TRUE, run static diagnostics with netdx(dynamic = FALSE).
If they are on target but the dynamic diagnostics remain off with a
fixed per-step burn-in, the approximation is the likely cause. It loses
accuracy when many partnerships form and dissolve at each time step,
that is, when durations are short or density is high. Fit the full
STERGM with edapprox = FALSE, or redefine the time step as a shorter
unit so that durations span more time steps, rescaling every other
time-based parameter of the model to match.
The cross-sectional fit. If the static diagnostics are also off, the
ERGM fit has not reached the targets, or the static simulation has not
moved far enough from its starting network. On a large network, raise
MCMC.burnin and MCMC.interval in the set.control.ergm of netdx()
before changing the estimation settings of netest().
Read the Pct Diff column of print.netdx() alongside the Z Score. The
standard error behind the Z score shrinks with the effective sample size, so
many static draws can make a difference of a fraction of a percent
statistically significant, while the autocorrelation between time steps
keeps the effective sample size of a dynamic simulation, and so its Z
scores, smaller.
The simulation settings that bring the netdx() diagnostics on target
belong in control.net() as well: the epidemic simulation steps the network
forward with the same tergm simulation, so without them it runs on the
network that the diagnostics flagged.
The control functions have many arguments, of which a few account for most adjustments in practice. Their help pages document the rest.
For the ERGM fit, in ergm::control.ergm():
MCMLE.maxit: the maximum number of MCMLE iterations. Raise it for a fit
that is still moving toward the targets when it stops.
MCMC.samplesize, MCMC.interval, and MCMC.burnin: the size,
spacing, and burn-in of the MCMC sample drawn at each iteration. Larger
networks generally need a longer interval and burn-in. By default ergm
extends the sample until it reaches the effective size set by
MCMLE.effectiveSize; setting MCMLE.effectiveSize = NULL holds it at
MCMC.samplesize draws, which bounds the time per iteration.
SAN.nsteps.times and SAN.maxit: simulated annealing (SAN) builds the
starting network that matches the target statistics. SAN.nsteps.times
scales the total number of SAN proposals, and SAN.maxit divides them
into that many runs. Raise SAN.nsteps.times when SAN does not reach the
targets.
MCMC.prop: hints for the MCMC proposal (see ergm::ergmHint). When
most ties fall within a few cells of a mixing matrix, a stratified
proposal such as ~strat(attr = ~age.grp) + sparse stops the sampler
from spending its proposals on cells that hold few or no ties. Listing
any hint replaces the default ones, so list sparse as well.
MCMC.maxedges: the maximum number of edges in a sampled network,
unlimited by default. A finite value makes a fit that wanders into dense,
degenerate networks stop with an error rather than run for hours.
MCMLE.steplength with MCMLE.steplength.margin = NULL: a fixed step
length below 1 (such as 0.5) keeps the first iterations of a hard fit
from overshooting. With the default margin, MCMLE.steplength is only
the maximum step length.
parallel: the number of cores across which the MCMC sample is drawn.
For the full STERGM fit, in tergm::control.tergm():
EGMME.MCMC.burnin.min and EGMME.MCMC.burnin.max: the number of
proposals per time step during estimation, set adaptively by default.
Setting both to the same value fixes it, which can stabilize a fit that
otherwise fails. In the course examples, 1e4 works for a network of
1,000 nodes, and larger networks may need a value on the order of the
network size. Fix the per-step burn-in of the simulation to the same
value.
SAN.nsteps.times, SAN.maxit, and MCMC.prop act as in
ergm::control.ergm().
For the dynamic simulation, in tergm::control.simulate.formula.tergm():
MCMC.burnin.min and MCMC.burnin.max: the number of proposals per
time step. Setting both to the same value fixes it, as described above.
tergm has no MCMC.interval; this pair takes its place.
MCMC.maxchanges: restate .Machine$integer.max when passing any other
setting.
MCMC.prop: the default, ~discord + sparse, proposes a share of its
toggles (set by MCMC.prop.args = list(discordance_fraction = ), 0.5 by
default) on dyads that have already changed within the time step. For
strongly structured mixing, add a strat() hint as in estimation and
keep discord and sparse in the formula.
For the cross-sectional simulation, in ergm::control.simulate.formula():
MCMC.burnin and MCMC.interval: the burn-in before the starting
network (or the first static draw) and the spacing between static draws.
Krivitsky PN, Hunter DR, Morris M, Klumb C. ergm 4: New Features for Analyzing Exponential-Family Random Graph Models. Journal of Statistical Software. 2023; 105(6): 1-44. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.18637/jss.v105.i06")}.
Krivitsky PN, Handcock MS. A Separable Model for Dynamic Networks. Journal of the Royal Statistical Society, Series B. 2014; 76(1): 29-46.
netest(), netdx(), and control.net(), whose arguments these
settings are passed through; print.netdx() and plot.netdx() for
reading the diagnostics.
nw <- network_initialize(n = 100)
formation <- ~edges + concurrent
target.stats <- c(50, 20)
coef.diss <- dissolution_coefs(dissolution = ~offset(edges), duration = 10)
est <- netest(nw, formation, target.stats, coef.diss)
# Fix the number of proposals per time step in the dynamic simulation,
# restating the MCMC.maxchanges default that EpiModel sets
sim.control <- control.simulate.formula.tergm(
MCMC.burnin.min = 1e4,
MCMC.burnin.max = 1e4,
MCMC.maxchanges = .Machine$integer.max
)
dx <- netdx(est, nsims = 2, nsteps = 100, set.control.tergm = sim.control,
verbose = FALSE)
dx
# Pass the same settings to the epidemic simulation
param <- param.net(inf.prob = 0.3, act.rate = 1)
init <- init.net(i.num = 10)
control <- control.net(type = "SI", nsims = 1, nsteps = 50,
set.control.tergm = sim.control, verbose = FALSE)
sim <- netsim(est, param, init, control)
## Not run:
# Estimation settings for a larger or slower ERGM fit
est <- netest(nw, formation, target.stats, coef.diss,
set.control.ergm = control.ergm(MCMLE.maxit = 500,
MCMC.samplesize = 1e4,
MCMC.interval = 5e3,
SAN.nsteps.times = 16,
parallel = 4))
# Full STERGM fit with a fixed number of proposals per time step
est <- netest(nw, formation, target.stats, coef.diss, edapprox = FALSE,
set.control.tergm = control.tergm(
EGMME.MCMC.burnin.min = 1e4,
EGMME.MCMC.burnin.max = 1e4,
MCMC.maxchanges = .Machine$integer.max
))
dx <- netdx(est, nsims = 5, nsteps = 500, set.control.tergm = sim.control)
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.