lululxvi / deepxde

A library for scientific machine learning and physics-informed learning
https://deepxde.readthedocs.io
GNU Lesser General Public License v2.1
2.76k stars 760 forks source link

Error reported when running inverse problem #637

Closed ZSTanone closed 2 years ago

ZSTanone commented 2 years ago

Hi Dr.Lu, @lululxvi When I try to solve the problem of parameter identification, the following error occurs image

The error type is RuntimeError: Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad(). Specify retain_graph=True if you need to backward through the graph a second time or if you need to access saved tensors after calling backward.

The strange thing is that when I have tried to solve some small number of parameter recognition problems with this program before, is this error related to the recognizability of the parameters?

lululxvi commented 2 years ago

Can you successfully run the codes of the examples? If so, then it should be a problem of your code.

ZSTanone commented 2 years ago

Can you successfully run the codes of the examples? If so, then it should be a problem of your code.

When I choose to identify the two parameters in odes, the program runs without problems, just that the result of identification is not very good. However, when I increase the number of parameters to be recognized to three, this error occurs and the program does not run

ZSTanone commented 2 years ago

` f = dde.Variable(0.1) kd = dde.Variable(0.0)

kp_ = dde.Variable(1.0)

var_list_ = [f_, kd_]

# f = 0.6
f = f_
# kd = 1e-5
kd = kd_
kp = 1600
# kp = kp_ * 1e3
ktc = ktd = 1e+8
kt = ktc + ktd

def ode(t, y):
    M = y[:, 0:1]
    I = y[:, 1:2]
    am0 = y[:, 2:3]
    dm0 = y[:, 3:4]
    am1 = y[:, 4:5]
    total = y[:, 5:6]

    dMdt = dde.grad.jacobian(y, t, i=0, j=0)
    dIdt = dde.grad.jacobian(y, t, i=1, j=0)
    dam0dt = dde.grad.jacobian(y, t, i=2, j=0)
    ddm0dt = dde.grad.jacobian(y, t, i=3, j=0)
    dam1dt = dde.grad.jacobian(y, t, i=4, j=0)
    dtotaldt = dde.grad.jacobian(y, t, i=5, j=0)

    return [
        dMdt + kp * M * am0,
        dIdt + kd * I,
        dam0dt - 2 * f * kd * I + am0 * kt * am0,
        ddm0dt - 2 * f * kd * I + 0.5 * ktc * am0 * am0,
        dam1dt - kp * M * am0 + kt * am0 * am1,
        dtotaldt - kp * M * (am0 + 2 * am1) - ktc * am1 * am1,
    ]

geom = dde.geometry.TimeDomain(data_t[0, 0], data_t[-1, 0])

n = len(data_t)

idx = np.append(
    np.random.choice(np.arange(1, n - 1), size=300, replace=False), [0, n - 1]  # [0,n-1] 表示开头和末尾
)

# observer_M = dde.PointSetBC(data_t[idx], data_M[idx], component=0)
observer_I = dde.PointSetBC(data_t[idx], data_I[idx], component=1)
observer_am0 = dde.PointSetBC(data_t[idx], data_am0[idx], component=2)

data = dde.data.PDE(geom, ode, [observer_I, observer_am0], anchors=data_t)

layer_size = [1] + [150] * 5 + [6]
activation = "swish"
initializer = "Glorot normal"
net = dde.nn.FNN(layer_size, activation, initializer)

def input_transform(t):
    t = t / 54000
    return t
net.apply_feature_transform(input_transform)

def output_transform(t, y):
    idx = 900
    k = (data_y[idx] - data_y[0]) / (data_t[idx] - data_t[0])
    b = (data_t[idx] * data_y[0] - data_t[0] * data_y[idx]) / (
            data_t[idx] - data_t[0]
    )
    linear = torch.as_tensor(k) * t + torch.as_tensor(b)
    factor = torch.tanh(t) * torch.tanh(idx - t)
    return linear + factor * torch.Tensor([1, 0.1, 1e-8, 1e-2, 1e-5, 1e2]) * y

net.apply_output_transform(output_transform)
model = dde.Model(data, net)

" 2 steps training "

first_train = 5000
callback_period = 1000
max_epochs = 50000

model.compile("adam", lr=1e-4, loss_weights=[0, 0, 0, 0, 0, 0, 1e7, 1e20])
model.train(epochs=first_train, display_every=1000)
model.compile(
    "adam",
    lr=1e-4,
    loss_weights=[1e8, 1e10, 1e13, 1e12, 1e13, 10, 1e7, 1e20],
    external_trainable_variables=var_list_,
)

variablefilename = "Mom_pred.dat"
variable = dde.callbacks.VariableValue(
    var_list_, period=callback_period, filename=variablefilename, precision=3
)
losshistory, train_state = model.train(
    epochs=max_epochs, display_every=1000, callbacks=[variable]
)

dde.saveplot(losshistory, train_state, issave=True, isplot=True)

` Here are the major part of my code ,I will provide my full code if needed

lululxvi commented 2 years ago

The issue is kp = kp_ * 1e3. See examples at https://github.com/lu-group/sbinn for how to transform the variable.

ZSTanone commented 2 years ago

The issue is kp = kp_ * 1e3. See examples at https://github.com/lu-group/sbinn for how to transform the variable.

Much appreciate for your reply!!!!

ZSTanone commented 2 years ago

The problem get solved when I moved the code which defines the parameters inside def ode (t,y) ,thanks a lot @lululxvi