Вопрос или проблема
Я пытался решить задачу Навье-Стокса, следуя примеру из DeepXDE. Вот ссылка на код: https://deepxde.readthedocs.io/en/latest/demos/pinn_forward/Kovasznay.flow.html
Здесь есть часть, где используются 2 оптимизатора. Сначала ADAM (10k эпох)
model = dde.Model(data, net)
model.compile("adam", lr=1e-3)
losshistory, train_state = model.train(epochs = 10000)
и модель обучается как и ожидалось: показывая
Лучшая модель на шаге 10000:
потери на обучении: 4.77e-02
потери на тестировании: 4.59e-02
метрика тестирования: []
'train' заняло 51.353845 с
затем LBFGS (для дальнейшего улучшения сходимости).
dde.optimizers.config.set_LBFGS_options(maxiter= 3000)
model.compile("L-BFGS")
losshistory, train_state = model.train()
dde.saveplot(losshistory, train_state, issave=False, isplot=False)
Но после запуска кода LBFGS модель внезапно прекращает обучение, показывая:
Компиляция модели...
'compile' заняло 0.623285 с
Обучение модели...
Шаг Потери на обучении Потери на тестировании Метрика тестирования
10000 [3.30e-03, 4.83e-04, 2.34e-03, 1.48e-02, 5.65e-03, 1.50e-02, 5.13e-03, 1.01e-03, 1.56e-05] [2.73e-03, 4.61e-04, 1.11e-03, 1.48e-02, 5.65e-03, 1.50e-02, 5.13e-03, 1.01e-03, 1.56e-05] []
INFO:tensorflow:Оптимизация завершена с:
Сообщение: СХОДИМОСТЬ: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH
Значение целевой функции: 0.047715
Количество итераций: 1
Количество оценок функций: 31
10017 [3.30e-03, 4.83e-04, 2.34e-03, 1.48e-02, 5.65e-03, 1.50e-02, 5.13e-03, 1.01e-03, 1.56e-05] [2.73e-03, 4.61e-04, 1.11e-03, 1.48e-02, 5.65e-03, 1.50e-02, 5.13e-03, 1.01e-03, 1.56e-05] []
Лучшая модель на шаге 10000:
потери на обучении: 4.77e-02
потери на тестировании: 4.59e-02
метрика тестирования: []
'train' заняло 3.500850 с
Хотя я установил максимальное количество итераций равным 3000, модель останавливается на 10017! Я хочу, чтобы модель обучалась до 3000 итераций! Я пытался изменить значения ftol
и gtol
в опции LBFGS
, но безуспешно.
Может кто-то помочь мне исправить эту проблему? Я делюсь полным исходным кодом, чтобы вы могли воспроизвести проблему:
# %%
import tensorflow as tf
import deepxde as dde
import numpy as np
import matplotlib.pyplot as plt
# %%
rho = 1
mu = 1
u_in = 1
D = 1
L = 2
# %%
geom = dde.geometry.Rectangle(xmin=[-L/2, -D/2], xmax=[L/2, D/2])
# %%
def boundary_wall(X, on_boundary):
print("X", X)
print("on_boundary", on_boundary)
on_wall = np.logical_and(np.logical_or(np.isclose(X[1], -D/2, rtol=1e-05, atol=1e-08), np.isclose(X[1], D/2, rtol=1e-05, atol=1e-08)), on_boundary)
return on_wall
def boundary_inlet(X, on_boundary):
on_inlet = np.logical_and(np.isclose(X[0], -L/2, rtol=1e-05, atol=1e-08), on_boundary)
return on_inlet
def boundary_outlet(X, on_boundary):
on_outlet = np.logical_and(np.isclose(X[0], L/2, rtol=1e-05, atol=1e-08), on_boundary)
return on_outlet
# %%
bc_wall_u = dde.DirichletBC(geom, lambda X: 0., boundary_wall, component=0)
bc_wall_v = dde.DirichletBC(geom, lambda X: 0., boundary_wall, component=1)
bc_inlet_u = dde.DirichletBC(geom, lambda X: u_in, boundary_inlet, component=0)
bc_inlet_v = dde.DirichletBC(geom, lambda X: 0., boundary_inlet, component=1)
bc_outlet_p = dde.DirichletBC(geom, lambda X: 0., boundary_outlet, component=2)
bc_outlet_v = dde.DirichletBC(geom, lambda X: 0., boundary_outlet, component=1)
# %%
def pde(X, Y):
du_x = dde.grad.jacobian(Y, X, i=0, j=0)
du_y = dde.grad.jacobian(Y, X, i=0, j=1)
dv_x = dde.grad.jacobian(Y, X, i=1, j=0)
dv_y = dde.grad.jacobian(Y, X, i=1, j=1)
dp_x = dde.grad.jacobian(Y, X, i=2, j=0)
dp_y = dde.grad.jacobian(Y, X, i=2, j=1)
du_xx = dde.grad.hessian(Y, X, component=0, i=0, j=0)
du_yy = dde.grad.hessian(Y, X, component=0, i=1, j=1)
dv_xx = dde.grad.hessian(Y, X, component=1, i=0, j=0)
dv_yy = dde.grad.hessian(Y, X, component=1, i=1, j=1)
pde_u = Y[:,0:1] * du_x + Y[:,1:2] * du_y + 1/rho * dp_x - (mu/rho) * (du_xx + du_yy)
pde_v = Y[:,0:1] * dv_x + Y[:,1:2] * dv_y + 1/rho * dp_y - (mu/rho) * (dv_xx + dv_yy)
pde_cont = du_x + dv_y
return [pde_u, pde_v, pde_cont]
# %%
data = dde.data.PDE(geom,
pde,
[bc_wall_u, bc_wall_v, bc_inlet_u, bc_inlet_v, bc_outlet_p, bc_outlet_v],
num_domain = 2000,
num_boundary= 200,
num_test = 200)
# %%
plt.figure(figsize=(10, 8))
plt.scatter(data.train_x_all[:, 0], data.train_x_all[:, 1], s=0.5)
plt.xlabel("x")
plt.ylabel("y")
plt.show()
# %%
net = dde.maps.FNN([2] + [64]*5 + [3], "tanh", "Glorot uniform")
# %%
model = dde.Model(data, net)
model.compile("adam", lr=1e-3)
# %%
losshistory, train_state = model.train(epochs = 10000)
# %%
dde.optimizers.config.set_LBFGS_options(maxiter= 3000)
model.compile("L-BFGS")
losshistory, train_state = model.train()
dde.saveplot(losshistory, train_state, issave=False, isplot=False)
# %%
samples = geom.random_points(500000)
result = model.predict(samples)
# %%
color_legend = [[0, 1.5], [-0.3, 0.3], [0, 35]]
for idx in range(3):
plt.figure(figsize=(20, 4))
plt.scatter(samples[:, 0],
samples[:, 1],
c=result[:, idx],
cmap='jet',
s=2)
plt.colorbar()
plt.clim(color_legend[idx])
plt.xlim((0 - L/2, L - L/2))
plt.ylim((0 - D/2, D - D/2))
plt.tight_layout()
plt.show()
# %%
# %%
Ответ или решение
Проблема, с которой вы столкнулись при использовании оптимизатора L-BFGS в DeepXDE, связана с остановкой обучения до достижения заданного количества итераций. Сообщение: *"Конвергенция: REL_REDUCTION_OF_F <= FACTREPSMCH"** указывает на то, что алгоритм оптимизации достиг условия сходимости. Это означает, что изменения в функции потерь между итерациями стали достаточными для того, чтобы считать, что больше улучшать модель не имеет смысла.
Причины и решения
-
Условия сходимости:
- L-BFGS автоматически прекращает выполнение, когда изменения в функции потерь становятся ниже терпимости (
ftol
иgtol
), которые вы можете задать. Если функция потерь достаточно близка к оптимальному значению, и улучшения незначительны, алгоритм будет считать, что достигнута сходимость. - Вы можете попробовать уменьшить значения
ftol
иgtol
. Обычно, более строгие значения позволяют алгоритму продолжить работу дольше. Например:dde.optimizers.config.set_LBFGS_options(maxiter=3000, ftol=1e-9, gtol=1e-9)
- L-BFGS автоматически прекращает выполнение, когда изменения в функции потерь становятся ниже терпимости (
-
Параметры L-BFGS:
- Важно также проверить настройки
maxiter
,maxfun
иmaxls
. Например, увеличениеmaxfun
(максимальное количество вычислений функции) может позволить большее количество итераций. - Убедитесь, что размер пакета данных (batch size) и количество итераций достаточно велики для точного вычисления оберточной функции потерь.
- Важно также проверить настройки
-
Проблемы с моделью:
- Обратите внимание на структуру вашей нейронной сети. Возможно, некоторые слои слишком "передерживают" информацию и не позволяют достаточно быстро обновлять параметры. Попробуйте уменьшить количество узлов или слоев.
- Также стоит проверить, не застрянет ли ваша модель в локальном минимуме. Возможно, стоит добавить некоторые механизмы регуляризации.
-
Целевое значение функции потерь:
- Если ваша цель уже достигнута на этапе оптимизации ADAM, то L-BFGS может не иметь возможности для дальнейшего улучшения. Просмотрите ваши целевые функции и убедитесь, что они соответствуют вашим задачам.
-
Отладка и мониторинг:
- Для отслеживания изменений в функции потерь в процессе тренировки вы можете добавлять логирование на каждой итерации. Это позволит вам увидеть, как меняется функция потерь и даст больше информации о том, где может быть проблема.
Итог
Решение проблемы подразумевает тщательную настройку параметров и возможно пересмотр архитектуры вашей модели. Не упустите возможность экспериментировать с метриками сходимости и различными параметрами оптимизации. Удачи в вашей работе с L-BFGS в DeepXDE!