Files
2026-07-13 12:40:42 +08:00

150 lines
4.7 KiB
Python

# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import paddle
from paddle.distributed.fleet import auto
from paddle.incubate.autograd import Hessian
np.random.seed(1234)
paddle.seed(1234)
class FCNet:
def __init__(self, num_ins, num_outs, num_layers, hidden_size):
self.num_ins = num_ins
self.num_outs = num_outs
self.num_layers = num_layers
self.hidden_size = hidden_size
self.activation = paddle.tanh
self.weights = []
self.biases = []
for i in range(self.num_layers):
if i == 0:
lsize = self.num_ins
rsize = self.hidden_size
elif i == (self.num_layers - 1):
lsize = self.hidden_size
rsize = self.num_outs
else:
lsize = self.hidden_size
rsize = self.hidden_size
w = paddle.static.create_parameter(
shape=[lsize, rsize], dtype="float32", is_bias=False
)
b = paddle.static.create_parameter(
shape=[rsize], dtype="float32", is_bias=True
)
self.weights.append(w)
self.biases.append(b)
def nn_func(self, ins):
u = ins
for i in range(self.num_layers - 1):
u = paddle.nn.functional.linear(u, self.weights[i], self.biases[i])
u = self.activation(u)
u = paddle.nn.functional.linear(u, self.weights[-1], self.biases[-1])
return u
class LaplaceModel(paddle.nn.Layer):
def __init__(self, num_ins=2, num_outs=1, num_layers=5, hidden_size=20):
super().__init__()
self.net = FCNet(
num_ins=num_ins,
num_outs=num_outs,
num_layers=num_layers,
hidden_size=hidden_size,
)
def forward(self, inputs, bc_index):
inputs.stop_gradient = False
outputs = self.net.nn_func(inputs)
# eq_loss
hes = Hessian(self.net.nn_func, inputs, is_batched=True)
eq_loss = paddle.norm(hes[:, 0, 0] + hes[:, 1, 1], p=2)
# bc_loss
bc_u = paddle.index_select(outputs, bc_index)
return eq_loss, bc_u
class LaplaceDataset(paddle.io.Dataset):
def __init__(self, num_sample):
self.num_sample = num_sample
def __getitem__(self, index):
x = np.linspace(0, 0.9, 10)
y = np.linspace(0, 0.9, 10)
np.random.seed(index) # Optional: Ensure reproducibility
bc_value = np.random.rand(36).reshape(36, 1).astype('float32')
domain_space = []
bc_index = []
for j in range(len(y)):
for i in range(len(x)):
domain_space.append([x[i], y[j]])
if i == 0 or i == 9 or j == 0 or j == 9:
bc_index.append(i + 10 * j)
domain_space = np.array(domain_space, dtype='float32')
bc_index = np.array(bc_index, dtype='int64')
# Return a single input point and its related information based on the index
idx = index % len(domain_space)
return domain_space[idx], bc_index, bc_value
def __len__(self):
return self.num_sample
def loss_func(eq_loss, bc_u, bc_value):
bc_diff = bc_u - bc_value
bc_loss = paddle.norm(bc_diff, p=2)
loss = eq_loss + bc_loss
return loss
def main():
paddle.enable_static()
# dataset
train_dataset = LaplaceDataset(10)
# optimizer
optimizer = paddle.optimizer.Adam(learning_rate=0.001)
# model
laplace = LaplaceModel()
dist_strategy = auto.Strategy()
dist_strategy.auto_mode = "semi"
engine = auto.Engine(
laplace, loss=loss_func, optimizer=optimizer, strategy=dist_strategy
)
engine.fit(train_dataset, train_sample_split=2, batch_size=None)
dist_context = engine.dist_context
block = engine.main_program.global_block()
ops = block.ops
for op in ops:
if op.type == 'p_norm':
op_dist_attr = dist_context.get_op_dist_attr_for_program(op)
assert op_dist_attr.impl_type == 'p_norm'
if 'x' in op.input_arg_names:
out_name = op.output_arg_names[0]
assert block.vars[out_name].shape[0] == 50
if __name__ == "__main__":
main()