import os
import time
import numpy as np
import torch
from matplotlib import pyplot as plt, gridspec
from torch import nn
from torch.autograd import Variable
from tqdm import tqdm, trange
from pyDOE import lhs
# import h5py
# import scipy.io
import argparse
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
seed = 1234
torch.set_default_dtype(torch.float)
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
np.random.seed(seed)
use_gpu = torch.cuda.is_available()
print('GPU:', use_gpu)
parser = argparse.ArgumentParser()
parser.add_argument('--hid_layers', help='number of hidden layers', type=int, default=6)
parser.add_argument('--hid_neurons', help='number of neurons per layer', type=int, default=128)
.
.
.
parser.add_argument('--adam_lr', help='learning rate of adam', type=float, default=0.001)
parser.add_argument('--lbfgs_lr', help='learning rate of lbfgs', type=float, default=0.5)
.
.
.
def generate_layers # 如 [ 2 128 128 128 128 128 q+1]
def random_fun # 随机生成可移动内部点,比如离散就随机生成维度为(1000,2)的内部点,而连续就是(1000,3)
def is_cuda # 将张量(Tensor)从CPU内存移动到GPU内存
def np_tensor # 将传入的 data_var(预期是一个NumPy数组)转换为一个PyTorch张量(Tensor),并确保这个张量的数据类型是浮点数
def np_to_tensor_to_cuda # 先把参数从numpy变成tensor再将Tensor从CPU内存移动到GPU内存
def hstack_data(var1, var2):
var_hstack = np.hstack((var1.flatten(order='F')[:, None],
var2.flatten(order='F')[:, None]))
return var_hstack
def get_col_data(lb, ub, num_x, num_y)
def get_bc_data(num_x, num_y, x, y)
def get_test_data(x, y)
def data_generate(x, y, t, lb, ub, num_x, num_y):
x_test = get_test_data(x, y)
(xyt_b_bot_meshgrid_train, xyt_b_top_meshgrid_train, xyt_b_left_meshgrid_train,
xyt_b_right_meshgrid_train) = get_bc_data(num_x, num_y, x, y)
x_f_N = get_col_data(lb, ub, num_x, num_y)
return (x_test, xyt_b_bot_meshgrid_train, xyt_b_top_meshgrid_train, xyt_b_left_meshgrid_train,
xyt_b_right_meshgrid_train, x_f_N)
class Net(nn.Module):
def __init__(self, layers):
def forward(self, x):
def __init__
def train_U(self, x):
return self.net(x)
def predict_U(self, x):
return self.train_U(x)[:, self.q:(self.q+1)] # h
即take the negative logarithm of the likelihood function to get the negative log-likelihood as the desired loss function
L
=
e
−
s
f
ϕ
L
f
ϕ
+
e
−
s
f
μ
L
f
μ
+
e
−
s
b
ϕ
L
b
ϕ
+
e
−
s
b
μ
L
b
μ
+
s
f
ϕ
+
s
f
μ
+
s
b
ϕ
+
s
b
μ
def likelihood_loss(self, loss_f_h, loss_b_h, loss_f_mu, loss_b_mu):
loss = (torch.exp(-self.x_f_s_h) * loss_f_h.detach() + self.x_f_s_h
+ torch.exp(-self.x_b_s_h) * loss_b_h.detach() + self.x_b_s_h
+ torch.exp(-self.x_f_s_mu) * loss_f_mu.detach() + self.x_f_s_mu
+ torch.exp(-self.x_b_s_mu) * loss_b_mu.detach() + self.x_b_s_mu)
return loss
即比likelihood的loss少加自适应权重
s
f
ϕ
+
s
f
μ
+
s
b
ϕ
+
s
b
μ
s_{f_{\phi}} + s_{f_{\mu}} + s_{b_{\phi}} + s_{b_{\mu}}
sfϕ+sfμ+sbϕ+sbμ,loss function如下:
L
=
e
−
s
f
ϕ
L
f
ϕ
+
e
−
s
f
μ
L
f
μ
+
e
−
s
b
ϕ
L
b
ϕ
+
e
−
s
b
μ
L
b
μ
def true_loss(self, loss_f_h, loss_b_h, loss_f_mu, loss_b_mu):
true_loss_value = (torch.exp(-self.x_f_s_h.detach()) * loss_f_h + torch.exp(-self.x_b_s_h.detach()) * loss_b_h
+ torch.exp(-self.x_f_s_mu.detach()) * loss_f_mu + torch.exp(-self.x_b_s_mu.detach()) * loss_b_mu)
return true_loss_value
def ub_x_h(self, boundary_data)
def ub_y_h(self, boundary_data)
def ub_x_mu(self, boundary_data)
def ub_y_mu(self, boundary_data)
def get_b_pred(self, boundary_data)
可移动到Model的外面
@staticmethod
def partial_derivative_phi(phi)
这里只构造了边界的loss,内部点的在epoch_loss里面直接构造了
def loss_boundary_h(self)
def loss_boundary_mu(self)
这一步应该可以移到外面
def draw_loss_f(self, current_t_num, x_f, U00, U11)
def epoch_loss(self)
这里先跑一下epoch_loss得到 L b ϕ \mathcal{L}_{b_{\phi}} Lbϕ, L b μ \mathcal{L}_{b_{\mu}} Lbμ, L f ϕ \mathcal{L}_{f_{\phi}} Lfϕ, L f μ \mathcal{L}_{f_{\mu}} Lfμ,然后把 L b ϕ \mathcal{L}_{b_{\phi}} Lbϕ, L b μ \mathcal{L}_{b_{\mu}} Lbμ, L f ϕ \mathcal{L}_{f_{\phi}} Lfϕ, L f μ \mathcal{L}_{f_{\mu}} Lfμ当作true_loss的输入,得到 L = e − s f ϕ L f ϕ + e − s f μ L f μ + e − s b ϕ L b ϕ + e − s b μ L b μ \mathcal{L}= e^{-s_{f_{\phi}}} \mathcal{L}_{f_{\phi}}+e^{-s_{f_{\mu}}} \mathcal{L}_{f_{\mu}} +e^{-s_{b_{\phi}}} \mathcal{L}_{b_{\phi}}+e^{-s_{b_{\mu}}} \mathcal{L}_{b_{\mu}} L=e−sfϕLfϕ+e−sfμLfμ+e−sbϕLbϕ+e−sbμLbμ
def LBFGS_epoch_loss(self)
这一步应该可以移到外面
def draw_evaluate(self, x_test, pred, exact)
这一个看看能不能移动到Model的外面
def move_some_movable_points_to_fixed_points(self)
run_AM: 决定选点
run_AM_AW1:likelihood_loss在这,决定选点
让自适应权重变成能够记录梯度属性的参数
%%%%%%%%%%%%%%%%%%%%%%%%%
创建AM的for loop
2.1 创建三个不同的优化器(L-BFGS的优化器,ADAM的优化器,自适应权重的优化器)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2.2 创建一个ADAM的for loop
2.2.1 通过epoch_loss得到
L
b
ϕ
\mathcal{L}_{b_{\phi}}
Lbϕ,
L
b
μ
\mathcal{L}_{b_{\mu}}
Lbμ,
L
f
ϕ
\mathcal{L}_{f_{\phi}}
Lfϕ,
L
f
μ
\mathcal{L}_{f_{\mu}}
Lfμ
-----------------------------------------------------------------------------
2.2.2 optimizer_adam.zero_grad() #使用optimizer_adam优化器更新
θ
\theta
θ之前,先清除之前的梯度信息
2.2.3 通过true_loss(
L
b
ϕ
\mathcal{L}_{b_{\phi}}
Lbϕ,
L
b
μ
\mathcal{L}_{b_{\mu}}
Lbμ,
L
f
ϕ
\mathcal{L}_{f_{\phi}}
Lfϕ,
L
f
μ
\mathcal{L}_{f_{\mu}}
Lfμ)得
L
=
e
−
s
f
ϕ
L
f
ϕ
+
e
−
s
f
μ
L
f
μ
+
e
−
s
b
ϕ
L
b
ϕ
+
e
−
s
b
μ
L
b
μ
\mathcal{L}= e^{-s_{f_{\phi}}} \mathcal{L}_{f_{\phi}}+e^{-s_{f_{\mu}}} \mathcal{L}_{f_{\mu}} +e^{-s_{b_{\phi}}} \mathcal{L}_{b_{\phi}}+e^{-s_{b_{\mu}}} \mathcal{L}_{b_{\mu}}
L=e−sfϕLfϕ+e−sfμLfμ+e−sbϕLbϕ+e−sbμLbμ
2.2.4 loss.backward() #计算2.2.3的
L
\mathcal{L}
L关于模型参数的梯度
2.2.5 optimizer_adam.step() #使用2.2.4计算出的梯度来更新网络模型参数
θ
\theta
θ
-------------------------------------------------------------------------------
2.2.6 optimizer_adam_weight.zero_grad() #使用optimizer_adam_weight优化器更新
s
f
ϕ
,
s
f
μ
,
s
b
ϕ
,
s
b
μ
s_{f_{\phi}},s_{f_{\mu}},s_{b_{\phi}},s_{b_{\mu}}
sfϕ,sfμ,sbϕ,sbμ之前,先清除之前的梯度信息
2.2.7 通过likelihood_loss(
L
b
ϕ
\mathcal{L}_{b_{\phi}}
Lbϕ,
L
b
μ
\mathcal{L}_{b_{\mu}}
Lbμ,
L
f
ϕ
\mathcal{L}_{f_{\phi}}
Lfϕ,
L
f
μ
\mathcal{L}_{f_{\mu}}
Lfμ)得
L
=
e
−
s
f
ϕ
L
f
ϕ
+
e
−
s
f
μ
L
f
μ
+
e
−
s
b
ϕ
L
b
ϕ
+
e
−
s
b
μ
L
b
μ
+
s
f
ϕ
+
s
f
μ
+
s
b
ϕ
+
s
b
μ
\mathcal{L}= e^{-s_{f_{\phi}}} \mathcal{L}_{f_{\phi}}+e^{-s_{f_{\mu}}} \mathcal{L}_{f_{\mu}} +e^{-s_{b_{\phi}}} \mathcal{L}_{b_{\phi}}+e^{-s_{b_{\mu}}} \mathcal{L}_{b_{\mu}} + s_{f_{\phi}} + s_{f_{\mu}} + s_{b_{\phi}} + s_{b_{\mu}}
L=e−sfϕLfϕ+e−sfμLfμ+e−sbϕLbϕ+e−sbμLbμ+sfϕ+sfμ+sbϕ+sbμ
2.2.8 loss.backward() #计算2.2.7的
L
\mathcal{L}
L关于模型参数的梯度
2.2.9 optimizer_adam_weight.step() #使用2.2.8计算出的梯度来更新自适应权重
s
f
ϕ
,
s
f
μ
,
s
b
ϕ
,
s
b
μ
s_{f_{\phi}},s_{f_{\mu}},s_{b_{\phi}},s_{b_{\mu}}
sfϕ,sfμ,sbϕ,sbμ
(即后面继续回到第2.2步开始新的迭代直至达到adam_iter的数)
2.3 打印 print(‘Adam done!’)
2.4 self.optimizer_LBFGS.step(self.LBFGS_epoch_loss)
2.5 打印 print(‘LBFGS done!’)
2.6 根据p(x)改变可移动内部点
(即后面继续回到第2步开始新的一轮)
def run_baseline(self)
def run_AM(self, current_t_num)
def run_AM_AW1(self, current_t_num)
这里生成可移动的内部点,定义自适应权重 s f ϕ s_{f_{\phi}} sfϕ, s b ϕ s_{b_{\phi}} sbϕ, s f μ s_{f_{\mu}} sfμ, s b μ s_{b_{\mu}} sbμ
def train(self, current_t_num)
又回到外面的一些函数
def is_in_red_square(x_f)
def get_initial_h(x_f)
def uf_x_h(h, col_pts)
def uf_y_h(h, col_pts)
def x_f_loss_fun_h(x_f, train_U)
def x_f_loss_fun_mu(x_f, train_U)
def draw_exact_count(AM_count, current_t_num)
def draw_pred_q_count(AM_count, current_t_num)
def draw_pred_q_current(time_current)
def draw_pred_q()
def draw_current_exact(pic_num)
def draw_exact()
def draw_exact_points_count(AM_count, points, N_points=None, show_exact=False)
def draw_epoch_loss_count(AM_count, current_t_num)
def draw_exact_points_current(current_t_num, points, N_points=None, show_exact=False)
def draw_exact_points(points, N_points=None, show_exact=False)
def draw_epoch_loss_current(loss_current_num)
def draw_epoch_loss()
def draw_epoch_w()
def define_lb_ub(initial_condition_type)
参数,train