Fits a fully connected network to a pinn_problem() (or a problem from
pinn_ode()) by minimising
$$w_r L_{residual} + w_c L_{conditions} + w_d L_{data},$$
where each term is a mean squared error. Training runs epochs steps of
Adam and then, optionally, lbfgs_iter iterations of L-BFGS, which
often sharpens the solution considerably.
Usage
pinn_fit(
problem,
hidden = c(32, 32, 32),
activation = "tanh",
epochs = 5000,
lr = 0.001,
lr_unknown = NULL,
lbfgs_iter = 0,
n_collocation = 1000,
sampling = c("lhs", "uniform"),
resample_every = 0,
weights = c(residual = 1, conditions = 1, data = 1),
precision = c("float32", "float64"),
device = "cpu",
seed = NULL,
verbose = interactive(),
record_every = 10,
windows = 1
)Arguments
- problem
A
pinn_problem.Integer vector of hidden layer widths.
- activation
Activation function; see
pinn_mlp().- epochs
Number of Adam steps.
- lr
Adam learning rate for the network weights.
- lr_unknown
Adam learning rate for unknown parameters. Defaults to
10 * lr.- lbfgs_iter
Number of L-BFGS iterations after Adam (0 to skip).
- n_collocation
Number of points inside the domain where the residual is evaluated.
- sampling
"lhs"(Latin hypercube) or"uniform".- resample_every
Draw new collocation and condition points every this many Adam steps (0 keeps one fixed set). Resampling reduces overfitting to the training points.
- weights
Named numeric vector with loss weights
residual,conditionsanddata. Missing names default to 1.- precision
"float32"(default) or"float64". Double precision is slower but can help L-BFGS reach smaller losses.- device
A torch device, such as
"cpu","cuda"or"mps".- seed
Optional integer seed for reproducible sampling and weights.
- verbose
Print progress messages.
- record_every
Store the loss every this many steps.
- windows
Number of time windows for ODE problems; see Long time horizons.
Value
An object of class pinn_fit, with methods for predict(),
coef(), residuals(), plot() and summary().
Choosing settings
The defaults solve small problems on a CPU
in seconds to minutes. If the loss stalls, try more epochs, a wider or
deeper network, more collocation points, or lbfgs_iter = 500. For
parameter estimation, a larger lr_unknown lets the parameters move
faster than the network weights. Long time horizons are hard for
PINNs; shorter windows, or more data, help.
Long time horizons
PINNs often converge to a wrong, flat
solution when an ODE is solved over a long horizon with fast early
dynamics (for example an epidemic starting from a few cases). For
problems from pinn_ode(), windows = k splits the time range into
k equal windows and trains one network per window, each starting
from the end state of the previous one ("time marching"). This is
available for forward problems (no unknown parameters).
Pressing Esc (or Ctrl+C) stops training early and returns the model as
trained so far, with a warning. If the loss becomes NaN or infinite,
training stops and the weights with the lowest loss seen so far are
returned, also with a warning (and diverged = TRUE in the result).
Examples
# Exponential decay dy/dt = -k y
decay <- function(t, y, parms) list(-parms["k"] * y)
prob <- pinn_ode(decay, y0 = c(y = 1), times = seq(0, 5, by = 0.5),
parms = c(k = 0.5))
fit <- pinn_fit(prob, hidden = c(16, 16), epochs = 1500, seed = 1)
head(predict(fit))
#> time y
#> 1 0.0 1.0000000
#> 2 0.5 0.8026445
#> 3 1.0 0.6265597
#> 4 1.5 0.4774747
#> 5 2.0 0.3590537
#> 6 2.5 0.2713972