From ab19b8ca20b3a959b30364bfa77d7c94132e6241 Mon Sep 17 00:00:00 2001 From: HydrogenSulfate <490868991@qq.com> Date: Tue, 12 Dec 2023 02:09:01 +0800 Subject: [PATCH 1/5] add MOO algorithm: ReloBRalo --- ppsci/loss/mtl/__init__.py | 4 +- ppsci/loss/mtl/relobralo.py | 94 +++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 ppsci/loss/mtl/relobralo.py diff --git a/ppsci/loss/mtl/__init__.py b/ppsci/loss/mtl/__init__.py index 8b5aa0d5b..83e185a49 100644 --- a/ppsci/loss/mtl/__init__.py +++ b/ppsci/loss/mtl/__init__.py @@ -17,11 +17,13 @@ from ppsci.loss.mtl.agda import AGDA from ppsci.loss.mtl.base import LossAggregator from ppsci.loss.mtl.pcgrad import PCGrad +from ppsci.loss.mtl.relobralo import Relobralo __all__ = [ + "AGDA", "LossAggregator", "PCGrad", - "AGDA", + "Relobralo", ] diff --git a/ppsci/loss/mtl/relobralo.py b/ppsci/loss/mtl/relobralo.py new file mode 100644 index 000000000..14d8dde54 --- /dev/null +++ b/ppsci/loss/mtl/relobralo.py @@ -0,0 +1,94 @@ +# Copyright (c) 2023 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. + +from __future__ import annotations + +from typing import List + +import paddle +from paddle import nn + +from ppsci.loss.mtl import base + + +class Relobralo(nn.Layer, base.LossAggregator): + """Base class of loss aggregator mainly for multitask learning. + + Args: + model (nn.Layer): Training model. + """ + + def __init__( + self, + model: nn.Layer, + num_losses: int, + alpha: float = 0.95, + beta: float = 0.99, + tau: float = 1.0, + eps: float = 1e-8, + ) -> None: + super().__init__(model) + self.num_losses: int = num_losses + self.alpha: float = alpha + self.beta: float = beta + self.tau: float = tau + self.eps: float = eps + self.register_buffer("losses_init", paddle.zeros([self.num_losses])) + self.register_buffer("losses_prev", paddle.zeros([self.num_losses])) + self.register_buffer("lmbda", paddle.ones([self.num_losses])) + + def _softmax(self, vec: paddle.Tensor) -> paddle.Tensor: + max_item = vec.max() + result = paddle.exp(vec - max_item) / paddle.exp(vec - max_item).sum() + return result + + def _compute_bal( + self, losses_vec1: paddle.Tensor, losses_vec2: paddle.Tensor + ) -> paddle.Tensor: + return self.num_losses * ( + self._softmax(losses_vec1 / (self.tau * losses_vec2 + self.eps)) + ) + + def __call__(self, losses: List[paddle.Tensor], step: int = 0) -> "Relobralo": + self.step = step + losses_stacked = paddle.stack(losses) # [num_losses, ] + + if self.step == 0: + self.loss = losses_stacked.sum() + paddle.assign(losses_stacked.detach(), self.losses_init) + else: + with paddle.no_grad(): + # 1. update lambda_hist + rho = paddle.bernoulli(paddle.tensor(self.beta)) + lmbda_hist = rho * self.lmbda + (1 - rho) * self._compute_bal( + losses_stacked, self.losses_init + ) + + # 2. update lambda + paddle.assign( + self.alpha * lmbda_hist + + (1 - self.alpha) + * self._compute_bal(losses_stacked, self.losses_prev), + self.lmbda, + ) + + # 3. compute reweighted total loss with lambda + self.loss = losses_stacked * self.lmbda + + # update losses_prev at the end of each step + paddle.assign(losses_stacked.detach(), self.losses_prev) + return self + + def backward(self) -> None: + self.loss.backward() From b8e5691139f987c31f735e448e5df2dc457544d2 Mon Sep 17 00:00:00 2001 From: HydrogenSulfate <490868991@qq.com> Date: Tue, 12 Dec 2023 09:05:00 +0800 Subject: [PATCH 2/5] update code --- ppsci/loss/mtl/relobralo.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ppsci/loss/mtl/relobralo.py b/ppsci/loss/mtl/relobralo.py index 14d8dde54..d52b92234 100644 --- a/ppsci/loss/mtl/relobralo.py +++ b/ppsci/loss/mtl/relobralo.py @@ -19,10 +19,8 @@ import paddle from paddle import nn -from ppsci.loss.mtl import base - -class Relobralo(nn.Layer, base.LossAggregator): +class Relobralo(nn.Layer): """Base class of loss aggregator mainly for multitask learning. Args: @@ -38,7 +36,13 @@ def __init__( tau: float = 1.0, eps: float = 1e-8, ) -> None: - super().__init__(model) + super().__init__() + self.model = model + self.step = 0 + self.param_num = 0 + for param in self.model.parameters(): + if not param.stop_gradient: + self.param_num += 1 self.num_losses: int = num_losses self.alpha: float = alpha self.beta: float = beta @@ -66,11 +70,12 @@ def __call__(self, losses: List[paddle.Tensor], step: int = 0) -> "Relobralo": if self.step == 0: self.loss = losses_stacked.sum() - paddle.assign(losses_stacked.detach(), self.losses_init) + with paddle.no_grad(): + paddle.assign(losses_stacked.detach(), self.losses_init) else: with paddle.no_grad(): # 1. update lambda_hist - rho = paddle.bernoulli(paddle.tensor(self.beta)) + rho = paddle.bernoulli(paddle.to_tensor(self.beta)) lmbda_hist = rho * self.lmbda + (1 - rho) * self._compute_bal( losses_stacked, self.losses_init ) @@ -83,11 +88,12 @@ def __call__(self, losses: List[paddle.Tensor], step: int = 0) -> "Relobralo": self.lmbda, ) - # 3. compute reweighted total loss with lambda - self.loss = losses_stacked * self.lmbda + # 3. compute reweighted total loss with lambda + self.loss = (losses_stacked * self.lmbda).sum() # update losses_prev at the end of each step - paddle.assign(losses_stacked.detach(), self.losses_prev) + with paddle.no_grad(): + paddle.assign(losses_stacked.detach(), self.losses_prev) return self def backward(self) -> None: From 6f2f841631a32fd41cf7164b5ef82d8742aedc09 Mon Sep 17 00:00:00 2001 From: HydrogenSulfate <490868991@qq.com> Date: Tue, 12 Dec 2023 02:49:31 +0000 Subject: [PATCH 3/5] add final ReloBRalo code --- docs/zh/api/loss.md | 3 ++- ppsci/loss/mtl/relobralo.py | 33 +++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/zh/api/loss.md b/docs/zh/api/loss.md index ccdabceee..a2b59e24b 100644 --- a/docs/zh/api/loss.md +++ b/docs/zh/api/loss.md @@ -23,8 +23,9 @@ handler: python options: members: + - AGDA - LossAggregator - PCGrad - - AGDA + - Relobralo show_root_heading: true heading_level: 3 diff --git a/ppsci/loss/mtl/relobralo.py b/ppsci/loss/mtl/relobralo.py index d52b92234..4bbc73e2d 100644 --- a/ppsci/loss/mtl/relobralo.py +++ b/ppsci/loss/mtl/relobralo.py @@ -21,15 +21,37 @@ class Relobralo(nn.Layer): - """Base class of loss aggregator mainly for multitask learning. + r""" + **Re**lative **Lo**ss **B**alancing with **Ra**ndom **Lo**okback + + [Multi-Objective Loss Balancing for Physics-Informed Deep Learning](https://arxiv.org/abs/2110.09813) Args: - model (nn.Layer): Training model. + num_losses (int): Number of losses. + alpha (float, optional): Ability for remembering past in paper. Defaults to 0.95. + beta (float, optional): Parameter for generating $\rho$ from bernoulli distribution, + and $E[\rho](=\beta)$ should be close to 1. Defaults to 0.99. + tau (float, optional): Temperature factor. Equivalent to softmax when $\tau$=1.0, + equivalent to argmax when $\tau$=0. Defaults to 1.0. + eps (float, optional): $\epsilon$ to avoid divided by 0 in losses. Defaults to 1e-8. + + Examples: + >>> import paddle + >>> from ppsci.loss import mtl + >>> model = paddle.nn.Linear(3, 4) + >>> loss_aggregator = mtl.Relobralo(2) + >>> for i in range(5): + ... x1 = paddle.randn([8, 3]) + ... x2 = paddle.randn([8, 3]) + ... y1 = model(x1) + ... y2 = model(x2) + ... loss1 = paddle.sum(y1) + ... loss2 = paddle.sum((y2 - 2) ** 2) + ... loss_aggregator([loss1, loss2]).backward() """ def __init__( self, - model: nn.Layer, num_losses: int, alpha: float = 0.95, beta: float = 0.99, @@ -37,12 +59,7 @@ def __init__( eps: float = 1e-8, ) -> None: super().__init__() - self.model = model self.step = 0 - self.param_num = 0 - for param in self.model.parameters(): - if not param.stop_gradient: - self.param_num += 1 self.num_losses: int = num_losses self.alpha: float = alpha self.beta: float = beta From acd2c9fdead4d65f329ed97e5904cb42ed159369 Mon Sep 17 00:00:00 2001 From: HydrogenSulfate <490868991@qq.com> Date: Tue, 12 Dec 2023 09:20:58 +0000 Subject: [PATCH 4/5] update document --- docs/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index e825c16e3..8577bef00 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,8 +26,9 @@ | 微分方程 | [洛伦兹方程](./zh/examples/lorenz.md) | 数据驱动 | Transformer-Physx | 监督学习 | [Data](https://github.com/zabaras/transformer-physx) | [Paper](https://arxiv.org/abs/2010.03957) | | 微分方程 | [若斯叻方程](./zh/examples/rossler.md) | 数据驱动 | Transformer-Physx | 监督学习 | [Data](https://github.com/zabaras/transformer-physx) | [Paper](https://arxiv.org/abs/2010.03957) | | 算子学习 | [DeepONet](./zh/examples/deeponet.md) | 数据驱动 | MLP | 监督学习 | [Data](https://deepxde.readthedocs.io/en/latest/demos/operator/antiderivative_unaligned.html) | [Paper](https://export.arxiv.org/pdf/1910.03193.pdf) | -| 微分方程 | 梯度增强的物理知识融合PDE求解coming soon | 机理驱动 | gPINN | 半监督学习 | - | [Paper](https://www.sciencedirect.com/science/article/abs/pii/S0045782522001438?via%3Dihub) | +| 微分方程 | [梯度增强的物理知识融合 PDE 求解](https://github.com/PaddlePaddle/PaddleScience/blob/develop/examples/gpinn/poisson_1d.py) | 机理驱动 | gPINN | 无监督学习 | - | [Paper](https://doi.org/10.1016/j.cma.2022.114823) | | 积分方程 | [沃尔泰拉积分方程](./zh/examples/volterra_ide.md) | 机理驱动 | MLP | 无监督学习 | - | [Project](https://github.com/lululxvi/deepxde/blob/master/examples/pinn_forward/Volterra_IDE.py) | +| 微分方程 | [分数阶微分方程](https://github.com/PaddlePaddle/PaddleScience/blob/develop/examples/fpde/fractional_poisson_2d.py) | 机理驱动 | MLP | 无监督学习 | - | - |

技术科学(AI for Technology)

From f741cd6910383325ced2d420d0e87b8d7d640e27 Mon Sep 17 00:00:00 2001 From: HydrogenSulfate <490868991@qq.com> Date: Tue, 12 Dec 2023 09:24:17 +0000 Subject: [PATCH 5/5] update css --- docs/stylesheets/extra.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index ebc042903..97d34cc25 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -7,7 +7,7 @@ .md-grid { /* readable page width */ - max-width: 70%; + max-width: 1440px; } .md-header__topic > .md-ellipsis {