From 407620acef7d64c94a1cd0cc1576b243d50940b3 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 6 Sep 2022 13:03:19 +0800 Subject: [PATCH 01/69] fix(workflows): clone repo in workers for version check --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 72dd012a..5553d434 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -105,6 +105,12 @@ jobs: (github.event_name != 'push' || startsWith(github.ref, 'refs/tags/')) timeout-minutes: 15 steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: "recursive" + fetch-depth: 1 + - name: Set up Python uses: actions/setup-python@v4 if: startsWith(github.ref, 'refs/tags/') From 579a1d3ed2ebba80b20563b2913be780d19f96a8 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 6 Sep 2022 13:25:40 +0800 Subject: [PATCH 02/69] chore(workflows): unshallow git clones --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5553d434..b330e07e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,7 +50,7 @@ jobs: uses: actions/checkout@v3 with: submodules: "recursive" - fetch-depth: 1 + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v4 @@ -81,7 +81,7 @@ jobs: uses: actions/checkout@v3 with: submodules: "recursive" - fetch-depth: 1 + fetch-depth: 0 - name: Build wheels uses: pypa/cibuildwheel@v2.8.1 @@ -109,7 +109,7 @@ jobs: uses: actions/checkout@v3 with: submodules: "recursive" - fetch-depth: 1 + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v4 From da0010099cc5da626970071c809f49288b3033f7 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Thu, 8 Sep 2022 19:53:26 +0800 Subject: [PATCH 03/69] feat: implicit differentiation integration (#41) Co-authored-by: Jie Co-authored-by: waterhorse1 <1098616530@qq.com> Co-authored-by: Xuehai Pan --- CHANGELOG.md | 2 +- pyproject.toml | 31 ++- requirements.txt | 1 + tests/helpers.py | 16 +- tests/requirements.txt | 3 + tests/test_implicit.py | 324 +++++++++++++++++++++++++++ torchopt/__init__.py | 15 +- torchopt/_src/base.py | 5 +- torchopt/_src/implicit_diff.py | 387 +++++++++++++++++++++++++++++++++ torchopt/_src/linalg.py | 214 ++++++++++++++++++ torchopt/_src/linear_solve.py | 134 ++++++++++++ torchopt/_src/visual.py | 2 +- 12 files changed, 1109 insertions(+), 25 deletions(-) create mode 100644 tests/test_implicit.py create mode 100644 torchopt/_src/implicit_diff.py create mode 100644 torchopt/_src/linalg.py create mode 100644 torchopt/_src/linear_solve.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5334e26a..5ee3c27c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - +- Implicit differentiation support by [@JieRen98](https://github.com/JieRen98) and [@waterhorse1](https://github.com/waterhorse1) and [@XuehaiPan](https://github.com/XuehaiPan) in [#41](https://github.com/metaopt/torchopt/pull/41). ### Changed diff --git a/pyproject.toml b/pyproject.toml index 47af443f..e59a21e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ classifiers = [ ] dependencies = [ "torch >= 1.12", + "functorch >= 0.2", "optree", "numpy", "graphviz", @@ -73,10 +74,12 @@ lint = [ "pre-commit", ] test = [ - 'functorch >= 0.2', 'pytest', 'pytest-cov', 'pytest-xdist', + 'jax[cpu] >= 0.3', + 'jaxopt', + 'optax', ] [tool.setuptools.packages.find] @@ -111,6 +114,7 @@ before-all = """ yum install -y nvidia-driver-latest-libs "cuda-minimal-build-${CUDA_PKG_SUFFIX}" fi echo "cat torchopt/version.py"; cat torchopt/version.py + touch .first-python """ test-extras = ["test"] test-command = """ @@ -122,17 +126,20 @@ test-command = """ xargs -0 -I '{}' bash -c "echo 'ldd {}'; ldd '{}'; echo 'patchelf --print-rpath {}'; patchelf --print-rpath '{}'" make -C "{project}" test || exit 1 TORCH_VERSION="$(python -c 'print(__import__("torch").__version__.partition("+")[0])')" - TEST_TORCH_SPECS="${TEST_TORCH_SPECS:-"${DEFAULT_TEST_TORCH_SPECS}"}" - for spec in ${TEST_TORCH_SPECS}; do - python -m pip uninstall -y torch - export PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/${spec}" - echo "PIP_EXTRA_INDEX_URL='${PIP_EXTRA_INDEX_URL}'" - python -m pip install "torch==${TORCH_VERSION}" - echo "ls ${TORCH_LIB_PATH}"; ls -lh "${TORCH_LIB_PATH}" - find "${SITE_PACKAGES}/torchopt" -name "*.so" -print0 | - xargs -0 -I '{}' bash -c "echo 'ldd {}'; ldd '{}'; echo 'patchelf --print-rpath {}'; patchelf --print-rpath '{}'" - make -C "{project}" test || exit 1 - done + if [[ -f .first-python ]]; then + TEST_TORCH_SPECS="${TEST_TORCH_SPECS:-"${DEFAULT_TEST_TORCH_SPECS}"}" + for spec in ${TEST_TORCH_SPECS}; do + python -m pip uninstall -y torch + export PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/${spec}" + echo "PIP_EXTRA_INDEX_URL='${PIP_EXTRA_INDEX_URL}'" + python -m pip install "torch==${TORCH_VERSION}" + echo "ls ${TORCH_LIB_PATH}"; ls -lh "${TORCH_LIB_PATH}" + find "${SITE_PACKAGES}/torchopt" -name "*.so" -print0 | + xargs -0 -I '{}' bash -c "echo 'ldd {}'; ldd '{}'; echo 'patchelf --print-rpath {}'; patchelf --print-rpath '{}'" + make -C "{project}" test || exit 1 + done + rm -f .first-python + fi rm -rf ~/.pip/cache ~/.cache/pip """ diff --git a/requirements.txt b/requirements.txt index a2ced2f2..8c520b14 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ torch >= 1.12 +functorch >= 0.2 optree numpy graphviz diff --git a/tests/helpers.py b/tests/helpers.py index d34ad41e..131a98a3 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -34,6 +34,14 @@ MODEL_HIDDEN_SIZE = 64 +def dtype_numpy2torch(dtype: np.dtype) -> torch.dtype: + return torch.tensor(np.zeros(1, dtype=dtype)).dtype + + +def dtype_torch2numpy(dtype: torch.dtype) -> np.dtype: + return torch.zeros(1, dtype=dtype).numpy().dtype + + def parametrize(**argvalues) -> pytest.mark.parametrize: arguments = list(argvalues) @@ -80,34 +88,29 @@ def get_models( in_features=MODEL_NUM_INPUTS, out_features=MODEL_HIDDEN_SIZE, bias=True, - dtype=dtype, ), nn.BatchNorm1d( num_features=MODEL_HIDDEN_SIZE, track_running_stats=True, - dtype=dtype, ), nn.ReLU(), nn.Linear( in_features=MODEL_HIDDEN_SIZE, out_features=MODEL_HIDDEN_SIZE, bias=True, - dtype=dtype, ), nn.BatchNorm1d( num_features=MODEL_HIDDEN_SIZE, track_running_stats=True, - dtype=dtype, ), nn.ReLU(), nn.Linear( in_features=MODEL_HIDDEN_SIZE, out_features=MODEL_NUM_CLASSES, bias=True, - dtype=dtype, ), nn.Softmax(dim=-1), - ) + ).to(dtype=dtype) for name, param in model_base.named_parameters(recurse=True): if name.endswith('weight') and param.ndim >= 2: nn.init.orthogonal_(param) @@ -123,6 +126,7 @@ def get_models( dataset = data.TensorDataset( torch.randint(0, 1, (BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), + # torch.empty((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS), dtype=dtype).uniform_(-1.0, +1.0), torch.randint(0, MODEL_NUM_CLASSES, (BATCH_SIZE * NUM_UPDATES,)), ) loader = data.DataLoader(dataset, BATCH_SIZE, shuffle=False) diff --git a/tests/requirements.txt b/tests/requirements.txt index d02db980..1143ebd3 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -18,3 +18,6 @@ pydocstyle pyenchant cpplint pre-commit +jax[cpu] >= 0.3 +jaxopt +optax diff --git a/tests/test_implicit.py b/tests/test_implicit.py new file mode 100644 index 00000000..c2d2ad72 --- /dev/null +++ b/tests/test_implicit.py @@ -0,0 +1,324 @@ +# Copyright 2022 MetaOPT Team. 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 copy +from collections import OrderedDict +from types import FunctionType +from typing import Optional, Tuple, Union + +import functorch +import jax +import jax.numpy as jnp +import jaxopt +import numpy as np +import optax +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch.utils import data + +import helpers +import torchopt +from torchopt import pytree + + +BATCH_SIZE = 8 +NUM_UPDATES = 3 + +MODEL_NUM_INPUTS = 10 +MODEL_NUM_CLASSES = 10 + + +def get_model_jax(dtype: np.dtype = np.float32) -> Tuple[FunctionType, OrderedDict]: + helpers.seed_everything(seed=42) + + def func(params, x): + return x @ params['weight'] + params['bias'] + + params = OrderedDict( + [ + ('weight', jnp.ones((MODEL_NUM_INPUTS, MODEL_NUM_CLASSES), dtype=dtype)), + ('bias', jnp.zeros((MODEL_NUM_CLASSES,), dtype=dtype)), + ] + ) + return func, params + + +@torch.no_grad() +def get_model_torch( + device: Optional[Union[str, torch.device]] = None, dtype: torch.dtype = torch.float32 +) -> Tuple[nn.Module, data.DataLoader]: + helpers.seed_everything(seed=42) + + class FcNet(nn.Module): + def __init__(self, dim, out): + super().__init__() + self.fc = nn.Linear(in_features=dim, out_features=out, bias=True) + nn.init.ones_(self.fc.weight) + nn.init.zeros_(self.fc.bias) + + def forward(self, x): + return self.fc(x) + + model = FcNet(MODEL_NUM_INPUTS, MODEL_NUM_CLASSES).to(dtype=dtype) + + if device is not None: + model = model.to(device=torch.device(device)) + + dataset = data.TensorDataset( + torch.randint(0, 1, (BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), + # torch.empty((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS), dtype=dtype).uniform_(-1.0, +1.0), + torch.randint(0, MODEL_NUM_CLASSES, (BATCH_SIZE * NUM_UPDATES,)), + ) + loader = data.DataLoader(dataset, BATCH_SIZE, shuffle=False) + + return model, loader + + +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-3, 1e-4], + inner_lr=[2e-2, 2e-3], + inner_update=[20, 50, 100], +) +def test_imaml(dtype: torch.dtype, lr: float, inner_lr: float, inner_update: int) -> None: + np_dtype = helpers.dtype_torch2numpy(dtype) + + jax_function, jax_params = get_model_jax(dtype=np_dtype) + model, loader = get_model_torch(device='cpu', dtype=dtype) + + fmodel, params = functorch.make_functional(model) + optim = torchopt.sgd(lr) + optim_state = optim.init(params) + + optim_jax = optax.sgd(lr) + optim_state_jax = optim_jax.init(jax_params) + + def imaml_objective_torchopt(optimal_params, init_params, data): + x, y, f = data + y_pred = f(optimal_params, x) + regularization_loss = 0 + for p1, p2 in zip(optimal_params, init_params): + regularization_loss += 0.5 * torch.sum(torch.square(p1 - p2)) + loss = F.cross_entropy(y_pred, y) + regularization_loss + return loss + + @torchopt.implicit_diff.custom_root( + functorch.grad(imaml_objective_torchopt, argnums=0), argnums=1 + ) + def inner_solver_torchopt(init_params_copy, init_params, data): + # Initial functional optimizer based on TorchOpt + x, y, f = data + params = init_params_copy + optimizer = torchopt.sgd(lr=inner_lr) + opt_state = optimizer.init(params) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(inner_update): + pred = f(params, x) + loss = F.cross_entropy(pred, y) # compute loss + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params, init_params): + regularization_loss += 0.5 * torch.sum(torch.square(p1 - p2)) + final_loss = loss + regularization_loss + grads = torch.autograd.grad(final_loss, params) # compute gradients + updates, opt_state = optimizer.update(grads, opt_state) # get updates + params = torchopt.apply_updates(params, updates) + return params + + def imaml_objective_jax(optimal_params, init_params, x, y): + y_pred = jax_function(optimal_params, x) + loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(y_pred, y)) + regularization_loss = 0 + for p1, p2 in zip(optimal_params.values(), init_params.values()): + regularization_loss += 0.5 * jnp.sum(jnp.square((p1 - p2))) + loss = loss + regularization_loss + return loss + + @jaxopt.implicit_diff.custom_root(jax.grad(imaml_objective_jax, argnums=0)) + def inner_solver_jax(init_params_copy, init_params, x, y): + """Solve ridge regression by conjugate gradient.""" + # Initial functional optimizer based on torchopt + params = init_params_copy + optimizer = optax.sgd(inner_lr) + opt_state = optimizer.init(params) + + def compute_loss(params, init_params, x, y): + pred = jax_function(params, x) + loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(pred, y)) + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params.values(), init_params.values()): + regularization_loss += 0.5 * jnp.sum(jnp.square((p1 - p2))) + final_loss = loss + regularization_loss + return final_loss + + for i in range(inner_update): + grads = jax.grad(compute_loss)(params, init_params, x, y) # compute gradients + updates, opt_state = optimizer.update(grads, opt_state) # get updates + params = optax.apply_updates(params, updates) + return params + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + data = (xs, ys, fmodel) + init_params_copy = pytree.tree_map( + lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params + ) + optimal_params = inner_solver_torchopt(init_params_copy, params, data) + outer_loss = fmodel(optimal_params, xs).mean() + + grad = torch.autograd.grad(outer_loss, params) + updates, optim_state = optim.update(grad, optim_state) + params = torchopt.apply_updates(params, updates) + + xs = xs.numpy() + ys = ys.numpy() + + def outer_level(p, xs, ys): + optimal_params = inner_solver_jax(copy.deepcopy(p), p, xs, ys) + outer_loss = jax_function(optimal_params, xs).mean() + return outer_loss + + grads_jax = jax.grad(outer_level, argnums=0)(jax_params, xs, ys) + updates_jax, optim_state_jax = optim_jax.update(grads_jax, optim_state_jax) # get updates + jax_params = optax.apply_updates(jax_params, updates_jax) + + jax_params_as_tensor = tuple( + nn.Parameter(torch.tensor(np.asarray(jax_params[j]), dtype=dtype)) for j in jax_params + ) + + for p, p_ref in zip(params, jax_params_as_tensor): + helpers.assert_all_close(p, p_ref) + + +@torch.no_grad() +def get_rr_dataset_torch() -> data.DataLoader: + helpers.seed_everything(seed=42) + + BATCH_SIZE = 1024 + NUM_UPDATES = 4 + dataset = data.TensorDataset( + torch.randn((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), + torch.randn((BATCH_SIZE * NUM_UPDATES)), + torch.randn((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), + torch.randn((BATCH_SIZE * NUM_UPDATES)), + ) + loader = data.DataLoader(dataset, BATCH_SIZE, shuffle=False) + + return loader + + +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-3, 1e-4], +) +def test_rr( + dtype: torch.dtype, + lr: float, +) -> None: + helpers.seed_everything(42) + np_dtype = helpers.dtype_torch2numpy(dtype) + input_size = 10 + + init_params_torch = torch.randn(input_size, dtype=dtype) + l2reg_torch = torch.rand(1, dtype=dtype).squeeze_().requires_grad_(True) + + init_params_jax = jnp.array(init_params_torch.detach().numpy(), dtype=np_dtype) + l2reg_jax = jnp.array(l2reg_torch.detach().numpy(), dtype=np_dtype) + + loader = get_rr_dataset_torch() + + optim = torchopt.sgd(lr) + optim_state = optim.init(l2reg_torch) + + optim_jax = optax.sgd(lr) + optim_state_jax = optim_jax.init(l2reg_jax) + + def ridge_objective_torch(params, l2reg, data): + """Ridge objective function.""" + X_tr, y_tr = data + residuals = X_tr @ params - y_tr + regularization_loss = 0.5 * l2reg * torch.sum(torch.square(params)) + return 0.5 * torch.mean(torch.square(residuals)) + regularization_loss + + @torchopt.implicit_diff.custom_root(functorch.grad(ridge_objective_torch, argnums=0), argnums=1) + def ridge_solver_torch(init_params, l2reg, data): + """Solve ridge regression by conjugate gradient.""" + X_tr, y_tr = data + + def matvec(u): + return X_tr.T @ (X_tr @ u) + + return torchopt.linear_solve.solve_cg( + matvec=matvec, + b=X_tr.T @ y_tr, + ridge=len(y_tr) * l2reg.item(), + init=init_params, + maxiter=20, + ) + + def ridge_objective_jax(params, l2reg, X_tr, y_tr): + """Ridge objective function.""" + residuals = X_tr @ params - y_tr + regularization_loss = 0.5 * l2reg * jnp.sum(jnp.square(params)) + return 0.5 * jnp.mean(jnp.square(residuals)) + regularization_loss + + @jaxopt.implicit_diff.custom_root(jax.grad(ridge_objective_jax, argnums=0)) + def ridge_solver_jax(init_params, l2reg, X_tr, y_tr): + """Solve ridge regression by conjugate gradient.""" + + def matvec(u): + return X_tr.T @ ((X_tr @ u)) + + return jaxopt.linear_solve.solve_cg( + matvec=matvec, + b=X_tr.T @ y_tr, + ridge=len(y_tr) * l2reg.item(), + init=init_params, + maxiter=20, + ) + + for xs, ys, xq, yq in loader: + xs = xs.to(dtype=dtype) + ys = ys.to(dtype=dtype) + xq = xq.to(dtype=dtype) + yq = yq.to(dtype=dtype) + + w_fit = ridge_solver_torch(init_params_torch, l2reg_torch, (xs, ys)) + outer_loss = F.mse_loss(xq @ w_fit, yq) + + grads, *_ = torch.autograd.grad(outer_loss, l2reg_torch) + updates, optim_state = optim.update(grads, optim_state) + l2reg_torch = torchopt.apply_updates(l2reg_torch, updates) + + xs = jnp.array(xs.numpy(), dtype=np_dtype) + ys = jnp.array(ys.numpy(), dtype=np_dtype) + xq = jnp.array(xq.numpy(), dtype=np_dtype) + yq = jnp.array(yq.numpy(), dtype=np_dtype) + + def outer_level(init_params_jax, l2reg_jax, xs, ys, xq, yq): + w_fit = ridge_solver_jax(init_params_jax, l2reg_jax, xs, ys) + y_pred = xq @ w_fit + loss_value = jnp.mean(jnp.square(y_pred - yq)) + return loss_value + + grads_jax = jax.grad(outer_level, argnums=1)(init_params_jax, l2reg_jax, xs, ys, xq, yq) + updates_jax, optim_state_jax = optim_jax.update(grads_jax, optim_state_jax) # get updates + l2reg_jax = optax.apply_updates(l2reg_jax, updates_jax) + + l2reg_jax_as_tensor = torch.tensor(np.asarray(l2reg_jax), dtype=dtype) + helpers.assert_all_close(l2reg_torch, l2reg_jax_as_tensor) diff --git a/torchopt/__init__.py b/torchopt/__init__.py index ab7a5a4d..fa242b52 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -14,7 +14,16 @@ # ============================================================================== """TorchOpt: a high-performance optimizer library built upon PyTorch.""" -from torchopt._src import accelerated_op_available, clip, combine, hook, schedule, visual +from torchopt._src import ( + accelerated_op_available, + clip, + combine, + hook, + implicit_diff, + linear_solve, + schedule, + visual, +) from torchopt._src.alias import adam, adamw, rmsprop, sgd from torchopt._src.clip import clip_grad_norm from torchopt._src.combine import chain @@ -28,7 +37,7 @@ MetaSGD, ) from torchopt._src.update import apply_updates -from torchopt._src.utils import extract_state_dict, recover_state_dict, stop_gradient +from torchopt._src.utils import extract_state_dict, pytree, recover_state_dict, stop_gradient from torchopt.version import __version__ @@ -39,6 +48,8 @@ 'hook', 'schedule', 'visual', + 'implicit_diff', + 'linear_solve', 'adam', 'adamw', 'rmsprop', diff --git a/torchopt/_src/base.py b/torchopt/_src/base.py index f17bf00f..9e5813d1 100644 --- a/torchopt/_src/base.py +++ b/torchopt/_src/base.py @@ -234,13 +234,12 @@ def init_fn(params: Params) -> OptState: # pylint: disable=unused-argument return EmptyState() @staticmethod - # pylint: disable-next=unused-argument def update_fn( updates: Updates, state: OptState, *, - params: Optional[Params] = None, - inplace: bool = True, + params: Optional[Params] = None, # pylint: disable=unused-argument + inplace: bool = True, # pylint: disable=unused-argument ) -> Tuple[Updates, OptState]: """Returns updates unchanged.""" return updates, state diff --git a/torchopt/_src/implicit_diff.py b/torchopt/_src/implicit_diff.py new file mode 100644 index 00000000..1806bea0 --- /dev/null +++ b/torchopt/_src/implicit_diff.py @@ -0,0 +1,387 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== + +# pylint: disable=invalid-name + +import functools +import inspect +from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union + +import functorch +import torch +from torch.autograd import Function + +from torchopt._src import linear_solve +from torchopt._src.utils import pytree + + +ARGS = Tuple[Any, ...] +KWARGS = Dict[Any, Any] + + +# pylint: disable-next=too-many-arguments,too-many-locals +def _root_vjp( + optimality_fun: Callable, + sol: Any, + args: ARGS, + cotangent: Any, + res_is_tensor: bool, + argnums: Tuple[int, ...], + solve: Callable = linear_solve.solve_normal_cg, +) -> Tuple[Any, ...]: + def fun_sol(sol): + # We close over the arguments. + if res_is_tensor: + return optimality_fun(sol[0], *args) + return optimality_fun(sol, *args) + + _, vjp_fun_sol, *_ = functorch.vjp(fun_sol, sol) + + # Compute the multiplication A^T u = (u^T A)^T. + def matvec(u): + if res_is_tensor: + return vjp_fun_sol(u[0])[0] + return vjp_fun_sol(u)[0] + + # The solution of A^T u = v, where + # A = jacobian(optimality_fun, argnums=0) + # v = -cotangent. + v = pytree.tree_map(torch.neg, cotangent) + u = solve(matvec, v) + + class MaskArgs: # pylint: disable=missing-class-docstring,too-few-public-methods + def __init__(self, argnums: Tuple[int, ...], *args) -> None: + self.argnums = argnums + + self.pre_filled = [] + self.post_filled = [] + for idx, arg in enumerate(args): + if idx + 1 in argnums: # plus 1 because we exclude the first argument + self.post_filled.append(arg) + else: + self.pre_filled.append(arg) + self.len_args = len(self.pre_filled) + len(self.post_filled) + + def __call__(self, *args) -> Any: + true_args = [] + pre_filled_counter = 0 + for idx in range(self.len_args): + if idx + 1 in self.argnums: # plus 1 because we exclude the first argument + arg = args[idx] + else: + arg = self.pre_filled[pre_filled_counter] + pre_filled_counter += 1 + true_args.append(arg) + if res_is_tensor: + return optimality_fun(sol[0], *true_args) + return optimality_fun(sol, *true_args) + + fun_args = MaskArgs(argnums, *args) + + _, vjp_fun_args, *_ = functorch.vjp(fun_args, *fun_args.post_filled) + + if res_is_tensor: + result = vjp_fun_args(u[0]) + else: + result = vjp_fun_args(u) + + true_result = [None] + for idx in range(fun_args.len_args): + if idx + 1 in argnums: # plus 1 because we exclude the first argument + true_result.append(result[idx]) + else: + true_result.append(None) + + return tuple(true_result) + + +def _extract_kwargs(kwarg_keys: Sequence[Any], flat_args: Tuple[Any, ...]) -> Tuple[ARGS, KWARGS]: + nargs = len(flat_args) - len(kwarg_keys) + args, kwarg_vals = flat_args[:nargs], flat_args[nargs:] + kwargs = dict(zip(kwarg_keys, kwarg_vals)) + return args, kwargs + + +def _signature_bind(signature: inspect.Signature, *args, **kwargs) -> Tuple[ARGS, KWARGS]: + bound = signature.bind(*args, **kwargs) + bound.apply_defaults() + return bound.args, bound.kwargs + + +def _signature_bind_and_match( + signature: inspect.Signature, *args, **kwargs +) -> Tuple[ARGS, KWARGS, Callable[[ARGS], Tuple[ARGS, KWARGS]]]: + # We want to bind *args and **kwargs based on the provided signature, but also to associate the + # resulting positional arguments back. To achieve this, we lift arguments to a triple: + # + # (was_kwarg, ref, value) + # + # where ref is an index position (int) if the original argument was from *args and a dictionary + # key if the original argument was from **kwargs. After binding to the inspected signature, we + # use the tags to associate the resolved positional arguments back to their arg and kwarg + # source. + + args = [(False, i, v) for i, v in enumerate(args)] + kwargs = {k: (True, k, v) for (k, v) in kwargs.items()} + bound = signature.bind(*args, **kwargs) + + mapping = [(was_kwarg, ref) for was_kwarg, ref, _ in bound.args] + + def map_args_back(out_args): + src_args = [None] * len(args) + src_kwargs = {} + for (was_kwarg, ref), out_arg in zip(mapping, out_args): + if was_kwarg: + src_kwargs[ref] = out_arg + else: + src_args[ref] = out_arg + return src_args, src_kwargs + + out_args = tuple(v for _, _, v in bound.args) + out_kwargs = {k: v for k, (_, _, v) in bound.kwargs.items()} + return out_args, out_kwargs, map_args_back + + +def _split_tensor_and_others( + mixed_tuple: Tuple, +) -> Tuple[pytree.PyTreeDef, Tuple[bool, ...], Tuple[torch.Tensor, ...], Tuple[Any, ...]]: + flattened, treedef = pytree.tree_flatten(mixed_tuple) + tensors = [] + non_tensors = [] + is_tensor_mask = [] + for item in flattened: + if isinstance(item, torch.Tensor): + tensors.append(item) + is_tensor_mask.append(True) + else: + non_tensors.append(item) + is_tensor_mask.append(False) + return treedef, tuple(is_tensor_mask), tuple(tensors), tuple(non_tensors) + + +def _merge_tensor_and_others( + treedef: pytree.PyTreeDef, + is_tensor_mask: Tuple[bool, ...], + tensors: Tuple[torch.Tensor, ...], + non_tensors: Tuple[Any, ...], +) -> Any: + tensor_counter = 0 + non_tensor_counter = 0 + results = [] + for is_tensor in is_tensor_mask: + if is_tensor: + results.append(tensors[tensor_counter]) + tensor_counter += 1 + else: + results.append(non_tensors[non_tensor_counter]) + non_tensor_counter += 1 + return pytree.tree_unflatten(treedef, results) + + +# pylint: disable-next=too-many-arguments,too-many-statements +def _custom_root( + solver_fun: Callable, + optimality_fun: Callable, + solve: Callable, + argnums: Tuple[int, ...], + has_aux: bool, + reference_signature: Optional[Union[inspect.Signature, Callable]] = None, +) -> Callable: + solver_fun_signature = inspect.signature(solver_fun) + + if reference_signature is None: + reference_signature = inspect.signature(optimality_fun) + elif not isinstance(reference_signature, inspect.Signature): + # If is a CompositeLinearFunction, accesses subfun. + # Otherwise, assumes a Callable. + fun = getattr(reference_signature, 'subfun', reference_signature) + reference_signature = inspect.signature(fun) + + def make_custom_vjp_solver_fun(solver_fun, kwarg_keys, args_sign): + # pylint: disable-next=missing-class-docstring,abstract-method + class ImplicitMetaGradient(Function): + @staticmethod + def forward(ctx, *flat_args): # pylint: disable=arguments-differ + args = [] + for idx, (start_point, is_tuple) in enumerate(args_sign): + if is_tuple: + args.append(tuple(flat_args[start_point : args_sign[idx + 1][0]])) + else: + args.append(flat_args[start_point]) + args = tuple(args) + + args, kwargs = _extract_kwargs(kwarg_keys, args) + res = solver_fun(*args, **kwargs) + ( + args_treedef, + args_is_tensor_mask, + args_tensors, + args_non_tensors, + ) = _split_tensor_and_others(args) + ctx.args_treedef = args_treedef + ctx.args_is_tensor_mask = args_is_tensor_mask + ctx.args_non_tensors = args_non_tensors + if has_aux: + aux = res[1] + res = res[0] + if isinstance(res, torch.Tensor): + ctx.save_for_backward(res, *args_tensors) + else: + ctx.save_for_backward(*res, *args_tensors) + ctx.res_is_tensor = isinstance(res, torch.Tensor) + return res + (aux,) + + if isinstance(res, torch.Tensor): + ctx.save_for_backward(res, *args_tensors) + else: + ctx.save_for_backward(*res, *args_tensors) + ctx.res_is_tensor = isinstance(res, torch.Tensor) + return res + + @staticmethod + def backward(ctx, *cotangent): # pylint: disable=too-many-locals + if has_aux: + cotangent = cotangent[:-1] + + saved_tensors = ctx.saved_tensors + res, args_tensors = saved_tensors[: len(cotangent)], saved_tensors[len(cotangent) :] + args_treedef = ctx.args_treedef + args_is_tensor_mask = ctx.args_is_tensor_mask + args_non_tensors = ctx.args_non_tensors + args = _merge_tensor_and_others( + args_treedef, args_is_tensor_mask, args_tensors, args_non_tensors + ) + + args, kwargs = _extract_kwargs(kwarg_keys, args) + + sol = res + bound_args, bound_kwargs, map_args_back = _signature_bind_and_match( + reference_signature, *args, **kwargs # type: ignore[arg-type] + ) + if bound_kwargs: + raise TypeError( + 'keyword arguments to solver_fun could not be resolved to ' + 'positional arguments based on the signature ' + f'{reference_signature}. This can happen under custom_root if ' + 'optimality_fun takes catch-all **kwargs, or under ' + 'custom_fixed_point if fixed_point_fun takes catch-all **kwargs, ' + 'both of which are currently unsupported.' + ) + + # Compute VJPs w.r.t. args. + vjps = _root_vjp( + optimality_fun=optimality_fun, + sol=sol, + args=bound_args[1:], + cotangent=cotangent, + res_is_tensor=ctx.res_is_tensor, + argnums=argnums, + solve=solve, + ) + # Prepend None as the vjp for init_params. + + arg_vjps, kwargs_vjps = map_args_back(vjps) + ordered_vjps = tuple(arg_vjps) + tuple(kwargs_vjps[k] for k in kwargs.keys()) + true_vjps = [] + for (_, is_tuple), vjp in zip(args_sign, ordered_vjps): + if is_tuple: + for item in vjp: + true_vjps.append(item) + else: + true_vjps.append(vjp) + return tuple(true_vjps) + + return ImplicitMetaGradient + + def wrapped_solver_fun(*args, **kwargs): + args, kwargs = _signature_bind(solver_fun_signature, *args, **kwargs) + keys, vals = list(kwargs.keys()), list(kwargs.values()) + + args_sign = [] + flatten_args = [] + args_counter = 0 + for idx, arg in enumerate(args): + if idx in argnums: + if isinstance(arg, torch.Tensor): + args_sign.append((args_counter, False)) # start position, is_tuple + flatten_args.append(arg) + args_counter += 1 + elif isinstance(arg, tuple): + args_sign.append((args_counter, True)) # start position, is_tuple + for arg_item in arg: + flatten_args.append(arg_item) + args_counter += len(arg) + else: + raise RuntimeError('must be tensor or tensor tuple') + else: + args_sign.append((args_counter, False)) # start position, is_tuple + flatten_args.append(arg) + args_counter += 1 + + args_sign = tuple(args_sign) + flatten_args = tuple(flatten_args) + + result = make_custom_vjp_solver_fun(solver_fun, keys, args_sign).apply(*flatten_args, *vals) + if has_aux: + return result[:-1], result[-1] + return result + + return wrapped_solver_fun + + +def custom_root( + optimality_fun: Callable, + argnums: Union[int, Tuple[int, ...]] = 0, + has_aux: bool = False, + solve: Callable = linear_solve.solve_normal_cg, + reference_signature: Optional[Union[inspect.Signature, Callable]] = None, +) -> Callable[[Callable], Callable]: + """Decorator for adding implicit differentiation to a root solver. + + Args: + optimality_fun: (callable) + An equation function, ``optimality_fun(params, *args)``. The invariant is + ``optimality_fun(sol, *args) == 0`` at the solution / root of ``sol``. + argnums: (int or tuple of int, default: :const:`0`) + Specifies arguments to compute gradients with respect to. + has_aux: (default: :data:`False`) + Whether the decorated solver function returns auxiliary data. + solve: (callable, optional, default: :func:`linear_solve.solve_normal_cg`) + a linear solver of the form ``solve(matvec, b)``. + reference_signature: (function signature, optional) + Function signature (i.e. arguments and keyword arguments), with which the solver and + optimality functions are expected to agree. Defaults to ``optimality_fun``. It is + required that solver and optimality functions share the same input signature, but both + might be defined in such a way that the signature correspondence is ambiguous (e.g. if + both accept catch-all ``**kwargs``). To satisfy ``custom_root``'s requirement, any + function with an unambiguous signature can be provided here. + + Returns: + A solver function decorator, i.e., ``custom_root(optimality_fun)(solver_fun)``. + """ + if isinstance(argnums, int): + assert argnums != 0 + argnums = (argnums,) + else: + assert 0 not in argnums + + return functools.partial( + _custom_root, + optimality_fun=optimality_fun, + solve=solve, + argnums=argnums, + has_aux=has_aux, + reference_signature=reference_signature, + ) diff --git a/torchopt/_src/linalg.py b/torchopt/_src/linalg.py new file mode 100644 index 00000000..52810bdd --- /dev/null +++ b/torchopt/_src/linalg.py @@ -0,0 +1,214 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/google/jax/blob/main/jax/_src/scipy/sparse/linalg.py +# ============================================================================== +# Copyright 2020 Google LLC +# +# 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 +# +# https://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. +# ============================================================================== + +# pylint: disable=invalid-name + +from functools import partial +from typing import Callable, List, Optional, Union + +import torch + +from torchopt._src.typing import TensorTree +from torchopt._src.utils import pytree + + +def _inner_product_kernel(x: torch.Tensor, y: torch.Tensor) -> float: + """Computes (x.conj() * y).real.""" + x = x.view(-1) + y = y.view(-1) + prod = torch.dot(x.real, y.real).item() + if x.is_complex() or y.is_complex(): + prod += torch.dot(x.imag, y.imag).item() + return prod + + +def tree_inner_product(tree_x: TensorTree, tree_y: TensorTree) -> float: + """Computes (tree_x.conj() * tree_y).real.sum().""" + leaves_x, treedef = pytree.tree_flatten(tree_x) + leaves_y = treedef.flatten_up_to(tree_y) + return sum(map(_inner_product_kernel, leaves_x, leaves_y)) + + +def _identity(x: TensorTree) -> TensorTree: + return x + + +def _normalize_matvec( + f: Union[Callable[[TensorTree], TensorTree], torch.Tensor] +) -> Callable[[TensorTree], TensorTree]: + """Normalize an argument for computing matrix-vector products.""" + if callable(f): + return f + + assert isinstance(f, torch.Tensor) + if f.ndim != 2 or f.shape[0] != f.shape[1]: + raise ValueError(f'linear operator must be a square matrix, but has shape: {f.shape}') + return partial(torch.matmul, f) + + +# pylint: disable-next=too-many-locals +def _cg_solve( + A: Callable[[TensorTree], TensorTree], + b: TensorTree, + x0: TensorTree, + *, + maxiter: int, + rtol: float = 1e-5, + atol: float = 0.0, + M: Callable[[TensorTree], TensorTree] = _identity, +) -> TensorTree: + # https://en.wikipedia.org/wiki/Conjugate_gradient_method#The_preconditioned_conjugate_gradient_method + + # tolerance handling uses the "non-legacy" behavior of `scipy.sparse.linalg.cg` + bs = tree_inner_product(b, b) + atol2 = max(rtol**2 * bs, atol**2) + + def cond_fun(value): + _, r, gamma, _, k = value + rs = gamma if M is _identity else tree_inner_product(r, r) + return rs > atol2 and k < maxiter + + def body_fun(value): + x, r, gamma, p, k = value + Ap = A(p) + alpha = gamma / tree_inner_product(p, Ap) + x_ = pytree.tree_map(lambda a, b: a.add(b, alpha=alpha), x, p) + r_ = pytree.tree_map(lambda a, b: a.sub(b, alpha=alpha), r, Ap) + z_ = M(r_) + gamma_ = tree_inner_product(r_, z_) + beta_ = gamma_ / gamma + p_ = pytree.tree_map(lambda a, b: a.add(b, alpha=beta_), z_, p) + return x_, r_, gamma_, p_, k + 1 + + r0 = pytree.tree_map(torch.sub, b, A(x0)) + p0 = z0 = M(r0) + gamma0 = tree_inner_product(r0, z0) + + value = (x0, r0, gamma0, p0, 0) + while cond_fun(value): + value = body_fun(value) + + x_final, *_ = value + + return x_final + + +def _shapes(tree: TensorTree) -> List[int]: + flattened = pytree.tree_leaves(tree) + return pytree.tree_leaves([tuple(term.shape) for term in flattened]) + + +def _isolve( + _isolve_solve: Callable, + A: Union[torch.Tensor, Callable[[TensorTree], TensorTree]], + b: TensorTree, + x0: Optional[TensorTree] = None, + *, + rtol: float = 1e-5, + atol: float = 0.0, + maxiter: Optional[int] = None, + M: Optional[Union[torch.Tensor, Callable[[TensorTree], TensorTree]]] = None, +) -> TensorTree: + if x0 is None: + x0 = pytree.tree_map(torch.zeros_like, b) + + if maxiter is None: + size = sum(_shapes(b)) + maxiter = 10 * size # copied from SciPy + + if M is None: + M = _identity + A = _normalize_matvec(A) + M = _normalize_matvec(M) + + if _shapes(x0) != _shapes(b): + raise ValueError( + 'arrays in x0 and b must have matching shapes: ' f'{_shapes(x0)} vs {_shapes(b)}' + ) + + isolve_solve = partial(_isolve_solve, x0=x0, rtol=rtol, atol=atol, maxiter=maxiter, M=M) + + x = isolve_solve(A, b) + return x + + +def cg( + A: Union[torch.Tensor, Callable[[TensorTree], TensorTree]], + b: TensorTree, + x0: Optional[TensorTree] = None, + *, + rtol: float = 1e-5, + atol: float = 0.0, + maxiter: Optional[int] = None, + M: Optional[Union[torch.Tensor, Callable[[TensorTree], TensorTree]]] = None, +) -> TensorTree: + """Use Conjugate Gradient iteration to solve ``Ax = b``. + + The numerics of JAX's ``cg`` should exact match SciPy's ``cg`` (up to numerical precision), but + note that the interface is slightly different: you need to supply the linear operator ``A`` as a + function instead of a sparse matrix or ``LinearOperator``. + + Derivatives of :func:`cg` are implemented via implicit differentiation with another :func:`cg` + solve, rather than by differentiating *through* the solver. They will be accurate only if both + solves converge. + + Args: + A: (tensor or tree of tensors or function) + 2D array or function that calculates the linear map (matrix-vector + product) ``Ax`` when called like ``A(x)``. ``A`` must represent a + hermitian, positive definite matrix, and must return array(s) with the + same structure and shape as its argument. + b: (tensor or tree of tensors) + Right hand side of the linear system representing a single vector. Can be + stored as an array or Python container of array(s) with any shape. + x0: (tensor or tree of tensors, optional) + Starting guess for the solution. Must have the same structure as ``b``. + rtol: (float, optional, default: :const:`1e-5`) + Tolerances for convergence, ``norm(residual) <= max(rtol*norm(b), atol)``. We do not + implement SciPy's "legacy" behavior, so JAX's tolerance will differ from SciPy unless + you explicitly pass ``atol`` to SciPy's ``cg``. + atol: (float, optional, default: :const:`0.0`) + Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``. We do not + implement SciPy's "legacy" behavior, so JAX's tolerance will differ from SciPy unless + you explicitly pass ``atol`` to SciPy's ``cg``. + maxiter: (integer, optional) + Maximum number of iterations. Iteration will stop after maxiter steps even if the + specified tolerance has not been achieved. + M: (tensor or tree of tensors or function) + Pre-conditioner for ``A``. The pre-conditioner should approximate the inverse of ``A``. + Effective preconditioning dramatically improves the rate of convergence, which implies + that fewer iterations are needed to reach a given error tolerance. + + Returns: + the Conjugate Gradient (CG) linear solver + """ + return _isolve(_cg_solve, A=A, b=b, x0=x0, rtol=rtol, atol=atol, maxiter=maxiter, M=M) diff --git a/torchopt/_src/linear_solve.py b/torchopt/_src/linear_solve.py new file mode 100644 index 00000000..2b370d85 --- /dev/null +++ b/torchopt/_src/linear_solve.py @@ -0,0 +1,134 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/google/jaxopt/blob/main/jaxopt/_src/implicit_diff.py +# ============================================================================== +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. +# ============================================================================== + +# pylint: disable=invalid-name + +from typing import Callable, Optional + +import functorch + +from torchopt._src import linalg +from torchopt._src.typing import TensorTree +from torchopt._src.utils import pytree + + +def tree_add(tree_x: TensorTree, tree_y: TensorTree, alpha: float = 1.0) -> TensorTree: + """Computes tree_x + alpha * tree_y.""" + return pytree.tree_map(lambda x, y: x.add(y, alpha=alpha), tree_x, tree_y) + + +def _make_ridge_matvec( + matvec: Callable[[TensorTree], TensorTree], ridge: float = 0.0 +) -> Callable[[TensorTree], TensorTree]: + def ridge_matvec(v: TensorTree) -> TensorTree: + return tree_add(matvec(v), v, alpha=ridge) + + return ridge_matvec + + +def solve_cg( + matvec: Callable[[TensorTree], TensorTree], + b: TensorTree, + ridge: Optional[float] = None, + init: Optional[TensorTree] = None, + **kwargs, +) -> TensorTree: + """Solves ``A x = b`` using conjugate gradient. + + It assumes that ``A`` is a Hermitian, positive definite matrix. + + Args: + matvec: a function that returns the product between ``A`` and a vector. + b: a tree of tensors. + ridge: optional ridge regularization. + init: optional initialization to be used by conjugate gradient. + **kwargs: additional keyword arguments for solver. + + Returns: + The solution with the same structure as ``b``. + """ + if ridge is not None: + matvec = _make_ridge_matvec(matvec, ridge=ridge) + return linalg.cg(matvec, b, x0=init, **kwargs) + + +def _make_rmatvec( + matvec: Callable[[TensorTree], TensorTree], x: TensorTree +) -> Callable[[TensorTree], TensorTree]: + _, vjp, *_ = functorch.vjp(matvec, x) + return lambda y: vjp(y)[0] + + +def _normal_matvec(matvec: Callable[[TensorTree], TensorTree], x: TensorTree) -> TensorTree: + """Computes A^T A x from matvec(x) = A x.""" + matvec_x, vjp, *_ = functorch.vjp(matvec, x) + return vjp(matvec_x)[0] + + +def solve_normal_cg( + matvec: Callable[[TensorTree], TensorTree], + b: TensorTree, + ridge: Optional[float] = None, + init: Optional[TensorTree] = None, + **kwargs, +) -> TensorTree: + """Solves the normal equation ``A^T A x = A^T b`` using conjugate gradient. + + This can be used to solve Ax=b using conjugate gradient when A is not + hermitian, positive definite. + + Args: + matvec: product between ``A`` and a vector. + b: pytree. + ridge: optional ridge regularization. + init: optional initialization to be used by normal conjugate gradient. + **kwargs: additional keyword arguments for solver. + + Returns: + The solution with the same structure as ``b``. + """ + if init is None: + example_x = b # This assumes that matvec is a square linear operator. + else: + example_x = init + + rmatvec = _make_rmatvec(matvec, example_x) + + def normal_matvec(x): + return _normal_matvec(matvec, x) + + if ridge is not None: + normal_matvec = _make_ridge_matvec(normal_matvec, ridge=ridge) + + Ab = rmatvec(b) # A.T b + + return linalg.cg(normal_matvec, Ab, x0=init, **kwargs) diff --git a/torchopt/_src/visual.py b/torchopt/_src/visual.py index edf052bc..ee493c6d 100644 --- a/torchopt/_src/visual.py +++ b/torchopt/_src/visual.py @@ -148,7 +148,7 @@ def get_var_name_with_flag(var): return f'{param_map[var][0]}\n{size_to_str(param_map[var][1].size())}' return None - def add_nodes(fn): + def add_nodes(fn): # pylint: disable=too-many-branches assert not torch.is_tensor(fn) if fn in seen: return From dff6188a6723ff91cd9e469fb71185a7e87f9704 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 9 Sep 2022 16:04:24 +0800 Subject: [PATCH 04/69] fix: change counts to scalar tensors (#71) --- .github/workflows/build.yml | 23 +++++++++++++++++++++++ CHANGELOG.md | 2 +- torchopt/_src/transform.py | 6 +++--- torchopt/version.py | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b330e07e..6900ab0a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,6 +58,14 @@ jobs: python-version: "3.7 - 3.10" update-environment: true + - name: Set __release__ + if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' + run: | + sed -i -E 's/^__release__\s*=.*$/__release__ = True/' torchopt/version.py + + - name: Print version + run: python setup.py --version + - name: Install dependencies run: python -m pip install --upgrade pip setuptools wheel build @@ -83,6 +91,21 @@ jobs: submodules: "recursive" fetch-depth: 0 + - name: Set up Python + id: py + uses: actions/setup-python@v4 + with: + python-version: "3.7 - 3.10" + update-environment: true + + - name: Set __release__ + if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' + run: | + sed -i -E 's/^__release__\s*=.*$/__release__ = True/' torchopt/version.py + + - name: Print version + run: python setup.py --version + - name: Build wheels uses: pypa/cibuildwheel@v2.8.1 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ee3c27c..906e43a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - +- Fix the step count tensor (`shape=(1,)`) can change the shape of the scalar updates (`shape=()`) by [@XuehaiPan](https://github.com/XuehaiPan) in [#71](https://github.com/metaopt/torchopt/pull/71). ### Removed diff --git a/torchopt/_src/transform.py b/torchopt/_src/transform.py index 15bf11ed..558dbe0e 100644 --- a/torchopt/_src/transform.py +++ b/torchopt/_src/transform.py @@ -161,7 +161,7 @@ def _scale_by_schedule( def init_fn(params): zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int32, device=t.device), params + lambda t: torch.zeros(1, dtype=torch.int32, device=t.device).squeeze_(), params ) return ScaleByScheduleState(count=zero) @@ -299,7 +299,7 @@ def _scale_by_adam( def init_fn(params): zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int32, device=t.device), params + lambda t: torch.zeros(1, dtype=torch.int32, device=t.device).squeeze_(), params ) mu = tree_map( # first moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params @@ -426,7 +426,7 @@ def update_fn(updates, state, *, params=None, inplace=True): def init_fn(params): zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int32, device=t.device), params + lambda t: torch.zeros(1, dtype=torch.int32, device=t.device).squeeze_(), params ) mu = tree_map( # first moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params diff --git a/torchopt/version.py b/torchopt/version.py index b79568e7..9c3e1646 100644 --- a/torchopt/version.py +++ b/torchopt/version.py @@ -15,3 +15,37 @@ """TorchOpt: a high-performance optimizer library built upon PyTorch.""" __version__ = '0.5.0' +__license__ = 'Apache License, Version 2.0' +__author__ = 'TorchOpt Contributors' +__release__ = False + +if not __release__: + import os + import subprocess + + try: + prefix, sep, suffix = ( + subprocess.check_output( + ['git', 'describe', '--abbrev=7'], + cwd=os.path.dirname(os.path.abspath(__file__)), + stderr=subprocess.DEVNULL, + universal_newlines=True, + ) + .strip() + .lstrip('v') + .replace('-', '.dev', 1) + .replace('-', '+', 1) + .partition('.dev') + ) + if sep: + version_prefix, dot, version_tail = prefix.rpartition('.') + prefix = f'{version_prefix}{dot}{int(version_tail) + 1}' + __version__ = sep.join((prefix, suffix)) + del version_prefix, dot, version_tail + else: + __version__ = prefix + del prefix, sep, suffix + except (OSError, subprocess.CalledProcessError): + pass + + del os, subprocess From d1b1898220778c3de83149c96e84b3f478db23d2 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Fri, 9 Sep 2022 16:52:32 +0800 Subject: [PATCH 05/69] fix(tutorials): update notebook links (#72) --- tutorials/1_Functional_Optimizer.ipynb | 4 +- tutorials/2_Visualization.ipynb | 515 +++++++++- tutorials/3_Meta_Optimizer.ipynb | 1087 +++++++++++++++++++- tutorials/4_Stop_Gradient.ipynb | 1273 +++++++++++++++++++++++- 4 files changed, 2861 insertions(+), 18 deletions(-) diff --git a/tutorials/1_Functional_Optimizer.ipynb b/tutorials/1_Functional_Optimizer.ipynb index f4194835..e0e82885 100644 --- a/tutorials/1_Functional_Optimizer.ipynb +++ b/tutorials/1_Functional_Optimizer.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "[](https://colab.research.google.com/drive/1yfi-ETyIptlIM7WFYWF_IFhX4WF3LldP?usp=sharing)" + "[](https://colab.research.google.com/github/metaopt/torchopt/blob/main/tutorials/1_Functional_Optimizer.ipynb)" ] }, { @@ -490,7 +490,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.8.13 64-bit", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/tutorials/2_Visualization.ipynb b/tutorials/2_Visualization.ipynb index f1af008f..061d71fd 100644 --- a/tutorials/2_Visualization.ipynb +++ b/tutorials/2_Visualization.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "[](https://colab.research.google.com/drive/1Uoo2epqZKmJNQOiO0EU8DGd33AVKBlAq?usp=sharing)" + "[](https://colab.research.google.com/github/metaopt/torchopt/blob/main/tutorials/2_Visualization.ipynb)" ] }, { @@ -42,7 +42,65 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n139996637621680\n\ny\n ()\n\n\n\n139993377217744\n\nMulBackward0\n\n\n\n139993377217744->139996637621680\n\n\n\n\n\n139993377217840\n\nAccumulateGrad\n\n\n\n139993377217840->139993377217744\n\n\n\n\n\n139996637619360\n\nx\n ()\n\n\n\n139996637619360->139993377217840\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "139996637621680\n", + "\n", + "y\n", + " ()\n", + "\n", + "\n", + "\n", + "139993377217744\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139993377217744->139996637621680\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993377217840\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139993377217840->139993377217744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139996637619360\n", + "\n", + "x\n", + " ()\n", + "\n", + "\n", + "\n", + "139996637619360->139993377217840\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -91,7 +149,114 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n139993376880096\n\nloss\n ()\n\n\n\n139996875678480\n\nMseLossBackward0\n\n\n\n139996875678480->139993376880096\n\n\n\n\n\n139996875677952\n\nAddmmBackward0\n\n\n\n139996875677952->139996875678480\n\n\n\n\n\n139996875678336\n\nAccumulateGrad\n\n\n\n139996875678336->139996875677952\n\n\n\n\n\n139993376879696\n\nfc.bias\n (1)\n\n\n\n139993376879696->139996875678336\n\n\n\n\n\n139996875678912\n\nTBackward0\n\n\n\n139996875678912->139996875677952\n\n\n\n\n\n139996875679152\n\nAccumulateGrad\n\n\n\n139996875679152->139996875678912\n\n\n\n\n\n139993376879616\n\nfc.weight\n (1, 5)\n\n\n\n139993376879616->139996875679152\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "139993376880096\n", + "\n", + "loss\n", + " ()\n", + "\n", + "\n", + "\n", + "139996875678480\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "139996875678480->139993376880096\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139996875677952\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139996875677952->139996875678480\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139996875678336\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139996875678336->139996875677952\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376879696\n", + "\n", + "fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139993376879696->139996875678336\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139996875678912\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139996875678912->139996875677952\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139996875679152\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139996875679152->139996875678912\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376879616\n", + "\n", + "fc.weight\n", + " (1, 5)\n", + "\n", + "\n", + "\n", + "139993376879616->139996875679152\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -139,7 +304,347 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n139993376892384\n\nloss\n ()\n\n\n\n139993376862752\n\nMseLossBackward0\n\n\n\n139993376862752->139993376892384\n\n\n\n\n\n139993376862800\n\nAddBackward0\n\n\n\n139993376862800->139993376862752\n\n\n\n\n\n139993376862896\n\nAddmmBackward0\n\n\n\n139993376862896->139993376862800\n\n\n\n\n\n139993377217840\n\nAddBackward0\n step1.fc.bias\n (1)\n\n\n\n139993377217840->139993376862896\n\n\n\n\n\n139993376863136\n\nAccumulateGrad\n\n\n\n139993376863136->139993377217840\n\n\n\n\n\n139993376863664\n\nAddmmBackward0\n\n\n\n139993376863136->139993376863664\n\n\n\n\n\n139993376891904\n\nstep0.fc.bias\n (1)\n\n\n\n139993376891904->139993376863136\n\n\n\n\n\n139993376863088\n\nMulBackward0\n\n\n\n139993376863088->139993377217840\n\n\n\n\n\n139993376863184\n\nViewBackward0\n\n\n\n139993376863184->139993376863088\n\n\n\n\n\n139993376863376\n\nSumBackward1\n\n\n\n139993376863376->139993376863184\n\n\n\n\n\n139993376863472\n\nMseLossBackwardBackward0\n\n\n\n139993376863472->139993376863376\n\n\n\n\n\n139993376864000\n\nTBackward0\n\n\n\n139993376863472->139993376864000\n\n\n\n\n\n139993376863568\n\nAddBackward0\n\n\n\n139993376863568->139993376863472\n\n\n\n\n\n139993376863664->139993376863568\n\n\n\n\n\n139993376863760\n\nTBackward0\n\n\n\n139993376863760->139993376863664\n\n\n\n\n\n139993376863856\n\nAccumulateGrad\n\n\n\n139993376863856->139993376863760\n\n\n\n\n\n139993377218464\n\nAddBackward0\n step1.fc.weight\n (1, 5)\n\n\n\n139993376863856->139993377218464\n\n\n\n\n\n139993376891664\n\nstep0.fc.weight\n (1, 5)\n\n\n\n139993376891664->139993376863856\n\n\n\n\n\n139993376862848\n\nAccumulateGrad\n\n\n\n139993376862848->139993376862800\n\n\n\n\n\n139993376862848->139993376863568\n\n\n\n\n\n139996637619600\n\nmeta_param\n ()\n\n\n\n139996637619600->139993376862848\n\n\n\n\n\n139993376863040\n\nTBackward0\n\n\n\n139993376863040->139993376862896\n\n\n\n\n\n139993377218464->139993376863040\n\n\n\n\n\n139993376863424\n\nMulBackward0\n\n\n\n139993376863424->139993377218464\n\n\n\n\n\n139993376863616\n\nTBackward0\n\n\n\n139993376863616->139993376863424\n\n\n\n\n\n139993376863808\n\nTBackward0\n\n\n\n139993376863808->139993376863616\n\n\n\n\n\n139993376863904\n\nMmBackward0\n\n\n\n139993376863904->139993376863808\n\n\n\n\n\n139993376864000->139993376863904\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "139993376892384\n", + "\n", + "loss\n", + " ()\n", + "\n", + "\n", + "\n", + "139993376862752\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "139993376862752->139993376892384\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376862800\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "139993376862800->139993376862752\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376862896\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139993376862896->139993376862800\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993377217840\n", + "\n", + "AddBackward0\n", + " step1.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139993377217840->139993376862896\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863136\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139993376863136->139993377217840\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863664\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139993376863136->139993376863664\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376891904\n", + "\n", + "step0.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139993376891904->139993376863136\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863088\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139993376863088->139993377217840\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863184\n", + "\n", + "ViewBackward0\n", + "\n", + "\n", + "\n", + "139993376863184->139993376863088\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863376\n", + "\n", + "SumBackward1\n", + "\n", + "\n", + "\n", + "139993376863376->139993376863184\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863472\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "139993376863472->139993376863376\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376864000\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139993376863472->139993376864000\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863568\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "139993376863568->139993376863472\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863664->139993376863568\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863760\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139993376863760->139993376863664\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863856\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139993376863856->139993376863760\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993377218464\n", + "\n", + "AddBackward0\n", + " step1.fc.weight\n", + " (1, 5)\n", + "\n", + "\n", + "\n", + "139993376863856->139993377218464\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376891664\n", + "\n", + "step0.fc.weight\n", + " (1, 5)\n", + "\n", + "\n", + "\n", + "139993376891664->139993376863856\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376862848\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139993376862848->139993376862800\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376862848->139993376863568\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139996637619600\n", + "\n", + "meta_param\n", + " ()\n", + "\n", + "\n", + "\n", + "139996637619600->139993376862848\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863040\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139993376863040->139993376862896\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993377218464->139993376863040\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863424\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139993376863424->139993377218464\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863616\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139993376863616->139993376863424\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863808\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139993376863808->139993376863616\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376863904\n", + "\n", + "MmBackward0\n", + "\n", + "\n", + "\n", + "139993376863904->139993376863808\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139993376864000->139993376863904\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -185,7 +690,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.8.13 ('torchopt')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/tutorials/3_Meta_Optimizer.ipynb b/tutorials/3_Meta_Optimizer.ipynb index aaca9e3f..f92da67b 100644 --- a/tutorials/3_Meta_Optimizer.ipynb +++ b/tutorials/3_Meta_Optimizer.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "[](https://colab.research.google.com/drive/1lo9q2gQz073urYln-4Yub5s8APUoHvQJ?usp=sharing)" + "[](https://colab.research.google.com/github/metaopt/torchopt/blob/main/tutorials/3_Meta_Optimizer.ipynb)" ] }, { @@ -161,7 +161,332 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n140393111569088\n\nouter_loss\n ()\n\n\n\n140393111544592\n\nMseLossBackward0\n\n\n\n140393111544592->140393111569088\n\n\n\n\n\n140393111544736\n\nMulBackward0\n\n\n\n140393111544736->140393111544592\n\n\n\n\n\n140396237940576\n\nAddBackward0\n step1.a\n ()\n\n\n\n140396237940576->140393111544736\n\n\n\n\n\n140393111545216\n\nAccumulateGrad\n\n\n\n140393111545216->140396237940576\n\n\n\n\n\n140393111545984\n\nMulBackward0\n\n\n\n140393111545216->140393111545984\n\n\n\n\n\n140393111534464\n\nstep0.a\n ()\n\n\n\n140393111534464->140393111545216\n\n\n\n\n\n140393111544112\n\nMulBackward0\n\n\n\n140393111544112->140396237940576\n\n\n\n\n\n140393111545168\n\nDivBackward0\n\n\n\n140393111545168->140393111544112\n\n\n\n\n\n140393111545408\n\nDivBackward0\n\n\n\n140393111545408->140393111545168\n\n\n\n\n\n140393111545552\n\nAddBackward0\n\n\n\n140393111545552->140393111545408\n\n\n\n\n\n140393111545648\n\nPowBackward0\n\n\n\n140393111545648->140393111545552\n\n\n\n\n\n140393111545744\n\nMulBackward0\n\n\n\n140393111545744->140393111545648\n\n\n\n\n\n140393111546272\n\nPowBackward0\n\n\n\n140393111545744->140393111546272\n\n\n\n\n\n140393111545840\n\nMseLossBackwardBackward0\n\n\n\n140393111545840->140393111545744\n\n\n\n\n\n140393111545984->140393111545840\n\n\n\n\n\n140393111545792\n\nPowBackward0\n\n\n\n140393111545792->140393111545744\n\n\n\n\n\n140393111545792->140393111545984\n\n\n\n\n\n140393111546128\n\nAccumulateGrad\n\n\n\n140393111546128->140393111545792\n\n\n\n\n\n140393111545024\n\nPowBackward0\n\n\n\n140393111546128->140393111545024\n\n\n\n\n\n140393111534624\n\nx\n ()\n\n\n\n140393111534624->140393111546128\n\n\n\n\n\n140393111545360\n\nAddBackward0\n\n\n\n140393111545360->140393111545168\n\n\n\n\n\n140393111545696\n\nSqrtBackward0\n\n\n\n140393111545696->140393111545360\n\n\n\n\n\n140393111545936\n\nAddBackward0\n\n\n\n140393111545936->140393111545696\n\n\n\n\n\n140393111545888\n\nDivBackward0\n\n\n\n140393111545888->140393111545936\n\n\n\n\n\n140393111546176\n\nAddBackward0\n\n\n\n140393111546176->140393111545888\n\n\n\n\n\n140393111546272->140393111546176\n\n\n\n\n\n140393111545024->140393111544736\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "140393111569088\n", + "\n", + "outer_loss\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111544592\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "140393111544592->140393111569088\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544736\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111544736->140393111544592\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140396237940576\n", + "\n", + "AddBackward0\n", + " step1.a\n", + " ()\n", + "\n", + "\n", + "\n", + "140396237940576->140393111544736\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545216\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393111545216->140396237940576\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545984\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111545216->140393111545984\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111534464\n", + "\n", + "step0.a\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111534464->140393111545216\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544112\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111544112->140396237940576\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545168\n", + "\n", + "DivBackward0\n", + "\n", + "\n", + "\n", + "140393111545168->140393111544112\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545408\n", + "\n", + "DivBackward0\n", + "\n", + "\n", + "\n", + "140393111545408->140393111545168\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545552\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111545552->140393111545408\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545648\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111545648->140393111545552\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545744\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111545744->140393111545648\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546272\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111545744->140393111546272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545840\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "140393111545840->140393111545744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545984->140393111545840\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545792\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111545792->140393111545744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545792->140393111545984\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546128\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393111546128->140393111545792\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545024\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111546128->140393111545024\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111534624\n", + "\n", + "x\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111534624->140393111546128\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545360\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111545360->140393111545168\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545696\n", + "\n", + "SqrtBackward0\n", + "\n", + "\n", + "\n", + "140393111545696->140393111545360\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545936\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111545936->140393111545696\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545888\n", + "\n", + "DivBackward0\n", + "\n", + "\n", + "\n", + "140393111545888->140393111545936\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546176\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111546176->140393111545888\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546272->140393111546176\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545024->140393111544736\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -204,7 +529,404 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n140393102737552\n\nouter_loss\n ()\n\n\n\n140393111544400\n\nMseLossBackward0\n\n\n\n140393111544400->140393102737552\n\n\n\n\n\n140393111544304\n\nMulBackward0\n\n\n\n140393111544304->140393111544400\n\n\n\n\n\n140396584753232\n\nAddBackward0\n step1.a\n ()\n\n\n\n140396584753232->140393111544304\n\n\n\n\n\n140393111544016\n\nAccumulateGrad\n\n\n\n140393111544016->140396584753232\n\n\n\n\n\n140393111547280\n\nMulBackward0\n\n\n\n140393111544016->140393111547280\n\n\n\n\n\n140393111570848\n\nstep0.a\n ()\n\n\n\n140393111570848->140393111544016\n\n\n\n\n\n140393111544256\n\nMulBackward0\n\n\n\n140393111544256->140396584753232\n\n\n\n\n\n140393111544160\n\nDivBackward0\n\n\n\n140393111544160->140393111544256\n\n\n\n\n\n140393111546512\n\nDivBackward0\n\n\n\n140393111546512->140393111544160\n\n\n\n\n\n140393111544112\n\nAddBackward0\n\n\n\n140393111544112->140393111546512\n\n\n\n\n\n140393111546368\n\nMulBackward0\n\n\n\n140393111546368->140393111544112\n\n\n\n\n\n140393111547040\n\nAccumulateGrad\n\n\n\n140393111547040->140393111546368\n\n\n\n\n\n140393111569408\n\n ()\n\n\n\n140393111569408->140393111547040\n\n\n\n\n\n140393111546272\n\nPowBackward0\n\n\n\n140393111546272->140393111544112\n\n\n\n\n\n140393111547088\n\nMulBackward0\n\n\n\n140393111547088->140393111546272\n\n\n\n\n\n140393111547328\n\nPowBackward0\n\n\n\n140393111547088->140393111547328\n\n\n\n\n\n140393111547184\n\nMseLossBackwardBackward0\n\n\n\n140393111547184->140393111547088\n\n\n\n\n\n140393111547280->140393111547184\n\n\n\n\n\n140393111546944\n\nPowBackward0\n\n\n\n140393111546944->140393111547088\n\n\n\n\n\n140393111546944->140393111547280\n\n\n\n\n\n140393111546320\n\nAccumulateGrad\n\n\n\n140393111546320->140393111546944\n\n\n\n\n\n140393111544208\n\nPowBackward0\n\n\n\n140393111546320->140393111544208\n\n\n\n\n\n140393111571168\n\nx\n ()\n\n\n\n140393111571168->140393111546320\n\n\n\n\n\n140393111546848\n\nAddBackward0\n\n\n\n140393111546848->140393111544160\n\n\n\n\n\n140393111547136\n\nSqrtBackward0\n\n\n\n140393111547136->140393111546848\n\n\n\n\n\n140393111547232\n\nAddBackward0\n\n\n\n140393111547232->140393111547136\n\n\n\n\n\n140393111545360\n\nDivBackward0\n\n\n\n140393111545360->140393111547232\n\n\n\n\n\n140393111547424\n\nAddBackward0\n\n\n\n140393111547424->140393111545360\n\n\n\n\n\n140393111547520\n\nMulBackward0\n\n\n\n140393111547520->140393111547424\n\n\n\n\n\n140393111547616\n\nAccumulateGrad\n\n\n\n140393111547616->140393111547520\n\n\n\n\n\n140393111570288\n\n ()\n\n\n\n140393111570288->140393111547616\n\n\n\n\n\n140393111547328->140393111547424\n\n\n\n\n\n140393111544208->140393111544304\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "140393102737552\n", + "\n", + "outer_loss\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111544400\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "140393111544400->140393102737552\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544304\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111544304->140393111544400\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140396584753232\n", + "\n", + "AddBackward0\n", + " step1.a\n", + " ()\n", + "\n", + "\n", + "\n", + "140396584753232->140393111544304\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544016\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393111544016->140396584753232\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547280\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111544016->140393111547280\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111570848\n", + "\n", + "step0.a\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111570848->140393111544016\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544256\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111544256->140396584753232\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544160\n", + "\n", + "DivBackward0\n", + "\n", + "\n", + "\n", + "140393111544160->140393111544256\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546512\n", + "\n", + "DivBackward0\n", + "\n", + "\n", + "\n", + "140393111546512->140393111544160\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544112\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111544112->140393111546512\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546368\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111546368->140393111544112\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547040\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393111547040->140393111546368\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111569408\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111569408->140393111547040\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546272\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111546272->140393111544112\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547088\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111547088->140393111546272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547328\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111547088->140393111547328\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547184\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "140393111547184->140393111547088\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547280->140393111547184\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546944\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111546944->140393111547088\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546944->140393111547280\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546320\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393111546320->140393111546944\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544208\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393111546320->140393111544208\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111571168\n", + "\n", + "x\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111571168->140393111546320\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546848\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111546848->140393111544160\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547136\n", + "\n", + "SqrtBackward0\n", + "\n", + "\n", + "\n", + "140393111547136->140393111546848\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547232\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111547232->140393111547136\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111545360\n", + "\n", + "DivBackward0\n", + "\n", + "\n", + "\n", + "140393111545360->140393111547232\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547424\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "140393111547424->140393111545360\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547520\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111547520->140393111547424\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547616\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393111547616->140393111547520\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111570288\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111570288->140393111547616\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111547328->140393111547424\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111544208->140393111544304\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -525,7 +1247,362 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n140393102828544\n\nouter_loss\n ()\n\n\n\n140393111546128\n\nMseLossBackward0\n\n\n\n140393111546128->140393102828544\n\n\n\n\n\n140393111546032\n\nMulBackward0\n\n\n\n140393111546032->140393111546128\n\n\n\n\n\n140396237940288\n\nAddBackward0\n step1.a\n ()\n\n\n\n140396237940288->140393111546032\n\n\n\n\n\n140393111546464\n\nAccumulateGrad\n\n\n\n140393111546464->140396237940288\n\n\n\n\n\n140393102725760\n\nMulBackward0\n\n\n\n140393111546464->140393102725760\n\n\n\n\n\n140393102827744\n\nstep0.a\n ()\n\n\n\n140393102827744->140393111546464\n\n\n\n\n\n140393102725232\n\nMulBackward0\n\n\n\n140393102725232->140396237940288\n\n\n\n\n\n140393112318976\n\nUpdatesOpBackward\n\n\n\n140393112318976->140393102725232\n\n\n\n\n\n140396647894368\n\nMuOpBackward\n\n\n\n140396647894368->140393112318976\n\n\n\n\n\n140393102725472\n\nMulBackward0\n\n\n\n140393102725472->140396647894368\n\n\n\n\n\n140393112318736\n\nNuOpBackward\n\n\n\n140393102725472->140393112318736\n\n\n\n\n\n140393102725616\n\nMseLossBackwardBackward0\n\n\n\n140393102725616->140393102725472\n\n\n\n\n\n140393102725760->140393102725616\n\n\n\n\n\n140393102725568\n\nPowBackward0\n\n\n\n140393102725568->140393102725472\n\n\n\n\n\n140393102725568->140393102725760\n\n\n\n\n\n140393102725904\n\nAccumulateGrad\n\n\n\n140393102725904->140393102725568\n\n\n\n\n\n140393111543968\n\nPowBackward0\n\n\n\n140393102725904->140393111543968\n\n\n\n\n\n140393111485872\n\nx\n ()\n\n\n\n140393111485872->140393102725904\n\n\n\n\n\n140393102725328\n\nAccumulateGrad\n\n\n\n140393102725328->140396647894368\n\n\n\n\n\n140393111534224\n\n ()\n\n\n\n140393111534224->140396647894368\n\n\n\n\n\n140393111534224->140393102725328\n\n\n\n\n\n140393111531904\n\n ()\n\n\n\n140393111531904->140396647894368\n\n\n\n\n\n140393111531904->140393112318736\n\n\n\n\n\n140393112318736->140393112318976\n\n\n\n\n\n140393102725712\n\nAccumulateGrad\n\n\n\n140393102725712->140393112318736\n\n\n\n\n\n140393102827824\n\n ()\n\n\n\n140393102827824->140393112318736\n\n\n\n\n\n140393102827824->140393102725712\n\n\n\n\n\n140393102828784\n\n ()\n\n\n\n140393102828784->140393112318976\n\n\n\n\n\n140393102828144\n\n ()\n\n\n\n140393102828144->140393112318976\n\n\n\n\n\n140393102828224\n\n ()\n\n\n\n140393102828224->140393112318976\n\n\n\n\n\n140393111543968->140393111546032\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "140393102828544\n", + "\n", + "outer_loss\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111546128\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "140393111546128->140393102828544\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546032\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111546032->140393111546128\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140396237940288\n", + "\n", + "AddBackward0\n", + " step1.a\n", + " ()\n", + "\n", + "\n", + "\n", + "140396237940288->140393111546032\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111546464\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393111546464->140396237940288\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725760\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393111546464->140393102725760\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102827744\n", + "\n", + "step0.a\n", + " ()\n", + "\n", + "\n", + "\n", + "140393102827744->140393111546464\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725232\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393102725232->140396237940288\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393112318976\n", + "\n", + "UpdatesOpBackward\n", + "\n", + "\n", + "\n", + "140393112318976->140393102725232\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140396647894368\n", + "\n", + "MuOpBackward\n", + "\n", + "\n", + "\n", + "140396647894368->140393112318976\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725472\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "140393102725472->140396647894368\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393112318736\n", + "\n", + "NuOpBackward\n", + "\n", + "\n", + "\n", + "140393102725472->140393112318736\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725616\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "140393102725616->140393102725472\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725760->140393102725616\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725568\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393102725568->140393102725472\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725568->140393102725760\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725904\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393102725904->140393102725568\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111543968\n", + "\n", + "PowBackward0\n", + "\n", + "\n", + "\n", + "140393102725904->140393111543968\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111485872\n", + "\n", + "x\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111485872->140393102725904\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725328\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393102725328->140396647894368\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111534224\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111534224->140396647894368\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111534224->140393102725328\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111531904\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393111531904->140396647894368\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111531904->140393112318736\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393112318736->140393112318976\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102725712\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "140393102725712->140393112318736\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102827824\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393102827824->140393112318736\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102827824->140393102725712\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102828784\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393102828784->140393112318976\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102828144\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393102828144->140393112318976\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393102828224\n", + "\n", + " ()\n", + "\n", + "\n", + "\n", + "140393102828224->140393112318976\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "140393111543968->140393111546032\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -550,7 +1627,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.8.13 ('torchopt')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/tutorials/4_Stop_Gradient.ipynb b/tutorials/4_Stop_Gradient.ipynb index 604196ca..8096afa0 100644 --- a/tutorials/4_Stop_Gradient.ipynb +++ b/tutorials/4_Stop_Gradient.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "[](https://colab.research.google.com/drive/1jp_oPHIG6aaQMYGNxG72FSuWjABk1DHo?usp=sharing)" + "[](https://colab.research.google.com/github/metaopt/torchopt/blob/main/tutorials/4_Stop_Gradient.ipynb)" ] }, { @@ -109,7 +109,114 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n139978828415600\n\ninner_loss\n ()\n\n\n\n139978603488640\n\nMseLossBackward0\n\n\n\n139978603488640->139978828415600\n\n\n\n\n\n139978603489744\n\nAddmmBackward0\n\n\n\n139978603489744->139978603488640\n\n\n\n\n\n139978603490800\n\nAccumulateGrad\n\n\n\n139978603490800->139978603489744\n\n\n\n\n\n139975938634512\n\nstep0.fc.bias\n (1)\n\n\n\n139975938634512->139978603490800\n\n\n\n\n\n139978603490224\n\nTBackward0\n\n\n\n139978603490224->139978603489744\n\n\n\n\n\n139978603490368\n\nAccumulateGrad\n\n\n\n139978603490368->139978603490224\n\n\n\n\n\n139975938634432\n\nstep0.fc.weight\n (1, 16)\n\n\n\n139975938634432->139978603490368\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "139978828415600\n", + "\n", + "inner_loss\n", + " ()\n", + "\n", + "\n", + "\n", + "139978603488640\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "139978603488640->139978828415600\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603489744\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139978603489744->139978603488640\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603490800\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139978603490800->139978603489744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938634512\n", + "\n", + "step0.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139975938634512->139978603490800\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603490224\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139978603490224->139978603489744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603490368\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139978603490368->139978603490224\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938634432\n", + "\n", + "step0.fc.weight\n", + " (1, 16)\n", + "\n", + "\n", + "\n", + "139975938634432->139978603490368\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -174,7 +281,329 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n139975938634752\n\nouter_loss\n ()\n\n\n\n139975938188288\n\nMseLossBackward0\n\n\n\n139975938188288->139975938634752\n\n\n\n\n\n139975938188336\n\nAddmmBackward0\n\n\n\n139975938188336->139975938188288\n\n\n\n\n\n139975938188096\n\nAddBackward0\n step1.fc.bias\n (1)\n\n\n\n139975938188096->139975938188336\n\n\n\n\n\n139978603490800\n\nAccumulateGrad\n\n\n\n139978603490800->139975938188096\n\n\n\n\n\n139978603489744\n\nAddmmBackward0\n\n\n\n139978603490800->139978603489744\n\n\n\n\n\n139975938634512\n\nstep0.fc.bias\n (1)\n\n\n\n139975938634512->139978603490800\n\n\n\n\n\n139975938188480\n\nMulBackward0\n\n\n\n139975938188480->139975938188096\n\n\n\n\n\n139975938188144\n\nViewBackward0\n\n\n\n139975938188144->139975938188480\n\n\n\n\n\n139975938187664\n\nSumBackward1\n\n\n\n139975938187664->139975938188144\n\n\n\n\n\n139975938188720\n\nMseLossBackwardBackward0\n\n\n\n139975938188720->139975938187664\n\n\n\n\n\n139975938189200\n\nTBackward0\n\n\n\n139975938188720->139975938189200\n\n\n\n\n\n139975938188816\n\nMulBackward0\n\n\n\n139975938188816->139975938188720\n\n\n\n\n\n139975938188912\n\nAccumulateGrad\n\n\n\n139975938188912->139975938188816\n\n\n\n\n\n139975938635072\n\nmeta_parameter\n ()\n\n\n\n139975938635072->139975938188912\n\n\n\n\n\n139978603489744->139975938188720\n\n\n\n\n\n139978603490224\n\nTBackward0\n\n\n\n139978603490224->139978603489744\n\n\n\n\n\n139978603490368\n\nAccumulateGrad\n\n\n\n139978603490368->139978603490224\n\n\n\n\n\n139975938187808\n\nAddBackward0\n step1.fc.weight\n (1, 16)\n\n\n\n139978603490368->139975938187808\n\n\n\n\n\n139975938634432\n\nstep0.fc.weight\n (1, 16)\n\n\n\n139975938634432->139978603490368\n\n\n\n\n\n139975938188384\n\nTBackward0\n\n\n\n139975938188384->139975938188336\n\n\n\n\n\n139975938187808->139975938188384\n\n\n\n\n\n139975938188672\n\nMulBackward0\n\n\n\n139975938188672->139975938187808\n\n\n\n\n\n139975938189008\n\nTBackward0\n\n\n\n139975938189008->139975938188672\n\n\n\n\n\n139975938189104\n\nTBackward0\n\n\n\n139975938189104->139975938189008\n\n\n\n\n\n139975938188864\n\nMmBackward0\n\n\n\n139975938188864->139975938189104\n\n\n\n\n\n139975938189200->139975938188864\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "139975938634752\n", + "\n", + "outer_loss\n", + " ()\n", + "\n", + "\n", + "\n", + "139975938188288\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "139975938188288->139975938634752\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188336\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139975938188336->139975938188288\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188096\n", + "\n", + "AddBackward0\n", + " step1.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139975938188096->139975938188336\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603490800\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139978603490800->139975938188096\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603489744\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139978603490800->139978603489744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938634512\n", + "\n", + "step0.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139975938634512->139978603490800\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188480\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938188480->139975938188096\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188144\n", + "\n", + "ViewBackward0\n", + "\n", + "\n", + "\n", + "139975938188144->139975938188480\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187664\n", + "\n", + "SumBackward1\n", + "\n", + "\n", + "\n", + "139975938187664->139975938188144\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188720\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "139975938188720->139975938187664\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189200\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938188720->139975938189200\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188816\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938188816->139975938188720\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188912\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139975938188912->139975938188816\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938635072\n", + "\n", + "meta_parameter\n", + " ()\n", + "\n", + "\n", + "\n", + "139975938635072->139975938188912\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603489744->139975938188720\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603490224\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139978603490224->139978603489744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139978603490368\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139978603490368->139978603490224\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187808\n", + "\n", + "AddBackward0\n", + " step1.fc.weight\n", + " (1, 16)\n", + "\n", + "\n", + "\n", + "139978603490368->139975938187808\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938634432\n", + "\n", + "step0.fc.weight\n", + " (1, 16)\n", + "\n", + "\n", + "\n", + "139975938634432->139978603490368\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188384\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938188384->139975938188336\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187808->139975938188384\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188672\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938188672->139975938187808\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189008\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938189008->139975938188672\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189104\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938189104->139975938189008\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188864\n", + "\n", + "MmBackward0\n", + "\n", + "\n", + "\n", + "139975938188864->139975938189104\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189200->139975938188864\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -265,7 +694,521 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n139978828415600\n\nouter_loss\n ()\n\n\n\n139975938626944\n\nMseLossBackward0\n\n\n\n139975938626944->139978828415600\n\n\n\n\n\n139975938626656\n\nAddmmBackward0\n\n\n\n139975938626656->139975938626944\n\n\n\n\n\n139975938188624\n\nAddBackward0\n\n\n\n139975938188624->139975938626656\n\n\n\n\n\n139975938188096\n\nAddBackward0\n step1.fc.bias\n (1)\n\n\n\n139975938188096->139975938188624\n\n\n\n\n\n139975938188144\n\nAddmmBackward0\n\n\n\n139975938188096->139975938188144\n\n\n\n\n\n139975938187424\n\nAccumulateGrad\n\n\n\n139975938187424->139975938188096\n\n\n\n\n\n139975938188912\n\nAddmmBackward0\n\n\n\n139975938187424->139975938188912\n\n\n\n\n\n139975938634512\n\nstep0.fc.bias\n (1)\n\n\n\n139975938634512->139975938187424\n\n\n\n\n\n139975938187856\n\nMulBackward0\n\n\n\n139975938187856->139975938188096\n\n\n\n\n\n139975938188768\n\nViewBackward0\n\n\n\n139975938188768->139975938187856\n\n\n\n\n\n139975938189200\n\nSumBackward1\n\n\n\n139975938189200->139975938188768\n\n\n\n\n\n139975938189008\n\nMseLossBackwardBackward0\n\n\n\n139975938189008->139975938189200\n\n\n\n\n\n139975938189728\n\nTBackward0\n\n\n\n139975938189008->139975938189728\n\n\n\n\n\n139975938188864\n\nMulBackward0\n\n\n\n139975938188864->139975938189008\n\n\n\n\n\n139975938187952\n\nAccumulateGrad\n\n\n\n139975938187952->139975938188864\n\n\n\n\n\n139975938187712\n\nMulBackward0\n\n\n\n139975938187952->139975938187712\n\n\n\n\n\n139975938635072\n\nmeta_parameter\n ()\n\n\n\n139975938635072->139975938187952\n\n\n\n\n\n139975938188912->139975938189008\n\n\n\n\n\n139975938188480\n\nTBackward0\n\n\n\n139975938188480->139975938188912\n\n\n\n\n\n139975938188384\n\nAccumulateGrad\n\n\n\n139975938188384->139975938188480\n\n\n\n\n\n139975938187808\n\nAddBackward0\n step1.fc.weight\n (1, 16)\n\n\n\n139975938188384->139975938187808\n\n\n\n\n\n139975938634432\n\nstep0.fc.weight\n (1, 16)\n\n\n\n139975938634432->139975938188384\n\n\n\n\n\n139975938187520\n\nMulBackward0\n\n\n\n139975938187520->139975938188624\n\n\n\n\n\n139975938189296\n\nViewBackward0\n\n\n\n139975938189296->139975938187520\n\n\n\n\n\n139975938188576\n\nSumBackward1\n\n\n\n139975938188576->139975938189296\n\n\n\n\n\n139975938188720\n\nMseLossBackwardBackward0\n\n\n\n139975938188720->139975938188576\n\n\n\n\n\n139975938189824\n\nTBackward0\n\n\n\n139975938188720->139975938189824\n\n\n\n\n\n139975938187712->139975938188720\n\n\n\n\n\n139975938188144->139975938188720\n\n\n\n\n\n139975938188816\n\nTBackward0\n\n\n\n139975938188816->139975938188144\n\n\n\n\n\n139975938187808->139975938188816\n\n\n\n\n\n139975938189104\n\nAddBackward0\n\n\n\n139975938187808->139975938189104\n\n\n\n\n\n139975938189248\n\nMulBackward0\n\n\n\n139975938189248->139975938187808\n\n\n\n\n\n139975938189344\n\nTBackward0\n\n\n\n139975938189344->139975938189248\n\n\n\n\n\n139975938189536\n\nTBackward0\n\n\n\n139975938189536->139975938189344\n\n\n\n\n\n139975938189440\n\nMmBackward0\n\n\n\n139975938189440->139975938189536\n\n\n\n\n\n139975938189728->139975938189440\n\n\n\n\n\n139975938187904\n\nTBackward0\n\n\n\n139975938187904->139975938626656\n\n\n\n\n\n139975938189104->139975938187904\n\n\n\n\n\n139975938188240\n\nMulBackward0\n\n\n\n139975938188240->139975938189104\n\n\n\n\n\n139975938188048\n\nTBackward0\n\n\n\n139975938188048->139975938188240\n\n\n\n\n\n139975938188528\n\nTBackward0\n\n\n\n139975938188528->139975938188048\n\n\n\n\n\n139975938189584\n\nMmBackward0\n\n\n\n139975938189584->139975938188528\n\n\n\n\n\n139975938189824->139975938189584\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "139978828415600\n", + "\n", + "outer_loss\n", + " ()\n", + "\n", + "\n", + "\n", + "139975938626944\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "139975938626944->139978828415600\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938626656\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139975938626656->139975938626944\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188624\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "139975938188624->139975938626656\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188096\n", + "\n", + "AddBackward0\n", + " step1.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139975938188096->139975938188624\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188144\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139975938188096->139975938188144\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187424\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139975938187424->139975938188096\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188912\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139975938187424->139975938188912\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938634512\n", + "\n", + "step0.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139975938634512->139975938187424\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187856\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938187856->139975938188096\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188768\n", + "\n", + "ViewBackward0\n", + "\n", + "\n", + "\n", + "139975938188768->139975938187856\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189200\n", + "\n", + "SumBackward1\n", + "\n", + "\n", + "\n", + "139975938189200->139975938188768\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189008\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "139975938189008->139975938189200\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189728\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938189008->139975938189728\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188864\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938188864->139975938189008\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187952\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139975938187952->139975938188864\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187712\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938187952->139975938187712\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938635072\n", + "\n", + "meta_parameter\n", + " ()\n", + "\n", + "\n", + "\n", + "139975938635072->139975938187952\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188912->139975938189008\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188480\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938188480->139975938188912\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188384\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139975938188384->139975938188480\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187808\n", + "\n", + "AddBackward0\n", + " step1.fc.weight\n", + " (1, 16)\n", + "\n", + "\n", + "\n", + "139975938188384->139975938187808\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938634432\n", + "\n", + "step0.fc.weight\n", + " (1, 16)\n", + "\n", + "\n", + "\n", + "139975938634432->139975938188384\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187520\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938187520->139975938188624\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189296\n", + "\n", + "ViewBackward0\n", + "\n", + "\n", + "\n", + "139975938189296->139975938187520\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188576\n", + "\n", + "SumBackward1\n", + "\n", + "\n", + "\n", + "139975938188576->139975938189296\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188720\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "139975938188720->139975938188576\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189824\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938188720->139975938189824\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187712->139975938188720\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188144->139975938188720\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188816\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938188816->139975938188144\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187808->139975938188816\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189104\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "139975938187808->139975938189104\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189248\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938189248->139975938187808\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189344\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938189344->139975938189248\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189536\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938189536->139975938189344\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189440\n", + "\n", + "MmBackward0\n", + "\n", + "\n", + "\n", + "139975938189440->139975938189536\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189728->139975938189440\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938187904\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938187904->139975938626656\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189104->139975938187904\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188240\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975938188240->139975938189104\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188048\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938188048->139975938188240\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938188528\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975938188528->139975938188048\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189584\n", + "\n", + "MmBackward0\n", + "\n", + "\n", + "\n", + "139975938189584->139975938188528\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938189824->139975938189584\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -404,7 +1347,325 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n139975938621248\n\nouter_loss\n ()\n\n\n\n139975251126352\n\nMseLossBackward0\n\n\n\n139975251126352->139975938621248\n\n\n\n\n\n139975251126592\n\nAddmmBackward0\n\n\n\n139975251126592->139975251126352\n\n\n\n\n\n139975251125920\n\nAddBackward0\n\n\n\n139975251125920->139975251126592\n\n\n\n\n\n139975251126400\n\nAccumulateGrad\n\n\n\n139975251126400->139975251125920\n\n\n\n\n\n139975251127120\n\nAddmmBackward0\n\n\n\n139975251126400->139975251127120\n\n\n\n\n\n139975938636032\n\nstep1.detached.fc.bias\n (1)\n\n\n\n139975938636032->139975251126400\n\n\n\n\n\n139975251126304\n\nMulBackward0\n\n\n\n139975251126304->139975251125920\n\n\n\n\n\n139975251127072\n\nViewBackward0\n\n\n\n139975251127072->139975251126304\n\n\n\n\n\n139975251128080\n\nSumBackward1\n\n\n\n139975251128080->139975251127072\n\n\n\n\n\n139975251126448\n\nMseLossBackwardBackward0\n\n\n\n139975251126448->139975251128080\n\n\n\n\n\n139975251127456\n\nTBackward0\n\n\n\n139975251126448->139975251127456\n\n\n\n\n\n139975251127312\n\nMulBackward0\n\n\n\n139975251127312->139975251126448\n\n\n\n\n\n139975251126016\n\nAccumulateGrad\n\n\n\n139975251126016->139975251127312\n\n\n\n\n\n139975938635072\n\nmeta_parameter\n ()\n\n\n\n139975938635072->139975251126016\n\n\n\n\n\n139975251127120->139975251126448\n\n\n\n\n\n139975251126880\n\nTBackward0\n\n\n\n139975251126880->139975251127120\n\n\n\n\n\n139975251126544\n\nAccumulateGrad\n\n\n\n139975251126544->139975251126880\n\n\n\n\n\n139975251128272\n\nAddBackward0\n\n\n\n139975251126544->139975251128272\n\n\n\n\n\n139975938635552\n\nstep1.detached.fc.weight\n (1, 16)\n\n\n\n139975938635552->139975251126544\n\n\n\n\n\n139975251126256\n\nTBackward0\n\n\n\n139975251126256->139975251126592\n\n\n\n\n\n139975251128272->139975251126256\n\n\n\n\n\n139975251127744\n\nMulBackward0\n\n\n\n139975251127744->139975251128272\n\n\n\n\n\n139975251126112\n\nTBackward0\n\n\n\n139975251126112->139975251127744\n\n\n\n\n\n139975251126640\n\nTBackward0\n\n\n\n139975251126640->139975251126112\n\n\n\n\n\n139975251126976\n\nMmBackward0\n\n\n\n139975251126976->139975251126640\n\n\n\n\n\n139975251127456->139975251126976\n\n\n\n\n\n" + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "139975938621248\n", + "\n", + "outer_loss\n", + " ()\n", + "\n", + "\n", + "\n", + "139975251126352\n", + "\n", + "MseLossBackward0\n", + "\n", + "\n", + "\n", + "139975251126352->139975938621248\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126592\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139975251126592->139975251126352\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251125920\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "139975251125920->139975251126592\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126400\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139975251126400->139975251125920\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251127120\n", + "\n", + "AddmmBackward0\n", + "\n", + "\n", + "\n", + "139975251126400->139975251127120\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938636032\n", + "\n", + "step1.detached.fc.bias\n", + " (1)\n", + "\n", + "\n", + "\n", + "139975938636032->139975251126400\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126304\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975251126304->139975251125920\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251127072\n", + "\n", + "ViewBackward0\n", + "\n", + "\n", + "\n", + "139975251127072->139975251126304\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251128080\n", + "\n", + "SumBackward1\n", + "\n", + "\n", + "\n", + "139975251128080->139975251127072\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126448\n", + "\n", + "MseLossBackwardBackward0\n", + "\n", + "\n", + "\n", + "139975251126448->139975251128080\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251127456\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975251126448->139975251127456\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251127312\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975251127312->139975251126448\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126016\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139975251126016->139975251127312\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938635072\n", + "\n", + "meta_parameter\n", + " ()\n", + "\n", + "\n", + "\n", + "139975938635072->139975251126016\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251127120->139975251126448\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126880\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975251126880->139975251127120\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126544\n", + "\n", + "AccumulateGrad\n", + "\n", + "\n", + "\n", + "139975251126544->139975251126880\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251128272\n", + "\n", + "AddBackward0\n", + "\n", + "\n", + "\n", + "139975251126544->139975251128272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975938635552\n", + "\n", + "step1.detached.fc.weight\n", + " (1, 16)\n", + "\n", + "\n", + "\n", + "139975938635552->139975251126544\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126256\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975251126256->139975251126592\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251128272->139975251126256\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251127744\n", + "\n", + "MulBackward0\n", + "\n", + "\n", + "\n", + "139975251127744->139975251128272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126112\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975251126112->139975251127744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126640\n", + "\n", + "TBackward0\n", + "\n", + "\n", + "\n", + "139975251126640->139975251126112\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251126976\n", + "\n", + "MmBackward0\n", + "\n", + "\n", + "\n", + "139975251126976->139975251126640\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "139975251127456->139975251126976\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] }, "metadata": {}, "output_type": "display_data" @@ -447,7 +1708,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.8.13 ('torchopt')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, From d8f90cc120fd45d1066669f9792e734965c675a1 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 10 Sep 2022 00:34:16 +0800 Subject: [PATCH 06/69] fix: fix lr scheduling (#76) --- CHANGELOG.md | 1 + tests/test_schedule.py | 67 ++++++++++++++++++++++++++++++++++ torchopt/_src/alias.py | 12 ++---- torchopt/_src/implicit_diff.py | 12 +++--- torchopt/_src/linalg.py | 2 +- torchopt/_src/schedule.py | 16 ++++---- torchopt/_src/transform.py | 17 ++++++--- torchopt/_src/utils.py | 4 +- 8 files changed, 99 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 906e43a8..920104ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fix LR scheduling by [@XuehaiPan](https://github.com/XuehaiPan) in [#76](https://github.com/metaopt/torchopt/pull/76). - Fix the step count tensor (`shape=(1,)`) can change the shape of the scalar updates (`shape=()`) by [@XuehaiPan](https://github.com/XuehaiPan) in [#71](https://github.com/metaopt/torchopt/pull/71). ### Removed diff --git a/tests/test_schedule.py b/tests/test_schedule.py index 971c0de4..a048c57f 100644 --- a/tests/test_schedule.py +++ b/tests/test_schedule.py @@ -13,8 +13,14 @@ # limitations under the License. # ============================================================================== +from typing import Callable, Tuple + +import functorch import numpy as np +import torch +import torch.nn.functional as F +import helpers import torchopt @@ -35,3 +41,64 @@ def test_linear_schedule() -> None: lr = schedule(i) lr_gt = init_value - gap_value * (i - transition_begin) / transition_steps assert np.allclose(lr, lr_gt) + + +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-2, 1e-3], + total_iters=[helpers.NUM_UPDATES, helpers.NUM_UPDATES * 2], + optimizers=[ + (torchopt.sgd, torch.optim.SGD), + (torchopt.adam, torch.optim.Adam), + (torchopt.adamw, torch.optim.AdamW), + (torchopt.rmsprop, torch.optim.RMSprop), + ], + inplace=[True, False], + weight_decay=[0.0, 1e-2], +) +def test_lr_linear_schedule( + dtype: torch.dtype, + lr: float, + total_iters: int, + optimizers: Tuple[Callable, torch.optim.Optimizer], + inplace: bool, + weight_decay: float, +) -> None: + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + torchopt_optimizer, torch_optimizer = optimizers + + fmodel, params, buffers = functorch.make_functional_with_buffers(model) + optim = torchopt_optimizer( + torchopt.schedule.linear_schedule( + init_value=lr, end_value=0.1 * lr, transition_steps=total_iters, transition_begin=0 + ), + weight_decay=weight_decay, + ) + optim_state = optim.init(params) + optim_ref = torch_optimizer( + model_ref.parameters(), + lr, + weight_decay=weight_decay, + ) + torch_scheduler = torch.optim.lr_scheduler.LinearLR( + optim_ref, start_factor=1.0, end_factor=0.1, total_iters=total_iters + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = fmodel(params, buffers, xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + grads = torch.autograd.grad(loss, params) + updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) + params = torchopt.apply_updates(params, updates, inplace=inplace) + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + torch_scheduler.step() + + helpers.assert_model_all_close((params, buffers), model_ref, model_base, dtype=dtype) diff --git a/torchopt/_src/alias.py b/torchopt/_src/alias.py index 40b2e92d..66ccc924 100644 --- a/torchopt/_src/alias.py +++ b/torchopt/_src/alias.py @@ -126,14 +126,10 @@ def _scale_by_neg_lr(lr: ScalarOrSchedule): if callable(lr): def schedule_wrapper(count): - def f(scaled_lr): - return -scaled_lr + return -lr(count) # type: ignore[operator] - return transform.map_flattened(f, lr(count)) # type: ignore[operator] - - return transform._scale_by_schedule( # pylint: disable=protected-access - schedule_wrapper, already_flattened=True - ) + # pylint: disable-next=protected-access + return transform._scale_by_schedule(schedule_wrapper, already_flattened=True) return transform._scale(-lr, already_flattened=True) # pylint: disable=protected-access @@ -318,7 +314,7 @@ def adamw( # pylint: disable-next=too-many-arguments def rmsprop( lr: ScalarOrSchedule = 1e-2, - alpha: float = 0.9, + alpha: float = 0.99, eps: float = 1e-8, weight_decay: float = 0.0, momentum: float = 0.0, diff --git a/torchopt/_src/implicit_diff.py b/torchopt/_src/implicit_diff.py index 1806bea0..4f470bd4 100644 --- a/torchopt/_src/implicit_diff.py +++ b/torchopt/_src/implicit_diff.py @@ -162,7 +162,7 @@ def _split_tensor_and_others( non_tensors = [] is_tensor_mask = [] for item in flattened: - if isinstance(item, torch.Tensor): + if torch.is_tensor(item): tensors.append(item) is_tensor_mask.append(True) else: @@ -236,18 +236,18 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ if has_aux: aux = res[1] res = res[0] - if isinstance(res, torch.Tensor): + if torch.is_tensor(res): ctx.save_for_backward(res, *args_tensors) else: ctx.save_for_backward(*res, *args_tensors) - ctx.res_is_tensor = isinstance(res, torch.Tensor) + ctx.res_is_tensor = torch.is_tensor(res) return res + (aux,) - if isinstance(res, torch.Tensor): + if torch.is_tensor(res): ctx.save_for_backward(res, *args_tensors) else: ctx.save_for_backward(*res, *args_tensors) - ctx.res_is_tensor = isinstance(res, torch.Tensor) + ctx.res_is_tensor = torch.is_tensor(res) return res @staticmethod @@ -314,7 +314,7 @@ def wrapped_solver_fun(*args, **kwargs): args_counter = 0 for idx, arg in enumerate(args): if idx in argnums: - if isinstance(arg, torch.Tensor): + if torch.is_tensor(arg): args_sign.append((args_counter, False)) # start position, is_tuple flatten_args.append(arg) args_counter += 1 diff --git a/torchopt/_src/linalg.py b/torchopt/_src/linalg.py index 52810bdd..88ec584d 100644 --- a/torchopt/_src/linalg.py +++ b/torchopt/_src/linalg.py @@ -69,7 +69,7 @@ def _normalize_matvec( if callable(f): return f - assert isinstance(f, torch.Tensor) + assert torch.is_tensor(f) if f.ndim != 2 or f.shape[0] != f.shape[1]: raise ValueError(f'linear operator must be a square matrix, but has shape: {f.shape}') return partial(torch.matmul, f) diff --git a/torchopt/_src/schedule.py b/torchopt/_src/schedule.py index d7367c2b..57aabe44 100644 --- a/torchopt/_src/schedule.py +++ b/torchopt/_src/schedule.py @@ -33,10 +33,10 @@ import logging import numpy as np +import torch from torchopt._src import base -from torchopt._src.typing import Scalar -from torchopt._src.utils import pytree +from torchopt._src.typing import Numeric, Scalar def polynomial_schedule( @@ -80,13 +80,11 @@ def polynomial_schedule( ) transition_begin = 0 - def schedule(count): - def impl(count): - count = np.clip(count - transition_begin, 0, transition_steps) - frac = 1 - count / transition_steps - return (init_value - end_value) * (frac**power) + end_value - - return pytree.tree_map(impl, count) + def schedule(count: Numeric) -> Numeric: + clip = torch.clamp if torch.is_tensor(count) else np.clip + count = clip(count - transition_begin, 0, transition_steps) # type: ignore[operator] + frac = 1.0 - count / transition_steps + return (init_value - end_value) * (frac**power) + end_value return schedule diff --git a/torchopt/_src/transform.py b/torchopt/_src/transform.py index 558dbe0e..c3cc3e9f 100644 --- a/torchopt/_src/transform.py +++ b/torchopt/_src/transform.py @@ -166,20 +166,25 @@ def init_fn(params): return ScaleByScheduleState(count=zero) def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument - step_size = step_size_fn(state.count) - if inplace: - def f(g): + def f(g, c): + step_size = step_size_fn(c) return g.mul_(step_size) if g is not None else None else: - def f(g): + def f(g, c): + step_size = step_size_fn(c) return g.mul(step_size) if g is not None else None - updates = tree_map(f, updates) - return updates, ScaleByScheduleState(count=inc_count(updates, state.count)) + updates = tree_map(f, updates, state.count) + return ( + updates, + ScaleByScheduleState( + count=_inc_count(updates, state.count, already_flattened=already_flattened) + ), + ) return base.GradientTransformation(init_fn, update_fn) diff --git a/torchopt/_src/utils.py b/torchopt/_src/utils.py index 6bfd5bbe..a8816035 100644 --- a/torchopt/_src/utils.py +++ b/torchopt/_src/utils.py @@ -48,7 +48,7 @@ def stop_gradient(target): from torchopt._src.optimizer.meta.base import MetaOptimizer def f(obj): - if isinstance(obj, torch.Tensor): + if torch.is_tensor(obj): requires_grad = obj.requires_grad obj.detach_().requires_grad_(requires_grad) @@ -134,7 +134,7 @@ def _update(term): if copy: def get_variable(t): - if not isinstance(t, torch.Tensor): + if not torch.is_tensor(t): return t requires_grad = t.requires_grad return t.clone().detach_().requires_grad_(requires_grad) From f3fe2dbc418caf7d023a6524c974a2f80629c8de Mon Sep 17 00:00:00 2001 From: Vincent Moens Date: Sun, 11 Sep 2022 14:42:58 +0200 Subject: [PATCH 07/69] feat: functorch integration (#6) --- CHANGELOG.md | 1 + README.md | 16 ++ docs/source/api/api.rst | 7 + examples/MAML-RL/func_maml.py | 196 +++++++++++++++++++++++ examples/MAML-RL/maml.py | 5 +- tests/test_optimizer.py | 56 ++++++- torchopt/__init__.py | 2 + torchopt/_src/alias.py | 12 ++ torchopt/_src/optimizer/__init__.py | 1 + torchopt/_src/optimizer/base.py | 3 + torchopt/_src/optimizer/func/__init__.py | 16 ++ torchopt/_src/optimizer/func/base.py | 88 ++++++++++ torchopt/_src/optimizer/meta/base.py | 3 + tutorials/1_Functional_Optimizer.ipynb | 95 ++++++++--- 14 files changed, 476 insertions(+), 25 deletions(-) create mode 100644 examples/MAML-RL/func_maml.py create mode 100644 torchopt/_src/optimizer/func/__init__.py create mode 100644 torchopt/_src/optimizer/func/base.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 920104ad..bf865c54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add wrapper class for functional optimizers and examples of `functorch` integration by [@vmoens](https://github.com/vmoens) and [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@XuehaiPan](https://github.com/XuehaiPan) in [#6](https://github.com/metaopt/torchopt/pull/6). - Implicit differentiation support by [@JieRen98](https://github.com/JieRen98) and [@waterhorse1](https://github.com/waterhorse1) and [@XuehaiPan](https://github.com/XuehaiPan) in [#41](https://github.com/metaopt/torchopt/pull/41). ### Changed diff --git a/README.md b/README.md index 13d005f5..40c69978 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,22 @@ updates, opt_state = optimizer.update(grads, opt_state) # get updates params = torchopt.apply_updates(params, updates) # update network parameters ``` +We also provide a wrapper `torchopt.FuncOptimizer` to make maintaining the optimizer state easier: + +```python +net = Net() # init +loader = Loader() +optimizer = torchopt.FuncOptimizer(torchopt.adam()) # wrap with `torchopt.FuncOptimizer` + +model, params = functorch.make_functional(net) # use functorch extract network parameters + +for xs, ys in loader: # get data + pred = model(params, xs) # forward + loss = F.cross_entropy(pred, ys) # compute loss + + params = optimizer.step(loss, params) # update network parameters +``` + ### PyTorch-Like API We also offer origin PyTorch APIs (e.g. `zero_grad()` or `step()`) by wrapping our Optax-Like API for traditional PyTorch user: diff --git a/docs/source/api/api.rst b/docs/source/api/api.rst index 545a8d54..04ec6035 100644 --- a/docs/source/api/api.rst +++ b/docs/source/api/api.rst @@ -29,11 +29,18 @@ Functional Optimizers .. autosummary:: + FuncOptimizer adam sgd rmsprop adamw +Wrapper for Function Optimizer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: FuncOptimizer + :members: + Functional Adam Optimizer ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/examples/MAML-RL/func_maml.py b/examples/MAML-RL/func_maml.py new file mode 100644 index 00000000..6413cc71 --- /dev/null +++ b/examples/MAML-RL/func_maml.py @@ -0,0 +1,196 @@ +# Copyright 2022 MetaOPT Team. 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 argparse +from typing import NamedTuple + +import functorch +import gym +import numpy as np +import torch +import torch.optim as optim + +import torchopt +from helpers.policy import CategoricalMLPPolicy + + +TASK_NUM = 40 +TRAJ_NUM = 20 +TRAJ_LEN = 10 + +STATE_DIM = 10 +ACTION_DIM = 5 + +GAMMA = 0.99 +LAMBDA = 0.95 + +outer_iters = 500 +inner_iters = 1 + + +class Traj(NamedTuple): + obs: np.ndarray + acs: np.ndarray + next_obs: np.ndarray + rews: np.ndarray + gammas: np.ndarray + + +def sample_traj(env, task, fpolicy, params): + env.reset_task(task) + obs_buf = np.zeros(shape=(TRAJ_LEN, TRAJ_NUM, STATE_DIM), dtype=np.float32) + next_obs_buf = np.zeros(shape=(TRAJ_LEN, TRAJ_NUM, STATE_DIM), dtype=np.float32) + acs_buf = np.zeros(shape=(TRAJ_LEN, TRAJ_NUM), dtype=np.int8) + rews_buf = np.zeros(shape=(TRAJ_LEN, TRAJ_NUM), dtype=np.float32) + gammas_buf = np.zeros(shape=(TRAJ_LEN, TRAJ_NUM), dtype=np.float32) + with torch.no_grad(): + for batch in range(TRAJ_NUM): + ob = env.reset() + for step in range(TRAJ_LEN): + ob_tensor = torch.from_numpy(ob) + pi, _ = fpolicy(params, ob_tensor) + ac_tensor = pi.sample() + ac = ac_tensor.cpu().numpy() + next_ob, rew, done, info = env.step(ac) + + obs_buf[step][batch] = ob + next_obs_buf[step][batch] = next_ob + acs_buf[step][batch] = ac + rews_buf[step][batch] = rew + gammas_buf[step][batch] = done * GAMMA + ob = next_ob + return Traj(obs=obs_buf, acs=acs_buf, next_obs=next_obs_buf, rews=rews_buf, gammas=gammas_buf) + + +def a2c_loss(traj, fpolicy, params, value_coef): + lambdas = np.ones_like(traj.gammas) * LAMBDA + _, next_values = fpolicy(params, torch.from_numpy(traj.next_obs)) + next_values = torch.squeeze(next_values, -1).detach().numpy() + # Work backwards to compute `G_{T-1}`, ..., `G_0`. + returns = [] + g = next_values[-1, :] + for i in reversed(range(next_values.shape[0])): + g = traj.rews[i, :] + traj.gammas[i, :] * ( + (1 - lambdas[i, :]) * next_values[i, :] + lambdas[i, :] * g + ) + returns.insert(0, g) + lambda_returns = torch.from_numpy(np.array(returns)) + pi, values = fpolicy(params, torch.from_numpy(traj.obs)) + log_probs = pi.log_prob(torch.from_numpy(traj.acs)) + advs = lambda_returns - torch.squeeze(values, -1) + action_loss = -(advs.detach() * log_probs).mean() + value_loss = advs.pow(2).mean() + + loss = action_loss + value_coef * value_loss + return loss + + +def evaluate(env, seed, task_num, fpolicy, params): + pre_reward_ls = [] + post_reward_ls = [] + inner_opt = torchopt.MetaSGD(lr=0.5) + env = gym.make( + 'TabularMDP-v0', + **dict( + num_states=STATE_DIM, num_actions=ACTION_DIM, max_episode_steps=TRAJ_LEN, seed=args.seed + ), + ) + tasks = env.sample_tasks(num_tasks=task_num) + + for idx in range(task_num): + for _ in range(inner_iters): + pre_trajs = sample_traj(env, tasks[idx], fpolicy, params) + + inner_loss = a2c_loss(pre_trajs, fpolicy, params, value_coef=0.5) + params = inner_opt.step(inner_loss, params) + post_trajs = sample_traj(env, tasks[idx], fpolicy, params) + + # Logging + pre_reward_ls.append(np.sum(pre_trajs.rews, axis=0).mean()) + post_reward_ls.append(np.sum(post_trajs.rews, axis=0).mean()) + + return pre_reward_ls, post_reward_ls + + +def main(args): + # init training + torch.manual_seed(args.seed) + torch.cuda.manual_seed_all(args.seed) + # Env + env = gym.make( + 'TabularMDP-v0', + **dict( + num_states=STATE_DIM, num_actions=ACTION_DIM, max_episode_steps=TRAJ_LEN, seed=args.seed + ), + ) + # Policy + policy = CategoricalMLPPolicy(input_size=STATE_DIM, output_size=ACTION_DIM) + fpolicy, params = functorch.make_functional(policy) + + inner_opt = torchopt.MetaSGD(lr=0.5) + outer_opt = optim.Adam(params, lr=1e-3) + train_pre_reward = [] + train_post_reward = [] + test_pre_reward = [] + test_post_reward = [] + + for i in range(outer_iters): + tasks = env.sample_tasks(num_tasks=TASK_NUM) + train_pre_reward_ls = [] + train_post_reward_ls = [] + + outer_opt.zero_grad() + + param_orig = [p.detach().clone().requires_grad_() for p in params] + _params = list(params) + for idx in range(TASK_NUM): + + for _ in range(inner_iters): + pre_trajs = sample_traj(env, tasks[idx], fpolicy, _params) + inner_loss = a2c_loss(pre_trajs, fpolicy, _params, value_coef=0.5) + _params = inner_opt.step(inner_loss, _params) + post_trajs = sample_traj(env, tasks[idx], fpolicy, _params) + outer_loss = a2c_loss(post_trajs, fpolicy, _params, value_coef=0.5) + outer_loss.backward() + _params = [p.detach().clone().requires_grad_() for p in param_orig] + + # Logging + train_pre_reward_ls.append(np.sum(pre_trajs.rews, axis=0).mean()) + train_post_reward_ls.append(np.sum(post_trajs.rews, axis=0).mean()) + outer_opt.step() + + test_pre_reward_ls, test_post_reward_ls = evaluate( + env, args.seed, TASK_NUM, fpolicy, params + ) + + train_pre_reward.append(sum(train_pre_reward_ls) / TASK_NUM) + train_post_reward.append(sum(train_post_reward_ls) / TASK_NUM) + test_pre_reward.append(sum(test_pre_reward_ls) / TASK_NUM) + test_post_reward.append(sum(test_post_reward_ls) / TASK_NUM) + + print('Train_iters', i) + print('train_pre_reward', sum(train_pre_reward_ls) / TASK_NUM) + print('train_post_reward', sum(train_post_reward_ls) / TASK_NUM) + print('test_pre_reward', sum(test_pre_reward_ls) / TASK_NUM) + print('test_post_reward', sum(test_post_reward_ls) / TASK_NUM) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Reinforcement learning with Model-Agnostic Meta-Learning (MAML) - Train' + ) + parser.add_argument('--seed', type=int, default=1, help='random seed (default: 1)') + args = parser.parse_args() + main(args) diff --git a/examples/MAML-RL/maml.py b/examples/MAML-RL/maml.py index f2bb38e9..447f540e 100644 --- a/examples/MAML-RL/maml.py +++ b/examples/MAML-RL/maml.py @@ -99,8 +99,9 @@ def a2c_loss(traj, policy, value_coef): advs = lambda_returns - torch.squeeze(values, -1) action_loss = -(advs.detach() * log_probs).mean() value_loss = advs.pow(2).mean() - a2c_loss = action_loss + value_coef * value_loss - return a2c_loss + + loss = action_loss + value_coef * value_loss + return loss def evaluate(env, seed, task_num, policy): diff --git a/tests/test_optimizer.py b/tests/test_optimizer.py index c0db3e34..f8fff9a3 100644 --- a/tests/test_optimizer.py +++ b/tests/test_optimizer.py @@ -13,8 +13,9 @@ # limitations under the License. # ============================================================================== -from typing import Tuple +from typing import Callable, Tuple +import functorch import pytest import torch import torch.nn.functional as F @@ -364,3 +365,56 @@ def test_RMSProp( optim_ref.step() helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) + + +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-2, 1e-3], + optimizers=[ + (torchopt.sgd, torch.optim.SGD), + (torchopt.adam, torch.optim.Adam), + (torchopt.adamw, torch.optim.AdamW), + (torchopt.rmsprop, torch.optim.RMSprop), + ], + inplace=[True, False], + weight_decay=[0.0, 1e-2], +) +def test_FuncOptimizer( + dtype: torch.dtype, + lr: float, + optimizers: Tuple[Callable, torch.optim.Optimizer], + inplace: bool, + weight_decay: float, +) -> None: + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + torchopt_optimizer, torch_optimizer = optimizers + + fmodel, params, buffers = functorch.make_functional_with_buffers(model) + optim = torchopt.FuncOptimizer( + torchopt_optimizer( + lr=lr, + weight_decay=weight_decay, + ), + inplace=inplace, + ) + optim_ref = torch_optimizer( + model_ref.parameters(), + lr, + weight_decay=weight_decay, + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = fmodel(params, buffers, xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + params = optim.step(loss, params) + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close((params, buffers), model_ref, model_base, dtype=dtype) diff --git a/torchopt/__init__.py b/torchopt/__init__.py index fa242b52..15aa8a08 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -28,6 +28,7 @@ from torchopt._src.clip import clip_grad_norm from torchopt._src.combine import chain from torchopt._src.optimizer import SGD, Adam, AdamW, Optimizer, RMSProp, RMSprop, meta +from torchopt._src.optimizer.func import FuncOptimizer from torchopt._src.optimizer.meta import ( MetaAdam, MetaAdamW, @@ -68,6 +69,7 @@ 'MetaAdamW', 'MetaRMSProp', 'MetaRMSprop', + 'FuncOptimizer', 'apply_updates', 'extract_state_dict', 'recover_state_dict', diff --git a/torchopt/_src/alias.py b/torchopt/_src/alias.py index 66ccc924..019e0248 100644 --- a/torchopt/_src/alias.py +++ b/torchopt/_src/alias.py @@ -178,6 +178,9 @@ def adam( Returns: The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. """ b1, b2 = betas # pylint: disable=unneeded-not @@ -270,6 +273,9 @@ def adamw( Returns: The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. """ b1, b2 = betas # pylint: disable=unneeded-not @@ -361,6 +367,9 @@ def rmsprop( Returns: The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. """ # pylint: disable=unneeded-not if not (callable(lr) or 0.0 <= lr): @@ -437,6 +446,9 @@ def sgd( Returns: The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. """ # pylint: disable=unneeded-not if not (callable(lr) or 0.0 <= lr): diff --git a/torchopt/_src/optimizer/__init__.py b/torchopt/_src/optimizer/__init__.py index 8501fb15..80fdd25e 100644 --- a/torchopt/_src/optimizer/__init__.py +++ b/torchopt/_src/optimizer/__init__.py @@ -17,5 +17,6 @@ from torchopt._src.optimizer.adam import Adam from torchopt._src.optimizer.adamw import AdamW from torchopt._src.optimizer.base import Optimizer +from torchopt._src.optimizer.func import FuncOptimizer from torchopt._src.optimizer.rmsprop import RMSProp, RMSprop from torchopt._src.optimizer.sgd import SGD diff --git a/torchopt/_src/optimizer/base.py b/torchopt/_src/optimizer/base.py index 99e18b36..8a00e937 100644 --- a/torchopt/_src/optimizer/base.py +++ b/torchopt/_src/optimizer/base.py @@ -37,6 +37,9 @@ def __init__(self, params: Iterable[torch.Tensor], impl: GradientTransformation) Note that using ``Optimizer(sgd())`` or ``Optimizer(chain(sgd()))`` is equivalent to :class:`torchopt.SGD`. """ + if not isinstance(impl, GradientTransformation): + raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') + self.impl = impl self.param_groups = [] # type: ignore self.param_tree_groups = [] # type: ignore diff --git a/torchopt/_src/optimizer/func/__init__.py b/torchopt/_src/optimizer/func/__init__.py new file mode 100644 index 00000000..3510a59b --- /dev/null +++ b/torchopt/_src/optimizer/func/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2022 MetaOPT Team. 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 torchopt._src.optimizer.func.base import FuncOptimizer diff --git a/torchopt/_src/optimizer/func/base.py b/torchopt/_src/optimizer/func/base.py new file mode 100644 index 00000000..f4ec35ac --- /dev/null +++ b/torchopt/_src/optimizer/func/base.py @@ -0,0 +1,88 @@ +# Copyright 2022 MetaOPT Team. 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 typing import Optional + +import torch + +from torchopt._src.base import GradientTransformation +from torchopt._src.typing import TensorTree +from torchopt._src.update import apply_updates + + +# mypy: ignore-errors +class FuncOptimizer: # pylint: disable=too-few-public-methods + """A wrapper class to hold the functional optimizer. + + This wrapper makes it easier to maintain the optimizer states. The optimizer states are held by + the wrapper internally. The wrapper provides a :meth:`step` function to compute the gradients + and update the parameters. + + See Also: + - The functional Adam optimizer: :func:`torchopt.adam`. + - The functional AdamW optimizer: :func:`torchopt.adamw`. + - The functional RMSprop optimizer: :func:`torchopt.rmsprop`. + - The functional SGD optimizer: :func:`torchopt.sgd`. + """ + + __NOT_INITIALIZED = object() + + def __init__(self, impl: GradientTransformation, *, inplace: bool = False) -> None: + """The :meth:`init` function. + + Args: + impl (GradientTransformation): A low level optimizer function, it could be a optimizer + function provided by `alias.py` or a customized `chain` provided by `combine.py`. + inplace (optional): (default: :data:`False`) + The default value of ``inplace`` for each optimization update. + """ + if not isinstance(impl, GradientTransformation): + raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') + + self.impl = impl + self.optim_state = self.__NOT_INITIALIZED + self.inplace = bool(inplace) + + def step( + self, loss: torch.Tensor, params: TensorTree, inplace: Optional[bool] = None + ) -> TensorTree: + r"""Compute the gradients of loss to the network parameters and update network parameters. + + Graph of the derivative will be constructed, allowing to compute higher order derivative + products. We use the differentiable optimizer (pass argument inplace=False) to scale the + gradients and update the network parameters without modifying tensors in-place. + + Args: + loss: (torch.Tensor) + loss that is used to compute the gradients to network parameters. + params: (tree of torch.Tensor) + An tree of :class:`torch.Tensor`\s. Specifies what tensors should be optimized. + inplace (optional): (default: :data:`None`) + Whether to update the parameters in-place. If :data:`None`, use the default value + specified in the constructor. + """ + if self.optim_state is self.__NOT_INITIALIZED: + self.optim_state = self.impl.init(params) + + if inplace is None: + inplace = self.inplace + + # Step parameter only + grads = torch.autograd.grad(loss, params, create_graph=True, allow_unused=True) + updates, self.optim_state = self.impl.update( + grads, self.optim_state, params=params, inplace=inplace + ) + new_params = apply_updates(params, updates, inplace=inplace) + return new_params diff --git a/torchopt/_src/optimizer/meta/base.py b/torchopt/_src/optimizer/meta/base.py index eb5a70b1..9309f165 100644 --- a/torchopt/_src/optimizer/meta/base.py +++ b/torchopt/_src/optimizer/meta/base.py @@ -37,6 +37,9 @@ def __init__(self, net: nn.Module, impl: GradientTransformation): ``MetaOptimizer(chain(sgd(moment_requires_grad=True)))`` is equivalent to :class:`torchopt.MetaSGD`. """ + if not isinstance(impl, GradientTransformation): + raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') + self.impl = impl self.param_containers_groups = [] # type: ignore self.state_groups = [] # type: ignore diff --git a/tutorials/1_Functional_Optimizer.ipynb b/tutorials/1_Functional_Optimizer.ipynb index e0e82885..8ed3571f 100644 --- a/tutorials/1_Functional_Optimizer.ipynb +++ b/tutorials/1_Functional_Optimizer.ipynb @@ -116,14 +116,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "Parameters before update: {\n", - " 'weight': DeviceArray([[1.]], dtype=float32)),\n", - " 'bias': DeviceArray([0.], dtype=float32)\n", - "}\n", - "Parameters after update: {\n", - " 'weight': DeviceArray([[6.735325e-06]], dtype=float32),\n", - " 'bias': DeviceArray([-0.99999326], dtype=float32)\n", - "}" + "Parameters before update: OrderedDict([\n", + " ('weight', DeviceArray([[1.]], dtype=float32)),\n", + " ('bias', DeviceArray([0.], dtype=float32))\n", + "])\n", + "Parameters after update: OrderedDict([\n", + " ('weight', DeviceArray([[6.735325e-06]], dtype=float32)),\n", + " ('bias', DeviceArray([-0.99999326], dtype=float32))\n", + "])" ] } ], @@ -165,7 +165,7 @@ "\n", " grads = torch.autograd.grad(loss, params)\n", " updates, opt_state = optimizer.update(grads, opt_state)\n", - " \n", + "\n", " print('Parameters before update:', params)\n", " params = torchopt.apply_updates(params, updates)\n", " print('Parameters after update:', params)" @@ -195,6 +195,57 @@ "interact_with_functorch()" ] }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def interact_with_functorch_with_wrapper():\n", + " batch_size = 1\n", + " dim = 1\n", + " net = Net(dim)\n", + " model, params = functorch.make_functional(net) # get the functional version of the model\n", + "\n", + " learning_rate = 1.\n", + " # The `torchopt.FuncOptimizer` wrapper makes it easier to maintain the optimizer states.\n", + " optimizer = torchopt.FuncOptimizer(torchopt.adam(learning_rate))\n", + "\n", + " xs = 2 * torch.ones((batch_size, dim))\n", + " ys = torch.ones((batch_size, 1))\n", + "\n", + " pred = model(params, xs)\n", + " loss = mse(pred, ys)\n", + "\n", + " print('Parameters before update:', params)\n", + " params = optimizer.step(loss, params)\n", + " print('Parameters after update:', params)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Parameters before update: (\n", + " Parameter containing: tensor([[1.]], requires_grad=True),\n", + " Parameter containing: tensor([0.], requires_grad=True)\n", + ")\n", + "Parameters after update: (\n", + " Parameter containing: tensor([[0.]], requires_grad=True),\n", + " Parameter containing: tensor([-1.], requires_grad=True)\n", + ")" + ] + } + ], + "source": [ + "interact_with_functorch_with_wrapper()" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -206,7 +257,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -233,7 +284,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -266,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -293,7 +344,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -328,7 +379,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -367,7 +418,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -393,7 +444,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -402,7 +453,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -411,7 +462,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -436,7 +487,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -453,7 +504,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -470,7 +521,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -480,7 +531,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ From ac2f0dbfe8f7e2169b48afd22caee0d11fe3afec Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sun, 11 Sep 2022 21:26:55 +0800 Subject: [PATCH 08/69] chore(setup): update version numbering --- Makefile | 2 +- setup.py | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index ac67d4b8..55f07513 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ PYTHON ?= $(shell command -v python3 || command -v python) default: install install: - $(PYTHON) -m pip install . + $(PYTHON) -m pip install -vvv . install-editable: $(PYTHON) -m pip install --upgrade pip diff --git a/setup.py b/setup.py index e0df95db..a8275f9a 100644 --- a/setup.py +++ b/setup.py @@ -14,9 +14,13 @@ from setuptools.command.build_ext import build_ext HERE = pathlib.Path(__file__).absolute().parent +VERSION_FILE = HERE / 'torchopt' / 'version.py' -sys.path.insert(0, str(HERE / 'torchopt')) -import version # noqa +try: + from torchopt import version # noqa +except ImportError: + sys.path.insert(0, str(VERSION_FILE.parent)) + import version # noqa class CMakeExtension(Extension): @@ -81,10 +85,28 @@ def build_extension(self, ext): os.chdir(HERE) -setup( - version=version.__version__, - package_data={'sharedlib': ['*.so', '*.pyd']}, - include_package_data=True, - cmdclass={'build_ext': cmake_build_ext}, - ext_modules=[CMakeExtension('torchopt._C', source_dir=HERE)], -) +VERSION_CONTENT = None +if not version.__release__: + import re + + VERSION_CONTENT = VERSION_FILE.read_text(encoding='UTF-8') + VERSION_FILE.write_text( + data=re.sub( + r"""__version__\s*=\s*('[^']+'|"[^"]+")""", + r"__version__ = '{}'".format(version.__version__), + string=VERSION_CONTENT, + ), + encoding='UTF-8', + ) + +try: + setup( + version=version.__version__, + package_data={'sharedlib': ['*.so', '*.pyd']}, + include_package_data=True, + cmdclass={'build_ext': cmake_build_ext}, + ext_modules=[CMakeExtension('torchopt._C', source_dir=HERE)], + ) +finally: + if VERSION_CONTENT is not None: + VERSION_FILE.write_text(data=VERSION_CONTENT, encoding='UTF-8') From b98ca4355d71156326c932b6dfe76f018acc6859 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 13 Sep 2022 16:56:24 +0800 Subject: [PATCH 09/69] chore(setup): update version numbering --- setup.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index a8275f9a..fe316152 100644 --- a/setup.py +++ b/setup.py @@ -16,11 +16,8 @@ HERE = pathlib.Path(__file__).absolute().parent VERSION_FILE = HERE / 'torchopt' / 'version.py' -try: - from torchopt import version # noqa -except ImportError: - sys.path.insert(0, str(VERSION_FILE.parent)) - import version # noqa +sys.path.insert(0, str(VERSION_FILE.parent)) +import version # noqa class CMakeExtension(Extension): @@ -93,7 +90,7 @@ def build_extension(self, ext): VERSION_FILE.write_text( data=re.sub( r"""__version__\s*=\s*('[^']+'|"[^"]+")""", - r"__version__ = '{}'".format(version.__version__), + f"__version__ = '{version.__version__}'", string=VERSION_CONTENT, ), encoding='UTF-8', From b782a4fe9c1fda5e322e7b50ab1e061e817e6ac7 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 13 Sep 2022 18:50:55 +0800 Subject: [PATCH 10/69] deps(workflows): bump cibuildwheel version --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6900ab0a..4128b4b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -107,7 +107,7 @@ jobs: run: python setup.py --version - name: Build wheels - uses: pypa/cibuildwheel@v2.8.1 + uses: pypa/cibuildwheel@v2.10.0 with: package-dir: . output-dir: wheelhouse From 45b06e4d9c7b2cb2b2f611fe901a35b06cdfddfe Mon Sep 17 00:00:00 2001 From: Benjamin-eecs Date: Tue, 20 Sep 2022 16:05:01 +0800 Subject: [PATCH 11/69] fix(torchopt): bugfix when input is nn.Parameter --- torchopt/_src/implicit_diff.py | 2 +- torchopt/_src/linalg.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/torchopt/_src/implicit_diff.py b/torchopt/_src/implicit_diff.py index 4f470bd4..6d19d5bd 100644 --- a/torchopt/_src/implicit_diff.py +++ b/torchopt/_src/implicit_diff.py @@ -163,7 +163,7 @@ def _split_tensor_and_others( is_tensor_mask = [] for item in flattened: if torch.is_tensor(item): - tensors.append(item) + tensors.append(item.data) is_tensor_mask.append(True) else: non_tensors.append(item) diff --git a/torchopt/_src/linalg.py b/torchopt/_src/linalg.py index 88ec584d..565c41be 100644 --- a/torchopt/_src/linalg.py +++ b/torchopt/_src/linalg.py @@ -43,8 +43,8 @@ def _inner_product_kernel(x: torch.Tensor, y: torch.Tensor) -> float: """Computes (x.conj() * y).real.""" - x = x.view(-1) - y = y.view(-1) + x = x.reshape(-1) + y = y.reshape(-1) prod = torch.dot(x.real, y.real).item() if x.is_complex() or y.is_complex(): prod += torch.dot(x.imag, y.imag).item() From f39849353e459172d90673868bb7d7d78bc3eb68 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 20 Sep 2022 22:28:13 +0800 Subject: [PATCH 12/69] fix(transform): fix inplace sqrt_ with add_ --- torchopt/_src/transform.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/torchopt/_src/transform.py b/torchopt/_src/transform.py index c3cc3e9f..08e0da9e 100644 --- a/torchopt/_src/transform.py +++ b/torchopt/_src/transform.py @@ -328,12 +328,12 @@ def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable= if inplace: def f(g, m, v): - return m.div_(v.add_(eps_root).sqrt_().add_(eps)) if g is not None else None + return m.div_(v.add_(eps_root).sqrt_().add(eps)) if g is not None else None else: def f(g, m, v): - return m.div(v.add(eps_root).sqrt_().add_(eps)) if g is not None else None + return m.div(v.add(eps_root).sqrt_().add(eps)) if g is not None else None updates = tree_map(f, updates, mu_hat, nu_hat) return updates, ScaleByAdamState(mu=mu, nu=nu, count=count_inc) @@ -642,7 +642,7 @@ def f(g, n): else: def f(g, n): - return g.div(n.sqrt().add_(eps)) + return g.div(n.sqrt().add(eps)) updates = tree_map(f, updates, nu) return updates, ScaleByRmsState(nu=nu) @@ -719,12 +719,12 @@ def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable= if inplace: def f(g, m, n): - return g.div_(n.addcmul(m, m, value=-1.0).sqrt_().add_(eps)) + return g.div_(n.addcmul(m, m, value=-1.0).sqrt_().add(eps)) else: def f(g, m, n): - return g.div(n.addcmul(m, m, value=-1.0).sqrt_().add_(eps)) + return g.div(n.addcmul(m, m, value=-1.0).sqrt_().add(eps)) updates = tree_map(f, updates, mu, nu) return updates, ScaleByRStdDevState(mu=mu, nu=nu) From dd55c1f1b1846befac841a1c4d44999cb8568674 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Wed, 21 Sep 2022 22:41:05 +0800 Subject: [PATCH 13/69] fix(utils): filter out None in module containers Fixes #84 --- torchopt/_src/utils.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/torchopt/_src/utils.py b/torchopt/_src/utils.py index a8816035..4304e838 100644 --- a/torchopt/_src/utils.py +++ b/torchopt/_src/utils.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================== -from typing import Dict, List, NamedTuple, Union +from typing import Dict, List, NamedTuple, Optional, Union import optree as pytree import torch @@ -113,9 +113,13 @@ def get_variable(t): return t.clone().detach_().requires_grad_(requires_grad) return t - def _update(term): + def _update(term: Dict[str, Optional[torch.Tensor]]): if len(term) != 0: - params.append({k: get_variable(v) for k, v in term.items()}) + params.append( + type(term)( + (k, get_variable(v)) for k, v in term.items() if isinstance(v, torch.Tensor) + ) + ) # pylint: disable=protected-access _update(mod._parameters) @@ -150,9 +154,11 @@ def _extract_container(mod, with_buffer=True): if isinstance(mod, nn.Module): containers = [] - def _update(term): + def _update(term: Dict[str, Optional[torch.Tensor]]) -> Dict[str, torch.Tensor]: if len(term) != 0: - containers.append(term) + containers.append( + type(term)((k, v) for k, v in term.items() if isinstance(v, torch.Tensor)) + ) # pylint: disable=protected-access _update(mod._parameters) From a2d1a3c3d2aad9c752ad5a015a6370a92db3f595 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Wed, 21 Sep 2022 22:41:47 +0800 Subject: [PATCH 14/69] test(utils): add test for no None in module containers --- tests/helpers.py | 2 +- tests/test_meta_optim.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/test_meta_optim.py diff --git a/tests/helpers.py b/tests/helpers.py index 131a98a3..af5587ed 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -107,7 +107,7 @@ def get_models( nn.Linear( in_features=MODEL_HIDDEN_SIZE, out_features=MODEL_NUM_CLASSES, - bias=True, + bias=False, ), nn.Softmax(dim=-1), ).to(dtype=dtype) diff --git a/tests/test_meta_optim.py b/tests/test_meta_optim.py new file mode 100644 index 00000000..51b36a08 --- /dev/null +++ b/tests/test_meta_optim.py @@ -0,0 +1,28 @@ +# Copyright 2022 MetaOPT Team. 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 torch + +import helpers +import torchopt +from torchopt import pytree + + +def test_no_none_in_containers(): + model = helpers.get_models()[0] + + meta_adam = torchopt.MetaAdam(model) + leaves = pytree.tree_leaves(meta_adam.param_containers_groups) + assert all(map(lambda t: isinstance(t, torch.Tensor), leaves)) From a2d31e53066e4f40b69c34e2335055790aaf507d Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Wed, 21 Sep 2022 22:47:19 +0800 Subject: [PATCH 15/69] docs(CHANGELOG): update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf865c54..c3560d0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fix `None` in module containers by [@XuehaiPan](https://github.com/XuehaiPan) +- Fix backward errors when using inplace `sqrt_` and `add_` by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan) - Fix LR scheduling by [@XuehaiPan](https://github.com/XuehaiPan) in [#76](https://github.com/metaopt/torchopt/pull/76). - Fix the step count tensor (`shape=(1,)`) can change the shape of the scalar updates (`shape=()`) by [@XuehaiPan](https://github.com/XuehaiPan) in [#71](https://github.com/metaopt/torchopt/pull/71). From 07f09966499572e753fd78a2be1ccadb741ddef3 Mon Sep 17 00:00:00 2001 From: Hello_World Date: Thu, 22 Sep 2022 11:10:00 +0800 Subject: [PATCH 16/69] feat(implicit): add cg solver wrapper (#85) Co-authored-by: Bo Liu --- torchopt/_src/implicit_diff.py | 4 ++-- torchopt/_src/linear_solve.py | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/torchopt/_src/implicit_diff.py b/torchopt/_src/implicit_diff.py index 6d19d5bd..e63a0a6c 100644 --- a/torchopt/_src/implicit_diff.py +++ b/torchopt/_src/implicit_diff.py @@ -39,7 +39,7 @@ def _root_vjp( cotangent: Any, res_is_tensor: bool, argnums: Tuple[int, ...], - solve: Callable = linear_solve.solve_normal_cg, + solve: Callable = linear_solve.solve_normal_cg(), ) -> Tuple[Any, ...]: def fun_sol(sol): # We close over the arguments. @@ -345,7 +345,7 @@ def custom_root( optimality_fun: Callable, argnums: Union[int, Tuple[int, ...]] = 0, has_aux: bool = False, - solve: Callable = linear_solve.solve_normal_cg, + solve: Callable = linear_solve.solve_normal_cg(), reference_signature: Optional[Union[inspect.Signature, Callable]] = None, ) -> Callable[[Callable], Callable]: """Decorator for adding implicit differentiation to a root solver. diff --git a/torchopt/_src/linear_solve.py b/torchopt/_src/linear_solve.py index 2b370d85..e0be591c 100644 --- a/torchopt/_src/linear_solve.py +++ b/torchopt/_src/linear_solve.py @@ -32,6 +32,7 @@ # pylint: disable=invalid-name +import functools from typing import Callable, Optional import functorch @@ -94,7 +95,7 @@ def _normal_matvec(matvec: Callable[[TensorTree], TensorTree], x: TensorTree) -> return vjp(matvec_x)[0] -def solve_normal_cg( +def _solve_normal_cg( matvec: Callable[[TensorTree], TensorTree], b: TensorTree, ridge: Optional[float] = None, @@ -132,3 +133,8 @@ def normal_matvec(x): Ab = rmatvec(b) # A.T b return linalg.cg(normal_matvec, Ab, x0=init, **kwargs) + + +def solve_normal_cg(**kwargs): + """Wrapper for `solve_normal_cg`.""" + return functools.partial(_solve_normal_cg, **kwargs) From 714f99d2e2fa122bde620dc7b8a08db41e6c7dfb Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Thu, 22 Sep 2022 19:21:42 +0800 Subject: [PATCH 17/69] fix(utils): fix module extractor --- tests/test_meta_optim.py | 7 +------ torchopt/_src/optimizer/meta/base.py | 17 ++++++++++++----- torchopt/_src/utils.py | 26 ++++++++++++-------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/test_meta_optim.py b/tests/test_meta_optim.py index 51b36a08..5916574e 100644 --- a/tests/test_meta_optim.py +++ b/tests/test_meta_optim.py @@ -13,16 +13,11 @@ # limitations under the License. # ============================================================================== -import torch - import helpers import torchopt -from torchopt import pytree -def test_no_none_in_containers(): +def test_filter_nones_in_params(): model = helpers.get_models()[0] meta_adam = torchopt.MetaAdam(model) - leaves = pytree.tree_leaves(meta_adam.param_containers_groups) - assert all(map(lambda t: isinstance(t, torch.Tensor), leaves)) diff --git a/torchopt/_src/optimizer/meta/base.py b/torchopt/_src/optimizer/meta/base.py index 9309f165..7e845fb0 100644 --- a/torchopt/_src/optimizer/meta/base.py +++ b/torchopt/_src/optimizer/meta/base.py @@ -46,7 +46,7 @@ def __init__(self, net: nn.Module, impl: GradientTransformation): self.add_param_group(net) - def step(self, loss: torch.Tensor): + def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals """Compute the gradients of the loss to the network parameters and update network parameters. Graph of the derivative will be constructed, allowing to compute higher order derivative @@ -61,8 +61,8 @@ def step(self, loss: torch.Tensor): for i, (param_container, new_state) in enumerate( zip(self.param_containers_groups, self.state_groups) ): - flattened_params, container_treedef = pytree.tree_flatten(param_container) - flattened_params = tuple(flattened_params) + flattened_params_or_none, container_treedef = pytree.tree_flatten(param_container) + flattened_params = tuple(filter(torch.is_tensor, flattened_params_or_none)) grads = torch.autograd.grad( loss, flattened_params, create_graph=True, allow_unused=True ) @@ -74,7 +74,14 @@ def step(self, loss: torch.Tensor): ) self.state_groups[i] = new_state flattened_new_params = apply_updates(flattened_params, updates, inplace=False) - new_params = pytree.tree_unflatten(container_treedef, flattened_new_params) + new_params_iter = iter(flattened_new_params) + flattened_new_params_or_none = [ + next(new_params_iter) + if isinstance(old_param_or_none, torch.Tensor) + else old_param_or_none + for old_param_or_none in flattened_params_or_none + ] + new_params = pytree.tree_unflatten(container_treedef, flattened_new_params_or_none) for container, new_param in zip(param_container, new_params): container.update(new_param) @@ -84,7 +91,7 @@ def add_param_group(self, net): from torchopt._src.utils import _extract_container net_container = _extract_container(net, with_buffer=False) - flattened_params = tuple(pytree.tree_leaves(net_container)) + flattened_params = tuple(filter(torch.is_tensor, pytree.tree_leaves(net_container))) optimizer_state = self.impl.init(flattened_params) self.param_containers_groups.append(net_container) self.state_groups.append(optimizer_state) diff --git a/torchopt/_src/utils.py b/torchopt/_src/utils.py index 4304e838..c68c6391 100644 --- a/torchopt/_src/utils.py +++ b/torchopt/_src/utils.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================== -from typing import Dict, List, NamedTuple, Optional, Union +from typing import Dict, List, NamedTuple, Union import optree as pytree import torch @@ -113,7 +113,7 @@ def get_variable(t): return t.clone().detach_().requires_grad_(requires_grad) return t - def _update(term: Dict[str, Optional[torch.Tensor]]): + def update_container(term): if len(term) != 0: params.append( type(term)( @@ -122,15 +122,15 @@ def _update(term: Dict[str, Optional[torch.Tensor]]): ) # pylint: disable=protected-access - _update(mod._parameters) + update_container(mod._parameters) if with_buffer: - _update(mod._buffers) + update_container(mod._buffers) for module in mod.modules(): if module is mod: continue - _update(module._parameters) + update_container(module._parameters) if with_buffer: - _update(module._buffers) + update_container(module._buffers) return _ModuleState(params=tuple(params), visual_contents=visual_contents) elif isinstance(mod, MetaOptimizer): @@ -154,22 +154,20 @@ def _extract_container(mod, with_buffer=True): if isinstance(mod, nn.Module): containers = [] - def _update(term: Dict[str, Optional[torch.Tensor]]) -> Dict[str, torch.Tensor]: + def update_container(term): if len(term) != 0: - containers.append( - type(term)((k, v) for k, v in term.items() if isinstance(v, torch.Tensor)) - ) + containers.append(term) # we need references to original dicts # pylint: disable=protected-access - _update(mod._parameters) + update_container(mod._parameters) if with_buffer: - _update(mod._buffers) + update_container(mod._buffers) for module in mod.modules(): if module is mod: continue - _update(module._parameters) + update_container(module._parameters) if with_buffer: - _update(module._buffers) + update_container(module._buffers) return tuple(containers) raise RuntimeError(f'Unexpected class of {mod}') From 50f18504f178867f713b9d2873e09c74ef4a2418 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Thu, 22 Sep 2022 22:43:03 +0800 Subject: [PATCH 18/69] docs(implicit_diff): implicit differentiation integration (#73) Co-authored-by: Jie Ren Co-authored-by: Xuehai Pan --- .gitignore | 1 + CHANGELOG.md | 5 +- Makefile | 1 + README.md | 16 +- docs/requirements.txt | 2 +- docs/source/api/api.rst | 36 +++ docs/source/index.rst | 48 +++- docs/source/spelling_wordlist.txt | 5 + docs/source/torchopt101/torchopt-101.rst | 9 +- tests/test_implicit.py | 26 +- torchopt/_src/implicit_diff.py | 55 +++-- torchopt/_src/linalg.py | 11 +- torchopt/_src/linear_solve.py | 6 +- tutorials/5_Implicit_Differentiation.ipynb | 265 +++++++++++++++++++++ 14 files changed, 419 insertions(+), 67 deletions(-) create mode 100644 tutorials/5_Implicit_Differentiation.ipynb diff --git a/.gitignore b/.gitignore index a0107f9b..69c9826d 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ instance/ # Sphinx documentation docs/_build/ +docs/build/ docs/source/_build/ # PyBuilder diff --git a/CHANGELOG.md b/CHANGELOG.md index c3560d0f..a187713e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add API documentation and tutorial for implicit gradients by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan) in [#73](https://github.com/metaopt/torchopt/pull/73). - Add wrapper class for functional optimizers and examples of `functorch` integration by [@vmoens](https://github.com/vmoens) and [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@XuehaiPan](https://github.com/XuehaiPan) in [#6](https://github.com/metaopt/torchopt/pull/6). - Implicit differentiation support by [@JieRen98](https://github.com/JieRen98) and [@waterhorse1](https://github.com/waterhorse1) and [@XuehaiPan](https://github.com/XuehaiPan) in [#41](https://github.com/metaopt/torchopt/pull/41). @@ -22,8 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Fix `None` in module containers by [@XuehaiPan](https://github.com/XuehaiPan) -- Fix backward errors when using inplace `sqrt_` and `add_` by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan) +- Fix `None` in module containers by [@XuehaiPan](https://github.com/XuehaiPan). +- Fix backward errors when using inplace `sqrt_` and `add_` by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan). - Fix LR scheduling by [@XuehaiPan](https://github.com/XuehaiPan) in [#76](https://github.com/metaopt/torchopt/pull/76). - Fix the step count tensor (`shape=(1,)`) can change the shape of the scalar updates (`shape=()`) by [@XuehaiPan](https://github.com/XuehaiPan) in [#71](https://github.com/metaopt/torchopt/pull/71). diff --git a/Makefile b/Makefile index 55f07513..bec404be 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,7 @@ docs: docs-install $(PYTHON) -m sphinx_autobuild --watch $(PROJECT_PATH) --open-browser docs/source docs/build spelling: docs-install + make -C docs clean make -C docs spelling SPHINXOPTS="-W" clean-docs: diff --git a/README.md b/README.md index 40c69978..6cab6423 100644 --- a/README.md +++ b/README.md @@ -273,8 +273,8 @@ make install-editable # or run `pip3 install --no-build-isolation --editable .` ## Future Plan -- [x] CPU-accelerated optimizer -- [ ] Support general implicit differentiation with functional programing +- [X] CPU-accelerated optimizer +- [X] Support general implicit differentiation with functional programing - [X] Support more optimizers such as AdamW, RMSProp - [ ] Zero order optimization - [ ] Distributed optimizers @@ -296,11 +296,11 @@ If you find TorchOpt useful, please cite it in your publications. ```bibtex @software{TorchOpt, - author = {Jie Ren and Xidong Feng and Bo Liu and Xuehai Pan and Luo Mai and Yaodong Yang}, - title = {TorchOpt}, - year = {2022}, - publisher = {GitHub}, - journal = {GitHub repository}, - howpublished = {\url{https://github.com/metaopt/torchopt}}, + author = {Jie Ren and Xidong Feng and Bo Liu and Xuehai Pan and Luo Mai and Yaodong Yang}, + title = {TorchOpt}, + year = {2022}, + publisher = {GitHub}, + journal = {GitHub repository}, + howpublished = {\url{https://github.com/metaopt/torchopt}} } ``` diff --git a/docs/requirements.txt b/docs/requirements.txt index cdfc5b18..f2c72f62 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -11,7 +11,7 @@ sphinx-copybutton sphinx-rtd-theme sphinxcontrib-katex sphinxcontrib-bibtex -sphinx-autodoc-typehints +sphinx-autodoc-typehints >= 1.19.2 IPython ipykernel pandoc diff --git a/docs/source/api/api.rst b/docs/source/api/api.rst index 04ec6035..b77fd648 100644 --- a/docs/source/api/api.rst +++ b/docs/source/api/api.rst @@ -131,6 +131,40 @@ Differentiable Meta-RMSProp Optimizer ------ +Implicit differentiation +======================== + +.. currentmodule:: torchopt._src.implicit_diff + +.. autosummary:: + + custom_root + +Custom solvers +~~~~~~~~~~~~~~ + +.. autofunction:: custom_root + +------ + +Linear system solving +===================== + +.. currentmodule:: torchopt._src.linear_solve + +.. autosummary:: + + solve_cg + solve_normal_cg + +Indirect solvers +~~~~~~~~~~~~~~~~ + +.. autofunction:: solve_cg +.. autofunction:: solve_normal_cg + +------ + Optimizer Hooks =============== @@ -147,6 +181,8 @@ Hook .. autofunction:: register_hook .. autofunction:: zero_nan_hook +------ + Gradient Transformation ======================= diff --git a/docs/source/index.rst b/docs/source/index.rst index fd488b6e..b68717a7 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -44,31 +44,31 @@ We provide a `conda `_ environment recipe to ins .. toctree:: - :caption: Getting Started - :maxdepth: 1 + :caption: Getting Started + :maxdepth: 1 - torchopt101/torchopt-101.rst + torchopt101/torchopt-101.rst .. toctree:: - :caption: Examples - :maxdepth: 1 + :caption: Examples + :maxdepth: 1 - examples/MAML.rst + examples/MAML.rst .. toctree:: - :caption: Developer Documentation - :maxdepth: 1 + :caption: Developer Documentation + :maxdepth: 1 - developer/contributing.rst - developer/contributor.rst + developer/contributing.rst + developer/contributor.rst .. toctree:: - :caption: API Documentation - :maxdepth: 2 + :caption: API Documentation + :maxdepth: 2 - api/api.rst + api/api.rst The Team -------- @@ -97,3 +97,25 @@ License ------- TorchOpt is licensed under the Apache 2.0 License. + +Citing +------ + +If you find TorchOpt useful, please cite it in your publications. + +.. code-block:: bibtex + + @software{TorchOpt, + author = {Jie Ren and Xidong Feng and Bo Liu and Xuehai Pan and Luo Mai and Yaodong Yang}, + title = {TorchOpt}, + year = {2022}, + publisher = {GitHub}, + journal = {GitHub repository}, + howpublished = {\url{https://github.com/metaopt/torchopt}} + } + + +Indices and tables +================== + +* :ref:`genindex` diff --git a/docs/source/spelling_wordlist.txt b/docs/source/spelling_wordlist.txt index ca34dd05..7436b3ef 100644 --- a/docs/source/spelling_wordlist.txt +++ b/docs/source/spelling_wordlist.txt @@ -60,6 +60,7 @@ autograd attrs GradientTransformations args +kwargs chainable adam Adam @@ -78,3 +79,7 @@ Loshchilov pytree booleans subtrees +optimality +argnums +matvec +Hermitian diff --git a/docs/source/torchopt101/torchopt-101.rst b/docs/source/torchopt101/torchopt-101.rst index 87bffd4c..15ab4fef 100644 --- a/docs/source/torchopt101/torchopt-101.rst +++ b/docs/source/torchopt101/torchopt-101.rst @@ -3,7 +3,8 @@ Get Started with Jupyter Notebook In this tutorial, we will use Google Colaboratory to show you the most basic usages of TorchOpt. -- 1: `Functional Optimizer `_ -- 2: `Visualization `_ -- 3: `Meta Optimizer `_ -- 4: `Stop Gradient `_ +- 1: `Functional Optimizer `_ +- 2: `Visualization `_ +- 3: `Meta Optimizer `_ +- 4: `Stop Gradient `_ +- 5: `Implicit Differentiation `_ diff --git a/tests/test_implicit.py b/tests/test_implicit.py index c2d2ad72..e4c7c3bf 100644 --- a/tests/test_implicit.py +++ b/tests/test_implicit.py @@ -96,7 +96,7 @@ def forward(self, x): def test_imaml(dtype: torch.dtype, lr: float, inner_lr: float, inner_update: int) -> None: np_dtype = helpers.dtype_torch2numpy(dtype) - jax_function, jax_params = get_model_jax(dtype=np_dtype) + jax_model, jax_params = get_model_jax(dtype=np_dtype) model, loader = get_model_torch(device='cpu', dtype=dtype) fmodel, params = functorch.make_functional(model) @@ -116,7 +116,7 @@ def imaml_objective_torchopt(optimal_params, init_params, data): return loss @torchopt.implicit_diff.custom_root( - functorch.grad(imaml_objective_torchopt, argnums=0), argnums=1 + functorch.grad(imaml_objective_torchopt, argnums=0), argnums=1, has_aux=True ) def inner_solver_torchopt(init_params_copy, init_params, data): # Initial functional optimizer based on TorchOpt @@ -137,10 +137,10 @@ def inner_solver_torchopt(init_params_copy, init_params, data): grads = torch.autograd.grad(final_loss, params) # compute gradients updates, opt_state = optimizer.update(grads, opt_state) # get updates params = torchopt.apply_updates(params, updates) - return params + return params, (0, {'a': 1, 'b': 2}) def imaml_objective_jax(optimal_params, init_params, x, y): - y_pred = jax_function(optimal_params, x) + y_pred = jax_model(optimal_params, x) loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(y_pred, y)) regularization_loss = 0 for p1, p2 in zip(optimal_params.values(), init_params.values()): @@ -148,7 +148,7 @@ def imaml_objective_jax(optimal_params, init_params, x, y): loss = loss + regularization_loss return loss - @jaxopt.implicit_diff.custom_root(jax.grad(imaml_objective_jax, argnums=0)) + @jaxopt.implicit_diff.custom_root(jax.grad(imaml_objective_jax, argnums=0), has_aux=True) def inner_solver_jax(init_params_copy, init_params, x, y): """Solve ridge regression by conjugate gradient.""" # Initial functional optimizer based on torchopt @@ -157,7 +157,7 @@ def inner_solver_jax(init_params_copy, init_params, x, y): opt_state = optimizer.init(params) def compute_loss(params, init_params, x, y): - pred = jax_function(params, x) + pred = jax_model(params, x) loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(pred, y)) # Compute regularization loss regularization_loss = 0 @@ -170,7 +170,7 @@ def compute_loss(params, init_params, x, y): grads = jax.grad(compute_loss)(params, init_params, x, y) # compute gradients updates, opt_state = optimizer.update(grads, opt_state) # get updates params = optax.apply_updates(params, updates) - return params + return params, (0, {'a': 1, 'b': 2}) for xs, ys in loader: xs = xs.to(dtype=dtype) @@ -178,19 +178,21 @@ def compute_loss(params, init_params, x, y): init_params_copy = pytree.tree_map( lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params ) - optimal_params = inner_solver_torchopt(init_params_copy, params, data) + optimal_params, aux = inner_solver_torchopt(init_params_copy, params, data) + assert aux == (0, {'a': 1, 'b': 2}) outer_loss = fmodel(optimal_params, xs).mean() - grad = torch.autograd.grad(outer_loss, params) - updates, optim_state = optim.update(grad, optim_state) + grads = torch.autograd.grad(outer_loss, params) + updates, optim_state = optim.update(grads, optim_state) params = torchopt.apply_updates(params, updates) xs = xs.numpy() ys = ys.numpy() def outer_level(p, xs, ys): - optimal_params = inner_solver_jax(copy.deepcopy(p), p, xs, ys) - outer_loss = jax_function(optimal_params, xs).mean() + optimal_params, aux = inner_solver_jax(copy.deepcopy(p), p, xs, ys) + assert aux == (0, {'a': 1, 'b': 2}) + outer_loss = jax_model(optimal_params, xs).mean() return outer_loss grads_jax = jax.grad(outer_level, argnums=0)(jax_params, xs, ys) diff --git a/torchopt/_src/implicit_diff.py b/torchopt/_src/implicit_diff.py index e63a0a6c..fcd32063 100644 --- a/torchopt/_src/implicit_diff.py +++ b/torchopt/_src/implicit_diff.py @@ -234,14 +234,15 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ ctx.args_is_tensor_mask = args_is_tensor_mask ctx.args_non_tensors = args_non_tensors if has_aux: - aux = res[1] - res = res[0] + res, aux = res if torch.is_tensor(res): ctx.save_for_backward(res, *args_tensors) - else: - ctx.save_for_backward(*res, *args_tensors) - ctx.res_is_tensor = torch.is_tensor(res) - return res + (aux,) + ctx.res_is_tensor = True + return (res, aux, True, torch.tensor) + + ctx.save_for_backward(*res, *args_tensors) + ctx.res_is_tensor = False + return (*res, aux, False, type(res)) if torch.is_tensor(res): ctx.save_for_backward(res, *args_tensors) @@ -253,7 +254,7 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ @staticmethod def backward(ctx, *cotangent): # pylint: disable=too-many-locals if has_aux: - cotangent = cotangent[:-1] + cotangent = cotangent[:-3] saved_tensors = ctx.saved_tensors res, args_tensors = saved_tensors[: len(cotangent)], saved_tensors[len(cotangent) :] @@ -335,7 +336,11 @@ def wrapped_solver_fun(*args, **kwargs): result = make_custom_vjp_solver_fun(solver_fun, keys, args_sign).apply(*flatten_args, *vals) if has_aux: - return result[:-1], result[-1] + *res, aux, res_is_tensor, res_type = result + if res_is_tensor: + return res[0], aux + res = res_type(res) + return res, aux return result return wrapped_solver_fun @@ -346,27 +351,42 @@ def custom_root( argnums: Union[int, Tuple[int, ...]] = 0, has_aux: bool = False, solve: Callable = linear_solve.solve_normal_cg(), - reference_signature: Optional[Union[inspect.Signature, Callable]] = None, ) -> Callable[[Callable], Callable]: """Decorator for adding implicit differentiation to a root solver. + This wrapper should be used as a decorator: + + .. code-block:: python + + def optimality_fun(optimal_params, ...): + ... + return residual + + @custom_root(optimality_fun, argnums=argnums) + def solver_fun(params, arg1, arg2, ...): + ... + return optimal_params + + The first argument to ``optimality_fun`` and ``solver_fun`` is preserved as the parameter input. + The ``argnums`` argument refers to the indices of the variables in ``solver_fun``'s signature. + For example, setting ``argnums=(1, 2)`` will compute the gradient of ``optimal_params`` with + respect to ``arg1`` and ``arg2`` in the above snippet. Note that, except the first argument, the + keyword arguments of the ``optimality_fun`` should be a subset of the ones of ``solver_fun``. + **In best practice, the ``optimality_fun`` should have the same signature as ``solver_fun``.** + Args: optimality_fun: (callable) An equation function, ``optimality_fun(params, *args)``. The invariant is ``optimality_fun(sol, *args) == 0`` at the solution / root of ``sol``. argnums: (int or tuple of int, default: :const:`0`) - Specifies arguments to compute gradients with respect to. + Specifies arguments to compute gradients with respect to. The ``argnums`` can be an + integer or a tuple of integers, which respect to the zero-based indices of the arguments + of the ``solver_fun(params, *args)`` function. The argument ``params`` is included + for the counting, while it is indexed as ``argnums=0``. has_aux: (default: :data:`False`) Whether the decorated solver function returns auxiliary data. solve: (callable, optional, default: :func:`linear_solve.solve_normal_cg`) a linear solver of the form ``solve(matvec, b)``. - reference_signature: (function signature, optional) - Function signature (i.e. arguments and keyword arguments), with which the solver and - optimality functions are expected to agree. Defaults to ``optimality_fun``. It is - required that solver and optimality functions share the same input signature, but both - might be defined in such a way that the signature correspondence is ambiguous (e.g. if - both accept catch-all ``**kwargs``). To satisfy ``custom_root``'s requirement, any - function with an unambiguous signature can be provided here. Returns: A solver function decorator, i.e., ``custom_root(optimality_fun)(solver_fun)``. @@ -383,5 +403,4 @@ def custom_root( solve=solve, argnums=argnums, has_aux=has_aux, - reference_signature=reference_signature, ) diff --git a/torchopt/_src/linalg.py b/torchopt/_src/linalg.py index 565c41be..6aca422b 100644 --- a/torchopt/_src/linalg.py +++ b/torchopt/_src/linalg.py @@ -183,13 +183,12 @@ def cg( Args: A: (tensor or tree of tensors or function) - 2D array or function that calculates the linear map (matrix-vector - product) ``Ax`` when called like ``A(x)``. ``A`` must represent a - hermitian, positive definite matrix, and must return array(s) with the - same structure and shape as its argument. + 2D array or function that calculates the linear map (matrix-vector product) ``Ax`` when + called like ``A(x)``. ``A`` must represent a Hermitian, positive definite matrix, and + must return array(s) with the same structure and shape as its argument. b: (tensor or tree of tensors) - Right hand side of the linear system representing a single vector. Can be - stored as an array or Python container of array(s) with any shape. + Right hand side of the linear system representing a single vector. Can be stored as an + array or Python container of array(s) with any shape. x0: (tensor or tree of tensors, optional) Starting guess for the solution. Must have the same structure as ``b``. rtol: (float, optional, default: :const:`1e-5`) diff --git a/torchopt/_src/linear_solve.py b/torchopt/_src/linear_solve.py index e0be591c..9b7130b3 100644 --- a/torchopt/_src/linear_solve.py +++ b/torchopt/_src/linear_solve.py @@ -104,8 +104,8 @@ def _solve_normal_cg( ) -> TensorTree: """Solves the normal equation ``A^T A x = A^T b`` using conjugate gradient. - This can be used to solve Ax=b using conjugate gradient when A is not - hermitian, positive definite. + This can be used to solve ``A x = b`` using conjugate gradient when ``A`` is not Hermitian, + positive definite. Args: matvec: product between ``A`` and a vector. @@ -136,5 +136,5 @@ def normal_matvec(x): def solve_normal_cg(**kwargs): - """Wrapper for `solve_normal_cg`.""" + """Wrapper for :func:`solve_normal_cg`.""" return functools.partial(_solve_normal_cg, **kwargs) diff --git a/tutorials/5_Implicit_Differentiation.ipynb b/tutorials/5_Implicit_Differentiation.ipynb new file mode 100644 index 00000000..18a7d1e8 --- /dev/null +++ b/tutorials/5_Implicit_Differentiation.ipynb @@ -0,0 +1,265 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8850c832-3b54-4971-8ee0-2cd64b585ea8", + "metadata": {}, + "source": [ + "# TorchOpt for implicit differentiation" + ] + }, + { + "cell_type": "markdown", + "id": "2b547376", + "metadata": {}, + "source": [ + "[](https://colab.research.google.com/github/metaopt/torchopt/blob/main/tutorials/5_Implicit_Differentiation.ipynb)" + ] + }, + { + "cell_type": "markdown", + "id": "01214059-78d9-4cde-9b08-007c2eb078b3", + "metadata": {}, + "source": [ + "In this tutorial, we will introduce how TorchOpt can be used to conduct implicit differentiation. Here we use the example of [IMAML](https://arxiv.org/abs/1909.04630) as the illustrative example." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8f13ae67-e328-409f-84a8-1fc425c03a66", + "metadata": {}, + "outputs": [], + "source": [ + "import functorch\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "\n", + "import torchopt\n", + "from torchopt import implicit_diff, sgd" + ] + }, + { + "cell_type": "markdown", + "id": "0cdaac49-4b94-4900-9bb5-a39057ac8b21", + "metadata": {}, + "source": [ + "## 1. Basic API\n", + "\n", + "The basic API is `torchopt.implicit_diff`, which is used as the decorator for the forward process implicit gradient procedures." + ] + }, + { + "cell_type": "markdown", + "id": "dbef87df-2164-4f1d-8919-37a6fbdc5011", + "metadata": {}, + "source": [ + "## 1.1 Forward Process, Backward Process with Optimality Conditions\n", + "For IMAML, the inner-loop objective is described by the following equation.\n", + "\n", + "$$\n", + "{\\mathcal{Alg}}^{\\star} \\left( \\boldsymbol{\\theta}, \\mathcal{D}_{i}^{\\text{tr}} \\right) = \\underset{\\phi' \\in \\Phi}{\\operatorname{\\arg \\min}} ~ G \\left( \\boldsymbol{\\phi}', \\boldsymbol{\\theta} \\right) \\triangleq \\mathcal{L} \\left( \\boldsymbol{\\phi}', \\mathcal{D}_{i}^{\\text{tr}} \\right) + \\frac{\\lambda}{2} {\\left\\| \\boldsymbol{\\phi}' - \\boldsymbol{\\theta} \\right\\|}^{2}\n", + "$$\n", + "\n", + "According to this function, we can define the forward function `inner_solver`, where we solve this equation based on sufficient gradient descents. For such inner-loop process, the optimality condition is that the gradient w.r.t inner-loop parameter is $0$.\n", + "\n", + "$$\n", + "{\\left. \\nabla_{\\boldsymbol{\\phi}'} G \\left( \\boldsymbol{\\phi}', \\boldsymbol{\\theta} \\right) \\right|}_{\\boldsymbol{\\phi}' = \\boldsymbol{\\phi}^{\\star}} = 0\n", + "$$\n", + "\n", + "Thus we can define the optimality function by defining `imaml_objective` and make it first-order gradient w.r.t the inner-loop parameter as $0$. We achieve so by calling out `functorch.grad(imaml_objective, argnums=0)`. Finally, the forward function is decorated by the `@implicit_diff.custom_root` and the optimality condition we define." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8d623b2f-48ee-4df6-a2ce-cf306b4c9067", + "metadata": {}, + "outputs": [], + "source": [ + "# Optimality function\n", + "def imaml_objective(optimal_params, init_params, data):\n", + " x, y, fmodel = data\n", + " y_pred = fmodel(optimal_params, x)\n", + " regularization_loss = 0.0\n", + " for p1, p2 in zip(optimal_params, init_params):\n", + " regularization_loss += 0.5 * torch.sum(torch.square(p1.view(-1) - p2.view(-1)))\n", + " loss = F.mse_loss(y_pred, y) + regularization_loss\n", + " return loss\n", + "\n", + "# Optimality Condition is: the gradient w.r.t inner-loop optimal params is 0 (we achieve so by\n", + "# specifying argnums=0 in functorch.grad) the argnums=1 specify which meta-parameter we want to\n", + "# backpropogate, in this case we want to backpropogate to the initial parameters so we set it as 1.\n", + "# You can also set argnums as (1, 2) if you want to backpropogate through multiple meta parameters\n", + "\n", + "# Here we pass argnums=1 to the custom_root. That means we want to compute the gradient of\n", + "# optimal_params w.r.t. the 1-indexed argument in inner_solver, i.e., init_params.\n", + "@implicit_diff.custom_root(functorch.grad(imaml_objective, argnums=0), argnums=1)\n", + "def inner_solver(init_params_copy, init_params, data):\n", + " \"\"\"Solve ridge regression by conjugate gradient.\"\"\"\n", + " # Initial functional optimizer based on TorchOpt\n", + " x, y, fmodel = data\n", + " params = init_params_copy\n", + " optimizer = sgd(lr=2e-2)\n", + " opt_state = optimizer.init(params)\n", + " with torch.enable_grad():\n", + " # Temporarily enable gradient computation for conducting the optimization\n", + " for i in range(100):\n", + " pred = fmodel(params, x) \n", + " loss = F.mse_loss(pred, y) # compute loss\n", + " \n", + " # Compute regularization loss\n", + " regularization_loss = 0.0\n", + " for p1, p2 in zip(params, init_params):\n", + " regularization_loss += 0.5 * torch.sum(torch.square(p1.view(-1) - p2.view(-1)))\n", + " final_loss = loss + regularization_loss\n", + " \n", + " grads = torch.autograd.grad(final_loss, params) # compute gradients\n", + " updates, opt_state = optimizer.update(grads, opt_state) # get updates\n", + " params = torchopt.apply_updates(params, updates)\n", + "\n", + " optimal_params = params\n", + " return optimal_params" + ] + }, + { + "cell_type": "markdown", + "id": "32a75c81-d479-4120-a73d-5b2b488358d0", + "metadata": {}, + "source": [ + "In the next step, we consider a specific case for one layer neural network to fit the linear data." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "fb95538b-1fd9-4ec8-9f57-6360bedc05b7", + "metadata": {}, + "outputs": [], + "source": [ + "torch.manual_seed(0)\n", + "x = torch.randn(20, 4)\n", + "w = torch.randn(4, 1)\n", + "b = torch.randn(1)\n", + "y = x @ w + b + 0.5 * torch.randn(20, 1)" + ] + }, + { + "cell_type": "markdown", + "id": "eeb1823a-2231-4471-bb68-cce7724f2578", + "metadata": {}, + "source": [ + "We instantiate an one layer neural network, where the weights and bias are initialised with constant." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d50a7bfe-ac69-4089-8cf8-3cbd69d6d4e7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class Net(nn.Module):\n", + " def __init__(self, dim):\n", + " super().__init__()\n", + " self.fc = nn.Linear(dim, 1, bias=True)\n", + " nn.init.ones_(self.fc.weight)\n", + " nn.init.zeros_(self.fc.bias)\n", + "\n", + " def forward(self, x):\n", + " return self.fc(x)\n", + "\n", + "model = Net(4)\n", + "fmodel, meta_params = functorch.make_functional(model)\n", + "data = (x, y, fmodel)\n", + "\n", + "# clone function for parameters\n", + "def clone(params):\n", + " cloned = []\n", + " for item in params:\n", + " if isinstance(item, torch.Tensor):\n", + " cloned.append(item.clone().detach_().requires_grad_(True))\n", + " else:\n", + " cloned.append(item)\n", + " return tuple(cloned)" + ] + }, + { + "cell_type": "markdown", + "id": "065c36c4-89e2-4a63-8213-63db6ee3b08e", + "metadata": {}, + "source": [ + "We take the forward process by calling out the forward function, then we pass the optimal params into the outer-loop loss function." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "115e79c6-911f-4743-a2ed-e50a71c3a813", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "optimal_params = inner_solver(clone(meta_params), meta_params, data)\n", + "\n", + "outer_loss = fmodel(optimal_params, x).mean()" + ] + }, + { + "cell_type": "markdown", + "id": "e2812351-f635-496e-9732-c80831ac04a6", + "metadata": {}, + "source": [ + "Finally, we can get the meta gradient as shown below." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6bdcbe8d-2336-4f80-b124-eb43c5a2fc0a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(tensor([[-0.0369, 0.0248, 0.0347, 0.0067]]), tensor([0.3156]))\n" + ] + } + ], + "source": [ + "torch.autograd.grad(outer_loss, meta_params)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.8.12 ('torchopt')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "vscode": { + "interpreter": { + "hash": "2a8cc1ff2cbc47027bf9993941710d9ab9175f14080903d9c7c432ee63d681da" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From cc5fb798d5fc464e7954569648cdfb7185da8011 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Fri, 23 Sep 2022 15:59:15 +0800 Subject: [PATCH 19/69] chore: add .github/dependabot.yml (#79) --- .github/dependabot.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..7612124f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,27 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + allow: + # Allow all updates for + # PyTorch and any packages starting "torch" + # - dependency-name: "torch*" + # dependency-type: "all" + # Allow both direct and indirect updates for all packages + - dependency-type: "all" + # Include a list of updated dependencies + # with a prefix determined by the dependency group + commit-message: + prefix: "pip prod" + prefix-development: "pip dev" + include: "scope" + # Add assignees + assignees: + - "XuehaiPan" From bc7a1c50d849e8a98896b1e9eb230c8b09985f8f Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 23 Sep 2022 23:25:27 +0800 Subject: [PATCH 20/69] revert: "chore: add .github/dependabot.yml" (#91) --- .github/dependabot.yml | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 7612124f..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,27 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: "pip" - directory: "/" - schedule: - interval: "weekly" - allow: - # Allow all updates for - # PyTorch and any packages starting "torch" - # - dependency-name: "torch*" - # dependency-type: "all" - # Allow both direct and indirect updates for all packages - - dependency-type: "all" - # Include a list of updated dependencies - # with a prefix determined by the dependency group - commit-message: - prefix: "pip prod" - prefix-development: "pip dev" - include: "scope" - # Add assignees - assignees: - - "XuehaiPan" From af6d24cbb1b80b5c056ff24b2ad74500d68302dd Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sun, 25 Sep 2022 18:49:02 +0800 Subject: [PATCH 21/69] refactor: reorganize code and add full type hint (#92) --- .github/workflows/build.yml | 8 +- .github/workflows/lint.yml | 9 +- .github/workflows/tests.yml | 4 +- .gitignore | 5 +- .pylintrc | 5 +- CHANGELOG.md | 3 +- CMakeLists.txt | 4 +- MANIFEST.in | 1 + Makefile | 6 +- conda-recipe.yaml | 6 +- docs/conda-recipe.yaml | 6 +- docs/requirements.txt | 5 +- docs/source/api/api.rst | 14 +- docs/source/spelling_wordlist.txt | 1 + examples/requirements.txt | 1 + pyproject.toml | 24 +- requirements.txt | 3 +- setup.py | 4 +- tests/test_optim.py | 420 ++++++++++++++++++ torchopt/__init__.py | 30 +- torchopt/_src/typing.py | 28 -- torchopt/_src/utils.py | 198 --------- .../{_src => }/accelerated_op/__init__.py | 9 +- torchopt/{_src => }/accelerated_op/adam_op.py | 1 + torchopt/{_src => }/alias.py | 12 +- torchopt/{_src => }/base.py | 44 +- torchopt/{_src => }/clip.py | 17 +- torchopt/{_src => }/combine.py | 10 +- torchopt/{_src => }/hook.py | 8 +- torchopt/{_src => }/implicit_diff.py | 40 +- torchopt/{_src => }/linalg.py | 14 +- torchopt/{_src => }/linear_solve.py | 17 +- .../{_src/optimizer => optim}/__init__.py | 15 +- torchopt/{_src/optimizer => optim}/adam.py | 12 +- torchopt/{_src/optimizer => optim}/adamw.py | 15 +- torchopt/{_src/optimizer => optim}/base.py | 52 ++- torchopt/{_src => optim/func}/__init__.py | 3 +- .../{_src/optimizer => optim}/func/base.py | 24 +- .../optimizer => optim}/meta/__init__.py | 11 +- .../{_src/optimizer => optim}/meta/adam.py | 12 +- .../{_src/optimizer => optim}/meta/adamw.py | 15 +- .../{_src/optimizer => optim}/meta/base.py | 54 ++- .../{_src/optimizer => optim}/meta/rmsprop.py | 12 +- .../{_src/optimizer => optim}/meta/sgd.py | 12 +- torchopt/{_src/optimizer => optim}/rmsprop.py | 12 +- torchopt/{_src/optimizer => optim}/sgd.py | 12 +- torchopt/py.typed | 0 .../optimizer/func/__init__.py => pytree.py} | 10 +- torchopt/{_src => }/schedule.py | 13 +- torchopt/{_src => }/transform.py | 136 +++--- torchopt/typing.py | 62 +++ torchopt/{_src => }/update.py | 12 +- torchopt/utils.py | 273 ++++++++++++ torchopt/{_src => }/visual.py | 66 +-- tutorials/requirements.txt | 1 + 55 files changed, 1227 insertions(+), 564 deletions(-) create mode 100644 tests/test_optim.py delete mode 100644 torchopt/_src/typing.py delete mode 100644 torchopt/_src/utils.py rename torchopt/{_src => }/accelerated_op/__init__.py (85%) rename torchopt/{_src => }/accelerated_op/adam_op.py (99%) rename torchopt/{_src => }/alias.py (98%) rename torchopt/{_src => }/base.py (90%) rename torchopt/{_src => }/clip.py (91%) rename torchopt/{_src => }/combine.py (88%) rename torchopt/{_src => }/hook.py (90%) rename torchopt/{_src => }/implicit_diff.py (94%) rename torchopt/{_src => }/linalg.py (96%) rename torchopt/{_src => }/linear_solve.py (94%) rename torchopt/{_src/optimizer => optim}/__init__.py (66%) rename torchopt/{_src/optimizer => optim}/adam.py (94%) rename torchopt/{_src/optimizer => optim}/adamw.py (93%) rename torchopt/{_src/optimizer => optim}/base.py (69%) rename torchopt/{_src => optim/func}/__init__.py (88%) rename torchopt/{_src/optimizer => optim}/func/base.py (86%) rename torchopt/{_src/optimizer => optim}/meta/__init__.py (69%) rename torchopt/{_src/optimizer => optim}/meta/adam.py (94%) rename torchopt/{_src/optimizer => optim}/meta/adamw.py (92%) rename torchopt/{_src/optimizer => optim}/meta/base.py (70%) rename torchopt/{_src/optimizer => optim}/meta/rmsprop.py (93%) rename torchopt/{_src/optimizer => optim}/meta/sgd.py (92%) rename torchopt/{_src/optimizer => optim}/rmsprop.py (94%) rename torchopt/{_src/optimizer => optim}/sgd.py (93%) create mode 100644 torchopt/py.typed rename torchopt/{_src/optimizer/func/__init__.py => pytree.py} (74%) rename torchopt/{_src => }/schedule.py (94%) rename torchopt/{_src => }/transform.py (89%) create mode 100644 torchopt/typing.py rename torchopt/{_src => }/update.py (90%) create mode 100644 torchopt/utils.py rename torchopt/{_src => }/visual.py (82%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4128b4b3..78d89f4b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.7 - 3.10" + python-version: "3.7 - 3.10" # sync with requires-python in pyproject.toml update-environment: true - name: Set __release__ @@ -95,7 +95,7 @@ jobs: id: py uses: actions/setup-python@v4 with: - python-version: "3.7 - 3.10" + python-version: "3.7 - 3.10" # sync with requires-python in pyproject.toml update-environment: true - name: Set __release__ @@ -107,7 +107,7 @@ jobs: run: python setup.py --version - name: Build wheels - uses: pypa/cibuildwheel@v2.10.0 + uses: pypa/cibuildwheel@v2.10.2 with: package-dir: . output-dir: wheelhouse @@ -138,7 +138,7 @@ jobs: uses: actions/setup-python@v4 if: startsWith(github.ref, 'refs/tags/') with: - python-version: "3.7 - 3.10" + python-version: "3.7 - 3.10" # sync with requires-python in pyproject.toml update-environment: true - name: Check consistency between the package version and release tag diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 44ece663..eb94beff 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -26,10 +26,10 @@ jobs: submodules: "recursive" fetch-depth: 1 - - name: Set up Python 3.7 # the lowest version we support + - name: Set up Python 3.7 uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.7" # the lowest version we support (sync with requires-python in pyproject.toml) update-environment: true - name: Setup CUDA Toolkit @@ -90,6 +90,11 @@ jobs: run: | make addlicense + - name: Install dev version of mypy + run: | + python -m pip install git+https://github.com/python/mypy.git + python -m pip install types-setuptools + - name: mypy run: | make mypy diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c36e78f2..7aafa905 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -37,10 +37,10 @@ jobs: submodules: "recursive" fetch-depth: 1 - - name: Set up Python 3.7 # the lowest version we support + - name: Set up Python 3.7 uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.7" # the lowest version we support (sync with requires-python in pyproject.toml) update-environment: true - name: Setup CUDA Toolkit diff --git a/.gitignore b/.gitignore index 69c9826d..09dbde3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -##### Project specific ##### -!torchopt/_src/ -!torchopt/_lib/ - ##### Python.gitignore ##### # Byte-compiled / optimized / DLL files __pycache__/ @@ -31,6 +27,7 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST +*.whl # PyInstaller # Usually these files are written by a python script from a template diff --git a/.pylintrc b/.pylintrc index e55faae7..1b77af4c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -53,7 +53,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.7 +py-version=3.7 # the lowest version we support (sync with requires-python in pyproject.toml) # Discover python modules and packages in the file system subtree. recursive=no @@ -266,7 +266,8 @@ good-names=i, t, lr, mu, - nu + nu, + x # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted diff --git a/CHANGELOG.md b/CHANGELOG.md index a187713e..5f95fdf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,13 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add full type hints by [@XuehaiPan](https://github.com/XuehaiPan) in [#92](https://github.com/metaopt/torchopt/pull/92). - Add API documentation and tutorial for implicit gradients by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan) in [#73](https://github.com/metaopt/torchopt/pull/73). - Add wrapper class for functional optimizers and examples of `functorch` integration by [@vmoens](https://github.com/vmoens) and [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@XuehaiPan](https://github.com/XuehaiPan) in [#6](https://github.com/metaopt/torchopt/pull/6). - Implicit differentiation support by [@JieRen98](https://github.com/JieRen98) and [@waterhorse1](https://github.com/waterhorse1) and [@XuehaiPan](https://github.com/XuehaiPan) in [#41](https://github.com/metaopt/torchopt/pull/41). ### Changed - +- Refactor code organization by [@XuehaiPan](https://github.com/XuehaiPan) in [#92](https://github.com/metaopt/torchopt/pull/92). ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index 26786756..30251a20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,7 +178,7 @@ if(NOT DEFINED PYTHON_INCLUDE_DIR) message(STATUS "Auto detecting Python include directory...") system( STRIP OUTPUT_VARIABLE PYTHON_INCLUDE_DIR - COMMAND "${PYTHON_EXECUTABLE}" -c "print(__import__('sysconfig').get_path('include'))" + COMMAND "${PYTHON_EXECUTABLE}" -c "print(__import__('sysconfig').get_path('platinclude'))" ) endif() @@ -191,7 +191,7 @@ endif() system( STRIP OUTPUT_VARIABLE PYTHON_SITE_PACKAGES - COMMAND "${PYTHON_EXECUTABLE}" -c "print(__import__('sysconfig') .get_path('purelib'))" + COMMAND "${PYTHON_EXECUTABLE}" -c "print(__import__('sysconfig').get_path('purelib'))" ) message(STATUS "Detected Python site packages: \"${PYTHON_SITE_PACKAGES}\"") diff --git a/MANIFEST.in b/MANIFEST.in index 08cf6257..09403999 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ recursive-include torchopt *.pyi +recursive-include torchopt *.typed include LICENSE # Include source files in sdist diff --git a/Makefile b/Makefile index bec404be..a0d72709 100644 --- a/Makefile +++ b/Makefile @@ -106,7 +106,7 @@ flake8: flake8-install $(PYTHON) -m flake8 $(PYTHON_FILES) --count --select=E9,F63,F7,F82,E225,E251 --show-source --statistics py-format: py-format-install - $(PYTHON) -m isort --project torchopt --check $(PYTHON_FILES) && \ + $(PYTHON) -m isort --project $(PROJECT_NAME) --check $(PYTHON_FILES) && \ $(PYTHON) -m black --check $(PYTHON_FILES) mypy: mypy-install @@ -143,10 +143,10 @@ clean-docs: # Utility functions -lint: flake8 py-format mypy clang-format cpplint docstyle spelling +lint: flake8 py-format mypy pylint clang-format cpplint docstyle spelling format: py-format-install clang-format-install addlicense-install - $(PYTHON) -m isort --project torchopt $(PYTHON_FILES) + $(PYTHON) -m isort --project $(PROJECT_NAME) $(PYTHON_FILES) $(PYTHON) -m black $(PYTHON_FILES) clang-format -style=file -i $(CXX_FILES) addlicense -c $(COPYRIGHT) -l apache -y 2022 $(SOURCE_FOLDERS) diff --git a/conda-recipe.yaml b/conda-recipe.yaml index 19229136..bd6d3225 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -17,11 +17,11 @@ dependencies: - pip # Learning - - pytorch::pytorch >= 1.12 + - pytorch::pytorch >= 1.12 # sync with project.dependencies - pytorch::torchvision - pytorch::pytorch-mutex = *=*cuda* - pip: - - functorch >= 0.2 + - functorch >= 0.2 # sync with project.dependencies - torchviz - sphinxcontrib-katex # for documentation - jax # for tutorials @@ -64,7 +64,7 @@ dependencies: - myst-nb - ipykernel - pandoc - - docutils = 0.16 + - docutils # Testing - pytest diff --git a/docs/conda-recipe.yaml b/docs/conda-recipe.yaml index 7ba50adb..476dc1a2 100644 --- a/docs/conda-recipe.yaml +++ b/docs/conda-recipe.yaml @@ -30,10 +30,10 @@ dependencies: - pip # Learning - - pytorch::pytorch >= 1.12 + - pytorch::pytorch >= 1.12 # sync with project.dependencies - pytorch::pytorch-mutex = *=*cpu* - pip: - - functorch >= 0.2 + - functorch >= 0.2 # sync with project.dependencies - torchviz - sphinxcontrib-katex # for documentation - tensorboard @@ -68,4 +68,4 @@ dependencies: - myst-nb - ipykernel - pandoc - - docutils = 0.16 + - docutils diff --git a/docs/requirements.txt b/docs/requirements.txt index f2c72f62..25615049 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,10 +1,11 @@ --extra-index-url https://download.pytorch.org/whl/cpu +# Sync with project.dependencies torch >= 1.12 functorch >= 0.2 --requirement ../requirements.txt -sphinx >= 5.0 +sphinx >= 5.0, < 5.2.0a0 sphinx-autoapi sphinx-autobuild sphinx-copybutton @@ -16,5 +17,5 @@ IPython ipykernel pandoc myst_nb -docutils == 0.16 +docutils matplotlib diff --git a/docs/source/api/api.rst b/docs/source/api/api.rst index b77fd648..5b632e9f 100644 --- a/docs/source/api/api.rst +++ b/docs/source/api/api.rst @@ -134,7 +134,7 @@ Differentiable Meta-RMSProp Optimizer Implicit differentiation ======================== -.. currentmodule:: torchopt._src.implicit_diff +.. currentmodule:: torchopt.implicit_diff .. autosummary:: @@ -150,7 +150,7 @@ Custom solvers Linear system solving ===================== -.. currentmodule:: torchopt._src.linear_solve +.. currentmodule:: torchopt.linear_solve .. autosummary:: @@ -168,7 +168,7 @@ Indirect solvers Optimizer Hooks =============== -.. currentmodule:: torchopt._src.hook +.. currentmodule:: torchopt.hook .. autosummary:: @@ -186,7 +186,7 @@ Hook Gradient Transformation ======================= -.. currentmodule:: torchopt._src.clip +.. currentmodule:: torchopt.clip .. autosummary:: @@ -200,7 +200,7 @@ Transforms Optimizer Schedules =================== -.. currentmodule:: torchopt._src.schedule +.. currentmodule:: torchopt.schedule .. autosummary:: @@ -231,7 +231,7 @@ Apply Updates Combining Optimizers ==================== -.. currentmodule:: torchopt._src.combine +.. currentmodule:: torchopt.combine .. autosummary:: @@ -273,7 +273,7 @@ Stop Gradient Visualizing Gradient Flow ========================= -.. currentmodule:: torchopt._src.visual +.. currentmodule:: torchopt.visual .. autosummary:: diff --git a/docs/source/spelling_wordlist.txt b/docs/source/spelling_wordlist.txt index 7436b3ef..ecdb936a 100644 --- a/docs/source/spelling_wordlist.txt +++ b/docs/source/spelling_wordlist.txt @@ -83,3 +83,4 @@ optimality argnums matvec Hermitian +deepcopy diff --git a/examples/requirements.txt b/examples/requirements.txt index 66636aad..a36da3aa 100644 --- a/examples/requirements.txt +++ b/examples/requirements.txt @@ -12,3 +12,4 @@ seaborn torchviz torchrl pillow +setproctitle diff --git a/pyproject.toml b/pyproject.toml index e59a21e9..db908e6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,7 @@ # Package ###################################################################### [build-system] +# Sync with project.dependencies requires = ["setuptools", "torch >= 1.12", "numpy", "pybind11"] build-backend = "setuptools.build_meta" @@ -8,7 +9,9 @@ build-backend = "setuptools.build_meta" name = "torchopt" description = "A Jax-style optimizer for PyTorch." readme = "README.md" -requires-python = ">= 3.7" +# Change this if wheels for `torch` is available +# Search "requires-python" and update all corresponding items +requires-python = ">= 3.7, < 3.11.0a0" authors = [ { name = "TorchOpt Contributors" }, { name = "Jie Ren", email = "jieren9806@gmail.com" }, @@ -29,6 +32,7 @@ keywords = [ classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: Apache Software License", + # Sync with requires-python "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", @@ -44,9 +48,9 @@ classifiers = [ "Topic :: Scientific/Engineering :: Artificial Intelligence", ] dependencies = [ - "torch >= 1.12", + "torch >= 1.12", # see also build-system.requires and project.requires-python "functorch >= 0.2", - "optree", + "optree >= 0.2.0", "numpy", "graphviz", "typing-extensions", @@ -88,7 +92,7 @@ include = ["torchopt", "torchopt.*"] # Wheel builder ################################################################ # Reference: https://cibuildwheel.readthedocs.io [tool.cibuildwheel] -archs = ["x86_64"] +archs = ["auto64"] build = "*manylinux*" skip = "pp*" build-frontend = "pip" @@ -163,6 +167,7 @@ repair-wheel-command = """ safe = true line-length = 100 skip-string-normalization = true +# Sync with requires-python target-version = ["py37", "py38", "py39", "py310"] [tool.isort] @@ -174,16 +179,19 @@ lines_after_imports = 2 multi_line_output = 3 [tool.mypy] +# Sync with requires-python +python_version = 3.7 +pretty = true +show_error_codes = true +show_error_context = true +show_traceback = true allow_redefinition = true +enable_recursive_aliases = true check_untyped_defs = true disallow_incomplete_defs = false disallow_untyped_defs = false ignore_missing_imports = true no_implicit_optional = true -pretty = true -show_error_codes = true -show_error_context = true -show_traceback = true strict_equality = true strict_optional = true warn_no_return = true diff --git a/requirements.txt b/requirements.txt index 8c520b14..a1d24b21 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ +# Sync with project.dependencies torch >= 1.12 functorch >= 0.2 -optree +optree >= 0.2.0 numpy graphviz typing-extensions diff --git a/setup.py b/setup.py index fe316152..f457b32e 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ import pathlib import shutil import sys +import sysconfig from setuptools import setup @@ -47,7 +48,6 @@ def build_extension(self, ext): extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) print(self.get_ext_fullpath(ext.name)) - PYTHON_INCLUDE_DIR = ';'.join(self.include_dirs) TORCH_INCLUDE_PATH = ';'.join(cpp_extension.include_paths()) TORCH_LIBRARY_PATH = ';'.join(cpp_extension.library_paths()) @@ -57,7 +57,7 @@ def build_extension(self, ext): f'-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_{config.upper()}={self.build_temp}', f'-DPYTHON_EXECUTABLE={sys.executable}', f'-DPYBIND11_CMAKE_DIR={pybind11.get_cmake_dir()}', - f'-DPYTHON_INCLUDE_DIR={PYTHON_INCLUDE_DIR}', + f'-DPYTHON_INCLUDE_DIR={sysconfig.get_path("platinclude")}', f'-DTORCH_INCLUDE_PATH={TORCH_INCLUDE_PATH}', f'-DTORCH_LIBRARY_PATH={TORCH_LIBRARY_PATH}', ] diff --git a/tests/test_optim.py b/tests/test_optim.py new file mode 100644 index 00000000..f8fff9a3 --- /dev/null +++ b/tests/test_optim.py @@ -0,0 +1,420 @@ +# Copyright 2022 MetaOPT Team. 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 typing import Callable, Tuple + +import functorch +import pytest +import torch +import torch.nn.functional as F + +import helpers +import torchopt + + +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-2, 1e-3, 1e-4], + momentum=[0.0, 0.1], + dampening=[0.0, 0.5], + nesterov=[False, True], + weight_decay=[0.0, 1e-2], + maximize=[False], # TODO: test maximize after PyTorch 1.13 +) +def test_SGD( + dtype: torch.dtype, + lr: float, + momentum: float, + dampening: float, + nesterov: bool, + weight_decay: float, + maximize: bool, +) -> None: + if nesterov and (momentum <= 0.0 or dampening != 0.0): + pytest.skip('Nesterov momentum requires a momentum and zero dampening.') + + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + optim = torchopt.SGD( + model.parameters(), + lr, + momentum=momentum, + dampening=dampening, + nesterov=nesterov, + weight_decay=weight_decay, + maximize=maximize, + ) + optim_ref = torch.optim.SGD( + model_ref.parameters(), + lr, + momentum=momentum, + dampening=dampening, + nesterov=nesterov, + weight_decay=weight_decay, + maximize=maximize, + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = model(xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + optim.zero_grad() + loss.backward() + optim.step() + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) + + +@helpers.parametrize( + dtype=[torch.float64], + lr=[1e-2, 1e-3, 1e-4], + betas=[(0.9, 0.999), (0.95, 0.9995)], + eps=[1e-8], + weight_decay=[0.0, 1e-2], + maximize=[False, True], +) +def test_Adam( + dtype: torch.dtype, + lr: float, + betas: Tuple[float, float], + eps: float, + weight_decay: float, + maximize: bool, +) -> None: + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + optim = torchopt.Adam( + model.parameters(), + lr, + betas=betas, + eps=eps, + eps_root=0.0, + weight_decay=weight_decay, + maximize=maximize, + ) + optim_ref = torch.optim.Adam( + model_ref.parameters(), + lr, + betas=betas, + eps=eps, + amsgrad=False, + weight_decay=weight_decay, + maximize=maximize, + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = model(xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + optim.zero_grad() + loss.backward() + optim.step() + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) + + +@helpers.parametrize( + dtype=[torch.float64], + lr=[1e-2, 1e-3, 1e-4], + betas=[(0.9, 0.999), (0.95, 0.9995)], + eps=[1e-8], + weight_decay=[1e-2, 1e-1], + maximize=[False, True], +) +def test_AdamW( + dtype: torch.dtype, + lr: float, + betas: Tuple[float, float], + eps: float, + weight_decay: float, + maximize: bool, +) -> None: + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + optim = torchopt.AdamW( + model.parameters(), + lr, + betas=betas, + eps=eps, + eps_root=0.0, + weight_decay=weight_decay, + maximize=maximize, + ) + optim_ref = torch.optim.AdamW( + model_ref.parameters(), + lr, + betas=betas, + eps=eps, + amsgrad=False, + weight_decay=weight_decay, + maximize=maximize, + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = model(xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + optim.zero_grad() + loss.backward() + optim.step() + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) + + +@helpers.parametrize( + dtype=[torch.float64], + lr=[1e-2, 1e-3, 1e-4], + betas=[(0.9, 0.999), (0.95, 0.9995)], + eps=[1e-8], + weight_decay=[0.0, 1e-2], + maximize=[False, True], +) +def test_Adam_accelerated_cpu( + dtype: torch.dtype, + lr: float, + betas: Tuple[float, float], + eps: float, + weight_decay: float, + maximize: bool, +) -> None: + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + optim = torchopt.Adam( + model.parameters(), + lr, + betas=betas, + eps=eps, + eps_root=0.0, + weight_decay=weight_decay, + maximize=maximize, + use_accelerated_op=True, + ) + optim_ref = torch.optim.Adam( + model_ref.parameters(), + lr, + betas=betas, + eps=eps, + amsgrad=False, + weight_decay=weight_decay, + maximize=maximize, + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = model(xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + optim.zero_grad() + loss.backward() + optim.step() + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) + + +@pytest.mark.skipif(not torch.cuda.is_available(), reason='No CUDA device available.') +@helpers.parametrize( + dtype=[torch.float64], + lr=[1e-2, 1e-3, 1e-4], + betas=[(0.9, 0.999), (0.95, 0.9995)], + eps=[1e-8], + weight_decay=[0.0, 1e-2], + maximize=[False, True], +) +def test_Adam_accelerated_cuda( + dtype: torch.dtype, + lr: float, + betas: Tuple[float, float], + eps: float, + weight_decay: float, + maximize: bool, +) -> None: + device = 'cuda' + model, model_ref, model_base, loader = helpers.get_models(device=device, dtype=dtype) + + optim = torchopt.Adam( + model.parameters(), + lr, + betas=betas, + eps=eps, + eps_root=0.0, + weight_decay=weight_decay, + maximize=maximize, + use_accelerated_op=True, + ) + optim_ref = torch.optim.Adam( + model_ref.parameters(), + lr, + betas=betas, + eps=eps, + amsgrad=False, + weight_decay=weight_decay, + maximize=maximize, + ) + + for xs, ys in loader: + xs = xs.to(device=device, dtype=dtype) + ys = ys.to(device=device) + pred = model(xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + optim.zero_grad() + loss.backward() + optim.step() + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) + + +@helpers.parametrize( + dtype=[torch.float64], + lr=[1e-2, 1e-3, 1e-4], + alpha=[0.9, 0.99], + eps=[1e-8], + momentum=[0.0, 0.1], + centered=[False, True], + weight_decay=[0.0, 1e-2], +) +def test_RMSProp( + dtype: torch.dtype, + lr: float, + alpha: float, + eps: float, + momentum: float, + centered: bool, + weight_decay: float, +) -> None: + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + optim = torchopt.RMSProp( + model.parameters(), + lr, + alpha=alpha, + eps=eps, + momentum=momentum, + centered=centered, + nesterov=False, + weight_decay=weight_decay, + ) + optim_ref = torch.optim.RMSprop( + model_ref.parameters(), + lr, + alpha=alpha, + eps=eps, + momentum=momentum, + centered=centered, + weight_decay=weight_decay, + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = model(xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + optim.zero_grad() + loss.backward() + optim.step() + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) + + +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-2, 1e-3], + optimizers=[ + (torchopt.sgd, torch.optim.SGD), + (torchopt.adam, torch.optim.Adam), + (torchopt.adamw, torch.optim.AdamW), + (torchopt.rmsprop, torch.optim.RMSprop), + ], + inplace=[True, False], + weight_decay=[0.0, 1e-2], +) +def test_FuncOptimizer( + dtype: torch.dtype, + lr: float, + optimizers: Tuple[Callable, torch.optim.Optimizer], + inplace: bool, + weight_decay: float, +) -> None: + model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) + + torchopt_optimizer, torch_optimizer = optimizers + + fmodel, params, buffers = functorch.make_functional_with_buffers(model) + optim = torchopt.FuncOptimizer( + torchopt_optimizer( + lr=lr, + weight_decay=weight_decay, + ), + inplace=inplace, + ) + optim_ref = torch_optimizer( + model_ref.parameters(), + lr, + weight_decay=weight_decay, + ) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + pred = fmodel(params, buffers, xs) + pred_ref = model_ref(xs) + loss = F.cross_entropy(pred, ys) + loss_ref = F.cross_entropy(pred_ref, ys) + + params = optim.step(loss, params) + + optim_ref.zero_grad() + loss_ref.backward() + optim_ref.step() + + helpers.assert_model_all_close((params, buffers), model_ref, model_base, dtype=dtype) diff --git a/torchopt/__init__.py b/torchopt/__init__.py index 15aa8a08..eeff87cc 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -14,22 +14,25 @@ # ============================================================================== """TorchOpt: a high-performance optimizer library built upon PyTorch.""" -from torchopt._src import ( - accelerated_op_available, +from torchopt import ( clip, combine, hook, implicit_diff, + linalg, linear_solve, + pytree, schedule, + typing, visual, ) -from torchopt._src.alias import adam, adamw, rmsprop, sgd -from torchopt._src.clip import clip_grad_norm -from torchopt._src.combine import chain -from torchopt._src.optimizer import SGD, Adam, AdamW, Optimizer, RMSProp, RMSprop, meta -from torchopt._src.optimizer.func import FuncOptimizer -from torchopt._src.optimizer.meta import ( +from torchopt.accelerated_op import is_available as accelerated_op_available +from torchopt.alias import adam, adamw, rmsprop, sgd +from torchopt.clip import clip_grad_norm +from torchopt.combine import chain +from torchopt.optim import SGD, Adam, AdamW, Optimizer, RMSProp, RMSprop, meta +from torchopt.optim.func import FuncOptimizer +from torchopt.optim.meta import ( MetaAdam, MetaAdamW, MetaOptimizer, @@ -37,20 +40,13 @@ MetaRMSprop, MetaSGD, ) -from torchopt._src.update import apply_updates -from torchopt._src.utils import extract_state_dict, pytree, recover_state_dict, stop_gradient +from torchopt.update import apply_updates +from torchopt.utils import extract_state_dict, recover_state_dict, stop_gradient from torchopt.version import __version__ __all__ = [ 'accelerated_op_available', - 'clip', - 'combine', - 'hook', - 'schedule', - 'visual', - 'implicit_diff', - 'linear_solve', 'adam', 'adamw', 'rmsprop', diff --git a/torchopt/_src/typing.py b/torchopt/_src/typing.py deleted file mode 100644 index b2104682..00000000 --- a/torchopt/_src/typing.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2022 MetaOPT Team. 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 typing import Any, Callable, Iterable, Mapping, TypeVar, Union - -from torch import Tensor - - -Scalar = TypeVar('Scalar', float, int) -Numeric = Union[Tensor, Scalar] - -Schedule = Callable[[Numeric], Numeric] -ScalarOrSchedule = Union[float, Schedule] - -# mypy: ignore-errors -TensorTree = Union[Tensor, Iterable['TensorTree'], Mapping[Any, 'TensorTree']] diff --git a/torchopt/_src/utils.py b/torchopt/_src/utils.py deleted file mode 100644 index c68c6391..00000000 --- a/torchopt/_src/utils.py +++ /dev/null @@ -1,198 +0,0 @@ -# Copyright 2022 MetaOPT Team. 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 typing import Dict, List, NamedTuple, Union - -import optree as pytree -import torch -import torch.nn as nn - - -class _ModuleState(NamedTuple): - params: List[Dict] - visual_contents: Union[None, Dict] = None - - -# mypy: ignore-errors -def stop_gradient(target): - """Stop the gradient for the input object. - - Since a tensor use :attr:`grad_fn` to connect itself with the previous computation graph, the - back-propagated gradient will flow over the tensor and continue flow to the tensors that is - connected by :attr:`grad_fn`. Some algorithms requires manually detaching tensors from the - computation graph. - - Note that the :func:`stop_gradient` operation is in-place. - - Args: - target: The target that to be detached from the computation graph, it could be a - :class:`nn.Module`, :class:`torchopt.MetaOptimizer`, state of the - :class:`torchopt.MetaOptimizer`, or just a plain list of tensors. - inplace: If :data:`True`, the target will be detached in-place. if :data:`Frue`, this - function will return a detached copy of the target. The in-place operation is fast and - memory efficient but may raise back-propagation error. - """ - # pylint: disable-next=import-outside-toplevel,cyclic-import - from torchopt._src.optimizer.meta.base import MetaOptimizer - - def f(obj): - if torch.is_tensor(obj): - requires_grad = obj.requires_grad - obj.detach_().requires_grad_(requires_grad) - - if isinstance(target, _ModuleState): - true_target = target.params - elif isinstance(target, nn.Module): - true_target = tuple(target.parameters()) - elif isinstance(target, MetaOptimizer): - true_target = pytree.tree_leaves(target.state_dict()) - else: - true_target = target - - pytree.tree_map(f, true_target) - - -# pylint: disable-next=too-many-branches,too-many-locals -def extract_state_dict(mod, copy=False, *, with_buffer=True, enable_visual=False, visual_prefix=''): - """Extract target state. - - Since a tensor use :attr:`grad_fn` to connect itself with the previous computation graph, the - back-propagated gradient will flow over the tensor and continue flow to the tensors that is - connected by :attr:`grad_fn`. Some algorithms requires manually detaching tensors from the - computation graph. - - Note that the extracted state is a reference, which means any in-place operator will affect the - target that the state is extracted from. - - Args: - mod: It could be a :class:`nn.Module` or :class:`torchopt.MetaOptimizer`. - with_buffer: - Extract buffer together with parameters, this argument is only used if the input target - is :class:`nn.Module`. - enable_visual: - Add additional annotations, which could be used in computation graph visualization. - Currently, this flag only has effect on :class:`nn.Module` but we will support - :class:`torchopt.MetaOptimizer` later. - visual_prefix: Prefix for the visualization annotations. - - Returns: - State extracted of the input object. - """ - # pylint: disable=import-outside-toplevel,cyclic-import - from torchopt._src.optimizer.meta.base import MetaOptimizer - - if isinstance(mod, nn.Module): # pylint: disable=no-else-return - if enable_visual: - visual_contents = {} - - for k, v in mod.named_parameters(): # pylint: disable=invalid-name - if v.grad_fn is not None: - visual_contents.update({v.grad_fn: (visual_prefix + k, v)}) - else: - visual_contents.update({v: visual_prefix + k}) - else: - visual_contents = None - - params = [] - - def get_variable(t): - if copy: - requires_grad = t.requires_grad - return t.clone().detach_().requires_grad_(requires_grad) - return t - - def update_container(term): - if len(term) != 0: - params.append( - type(term)( - (k, get_variable(v)) for k, v in term.items() if isinstance(v, torch.Tensor) - ) - ) - - # pylint: disable=protected-access - update_container(mod._parameters) - if with_buffer: - update_container(mod._buffers) - for module in mod.modules(): - if module is mod: - continue - update_container(module._parameters) - if with_buffer: - update_container(module._buffers) - return _ModuleState(params=tuple(params), visual_contents=visual_contents) - - elif isinstance(mod, MetaOptimizer): - state = mod.state_dict() - if copy: - - def get_variable(t): - if not torch.is_tensor(t): - return t - requires_grad = t.requires_grad - return t.clone().detach_().requires_grad_(requires_grad) - - return pytree.tree_map(get_variable, state) - - return state - - raise RuntimeError(f'Unexpected class of {mod}') - - -def _extract_container(mod, with_buffer=True): - if isinstance(mod, nn.Module): - containers = [] - - def update_container(term): - if len(term) != 0: - containers.append(term) # we need references to original dicts - - # pylint: disable=protected-access - update_container(mod._parameters) - if with_buffer: - update_container(mod._buffers) - for module in mod.modules(): - if module is mod: - continue - update_container(module._parameters) - if with_buffer: - update_container(module._buffers) - return tuple(containers) - - raise RuntimeError(f'Unexpected class of {mod}') - - -def recover_state_dict(mod, state): - """Recover state. - - This function is compatible for the ``extract_state``. - - Note that the recovering process is not in-place, so the tensors of the object will not be - modified. - - Args: - mod: Target that need to recover. - state: The recovering state. - """ - # pylint: disable-next=import-outside-toplevel,cyclic-import - from torchopt._src.optimizer.meta.base import MetaOptimizer - - if isinstance(mod, nn.Module): - target_container = _extract_container(mod) - for target, source in zip(target_container, state.params): - target.update(source) - elif isinstance(mod, MetaOptimizer): - mod.load_state_dict(state) - else: - raise RuntimeError(f'Unexpected class of {mod}') diff --git a/torchopt/_src/accelerated_op/__init__.py b/torchopt/accelerated_op/__init__.py similarity index 85% rename from torchopt/_src/accelerated_op/__init__.py rename to torchopt/accelerated_op/__init__.py index 4c7f1cd9..874174f2 100644 --- a/torchopt/_src/accelerated_op/__init__.py +++ b/torchopt/accelerated_op/__init__.py @@ -12,16 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""The accelerated Ops.""" from typing import Iterable, Optional, Union import torch -from torchopt._src.accelerated_op.adam_op import AdamOp +from torchopt.accelerated_op.adam_op import AdamOp -def accelerated_op_available( - devices: Optional[Union[str, torch.device, Iterable[Union[str, torch.device]]]] = None +def is_available( + devices: Optional[Union[int, str, torch.device, Iterable[Union[int, str, torch.device]]]] = None ) -> bool: """Check the availability of accelerated optimizer.""" op = AdamOp() @@ -30,7 +31,7 @@ def accelerated_op_available( devices = [torch.device('cuda'), torch.device('cpu')] elif isinstance(devices, torch.device): devices = [devices] - elif isinstance(devices, str): + elif isinstance(devices, (int, str)): devices = [torch.device(devices)] try: diff --git a/torchopt/_src/accelerated_op/adam_op.py b/torchopt/accelerated_op/adam_op.py similarity index 99% rename from torchopt/_src/accelerated_op/adam_op.py rename to torchopt/accelerated_op/adam_op.py index 00261c1a..48f83584 100644 --- a/torchopt/_src/accelerated_op/adam_op.py +++ b/torchopt/accelerated_op/adam_op.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""The accelerated AdamOp.""" # pylint: disable=c-extension-no-member,invalid-name diff --git a/torchopt/_src/alias.py b/torchopt/alias.py similarity index 98% rename from torchopt/_src/alias.py rename to torchopt/alias.py index 019e0248..4d641b4f 100644 --- a/torchopt/_src/alias.py +++ b/torchopt/alias.py @@ -29,13 +29,17 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +r"""The aliases of preset ``GradientTransformation``\s for optimizers.""" # pylint: disable=invalid-name from typing import Any, Callable, Optional, Tuple, Union -from torchopt._src import base, combine, transform -from torchopt._src.typing import ScalarOrSchedule +from torchopt import base, combine, transform +from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import + + +__all__ = ['adam', 'adamw', 'rmsprop', 'sgd'] def _flip_sign_and_weight_decay(weight_decay: float = 0.0, maximize=False): @@ -126,7 +130,7 @@ def _scale_by_neg_lr(lr: ScalarOrSchedule): if callable(lr): def schedule_wrapper(count): - return -lr(count) # type: ignore[operator] + return -lr(count) # pylint: disable-next=protected-access return transform._scale_by_schedule(schedule_wrapper, already_flattened=True) @@ -225,7 +229,7 @@ def adamw( weight_decay: float = 1e-2, *, eps_root: float = 0.0, - mask: Optional[Union[Any, Callable[['base.Params'], Any]]] = None, + mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, moment_requires_grad: bool = False, maximize: bool = False, use_accelerated_op: bool = False, diff --git a/torchopt/_src/base.py b/torchopt/base.py similarity index 90% rename from torchopt/_src/base.py rename to torchopt/base.py index 9e5813d1..98074204 100644 --- a/torchopt/_src/base.py +++ b/torchopt/base.py @@ -29,26 +29,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""The base classes for gradient transformation.""" import itertools from abc import abstractmethod -from typing import Callable, NamedTuple, Optional, Tuple - -from torchopt._src.typing import Numeric, TensorTree +from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Tuple try: - from typing import Protocol + from typing import Protocol # pylint: disable=unused-import except ImportError: - from typing_extensions import Protocol # type: ignore[misc] + from typing_extensions import Protocol # type: ignore[assignment] + +if TYPE_CHECKING: + from torchopt.typing import OptState, Params, Updates -OptState = TensorTree # States are arbitrary nests of `torch.Tensor`. -# Parameters are arbitrary nests of `torch.Tensor`. -Params = TensorTree -Updates = Params # Gradient updates are of the same type as parameters. -Schedule = Callable[[Numeric], Numeric] +__all__ = ['EmptyState', 'GradientTransformation', 'ChainedGradientTransformation', 'identity'] class EmptyState(NamedTuple): @@ -64,8 +62,8 @@ class TransformInitFn(Protocol): # pylint: disable=too-few-public-methods """ @abstractmethod - def __call__(self, params: Params) -> OptState: - """The `init` function. + def __call__(self, params: 'Params') -> 'OptState': + """The ``init`` function. Args: params: @@ -90,13 +88,13 @@ class TransformUpdateFn(Protocol): # pylint: disable=too-few-public-methods @abstractmethod def __call__( self, - updates: Updates, - state: OptState, + updates: 'Updates', + state: 'OptState', *, - params: Optional[Params] = None, + params: Optional['Params'] = None, inplace: bool = True, - ) -> Tuple[Updates, OptState]: - """The `update` function. + ) -> Tuple['Updates', 'OptState']: + """The ``update`` function. Args: updates: A tree of candidate updates. @@ -188,7 +186,7 @@ def update_fn(updates, state, *, params=None, inplace=True): instance.transformations = transformations return instance - def __str__(self): + def __str__(self) -> str: """Returns a string representation of the chained gradient transformation.""" return '{}(\n {}\n)'.format( self.__class__.__name__, ',\n '.join(repr(t) for t in self.transformations) @@ -229,18 +227,18 @@ def __new__(cls): return super().__new__(cls, init=cls.init_fn, update=cls.update_fn) @staticmethod - def init_fn(params: Params) -> OptState: # pylint: disable=unused-argument + def init_fn(params: 'Params') -> 'OptState': # pylint: disable=unused-argument """Returns empty state.""" return EmptyState() @staticmethod def update_fn( - updates: Updates, - state: OptState, + updates: 'Updates', + state: 'OptState', *, - params: Optional[Params] = None, # pylint: disable=unused-argument + params: Optional['Params'] = None, # pylint: disable=unused-argument inplace: bool = True, # pylint: disable=unused-argument - ) -> Tuple[Updates, OptState]: + ) -> Tuple['Updates', 'OptState']: """Returns updates unchanged.""" return updates, state diff --git a/torchopt/_src/clip.py b/torchopt/clip.py similarity index 91% rename from torchopt/_src/clip.py rename to torchopt/clip.py index 31d54797..02fe9003 100644 --- a/torchopt/_src/clip.py +++ b/torchopt/clip.py @@ -15,20 +15,23 @@ # This file is modified from: # https://github.com/pytorch/pytorch/blob/master/torch/nn/utils/clip_grad.py # ============================================================================== +"""Utilities for gradient clipping.""" import torch -from torch._six import inf -from torchopt._src import base -from torchopt._src.utils import pytree +from torchopt import pytree +from torchopt.base import EmptyState, GradientTransformation -ClipState = base.EmptyState +__all__ = ['clip_grad_norm'] + + +ClipState = EmptyState def clip_grad_norm( max_norm: float, norm_type: float = 2.0, error_if_nonfinite: bool = False -) -> base.GradientTransformation: +) -> GradientTransformation: """Clips gradient norm of an iterable of parameters. Args: @@ -50,7 +53,7 @@ def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable= return torch.tensor(0.0) device = available_updates[0].device with torch.no_grad(): - if norm_type == inf: + if norm_type == torch.inf: norms = [p.abs().max().to(device) for p in available_updates] total_norm = norms[0] if len(norms) == 1 else torch.max(torch.stack(norms)) else: @@ -82,4 +85,4 @@ def f(g): new_updates = pytree.tree_map(f, updates) return new_updates, state - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) diff --git a/torchopt/_src/combine.py b/torchopt/combine.py similarity index 88% rename from torchopt/_src/combine.py rename to torchopt/combine.py index 00e90bc1..e3145020 100644 --- a/torchopt/_src/combine.py +++ b/torchopt/combine.py @@ -29,11 +29,15 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Utilities to define a chained transformation.""" -from torchopt._src import base +from torchopt.base import ChainedGradientTransformation, GradientTransformation -def chain(*args: base.GradientTransformation) -> base.GradientTransformation: +__all__ = ['chain'] + + +def chain(*args: GradientTransformation) -> GradientTransformation: """Applies a list of chainable update transformations. Given a sequence of chainable transforms, :func:`chain` returns an :func:`init_fn` that @@ -47,4 +51,4 @@ def chain(*args: base.GradientTransformation) -> base.GradientTransformation: Returns: A single ``(init_fn, update_fn)`` tuple. """ - return base.ChainedGradientTransformation(*args) + return ChainedGradientTransformation(*args) diff --git a/torchopt/_src/hook.py b/torchopt/hook.py similarity index 90% rename from torchopt/_src/hook.py rename to torchopt/hook.py index 305c34ca..76e1d73d 100644 --- a/torchopt/_src/hook.py +++ b/torchopt/hook.py @@ -12,11 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Hook utilities.""" import torch -from torchopt._src.base import EmptyState, GradientTransformation -from torchopt._src.utils import pytree +from torchopt import pytree +from torchopt.base import EmptyState, GradientTransformation + + +__all__ = ['zero_nan_hook', 'register_hook'] def zero_nan_hook(g: torch.Tensor) -> torch.Tensor: diff --git a/torchopt/_src/implicit_diff.py b/torchopt/implicit_diff.py similarity index 94% rename from torchopt/_src/implicit_diff.py rename to torchopt/implicit_diff.py index fcd32063..6a97e3fb 100644 --- a/torchopt/_src/implicit_diff.py +++ b/torchopt/implicit_diff.py @@ -12,30 +12,33 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Implicit Meta-Gradient.""" # pylint: disable=invalid-name import functools import inspect -from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union import functorch import torch from torch.autograd import Function -from torchopt._src import linear_solve -from torchopt._src.utils import pytree +from torchopt import linear_solve, pytree -ARGS = Tuple[Any, ...] -KWARGS = Dict[Any, Any] +__all__ = ['custom_root'] + + +Args = Tuple[Any, ...] +KwArgs = Dict[str, Any] # pylint: disable-next=too-many-arguments,too-many-locals def _root_vjp( optimality_fun: Callable, sol: Any, - args: ARGS, + args: Args, cotangent: Any, res_is_tensor: bool, argnums: Tuple[int, ...], @@ -107,14 +110,14 @@ def __call__(self, *args) -> Any: return tuple(true_result) -def _extract_kwargs(kwarg_keys: Sequence[Any], flat_args: Tuple[Any, ...]) -> Tuple[ARGS, KWARGS]: +def _extract_kwargs(kwarg_keys: Sequence[Any], flat_args: Tuple[Any, ...]) -> Tuple[Args, KwArgs]: nargs = len(flat_args) - len(kwarg_keys) args, kwarg_vals = flat_args[:nargs], flat_args[nargs:] kwargs = dict(zip(kwarg_keys, kwarg_vals)) return args, kwargs -def _signature_bind(signature: inspect.Signature, *args, **kwargs) -> Tuple[ARGS, KWARGS]: +def _signature_bind(signature: inspect.Signature, *args, **kwargs) -> Tuple[Args, KwArgs]: bound = signature.bind(*args, **kwargs) bound.apply_defaults() return bound.args, bound.kwargs @@ -122,7 +125,7 @@ def _signature_bind(signature: inspect.Signature, *args, **kwargs) -> Tuple[ARGS def _signature_bind_and_match( signature: inspect.Signature, *args, **kwargs -) -> Tuple[ARGS, KWARGS, Callable[[ARGS], Tuple[ARGS, KWARGS]]]: +) -> Tuple[Args, KwArgs, Callable[[Args], Tuple[Args, KwArgs]]]: # We want to bind *args and **kwargs based on the provided signature, but also to associate the # resulting positional arguments back. To achieve this, we lift arguments to a triple: # @@ -155,14 +158,15 @@ def map_args_back(out_args): def _split_tensor_and_others( - mixed_tuple: Tuple, + mixed_tuple: Tuple[Any, ...], ) -> Tuple[pytree.PyTreeDef, Tuple[bool, ...], Tuple[torch.Tensor, ...], Tuple[Any, ...]]: - flattened, treedef = pytree.tree_flatten(mixed_tuple) - tensors = [] - non_tensors = [] - is_tensor_mask = [] + flattened: List[Any] + flattened, treedef = pytree.tree_flatten(mixed_tuple) # type: ignore[arg-type] + tensors: List[torch.Tensor] = [] + non_tensors: List[Any] = [] + is_tensor_mask: List[bool] = [] for item in flattened: - if torch.is_tensor(item): + if isinstance(item, torch.Tensor): tensors.append(item.data) is_tensor_mask.append(True) else: @@ -244,11 +248,11 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ ctx.res_is_tensor = False return (*res, aux, False, type(res)) - if torch.is_tensor(res): + if isinstance(res, torch.Tensor): ctx.save_for_backward(res, *args_tensors) else: ctx.save_for_backward(*res, *args_tensors) - ctx.res_is_tensor = torch.is_tensor(res) + ctx.res_is_tensor = isinstance(res, torch.Tensor) return res @staticmethod @@ -315,7 +319,7 @@ def wrapped_solver_fun(*args, **kwargs): args_counter = 0 for idx, arg in enumerate(args): if idx in argnums: - if torch.is_tensor(arg): + if isinstance(arg, torch.Tensor): args_sign.append((args_counter, False)) # start position, is_tuple flatten_args.append(arg) args_counter += 1 diff --git a/torchopt/_src/linalg.py b/torchopt/linalg.py similarity index 96% rename from torchopt/_src/linalg.py rename to torchopt/linalg.py index 6aca422b..32b18503 100644 --- a/torchopt/_src/linalg.py +++ b/torchopt/linalg.py @@ -29,6 +29,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Linear algebra functions.""" # pylint: disable=invalid-name @@ -37,8 +38,11 @@ import torch -from torchopt._src.typing import TensorTree -from torchopt._src.utils import pytree +from torchopt import pytree +from torchopt.typing import TensorTree + + +__all__ = ['cg'] def _inner_product_kernel(x: torch.Tensor, y: torch.Tensor) -> float: @@ -55,7 +59,7 @@ def tree_inner_product(tree_x: TensorTree, tree_y: TensorTree) -> float: """Computes (tree_x.conj() * tree_y).real.sum().""" leaves_x, treedef = pytree.tree_flatten(tree_x) leaves_y = treedef.flatten_up_to(tree_y) - return sum(map(_inner_product_kernel, leaves_x, leaves_y)) + return sum(map(_inner_product_kernel, leaves_x, leaves_y)) # type: ignore[arg-type] def _identity(x: TensorTree) -> TensorTree: @@ -69,7 +73,7 @@ def _normalize_matvec( if callable(f): return f - assert torch.is_tensor(f) + assert isinstance(f, torch.Tensor) if f.ndim != 2 or f.shape[0] != f.shape[1]: raise ValueError(f'linear operator must be a square matrix, but has shape: {f.shape}') return partial(torch.matmul, f) @@ -124,7 +128,7 @@ def body_fun(value): def _shapes(tree: TensorTree) -> List[int]: flattened = pytree.tree_leaves(tree) - return pytree.tree_leaves([tuple(term.shape) for term in flattened]) + return pytree.tree_leaves([tuple(term.shape) for term in flattened]) # type: ignore[arg-type] def _isolve( diff --git a/torchopt/_src/linear_solve.py b/torchopt/linear_solve.py similarity index 94% rename from torchopt/_src/linear_solve.py rename to torchopt/linear_solve.py index 9b7130b3..3c15a962 100644 --- a/torchopt/_src/linear_solve.py +++ b/torchopt/linear_solve.py @@ -29,6 +29,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Linear algebra solvers.""" # pylint: disable=invalid-name @@ -37,9 +38,11 @@ import functorch -from torchopt._src import linalg -from torchopt._src.typing import TensorTree -from torchopt._src.utils import pytree +from torchopt import linalg, pytree +from torchopt.typing import TensorTree + + +__all__ = ['solve_cg', 'solve_normal_cg'] def tree_add(tree_x: TensorTree, tree_y: TensorTree, alpha: float = 1.0) -> TensorTree: @@ -57,12 +60,12 @@ def ridge_matvec(v: TensorTree) -> TensorTree: def solve_cg( - matvec: Callable[[TensorTree], TensorTree], - b: TensorTree, + matvec: Callable[['TensorTree'], 'TensorTree'], + b: 'TensorTree', ridge: Optional[float] = None, - init: Optional[TensorTree] = None, + init: Optional['TensorTree'] = None, **kwargs, -) -> TensorTree: +) -> 'TensorTree': """Solves ``A x = b`` using conjugate gradient. It assumes that ``A`` is a Hermitian, positive definite matrix. diff --git a/torchopt/_src/optimizer/__init__.py b/torchopt/optim/__init__.py similarity index 66% rename from torchopt/_src/optimizer/__init__.py rename to torchopt/optim/__init__.py index 80fdd25e..b75da23c 100644 --- a/torchopt/_src/optimizer/__init__.py +++ b/torchopt/optim/__init__.py @@ -12,11 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""object oriented optimizer implementations.""" -from torchopt._src.optimizer import meta -from torchopt._src.optimizer.adam import Adam -from torchopt._src.optimizer.adamw import AdamW -from torchopt._src.optimizer.base import Optimizer -from torchopt._src.optimizer.func import FuncOptimizer -from torchopt._src.optimizer.rmsprop import RMSProp, RMSprop -from torchopt._src.optimizer.sgd import SGD +from torchopt.optim import meta +from torchopt.optim.adam import Adam +from torchopt.optim.adamw import AdamW +from torchopt.optim.base import Optimizer +from torchopt.optim.func import FuncOptimizer +from torchopt.optim.rmsprop import RMSProp, RMSprop +from torchopt.optim.sgd import SGD diff --git a/torchopt/_src/optimizer/adam.py b/torchopt/optim/adam.py similarity index 94% rename from torchopt/_src/optimizer/adam.py rename to torchopt/optim/adam.py index 6776408e..4ac12db8 100644 --- a/torchopt/_src/optimizer/adam.py +++ b/torchopt/optim/adam.py @@ -12,14 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Adam optimizer.""" from typing import Iterable, Tuple import torch -from torchopt._src.alias import adam -from torchopt._src.optimizer.base import Optimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import adam +from torchopt.optim.base import Optimizer +from torchopt.typing import ScalarOrSchedule + + +__all__ = ['Adam'] class Adam(Optimizer): @@ -42,7 +46,7 @@ def __init__( eps_root: float = 0.0, maximize: bool = False, use_accelerated_op: bool = False, - ): + ) -> None: r"""The :meth:`init` function. Args: diff --git a/torchopt/_src/optimizer/adamw.py b/torchopt/optim/adamw.py similarity index 93% rename from torchopt/_src/optimizer/adamw.py rename to torchopt/optim/adamw.py index 886cd77a..3b45bbe1 100644 --- a/torchopt/_src/optimizer/adamw.py +++ b/torchopt/optim/adamw.py @@ -12,15 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""AdamW optimizer.""" from typing import Any, Callable, Iterable, Optional, Tuple, Union import torch -from torchopt._src import base # pylint: disable=unused-import -from torchopt._src.alias import adamw -from torchopt._src.optimizer.base import Optimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import adamw +from torchopt.optim.base import Optimizer +from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import + + +__all__ = ['AdamW'] class AdamW(Optimizer): @@ -41,10 +44,10 @@ def __init__( weight_decay: float = 1e-2, *, eps_root: float = 0.0, - mask: Optional[Union[Any, Callable[['base.Params'], Any]]] = None, + mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, maximize: bool = False, use_accelerated_op: bool = False, - ): + ) -> None: r"""The :meth:`init` function. Args: diff --git a/torchopt/_src/optimizer/base.py b/torchopt/optim/base.py similarity index 69% rename from torchopt/_src/optimizer/base.py rename to torchopt/optim/base.py index 8a00e937..afbab30e 100644 --- a/torchopt/_src/optimizer/base.py +++ b/torchopt/optim/base.py @@ -12,20 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""The base class for optimizers.""" -from typing import Iterable +from typing import Callable, Iterable, List, Optional, Sequence, Tuple, cast import torch -from torchopt._src.base import GradientTransformation -from torchopt._src.update import apply_updates -from torchopt._src.utils import pytree +from torchopt import pytree +from torchopt.typing import GradientTransformation, OptState, Params +from torchopt.update import apply_updates + + +__all__ = ['Optimizer'] class Optimizer: """A base class for classic optimizers that similar to :class:`torch.optim.Optimizer`.""" - def __init__(self, params: Iterable[torch.Tensor], impl: GradientTransformation): + def __init__(self, params: Iterable[torch.Tensor], impl: GradientTransformation) -> None: r"""The :meth:`init` function. Args: @@ -40,16 +44,16 @@ def __init__(self, params: Iterable[torch.Tensor], impl: GradientTransformation) if not isinstance(impl, GradientTransformation): raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') - self.impl = impl - self.param_groups = [] # type: ignore - self.param_tree_groups = [] # type: ignore - self.state_groups = [] # type: ignore + self.impl: GradientTransformation = impl + self.param_groups: List[Tuple[torch.Tensor]] = [] + self.param_treedefs: List[pytree.PyTreeDef] = [] + self.state_groups: List[OptState] = [] if not isinstance(params, list): params = list(params) self.add_param_group(params) - def zero_grad(self, set_to_none: bool = False): + def zero_grad(self, set_to_none: bool = False) -> None: r"""Sets the gradients of all optimized :class:`torch.Tensor`\s to zero. The behavior is similar to :meth:`torch.optim.Optimizer.zero_grad`. @@ -74,22 +78,22 @@ def f(p): p.grad.requires_grad_(False) p.grad.zero_() - pytree.tree_map(f, group) + pytree.tree_map(f, cast(Params, group)) - def state_dict(self): + def state_dict(self) -> Tuple['OptState', ...]: """Returns the state of the optimizer.""" - return self.state_groups + return tuple(self.state_groups) - def load_state_dict(self, state_dict): + def load_state_dict(self, state_dict: Sequence['OptState']) -> None: """Loads the optimizer state. Args: - state_dict (dict): Optimizer state. Should be an object returned from a call to + state_dict: Optimizer state. Should be an object returned from a call to :meth:`state_dict`. """ - self.state_groups = state_dict + self.state_groups[:] = list(state_dict) - def step(self, closure=None): + def step(self, closure: Optional[Callable[[], torch.Tensor]] = None) -> Optional[torch.Tensor]: """Performs a single optimization step. The behavior is similar to :meth:`torch.optim.Optimizer.step`. @@ -106,17 +110,17 @@ def f(p): return p.grad for i, (params, state) in enumerate(zip(self.param_groups, self.state_groups)): - grads = pytree.tree_map(f, params) + grads = pytree.tree_map(f, cast(Params, params)) updates, new_state = self.impl.update(grads, state, params=params, inplace=True) self.param_groups[i] = apply_updates(params, updates, inplace=True) self.state_groups[i] = new_state return loss - def add_param_group(self, params): + def add_param_group(self, params: 'Params') -> None: """Add a param group to the optimizer's :attr:`param_groups`.""" - params, params_tree = pytree.tree_flatten(params) - params = tuple(params) - self.param_groups.append(params) - self.param_tree_groups.append(params_tree) - self.state_groups.append(self.impl.init(params)) + flattened_params, params_treedef = pytree.tree_flatten(params) + flattened_params: Tuple[torch.Tensor] = tuple(flattened_params) # type: ignore[assignment] + self.param_groups.append(flattened_params) + self.param_treedefs.append(params_treedef) + self.state_groups.append(self.impl.init(flattened_params)) diff --git a/torchopt/_src/__init__.py b/torchopt/optim/func/__init__.py similarity index 88% rename from torchopt/_src/__init__.py rename to torchopt/optim/func/__init__.py index 75b3cf8d..f14fc6ae 100644 --- a/torchopt/_src/__init__.py +++ b/torchopt/optim/func/__init__.py @@ -12,5 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Functional optimizer wrappers.""" -from torchopt._src.accelerated_op import accelerated_op_available +from torchopt.optim.func.base import FuncOptimizer diff --git a/torchopt/_src/optimizer/func/base.py b/torchopt/optim/func/base.py similarity index 86% rename from torchopt/_src/optimizer/func/base.py rename to torchopt/optim/func/base.py index f4ec35ac..f1d0b684 100644 --- a/torchopt/_src/optimizer/func/base.py +++ b/torchopt/optim/func/base.py @@ -12,17 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Functional optimizer wrappers.""" from typing import Optional import torch -from torchopt._src.base import GradientTransformation -from torchopt._src.typing import TensorTree -from torchopt._src.update import apply_updates +from torchopt.base import GradientTransformation +from torchopt.typing import OptState, Params # pylint: disable=unused-import +from torchopt.update import apply_updates + + +__all__ = ['FuncOptimizer'] -# mypy: ignore-errors class FuncOptimizer: # pylint: disable=too-few-public-methods """A wrapper class to hold the functional optimizer. @@ -51,13 +54,16 @@ def __init__(self, impl: GradientTransformation, *, inplace: bool = False) -> No if not isinstance(impl, GradientTransformation): raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') - self.impl = impl - self.optim_state = self.__NOT_INITIALIZED - self.inplace = bool(inplace) + self.impl: GradientTransformation = impl + self.optim_state: Optional[OptState] = self.__NOT_INITIALIZED + self.inplace: bool = bool(inplace) def step( - self, loss: torch.Tensor, params: TensorTree, inplace: Optional[bool] = None - ) -> TensorTree: + self, + loss: torch.Tensor, + params: 'Params', + inplace: Optional[bool] = None, + ) -> 'Params': r"""Compute the gradients of loss to the network parameters and update network parameters. Graph of the derivative will be constructed, allowing to compute higher order derivative diff --git a/torchopt/_src/optimizer/meta/__init__.py b/torchopt/optim/meta/__init__.py similarity index 69% rename from torchopt/_src/optimizer/meta/__init__.py rename to torchopt/optim/meta/__init__.py index ec227474..ba486d6d 100644 --- a/torchopt/_src/optimizer/meta/__init__.py +++ b/torchopt/optim/meta/__init__.py @@ -12,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Differentiable Meta-Optimizers.""" -from torchopt._src.optimizer.meta.adam import MetaAdam -from torchopt._src.optimizer.meta.adamw import MetaAdamW -from torchopt._src.optimizer.meta.base import MetaOptimizer -from torchopt._src.optimizer.meta.rmsprop import MetaRMSProp, MetaRMSprop -from torchopt._src.optimizer.meta.sgd import MetaSGD +from torchopt.optim.meta.adam import MetaAdam +from torchopt.optim.meta.adamw import MetaAdamW +from torchopt.optim.meta.base import MetaOptimizer +from torchopt.optim.meta.rmsprop import MetaRMSProp, MetaRMSprop +from torchopt.optim.meta.sgd import MetaSGD diff --git a/torchopt/_src/optimizer/meta/adam.py b/torchopt/optim/meta/adam.py similarity index 94% rename from torchopt/_src/optimizer/meta/adam.py rename to torchopt/optim/meta/adam.py index 6b76f959..bb578f23 100644 --- a/torchopt/_src/optimizer/meta/adam.py +++ b/torchopt/optim/meta/adam.py @@ -12,14 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Differentiable Adam optimizer.""" from typing import Tuple import torch.nn as nn -from torchopt._src.alias import adam -from torchopt._src.optimizer.meta.base import MetaOptimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import adam +from torchopt.optim.meta.base import MetaOptimizer +from torchopt.typing import ScalarOrSchedule + + +__all__ = ['MetaAdam'] class MetaAdam(MetaOptimizer): @@ -43,7 +47,7 @@ def __init__( moment_requires_grad: bool = True, maximize: bool = False, use_accelerated_op: bool = False, - ): + ) -> None: """The :meth:`init` function. Args: diff --git a/torchopt/_src/optimizer/meta/adamw.py b/torchopt/optim/meta/adamw.py similarity index 92% rename from torchopt/_src/optimizer/meta/adamw.py rename to torchopt/optim/meta/adamw.py index c38f3c5c..0e40dcd4 100644 --- a/torchopt/_src/optimizer/meta/adamw.py +++ b/torchopt/optim/meta/adamw.py @@ -12,15 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Differentiable AdamW optimizer.""" from typing import Any, Callable, Optional, Tuple, Union import torch.nn as nn -from torchopt._src import base # pylint: disable=unused-import -from torchopt._src.alias import adamw -from torchopt._src.optimizer.meta.base import MetaOptimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import adamw +from torchopt.optim.meta.base import MetaOptimizer +from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import + + +__all__ = ['MetaAdamW'] class MetaAdamW(MetaOptimizer): @@ -41,11 +44,11 @@ def __init__( weight_decay: float = 1e-2, *, eps_root: float = 0.0, - mask: Optional[Union[Any, Callable[['base.Params'], Any]]] = None, + mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, moment_requires_grad: bool = False, maximize: bool = False, use_accelerated_op: bool = False, - ): + ) -> None: """The :meth:`init` function. Args: diff --git a/torchopt/_src/optimizer/meta/base.py b/torchopt/optim/meta/base.py similarity index 70% rename from torchopt/_src/optimizer/meta/base.py rename to torchopt/optim/meta/base.py index 7e845fb0..cec74f86 100644 --- a/torchopt/_src/optimizer/meta/base.py +++ b/torchopt/optim/meta/base.py @@ -12,13 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""The base class for differentiable meta-optimizers.""" + +from typing import Dict, List, Optional, Sequence, Tuple, cast import torch import torch.nn as nn -from torchopt._src.base import GradientTransformation -from torchopt._src.update import apply_updates -from torchopt._src.utils import pytree +from torchopt import pytree +from torchopt.typing import GradientTransformation, OptState +from torchopt.update import apply_updates + + +__all__ = ['MetaOptimizer'] class MetaOptimizer: @@ -40,9 +46,9 @@ def __init__(self, net: nn.Module, impl: GradientTransformation): if not isinstance(impl, GradientTransformation): raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') - self.impl = impl - self.param_containers_groups = [] # type: ignore - self.state_groups = [] # type: ignore + self.impl: GradientTransformation = impl + self.param_containers_groups: List[Tuple[Dict[str, Optional[torch.Tensor]], ...]] = [] + self.state_groups: List[OptState] = [] self.add_param_group(net) @@ -61,10 +67,17 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals for i, (param_container, new_state) in enumerate( zip(self.param_containers_groups, self.state_groups) ): - flattened_params_or_none, container_treedef = pytree.tree_flatten(param_container) - flattened_params = tuple(filter(torch.is_tensor, flattened_params_or_none)) + flattened_params_or_none: List[Optional[torch.Tensor]] + flattened_params_or_none, container_treedef = pytree.tree_flatten(param_container) # type: ignore[arg-type] + flattened_params = cast( + Tuple[torch.Tensor, ...], + tuple(filter(torch.is_tensor, flattened_params_or_none)), + ) grads = torch.autograd.grad( - loss, flattened_params, create_graph=True, allow_unused=True + loss, + flattened_params, + create_graph=True, + allow_unused=True, ) updates, new_state = self.impl.update( grads, @@ -81,22 +94,31 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals else old_param_or_none for old_param_or_none in flattened_params_or_none ] - new_params = pytree.tree_unflatten(container_treedef, flattened_new_params_or_none) + new_params = cast( + Tuple[Dict[str, Optional[torch.Tensor]], ...], + pytree.tree_unflatten(container_treedef, flattened_new_params_or_none), + ) for container, new_param in zip(param_container, new_params): container.update(new_param) - def add_param_group(self, net): + def add_param_group(self, net: nn.Module) -> None: """Add a param group to the optimizer's :attr:`state_groups`.""" - # pylint: disable-next=import-outside-toplevel,cyclic-import - from torchopt._src.utils import _extract_container + # pylint: disable-next=import-outside-toplevel + from torchopt.utils import _extract_container net_container = _extract_container(net, with_buffer=False) - flattened_params = tuple(filter(torch.is_tensor, pytree.tree_leaves(net_container))) + flattened_params = tuple( + filter( + torch.is_tensor, # type: ignore[arg-type] + # pylint: disable-next=line-too-long + cast(List[Optional[torch.Tensor]], pytree.tree_leaves(net_container)), # type: ignore[arg-type] + ) + ) optimizer_state = self.impl.init(flattened_params) self.param_containers_groups.append(net_container) self.state_groups.append(optimizer_state) - def state_dict(self): + def state_dict(self) -> Tuple['OptState', ...]: """Extract the references of the optimizer states. Note that the states are references, so any in-place operations will change the states @@ -104,6 +126,6 @@ def state_dict(self): """ return tuple(self.state_groups) - def load_state_dict(self, state_dict): + def load_state_dict(self, state_dict: Sequence['OptState']) -> None: """Load the references of the optimizer states.""" self.state_groups[:] = list(state_dict) diff --git a/torchopt/_src/optimizer/meta/rmsprop.py b/torchopt/optim/meta/rmsprop.py similarity index 93% rename from torchopt/_src/optimizer/meta/rmsprop.py rename to torchopt/optim/meta/rmsprop.py index 20183236..533d3219 100644 --- a/torchopt/_src/optimizer/meta/rmsprop.py +++ b/torchopt/optim/meta/rmsprop.py @@ -12,12 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Differentiable RMSProp optimizer.""" import torch.nn as nn -from torchopt._src.alias import rmsprop -from torchopt._src.optimizer.meta.base import MetaOptimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import rmsprop +from torchopt.optim.meta.base import MetaOptimizer +from torchopt.typing import ScalarOrSchedule + + +__all__ = ['MetaRMSProp', 'MetaRMSprop'] class MetaRMSProp(MetaOptimizer): @@ -42,7 +46,7 @@ def __init__( initial_scale: float = 0.0, nesterov: bool = False, maximize: bool = False, - ): + ) -> None: """The :meth:`init` function. Args: diff --git a/torchopt/_src/optimizer/meta/sgd.py b/torchopt/optim/meta/sgd.py similarity index 92% rename from torchopt/_src/optimizer/meta/sgd.py rename to torchopt/optim/meta/sgd.py index b8ae5d24..44810725 100644 --- a/torchopt/_src/optimizer/meta/sgd.py +++ b/torchopt/optim/meta/sgd.py @@ -12,12 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Differentiable SGD optimizer.""" import torch.nn as nn -from torchopt._src.alias import sgd -from torchopt._src.optimizer.meta.base import MetaOptimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import sgd +from torchopt.optim.meta.base import MetaOptimizer +from torchopt.typing import ScalarOrSchedule + + +__all__ = ['MetaSGD'] class MetaSGD(MetaOptimizer): @@ -39,7 +43,7 @@ def __init__( nesterov: bool = False, moment_requires_grad: bool = True, maximize: bool = False, - ): + ) -> None: """The :meth:`init` function. Args: diff --git a/torchopt/_src/optimizer/rmsprop.py b/torchopt/optim/rmsprop.py similarity index 94% rename from torchopt/_src/optimizer/rmsprop.py rename to torchopt/optim/rmsprop.py index 3b8634f3..cc770834 100644 --- a/torchopt/_src/optimizer/rmsprop.py +++ b/torchopt/optim/rmsprop.py @@ -12,14 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""RMSProp optimizer.""" from typing import Iterable import torch -from torchopt._src.alias import rmsprop -from torchopt._src.optimizer.base import Optimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import rmsprop +from torchopt.optim.base import Optimizer +from torchopt.typing import ScalarOrSchedule + + +__all__ = ['RMSProp', 'RMSprop'] class RMSProp(Optimizer): @@ -44,7 +48,7 @@ def __init__( initial_scale: float = 0.0, nesterov: bool = False, maximize: bool = False, - ): + ) -> None: r"""The `init` function. Args: diff --git a/torchopt/_src/optimizer/sgd.py b/torchopt/optim/sgd.py similarity index 93% rename from torchopt/_src/optimizer/sgd.py rename to torchopt/optim/sgd.py index a7f415f6..9161a49b 100644 --- a/torchopt/_src/optimizer/sgd.py +++ b/torchopt/optim/sgd.py @@ -12,14 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""SGD optimizer.""" from typing import Iterable import torch -from torchopt._src.alias import sgd -from torchopt._src.optimizer.base import Optimizer -from torchopt._src.typing import ScalarOrSchedule +from torchopt.alias import sgd +from torchopt.optim.base import Optimizer +from torchopt.typing import ScalarOrSchedule + + +__all__ = ['SGD'] class SGD(Optimizer): @@ -40,7 +44,7 @@ def __init__( dampening: float = 0.0, nesterov: bool = False, maximize: bool = False, - ): + ) -> None: r"""The :meth:`init` function. Args: diff --git a/torchopt/py.typed b/torchopt/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/torchopt/_src/optimizer/func/__init__.py b/torchopt/pytree.py similarity index 74% rename from torchopt/_src/optimizer/func/__init__.py rename to torchopt/pytree.py index 3510a59b..1d0fabea 100644 --- a/torchopt/_src/optimizer/func/__init__.py +++ b/torchopt/pytree.py @@ -12,5 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""The PyTree utilities.""" -from torchopt._src.optimizer.func.base import FuncOptimizer +import optree +import optree.typing as typing # pylint: disable=unused-import +from optree import * # pylint: disable=wildcard-import,unused-wildcard-import + + +__all__ = optree.__all__.copy() + +del optree diff --git a/torchopt/_src/schedule.py b/torchopt/schedule.py similarity index 94% rename from torchopt/_src/schedule.py rename to torchopt/schedule.py index 57aabe44..4effb95b 100644 --- a/torchopt/_src/schedule.py +++ b/torchopt/schedule.py @@ -29,14 +29,17 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Learning rate schedules.""" import logging import numpy as np import torch -from torchopt._src import base -from torchopt._src.typing import Numeric, Scalar +from torchopt.typing import Numeric, Scalar, Schedule + + +__all__ = ['polynomial_schedule', 'linear_schedule'] def polynomial_schedule( @@ -45,7 +48,7 @@ def polynomial_schedule( power: Scalar, transition_steps: int, transition_begin: int = 0, -) -> base.Schedule: +) -> Schedule: """Constructs a schedule with polynomial transition from init to end value. Args: @@ -81,7 +84,7 @@ def polynomial_schedule( transition_begin = 0 def schedule(count: Numeric) -> Numeric: - clip = torch.clamp if torch.is_tensor(count) else np.clip + clip = torch.clamp if isinstance(count, torch.Tensor) else np.clip count = clip(count - transition_begin, 0, transition_steps) # type: ignore[operator] frac = 1.0 - count / transition_steps return (init_value - end_value) * (frac**power) + end_value @@ -95,7 +98,7 @@ def linear_schedule( end_value: Scalar, transition_steps: int, transition_begin: int = 0, -) -> base.Schedule: +) -> Schedule: """Alias polynomial schedule to linear schedule for convenience.""" return polynomial_schedule( init_value=init_value, diff --git a/torchopt/_src/transform.py b/torchopt/transform.py similarity index 89% rename from torchopt/_src/transform.py rename to torchopt/transform.py index 08e0da9e..c417cc30 100644 --- a/torchopt/_src/transform.py +++ b/torchopt/transform.py @@ -29,21 +29,22 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Preset transformations.""" # pylint: disable=invalid-name -from typing import Any, Callable, List, NamedTuple, Optional, Sequence, Union +from typing import Any, Callable, List, NamedTuple, Optional, Sequence, Tuple, Union, cast import torch -from torchopt._src import base -from torchopt._src.typing import Schedule -from torchopt._src.utils import pytree +from torchopt import pytree +from torchopt.base import EmptyState, GradientTransformation, identity +from torchopt.typing import Params, PyTree, Schedule, TensorTree, Updates -ScaleState = base.EmptyState +ScaleState = EmptyState INT32_MAX = torch.iinfo(torch.int32).max -TRIPLE_PYTREEDEF = pytree.tree_structure((0, 1, 2)) +TRIPLE_PYTREEDEF = pytree.tree_structure(cast(PyTree[int], (0, 1, 2))) def map_flattened(func: Callable, *args: Any) -> List[Any]: @@ -51,7 +52,7 @@ def map_flattened(func: Callable, *args: Any) -> List[Any]: return list(map(func, *args)) -def with_flattened_tree(inner: base.GradientTransformation) -> base.GradientTransformation: +def with_flattened_tree(inner: GradientTransformation) -> GradientTransformation: # pylint: disable-next=line-too-long """Wraps around the inner transformation that manipulates the flattened tree structure (:class:``list``).""" @@ -70,10 +71,10 @@ def update_fn(updates, state, *, params=None, inplace=True): return updates, state - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) -def inc_count(updates: base.Updates, count: Sequence[torch.Tensor]) -> Sequence[torch.Tensor]: +def inc_count(updates: Updates, count: TensorTree) -> TensorTree: """Increments int counter by one. Returns: @@ -83,8 +84,8 @@ def inc_count(updates: base.Updates, count: Sequence[torch.Tensor]) -> Sequence[ def _inc_count( - updates: base.Updates, count: Sequence[torch.Tensor], *, already_flattened: bool = False -) -> Sequence[torch.Tensor]: + updates: Updates, count: TensorTree, *, already_flattened: bool = False +) -> TensorTree: def f(c, g): return c + (c != INT32_MAX).to(torch.int32) if g is not None else c @@ -93,7 +94,7 @@ def f(c, g): return pytree.tree_map(f, count, updates) -def scale(step_size: float) -> base.GradientTransformation: +def scale(step_size: float) -> GradientTransformation: """Scale updates by some fixed scalar ``step_size``. Args: @@ -105,11 +106,11 @@ def scale(step_size: float) -> base.GradientTransformation: return _scale(step_size=step_size, already_flattened=False) -def _scale(step_size: float, *, already_flattened: bool = False) -> base.GradientTransformation: +def _scale(step_size: float, *, already_flattened: bool = False) -> GradientTransformation: if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def init_fn(params): # pylint: disable=unused-argument return ScaleState() @@ -128,7 +129,7 @@ def f(g): updates = tree_map(f, updates) return updates, state - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) class ScaleByScheduleState(NamedTuple): @@ -137,7 +138,7 @@ class ScaleByScheduleState(NamedTuple): count: Sequence[torch.Tensor] # type: ignore -def scale_by_schedule(step_size_fn: Schedule) -> base.GradientTransformation: +def scale_by_schedule(step_size_fn: Schedule) -> GradientTransformation: """Scale updates using a custom schedule for the ``step_size``. Args: @@ -153,11 +154,11 @@ def scale_by_schedule(step_size_fn: Schedule) -> base.GradientTransformation: def _scale_by_schedule( step_size_fn: Schedule, *, already_flattened: bool = False -) -> base.GradientTransformation: +) -> GradientTransformation: if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def init_fn(params): zero = tree_map( # count init @@ -186,7 +187,7 @@ def f(g, c): ), ) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) def _update_moment(updates, moments, decay, *, order, inplace=True, already_flattened=False): @@ -225,8 +226,8 @@ def f(g, t): class ScaleByAdamState(NamedTuple): """State for the Adam algorithm.""" - mu: base.Updates - nu: base.Updates + mu: Updates + nu: Updates count: Sequence[torch.Tensor] # type: ignore @@ -247,7 +248,7 @@ def scale_by_adam( eps: float = 1e-8, eps_root: float = 0.0, moment_requires_grad: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: """Rescale updates according to the Adam algorithm. References: @@ -287,7 +288,7 @@ def _scale_by_adam( moment_requires_grad: bool = False, *, already_flattened: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: # pylint: disable=unneeded-not if not 0.0 <= eps: raise ValueError(f'Invalid epsilon value: {eps}') @@ -300,7 +301,7 @@ def _scale_by_adam( if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def init_fn(params): zero = tree_map( # count init @@ -338,7 +339,7 @@ def f(g, m, v): updates = tree_map(f, updates, mu_hat, nu_hat) return updates, ScaleByAdamState(mu=mu, nu=nu, count=count_inc) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) def scale_by_accelerated_adam( @@ -347,7 +348,7 @@ def scale_by_accelerated_adam( eps: float = 1e-8, eps_root: float = 0.0, moment_requires_grad: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: """Rescale updates according to the Adam algorithm. This function is accelerated by using some fused accelerated operators. @@ -389,7 +390,7 @@ def _scale_by_accelerated_adam( moment_requires_grad: bool = False, *, already_flattened: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: # pylint: disable=unneeded-not if not 0.0 <= eps: raise ValueError(f'Invalid epsilon value: {eps}') @@ -399,7 +400,7 @@ def _scale_by_accelerated_adam( raise ValueError(f'Invalid beta parameter at index 1: {b2}') # pylint: enable=unneeded-not - from torchopt._src.accelerated_op import AdamOp # pylint: disable=import-outside-toplevel + from torchopt.accelerated_op import AdamOp # pylint: disable=import-outside-toplevel if already_flattened: tree_map = map_flattened @@ -415,7 +416,7 @@ def update_fn(updates, state, *, params=None, inplace=True): return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] # pylint: disable-next=unused-argument def update_fn(updates, state, *, params=None, inplace=True): @@ -426,7 +427,10 @@ def update_fn(updates, state, *, params=None, inplace=True): op = AdamOp(b1=b1, b2=b2, eps=eps, eps_root=eps_root, inplace=inplace) out = pytree.tree_map(op, state.mu, state.nu, updates, count_inc) - new_mu, new_nu, new_updates = pytree.tree_transpose(treedef, TRIPLE_PYTREEDEF, out) + new_mu, new_nu, new_updates = cast( + Tuple[TensorTree, TensorTree, TensorTree], + pytree.tree_transpose(treedef, TRIPLE_PYTREEDEF, out), + ) return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) def init_fn(params): @@ -441,13 +445,13 @@ def init_fn(params): ) return ScaleByAdamState(mu=mu, nu=nu, count=zero) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) class TraceState(NamedTuple): """Holds an aggregation of past updates.""" - trace: base.Params + trace: Params def trace( @@ -455,7 +459,7 @@ def trace( dampening: float = 0.0, nesterov: bool = False, moment_requires_grad: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: """Compute a trace of past updates. Note: `trace` and `ema` have very similar but distinct updates; @@ -491,7 +495,7 @@ def _trace( moment_requires_grad: bool = False, *, already_flattened: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: # pylint: disable=unneeded-not if not 0.0 <= momentum: raise ValueError(f'Invalid momentum value: {momentum}') @@ -500,12 +504,12 @@ def _trace( # pylint: enable=unneeded-not if momentum == 0.0: - return base.identity() + return identity() if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def init_fn(params): return TraceState( @@ -570,18 +574,18 @@ def f(g, t): first_call = False return updates, TraceState(trace=new_trace) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) class ScaleByRmsState(NamedTuple): """State for exponential root mean-squared (RMS)-normalized updates.""" - nu: base.Updates + nu: Updates def scale_by_rms( alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 -) -> base.GradientTransformation: +) -> GradientTransformation: """Rescale updates by the root of the exp. moving avg of the square. References: @@ -612,7 +616,7 @@ def _scale_by_rms( initial_scale: float = 0.0, *, already_flattened: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: # pylint: disable=unneeded-not if not 0.0 <= alpha: raise ValueError(f'Invalid alpha value: {alpha}') @@ -623,7 +627,7 @@ def _scale_by_rms( if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def init_fn(params): nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment @@ -647,19 +651,19 @@ def f(g, n): updates = tree_map(f, updates, nu) return updates, ScaleByRmsState(nu=nu) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) class ScaleByRStdDevState(NamedTuple): """State for centered exponential moving average of squares of updates.""" - mu: base.Updates - nu: base.Updates + mu: Updates + nu: Updates def scale_by_stddev( alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 -) -> base.GradientTransformation: +) -> GradientTransformation: """Rescale updates by the root of the centered exp. moving average of squares. References: @@ -690,7 +694,7 @@ def _scale_by_stddev( initial_scale: float = 0.0, *, already_flattened: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: # pylint: disable=unneeded-not if not 0.0 <= alpha: raise ValueError(f'Invalid alpha value: {alpha}') @@ -701,7 +705,7 @@ def _scale_by_stddev( if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def init_fn(params): mu = tree_map(torch.zeros_like, params) # first moment @@ -729,7 +733,7 @@ def f(g, m, n): updates = tree_map(f, updates, mu, nu) return updates, ScaleByRStdDevState(mu=mu, nu=nu) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) class MaskedState(NamedTuple): @@ -748,9 +752,9 @@ class MaskedNode(NamedTuple): def masked( - inner: base.GradientTransformation, - mask: Union[Any, Callable[[base.Params], Any]], -) -> base.GradientTransformation: + inner: GradientTransformation, + mask: Union[Any, Callable[[Params], Any]], +) -> GradientTransformation: """Mask updates so only some are transformed, the rest are passed through. For example, it is common to skip weight decay for BatchNorm scale and all @@ -784,16 +788,16 @@ def masked( def _masked( - inner: base.GradientTransformation, - mask: Union[Any, Callable[[base.Params], Any]], + inner: GradientTransformation, + mask: Union[Any, Callable[[Params], Any]], *, already_flattened: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def tree_mask(params, mask_tree): return tree_map(lambda p, m: p if m else MaskedNode(), params, mask_tree) @@ -817,17 +821,16 @@ def update_fn(updates, state, params=None, inplace=True): # pylint: disable=unu ) return new_updates, MaskedState(inner_state=new_inner_state) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) -AddDecayedWeightsState = base.EmptyState +AddDecayedWeightsState = EmptyState -# mypy: ignore-errors def add_decayed_weights( weight_decay: float = 0.0, - mask: Optional[Union[Any, Callable[[base.Params], Any]]] = None, -) -> base.GradientTransformation: + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, +) -> GradientTransformation: """Add parameter scaled by `weight_decay`. Args: @@ -847,23 +850,22 @@ def add_decayed_weights( ) -# mypy: ignore-errors def _add_decayed_weights( weight_decay: float = 0.0, - mask: Optional[Union[Any, Callable[[base.Params], Any]]] = None, + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, *, already_flattened: bool = False, -) -> base.GradientTransformation: +) -> GradientTransformation: if not 0.0 <= weight_decay: # pylint: disable=unneeded-not raise ValueError(f'Invalid weight_decay value: {weight_decay}') if weight_decay == 0.0 and mask is None: - return base.identity() + return identity() if already_flattened: tree_map = map_flattened else: - tree_map = pytree.tree_map + tree_map = pytree.tree_map # type: ignore[assignment] def init_fn(params): # pylint: disable=unused-argument return AddDecayedWeightsState() @@ -895,8 +897,8 @@ def f(g, p): # E.g. it is common to skip weight decay on bias units and batch stats. if mask is not None: return _masked( - inner=base.GradientTransformation(init_fn, update_fn), + inner=GradientTransformation(init_fn, update_fn), mask=mask, already_flattened=already_flattened, ) - return base.GradientTransformation(init_fn, update_fn) + return GradientTransformation(init_fn, update_fn) diff --git a/torchopt/typing.py b/torchopt/typing.py new file mode 100644 index 00000000..3680ba2a --- /dev/null +++ b/torchopt/typing.py @@ -0,0 +1,62 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Typing utilities.""" + +from typing import Callable, Optional, TypeVar, Union + +from optree.typing import PyTree +from torch import Tensor + +from torchopt.base import ChainedGradientTransformation, EmptyState, GradientTransformation + + +try: + from typing import TypeAlias # type: ignore[attr-defined] +except ImportError: + from typing_extensions import TypeAlias + + +__all__ = [ + 'GradientTransformation', + 'ChainedGradientTransformation', + 'EmptyState', + 'Params', + 'Updates', + 'OptState', + 'Scalar', + 'Numeric', + 'Schedule', + 'ScalarOrSchedule', + 'PyTree', + 'Tensor', + 'TensorTree', + 'OptionalTensorTree', +] + +T = TypeVar('T') + +Scalar: TypeAlias = Union[float, int, bool] +Numeric: TypeAlias = Union[Tensor, Scalar] + +Schedule: TypeAlias = Callable[[Numeric], Numeric] +ScalarOrSchedule: TypeAlias = Union[float, Schedule] + +TensorTree: TypeAlias = PyTree[Tensor] +OptionalTensorTree: TypeAlias = PyTree[Optional[Tensor]] + +# Parameters are arbitrary nests of `torch.Tensor`. +Params: TypeAlias = TensorTree +Updates: TypeAlias = Params # Gradient updates are of the same type as parameters. +OptState: TypeAlias = TensorTree # States are arbitrary nests of `torch.Tensor`. diff --git a/torchopt/_src/update.py b/torchopt/update.py similarity index 90% rename from torchopt/_src/update.py rename to torchopt/update.py index 753292d7..bdcdc301 100644 --- a/torchopt/_src/update.py +++ b/torchopt/update.py @@ -29,14 +29,16 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""Helper functions for applying updates.""" -from torchopt._src import base # pylint: disable=unused-import -from torchopt._src.utils import pytree +from torchopt import pytree +from torchopt.typing import Params, Updates # pylint: disable=unused-import -def apply_updates( - params: 'base.Params', updates: 'base.Updates', *, inplace: bool = True -) -> 'base.Params': +__all__ = ['apply_updates'] + + +def apply_updates(params: 'Params', updates: 'Updates', *, inplace: bool = True) -> 'Params': """Applies an update to the corresponding parameters. This is a utility functions that applies an update to a set of parameters, and then returns the diff --git a/torchopt/utils.py b/torchopt/utils.py new file mode 100644 index 00000000..58e632fc --- /dev/null +++ b/torchopt/utils.py @@ -0,0 +1,273 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Utilities for TorchOpt.""" + +from typing import TYPE_CHECKING, Dict, NamedTuple, Optional, Sequence, Tuple, Union, cast + +import torch +import torch.nn as nn + +from torchopt import pytree +from torchopt.typing import OptState, TensorTree # pylint: disable=unused-import + + +try: + from typing import Literal # type: ignore[attr-defined] +except ImportError: + from typing_extensions import Literal + + +if TYPE_CHECKING: + from torchopt.optim.meta.base import MetaOptimizer + + +__all__ = [ + 'ModuleState', + 'stop_gradient', + 'extract_state_dict', + 'recover_state_dict', +] + + +class ModuleState(NamedTuple): + """Container for module state.""" + + params: Tuple[Dict[str, torch.Tensor], ...] + visual_contents: Optional[Dict] = None + + +def stop_gradient(target: Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer']) -> None: + """Stop the gradient for the input object. + + Since a tensor use :attr:`grad_fn` to connect itself with the previous computation graph, the + back-propagated gradient will flow over the tensor and continue flow to the tensors that is + connected by :attr:`grad_fn`. Some algorithms requires manually detaching tensors from the + computation graph. + + Note that the :func:`stop_gradient` operation is in-place. + + Args: + target: The target that to be detached from the computation graph, it could be a + :class:`nn.Module`, :class:`torchopt.MetaOptimizer`, state of the + :class:`torchopt.MetaOptimizer`, or just a plain list of tensors. + inplace: If :data:`True`, the target will be detached in-place. if :data:`Frue`, this + function will return a detached copy of the target. The in-place operation is fast and + memory efficient but may raise back-propagation error. + """ + # pylint: disable-next=import-outside-toplevel + from torchopt.optim.meta.base import MetaOptimizer + + def f(obj): + if isinstance(obj, torch.Tensor): + obj.detach_().requires_grad_(obj.requires_grad) + + if isinstance(target, ModuleState): + true_target = cast(TensorTree, target.params) + elif isinstance(target, nn.Module): + true_target = cast(TensorTree, tuple(target.parameters())) + elif isinstance(target, MetaOptimizer): + true_target = cast(TensorTree, target.state_dict()) + else: + true_target = cast(TensorTree, target) # tree of tensors + + pytree.tree_map(f, true_target) + + +# pylint: disable-next=too-many-branches,too-many-locals +def extract_state_dict( + target: Union[nn.Module, 'MetaOptimizer'], + *, + by: Literal['reference', 'copy', 'deepcopy'] = 'reference', # type: ignore[name-defined] + device: Optional[Union[int, str, torch.device]] = None, + with_buffer: bool = True, + enable_visual: bool = False, + visual_prefix: str = '', +) -> Union[ModuleState, Tuple['OptState', ...]]: + """Extract target state. + + Since a tensor use :attr:`grad_fn` to connect itself with the previous computation graph, the + back-propagated gradient will flow over the tensor and continue flow to the tensors that is + connected by :attr:`grad_fn`. Some algorithms requires manually detaching tensors from the + computation graph. + + Note that the extracted state is a reference, which means any in-place operator will affect the + target that the state is extracted from. + + Args: + target: It could be a :class:`nn.Module` or :class:`torchopt.MetaOptimizer`. + by: The extract policy of tensors in the target. + - :const:`'reference'`: The extracted tensors will be references to the original + tensors. + - :const:`'copy'`: The extracted tensors will be clones of the original tensors. This + makes the copied tensors have :attr:`grad_fn` to be a ```` function + points to the original tensors. + - :const:`'deepcopy'`: The extracted tensors will be deep-copied from the original + tensors. The deep-copied tensors will detach from the original computation graph. + device: If specified, move the extracted state to the specified device. + with_buffer: + Extract buffer together with parameters, this argument is only used if the input target + is :class:`nn.Module`. + enable_visual: + Add additional annotations, which could be used in computation graph visualization. + Currently, this flag only has effect on :class:`nn.Module` but we will support + :class:`torchopt.MetaOptimizer` later. + visual_prefix: Prefix for the visualization annotations. + + Returns: + State extracted of the input object. + """ + assert by in ('reference', 'copy', 'deepcopy', 'clone', 'deepclone') + by = by.replace('clone', 'copy') + if device is not None: + device = torch.device(device) + + # pylint: disable=import-outside-toplevel + from torchopt.optim.meta.base import MetaOptimizer + + if by == 'reference': + + if device is not None: + + def replicate(t): + return t.to(device=device) + + else: + + def replicate(t): + return t + + elif by == 'copy': + if device is not None: + + def replicate(t): + return t.clone().to(device=device) + + else: + + def replicate(t): + return t.clone() + + else: + if device is not None: + + def replicate(t): + return t.clone().detach_().to(device=device).requires_grad_(t.requires_grad) + + else: + + def replicate(t): + return t.clone().detach_().requires_grad_(t.requires_grad) + + if isinstance(target, nn.Module): # pylint: disable=no-else-return + if enable_visual: + visual_contents = {} + + for k, v in target.named_parameters(): # pylint: disable=invalid-name + if v.grad_fn is not None: + visual_contents.update({v.grad_fn: (visual_prefix + k, v)}) + else: + visual_contents.update({v: visual_prefix + k}) # type: ignore[dict-item] + else: + visual_contents = None + + params = [] + + def update_container(term): + if len(term) != 0: + params.append( + type(term)( + (k, replicate(v)) for k, v in term.items() if isinstance(v, torch.Tensor) + ) + ) + + # pylint: disable=protected-access + update_container(target._parameters) + if with_buffer: + update_container(target._buffers) + for module in target.modules(): + if module is target: + continue + update_container(module._parameters) + if with_buffer: + update_container(module._buffers) + return ModuleState(params=tuple(params), visual_contents=visual_contents) + + elif isinstance(target, MetaOptimizer): + state = target.state_dict() + + def get_variable(t): + if isinstance(t, torch.Tensor): + return replicate(t) + return t + + state = pytree.tree_map(get_variable, state) # type: ignore[arg-type,assignment] + return state + + raise RuntimeError(f'Unexpected class of {target}') + + +def _extract_container( + module: nn.Module, with_buffer: bool = True +) -> Tuple[Dict[str, Optional[torch.Tensor]], ...]: + if isinstance(module, nn.Module): + containers = [] + + def update_container(term): + if len(term) != 0: + containers.append(term) # we need references to original dicts + + # pylint: disable=protected-access + update_container(module._parameters) + if with_buffer: + update_container(module._buffers) + for submodule in module.modules(): + if submodule is module: + continue + update_container(submodule._parameters) + if with_buffer: + update_container(submodule._buffers) + return tuple(containers) + + raise RuntimeError(f'Unexpected class of {module}') + + +def recover_state_dict( + target: Union[nn.Module, 'MetaOptimizer'], + state: Union[ModuleState, Sequence['OptState']], +) -> None: + """Recover state. + + This function is compatible for the ``extract_state``. + + Note that the recovering process is not in-place, so the tensors of the object will not be + modified. + + Args: + target: Target that need to recover. + state: The recovering state. + """ + # pylint: disable-next=import-outside-toplevel + from torchopt.optim.meta.base import MetaOptimizer + + if isinstance(target, nn.Module): + target_container = _extract_container(target) + state = cast(ModuleState, state) + for tgt, source in zip(target_container, state.params): + tgt.update(source) + elif isinstance(target, MetaOptimizer): + state = cast(Sequence[OptState], state) + target.load_state_dict(state) + else: + raise RuntimeError(f'Unexpected class of {target}') diff --git a/torchopt/_src/visual.py b/torchopt/visual.py similarity index 82% rename from torchopt/_src/visual.py rename to torchopt/visual.py index ee493c6d..90f161b5 100644 --- a/torchopt/_src/visual.py +++ b/torchopt/visual.py @@ -15,15 +15,21 @@ # This file is modified from: # https://github.com/szagoruyko/pytorchviz/blob/master/torchviz/dot.py # ============================================================================== +"""Computation graph visualization.""" import warnings from collections import namedtuple -from typing import Dict, Generator +from typing import Generator, Iterable, Mapping, Optional, Sequence, Union, cast import torch from graphviz import Digraph from pkg_resources import parse_version +from torchopt.utils import ModuleState + + +__all__ = ['make_dot', 'resize_graph'] + Node = namedtuple('Node', ('name', 'inputs', 'attr', 'op')) @@ -42,9 +48,9 @@ def get_fn_name(fn, show_attrs, max_attr_chars): continue val = getattr(fn, attr) attr = attr[len(SAVED_PREFIX) :] - if torch.is_tensor(val): + if isinstance(val, torch.Tensor): attrs[attr] = '[saved tensor]' - elif isinstance(val, tuple) and any(torch.is_tensor(t) for t in val): + elif isinstance(val, tuple) and any(isinstance(t, torch.Tensor) for t in val): attrs[attr] = '[saved tensors]' else: attrs[attr] = str(val) @@ -63,10 +69,20 @@ def truncate(s): # pylint: disable=invalid-name return name + '\n' + sep + '\n' + params -# mypy: ignore-errors # pylint: disable-next=too-many-branches,too-many-statements,too-many-locals def make_dot( - var: torch.Tensor, params=None, show_attrs=False, show_saved=False, max_attr_chars=50 + var: Union[torch.Tensor, Sequence[torch.Tensor]], + params: Optional[ + Union[ + Mapping[str, torch.Tensor], + ModuleState, + Generator, + Iterable[Union[Mapping[str, torch.Tensor], ModuleState, Generator]], + ] + ] = None, + show_attrs: bool = False, + show_saved: bool = False, + max_attr_chars: int = 50, ) -> Digraph: """Produces Graphviz representation of PyTorch autograd graph. @@ -106,22 +122,20 @@ def make_dot( param_map = {} if params is not None: - from torchopt._src.utils import _ModuleState # pylint: disable=import-outside-toplevel - - if isinstance(params, _ModuleState): + if isinstance(params, ModuleState) and params.visual_contents is not None: param_map.update(params.visual_contents) - elif isinstance(params, Dict): + elif isinstance(params, Mapping): param_map.update({v: k for k, v in params.items()}) elif isinstance(params, Generator): param_map.update({v: k for k, v in params}) else: for param in params: - if isinstance(param, _ModuleState): + if isinstance(param, ModuleState) and param.visual_contents is not None: param_map.update(param.visual_contents) elif isinstance(param, Generator): param_map.update({v: k for k, v in param}) else: - param_map.update({v: k for k, v in param.items()}) + param_map.update({v: k for k, v in cast(Mapping, param).items()}) node_attr = dict( style='filled', @@ -149,7 +163,7 @@ def get_var_name_with_flag(var): return None def add_nodes(fn): # pylint: disable=too-many-branches - assert not torch.is_tensor(fn) + assert not isinstance(fn, torch.Tensor) if fn in seen: return seen.add(fn) @@ -161,12 +175,12 @@ def add_nodes(fn): # pylint: disable=too-many-branches val = getattr(fn, attr) seen.add(val) attr = attr[len(SAVED_PREFIX) :] - if torch.is_tensor(val): + if isinstance(val, torch.Tensor): dot.edge(str(id(fn)), str(id(val)), dir='none') dot.node(str(id(val)), get_var_name(val, attr), fillcolor='orange') if isinstance(val, tuple): for i, t in enumerate(val): - if torch.is_tensor(t): + if isinstance(t, torch.Tensor): name = f'{attr}[{i}]' dot.edge(str(id(fn)), str(id(t)), dir='none') dot.node(str(id(t)), get_var_name(t, name), fillcolor='orange') @@ -203,21 +217,21 @@ def add_nodes(fn): # pylint: disable=too-many-branches dot.edge(str(id(t)), str(id(fn))) dot.node(str(id(t)), get_var_name(t), fillcolor='orange') - def add_base_tensor(var, color='darkolivegreen1'): - if var in seen: + def add_base_tensor(v, color='darkolivegreen1'): # pylint: disable=invalid-name + if v in seen: return - seen.add(var) - dot.node(str(id(var)), get_var_name(var), fillcolor=color) - if var.grad_fn: - add_nodes(var.grad_fn) - dot.edge(str(id(var.grad_fn)), str(id(var))) + seen.add(v) + dot.node(str(id(v)), get_var_name(v), fillcolor=color) + if v.grad_fn: + add_nodes(v.grad_fn) + dot.edge(str(id(v.grad_fn)), str(id(v))) # pylint: disable=protected-access - if var._is_view(): - add_base_tensor(var._base, color='darkolivegreen3') - dot.edge(str(id(var._base)), str(id(var)), style='dotted') + if v._is_view(): + add_base_tensor(v._base, color='darkolivegreen3') + dot.edge(str(id(v._base)), str(id(v)), style='dotted') # handle multiple outputs - if isinstance(var, tuple): + if isinstance(var, (tuple, list)): for v in var: # pylint: disable=invalid-name add_base_tensor(v) else: @@ -228,7 +242,7 @@ def add_base_tensor(var, color='darkolivegreen1'): return dot -def resize_graph(dot, size_per_element=0.5, min_size=12): +def resize_graph(dot: Digraph, size_per_element: float = 0.5, min_size: float = 12.0) -> None: """Resize the graph according to how much content it contains. Modify the graph in place. diff --git a/tutorials/requirements.txt b/tutorials/requirements.txt index 5fe3b1ad..7531b8f8 100644 --- a/tutorials/requirements.txt +++ b/tutorials/requirements.txt @@ -1,4 +1,5 @@ --extra-index-url https://download.pytorch.org/whl/cu116 +# Sync with project.dependencies torch >= 1.12 torchvision functorch >= 0.2 From a6aba365d7636d48dfdfc86f4ddb0af8f4e0023f Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Wed, 28 Sep 2022 17:07:43 +0800 Subject: [PATCH 22/69] feat(distributed): RPC-based distributed training support and add distributed MAML example (#83) --- CHANGELOG.md | 1 + conda-recipe.yaml | 1 + docs/requirements.txt | 2 +- docs/source/spelling_wordlist.txt | 3 + examples/distributed/few-shot/README.md | 18 + examples/distributed/few-shot/maml-accs.png | Bin 0 -> 157986 bytes .../distributed/few-shot/maml_omniglot.py | 310 ++++++++++++ .../few-shot/maml_omniglot_local_loader.py | 353 +++++++++++++ .../few-shot/support/omniglot_loaders.py | 327 ++++++++++++ examples/few-shot/README.md | 2 +- examples/few-shot/maml-accs.png | Bin 33854 -> 151372 bytes examples/few-shot/maml_omniglot.py | 16 +- tests/test_optimizer.py | 420 ---------------- torchopt/__init__.py | 11 +- torchopt/distributed/__init__.py | 30 ++ torchopt/distributed/api.py | 471 ++++++++++++++++++ torchopt/distributed/autograd.py | 129 +++++ torchopt/distributed/world.py | 228 +++++++++ torchopt/pytree.py | 42 +- torchopt/typing.py | 10 + torchopt/utils.py | 92 ++++ 21 files changed, 2035 insertions(+), 431 deletions(-) create mode 100644 examples/distributed/few-shot/README.md create mode 100644 examples/distributed/few-shot/maml-accs.png create mode 100644 examples/distributed/few-shot/maml_omniglot.py create mode 100644 examples/distributed/few-shot/maml_omniglot_local_loader.py create mode 100644 examples/distributed/few-shot/support/omniglot_loaders.py delete mode 100644 tests/test_optimizer.py create mode 100644 torchopt/distributed/__init__.py create mode 100644 torchopt/distributed/api.py create mode 100644 torchopt/distributed/autograd.py create mode 100644 torchopt/distributed/world.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f95fdf8..5d86f2f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add RPC-based distributed training support and add distributed MAML example by [@XuehaiPan](https://github.com/XuehaiPan) in [#83](https://github.com/metaopt/torchopt/pull/83). - Add full type hints by [@XuehaiPan](https://github.com/XuehaiPan) in [#92](https://github.com/metaopt/torchopt/pull/92). - Add API documentation and tutorial for implicit gradients by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan) in [#73](https://github.com/metaopt/torchopt/pull/73). - Add wrapper class for functional optimizers and examples of `functorch` integration by [@vmoens](https://github.com/vmoens) and [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@XuehaiPan](https://github.com/XuehaiPan) in [#6](https://github.com/metaopt/torchopt/pull/6). diff --git a/conda-recipe.yaml b/conda-recipe.yaml index bd6d3225..7c170f8d 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -51,6 +51,7 @@ dependencies: - seaborn - python-graphviz - pillow + - setproctitle # Documentation - sphinx diff --git a/docs/requirements.txt b/docs/requirements.txt index 25615049..9060c0ec 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -5,7 +5,7 @@ functorch >= 0.2 --requirement ../requirements.txt -sphinx >= 5.0, < 5.2.0a0 +sphinx >= 5.2.1 sphinx-autoapi sphinx-autobuild sphinx-copybutton diff --git a/docs/source/spelling_wordlist.txt b/docs/source/spelling_wordlist.txt index ecdb936a..22e3c832 100644 --- a/docs/source/spelling_wordlist.txt +++ b/docs/source/spelling_wordlist.txt @@ -56,6 +56,7 @@ iterable nan param Graphviz +Autograd autograd attrs GradientTransformations @@ -84,3 +85,5 @@ argnums matvec Hermitian deepcopy +RRef +rref diff --git a/examples/distributed/few-shot/README.md b/examples/distributed/few-shot/README.md new file mode 100644 index 00000000..a0a758fa --- /dev/null +++ b/examples/distributed/few-shot/README.md @@ -0,0 +1,18 @@ +# MAML few-shot Omniglot classification-examples + +Code on MAML few-shot Omniglot classification in paper [Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks](https://arxiv.org/abs/1703.03400) using TorchOpt. We use `MetaSGD` as the inner-loop optimizer. + +## Usage + +```bash +### Run +torchrun --nnode 1 --nproc_per_node 8 maml_omniglot.py +``` + +## Results + +The figure illustrate the experimental result. + +
+ +
diff --git a/examples/distributed/few-shot/maml-accs.png b/examples/distributed/few-shot/maml-accs.png new file mode 100644 index 0000000000000000000000000000000000000000..95a4a0f9e33af07601f21264152c63fd5f2602f2 GIT binary patch literal 157986 zcmeFZcUY5Y_bv)HEGT0IrP&=tK$=L$1|m&FK)Q(ZF1-Y>fdxSkL1{sHN2J%NC=rnw zdLU5&sUZS^00FYsgEQaE_w8@b@9gvExlXQY1_>$e`;@irb>H`T9$eB;-n?H}hY#7{d_muph2`+df2`B??i*QH zSy)ugoxb7~JKpE%#xvNCpTw5ms4wo7aqL>BZU1odI>Nh%ySw(%npfL6U08qUuHv>c zs@AM$0@v94Y~a;)u(xL~rJJ;8lNh%3l>zG=#C!U>yHj=M{TnBxNZs8pl_}lbWldF* z?@q9vg$wxeL34gE$@k|k=w}=&tJ~jxKgYuRx8GFOG{a^7`FQgG|B;2||LcPg$oK8T zcFiki&fKPx9~_D2qV97)8n8gXs*!Pb@2)Y-@ z8(0!k1*(S{;$%9l92*-OL+P(!-TY=%_pjyFtgE3BTI|@D85_&f-q!Z%oAd7n4xC+L z&^t?A`rSV53$|`fI6cXC7~U4>c%MZYz5P&kclRDi$JiXqv+(eU`1o8J&22N!sY_>r z*ju{t%_Y32Zm7pe>)`o(v)8e6{no#A_3%XX!l*!;TdN8ymboyNCt=r-eZR?-T16k7 zsG!a=j4odeHxknOF!UsObkue;zr4}o$B$DftJkq#I(_<9YisL%dF9t-i-S?79Xs`m zwoZDR_|ID`4IEL}Fz07t60h`lkA*jTfVteayW45)dZy=PtG(ua#5mEW>V@q{mEJui zPNvOEX=*PMr<)W^^^D!0AJ&NNVm+`1?xuPBrT1ue-Ctco%vo6Qc^(yIhY#g7D0j;+ z@gCf{G#M7qCN&hBbo$P^k^2Wio9}SQTMOK8Zg>CqChxV9es8W>W31Fx{+bi)Fv^ls z@49}%{V~=w9m+^dJVV7X{ewgH?IDY)_QnjmJ4qsBB={;K0BKuVlr=mMw6BduP`ttcL50dt%0AP+{cJhr;3G(XBa8zAsy#4KNvMLOLQ7rW>7mDB*{EUEvtrYMn^|! z=*i5i+>Hz_-sdV+W;N?_42q6@oi_EKPq}&Xrnu#o7cW9#)T-vbKPn%J_kAy48!P2{ zgG*_La{J5`9i5Tvg2s(pr*X~0rZ zuVcxG#OBSL%O`8Oi{NYI<_Df#yl`RozVKSObVbRtE5Y;rs{>)Ot-8WJ-@jkaxtf1Q zKsUR2aelhUZ~i70vxl2|CWgGIgq~Ctu1X%b!HAkRF5-8znoLtzdax~H_~Zhen)mth zMQT5%iPyey79R(P9Fq4CFQJ%q^}6)L#QljP3k3NZ*?s%o?YKMZB^xc{>3HrIMX@KK z=|^K+Rt2?MCYvP(2KkY2wRO*~EULbh4veI>hSYi33X|TBKfk{7`Fe}Zt?p118f?}u zt;?4a1D3{2(X#{2r_`F3rm@Tj!bn>|lRWoK{(%!cC_^MvB;1vOpUoTCd8MydVKK!M zRdf?U!(z28-JDj~E8iqfO~Zm5`z(+bQu8~j8ylyoUw(Lacx4!FdBKiCs*=ezuY!@Y zwYL5#FF*J7jyvr6bF#IwJX?ZIFf%%Y;*Rlw;_J`5F&+9=M+F4x8K-1q3}H!a9J`99 zGUE_Fkae}&!bqC3^amlBPh*#lJN@qraT>clEp{U3j^$P~ih2pDpx7Ws?@ijweRBA9 z&6a8JWmsl}q%iqCMJ{N04@>>A%$v6=^Sp{O_1EY3pL?}#3(xTMBDYiJ>1!;CSCv9} zG6)(n4UDc|n=RYC;iVX!HWzJ|`{0H(YZY^uaZFfP(xGBBGs{nO$o1w;8bl1GrNxnv zk@A6XRW)Ky0L7yypbwtSZEI_LjqhleU7`^de%5ecis5bsefl3uw&4PpPeLVaS`P|d zeXU4HRiE~r2$h*=4%*E9p7$7BY9Qakl{nb^VCiSDLR+Rzmbll?YuKS>`0bL=PQ|Oa zRkH?!ei&#izOW<7=Jv$mhBln^p+ko(+eLb!oT$W-yhb^?kuiLsJmq)~m0OU4v!Yf` zhuYfOo{?74(RohtrOMU!dsxAH%KJlQ{ED%DQ*}O*A32}D;37F>!kV*QUYy?}?Urs+ z0ZZbsB#Em-WM#)1(G<~+l`hLS$B)AE&Ewq#gB}%C#F*%4H+rAvSW1-1=<9s(lP7Jb ze>C)zyJsB}5I{>YIr-qsXuB$k{4Yez#m(NYdCVjArlxjB?vEdqIVM#G#9{|+ef^iP zE*54fSxKSN7nOP4uLOr$)JF;$lsLw1+_-VTOm+3=E>zZQhftm83K>oD`<3q@>i=^zzxWBuEJ92?>fiIy$3-w6Mc!FA{c( zSW)j*C!o%4rW-$`@u}p2-xMeSrHRo ziUd5o`88usHaPuo^PKs5ha)pLx3N$VQel%EJvJjp@f5o3fW>}(`RA)51r1ZZr+-m8f`7g{5kTNg%7@7tT1LaA0O^KcI?bMas&Rya{pnKFMUtA8dKxcx4Y@Q%qZMqO4Fpaw)W%q@82inq2#%LPbY*b zyG2;Z;+HR9_N)C$CEwqAAmouy`6sWz=XxO!`mz1<43m2cPH=PncxkIf9xR4F(Km+i zAM41emFP4wzhP;)AUC0-XFTZo1tt$~r65xqvU~f_t}VeeUbGhF$1eS~YZv$U&Wu_Z zxwV|Hg^gt&CmcaN`+E;RB!Y>_3NpNT=VX&RWY%JQktfxpUk|tNT*QCTtKK{{EsZ-Z z&LeuV?g;ko%uER#q8qoERipT}ZQB;(g+)YKPR+DwKfbq#Gup(8&fr4nZ%PV~2FZ>q z$ZT;`4=3t?gJ59K-#K`5cTLb{v8v@74h3=c8qaE#ix(db+x?`|OK#L{qfR?j%|td$ zYs$~x=o*@qR514Ja}P4(s)a;yy~iJJB-m{nB^BDjk$A87C)k+*GTz?aW{)MJsWL5B z^z^J~6r$vh0JbA>ZsAQ*8d8H133;1NHsu)XZB zB?P`MK8=pHHS(MMsHCBx@yXQpHGSdyqg}hvEkAwng6pT<3sH-QlMv3iAh--n8&(Z< z4?3R;fu-I2Lfq!^Tanb%)IE@-Ugi5Q`B29emjt`K6&`f>rVvKN<1w@P{axl^5|98^ zg~~y)dLfS~pM;&bM_paLIF#bV$1!7S6~~Dph`_~C6qt=aIQdU=W2cH68XA1Ya!Rgy zG*(v1#yP*=u+S3bpA7q;Zp5v}#~5(hGK0(O&7$$b@`V-RaQodOt!l)ehdul|s?7pMWutOKE^&cN{MeL7TJk=4^eRQ2OM#H6QC3!F7FUvdzOZ zjKT!0k8CV+ap-25ky)H@M-N>901O>=i^W(GgwqEPA3m%M3*O9~D%K<`7G3k~Aa1D} z|Cl>XzrfO)AM4sE_4)H>QOfo#(Fr{xmwT`qD#M~+<_%!rWfyiYdi1&x)a8l0gp9am$yH`t<$&%a%xl?EhKi)#dBiE)A%f>g z3g-9k8Y+v9-ec_iZml$6!6LVj*1&0HSJwiP-?X~=OVRUiBkS$HP^5Ua^f}jTmL5rd zCLXZtS5FUz6hDlHdbd^VtA&My^jLDPPL{6CXj=wK7=`Be&_ITSq~sW-gxrBLDjT0y z!fNGVGGx{afUs93NnT0S^FO$?ixOtpYnnel7nmWEmvx^VR-dvNfoTtHy!9)|oe$wx zFhRhgX%^=C}N|zK3Nc&q^QN2naAR8em?30 ztIYvhQeAB_6zdwQn`^Xt>ID(sGtl%9=4t*@rtRDXGV4Ly`Ob8aY() z2MP^DXlt~pXCIT91+6u7wuNWDP_nm}dFD_ttKKg{&ZBa2Xohw(8 z^Ki=sSpS6#K-KDbSTUrLeET_JXk?U) zX4as>!=afhmT|~;x{#nT&E3@v#ev(qwVc*d19h;CFT1$p!xUw3C@eO|I541C8iC}< z?i24-`XkzoHfGA~Vax%bXm0YK6|3)zh>Tn~-fM$x;1gUHtqYiXhMluVn36VL&=g%< z_4EBE>BXNlN%E<7xn)XF;#JcpQPlvOyy+(EEx=;}d6nN?W8(+1@~Wr0cRk8nn~{-$ z_AZUgT<$Eyv?QKC9Z*7K;1!n5Hr@@}EvAI_*B1G?Yn!=FAPi(s?N^3^>B5apvfp$= zw484-R8tDZJ|iiqqpOv9T<$iW>SuqfhkNRG^#27+u z3xt+$({d5XP>jCIDu z^8=a%C}1ho0qH{_LU=Q*d=~*egkRjmcv~KM41Rv@?`!BtuI`(1e>JOU3Ke>jRBaf) z({bbSwvJN*$Bu;n1JZtKd9MGl%tYyd;pLX$n4Zt33WVaN3r^)Dhm*3ikAEHG=H|u} zpU-0R0iZ@_>g(&*!sPAvS+sWT+FB^|`%3~wAu5)uQ@px(ARdmt%>{a9IG9=8Vdda&moM9RB_-ug zuF%cCy7k$#9Ig4R{1DojgLaDz(>b_+DxVqA<(aℑROxFp;|vM?)sZz>hC9`SNS; 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

~%JHJ;+~y8cZ@J0?UG%;nv%Q&^nJ@v%w+#t4 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

s5b|%eLop*5_(PArWw}5x#C5 ze>voUiM%3Bu!eyzZk)(d1JP<5+7IsU&)Ve4dG?Z4EZWI4+bY>_=rgMLiRISOvkAMN zy|2w{D-ueXvTz-=^JNVpzjE?qk74!pz~DcyFRdKFy}uVaQv+hi%BXo4z*Q>`k+@SQ z=Wp|_X4CZL#xV8erDC`sYyJ}gh=L`Ed6Mhtu%j8hvM=-Y&U%V5FN^(B`jRq~6O4e_ z6TgwV8MQRCN^~mjNAHE))$L%1Ia2EyAXd!mj{v!NW!4s8n`iZ(p-nXXyI!%I

&P8Q)TFVoq_Nd{EuA?NrQaq> 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

  • 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 literal 0 HcmV?d00001 diff --git a/examples/distributed/few-shot/maml_omniglot.py b/examples/distributed/few-shot/maml_omniglot.py new file mode 100644 index 00000000..d798c4f5 --- /dev/null +++ b/examples/distributed/few-shot/maml_omniglot.py @@ -0,0 +1,310 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/facebookresearch/higher/blob/main/examples/maml-omniglot.py +# ============================================================================== +# Copyright (c) Facebook, Inc. and its affiliates. +# +# 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. +""" +This example shows how to use TorchOpt to do Model Agnostic Meta Learning (MAML) +for few-shot Omniglot classification. +For more details see the original MAML paper: +https://arxiv.org/abs/1703.03400 +This code has been modified from Jackie Loong's PyTorch MAML implementation: +https://github.com/dragen1860/MAML-Pytorch/blob/master/omniglot_train.py +Our MAML++ fork and experiments are available at: +https://github.com/bamos/HowToTrainYourMAMLPytorch +""" + +import argparse +import os +import random +import time + +import matplotlib as mpl +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from setproctitle import getproctitle, setproctitle + +import torchopt +import torchopt.distributed as todist + + +from support.omniglot_loaders import OmniglotNShot # isort: skip + + +mpl.use('Agg') +plt.style.use('bmh') + + +def worker_init(): + world_info = todist.get_world_info() + + proctitle = f'{world_info.worker_name}: {getproctitle().strip()}' + print(f'worker_init => {proctitle}') + setproctitle(proctitle) + + seed = world_info.local_rank + + os.environ['PYTHONHASHSEED'] = str(seed) + + random.seed(seed) + np.random.seed(seed) + + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + + if world_info.local_rank < torch.cuda.device_count(): + torch.cuda.set_device(world_info.local_rank) + + +def build_model(args, device): + return nn.Sequential( + nn.Conv2d(1, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Flatten(), + nn.Linear(64, args.n_way), + ).to(device) + + +@todist.rank_zero_only +def get_data_loader(args, device): + rng = np.random.default_rng(args.seed) + + return OmniglotNShot( + '/tmp/omniglot-data', + batchsz=args.task_num, + n_way=args.n_way, + k_shot=args.k_spt, + k_query=args.k_qry, + imgsz=28, + rng=rng, + device=device, + ) + + +@todist.auto_init_rpc(worker_init) +def main(): + argparser = argparse.ArgumentParser() + argparser.add_argument('--n_way', type=int, help='n way', default=5) + argparser.add_argument('--k_spt', type=int, help='k shot for support set', default=5) + argparser.add_argument('--k_qry', type=int, help='k shot for query set', default=15) + argparser.add_argument( + '--task_num', type=int, help='meta batch size, namely task num', default=32 + ) + argparser.add_argument('--seed', type=int, help='random seed', default=1) + args = argparser.parse_args() + + torch.manual_seed(args.seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(args.seed) + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + np.random.seed(args.seed) + + # Set up the Omniglot loader. + db = get_data_loader(args, device=torch.device('cpu')) + + # Create a vanilla PyTorch neural network. + net = build_model(args, device=torch.device('cpu')) + + # We will use Adam to (meta-)optimize the initial parameters + # to be adapted. + meta_opt = optim.Adam(net.parameters(), lr=1e-3) + + log = [] + test(db, net, epoch=-1, log=log) + for epoch in range(10): + train(db, net, meta_opt, epoch=epoch, log=log) + test(db, net, epoch=epoch, log=log) + plot(log) + + +def transpose_mean_reducer(results): + qry_losses, qry_accs = tuple(zip(*results)) + qry_loss = torch.mean(torch.stack(qry_losses)) + qry_acc = np.mean(qry_accs) + return qry_loss, qry_acc + + +@todist.parallelize( + partitioner=todist.dim_partitioner(dim=0, exclusive=True, keepdim=False), + reducer=transpose_mean_reducer, +) +def inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter): + if torch.cuda.is_available(): + device = torch.device(f'cuda:{todist.get_local_rank() % torch.cuda.device_count()}') + torch.cuda.set_device(device) + else: + device = None + + original_net = net_rref.to_here() + net = torchopt.module_clone(original_net, by='reference', device=device) + if device is not None: + x_spt = x_spt.to(device) + y_spt = y_spt.to(device) + x_qry = x_qry.to(device) + y_qry = y_qry.to(device) + + querysz = x_qry.size(0) + inner_opt = torchopt.MetaSGD(net, lr=1e-1) + + for _ in range(n_inner_iter): + spt_logits = net(x_spt) + spt_loss = F.cross_entropy(spt_logits, y_spt) + inner_opt.step(spt_loss) + + qry_logits = net(x_qry) + qry_loss = F.cross_entropy(qry_logits, y_qry).cpu() + qry_acc = (qry_logits.argmax(dim=1) == y_qry).sum().cpu().item() / querysz + + return qry_loss, qry_acc + + +@todist.rank_zero_only +def train(db: OmniglotNShot, net: nn.Module, meta_opt: optim.Adam, epoch: int, log: list): + net.train() + n_train_iter = db.x_train.shape[0] // db.batchsz + + net_rref = todist.rpc.RRef(net) + for batch_idx in range(n_train_iter): + start_time = time.time() + # Sample a batch of support and query images and labels. + x_spt, y_spt, x_qry, y_qry = db.next() + + # TODO: Maybe pull this out into a separate module so it + # doesn't have to be duplicated between `train` and `test`? + + # Initialize the inner optimizer to adapt the parameters to + # the support set. + n_inner_iter = 5 + + meta_opt.zero_grad() + with todist.autograd.context() as context_id: + qry_loss, qry_acc = inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter) + todist.autograd.backward(context_id, qry_loss) + meta_opt.step() + + qry_loss = qry_loss.item() + qry_acc = 100.0 * qry_acc + i = epoch + float(batch_idx) / n_train_iter + iter_time = time.time() - start_time + + print( + f'[Epoch {i:.2f}] Train Loss: {qry_loss:.2f} | Acc: {qry_acc:.2f} | Time: {iter_time:.2f}' + ) + + log.append( + { + 'epoch': i, + 'loss': qry_loss, + 'acc': qry_acc, + 'mode': 'train', + 'time': time.time(), + } + ) + + +@todist.rank_zero_only +def test(db, net, epoch, log): + # Crucially in our testing procedure here, we do *not* fine-tune + # the model during testing for simplicity. + # Most research papers using MAML for this task do an extra + # stage of fine-tuning here that should be added if you are + # adapting this code for research. + net.train() + n_test_iter = db.x_test.shape[0] // db.batchsz + + qry_losses = [] + qry_accs = [] + + net_rref = todist.rpc.RRef(net) + for _ in range(n_test_iter): + x_spt, y_spt, x_qry, y_qry = db.next('test') + + # TODO: Maybe pull this out into a separate module so it + # doesn't have to be duplicated between `train` and `test`? + n_inner_iter = 5 + + qry_loss, qry_acc = inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter) + qry_losses.append(qry_loss.item()) + qry_accs.append(qry_acc) + + qry_losses = np.mean(qry_losses) + qry_accs = 100.0 * np.mean(qry_accs) + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') + log.append( + { + 'epoch': epoch + 1, + 'loss': qry_losses, + 'acc': qry_accs, + 'mode': 'test', + 'time': time.time(), + } + ) + + +@todist.rank_zero_only +def plot(log): + # Generally you should pull your plotting code out of your training + # script but we are doing it here for brevity. + df = pd.DataFrame(log) + + fig, ax = plt.subplots(figsize=(8, 4), dpi=250) + train_df = df[df['mode'] == 'train'] + test_df = df[df['mode'] == 'test'] + ax.plot(train_df['epoch'], train_df['acc'], label='Train') + ax.plot(test_df['epoch'], test_df['acc'], label='Test') + ax.set_xlabel('Epoch') + ax.set_ylabel('Accuracy') + ax.set_ylim(85, 100) + ax.set_title('Distributed MAML Omniglot') + ax.legend(ncol=2, loc='lower right') + fig.tight_layout() + fname = 'maml-accs.png' + print(f'--- Plotting accuracy to {fname}') + fig.savefig(fname) + plt.close(fig) + + +if __name__ == '__main__': + main() diff --git a/examples/distributed/few-shot/maml_omniglot_local_loader.py b/examples/distributed/few-shot/maml_omniglot_local_loader.py new file mode 100644 index 00000000..66c0dd90 --- /dev/null +++ b/examples/distributed/few-shot/maml_omniglot_local_loader.py @@ -0,0 +1,353 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/facebookresearch/higher/blob/main/examples/maml-omniglot.py +# ============================================================================== +# Copyright (c) Facebook, Inc. and its affiliates. +# +# 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. +""" +This example shows how to use TorchOpt to do Model Agnostic Meta Learning (MAML) +for few-shot Omniglot classification. +For more details see the original MAML paper: +https://arxiv.org/abs/1703.03400 +This code has been modified from Jackie Loong's PyTorch MAML implementation: +https://github.com/dragen1860/MAML-Pytorch/blob/master/omniglot_train.py +Our MAML++ fork and experiments are available at: +https://github.com/bamos/HowToTrainYourMAMLPytorch +""" + +import argparse +import copy +import os +import random +import threading +import time + +import matplotlib as mpl +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from setproctitle import getproctitle, setproctitle + +import torchopt +import torchopt.distributed as todist + + +from support.omniglot_loaders import OmniglotNShot # isort: skip + + +mpl.use('Agg') +plt.style.use('bmh') + + +LOCK = threading.Lock() +LOCAL_DATA_LOADER = None +TASK_DATA_LOADERS = {} +LOCAL_DEVICE = None + + +def worker_init(): + global LOCAL_DEVICE + + world_info = todist.get_world_info() + + proctitle = f'{world_info.worker_name}: {getproctitle().strip()}' + print(f'worker_init => {proctitle}') + setproctitle(proctitle) + + seed = world_info.world_rank + local_rank = world_info.local_rank + + os.environ['PYTHONHASHSEED'] = str(seed) + + random.seed(seed) + np.random.seed(seed) + + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + + if world_info.local_rank < torch.cuda.device_count(): + torch.cuda.set_device(world_info.local_rank) + + if torch.cuda.is_available(): + device = torch.device(f'cuda:{local_rank % torch.cuda.device_count()}') + torch.cuda.set_device(device) + else: + device = None + LOCAL_DEVICE = device + + +def build_model(args, device): + return nn.Sequential( + nn.Conv2d(1, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Flatten(), + nn.Linear(64, args.n_way), + ).to(device) + + +def set_local_data_loader(args, device): + global LOCAL_DATA_LOADER + + if LOCAL_DATA_LOADER is None: + rng = np.random.default_rng(args.seed) + + with LOCK: + LOCAL_DATA_LOADER = OmniglotNShot( + '/tmp/omniglot-data', + batchsz=args.task_num, + n_way=args.n_way, + k_shot=args.k_spt, + k_query=args.k_qry, + imgsz=28, + rng=rng, + device=device, + ) + + return LOCAL_DATA_LOADER + + +def get_next_batch(task_id, mode): + assert LOCAL_DATA_LOADER is not None + + if task_id not in TASK_DATA_LOADERS: + with LOCK: + TASK_DATA_LOADERS[task_id] = copy.deepcopy(LOCAL_DATA_LOADER) + + db = TASK_DATA_LOADERS[task_id] + x_spt, y_spt, x_qry, y_qry = db.next(mode) + x_spt, y_spt, x_qry, y_qry = x_spt[task_id], y_spt[task_id], x_qry[task_id], y_qry[task_id] + return x_qry, y_qry, x_spt, y_spt + + +@todist.auto_init_rpc(worker_init) +def main(): + argparser = argparse.ArgumentParser() + argparser.add_argument('--n_way', type=int, help='n way', default=5) + argparser.add_argument('--k_spt', type=int, help='k shot for support set', default=5) + argparser.add_argument('--k_qry', type=int, help='k shot for query set', default=15) + argparser.add_argument( + '--task_num', type=int, help='meta batch size, namely task num', default=32 + ) + argparser.add_argument('--seed', type=int, help='random seed', default=1) + args = argparser.parse_args() + + torch.manual_seed(args.seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(args.seed) + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + np.random.seed(args.seed) + + # Set up the Omniglot loader. + set_local_data_loader(args, device=LOCAL_DEVICE) + todist.barrier() # ensure that all workers have loaded the data + + # Create a vanilla PyTorch neural network. + net = build_model(args, device=torch.device('cpu')) + + # We will use Adam to (meta-)optimize the initial parameters + # to be adapted. + meta_opt = optim.Adam(net.parameters(), lr=1e-3) + + log = [] + test(net, epoch=-1, log=log) + for epoch in range(10): + train(net, meta_opt, epoch=epoch, log=log) + test(net, epoch=epoch, log=log) + plot(log) + + +def args_replicator(net_rref, n_inner_iter, task_id, task_num, mode): + del task_id + num_workers = todist.get_world_size() + return [ + (task_id % num_workers, (net_rref, n_inner_iter, task_id, task_num, mode), None) + for task_id in range(task_num) + ] + + +def transpose_mean_reducer(results): + qry_losses, qry_accs = tuple(zip(*results)) + qry_loss = torch.mean(torch.stack(qry_losses)) + qry_acc = np.mean(qry_accs) + return qry_loss, qry_acc + + +@todist.parallelize(partitioner=args_replicator, reducer=transpose_mean_reducer) +def inner_loop(net_rref, n_inner_iter, task_id, task_num, mode): + device = LOCAL_DEVICE + + original_net = net_rref.to_here() + net = torchopt.module_clone(original_net, by='reference', device=device) + + x_spt, y_spt, x_qry, y_qry = get_next_batch(task_id, mode) + if device is not None: + x_spt = x_spt.to(device) + y_spt = y_spt.to(device) + x_qry = x_qry.to(device) + y_qry = y_qry.to(device) + + querysz = x_qry.size(0) + inner_opt = torchopt.MetaSGD(net, lr=1e-1) + + for _ in range(n_inner_iter): + spt_logits = net(x_spt) + spt_loss = F.cross_entropy(spt_logits, y_spt) + inner_opt.step(spt_loss) + + qry_logits = net(x_qry) + qry_loss = F.cross_entropy(qry_logits, y_qry).cpu() + qry_acc = (qry_logits.argmax(dim=1) == y_qry).sum().cpu().item() / querysz + + return qry_loss, qry_acc + + +@todist.rank_zero_only +def train(net: nn.Module, meta_opt: optim.Adam, epoch: int, log: list): + net.train() + + db = LOCAL_DATA_LOADER + n_train_iter = db.x_train.shape[0] // db.batchsz + task_num = db.x_train.shape[1] + + net_rref = todist.rpc.RRef(net) + for batch_idx in range(n_train_iter): + start_time = time.time() + + # TODO: Maybe pull this out into a separate module so it + # doesn't have to be duplicated between `train` and `test`? + + # Initialize the inner optimizer to adapt the parameters to + # the support set. + n_inner_iter = 5 + + meta_opt.zero_grad() + with todist.autograd.context() as context_id: + qry_loss, qry_acc = inner_loop(net_rref, n_inner_iter, None, task_num, 'train') + todist.autograd.backward(context_id, qry_loss) + meta_opt.step() + + qry_loss = qry_loss.item() + qry_acc = 100.0 * qry_acc + i = epoch + float(batch_idx) / n_train_iter + iter_time = time.time() - start_time + + print( + f'[Epoch {i:.2f}] Train Loss: {qry_loss:.2f} | Acc: {qry_acc:.2f} | Time: {iter_time:.2f}' + ) + + log.append( + { + 'epoch': i, + 'loss': qry_loss, + 'acc': qry_acc, + 'mode': 'train', + 'time': time.time(), + } + ) + + +@todist.rank_zero_only +def test(net, epoch, log): + # Crucially in our testing procedure here, we do *not* fine-tune + # the model during testing for simplicity. + # Most research papers using MAML for this task do an extra + # stage of fine-tuning here that should be added if you are + # adapting this code for research. + net.train() + + db = LOCAL_DATA_LOADER + n_test_iter = db.x_test.shape[0] // db.batchsz + task_num = db.x_train.shape[1] + + qry_losses = [] + qry_accs = [] + + net_rref = todist.rpc.RRef(net) + for _ in range(n_test_iter): + # TODO: Maybe pull this out into a separate module so it + # doesn't have to be duplicated between `train` and `test`? + n_inner_iter = 5 + + qry_loss, qry_acc = inner_loop(net_rref, n_inner_iter, None, task_num, 'test') + qry_losses.append(qry_loss.item()) + qry_accs.append(qry_acc) + + qry_losses = np.mean(qry_losses) + qry_accs = 100.0 * np.mean(qry_accs) + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') + log.append( + { + 'epoch': epoch + 1, + 'loss': qry_losses, + 'acc': qry_accs, + 'mode': 'test', + 'time': time.time(), + } + ) + + +@todist.rank_zero_only +def plot(log): + # Generally you should pull your plotting code out of your training + # script but we are doing it here for brevity. + df = pd.DataFrame(log) + + fig, ax = plt.subplots(figsize=(8, 4), dpi=250) + train_df = df[df['mode'] == 'train'] + test_df = df[df['mode'] == 'test'] + ax.plot(train_df['epoch'], train_df['acc'], label='Train') + ax.plot(test_df['epoch'], test_df['acc'], label='Test') + ax.set_xlabel('Epoch') + ax.set_ylabel('Accuracy') + ax.set_ylim(85, 100) + ax.set_title('Distributed MAML Omniglot') + ax.legend(ncol=2, loc='lower right') + fig.tight_layout() + fname = 'maml-accs.png' + print(f'--- Plotting accuracy to {fname}') + fig.savefig(fname) + plt.close(fig) + + +if __name__ == '__main__': + main() diff --git a/examples/distributed/few-shot/support/omniglot_loaders.py b/examples/distributed/few-shot/support/omniglot_loaders.py new file mode 100644 index 00000000..d857d386 --- /dev/null +++ b/examples/distributed/few-shot/support/omniglot_loaders.py @@ -0,0 +1,327 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# 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. +# ============================================================================== +# These Omniglot loaders are from Jackie Loong's PyTorch MAML implementation: +# https://github.com/dragen1860/MAML-Pytorch +# https://github.com/dragen1860/MAML-Pytorch/blob/master/omniglot.py +# https://github.com/dragen1860/MAML-Pytorch/blob/master/omniglotNShot.py +# ============================================================================== + +import errno +import os + +import numpy as np +import torch +import torch.utils.data as data +import torchvision.transforms as transforms +from PIL import Image + + +class Omniglot(data.Dataset): + """ + The items are ``(filename, category)``. The index of all the categories can be found in + :attr:`idx_classes`. + + Args: + root: the directory where the dataset will be stored + transform: how to transform the input + target_transform: how to transform the target + download: need to download the dataset + """ + + urls = [ + 'https://github.com/brendenlake/omniglot/raw/master/python/images_background.zip', + 'https://github.com/brendenlake/omniglot/raw/master/python/images_evaluation.zip', + ] + raw_folder = 'raw' + processed_folder = 'processed' + training_file = 'training.pt' + test_file = 'test.pt' + + def __init__(self, root, transform=None, target_transform=None, download=False): + self.root = root + self.transform = transform + self.target_transform = target_transform + + if not self._check_exists(): + if download: + self.download() + else: + raise RuntimeError('Dataset not found. You can use download=True to download it') + + self.all_items = find_classes(os.path.join(self.root, self.processed_folder)) + self.idx_classes = index_classes(self.all_items) + + def __getitem__(self, index): + filename = self.all_items[index][0] + img = str.join('/', [self.all_items[index][2], filename]) + + target = self.idx_classes[self.all_items[index][1]] + if self.transform is not None: + img = self.transform(img) + if self.target_transform is not None: + target = self.target_transform(target) + + return img, target + + def __len__(self): + return len(self.all_items) + + def _check_exists(self): + return os.path.exists( + os.path.join(self.root, self.processed_folder, 'images_evaluation') + ) and os.path.exists(os.path.join(self.root, self.processed_folder, 'images_background')) + + def download(self): + import zipfile + + from six.moves import urllib + + if self._check_exists(): + return + + # download files + try: + os.makedirs(os.path.join(self.root, self.raw_folder)) + os.makedirs(os.path.join(self.root, self.processed_folder)) + except OSError as e: + if e.errno == errno.EEXIST: + pass + else: + raise + + for url in self.urls: + print('== Downloading ' + url) + data = urllib.request.urlopen(url) + filename = url.rpartition('/')[2] + file_path = os.path.join(self.root, self.raw_folder, filename) + with open(file_path, 'wb') as f: + f.write(data.read()) + file_processed = os.path.join(self.root, self.processed_folder) + print('== Unzip from ' + file_path + ' to ' + file_processed) + zip_ref = zipfile.ZipFile(file_path, 'r') + zip_ref.extractall(file_processed) + zip_ref.close() + print('Download finished.') + + +def find_classes(root_dir): + retour = [] + for (root, dirs, files) in os.walk(root_dir): + for f in files: + if f.endswith('png'): + r = root.split('/') + lr = len(r) + retour.append((f, r[lr - 2] + '/' + r[lr - 1], root)) + print('== Found %d items ' % len(retour)) + return retour + + +def index_classes(items): + idx = {} + for i in items: + if i[1] not in idx: + idx[i[1]] = len(idx) + print('== Found %d classes' % len(idx)) + return idx + + +class OmniglotNShot: + def __init__(self, root, batchsz, n_way, k_shot, k_query, imgsz, rng, device=None): + """ + Different from mnistNShot, the + :param root: + :param batchsz: task num + :param n_way: + :param k_shot: + :param k_qry: + :param imgsz: + """ + + self.resize = imgsz + self.rng = rng + self.device = device + if not os.path.isfile(os.path.join(root, 'omniglot.npy')): + # if root/data.npy does not exist, just download it + self.x = Omniglot( + root, + download=True, + transform=transforms.Compose( + [ + lambda x: Image.open(x).convert('L'), + lambda x: x.resize((imgsz, imgsz)), + lambda x: np.reshape(x, (imgsz, imgsz, 1)), + lambda x: np.transpose(x, [2, 0, 1]), + lambda x: x / 255.0, + ] + ), + ) + + # {label: [img1, img2..., img20], label2: [img1, img2, ...], ... 1623 labels in total} + temp = {} + for (img, label) in self.x: + if label in temp.keys(): + temp[label].append(img) + else: + temp[label] = [img] + + self.x = [] + for ( + label, + imgs, + ) in temp.items(): # labels info deserted , each label contains 20imgs + self.x.append(np.array(imgs)) + + # as different class may have different number of imgs + self.x = np.array(self.x).astype(np.float) # [[20 imgs],..., 1623 classes in total] + # each character contains 20 imgs + print('data shape:', self.x.shape) # [1623, 20, 84, 84, 1] + temp = [] # Free memory + # save all dataset into npy file. + np.save(os.path.join(root, 'omniglot.npy'), self.x) + print('write into omniglot.npy.') + else: + # if data.npy exists, just load it. + self.x = np.load(os.path.join(root, 'omniglot.npy')) + print('load from omniglot.npy.') + + # [1623, 20, 84, 84, 1] + # TODO: can not shuffle here, we must keep training and test set distinct! + self.x_train, self.x_test = self.x[:1200], self.x[1200:] + + # self.normalization() + + self.batchsz = batchsz + self.n_cls = self.x.shape[0] # 1623 + self.n_way = n_way # n way + self.k_shot = k_shot # k shot + self.k_query = k_query # k query + assert (k_shot + k_query) <= 20 + + # save pointer of current read batch in total cache + self.indexes = {'train': 0, 'test': 0} + self.datasets = { + 'train': self.x_train, + 'test': self.x_test, + } # original data cached + print('DB: train', self.x_train.shape, 'test', self.x_test.shape) + + self.datasets_cache = { + 'train': self.load_data_cache(self.datasets['train']), # current epoch data cached + 'test': self.load_data_cache(self.datasets['test']), + } + + def normalization(self): + """ + Normalizes our data, to have a mean of 0 and sdt of 1 + """ + self.mean = np.mean(self.x_train) + self.std = np.std(self.x_train) + self.max = np.max(self.x_train) + self.min = np.min(self.x_train) + # print("before norm:", "mean", self.mean, "max", self.max, "min", self.min, "std", self.std) + self.x_train = (self.x_train - self.mean) / self.std + self.x_test = (self.x_test - self.mean) / self.std + + self.mean = np.mean(self.x_train) + self.std = np.std(self.x_train) + self.max = np.max(self.x_train) + self.min = np.min(self.x_train) + + # print("after norm:", "mean", self.mean, "max", self.max, "min", self.min, "std", self.std) + + def load_data_cache(self, data_pack): + """ + Collects several batches data for N-shot learning + :param data_pack: [cls_num, 20, 84, 84, 1] + :return: A list with [support_set_x, support_set_y, target_x, target_y] ready to be fed to our networks + """ + + # take 5 way 1 shot as example: 5 * 1 + setsz = self.k_shot * self.n_way + querysz = self.k_query * self.n_way + data_cache = [] + + # print('preload next 50 caches of batchsz of batch.') + for sample in range(10): # num of episodes + + x_spts, y_spts, x_qrys, y_qrys = [], [], [], [] + for i in range(self.batchsz): # one batch means one set + + x_spt, y_spt, x_qry, y_qry = [], [], [], [] + selected_cls = self.rng.choice(data_pack.shape[0], self.n_way, False) + + for j, cur_class in enumerate(selected_cls): + + selected_img = self.rng.choice(20, self.k_shot + self.k_query, False) + + # meta-training and meta-test + x_spt.append(data_pack[cur_class][selected_img[: self.k_shot]]) + x_qry.append(data_pack[cur_class][selected_img[self.k_shot :]]) + y_spt.append([j for _ in range(self.k_shot)]) + y_qry.append([j for _ in range(self.k_query)]) + + # shuffle inside a batch + perm = self.rng.permutation(self.n_way * self.k_shot) + x_spt = np.array(x_spt).reshape( + self.n_way * self.k_shot, 1, self.resize, self.resize + )[perm] + y_spt = np.array(y_spt).reshape(self.n_way * self.k_shot)[perm] + perm = self.rng.permutation(self.n_way * self.k_query) + x_qry = np.array(x_qry).reshape( + self.n_way * self.k_query, 1, self.resize, self.resize + )[perm] + y_qry = np.array(y_qry).reshape(self.n_way * self.k_query)[perm] + + # append [sptsz, 1, 84, 84] => [b, setsz, 1, 84, 84] + x_spts.append(x_spt) + y_spts.append(y_spt) + x_qrys.append(x_qry) + y_qrys.append(y_qry) + + # [b, setsz, 1, 84, 84] + x_spts = np.array(x_spts, dtype=np.float32).reshape( + self.batchsz, setsz, 1, self.resize, self.resize + ) + y_spts = np.array(y_spts, dtype=np.int).reshape(self.batchsz, setsz) + # [b, qrysz, 1, 84, 84] + x_qrys = np.array(x_qrys, dtype=np.float32).reshape( + self.batchsz, querysz, 1, self.resize, self.resize + ) + y_qrys = np.array(y_qrys, dtype=np.int).reshape(self.batchsz, querysz) + + x_spts, y_spts, x_qrys, y_qrys = [ + torch.from_numpy(z).to(self.device) for z in [x_spts, y_spts, x_qrys, y_qrys] + ] + + data_cache.append([x_spts, y_spts, x_qrys, y_qrys]) + + return data_cache + + def next(self, mode='train'): + """ + Gets next batch from the dataset with name. + :param mode: The name of the splitting (one of "train", "val", "test") + :return: + """ + + # update cache if indexes is larger cached num + if self.indexes[mode] >= len(self.datasets_cache[mode]): + self.indexes[mode] = 0 + self.datasets_cache[mode] = self.load_data_cache(self.datasets[mode]) + + next_batch = self.datasets_cache[mode][self.indexes[mode]] + self.indexes[mode] += 1 + + return next_batch diff --git a/examples/few-shot/README.md b/examples/few-shot/README.md index d25eafc4..df6578f3 100644 --- a/examples/few-shot/README.md +++ b/examples/few-shot/README.md @@ -14,5 +14,5 @@ python3 maml_omniglot.py The figure illustrate the experimental result.
    - +
    diff --git a/examples/few-shot/maml-accs.png b/examples/few-shot/maml-accs.png index a3a0f4cea0c71bd1ad42c434f136ffc6e5d30fda..4a34be0a0357779928d9896def1a083a86f38dec 100644 GIT binary patch literal 151372 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
    W?eu4i-dxzu)N9&PQwy%0R&sCvG4 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

    CJ|12$n77`cpmlr=ByI4=|532cV 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 H{MY{j&4~>^ literal 33854 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 diff --git a/examples/few-shot/maml_omniglot.py b/examples/few-shot/maml_omniglot.py index 30b10559..0eafce01 100644 --- a/examples/few-shot/maml_omniglot.py +++ b/examples/few-shot/maml_omniglot.py @@ -75,11 +75,13 @@ def main(): torch.manual_seed(args.seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(args.seed) + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True np.random.seed(args.seed) rng = np.random.default_rng(args.seed) # Set up the Omniglot loader. - device = torch.device('cuda:0') + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') db = OmniglotNShot( '/tmp/omniglot-data', batchsz=args.task_num, @@ -114,9 +116,10 @@ def main(): meta_opt = optim.Adam(net.parameters(), lr=1e-3) log = [] + test(db, net, epoch=-1, log=log) for epoch in range(10): - train(db, net, meta_opt, epoch, log) - test(db, net, epoch, log) + train(db, net, meta_opt, epoch=epoch, log=log) + test(db, net, epoch=epoch, log=log) plot(log) @@ -257,15 +260,16 @@ def plot(log): # script but we are doing it here for brevity. df = pd.DataFrame(log) - fig, ax = plt.subplots(figsize=(6, 4)) + fig, ax = plt.subplots(figsize=(8, 4), dpi=250) train_df = df[df['mode'] == 'train'] test_df = df[df['mode'] == 'test'] ax.plot(train_df['epoch'], train_df['acc'], label='Train') ax.plot(test_df['epoch'], test_df['acc'], label='Test') ax.set_xlabel('Epoch') ax.set_ylabel('Accuracy') - ax.set_ylim(70, 100) - fig.legend(ncol=2, loc='lower right') + ax.set_ylim(85, 100) + ax.set_title('MAML Omniglot') + ax.legend(ncol=2, loc='lower right') fig.tight_layout() fname = 'maml-accs.png' print(f'--- Plotting accuracy to {fname}') diff --git a/tests/test_optimizer.py b/tests/test_optimizer.py deleted file mode 100644 index f8fff9a3..00000000 --- a/tests/test_optimizer.py +++ /dev/null @@ -1,420 +0,0 @@ -# Copyright 2022 MetaOPT Team. 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 typing import Callable, Tuple - -import functorch -import pytest -import torch -import torch.nn.functional as F - -import helpers -import torchopt - - -@helpers.parametrize( - dtype=[torch.float64, torch.float32], - lr=[1e-2, 1e-3, 1e-4], - momentum=[0.0, 0.1], - dampening=[0.0, 0.5], - nesterov=[False, True], - weight_decay=[0.0, 1e-2], - maximize=[False], # TODO: test maximize after PyTorch 1.13 -) -def test_SGD( - dtype: torch.dtype, - lr: float, - momentum: float, - dampening: float, - nesterov: bool, - weight_decay: float, - maximize: bool, -) -> None: - if nesterov and (momentum <= 0.0 or dampening != 0.0): - pytest.skip('Nesterov momentum requires a momentum and zero dampening.') - - model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) - - optim = torchopt.SGD( - model.parameters(), - lr, - momentum=momentum, - dampening=dampening, - nesterov=nesterov, - weight_decay=weight_decay, - maximize=maximize, - ) - optim_ref = torch.optim.SGD( - model_ref.parameters(), - lr, - momentum=momentum, - dampening=dampening, - nesterov=nesterov, - weight_decay=weight_decay, - maximize=maximize, - ) - - for xs, ys in loader: - xs = xs.to(dtype=dtype) - pred = model(xs) - pred_ref = model_ref(xs) - loss = F.cross_entropy(pred, ys) - loss_ref = F.cross_entropy(pred_ref, ys) - - optim.zero_grad() - loss.backward() - optim.step() - - optim_ref.zero_grad() - loss_ref.backward() - optim_ref.step() - - helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) - - -@helpers.parametrize( - dtype=[torch.float64], - lr=[1e-2, 1e-3, 1e-4], - betas=[(0.9, 0.999), (0.95, 0.9995)], - eps=[1e-8], - weight_decay=[0.0, 1e-2], - maximize=[False, True], -) -def test_Adam( - dtype: torch.dtype, - lr: float, - betas: Tuple[float, float], - eps: float, - weight_decay: float, - maximize: bool, -) -> None: - model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) - - optim = torchopt.Adam( - model.parameters(), - lr, - betas=betas, - eps=eps, - eps_root=0.0, - weight_decay=weight_decay, - maximize=maximize, - ) - optim_ref = torch.optim.Adam( - model_ref.parameters(), - lr, - betas=betas, - eps=eps, - amsgrad=False, - weight_decay=weight_decay, - maximize=maximize, - ) - - for xs, ys in loader: - xs = xs.to(dtype=dtype) - pred = model(xs) - pred_ref = model_ref(xs) - loss = F.cross_entropy(pred, ys) - loss_ref = F.cross_entropy(pred_ref, ys) - - optim.zero_grad() - loss.backward() - optim.step() - - optim_ref.zero_grad() - loss_ref.backward() - optim_ref.step() - - helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) - - -@helpers.parametrize( - dtype=[torch.float64], - lr=[1e-2, 1e-3, 1e-4], - betas=[(0.9, 0.999), (0.95, 0.9995)], - eps=[1e-8], - weight_decay=[1e-2, 1e-1], - maximize=[False, True], -) -def test_AdamW( - dtype: torch.dtype, - lr: float, - betas: Tuple[float, float], - eps: float, - weight_decay: float, - maximize: bool, -) -> None: - model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) - - optim = torchopt.AdamW( - model.parameters(), - lr, - betas=betas, - eps=eps, - eps_root=0.0, - weight_decay=weight_decay, - maximize=maximize, - ) - optim_ref = torch.optim.AdamW( - model_ref.parameters(), - lr, - betas=betas, - eps=eps, - amsgrad=False, - weight_decay=weight_decay, - maximize=maximize, - ) - - for xs, ys in loader: - xs = xs.to(dtype=dtype) - pred = model(xs) - pred_ref = model_ref(xs) - loss = F.cross_entropy(pred, ys) - loss_ref = F.cross_entropy(pred_ref, ys) - - optim.zero_grad() - loss.backward() - optim.step() - - optim_ref.zero_grad() - loss_ref.backward() - optim_ref.step() - - helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) - - -@helpers.parametrize( - dtype=[torch.float64], - lr=[1e-2, 1e-3, 1e-4], - betas=[(0.9, 0.999), (0.95, 0.9995)], - eps=[1e-8], - weight_decay=[0.0, 1e-2], - maximize=[False, True], -) -def test_Adam_accelerated_cpu( - dtype: torch.dtype, - lr: float, - betas: Tuple[float, float], - eps: float, - weight_decay: float, - maximize: bool, -) -> None: - model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) - - optim = torchopt.Adam( - model.parameters(), - lr, - betas=betas, - eps=eps, - eps_root=0.0, - weight_decay=weight_decay, - maximize=maximize, - use_accelerated_op=True, - ) - optim_ref = torch.optim.Adam( - model_ref.parameters(), - lr, - betas=betas, - eps=eps, - amsgrad=False, - weight_decay=weight_decay, - maximize=maximize, - ) - - for xs, ys in loader: - xs = xs.to(dtype=dtype) - pred = model(xs) - pred_ref = model_ref(xs) - loss = F.cross_entropy(pred, ys) - loss_ref = F.cross_entropy(pred_ref, ys) - - optim.zero_grad() - loss.backward() - optim.step() - - optim_ref.zero_grad() - loss_ref.backward() - optim_ref.step() - - helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) - - -@pytest.mark.skipif(not torch.cuda.is_available(), reason='No CUDA device available.') -@helpers.parametrize( - dtype=[torch.float64], - lr=[1e-2, 1e-3, 1e-4], - betas=[(0.9, 0.999), (0.95, 0.9995)], - eps=[1e-8], - weight_decay=[0.0, 1e-2], - maximize=[False, True], -) -def test_Adam_accelerated_cuda( - dtype: torch.dtype, - lr: float, - betas: Tuple[float, float], - eps: float, - weight_decay: float, - maximize: bool, -) -> None: - device = 'cuda' - model, model_ref, model_base, loader = helpers.get_models(device=device, dtype=dtype) - - optim = torchopt.Adam( - model.parameters(), - lr, - betas=betas, - eps=eps, - eps_root=0.0, - weight_decay=weight_decay, - maximize=maximize, - use_accelerated_op=True, - ) - optim_ref = torch.optim.Adam( - model_ref.parameters(), - lr, - betas=betas, - eps=eps, - amsgrad=False, - weight_decay=weight_decay, - maximize=maximize, - ) - - for xs, ys in loader: - xs = xs.to(device=device, dtype=dtype) - ys = ys.to(device=device) - pred = model(xs) - pred_ref = model_ref(xs) - loss = F.cross_entropy(pred, ys) - loss_ref = F.cross_entropy(pred_ref, ys) - - optim.zero_grad() - loss.backward() - optim.step() - - optim_ref.zero_grad() - loss_ref.backward() - optim_ref.step() - - helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) - - -@helpers.parametrize( - dtype=[torch.float64], - lr=[1e-2, 1e-3, 1e-4], - alpha=[0.9, 0.99], - eps=[1e-8], - momentum=[0.0, 0.1], - centered=[False, True], - weight_decay=[0.0, 1e-2], -) -def test_RMSProp( - dtype: torch.dtype, - lr: float, - alpha: float, - eps: float, - momentum: float, - centered: bool, - weight_decay: float, -) -> None: - model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) - - optim = torchopt.RMSProp( - model.parameters(), - lr, - alpha=alpha, - eps=eps, - momentum=momentum, - centered=centered, - nesterov=False, - weight_decay=weight_decay, - ) - optim_ref = torch.optim.RMSprop( - model_ref.parameters(), - lr, - alpha=alpha, - eps=eps, - momentum=momentum, - centered=centered, - weight_decay=weight_decay, - ) - - for xs, ys in loader: - xs = xs.to(dtype=dtype) - pred = model(xs) - pred_ref = model_ref(xs) - loss = F.cross_entropy(pred, ys) - loss_ref = F.cross_entropy(pred_ref, ys) - - optim.zero_grad() - loss.backward() - optim.step() - - optim_ref.zero_grad() - loss_ref.backward() - optim_ref.step() - - helpers.assert_model_all_close(model, model_ref, model_base, dtype=dtype) - - -@helpers.parametrize( - dtype=[torch.float64, torch.float32], - lr=[1e-2, 1e-3], - optimizers=[ - (torchopt.sgd, torch.optim.SGD), - (torchopt.adam, torch.optim.Adam), - (torchopt.adamw, torch.optim.AdamW), - (torchopt.rmsprop, torch.optim.RMSprop), - ], - inplace=[True, False], - weight_decay=[0.0, 1e-2], -) -def test_FuncOptimizer( - dtype: torch.dtype, - lr: float, - optimizers: Tuple[Callable, torch.optim.Optimizer], - inplace: bool, - weight_decay: float, -) -> None: - model, model_ref, model_base, loader = helpers.get_models(device='cpu', dtype=dtype) - - torchopt_optimizer, torch_optimizer = optimizers - - fmodel, params, buffers = functorch.make_functional_with_buffers(model) - optim = torchopt.FuncOptimizer( - torchopt_optimizer( - lr=lr, - weight_decay=weight_decay, - ), - inplace=inplace, - ) - optim_ref = torch_optimizer( - model_ref.parameters(), - lr, - weight_decay=weight_decay, - ) - - for xs, ys in loader: - xs = xs.to(dtype=dtype) - pred = fmodel(params, buffers, xs) - pred_ref = model_ref(xs) - loss = F.cross_entropy(pred, ys) - loss_ref = F.cross_entropy(pred_ref, ys) - - params = optim.step(loss, params) - - optim_ref.zero_grad() - loss_ref.backward() - optim_ref.step() - - helpers.assert_model_all_close((params, buffers), model_ref, model_base, dtype=dtype) diff --git a/torchopt/__init__.py b/torchopt/__init__.py index eeff87cc..deafcc55 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -17,6 +17,7 @@ from torchopt import ( clip, combine, + distributed, hook, implicit_diff, linalg, @@ -41,7 +42,13 @@ MetaSGD, ) from torchopt.update import apply_updates -from torchopt.utils import extract_state_dict, recover_state_dict, stop_gradient +from torchopt.utils import ( + extract_state_dict, + module_clone, + module_detach_, + recover_state_dict, + stop_gradient, +) from torchopt.version import __version__ @@ -70,4 +77,6 @@ 'extract_state_dict', 'recover_state_dict', 'stop_gradient', + 'module_clone', + 'module_detach_', ] diff --git a/torchopt/distributed/__init__.py b/torchopt/distributed/__init__.py new file mode 100644 index 00000000..d966691c --- /dev/null +++ b/torchopt/distributed/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Distributed utilities.""" + +import torch.distributed as dist +import torch.distributed.rpc as rpc + +from torchopt.distributed import api, autograd, world +from torchopt.distributed.api import * +from torchopt.distributed.world import * + + +__all__ = ['is_available', *api.__all__, *world.__all__] + + +def is_available(): + """Check if the distributed module is available.""" + return dist.is_available() and rpc.is_available() and autograd.is_available() diff --git a/torchopt/distributed/api.py b/torchopt/distributed/api.py new file mode 100644 index 00000000..000228db --- /dev/null +++ b/torchopt/distributed/api.py @@ -0,0 +1,471 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Distributed APIs.""" + +import functools +import sys +from typing import ( + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Sequence, + Tuple, + TypeVar, + Union, + cast, +) + +import torch +import torch.distributed.rpc as rpc + +import torchopt.pytree as pytree +from torchopt.distributed.world import get_worker_id, get_world_rank, get_world_size +from torchopt.typing import Future, PyTree + + +__all__ = [ + 'TensorDimensionPartitioner', + 'dim_partitioner', + 'batch_partitioner', + 'mean_reducer', + 'sum_reducer', + 'remote_async_call', + 'remote_sync_call', + 'parallelize', + 'parallelize_async', + 'parallelize_sync', +] + + +UNSET_RPC_TIMEOUT = rpc.api.UNSET_RPC_TIMEOUT + + +T = TypeVar('T') +U = TypeVar('U') +Args = Tuple[Any, ...] +KwArgs = Dict[str, Any] +PartitionFunction = Callable[..., Sequence[Tuple[int, Optional[Args], Optional[KwArgs]]]] +Partitioner = Union[int, str, PartitionFunction] + + +class TensorDimensionPartitioner: + """Partitioner class that partitions a batch of inputs along a given dimension. + + All tensors in the ``args`` and ``kwargs`` will be partitioned along the dimension ``dim``, + while the non-tensor values will be broadcasted to partitions. + + Args: + dim: The dimension to partition. + exclusive: Whether to partition the batch exclusively. + If :data:`True`, the batch will be partitioned into ``batch_size`` partitions, where + ``batch_size`` is the size of the batch along the given dimension. Each batch sample + will be assigned to a separate RPC call. + If :data:`False`, the batch will be partitioned into ``min(batch_size, num_workers)`` + partitions, where ``num_workers`` is the number of workers in the world. When + ``batch_size > num_workers``, there can be multiple batch samples forward in a single + RPC call. + keepdim: Whether to keep the partitioned dimension. Defaults to :data:`True`, i.e., keep the + batch dimension. If :data:`False`, use select instead of slicing. This functionality + should be used with ``exclusive=True``. + workers: The workers to partition the batch to. If :data:`None`, the batch will be + partitioned to all workers in the world. + """ + + def __init__( + self, + dim: int, + *, + exclusive: bool = False, + keepdim: bool = False, + workers: Optional[Sequence[Union[int, str]]] = None, + ) -> None: + """Initialize the partitioner instance.""" + if not keepdim and not exclusive: + raise ValueError('keepdim=False should be used with exclusive=True.') + + self.dim = dim + self.exclusive = exclusive + self.keepdim = keepdim + self.workers = workers + + # pylint: disable-next=too-many-branches,too-many-locals + def __call__( + self, + *args: Any, + **kwargs: Any, + ) -> List[Tuple[int, Optional[Args], Optional[KwArgs]]]: + """Partition the batch of inputs along the given dimension.""" + if self.workers is None: + workers = list(range(get_world_size())) + else: + workers = list(map(get_worker_id, self.workers)) + num_workers = len(workers) + + args_tree = cast(PyTree[Any], (args, kwargs)) + flattened_args, treedef = pytree.tree_flatten(args_tree) + + batch_size = None + for arg in flattened_args: + if isinstance(arg, torch.Tensor): + if batch_size is None: + batch_size = arg.shape[self.dim] + elif batch_size != arg.shape[self.dim]: # type: ignore[unreachable] + raise ValueError( + f'Batch size mismatch on dim={self.dim}. ' + f'Expected {batch_size}, got {arg.shape[self.dim]} (shape: {arg.shape}).' + ) + + if batch_size is None: + return [(get_world_rank(), args, kwargs.copy())] + + dim_slices: List[Union[int, slice]] + # pylint: disable-next=line-too-long + batch_slices: List[Tuple[Union[int, slice, Ellipsis.__class__], ...]] # type: ignore[name-defined] + if self.exclusive: + num_replicas = batch_size + if self.keepdim: + dim_slices = [slice(i, i + 1) for i in range(num_replicas)] + else: + dim_slices = list(range(num_replicas)) + else: + if batch_size <= num_workers: + num_replicas = batch_size + dim_slices = [slice(i, i + 1) for i in range(batch_size)] # keepdim=True + else: + num_replicas = num_workers + local_size = batch_size // num_workers + local_batch_indices = [i * local_size for i in range(num_workers)] + [batch_size] + dim_slices = [ + slice(local_batch_indices[i], local_batch_indices[i + 1]) + for i in range(num_workers) + ] + + if self.dim >= 0: + batch_slices = [ + (slice(None, None),) * self.dim + (dim_slice,) for dim_slice in dim_slices + ] + elif self.dim < 0: + batch_slices = [ + ( + ..., + dim_slice, + ) + + (slice(None, None),) * (-self.dim - 1) + for dim_slice in dim_slices + ] + + flattened_args_replicas: List[List[Any]] = [[] for _ in range(num_replicas)] + for arg in flattened_args: + if isinstance(arg, torch.Tensor): + for i, batch_slice in enumerate(batch_slices): + flattened_args_replicas[i].append(arg[batch_slice]) + else: + for i in range(num_replicas): + flattened_args_replicas[i].append(arg) + + args_replicas: List[Tuple[Args, KwArgs]] = [ + pytree.tree_unflatten(treedef, args_replica) # type: ignore[misc] + for args_replica in flattened_args_replicas + ] + + return [ + (workers[i % num_workers], worker_args, worker_kwargs) + for i, (worker_args, worker_kwargs) in enumerate(args_replicas) + ] + + def __reduce__( + self, + ) -> Tuple[ + Callable[..., 'TensorDimensionPartitioner'], + Tuple[int], + Dict[str, Union[bool, Optional[Sequence[Union[int, str]]]]], + ]: + """Return a tuple that allows the partitioner to be pickled.""" + return ( + TensorDimensionPartitioner, + (self.dim,), + dict(exclusive=self.exclusive, keepdim=self.keepdim, workers=self.workers), + ) + + +def dim_partitioner( + dim: int = 0, + *, + exclusive: bool = False, + keepdim: bool = True, + workers: Optional[Sequence[Union[int, str]]] = None, +) -> PartitionFunction: + """Partition a batch of inputs along a given dimension. + + All tensors in the ``args`` and ``kwargs`` will be partitioned along the dimension ``dim``, + while the non-tensor values will be broadcasted to partitions. + + Args: + dim: The dimension to partition. + exclusive: Whether to partition the batch exclusively. + If :data:`True`, the batch will be partitioned into ``batch_size`` partitions, where + ``batch_size`` is the size of the batch along the given dimension. Each batch sample + will be assigned to a separate RPC call. + If :data:`False`, the batch will be partitioned into ``min(batch_size, num_workers)`` + partitions, where ``num_workers`` is the number of workers in the world. When + ``batch_size > num_workers``, there can be multiple batch samples forward in a single + RPC call. + keepdim: Whether to keep the partitioned dimension. Defaults to :data:`True`, i.e., keep the + batch dimension. If :data:`False`, use select instead of slicing. This functionality + should be used with ``exclusive=True``. + workers: The workers to partition the batch to. If :data:`None`, the batch will be + partitioned to all workers in the world. + + Returns: + A partition function. + """ + return TensorDimensionPartitioner(dim, exclusive=exclusive, keepdim=keepdim, workers=workers) + + +# fmt: off +# pylint: disable=line-too-long +batch_partitioner: PartitionFunction = dim_partitioner(dim=0, keepdim=True, exclusive=False) +"""Partitioner for batch dimension. Divide and replicates the arguments to all workers along the first dimension. + +The batch will be partitioned into ``min(batch_size, num_workers)`` partitions, where +``num_workers`` is the number of workers in the world. +When ``batch_size > num_workers``, there can be multiple batch samples forward in a single RPC call. + +All tensors in the ``args`` and ``kwargs`` will be partitioned along the dimension ``dim``, +while the non-tensor values will be broadcasted to partitions. +""" +exclusive_batch_partitioner: PartitionFunction = dim_partitioner(dim=0, keepdim=True, exclusive=True) +"""Partitioner for batch dimension. Divide and replicates the arguments to all workers along the first dimension. + +Each batch sample will be assigned to a separate RPC call. + +All tensors in the ``args`` and ``kwargs`` will be partitioned along the dimension ``dim``, +while the non-tensor values will be broadcasted to partitions. +""" +# pylint: enable=line-too-long +# fmt: on + + +def mean_reducer(results: Iterable[torch.Tensor]) -> torch.Tensor: + """Reduce the results by averaging them.""" + return torch.mean(torch.stack(tuple(results), dim=0), dim=0) + + +def sum_reducer(results: Iterable[torch.Tensor]) -> torch.Tensor: + """Reduce the results by summing them.""" + return torch.sum(torch.stack(tuple(results), dim=0), dim=0) + + +def remote_async_call( + func: Callable[..., T], + *, + args: Optional[Args] = None, + kwargs: Optional[KwArgs] = None, + partitioner: Partitioner = batch_partitioner, + reducer: Optional[Callable[[Iterable[T]], U]] = None, + timeout: Optional[float] = UNSET_RPC_TIMEOUT, +) -> Union[Future[List[T]], Future[U]]: + # pylint: disable=line-too-long + """Asynchronously do an RPC on remote workers and return the a :class:`torch.Future` instance at the current worker. + + Args: + func (Callable[..., T]): The function to call. + args (Optional[Args], optional): The arguments to pass to the function. Defaults to + :data:`None`. + kwargs (Optional[KwArgs], optional): The keyword arguments to pass to the function. Defaults + to :data:`None`. + partitioner (Partitioner, optional): A partitioner that partitions the arguments to multiple + workers. Defaults to :func:`batch_partitioner`. + reducer (Callable[[Iterable[T]], U], optional): A reducer that reduces the results from + multiple workers. Defaults to :data:`None`. + timeout (float, optional): The timeout for the RPC call. Defaults to + :data:`rpc.api.UNSET_RPC_TIMEOUT`. + + Returns: + A :class:`torch.Future` instance for the result. The result is at the current worker. + """ + if args is None: + args = () + if kwargs is None: + kwargs = {} + if isinstance(partitioner, (int, str)): + partitions = [(get_worker_id(id=partitioner), args, kwargs)] + elif callable(partitioner): + partitions = partitioner(*args, **kwargs) # type: ignore[assignment] + else: + raise ValueError(f'Invalid partitioner: {partitioner!r}.') + + futures = [] + for rank, worker_args, worker_kwargs in partitions: + fut = rpc.rpc_async(rank, func, args=worker_args, kwargs=worker_kwargs, timeout=timeout) + futures.append(fut) + + future = cast( + Future[List[T]], + torch.futures.collect_all(futures).then(lambda fut: [f.wait() for f in fut.wait()]), + ) + if reducer is not None: + return cast( + Future[U], + future.then(lambda fut: cast(Callable[[Iterable[T]], U], reducer)(fut.wait())), + ) + return future + + +def remote_sync_call( + func: Callable[..., T], + *, + args: Optional[Args] = None, + kwargs: Optional[KwArgs] = None, + partitioner: Partitioner = batch_partitioner, + reducer: Optional[Callable[[Iterable[T]], U]] = None, + timeout: Optional[float] = UNSET_RPC_TIMEOUT, +) -> Union[List[T], U]: + """Synchronously do an RPC on remote workers and return the result to the current worker. + + Args: + func (Callable[..., T]): The function to call. + args (Optional[Args], optional): The arguments to pass to the function. Defaults to + :data:`None`. + kwargs (Optional[KwArgs], optional): The keyword arguments to pass to the function. Defaults + to :data:`None`. + partitioner (Partitioner, optional): A partitioner that partitions the arguments to multiple + workers. Defaults to :func:`batch_partitioner`. + reducer (Callable[[Iterable[T]], U], optional): A reducer that reduces the results from + multiple workers. Defaults to :data:`None`. + timeout (float, optional): The timeout for the RPC call. Defaults to + :data:`rpc.api.UNSET_RPC_TIMEOUT`. + + Returns: + The result of the RPC call. The result is at the current worker. + """ + return remote_async_call( + func, + args=args, + kwargs=kwargs, + partitioner=partitioner, + timeout=timeout, + reducer=reducer, + ).wait() + + +def parallelize_async( + partitioner: Partitioner = batch_partitioner, + reducer: Optional[Callable[[Iterable[T]], U]] = None, + timeout: Optional[float] = UNSET_RPC_TIMEOUT, +) -> Callable[[Callable[..., T]], Callable[..., Union[Future[List[T]], Future[U]]]]: + """Decorator for parallelizing a function. + + This decorator can be used to parallelize a function call across multiple workers. The + function will be called asynchronously on remote workers. The decorated function will + return a :class:`torch.Future` instance of the result. + + Args: + partitioner (Partitioner, optional): A partitioner that partitions the arguments to multiple + workers. Defaults to :func:`batch_partitioner`. + reducer (Callable[[Iterable[T]], U], optional): A reducer that reduces the results from + multiple workers. Defaults to :data:`None`. + timeout (float, optional): The timeout for the RPC call. Defaults to + :data:`rpc.api.UNSET_RPC_TIMEOUT`. + + Returns: + The decorated function. + """ + + def wrapper(func: Callable[..., T]) -> Callable[..., Union[Future[List[T]], Future[U]]]: + @functools.wraps(func) + def wrapped(*args: Any, **kwargs: Any) -> Union[Future[List[T]], Future[U]]: + return remote_async_call( + func, + args=args, + kwargs=kwargs, + partitioner=partitioner, + reducer=reducer, + timeout=timeout, + ) + + suffix = '__parallelize_async_unwrapped__' + module_name = func.__module__ + try: + name = func.__qualname__ + except AttributeError: + name = func.__name__ + else: + func.__qualname__ = f'{func.__qualname__}{suffix}' + func.__name__ = f'{func.__name__}{suffix}' + __import__(module_name, level=0) + module = sys.modules[module_name] + setattr(module, f'{name}{suffix}', func) + + return wrapped + + return wrapper + + +def parallelize( + partitioner: Partitioner = batch_partitioner, + reducer: Optional[Callable[[Iterable[T]], U]] = None, + timeout: Optional[float] = UNSET_RPC_TIMEOUT, +) -> Callable[[Callable[..., T]], Callable[..., Union[List[T], U]]]: + """Decorator for parallelizing a function. + + This decorator can be used to parallelize a function call across multiple workers. + + Args: + partitioner (Partitioner, optional): A partitioner that partitions the arguments to multiple + workers. Defaults to :func:`batch_partitioner`. + reducer (Callable[[Iterable[T]], U], optional): A reducer that reduces the results from + multiple workers. Defaults to :data:`None`. + timeout (float, optional): The timeout for the RPC call. Defaults to + :data:`rpc.api.UNSET_RPC_TIMEOUT`. + + Returns: + The decorated function. + """ + + def wrapper(func: Callable[..., T]) -> Callable[..., Union[List[T], U]]: + @functools.wraps(func) + def wrapped(*args: Any, **kwargs: Any) -> Union[List[T], U]: + return remote_sync_call( + func, + args=args, + kwargs=kwargs, + partitioner=partitioner, + reducer=reducer, + timeout=timeout, + ) + + suffix = '__parallelize_unwrapped__' + module_name = func.__module__ + try: + name = func.__qualname__ + except AttributeError: + name = func.__name__ + else: + func.__qualname__ = f'{func.__qualname__}{suffix}' + func.__name__ = f'{func.__name__}{suffix}' + __import__(module_name, level=0) + module = sys.modules[module_name] + setattr(module, f'{name}{suffix}', func) + + return wrapped + + return wrapper + + +parallelize_sync = parallelize diff --git a/torchopt/distributed/autograd.py b/torchopt/distributed/autograd.py new file mode 100644 index 00000000..65442931 --- /dev/null +++ b/torchopt/distributed/autograd.py @@ -0,0 +1,129 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Distributed Autograd.""" + +from threading import Lock +from typing import Optional, Sequence, Tuple, Union + +import torch +import torch.distributed.autograd as autograd +from torch.distributed.autograd import context + + +__all__ = ['is_available', 'context'] + + +LOCK = Lock() + + +def is_available(): + """Check if distributed autograd module is available.""" + return autograd.is_available() + + +if is_available(): + # pylint: disable-next=unused-import + from torch.distributed.autograd import DistAutogradContext, get_gradients + + def backward( + autograd_ctx_id: int, + tensors: Union[torch.Tensor, Sequence[torch.Tensor]], + retain_graph: bool = False, + inputs: Optional[Union[torch.Tensor, Sequence[torch.Tensor]]] = None, + ) -> None: + """Perform distributed backward pass for local parameters. + + Computes the sum of gradients of given tensors with respect to graph leaves. + + Args: + autograd_ctx_id: The autograd context id. + tensors (Sequence[Tensor] or Tensor): Tensors of which the derivative will be computed. + retain_graph (bool, optional): If :data:`False`, the graph used to compute the grad will + be freed. Note that in nearly all cases setting this option to :data:`True` is not + needed and often can be worked around in a much more efficient way. + inputs (Sequence[Tensor] or Tensor, optional): Inputs w.r.t. which the gradient be will + accumulated into ``.grad``. All other Tensors will be ignored. If not provided, the + gradient is accumulated into all the leaf Tensors that were used to compute the + attr::tensors. + """ + if inputs is not None: + if isinstance(inputs, torch.Tensor): + inputs = (inputs,) + elif len(inputs) == 0: + raise RuntimeError("'inputs' argument to backward() cannot be empty.") + else: + inputs = tuple(inputs) + if not all(map(lambda t: t.requires_grad, inputs)): + raise RuntimeError('One of the differentiated Tensors does not require grad') + + roots = [tensors] if isinstance(tensors, torch.Tensor) else list(tensors) + autograd.backward(autograd_ctx_id, roots=roots, retain_graph=retain_graph) + + all_local_grads = autograd.get_gradients(autograd_ctx_id) + if inputs is not None: + inputs = set(inputs) # type: ignore[assignment] + all_local_grads = {p: g for p, g in all_local_grads.items() if p in inputs} + + with LOCK: + for p, g in all_local_grads.items(): + if getattr(p, 'grad', None) is not None: + p.grad = p.grad.add(g) + else: + p.grad = g + + def grad( + autograd_ctx_id: int, + outputs: Union[torch.Tensor, Sequence[torch.Tensor]], + inputs: Union[torch.Tensor, Sequence[torch.Tensor]], + retain_graph: bool = False, + allow_unused: bool = False, + ) -> Tuple[torch.Tensor, ...]: + """Computes and returns the sum of gradients of outputs with respect to the inputs. + + Args: + autograd_ctx_id: The autograd context id. + outputs (sequence of Tensor): outputs of the differentiated function. + inputs (sequence of Tensor): Inputs w.r.t. which the gradient will be returned (and not + accumulated into ``.grad``). + retain_graph (bool, optional): If :data:`False`, the graph used to compute the grad will + be freed. Note that in nearly all cases setting this option to :data:`True` is not + needed and often can be worked around in a much more efficient way. + allow_unused (bool, optional): If :data:`False`, specifying inputs that were not used + when computing outputs (and therefore their grad is always zero) is an error. + Defaults to :data:`False`. + """ + outputs = [outputs] if isinstance(outputs, torch.Tensor) else list(outputs) + inputs = (inputs,) if isinstance(inputs, torch.Tensor) else tuple(inputs) + if not all(map(lambda t: t.requires_grad, inputs)): + raise RuntimeError('One of the differentiated Tensors does not require grad') + + autograd.backward(autograd_ctx_id, roots=outputs, retain_graph=retain_graph) + + all_local_grads = autograd.get_gradients(autograd_ctx_id) + grads = [] + for p in inputs: + try: + grads.append(all_local_grads[p]) + except KeyError as ex: + if not allow_unused: + raise RuntimeError( + 'One of the differentiated Tensors appears to not have been used in the ' + 'graph. Set allow_unused=True if this is the desired behavior.' + ) from ex + grads.append(None) # type: ignore[arg-type] + + return tuple(grads) + + __all__.extend(['DistAutogradContext', 'get_gradients', 'backward', 'grad']) diff --git a/torchopt/distributed/world.py b/torchopt/distributed/world.py new file mode 100644 index 00000000..9f67cb66 --- /dev/null +++ b/torchopt/distributed/world.py @@ -0,0 +1,228 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Utilities for gathering information about the world.""" + +import atexit +import functools +import os +from typing import Any, Callable, Iterable, NamedTuple, Optional, TypeVar, Union + +import torch.distributed.rpc as rpc +from torch.distributed.elastic.multiprocessing.errors import record + + +__all__ = [ + 'get_world_info', + 'get_world_rank', + 'get_rank', + 'get_world_size', + 'get_local_rank', + 'get_local_world_size', + 'get_worker_id', + 'barrier', + 'auto_init_rpc', + 'on_rank', + 'not_on_rank', + 'rank_zero_only', + 'rank_non_zero_only', +] + + +def default_worker_name_format( + world_rank: int, + world_size: int, + local_rank: int, # pylint: disable=unused-argument + local_world_size: int, # pylint: disable=unused-argument +) -> str: + """Default worker name format.""" + return f'worker{world_rank:0{len(str(world_size))}d}' + + +F = TypeVar('F', bound=Callable[..., Any]) +_WORKER_NAME_FORMAT: Callable[..., str] = default_worker_name_format + + +class WorldInfo(NamedTuple): + """Information about the world.""" + + world_rank: int + world_size: int + local_rank: int + local_world_size: int + + @property + def rank(self) -> int: + """The global world rank of the current worker.""" + return self.world_rank + + @property + def worker_name(self) -> str: + """The name of the current worker.""" + return _WORKER_NAME_FORMAT( + world_rank=self.world_rank, + world_size=self.world_size, + local_rank=self.local_rank, + local_world_size=self.local_world_size, + ) + + +def get_world_info() -> WorldInfo: + """Get the world information.""" + world_info = getattr(get_world_info, 'world_info', None) + + if world_info is None: + world_rank = int(os.getenv('RANK', '0')) + world_size = int(os.getenv('WORLD_SIZE', '1')) + local_rank = int(os.getenv('LOCAL_RANK', '0')) + local_world_size = int(os.getenv('LOCAL_WORLD_SIZE', '1')) + world_info = WorldInfo(world_rank, world_size, local_rank, local_world_size) + # pylint: disable=line-too-long + get_world_info.world_info = get_world_info.WORLD_INFO = world_info # type: ignore[attr-defined] + get_world_info.world_rank = get_world_info.WORLD_RANK = world_rank # type: ignore[attr-defined] + get_world_info.rank = get_world_info.RANK = world_rank # type: ignore[attr-defined] + get_world_info.world_size = get_world_info.WORLD_SIZE = world_size # type: ignore[attr-defined] + get_world_info.local_rank = get_world_info.LOCAL_RANK = local_rank # type: ignore[attr-defined] + get_world_info.local_world_size = get_world_info.LOCAL_WORLD_SIZE = local_world_size # type: ignore[attr-defined] + # pylint: enable=line-too-long + + return world_info + + +def get_world_rank() -> int: + """Get the global world rank of the current worker.""" + return get_world_info().world_rank + + +get_rank = get_world_rank + + +def get_world_size() -> int: + """Get the world size.""" + return get_world_info().world_size + + +def get_local_rank() -> int: + """Get the local rank of the current worker on the current node.""" + return get_world_info().local_rank + + +def get_local_world_size() -> int: + """Get the local world size on the current node.""" + return get_world_info().local_world_size + + +get_world_info() + + +# pylint: disable-next=redefined-builtin,invalid-name +def get_worker_id(id: Optional[Union[str, int]] = None) -> int: + """Get the worker id from the given id.""" + if isinstance(id, int): + return id + return rpc.get_worker_info(worker_name=id).id + + +def barrier(worker_names: Optional[Iterable[str]] = None) -> None: + r"""Synchronizes local and remote RPC processes. + + This will block until all local and remote RPC processes specified under worker_names + reach this method to wait for all outstanding work to complete. + + Args: + worker_names: The set of workers to synchronize. If :data:`None`, all workers. + """ + worker_names = {} if worker_names is None else set(worker_names) + rpc.api._barrier(worker_names) # pylint: disable=protected-access + + +def auto_init_rpc( + worker_init_fn: Optional[Callable[[], None]] = None, + worker_name_format: Callable[..., str] = default_worker_name_format, + *, + backend: Optional[rpc.BackendType] = None, + rpc_backend_options: Optional[rpc.RpcBackendOptions] = None, +) -> Callable[[F], F]: + """Decorator to automatically initialize RPC on the decorated function.""" + global _WORKER_NAME_FORMAT # pylint: disable=global-statement + _WORKER_NAME_FORMAT = worker_name_format + + def wrapper(func: F) -> F: + world_info = get_world_info() + + @record + @functools.wraps(func) + def wrapped(*args, **kwargs): + rpc.init_rpc( + name=world_info.worker_name, + rank=world_info.rank, + world_size=world_info.world_size, + backend=backend, + rpc_backend_options=rpc_backend_options, + ) + atexit.register(rpc.shutdown, graceful=True) + if worker_init_fn is not None: + barrier() + worker_init_fn() + barrier() + return func(*args, **kwargs) + + return wrapped # type: ignore[return-value] + + return wrapper + + +def __on_ranks(ranks: Iterable[int], inverse: bool = False) -> Callable[[F], F]: + ranks = frozenset(ranks) + + def wrapper(func: F) -> F: + world_rank = get_world_info().world_rank + + @functools.wraps(func) + def wrapped(*args, **kwargs): + if inverse: + if world_rank not in ranks: + return func(*args, **kwargs) + elif world_rank in ranks: + return func(*args, **kwargs) + return None + + return wrapped # type: ignore[return-value] + + return wrapper + + +def on_rank(*ranks: int) -> Callable[[F], F]: + """Decorator to mark a function to be executed only on given ranks.""" + return __on_ranks(ranks=ranks, inverse=False) + + +def not_on_rank(*ranks) -> Callable[[F], F]: + """Decorator to mark a function to be executed only on non given ranks.""" + return __on_ranks(ranks=ranks, inverse=True) + + +def rank_all(func: F) -> F: + """Decorator to mark a function to be executed on all ranks.""" + return func + + +def rank_zero_only(func: F) -> F: + """Decorator to mark a function to be executed only on rank zero.""" + return on_rank(0)(func) + + +def rank_non_zero_only(func: F) -> F: + """Decorator to mark a function to be executed only on non rank zero.""" + return not_on_rank(0)(func) diff --git a/torchopt/pytree.py b/torchopt/pytree.py index 1d0fabea..2b25b027 100644 --- a/torchopt/pytree.py +++ b/torchopt/pytree.py @@ -16,9 +16,47 @@ import optree import optree.typing as typing # pylint: disable=unused-import +import torch.distributed.rpc as rpc from optree import * # pylint: disable=wildcard-import,unused-wildcard-import +from torchopt.typing import Future, PyTree, RRef, T -__all__ = optree.__all__.copy() -del optree +__all__ = [*optree.__all__, 'tree_wait'] + + +def tree_wait(future_tree: PyTree[Future[T]]) -> PyTree[T]: + r"""Convert a tree of :class:`Future`\s to a tree of results.""" + import torch # pylint: disable=import-outside-toplevel + + futures, treedef = tree_flatten(future_tree) + + results = torch.futures.wait_all(futures) + + return tree_unflatten(treedef, results) + + +if rpc.is_available(): + + def tree_as_rref(tree: PyTree[T]) -> 'PyTree[RRef[T]]': + r"""Convert a tree of local objects to a tree of :class:`RRef`\s.""" + # pylint: disable-next=import-outside-toplevel,redefined-outer-name,reimported + from torch.distributed.rpc import RRef + + return tree_map(RRef, tree) + + def tree_to_here( + rref_tree: 'PyTree[RRef[T]]', + timeout: float = rpc.api.UNSET_RPC_TIMEOUT, + ) -> PyTree[T]: + r"""Convert a tree of :class:`RRef`\s to a tree of local objects.""" + return tree_map(lambda x: x.to_here(timeout=timeout), rref_tree) + + def tree_local_value(rref_tree: 'PyTree[RRef[T]]'): + r"""Return the local value of a tree of :class:`RRef`\s.""" + return tree_map(lambda x: x.local_value(), rref_tree) + + __all__.extend(['tree_as_rref', 'tree_to_here']) + + +del optree, rpc, PyTree, T, RRef diff --git a/torchopt/typing.py b/torchopt/typing.py index 3680ba2a..440b78b1 100644 --- a/torchopt/typing.py +++ b/torchopt/typing.py @@ -16,8 +16,10 @@ from typing import Callable, Optional, TypeVar, Union +import torch.distributed.rpc as rpc from optree.typing import PyTree from torch import Tensor +from torch.futures import Future from torchopt.base import ChainedGradientTransformation, EmptyState, GradientTransformation @@ -43,6 +45,7 @@ 'Tensor', 'TensorTree', 'OptionalTensorTree', + 'Future', ] T = TypeVar('T') @@ -60,3 +63,10 @@ Params: TypeAlias = TensorTree Updates: TypeAlias = Params # Gradient updates are of the same type as parameters. OptState: TypeAlias = TensorTree # States are arbitrary nests of `torch.Tensor`. + +if rpc.is_available(): + from torch.distributed.rpc import RRef # pylint: disable=ungrouped-imports,unused-import + + __all__.extend(['RRef']) +else: + RRef = None # type: ignore[misc,assignment] # pylint: disable=invalid-name diff --git a/torchopt/utils.py b/torchopt/utils.py index 58e632fc..8f7c2f62 100644 --- a/torchopt/utils.py +++ b/torchopt/utils.py @@ -38,6 +38,8 @@ 'stop_gradient', 'extract_state_dict', 'recover_state_dict', + 'module_clone', + 'module_detach_', ] @@ -271,3 +273,93 @@ def recover_state_dict( target.load_state_dict(state) else: raise RuntimeError(f'Unexpected class of {target}') + + +def module_clone( + target: Union[TensorTree, nn.Module, 'MetaOptimizer'], + *, + by: Literal['reference', 'copy', 'deepcopy'] = 'reference', # type: ignore[name-defined] + device: Optional[Union[int, str, torch.device]] = None, +) -> Union[TensorTree, nn.Module, 'MetaOptimizer']: + """Clone a module. + + Args: + target: The target to be cloned. + by: The extract policy of tensors in the target. + - :const:`'reference'`: The extracted tensors will be references to the original + tensors. + - :const:`'copy'`: The extracted tensors will be clones of the original tensors. This + makes the copied tensors have :attr:`grad_fn` to be a ```` function + points to the original tensors. + - :const:`'deepcopy'`: The extracted tensors will be deep-copied from the original + tensors. The deep-copied tensors will detach from the original computation graph. + device: If specified, move the cloned module to the specified device. + + Returns: + The cloned module. + """ + assert by in ('reference', 'copy', 'deepcopy', 'clone', 'deepclone') + by = by.replace('clone', 'copy') + if device is not None: + device = torch.device(device) + + # pylint: disable=import-outside-toplevel + import copy + + from torchopt.optim.meta.base import MetaOptimizer + + if isinstance(target, (nn.Module, MetaOptimizer)): + cloned = copy.deepcopy(target) + recover_state_dict(cloned, extract_state_dict(target, by=by, device=device)) + return cloned + + # Tree of tensors + if by == 'reference': + if device is not None: + + def replicate(t): + return t.to(device=device) + + else: + + def replicate(t): + return t + + elif by == 'copy': + if device is not None: + + def replicate(t): + return t.clone().to(device=device) + + else: + + def replicate(t): + return t.clone() + + else: + if device is not None: + + def replicate(t): + return t.clone().detach_().to(device=device).requires_grad_(t.requires_grad) + + else: + + def replicate(t): + return t.clone().detach_().requires_grad_(t.requires_grad) + + return pytree.tree_map(replicate, cast(TensorTree, target)) + + +def module_detach_( + target: Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer'] +) -> Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer']: + """Detach a module from the computation graph. + + Args: + target: The target to be detached. + + Returns: + The detached module. + """ + stop_gradient(target) + return target From 87f1af5141d853dd8a17fa40f14a928a913a772f Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 8 Oct 2022 17:43:46 +0800 Subject: [PATCH 23/69] fix(examples): align results of distributed examples (#95) --- CHANGELOG.md | 1 + README.md | 6 +- conda-recipe.yaml | 2 +- docs/source/examples/MAML.rst | 18 +- examples/L2R/l2r.py | 22 +- examples/LOLA/helper/agent.py | 2 +- examples/LOLA/lola_dice.py | 4 +- examples/distributed/few-shot/maml-accs.png | Bin 157986 -> 158491 bytes .../distributed/few-shot/maml_omniglot.py | 10 +- .../few-shot/maml_omniglot_local_loader.py | 9 +- examples/few-shot/maml-accs.png | Bin 151372 -> 150134 bytes examples/few-shot/maml_omniglot.py | 21 +- pyproject.toml | 3 +- tests/requirements.txt | 2 +- torchopt/distributed/api.py | 28 +- torchopt/distributed/autograd.py | 2 +- torchopt/optim/base.py | 29 +- torchopt/optim/meta/base.py | 6 +- torchopt/transform.py | 10 +- torchopt/utils.py | 332 +++-- tutorials/3_Meta_Optimizer.ipynb | 1109 +---------------- 21 files changed, 347 insertions(+), 1269 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d86f2f8..33e97795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Align results of distributed examples by [@XuehaiPan](https://github.com/XuehaiPan) in [#95](https://github.com/metaopt/torchopt/pull/95). - Fix `None` in module containers by [@XuehaiPan](https://github.com/XuehaiPan). - Fix backward errors when using inplace `sqrt_` and `add_` by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan). - Fix LR scheduling by [@XuehaiPan](https://github.com/XuehaiPan) in [#76](https://github.com/metaopt/torchopt/pull/76). diff --git a/README.md b/README.md index 6cab6423..3af9d667 100644 --- a/README.md +++ b/README.md @@ -154,8 +154,8 @@ outer_optim = torchopt.Adam(net.parameters()) for train_iter in range(train_iters): outer_loss = 0 - for task in range(tasks): - loader = Loader(tasks) + for task in range(num_tasks): + loader = Loader(num_tasks) # Store states at the initial points net_state = torchopt.extract_state_dict(net) # extract state @@ -176,7 +176,7 @@ for train_iter in range(train_iters): torchopt.recover_state_dict(inner_optim, optim_state) torchopt.recover_state_dict(net, net_state) - outer_loss = outer_loss / len(tasks) # task average + outer_loss = outer_loss / num_tasks # task average outer_optim.zero_grad() outer_loss.backward() outer_optim.step() diff --git a/conda-recipe.yaml b/conda-recipe.yaml index 7c170f8d..d6f88b08 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -77,7 +77,7 @@ dependencies: - mypy - flake8 - flake8-bugbear - - doc8 < 1.0.0a0 + - doc8 - pydocstyle - clang-format - clang-tools # clang-tidy diff --git a/docs/source/examples/MAML.rst b/docs/source/examples/MAML.rst index bba6c35a..390e45cc 100644 --- a/docs/source/examples/MAML.rst +++ b/docs/source/examples/MAML.rst @@ -63,16 +63,17 @@ TorchOpt supports any user-defined PyTorch networks. Here is an example: net = nn.Sequential( nn.Conv2d(1, 64, 3), - nn.BatchNorm2d(64, momentum=1., affine=True), + nn.BatchNorm2d(64, momentum=1.0, affine=True), nn.ReLU(inplace=False), nn.MaxPool2d(2, 2), nn.Conv2d(64, 64, 3), - nn.BatchNorm2d(64, momentum=1., affine=True), + nn.BatchNorm2d(64, momentum=1.0, affine=True), nn.ReLU(inplace=False), nn.MaxPool2d(2, 2), nn.Conv2d(64, 64, 3), - nn.BatchNorm2d(64, momentum=1., affine=True), - nn.ReLU(inplace=False), nn.MaxPool2d(2, 2), + nn.BatchNorm2d(64, momentum=1.0, affine=True), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), nn.Flatten(), nn.Linear(64, args.n_way), ).to(device) @@ -132,14 +133,11 @@ Define the ``train`` function: qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).sum().item() / querysz qry_accs.append(qry_acc) - # Update the model's meta-parameters to optimize the query - # losses across all of the tasks sampled in this batch. - # This unrolls through the gradient steps. - qry_loss.backward() - torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) + qry_losses = torch.mean(torch.stack(qry_losses)) + qry_losses.backward() meta_opt.step() qry_losses = sum(qry_losses) / task_num qry_accs = 100. * sum(qry_accs) / task_num @@ -210,7 +208,7 @@ Define the ``test`` function: torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) - qry_losses = torch.cat(qry_losses).mean().item() + qry_losses = torch.mean(torch.stack(qry_losses)).item() qry_accs = 100. * torch.cat(qry_accs).float().mean().item() print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( diff --git a/examples/L2R/l2r.py b/examples/L2R/l2r.py index cd093313..989b71cc 100644 --- a/examples/L2R/l2r.py +++ b/examples/L2R/l2r.py @@ -74,7 +74,7 @@ def run_baseline(args, mnist_train, mnist_test): test_loader = DataLoader(test_set, batch_size=args.batch_size, shuffle=True, num_workers=1) model = LeNet5(args).to(args.device) - model_optimiser = torch.optim.Adam(model.parameters(), lr=args.lr) + model_optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) step = 0 running_train_loss = [] @@ -85,9 +85,9 @@ def run_baseline(args, mnist_train, mnist_test): train_x, train_label = train_x.to(args.device), train_label.to(args.device) outer_loss = model.outer_loss(train_x, train_label) - model_optimiser.zero_grad() + model_optimizer.zero_grad() outer_loss.backward() - model_optimiser.step() + model_optimizer.step() running_train_loss.append(outer_loss.item()) writer.add_scalar('train_loss', outer_loss.item(), step) @@ -142,8 +142,8 @@ def run_L2R(args, mnist_train, mnist_test): valid_loader = DataLoader(val_set, batch_size=args.batch_size, shuffle=True, num_workers=1) test_loader = DataLoader(test_set, batch_size=args.batch_size, shuffle=True, num_workers=1) model = LeNet5(args).to(args.device) - model_optimiser = torchopt.MetaSGD(model, lr=args.lr) - real_model_optimiser = torch.optim.Adam(model.parameters(), lr=args.lr) + model_optimizer = torchopt.MetaSGD(model, lr=args.lr) + real_model_optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) step = 0 time_bp = 0 @@ -170,11 +170,11 @@ def run_L2R(args, mnist_train, mnist_test): model.reset_meta(size=train_x.size(0)) net_state_dict = torchopt.extract_state_dict(model) - optim_state_dict = torchopt.extract_state_dict(model_optimiser) + optim_state_dict = torchopt.extract_state_dict(model_optimizer) for _ in range(1): inner_loss = model.inner_loss(train_x, train_label) - model_optimiser.step(inner_loss) + model_optimizer.step(inner_loss) # caclulate outer_loss, deirve meta-gradient and normalise outer_loss = model.outer_loss(valid_x, valid_label) @@ -186,17 +186,17 @@ def run_L2R(args, mnist_train, mnist_test): running_valid_loss.append(outer_loss.item()) writer.add_scalar('validation_loss', outer_loss.item(), step) - # reset the model and model optimiser + # reset the model and model optimizer torchopt.recover_state_dict(model, net_state_dict) - torchopt.recover_state_dict(model_optimiser, optim_state_dict) + torchopt.recover_state_dict(model_optimizer, optim_state_dict) # reuse inner_adapt to conduct real update based on learned meta weights inner_loss = model.inner_loss(train_x, train_label) for _ in range(1): inner_loss = model.inner_loss(train_x, train_label) - real_model_optimiser.zero_grad() + real_model_optimizer.zero_grad() inner_loss.backward() - real_model_optimiser.step() + real_model_optimizer.step() running_train_loss.append(inner_loss.item()) writer.add_scalar('weighted_train_loss', inner_loss.item(), step) diff --git a/examples/LOLA/helper/agent.py b/examples/LOLA/helper/agent.py index 8b30a983..3b37daf2 100644 --- a/examples/LOLA/helper/agent.py +++ b/examples/LOLA/helper/agent.py @@ -44,7 +44,7 @@ def __init__(self, args): def set_virtual(self): self.virtual_theta = theta_model(self.theta) - self.virtual_optimiser = torchopt.MetaSGD(self.virtual_theta, lr=self.args.lr_in) + self.virtual_optimizer = torchopt.MetaSGD(self.virtual_theta, lr=self.args.lr_in) def value_update(self, loss): self.value_optimizer.zero_grad() diff --git a/examples/LOLA/lola_dice.py b/examples/LOLA/lola_dice.py index 61d2e22c..7b1417a4 100644 --- a/examples/LOLA/lola_dice.py +++ b/examples/LOLA/lola_dice.py @@ -49,7 +49,7 @@ def main(args): args, ) inner_loss = memory1.dice_objective(use_baseline=args.use_baseline) - agent1.virtual_optimiser.step(inner_loss) + agent1.virtual_optimizer.step(inner_loss) # agent 1 assumes that agent 2 conducts n-step lookahead for _ in range(n_lookaheads): @@ -60,7 +60,7 @@ def main(args): args, ) inner_loss = memory2.dice_objective(use_baseline=args.use_baseline) - agent2.virtual_optimiser.step(inner_loss) + agent2.virtual_optimizer.step(inner_loss) # update agent 1 memory1, memory2 = sample( diff --git a/examples/distributed/few-shot/maml-accs.png b/examples/distributed/few-shot/maml-accs.png index 95a4a0f9e33af07601f21264152c63fd5f2602f2..8d70607cbdd12b63d38fab9f3bf266eee6ffa4b5 100644 GIT binary patch literal 158491 zcmeEucRZGT-~VZZWR-->2xS)8yGSLZi0sJ7-g{Fjq$G-rDA}_2j+5-{O|thMr}6t7 z>bmdyy6@+CUeD|I@9*bzUsqk-9OrR-zn|~t^Ik{K?sY#!8UBc)@GZJ7w`}>z`Vcbhg z)XBenDH~U!ME>?CCr?sIu`&Ja3;RF62Zh)6{O?ysUGi3x`P&z+H)p`!nOAp+QkzgHo=9>SX?4*CO0DW1rzQ^}$Y2PB2;CWwXy%HZxZ7 z%e}mzIB7qbfkD@~bRUZg4yKE-AB|%@@)M$DWPS;1uY4$Y)Nm@KTv$@FA|Xl^DJVM5 zPYE)RY~M_^f|W5K$0=B)xHr3u|a-DE6Q} z)9j+>{)XBIx5c9DR;#}3V|>Of=4&=*xV4^riS^W2EgBuw>ow08V8B70J$tsT#L0>( z_&4EX-NkYkj)CaP>P!mR=P$5raf2oyLu$B@oAw zFFZPn4ycl$my?r5ot>Sd+biR}#SR=2JHN>H_LscSh7sDxIz0UG>85(F$?Fuxt7<(I zjpd=d;k65A&+zCBPI?gddb7xf=ayY&cR$#fqOY<;C8ej=ZjE@2a9b>+&G1kR9_z1l zH#_Lehl(lqjG8K&-t(;-V3txPmgt0Saa+Z=Xs^GdeLk02L4WMnF)YiA%II->M&uTK z(7#)gGTV6q?9IiYK(-iXY-D%13I=_vtE*pHo;m5jr|Ypn5g8RVkQ<^9C2&qqut$mO z?&eqk!|wVANsGb4tY$yy)z#Ink2_couOywwQRgh&8g{#E*3D@?Qa&`bFGNe?zB3U) zCGL7fVtW)vGXK?4H*#ePw?68EgmKf;CPXv>w^xhm>aJh8awYELN9nB6tS-}9Smotr z!I9COsaP})sTf&Y_bFwij?PYhtMVPZ6K6P=T^JVL-i&_x_DNII?Y=2N^ImVLH6mJ} zOK}TixLEQL+_ikIV&iKPu#iO3WP80S8DGlF=_z&Hv&=`uczI7zYTKWz3tC@y}i%YS|u6WwiY*>xmj3_ z@suuOXH*=x%E-wzE+%AWpIR!%aO*ga9fK3uZU+x5kanMA*z3@vq9FR0O(Y5ObhF&* z)kjk!iTsAVe9h+wofl6|Q0k*!($zOLeNzw|I#2y!XK$_5X02J!Ns8lnl4#*#@f;Z~ z?YwKLVdI%!zkY4!X7ZG8W8?W%Z8*>OW(h6icJvQkcQVSMj`iG4HhIq{T9hYc=&0+y zQhVdZ4Quh1)>d>~FpWol&r@O=nR~Y9Sy;y61G!Dj$V*`BtUDA0Z{oFP7EPX|6?G(X z8ng+}U#3Ofy?1Y=iLaHBgX07_o8r3jfgh6HdA0 z-ZD<;n>XSyhd%>(sHhm3V%HZ2C@FQEKh9+_5~ycCdai`gD0R-7Ua=?`>JCqA*oC8{ zeD5B!Mn0VHkft4|F!SE8RZHlQXU{4(dUSa-CJzcyC(4KRcGgawIWuWDP#ozr?1B#; z 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�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 literal 157986 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ℑROxFp;|vM?)sZz>hC9`SNS; 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

    ~%JHJ;+~y8cZ@J0?UG%;nv%Q&^nJ@v%w+#t4 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

    s5b|%eLop*5_(PArWw}5x#C5 ze>voUiM%3Bu!eyzZk)(d1JP<5+7IsU&)Ve4dG?Z4EZWI4+bY>_=rgMLiRISOvkAMN zy|2w{D-ueXvTz-=^JNVpzjE?qk74!pz~DcyFRdKFy}uVaQv+hi%BXo4z*Q>`k+@SQ z=Wp|_X4CZL#xV8erDC`sYyJ}gh=L`Ed6Mhtu%j8hvM=-Y&U%V5FN^(B`jRq~6O4e_ z6TgwV8MQRCN^~mjNAHE))$L%1Ia2EyAXd!mj{v!NW!4s8n`iZ(p-nXXyI!%I

    &P8Q)TFVoq_Nd{EuA?NrQaq> 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

  • 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 diff --git a/examples/distributed/few-shot/maml_omniglot.py b/examples/distributed/few-shot/maml_omniglot.py index d798c4f5..22c8bda1 100644 --- a/examples/distributed/few-shot/maml_omniglot.py +++ b/examples/distributed/few-shot/maml_omniglot.py @@ -69,7 +69,7 @@ def worker_init(): world_info = todist.get_world_info() proctitle = f'{world_info.worker_name}: {getproctitle().strip()}' - print(f'worker_init => {proctitle}') + print(f'Worker init:=> {proctitle}') setproctitle(proctitle) seed = world_info.local_rank @@ -178,7 +178,9 @@ def inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter): device = None original_net = net_rref.to_here() - net = torchopt.module_clone(original_net, by='reference', device=device) + # The local net can be shared across multiple RPC calls on the current worker + # We need to detach the buffers to avoid sharing the same buffers across + net = torchopt.module_clone(original_net, by='reference', detach_buffers=True, device=device) if device is not None: x_spt = x_spt.to(device) y_spt = y_spt.to(device) @@ -205,7 +207,6 @@ def train(db: OmniglotNShot, net: nn.Module, meta_opt: optim.Adam, epoch: int, l net.train() n_train_iter = db.x_train.shape[0] // db.batchsz - net_rref = todist.rpc.RRef(net) for batch_idx in range(n_train_iter): start_time = time.time() # Sample a batch of support and query images and labels. @@ -219,6 +220,9 @@ def train(db: OmniglotNShot, net: nn.Module, meta_opt: optim.Adam, epoch: int, l n_inner_iter = 5 meta_opt.zero_grad() + # Sending modules contains nn.Parameter will detach from the current computation graph + # Here we explicitly convert the parameters to tensors with `CloneBackward` + net_rref = todist.rpc.RRef(torchopt.module_clone(net, by='copy')) with todist.autograd.context() as context_id: qry_loss, qry_acc = inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter) todist.autograd.backward(context_id, qry_loss) diff --git a/examples/distributed/few-shot/maml_omniglot_local_loader.py b/examples/distributed/few-shot/maml_omniglot_local_loader.py index 66c0dd90..9c36c6ad 100644 --- a/examples/distributed/few-shot/maml_omniglot_local_loader.py +++ b/examples/distributed/few-shot/maml_omniglot_local_loader.py @@ -79,7 +79,7 @@ def worker_init(): world_info = todist.get_world_info() proctitle = f'{world_info.worker_name}: {getproctitle().strip()}' - print(f'worker_init => {proctitle}') + print(f'Worker init:=> {proctitle}') setproctitle(proctitle) seed = world_info.world_rank @@ -217,7 +217,9 @@ def inner_loop(net_rref, n_inner_iter, task_id, task_num, mode): device = LOCAL_DEVICE original_net = net_rref.to_here() - net = torchopt.module_clone(original_net, by='reference', device=device) + # The local net can be shared across multiple RPC calls on the current worker + # We need to detach the buffers to avoid sharing the same buffers across + net = torchopt.module_clone(original_net, by='reference', detach_buffers=True, device=device) x_spt, y_spt, x_qry, y_qry = get_next_batch(task_id, mode) if device is not None: @@ -261,6 +263,9 @@ def train(net: nn.Module, meta_opt: optim.Adam, epoch: int, log: list): n_inner_iter = 5 meta_opt.zero_grad() + # Sending modules contains nn.Parameter will detach from the current computation graph + # Here we explicitly convert the parameters to tensors with `CloneBackward` + net_rref = todist.rpc.RRef(torchopt.module_clone(net, by='copy')) with todist.autograd.context() as context_id: qry_loss, qry_acc = inner_loop(net_rref, n_inner_iter, None, task_num, 'train') todist.autograd.backward(context_id, qry_loss) diff --git a/examples/few-shot/maml-accs.png b/examples/few-shot/maml-accs.png index 4a34be0a0357779928d9896def1a083a86f38dec..df0b37db83f43b01a61fa1acfe8bf25462893551 100644 GIT binary patch literal 150134 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 #Y;$f+EWSVf+)J?qsE%3KCbEiK=p4zxbc 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 literal 151372 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

    CJ|12$n77`cpmlr=ByI4=|532cV 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 H{MY{j&4~>^ diff --git a/examples/few-shot/maml_omniglot.py b/examples/few-shot/maml_omniglot.py index 0eafce01..766391db 100644 --- a/examples/few-shot/maml_omniglot.py +++ b/examples/few-shot/maml_omniglot.py @@ -147,8 +147,8 @@ def train(db, net, meta_opt, epoch, log): qry_accs = [] meta_opt.zero_grad() - net_state_dict = torchopt.extract_state_dict(net) - optim_state_dict = torchopt.extract_state_dict(inner_opt) + net_state_dict = torchopt.extract_state_dict(net, by='reference', detach_buffers=True) + optim_state_dict = torchopt.extract_state_dict(inner_opt, by='reference') for i in range(task_num): # Optimize the likelihood of the support set by taking # gradient steps w.r.t. the model's parameters. @@ -165,20 +165,17 @@ def train(db, net, meta_opt, epoch, log): # These will be used to update the model's meta-parameters. qry_logits = net(x_qry[i]) qry_loss = F.cross_entropy(qry_logits, y_qry[i]) - qry_losses.append(qry_loss.detach()) + qry_losses.append(qry_loss) qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).sum().item() / querysz qry_accs.append(qry_acc) - # Update the model's meta-parameters to optimize the query - # losses across all of the tasks sampled in this batch. - # This unrolls through the gradient steps. - qry_loss.backward() - torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) + qry_losses = torch.mean(torch.stack(qry_losses)) + qry_losses.backward() meta_opt.step() - qry_losses = sum(qry_losses) / task_num + qry_losses = qry_losses.item() qry_accs = 100.0 * sum(qry_accs) / task_num i = epoch + float(batch_idx) / n_train_iter iter_time = time.time() - start_time @@ -221,8 +218,8 @@ def test(db, net, epoch, log): # doesn't have to be duplicated between `train` and `test`? n_inner_iter = 5 - net_state_dict = torchopt.extract_state_dict(net) - optim_state_dict = torchopt.extract_state_dict(inner_opt) + net_state_dict = torchopt.extract_state_dict(net, by='reference', detach_buffers=True) + optim_state_dict = torchopt.extract_state_dict(inner_opt, by='reference') for i in range(task_num): # Optimize the likelihood of the support set by taking # gradient steps w.r.t. the model's parameters. @@ -241,7 +238,7 @@ def test(db, net, epoch, log): torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) - qry_losses = torch.cat(qry_losses).mean().item() + qry_losses = torch.mean(torch.stack(qry_losses)).item() qry_accs = 100.0 * torch.cat(qry_accs).float().mean().item() print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( diff --git a/pyproject.toml b/pyproject.toml index db908e6c..b629ca60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ lint = [ "mypy", "flake8", "flake8-bugbear", - "doc8 < 1.0.0a0", + "doc8", "pydocstyle", "pyenchant", "cpplint", @@ -186,7 +186,6 @@ show_error_codes = true show_error_context = true show_traceback = true allow_redefinition = true -enable_recursive_aliases = true check_untyped_defs = true disallow_incomplete_defs = false disallow_untyped_defs = false diff --git a/tests/requirements.txt b/tests/requirements.txt index 1143ebd3..11b76eb6 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -13,7 +13,7 @@ pylint mypy flake8 flake8-bugbear -doc8 < 1.0.0a0 +doc8 pydocstyle pyenchant cpplint diff --git a/torchopt/distributed/api.py b/torchopt/distributed/api.py index 000228db..80f96311 100644 --- a/torchopt/distributed/api.py +++ b/torchopt/distributed/api.py @@ -276,7 +276,7 @@ def remote_async_call( *, args: Optional[Args] = None, kwargs: Optional[KwArgs] = None, - partitioner: Partitioner = batch_partitioner, + partitioner: Optional[Partitioner] = None, reducer: Optional[Callable[[Iterable[T]], U]] = None, timeout: Optional[float] = UNSET_RPC_TIMEOUT, ) -> Union[Future[List[T]], Future[U]]: @@ -303,6 +303,8 @@ def remote_async_call( args = () if kwargs is None: kwargs = {} + if partitioner is None: + partitioner = batch_partitioner if isinstance(partitioner, (int, str)): partitions = [(get_worker_id(id=partitioner), args, kwargs)] elif callable(partitioner): @@ -332,7 +334,7 @@ def remote_sync_call( *, args: Optional[Args] = None, kwargs: Optional[KwArgs] = None, - partitioner: Partitioner = batch_partitioner, + partitioner: Optional[Partitioner] = None, reducer: Optional[Callable[[Iterable[T]], U]] = None, timeout: Optional[float] = UNSET_RPC_TIMEOUT, ) -> Union[List[T], U]: @@ -365,7 +367,7 @@ def remote_sync_call( def parallelize_async( - partitioner: Partitioner = batch_partitioner, + partitioner: Optional[Partitioner] = None, reducer: Optional[Callable[[Iterable[T]], U]] = None, timeout: Optional[float] = UNSET_RPC_TIMEOUT, ) -> Callable[[Callable[..., T]], Callable[..., Union[Future[List[T]], Future[U]]]]: @@ -379,13 +381,18 @@ def parallelize_async( partitioner (Partitioner, optional): A partitioner that partitions the arguments to multiple workers. Defaults to :func:`batch_partitioner`. reducer (Callable[[Iterable[T]], U], optional): A reducer that reduces the results from - multiple workers. Defaults to :data:`None`. + multiple workers. Defaults to :func:`mean_reducer` if the ``partitioner`` is not + specified, i.e., :func:`batch_partitioner`. Otherwise, it defaults to :data:`None`. timeout (float, optional): The timeout for the RPC call. Defaults to :data:`rpc.api.UNSET_RPC_TIMEOUT`. Returns: - The decorated function. + The decorator function. """ + if partitioner is None: + partitioner = batch_partitioner + if reducer is None: + reducer = mean_reducer # type: ignore[assignment] def wrapper(func: Callable[..., T]) -> Callable[..., Union[Future[List[T]], Future[U]]]: @functools.wraps(func) @@ -418,7 +425,7 @@ def wrapped(*args: Any, **kwargs: Any) -> Union[Future[List[T]], Future[U]]: def parallelize( - partitioner: Partitioner = batch_partitioner, + partitioner: Optional[Partitioner] = None, reducer: Optional[Callable[[Iterable[T]], U]] = None, timeout: Optional[float] = UNSET_RPC_TIMEOUT, ) -> Callable[[Callable[..., T]], Callable[..., Union[List[T], U]]]: @@ -430,13 +437,18 @@ def parallelize( partitioner (Partitioner, optional): A partitioner that partitions the arguments to multiple workers. Defaults to :func:`batch_partitioner`. reducer (Callable[[Iterable[T]], U], optional): A reducer that reduces the results from - multiple workers. Defaults to :data:`None`. + multiple workers. Defaults to :func:`mean_reducer` if the ``partitioner`` is not + specified, i.e., :func:`batch_partitioner`. Otherwise, it defaults to :data:`None`. timeout (float, optional): The timeout for the RPC call. Defaults to :data:`rpc.api.UNSET_RPC_TIMEOUT`. Returns: - The decorated function. + The decorator function. """ + if partitioner is None: + partitioner = batch_partitioner + if reducer is None: + reducer = mean_reducer # type: ignore[assignment] def wrapper(func: Callable[..., T]) -> Callable[..., Union[List[T], U]]: @functools.wraps(func) diff --git a/torchopt/distributed/autograd.py b/torchopt/distributed/autograd.py index 65442931..9425b4a5 100644 --- a/torchopt/distributed/autograd.py +++ b/torchopt/distributed/autograd.py @@ -78,7 +78,7 @@ def backward( with LOCK: for p, g in all_local_grads.items(): - if getattr(p, 'grad', None) is not None: + if p.grad is not None: p.grad = p.grad.add(g) else: p.grad = g diff --git a/torchopt/optim/base.py b/torchopt/optim/base.py index afbab30e..572eb8a8 100644 --- a/torchopt/optim/base.py +++ b/torchopt/optim/base.py @@ -19,7 +19,7 @@ import torch from torchopt import pytree -from torchopt.typing import GradientTransformation, OptState, Params +from torchopt.typing import GradientTransformation, OptState, Params, TensorTree from torchopt.update import apply_updates @@ -61,24 +61,23 @@ def zero_grad(self, set_to_none: bool = False) -> None: Args: set_to_none (bool): Instead of setting to zero, set the ``grads`` to :data:`None`. """ - for group in self.param_groups: - if set_to_none: + if set_to_none: - def f(p): - p.grad = None + def f(p): + p.grad = None - else: + else: - def f(p): - if p.grad is None: - return - if p.grad.grad_fn is not None: - p.grad.detach_() - else: - p.grad.requires_grad_(False) - p.grad.zero_() + def f(p): + if p.grad is None: + return + if p.grad.grad_fn is not None: + p.grad.detach_() + else: + p.grad.requires_grad_(False) + p.grad.zero_() - pytree.tree_map(f, cast(Params, group)) + pytree.tree_map(f, cast(TensorTree, self.param_groups)) def state_dict(self) -> Tuple['OptState', ...]: """Returns the state of the optimizer.""" diff --git a/torchopt/optim/meta/base.py b/torchopt/optim/meta/base.py index cec74f86..9dd525f6 100644 --- a/torchopt/optim/meta/base.py +++ b/torchopt/optim/meta/base.py @@ -106,16 +106,16 @@ def add_param_group(self, net: nn.Module) -> None: # pylint: disable-next=import-outside-toplevel from torchopt.utils import _extract_container - net_container = _extract_container(net, with_buffer=False) + params_container, _ = _extract_container(net, with_buffers=False) flattened_params = tuple( filter( torch.is_tensor, # type: ignore[arg-type] # pylint: disable-next=line-too-long - cast(List[Optional[torch.Tensor]], pytree.tree_leaves(net_container)), # type: ignore[arg-type] + cast(List[Optional[torch.Tensor]], pytree.tree_leaves(params_container)), # type: ignore[arg-type] ) ) optimizer_state = self.impl.init(flattened_params) - self.param_containers_groups.append(net_container) + self.param_containers_groups.append(params_container) self.state_groups.append(optimizer_state) def state_dict(self) -> Tuple['OptState', ...]: diff --git a/torchopt/transform.py b/torchopt/transform.py index c417cc30..ac98d8bf 100644 --- a/torchopt/transform.py +++ b/torchopt/transform.py @@ -43,7 +43,7 @@ ScaleState = EmptyState -INT32_MAX = torch.iinfo(torch.int32).max +INT64_MAX = torch.iinfo(torch.int64).max TRIPLE_PYTREEDEF = pytree.tree_structure(cast(PyTree[int], (0, 1, 2))) @@ -87,7 +87,7 @@ def _inc_count( updates: Updates, count: TensorTree, *, already_flattened: bool = False ) -> TensorTree: def f(c, g): - return c + (c != INT32_MAX).to(torch.int32) if g is not None else c + return c + (c != INT64_MAX).to(torch.int64) if g is not None else c if already_flattened: return map_flattened(f, count, updates) @@ -162,7 +162,7 @@ def _scale_by_schedule( def init_fn(params): zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int32, device=t.device).squeeze_(), params + lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params ) return ScaleByScheduleState(count=zero) @@ -305,7 +305,7 @@ def _scale_by_adam( def init_fn(params): zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int32, device=t.device).squeeze_(), params + lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params ) mu = tree_map( # first moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params @@ -435,7 +435,7 @@ def update_fn(updates, state, *, params=None, inplace=True): def init_fn(params): zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int32, device=t.device).squeeze_(), params + lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params ) mu = tree_map( # first moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params diff --git a/torchopt/utils.py b/torchopt/utils.py index 8f7c2f62..d5d7d6d3 100644 --- a/torchopt/utils.py +++ b/torchopt/utils.py @@ -14,7 +14,20 @@ # ============================================================================== """Utilities for TorchOpt.""" -from typing import TYPE_CHECKING, Dict, NamedTuple, Optional, Sequence, Tuple, Union, cast +import itertools +from typing import ( + TYPE_CHECKING, + Dict, + List, + NamedTuple, + Optional, + Sequence, + Set, + Tuple, + Union, + cast, + overload, +) import torch import torch.nn as nn @@ -47,7 +60,9 @@ class ModuleState(NamedTuple): """Container for module state.""" params: Tuple[Dict[str, torch.Tensor], ...] + buffers: Tuple[Dict[str, torch.Tensor], ...] visual_contents: Optional[Dict] = None + detach_buffers: bool = False def stop_gradient(target: Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer']) -> None: @@ -76,7 +91,7 @@ def f(obj): obj.detach_().requires_grad_(obj.requires_grad) if isinstance(target, ModuleState): - true_target = cast(TensorTree, target.params) + true_target = cast(TensorTree, (target.params, target.buffers)) elif isinstance(target, nn.Module): true_target = cast(TensorTree, tuple(target.parameters())) elif isinstance(target, MetaOptimizer): @@ -87,13 +102,43 @@ def f(obj): pytree.tree_map(f, true_target) +@overload +def extract_state_dict( + target: nn.Module, + *, + # pylint: disable-next=line-too-long + by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + device: Optional[Union[int, str, torch.device]] = None, + with_buffers: bool = True, + enable_visual: bool = False, + visual_prefix: str = '', +) -> ModuleState: + ... + + +@overload +def extract_state_dict( + target: 'MetaOptimizer', + *, + # pylint: disable-next=line-too-long + by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + device: Optional[Union[int, str, torch.device]] = None, + with_buffers: bool = True, + enable_visual: bool = False, + visual_prefix: str = '', +) -> Tuple['OptState', ...]: + ... + + # pylint: disable-next=too-many-branches,too-many-locals def extract_state_dict( target: Union[nn.Module, 'MetaOptimizer'], *, - by: Literal['reference', 'copy', 'deepcopy'] = 'reference', # type: ignore[name-defined] + # pylint: disable-next=line-too-long + by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] device: Optional[Union[int, str, torch.device]] = None, - with_buffer: bool = True, + with_buffers: bool = True, + detach_buffers: bool = False, enable_visual: bool = False, visual_prefix: str = '', ) -> Union[ModuleState, Tuple['OptState', ...]]: @@ -118,59 +163,54 @@ def extract_state_dict( - :const:`'deepcopy'`: The extracted tensors will be deep-copied from the original tensors. The deep-copied tensors will detach from the original computation graph. device: If specified, move the extracted state to the specified device. - with_buffer: - Extract buffer together with parameters, this argument is only used if the input target - is :class:`nn.Module`. - enable_visual: - Add additional annotations, which could be used in computation graph visualization. - Currently, this flag only has effect on :class:`nn.Module` but we will support - :class:`torchopt.MetaOptimizer` later. + with_buffers: Extract buffer together with parameters, this argument is only used if the + input target is :class:`nn.Module`. + detach_buffers: Whether to detach the reference to the buffers, this argument is only used + if the input target is :class:`nn.Module` and ``by='reference'``. + enable_visual: Add additional annotations, which could be used in computation graph + visualization. Currently, this flag only has effect on :class:`nn.Module` but we will + support :class:`torchopt.MetaOptimizer` later. visual_prefix: Prefix for the visualization annotations. Returns: State extracted of the input object. """ - assert by in ('reference', 'copy', 'deepcopy', 'clone', 'deepclone') + assert by in ('reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone') by = by.replace('clone', 'copy') - if device is not None: - device = torch.device(device) + by = 'reference' if by == 'ref' else by # pylint: disable=import-outside-toplevel from torchopt.optim.meta.base import MetaOptimizer - if by == 'reference': - - if device is not None: + if device is not None: + target_device = torch.device(device) - def replicate(t): - return t.to(device=device) + def reference(t: torch.Tensor) -> torch.Tensor: + return t.to(device=target_device) - else: + def clone(t: torch.Tensor) -> torch.Tensor: + return t.clone().to(device=target_device) - def replicate(t): - return t + def clone_detach_(t: torch.Tensor) -> torch.Tensor: + return t.clone().detach_().to(device=target_device).requires_grad_(t.requires_grad) - elif by == 'copy': - if device is not None: + else: - def replicate(t): - return t.clone().to(device=device) + def reference(t: torch.Tensor) -> torch.Tensor: + return t - else: + def clone(t: torch.Tensor) -> torch.Tensor: + return t.clone() - def replicate(t): - return t.clone() + def clone_detach_(t: torch.Tensor) -> torch.Tensor: + return t.clone().detach_().requires_grad_(t.requires_grad) + if by == 'reference': + replicate = reference + elif by == 'copy': + replicate = clone else: - if device is not None: - - def replicate(t): - return t.clone().detach_().to(device=device).requires_grad_(t.requires_grad) - - else: - - def replicate(t): - return t.clone().detach_().requires_grad_(t.requires_grad) + replicate = clone_detach_ if isinstance(target, nn.Module): # pylint: disable=no-else-return if enable_visual: @@ -184,27 +224,48 @@ def replicate(t): else: visual_contents = None - params = [] + params: List[Dict[str, torch.Tensor]] = [] + buffers: List[Dict[str, torch.Tensor]] = [] + memo: Set[nn.Module] = set() - def update_container(term): - if len(term) != 0: + def update_params(container): + if len(container) > 0: params.append( - type(term)( - (k, replicate(v)) for k, v in term.items() if isinstance(v, torch.Tensor) + type(container)( + (k, replicate(v)) + for k, v in container.items() + if isinstance(v, torch.Tensor) + ) + ) + + def update_buffers(container): + if len(container) > 0: + fn = clone_detach_ if detach_buffers else replicate + buffers.append( + type(container)( + (k, fn(v)) for k, v in container.items() if isinstance(v, torch.Tensor) ) ) # pylint: disable=protected-access - update_container(target._parameters) - if with_buffer: - update_container(target._buffers) - for module in target.modules(): - if module is target: + update_params(target._parameters) + if with_buffers: + update_buffers(target._buffers) + memo.add(target) + for submodule in target.modules(): + if submodule in memo: continue - update_container(module._parameters) - if with_buffer: - update_container(module._buffers) - return ModuleState(params=tuple(params), visual_contents=visual_contents) + update_params(submodule._parameters) + if with_buffers: + update_buffers(submodule._buffers) + memo.add(submodule) + + return ModuleState( + params=tuple(params), + buffers=tuple(buffers), + visual_contents=visual_contents, + detach_buffers=detach_buffers, + ) elif isinstance(target, MetaOptimizer): state = target.state_dict() @@ -221,26 +282,33 @@ def get_variable(t): def _extract_container( - module: nn.Module, with_buffer: bool = True -) -> Tuple[Dict[str, Optional[torch.Tensor]], ...]: + module: nn.Module, with_buffers: bool = True +) -> Tuple[ + Tuple[Dict[str, Optional[torch.Tensor]], ...], + Tuple[Dict[str, Optional[torch.Tensor]], ...], +]: if isinstance(module, nn.Module): - containers = [] + params: List[Dict[str, Optional[torch.Tensor]]] = [] + buffers: List[Dict[str, Optional[torch.Tensor]]] = [] + memo: Set[nn.Module] = set() - def update_container(term): - if len(term) != 0: - containers.append(term) # we need references to original dicts + def update_container(container, items): + if len(items) > 0: + container.append(items) # we need references to original dicts # pylint: disable=protected-access - update_container(module._parameters) - if with_buffer: - update_container(module._buffers) + update_container(params, module._parameters) + if with_buffers: + update_container(buffers, module._buffers) + memo.add(module) for submodule in module.modules(): - if submodule is module: + if submodule in memo: continue - update_container(submodule._parameters) - if with_buffer: - update_container(submodule._buffers) - return tuple(containers) + update_container(params, submodule._parameters) + if with_buffers: + update_container(buffers, submodule._buffers) + memo.add(submodule) + return tuple(params), tuple(buffers) raise RuntimeError(f'Unexpected class of {module}') @@ -264,10 +332,24 @@ def recover_state_dict( from torchopt.optim.meta.base import MetaOptimizer if isinstance(target, nn.Module): - target_container = _extract_container(target) - state = cast(ModuleState, state) - for tgt, source in zip(target_container, state.params): - tgt.update(source) + params, buffers, *_ = state = cast(ModuleState, state) + params_container, buffers_container = _extract_container(target, with_buffers=True) + + if state.detach_buffers: + + def clone_detach_(t: torch.Tensor) -> torch.Tensor: + return t.clone().detach_().requires_grad_(t.requires_grad) + + buffers = cast( + Tuple[Dict[str, torch.Tensor], ...], + pytree.tree_map(clone_detach_, buffers), # type: ignore[arg-type] + ) + + for tgt, src in itertools.chain( + zip(params_container, params), + zip(buffers_container, buffers), + ): + tgt.update(src) elif isinstance(target, MetaOptimizer): state = cast(Sequence[OptState], state) target.load_state_dict(state) @@ -275,12 +357,51 @@ def recover_state_dict( raise RuntimeError(f'Unexpected class of {target}') +@overload +def module_clone( + target: nn.Module, + *, + # pylint: disable-next=line-too-long + by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + detach_buffers: bool = False, + device: Optional[Union[int, str, torch.device]] = None, +) -> nn.Module: + ... + + +@overload +def module_clone( + target: 'MetaOptimizer', + *, + # pylint: disable-next=line-too-long + by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + detach_buffers: bool = False, + device: Optional[Union[int, str, torch.device]] = None, +) -> 'MetaOptimizer': + ... + + +@overload +def module_clone( + target: TensorTree, + *, + # pylint: disable-next=line-too-long + by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + detach_buffers: bool = False, + device: Optional[Union[int, str, torch.device]] = None, +) -> TensorTree: + ... + + +# pylint: disable-next=too-many-locals def module_clone( - target: Union[TensorTree, nn.Module, 'MetaOptimizer'], + target: Union[nn.Module, 'MetaOptimizer', TensorTree], *, - by: Literal['reference', 'copy', 'deepcopy'] = 'reference', # type: ignore[name-defined] + # pylint: disable-next=line-too-long + by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + detach_buffers: bool = False, device: Optional[Union[int, str, torch.device]] = None, -) -> Union[TensorTree, nn.Module, 'MetaOptimizer']: +) -> Union[nn.Module, 'MetaOptimizer', TensorTree]: """Clone a module. Args: @@ -293,13 +414,16 @@ def module_clone( points to the original tensors. - :const:`'deepcopy'`: The extracted tensors will be deep-copied from the original tensors. The deep-copied tensors will detach from the original computation graph. + detach_buffers: Whether to detach the reference to the buffers, this argument is only used + if the input target is :class:`nn.Module` and ``by='reference'``. device: If specified, move the cloned module to the specified device. Returns: The cloned module. """ - assert by in ('reference', 'copy', 'deepcopy', 'clone', 'deepclone') + assert by in ('reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone') by = by.replace('clone', 'copy') + by = 'reference' if by == 'ref' else by if device is not None: device = torch.device(device) @@ -309,43 +433,53 @@ def module_clone( from torchopt.optim.meta.base import MetaOptimizer if isinstance(target, (nn.Module, MetaOptimizer)): - cloned = copy.deepcopy(target) - recover_state_dict(cloned, extract_state_dict(target, by=by, device=device)) + if isinstance(target, nn.Module): + containers = cast(TensorTree, _extract_container(target, with_buffers=True)) + else: + containers = cast(TensorTree, target.state_dict()) + tensors = pytree.tree_leaves(containers) + memo = {id(t): t for t in tensors} + cloned = copy.deepcopy(target, memo=memo) + state = extract_state_dict( # type: ignore[call-overload] + target, + by=by, + with_buffers=True, + detach_buffers=detach_buffers, + device=device, + ) + recover_state_dict(cloned, state) return cloned # Tree of tensors - if by == 'reference': - if device is not None: + if device is not None: + target_device = torch.device(device) - def replicate(t): - return t.to(device=device) + def reference(t: torch.Tensor) -> torch.Tensor: + return t.to(device=target_device) - else: + def clone(t: torch.Tensor) -> torch.Tensor: + return t.clone().to(device=target_device) - def replicate(t): - return t + def clone_detach_(t: torch.Tensor) -> torch.Tensor: + return t.clone().detach_().to(device=target_device).requires_grad_(t.requires_grad) - elif by == 'copy': - if device is not None: + else: - def replicate(t): - return t.clone().to(device=device) + def reference(t: torch.Tensor) -> torch.Tensor: + return t - else: + def clone(t: torch.Tensor) -> torch.Tensor: + return t.clone() - def replicate(t): - return t.clone() + def clone_detach_(t: torch.Tensor) -> torch.Tensor: + return t.clone().detach_().requires_grad_(t.requires_grad) + if by == 'reference': + replicate = reference + elif by == 'copy': + replicate = clone else: - if device is not None: - - def replicate(t): - return t.clone().detach_().to(device=device).requires_grad_(t.requires_grad) - - else: - - def replicate(t): - return t.clone().detach_().requires_grad_(t.requires_grad) + replicate = clone_detach_ return pytree.tree_map(replicate, cast(TensorTree, target)) diff --git a/tutorials/3_Meta_Optimizer.ipynb b/tutorials/3_Meta_Optimizer.ipynb index f92da67b..0b371b2d 100644 --- a/tutorials/3_Meta_Optimizer.ipynb +++ b/tutorials/3_Meta_Optimizer.ipynb @@ -161,332 +161,7 @@ }, { "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "%3\n", - "\n", - "\n", - "\n", - "140393111569088\n", - "\n", - "outer_loss\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111544592\n", - "\n", - "MseLossBackward0\n", - "\n", - "\n", - "\n", - "140393111544592->140393111569088\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544736\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111544736->140393111544592\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140396237940576\n", - "\n", - "AddBackward0\n", - " step1.a\n", - " ()\n", - "\n", - "\n", - "\n", - "140396237940576->140393111544736\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545216\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393111545216->140396237940576\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545984\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111545216->140393111545984\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111534464\n", - "\n", - "step0.a\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111534464->140393111545216\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544112\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111544112->140396237940576\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545168\n", - "\n", - "DivBackward0\n", - "\n", - "\n", - "\n", - "140393111545168->140393111544112\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545408\n", - "\n", - "DivBackward0\n", - "\n", - "\n", - "\n", - "140393111545408->140393111545168\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545552\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111545552->140393111545408\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545648\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111545648->140393111545552\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545744\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111545744->140393111545648\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546272\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111545744->140393111546272\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545840\n", - "\n", - "MseLossBackwardBackward0\n", - "\n", - "\n", - "\n", - "140393111545840->140393111545744\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545984->140393111545840\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545792\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111545792->140393111545744\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545792->140393111545984\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546128\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393111546128->140393111545792\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545024\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111546128->140393111545024\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111534624\n", - "\n", - "x\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111534624->140393111546128\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545360\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111545360->140393111545168\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545696\n", - "\n", - "SqrtBackward0\n", - "\n", - "\n", - "\n", - "140393111545696->140393111545360\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545936\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111545936->140393111545696\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545888\n", - "\n", - "DivBackward0\n", - "\n", - "\n", - "\n", - "140393111545888->140393111545936\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546176\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111546176->140393111545888\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546272->140393111546176\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545024->140393111544736\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] + "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n140393111569088\n\nouter_loss\n ()\n\n\n\n140393111544592\n\nMseLossBackward0\n\n\n\n140393111544592->140393111569088\n\n\n\n\n\n140393111544736\n\nMulBackward0\n\n\n\n140393111544736->140393111544592\n\n\n\n\n\n140396237940576\n\nAddBackward0\n step1.a\n ()\n\n\n\n140396237940576->140393111544736\n\n\n\n\n\n140393111545216\n\nAccumulateGrad\n\n\n\n140393111545216->140396237940576\n\n\n\n\n\n140393111545984\n\nMulBackward0\n\n\n\n140393111545216->140393111545984\n\n\n\n\n\n140393111534464\n\nstep0.a\n ()\n\n\n\n140393111534464->140393111545216\n\n\n\n\n\n140393111544112\n\nMulBackward0\n\n\n\n140393111544112->140396237940576\n\n\n\n\n\n140393111545168\n\nDivBackward0\n\n\n\n140393111545168->140393111544112\n\n\n\n\n\n140393111545408\n\nDivBackward0\n\n\n\n140393111545408->140393111545168\n\n\n\n\n\n140393111545552\n\nAddBackward0\n\n\n\n140393111545552->140393111545408\n\n\n\n\n\n140393111545648\n\nPowBackward0\n\n\n\n140393111545648->140393111545552\n\n\n\n\n\n140393111545744\n\nMulBackward0\n\n\n\n140393111545744->140393111545648\n\n\n\n\n\n140393111546272\n\nPowBackward0\n\n\n\n140393111545744->140393111546272\n\n\n\n\n\n140393111545840\n\nMseLossBackwardBackward0\n\n\n\n140393111545840->140393111545744\n\n\n\n\n\n140393111545984->140393111545840\n\n\n\n\n\n140393111545792\n\nPowBackward0\n\n\n\n140393111545792->140393111545744\n\n\n\n\n\n140393111545792->140393111545984\n\n\n\n\n\n140393111546128\n\nAccumulateGrad\n\n\n\n140393111546128->140393111545792\n\n\n\n\n\n140393111545024\n\nPowBackward0\n\n\n\n140393111546128->140393111545024\n\n\n\n\n\n140393111534624\n\nx\n ()\n\n\n\n140393111534624->140393111546128\n\n\n\n\n\n140393111545360\n\nAddBackward0\n\n\n\n140393111545360->140393111545168\n\n\n\n\n\n140393111545696\n\nSqrtBackward0\n\n\n\n140393111545696->140393111545360\n\n\n\n\n\n140393111545936\n\nAddBackward0\n\n\n\n140393111545936->140393111545696\n\n\n\n\n\n140393111545888\n\nDivBackward0\n\n\n\n140393111545888->140393111545936\n\n\n\n\n\n140393111546176\n\nAddBackward0\n\n\n\n140393111546176->140393111545888\n\n\n\n\n\n140393111546272->140393111546176\n\n\n\n\n\n140393111545024->140393111544736\n\n\n\n\n\n" }, "metadata": {}, "output_type": "display_data" @@ -529,404 +204,7 @@ }, { "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "%3\n", - "\n", - "\n", - "\n", - "140393102737552\n", - "\n", - "outer_loss\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111544400\n", - "\n", - "MseLossBackward0\n", - "\n", - "\n", - "\n", - "140393111544400->140393102737552\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544304\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111544304->140393111544400\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140396584753232\n", - "\n", - "AddBackward0\n", - " step1.a\n", - " ()\n", - "\n", - "\n", - "\n", - "140396584753232->140393111544304\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544016\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393111544016->140396584753232\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547280\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111544016->140393111547280\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111570848\n", - "\n", - "step0.a\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111570848->140393111544016\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544256\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111544256->140396584753232\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544160\n", - "\n", - "DivBackward0\n", - "\n", - "\n", - "\n", - "140393111544160->140393111544256\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546512\n", - "\n", - "DivBackward0\n", - "\n", - "\n", - "\n", - "140393111546512->140393111544160\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544112\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111544112->140393111546512\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546368\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111546368->140393111544112\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547040\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393111547040->140393111546368\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111569408\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111569408->140393111547040\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546272\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111546272->140393111544112\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547088\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111547088->140393111546272\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547328\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111547088->140393111547328\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547184\n", - "\n", - "MseLossBackwardBackward0\n", - "\n", - "\n", - "\n", - "140393111547184->140393111547088\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547280->140393111547184\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546944\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111546944->140393111547088\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546944->140393111547280\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546320\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393111546320->140393111546944\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544208\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393111546320->140393111544208\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111571168\n", - "\n", - "x\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111571168->140393111546320\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546848\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111546848->140393111544160\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547136\n", - "\n", - "SqrtBackward0\n", - "\n", - "\n", - "\n", - "140393111547136->140393111546848\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547232\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111547232->140393111547136\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111545360\n", - "\n", - "DivBackward0\n", - "\n", - "\n", - "\n", - "140393111545360->140393111547232\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547424\n", - "\n", - "AddBackward0\n", - "\n", - "\n", - "\n", - "140393111547424->140393111545360\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547520\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111547520->140393111547424\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547616\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393111547616->140393111547520\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111570288\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111570288->140393111547616\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111547328->140393111547424\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111544208->140393111544304\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] + "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n140393102737552\n\nouter_loss\n ()\n\n\n\n140393111544400\n\nMseLossBackward0\n\n\n\n140393111544400->140393102737552\n\n\n\n\n\n140393111544304\n\nMulBackward0\n\n\n\n140393111544304->140393111544400\n\n\n\n\n\n140396584753232\n\nAddBackward0\n step1.a\n ()\n\n\n\n140396584753232->140393111544304\n\n\n\n\n\n140393111544016\n\nAccumulateGrad\n\n\n\n140393111544016->140396584753232\n\n\n\n\n\n140393111547280\n\nMulBackward0\n\n\n\n140393111544016->140393111547280\n\n\n\n\n\n140393111570848\n\nstep0.a\n ()\n\n\n\n140393111570848->140393111544016\n\n\n\n\n\n140393111544256\n\nMulBackward0\n\n\n\n140393111544256->140396584753232\n\n\n\n\n\n140393111544160\n\nDivBackward0\n\n\n\n140393111544160->140393111544256\n\n\n\n\n\n140393111546512\n\nDivBackward0\n\n\n\n140393111546512->140393111544160\n\n\n\n\n\n140393111544112\n\nAddBackward0\n\n\n\n140393111544112->140393111546512\n\n\n\n\n\n140393111546368\n\nMulBackward0\n\n\n\n140393111546368->140393111544112\n\n\n\n\n\n140393111547040\n\nAccumulateGrad\n\n\n\n140393111547040->140393111546368\n\n\n\n\n\n140393111569408\n\n ()\n\n\n\n140393111569408->140393111547040\n\n\n\n\n\n140393111546272\n\nPowBackward0\n\n\n\n140393111546272->140393111544112\n\n\n\n\n\n140393111547088\n\nMulBackward0\n\n\n\n140393111547088->140393111546272\n\n\n\n\n\n140393111547328\n\nPowBackward0\n\n\n\n140393111547088->140393111547328\n\n\n\n\n\n140393111547184\n\nMseLossBackwardBackward0\n\n\n\n140393111547184->140393111547088\n\n\n\n\n\n140393111547280->140393111547184\n\n\n\n\n\n140393111546944\n\nPowBackward0\n\n\n\n140393111546944->140393111547088\n\n\n\n\n\n140393111546944->140393111547280\n\n\n\n\n\n140393111546320\n\nAccumulateGrad\n\n\n\n140393111546320->140393111546944\n\n\n\n\n\n140393111544208\n\nPowBackward0\n\n\n\n140393111546320->140393111544208\n\n\n\n\n\n140393111571168\n\nx\n ()\n\n\n\n140393111571168->140393111546320\n\n\n\n\n\n140393111546848\n\nAddBackward0\n\n\n\n140393111546848->140393111544160\n\n\n\n\n\n140393111547136\n\nSqrtBackward0\n\n\n\n140393111547136->140393111546848\n\n\n\n\n\n140393111547232\n\nAddBackward0\n\n\n\n140393111547232->140393111547136\n\n\n\n\n\n140393111545360\n\nDivBackward0\n\n\n\n140393111545360->140393111547232\n\n\n\n\n\n140393111547424\n\nAddBackward0\n\n\n\n140393111547424->140393111545360\n\n\n\n\n\n140393111547520\n\nMulBackward0\n\n\n\n140393111547520->140393111547424\n\n\n\n\n\n140393111547616\n\nAccumulateGrad\n\n\n\n140393111547616->140393111547520\n\n\n\n\n\n140393111570288\n\n ()\n\n\n\n140393111570288->140393111547616\n\n\n\n\n\n140393111547328->140393111547424\n\n\n\n\n\n140393111544208->140393111544304\n\n\n\n\n\n" }, "metadata": {}, "output_type": "display_data" @@ -994,12 +272,18 @@ "optim = torchopt.MetaAdam(net, lr=1.)\n", "\n", "# Get the reference of state dictionary\n", - "init_net_state = torchopt.extract_state_dict(net)\n", - "init_optim_state = torchopt.extract_state_dict(optim)\n", + "init_net_state = torchopt.extract_state_dict(net, by='reference')\n", + "init_optim_state = torchopt.extract_state_dict(optim, by='reference')\n", + "# If set `detach_buffers=True`, the parameters are referenced as references while buffers are detached copies\n", + "init_net_state = torchopt.extract_state_dict(net, by='reference', detach_buffers=True)\n", "\n", - "# Set `copy=True` to get the copy of state dictionary\n", - "init_net_state_copy = torchopt.extract_state_dict(net, copy=True)\n", - "init_optim_state_copy = torchopt.extract_state_dict(optim, copy=True)\n", + "# Set `copy` to get the copy of state dictionary\n", + "init_net_state_copy = torchopt.extract_state_dict(net, by='copy')\n", + "init_optim_state_copy = torchopt.extract_state_dict(optim, by='copy')\n", + "\n", + "# Set `deepcopy` to get the detached copy of state dictionary\n", + "init_net_state_deepcopy = torchopt.extract_state_dict(net, by='deepcopy')\n", + "init_optim_state_deepcopy = torchopt.extract_state_dict(optim, by='deepcopy')\n", "\n", "# Conduct 2 inner-loop optimization\n", "for i in range(2):\n", @@ -1096,8 +380,8 @@ ], "source": [ "# Get the reference of state dictionary\n", - "init_net_state = torchopt.extract_state_dict(net)\n", - "init_optim_state = torchopt.extract_state_dict(optim)\n", + "init_net_state = torchopt.extract_state_dict(net, by='reference')\n", + "init_optim_state = torchopt.extract_state_dict(optim, by='reference')\n", "# The `state_dict` is empty for vanilla SGD optimizer\n", "print(f'init_optim_state = {init_optim_state!r}')\n", "\n", @@ -1247,362 +531,7 @@ }, { "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "%3\n", - "\n", - "\n", - "\n", - "140393102828544\n", - "\n", - "outer_loss\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111546128\n", - "\n", - "MseLossBackward0\n", - "\n", - "\n", - "\n", - "140393111546128->140393102828544\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546032\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111546032->140393111546128\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140396237940288\n", - "\n", - "AddBackward0\n", - " step1.a\n", - " ()\n", - "\n", - "\n", - "\n", - "140396237940288->140393111546032\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111546464\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393111546464->140396237940288\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725760\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393111546464->140393102725760\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102827744\n", - "\n", - "step0.a\n", - " ()\n", - "\n", - "\n", - "\n", - "140393102827744->140393111546464\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725232\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393102725232->140396237940288\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393112318976\n", - "\n", - "UpdatesOpBackward\n", - "\n", - "\n", - "\n", - "140393112318976->140393102725232\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140396647894368\n", - "\n", - "MuOpBackward\n", - "\n", - "\n", - "\n", - "140396647894368->140393112318976\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725472\n", - "\n", - "MulBackward0\n", - "\n", - "\n", - "\n", - "140393102725472->140396647894368\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393112318736\n", - "\n", - "NuOpBackward\n", - "\n", - "\n", - "\n", - "140393102725472->140393112318736\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725616\n", - "\n", - "MseLossBackwardBackward0\n", - "\n", - "\n", - "\n", - "140393102725616->140393102725472\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725760->140393102725616\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725568\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393102725568->140393102725472\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725568->140393102725760\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725904\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393102725904->140393102725568\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111543968\n", - "\n", - "PowBackward0\n", - "\n", - "\n", - "\n", - "140393102725904->140393111543968\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111485872\n", - "\n", - "x\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111485872->140393102725904\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725328\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393102725328->140396647894368\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111534224\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111534224->140396647894368\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111534224->140393102725328\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111531904\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393111531904->140396647894368\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111531904->140393112318736\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393112318736->140393112318976\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102725712\n", - "\n", - "AccumulateGrad\n", - "\n", - "\n", - "\n", - "140393102725712->140393112318736\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102827824\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393102827824->140393112318736\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102827824->140393102725712\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102828784\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393102828784->140393112318976\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102828144\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393102828144->140393112318976\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393102828224\n", - "\n", - " ()\n", - "\n", - "\n", - "\n", - "140393102828224->140393112318976\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "140393111543968->140393111546032\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ] + "image/svg+xml": "\n\n\n\n\n\n%3\n\n\n\n140393102828544\n\nouter_loss\n ()\n\n\n\n140393111546128\n\nMseLossBackward0\n\n\n\n140393111546128->140393102828544\n\n\n\n\n\n140393111546032\n\nMulBackward0\n\n\n\n140393111546032->140393111546128\n\n\n\n\n\n140396237940288\n\nAddBackward0\n step1.a\n ()\n\n\n\n140396237940288->140393111546032\n\n\n\n\n\n140393111546464\n\nAccumulateGrad\n\n\n\n140393111546464->140396237940288\n\n\n\n\n\n140393102725760\n\nMulBackward0\n\n\n\n140393111546464->140393102725760\n\n\n\n\n\n140393102827744\n\nstep0.a\n ()\n\n\n\n140393102827744->140393111546464\n\n\n\n\n\n140393102725232\n\nMulBackward0\n\n\n\n140393102725232->140396237940288\n\n\n\n\n\n140393112318976\n\nUpdatesOpBackward\n\n\n\n140393112318976->140393102725232\n\n\n\n\n\n140396647894368\n\nMuOpBackward\n\n\n\n140396647894368->140393112318976\n\n\n\n\n\n140393102725472\n\nMulBackward0\n\n\n\n140393102725472->140396647894368\n\n\n\n\n\n140393112318736\n\nNuOpBackward\n\n\n\n140393102725472->140393112318736\n\n\n\n\n\n140393102725616\n\nMseLossBackwardBackward0\n\n\n\n140393102725616->140393102725472\n\n\n\n\n\n140393102725760->140393102725616\n\n\n\n\n\n140393102725568\n\nPowBackward0\n\n\n\n140393102725568->140393102725472\n\n\n\n\n\n140393102725568->140393102725760\n\n\n\n\n\n140393102725904\n\nAccumulateGrad\n\n\n\n140393102725904->140393102725568\n\n\n\n\n\n140393111543968\n\nPowBackward0\n\n\n\n140393102725904->140393111543968\n\n\n\n\n\n140393111485872\n\nx\n ()\n\n\n\n140393111485872->140393102725904\n\n\n\n\n\n140393102725328\n\nAccumulateGrad\n\n\n\n140393102725328->140396647894368\n\n\n\n\n\n140393111534224\n\n ()\n\n\n\n140393111534224->140396647894368\n\n\n\n\n\n140393111534224->140393102725328\n\n\n\n\n\n140393111531904\n\n ()\n\n\n\n140393111531904->140396647894368\n\n\n\n\n\n140393111531904->140393112318736\n\n\n\n\n\n140393112318736->140393112318976\n\n\n\n\n\n140393102725712\n\nAccumulateGrad\n\n\n\n140393102725712->140393112318736\n\n\n\n\n\n140393102827824\n\n ()\n\n\n\n140393102827824->140393112318736\n\n\n\n\n\n140393102827824->140393102725712\n\n\n\n\n\n140393102828784\n\n ()\n\n\n\n140393102828784->140393112318976\n\n\n\n\n\n140393102828144\n\n ()\n\n\n\n140393102828144->140393112318976\n\n\n\n\n\n140393102828224\n\n ()\n\n\n\n140393102828224->140393112318976\n\n\n\n\n\n140393111543968->140393111546032\n\n\n\n\n\n" }, "metadata": {}, "output_type": "display_data" @@ -1615,10 +544,10 @@ "\n", "optim = torchopt.MetaAdam(net, lr=1., moment_requires_grad=True, use_accelerated_op=True)\n", "\n", - "net_state_0 = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step0.')\n", + "net_state_0 = torchopt.extract_state_dict(net, by='reference', enable_visual=True, visual_prefix='step0.')\n", "inner_loss = F.mse_loss(net(x), y)\n", "optim.step(inner_loss)\n", - "net_state_1 = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step1.')\n", + "net_state_1 = torchopt.extract_state_dict(net, by='reference', enable_visual=True, visual_prefix='step1.')\n", "\n", "outer_loss = F.mse_loss(net(x), y)\n", "display(torchopt.visual.make_dot(outer_loss, params=[net_state_0, net_state_1, {'x': x, 'outer_loss': outer_loss}]))" @@ -1641,7 +570,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.8.12" }, "vscode": { "interpreter": { From fa03d11e05447565bd188e1d92a537abb76f8606 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 8 Oct 2022 20:41:58 +0800 Subject: [PATCH 24/69] style: format tutorial notebooks --- .pre-commit-config.yaml | 2 +- Makefile | 6 +- conda-recipe.yaml | 2 +- pyproject.toml | 3 +- tests/requirements.txt | 2 +- torchopt/_C/adam_op.pyi | 1 + tutorials/1_Functional_Optimizer.ipynb | 25 +++---- tutorials/2_Visualization.ipynb | 10 ++- tutorials/3_Meta_Optimizer.ipynb | 79 ++++++++++++++-------- tutorials/4_Stop_Gradient.ipynb | 33 +++++---- tutorials/5_Implicit_Differentiation.ipynb | 14 ++-- 11 files changed, 107 insertions(+), 70 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21062f0e..90bedada 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - repo: https://github.com/psf/black rev: 22.8.0 hooks: - - id: black + - id: black-jupyter stages: [commit, push, manual] - repo: local hooks: diff --git a/Makefile b/Makefile index a0d72709..5dd4a4cf 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ flake8-install: py-format-install: $(call check_pip_install,isort) - $(call check_pip_install,black) + $(call check_pip_install_extra,black,black[jupyter]) mypy-install: $(call check_pip_install,mypy) @@ -107,7 +107,7 @@ flake8: flake8-install py-format: py-format-install $(PYTHON) -m isort --project $(PROJECT_NAME) --check $(PYTHON_FILES) && \ - $(PYTHON) -m black --check $(PYTHON_FILES) + $(PYTHON) -m black --check $(PYTHON_FILES) tutorials mypy: mypy-install $(PYTHON) -m mypy $(PROJECT_PATH) @@ -147,7 +147,7 @@ lint: flake8 py-format mypy pylint clang-format cpplint docstyle spelling format: py-format-install clang-format-install addlicense-install $(PYTHON) -m isort --project $(PROJECT_NAME) $(PYTHON_FILES) - $(PYTHON) -m black $(PYTHON_FILES) + $(PYTHON) -m black $(PYTHON_FILES) tutorials clang-format -style=file -i $(CXX_FILES) addlicense -c $(COPYRIGHT) -l apache -y 2022 $(SOURCE_FOLDERS) diff --git a/conda-recipe.yaml b/conda-recipe.yaml index d6f88b08..d6d94be3 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -72,7 +72,7 @@ dependencies: - pytest-cov - pytest-xdist - isort - - conda-forge::black >= 22.6.0 + - conda-forge::black-jupyter >= 22.6.0 - pylint - mypy - flake8 diff --git a/pyproject.toml b/pyproject.toml index b629ca60..f8b1363b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,7 @@ Documentation = "https://torchopt.readthedocs.io" [project.optional-dependencies] lint = [ "isort", - "black >= 22.6.0", + "black[jupyter] >= 22.6.0", "pylint", "mypy", "flake8", @@ -171,6 +171,7 @@ skip-string-normalization = true target-version = ["py37", "py38", "py39", "py310"] [tool.isort] +atomic = true profile = "black" src_paths = ["torchopt", "examples", "tests"] indent = 4 diff --git a/tests/requirements.txt b/tests/requirements.txt index 11b76eb6..51955f5d 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -8,7 +8,7 @@ pytest pytest-cov pytest-xdist isort -black >= 22.6.0 +black[jupyter] >= 22.6.0 pylint mypy flake8 diff --git a/torchopt/_C/adam_op.pyi b/torchopt/_C/adam_op.pyi index 7b98a576..5430e111 100644 --- a/torchopt/_C/adam_op.pyi +++ b/torchopt/_C/adam_op.pyi @@ -13,6 +13,7 @@ # limitations under the License. # ============================================================================== +# pylint: disable=all # isort: off from typing import Tuple diff --git a/tutorials/1_Functional_Optimizer.ipynb b/tutorials/1_Functional_Optimizer.ipynb index 8ed3571f..3f7ba55b 100644 --- a/tutorials/1_Functional_Optimizer.ipynb +++ b/tutorials/1_Functional_Optimizer.ipynb @@ -88,7 +88,7 @@ " return jnp.matmul(x, params['weight']) + params['bias']\n", "\n", " # Obtain the `opt_state` that contains statistics for the optimizer\n", - " learning_rate = 1.\n", + " learning_rate = 1.0\n", " optimizer = optax.adam(learning_rate)\n", " opt_state = optimizer.init(params)\n", "\n", @@ -153,7 +153,7 @@ " model, params = functorch.make_functional(net) # get the functional version of the model\n", "\n", " # Obtain the `opt_state` that contains statistics for the optimizer\n", - " learning_rate = 1.\n", + " learning_rate = 1.0\n", " optimizer = torchopt.adam(learning_rate)\n", " opt_state = optimizer.init(params)\n", "\n", @@ -207,7 +207,7 @@ " net = Net(dim)\n", " model, params = functorch.make_functional(net) # get the functional version of the model\n", "\n", - " learning_rate = 1.\n", + " learning_rate = 1.0\n", " # The `torchopt.FuncOptimizer` wrapper makes it easier to maintain the optimizer states.\n", " optimizer = torchopt.FuncOptimizer(torchopt.adam(learning_rate))\n", "\n", @@ -266,7 +266,7 @@ " dim = 1\n", " net = Net(dim)\n", "\n", - " learning_rate = 1.\n", + " learning_rate = 1.0\n", " optim = torchopt.Adam(net.parameters(), lr=learning_rate)\n", "\n", " xs = 2 * torch.ones((batch_size, dim))\n", @@ -326,7 +326,7 @@ " dim = 1\n", " net = Net(dim)\n", "\n", - " learning_rate = 1.\n", + " learning_rate = 1.0\n", " optim = torch.optim.Adam(net.parameters(), lr=learning_rate)\n", "\n", " xs = 2 * torch.ones((batch_size, dim))\n", @@ -393,7 +393,7 @@ " meta_param = nn.Parameter(torch.ones(1))\n", "\n", " # SGD example\n", - " learning_rate = 1.\n", + " learning_rate = 1.0\n", " optimizer = torchopt.sgd(learning_rate)\n", " opt_state = optimizer.init(params)\n", "\n", @@ -407,7 +407,8 @@ "\n", " grads = torch.autograd.grad(loss, params, create_graph=True)\n", " updates, opt_state = optimizer.update(grads, opt_state, inplace=False)\n", - " params = torchopt.apply_updates(params, updates, inplace=False) # update parameters with single step SGD update\n", + " # Update parameters with single step SGD update\n", + " params = torchopt.apply_updates(params, updates, inplace=False)\n", "\n", " pred = model(params, xs)\n", " loss = mse(pred, ys)\n", @@ -448,7 +449,7 @@ "metadata": {}, "outputs": [], "source": [ - "optim = torchopt.adam(lr=1., moment_requires_grad=False)" + "optim = torchopt.adam(lr=1.0, moment_requires_grad=False)" ] }, { @@ -457,7 +458,7 @@ "metadata": {}, "outputs": [], "source": [ - "optim = torchopt.adam(lr=1., moment_requires_grad=True)" + "optim = torchopt.adam(lr=1.0, moment_requires_grad=True)" ] }, { @@ -466,7 +467,7 @@ "metadata": {}, "outputs": [], "source": [ - "optim = torchopt.sgd(lr=1., momentum=0.8, moment_requires_grad=True)" + "optim = torchopt.sgd(lr=1.0, momentum=0.8, moment_requires_grad=True)" ] }, { @@ -526,7 +527,7 @@ "outputs": [], "source": [ "net = Net(1).cuda()\n", - "optim = torchopt.Adam(net.parameters(), lr=1., use_accelerated_op=True)" + "optim = torchopt.Adam(net.parameters(), lr=1.0, use_accelerated_op=True)" ] }, { @@ -535,7 +536,7 @@ "metadata": {}, "outputs": [], "source": [ - "optim = torchopt.adam(lr=1., use_accelerated_op=True)" + "optim = torchopt.adam(lr=1.0, use_accelerated_op=True)" ] } ], diff --git a/tutorials/2_Visualization.ipynb b/tutorials/2_Visualization.ipynb index 061d71fd..9b47b402 100644 --- a/tutorials/2_Visualization.ipynb +++ b/tutorials/2_Visualization.ipynb @@ -116,7 +116,7 @@ "import torchopt\n", "\n", "\n", - "x = torch.tensor(1., requires_grad=True)\n", + "x = torch.tensor(1.0, requires_grad=True)\n", "y = 2 * x\n", "display(torchopt.visual.make_dot(y, params={'x': x, 'y': y}))" ] @@ -668,7 +668,7 @@ "ys = torch.ones((batch_size, 1))\n", "\n", "optimizer = torchopt.MetaSGD(net, lr=1e-3)\n", - "meta_param = torch.tensor(1., requires_grad=True)\n", + "meta_param = torch.tensor(1.0, requires_grad=True)\n", "\n", "# Set enable_visual\n", "net_state_0 = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step0.')\n", @@ -684,7 +684,11 @@ "loss = F.mse_loss(pred, torch.ones_like(pred))\n", "\n", "# Draw computation graph\n", - "display(torchopt.visual.make_dot(loss, [net_state_0, net_state_1, {'meta_param': meta_param, 'loss': loss}]))" + "display(\n", + " torchopt.visual.make_dot(\n", + " loss, [net_state_0, net_state_1, {'meta_param': meta_param, 'loss': loss}]\n", + " )\n", + ")" ] } ], diff --git a/tutorials/3_Meta_Optimizer.ipynb b/tutorials/3_Meta_Optimizer.ipynb index 0b371b2d..0ed88df3 100644 --- a/tutorials/3_Meta_Optimizer.ipynb +++ b/tutorials/3_Meta_Optimizer.ipynb @@ -73,10 +73,10 @@ "class Net(nn.Module):\n", " def __init__(self):\n", " super().__init__()\n", - " self.a = nn.Parameter(torch.tensor(1.), requires_grad=True)\n", - " \n", + " self.a = nn.Parameter(torch.tensor(1.0), requires_grad=True)\n", + "\n", " def forward(self, x):\n", - " return self.a * (x ** 2)" + " return self.a * (x**2)" ] }, { @@ -93,7 +93,7 @@ "outputs": [], "source": [ "net = Net()\n", - "x = nn.Parameter(torch.tensor(2.), requires_grad=True)" + "x = nn.Parameter(torch.tensor(2.0), requires_grad=True)" ] }, { @@ -117,7 +117,7 @@ } ], "source": [ - "optim = torchopt.MetaSGD(net, lr=1.)\n", + "optim = torchopt.MetaSGD(net, lr=1.0)\n", "\n", "inner_loss = net(x)\n", "optim.step(inner_loss)\n", @@ -169,10 +169,10 @@ ], "source": [ "net = Net()\n", - "x = nn.Parameter(torch.tensor(2.), requires_grad=True)\n", - "y = torch.tensor(1.)\n", + "x = nn.Parameter(torch.tensor(2.0), requires_grad=True)\n", + "y = torch.tensor(1.0)\n", "\n", - "optim = torchopt.MetaAdam(net, lr=1., moment_requires_grad=False)\n", + "optim = torchopt.MetaAdam(net, lr=1.0, moment_requires_grad=False)\n", "\n", "net_state_0 = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step0.')\n", "inner_loss = F.mse_loss(net(x), y)\n", @@ -180,7 +180,11 @@ "net_state_1 = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step1.')\n", "\n", "outer_loss = F.mse_loss(net(x), y)\n", - "display(torchopt.visual.make_dot(outer_loss, params=[net_state_0, net_state_1, {'x': x, 'outer_loss': outer_loss}]))" + "display(\n", + " torchopt.visual.make_dot(\n", + " outer_loss, params=[net_state_0, net_state_1, {'x': x, 'outer_loss': outer_loss}]\n", + " )\n", + ")" ] }, { @@ -212,10 +216,10 @@ ], "source": [ "net = Net()\n", - "x = nn.Parameter(torch.tensor(2.), requires_grad=True)\n", - "y = torch.tensor(1.)\n", + "x = nn.Parameter(torch.tensor(2.0), requires_grad=True)\n", + "y = torch.tensor(1.0)\n", "\n", - "optim = torchopt.MetaAdam(net, lr=1., moment_requires_grad=True)\n", + "optim = torchopt.MetaAdam(net, lr=1.0, moment_requires_grad=True)\n", "\n", "net_state_0 = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step0.')\n", "inner_loss = F.mse_loss(net(x), y)\n", @@ -223,7 +227,11 @@ "net_state_1 = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step1.')\n", "\n", "outer_loss = F.mse_loss(net(x), y)\n", - "display(torchopt.visual.make_dot(outer_loss, params=[net_state_0, net_state_1, {'x': x, 'outer_loss': outer_loss}]))" + "display(\n", + " torchopt.visual.make_dot(\n", + " outer_loss, params=[net_state_0, net_state_1, {'x': x, 'outer_loss': outer_loss}]\n", + " )\n", + ")" ] }, { @@ -267,9 +275,9 @@ ], "source": [ "net = Net()\n", - "x = nn.Parameter(torch.tensor(2.), requires_grad=True)\n", + "x = nn.Parameter(torch.tensor(2.0), requires_grad=True)\n", "\n", - "optim = torchopt.MetaAdam(net, lr=1.)\n", + "optim = torchopt.MetaAdam(net, lr=1.0)\n", "\n", "# Get the reference of state dictionary\n", "init_net_state = torchopt.extract_state_dict(net, by='reference')\n", @@ -341,19 +349,19 @@ "class Net2Tasks(nn.Module):\n", " def __init__(self):\n", " super().__init__()\n", - " self.a = nn.Parameter(torch.tensor(1.), requires_grad=True)\n", - " \n", + " self.a = nn.Parameter(torch.tensor(1.0), requires_grad=True)\n", + "\n", " def task1(self, x):\n", - " return self.a * x ** 2\n", - " \n", + " return self.a * x**2\n", + "\n", " def task2(self, x):\n", " return self.a * x\n", "\n", "\n", "net = Net2Tasks()\n", - "x = nn.Parameter(torch.tensor(2.), requires_grad=True)\n", + "x = nn.Parameter(torch.tensor(2.0), requires_grad=True)\n", "\n", - "optim = torchopt.MetaSGD(net, lr=1.)" + "optim = torchopt.MetaSGD(net, lr=1.0)" ] }, { @@ -449,9 +457,12 @@ ], "source": [ "net = Net()\n", - "x = nn.Parameter(torch.tensor(2.), requires_grad=True)\n", + "x = nn.Parameter(torch.tensor(2.0), requires_grad=True)\n", "\n", - "optim_impl = torchopt.combine.chain(torchopt.clip.clip_grad_norm(max_norm=2.), torchopt.sgd(lr=1., moment_requires_grad=True))\n", + "optim_impl = torchopt.combine.chain(\n", + " torchopt.clip.clip_grad_norm(max_norm=2.0),\n", + " torchopt.sgd(lr=1.0, moment_requires_grad=True),\n", + ")\n", "optim = torchopt.MetaOptimizer(net, optim_impl)\n", "\n", "inner_loss = net(x)\n", @@ -539,18 +550,26 @@ ], "source": [ "net = Net().to(device='cuda')\n", - "x = nn.Parameter(torch.tensor(2., device=torch.device('cuda')), requires_grad=True)\n", - "y = torch.tensor(1., device=torch.device('cuda'))\n", + "x = nn.Parameter(torch.tensor(2.0, device=torch.device('cuda')), requires_grad=True)\n", + "y = torch.tensor(1.0, device=torch.device('cuda'))\n", "\n", - "optim = torchopt.MetaAdam(net, lr=1., moment_requires_grad=True, use_accelerated_op=True)\n", + "optim = torchopt.MetaAdam(net, lr=1.0, moment_requires_grad=True, use_accelerated_op=True)\n", "\n", - "net_state_0 = torchopt.extract_state_dict(net, by='reference', enable_visual=True, visual_prefix='step0.')\n", + "net_state_0 = torchopt.extract_state_dict(\n", + " net, by='reference', enable_visual=True, visual_prefix='step0.'\n", + ")\n", "inner_loss = F.mse_loss(net(x), y)\n", "optim.step(inner_loss)\n", - "net_state_1 = torchopt.extract_state_dict(net, by='reference', enable_visual=True, visual_prefix='step1.')\n", + "net_state_1 = torchopt.extract_state_dict(\n", + " net, by='reference', enable_visual=True, visual_prefix='step1.'\n", + ")\n", "\n", "outer_loss = F.mse_loss(net(x), y)\n", - "display(torchopt.visual.make_dot(outer_loss, params=[net_state_0, net_state_1, {'x': x, 'outer_loss': outer_loss}]))" + "display(\n", + " torchopt.visual.make_dot(\n", + " outer_loss, params=[net_state_0, net_state_1, {'x': x, 'outer_loss': outer_loss}]\n", + " )\n", + ")" ] } ], @@ -570,7 +589,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.8.13" }, "vscode": { "interpreter": { diff --git a/tutorials/4_Stop_Gradient.ipynb b/tutorials/4_Stop_Gradient.ipynb index 8096afa0..dba2a79f 100644 --- a/tutorials/4_Stop_Gradient.ipynb +++ b/tutorials/4_Stop_Gradient.ipynb @@ -40,10 +40,11 @@ " def __init__(self, dim):\n", " super().__init__()\n", " self.fc = nn.Linear(dim, 1, bias=True)\n", - " \n", + "\n", " def forward(self, x):\n", " return self.fc(x)\n", "\n", + "\n", "loss_fn = F.mse_loss" ] }, @@ -81,7 +82,7 @@ "metadata": {}, "outputs": [], "source": [ - "meta_parameter = nn.Parameter(torch.tensor(1.), requires_grad=True)\n", + "meta_parameter = nn.Parameter(torch.tensor(1.0), requires_grad=True)\n", "\n", "optim = torchopt.MetaSGD(net, lr=1e-1)\n", "meta_optim = torch.optim.Adam([meta_parameter], lr=1e-1)" @@ -229,12 +230,7 @@ "inner_loss = loss_fn(net(x), y)\n", "\n", "print(f'inner loss: {inner_loss:.4f}')\n", - "display(\n", - " torchopt.visual.make_dot(\n", - " inner_loss,\n", - " params=(init_net_state, {'inner_loss': inner_loss})\n", - " )\n", - ")" + "display(torchopt.visual.make_dot(inner_loss, params=(init_net_state, {'inner_loss': inner_loss})))" ] }, { @@ -620,7 +616,11 @@ "display(\n", " torchopt.visual.make_dot(\n", " outer_loss,\n", - " params=(init_net_state, one_step_net_state, {'meta_parameter': meta_parameter, 'outer_loss': outer_loss})\n", + " params=(\n", + " init_net_state,\n", + " one_step_net_state,\n", + " {'meta_parameter': meta_parameter, 'outer_loss': outer_loss},\n", + " ),\n", " )\n", ")" ] @@ -1294,7 +1294,11 @@ "display(\n", " torchopt.visual.make_dot(\n", " outer_loss,\n", - " params=(init_net_state, one_step_net_state, {'meta_parameter': meta_parameter, 'outer_loss': outer_loss})\n", + " params=(\n", + " init_net_state,\n", + " one_step_net_state,\n", + " {'meta_parameter': meta_parameter, 'outer_loss': outer_loss},\n", + " ),\n", " )\n", ")\n", "\n", @@ -1675,7 +1679,9 @@ "# Stop gradient and make them become the leaf node\n", "torchopt.stop_gradient(net)\n", "torchopt.stop_gradient(optim)\n", - "one_step_net_state_detached = torchopt.extract_state_dict(net, enable_visual=True, visual_prefix='step1.detached.')\n", + "one_step_net_state_detached = torchopt.extract_state_dict(\n", + " net, enable_visual=True, visual_prefix='step1.detached.'\n", + ")\n", "\n", "# Inner update\n", "inner_loss = loss_fn(net(x), y)\n", @@ -1693,7 +1699,10 @@ "display(\n", " torchopt.visual.make_dot(\n", " outer_loss,\n", - " params=(one_step_net_state_detached, {'meta_parameter': meta_parameter, 'outer_loss': outer_loss})\n", + " params=(\n", + " one_step_net_state_detached,\n", + " {'meta_parameter': meta_parameter, 'outer_loss': outer_loss},\n", + " ),\n", " )\n", ")" ] diff --git a/tutorials/5_Implicit_Differentiation.ipynb b/tutorials/5_Implicit_Differentiation.ipynb index 18a7d1e8..0bc0e59e 100644 --- a/tutorials/5_Implicit_Differentiation.ipynb +++ b/tutorials/5_Implicit_Differentiation.ipynb @@ -88,6 +88,7 @@ " loss = F.mse_loss(y_pred, y) + regularization_loss\n", " return loss\n", "\n", + "\n", "# Optimality Condition is: the gradient w.r.t inner-loop optimal params is 0 (we achieve so by\n", "# specifying argnums=0 in functorch.grad) the argnums=1 specify which meta-parameter we want to\n", "# backpropogate, in this case we want to backpropogate to the initial parameters so we set it as 1.\n", @@ -106,16 +107,16 @@ " with torch.enable_grad():\n", " # Temporarily enable gradient computation for conducting the optimization\n", " for i in range(100):\n", - " pred = fmodel(params, x) \n", - " loss = F.mse_loss(pred, y) # compute loss\n", - " \n", + " pred = fmodel(params, x)\n", + " loss = F.mse_loss(pred, y) # compute loss\n", + "\n", " # Compute regularization loss\n", " regularization_loss = 0.0\n", " for p1, p2 in zip(params, init_params):\n", " regularization_loss += 0.5 * torch.sum(torch.square(p1.view(-1) - p2.view(-1)))\n", " final_loss = loss + regularization_loss\n", - " \n", - " grads = torch.autograd.grad(final_loss, params) # compute gradients\n", + "\n", + " grads = torch.autograd.grad(final_loss, params) # compute gradients\n", " updates, opt_state = optimizer.update(grads, opt_state) # get updates\n", " params = torchopt.apply_updates(params, updates)\n", "\n", @@ -172,6 +173,7 @@ " def forward(self, x):\n", " return self.fc(x)\n", "\n", + "\n", "model = Net(4)\n", "fmodel, meta_params = functorch.make_functional(model)\n", "data = (x, y, fmodel)\n", @@ -252,7 +254,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.8.13" }, "vscode": { "interpreter": { From 0a9703d41d2b7b99ebdf44319678121b59b0776d Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Sun, 9 Oct 2022 22:48:05 +0800 Subject: [PATCH 25/69] fix: appease linters (#97) Co-authored-by: Xuehai Pan --- Makefile | 6 +++++- docs/source/spelling_wordlist.txt | 3 ++- tests/requirements.txt | 3 ++- torchopt/linalg.py | 2 +- torchopt/linear_solve.py | 4 ++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 5dd4a4cf..7633939a 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,10 @@ pre-commit-install: docs-install: $(call check_pip_install,pydocstyle) - $(call check_pip_install,doc8) + $(PYTHON) -m pip uninstall --yes doc8 + $(call check_pip_install_extra,doc8, "doc8<1") + $(PYTHON) -m pip uninstall --yes importlib_metadata + $(call check_pip_install_extra,importlib_metadata, "importlib_metadata<5") $(call check_pip_install,sphinx) $(call check_pip_install,sphinx-rtd-theme) $(call check_pip_install,sphinx-autoapi) @@ -129,6 +132,7 @@ addlicense: addlicense-install addlicense -c $(COPYRIGHT) -l apache -y 2022 -check $(SOURCE_FOLDERS) docstyle: docs-install + make -C docs clean $(PYTHON) -m pydocstyle $(PROJECT_PATH) && doc8 docs && make -C docs html SPHINXOPTS="-W" docs: docs-install diff --git a/docs/source/spelling_wordlist.txt b/docs/source/spelling_wordlist.txt index 22e3c832..f590b546 100644 --- a/docs/source/spelling_wordlist.txt +++ b/docs/source/spelling_wordlist.txt @@ -83,7 +83,8 @@ subtrees optimality argnums matvec -Hermitian +hermitian deepcopy +deepclone RRef rref diff --git a/tests/requirements.txt b/tests/requirements.txt index 51955f5d..cf1a0452 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -13,7 +13,8 @@ pylint mypy flake8 flake8-bugbear -doc8 +# https://github.com/PyCQA/doc8/issues/112 +doc8<1 pydocstyle pyenchant cpplint diff --git a/torchopt/linalg.py b/torchopt/linalg.py index 32b18503..12bcb3a8 100644 --- a/torchopt/linalg.py +++ b/torchopt/linalg.py @@ -188,7 +188,7 @@ def cg( Args: A: (tensor or tree of tensors or function) 2D array or function that calculates the linear map (matrix-vector product) ``Ax`` when - called like ``A(x)``. ``A`` must represent a Hermitian, positive definite matrix, and + called like ``A(x)``. ``A`` must represent a hermitian, positive definite matrix, and must return array(s) with the same structure and shape as its argument. b: (tensor or tree of tensors) Right hand side of the linear system representing a single vector. Can be stored as an diff --git a/torchopt/linear_solve.py b/torchopt/linear_solve.py index 3c15a962..6bb7e011 100644 --- a/torchopt/linear_solve.py +++ b/torchopt/linear_solve.py @@ -68,7 +68,7 @@ def solve_cg( ) -> 'TensorTree': """Solves ``A x = b`` using conjugate gradient. - It assumes that ``A`` is a Hermitian, positive definite matrix. + It assumes that ``A`` is a hermitian, positive definite matrix. Args: matvec: a function that returns the product between ``A`` and a vector. @@ -107,7 +107,7 @@ def _solve_normal_cg( ) -> TensorTree: """Solves the normal equation ``A^T A x = A^T b`` using conjugate gradient. - This can be used to solve ``A x = b`` using conjugate gradient when ``A`` is not Hermitian, + This can be used to solve ``A x = b`` using conjugate gradient when ``A`` is not hermitian, positive definite. Args: From 5f4680e087ca3d3ded3284cb8d0b8042943389cf Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sun, 9 Oct 2022 23:09:29 +0800 Subject: [PATCH 26/69] deps: update requirement constraints --- Makefile | 9 +++++---- conda-recipe.yaml | 2 +- pyproject.toml | 2 +- tests/requirements.txt | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 7633939a..f4e5f7ea 100644 --- a/Makefile +++ b/Makefile @@ -54,10 +54,11 @@ pre-commit-install: docs-install: $(call check_pip_install,pydocstyle) - $(PYTHON) -m pip uninstall --yes doc8 - $(call check_pip_install_extra,doc8, "doc8<1") - $(PYTHON) -m pip uninstall --yes importlib_metadata - $(call check_pip_install_extra,importlib_metadata, "importlib_metadata<5") + $(call check_pip_install_extra,doc8,"doc8<1.0.0a0") + if ! $(PYTHON) -c "import sys; exit(sys.version_info < (3, 8))"; then \ + $(PYTHON) -m pip uninstall --yes importlib-metadata; \ + $(call check_pip_install_extra,importlib-metadata,"importlib-metadata<5.0.0a0"); \ + fi $(call check_pip_install,sphinx) $(call check_pip_install,sphinx-rtd-theme) $(call check_pip_install,sphinx-autoapi) diff --git a/conda-recipe.yaml b/conda-recipe.yaml index d6d94be3..4b6989b2 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -77,7 +77,7 @@ dependencies: - mypy - flake8 - flake8-bugbear - - doc8 + - doc8 < 1.0.0a0 - pydocstyle - clang-format - clang-tools # clang-tidy diff --git a/pyproject.toml b/pyproject.toml index f8b1363b..0d74fd78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ lint = [ "mypy", "flake8", "flake8-bugbear", - "doc8", + "doc8 < 1.0.0a0", "pydocstyle", "pyenchant", "cpplint", diff --git a/tests/requirements.txt b/tests/requirements.txt index cf1a0452..4cebb171 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -14,7 +14,7 @@ mypy flake8 flake8-bugbear # https://github.com/PyCQA/doc8/issues/112 -doc8<1 +doc8 < 1.0.0a0 pydocstyle pyenchant cpplint From fad99d84dd8b6deb4c2d59d5bc43dedcd659c090 Mon Sep 17 00:00:00 2001 From: Hello_World Date: Tue, 11 Oct 2022 20:31:58 +0800 Subject: [PATCH 27/69] feat(zero_order): implemented the zero order feature (#93) Co-authored-by: Benjamin-eecs Co-authored-by: Xuehai Pan --- .pylintrc | 2 +- CHANGELOG.md | 1 + pyproject.toml | 1 + torchopt/__init__.py | 1 + torchopt/accelerated_op/adam_op.py | 3 - torchopt/alias.py | 2 +- torchopt/base.py | 9 +- torchopt/distributed/api.py | 27 +-- torchopt/implicit_diff.py | 242 +++++++++++--------- torchopt/linalg.py | 24 +- torchopt/optim/base.py | 30 +-- torchopt/optim/func/base.py | 6 +- torchopt/optim/meta/base.py | 34 ++- torchopt/transform.py | 48 ++-- torchopt/typing.py | 7 +- torchopt/utils.py | 32 +-- torchopt/zero_order_diff.py | 347 +++++++++++++++++++++++++++++ 17 files changed, 585 insertions(+), 231 deletions(-) create mode 100644 torchopt/zero_order_diff.py diff --git a/.pylintrc b/.pylintrc index 1b77af4c..73dbcdf0 100644 --- a/.pylintrc +++ b/.pylintrc @@ -444,7 +444,7 @@ indent-after-paren=4 indent-string=' ' # Maximum number of characters on a single line. -max-line-length=100 +max-line-length=120 # Maximum number of lines in a module. max-module-lines=1000 diff --git a/CHANGELOG.md b/CHANGELOG.md index 33e97795..7a978e0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add zero-order gradient estimation by [@JieRen98](https://github.com/JieRen98) in [#93](https://github.com/metaopt/torchopt/pull/93). - Add RPC-based distributed training support and add distributed MAML example by [@XuehaiPan](https://github.com/XuehaiPan) in [#83](https://github.com/metaopt/torchopt/pull/83). - Add full type hints by [@XuehaiPan](https://github.com/XuehaiPan) in [#92](https://github.com/metaopt/torchopt/pull/92). - Add API documentation and tutorial for implicit gradients by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan) in [#73](https://github.com/metaopt/torchopt/pull/73). diff --git a/pyproject.toml b/pyproject.toml index 0d74fd78..f5eaaf82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -174,6 +174,7 @@ target-version = ["py37", "py38", "py39", "py310"] atomic = true profile = "black" src_paths = ["torchopt", "examples", "tests"] +extra_standard_library = ["typing_extensions"] indent = 4 line_length = 100 lines_after_imports = 2 diff --git a/torchopt/__init__.py b/torchopt/__init__.py index deafcc55..f9b81614 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -26,6 +26,7 @@ schedule, typing, visual, + zero_order_diff, ) from torchopt.accelerated_op import is_available as accelerated_op_available from torchopt.alias import adam, adamw, rmsprop, sgd diff --git a/torchopt/accelerated_op/adam_op.py b/torchopt/accelerated_op/adam_op.py index 48f83584..774ac702 100644 --- a/torchopt/accelerated_op/adam_op.py +++ b/torchopt/accelerated_op/adam_op.py @@ -31,7 +31,6 @@ class MuOp(torch.autograd.Function): # pylint: disable=abstract-method @staticmethod def jvp(ctx: Any, *grad_inputs: Any) -> Any: - # pylint: disable-next=line-too-long """Defines a formula for differentiating the operation with forward mode automatic differentiation.""" @staticmethod @@ -58,7 +57,6 @@ class NuOp(torch.autograd.Function): # pylint: disable=abstract-method @staticmethod def jvp(ctx: Any, *grad_inputs: Any) -> Any: - # pylint: disable-next=line-too-long """Defines a formula for differentiating the operation with forward mode automatic differentiation.""" @staticmethod @@ -85,7 +83,6 @@ class UpdatesOp(torch.autograd.Function): # pylint: disable=abstract-method @staticmethod def jvp(ctx: Any, *grad_inputs: Any) -> Any: - # pylint: disable-next=line-too-long """Defines a formula for differentiating the operation with forward mode automatic differentiation.""" @staticmethod diff --git a/torchopt/alias.py b/torchopt/alias.py index 4d641b4f..07fdd96a 100644 --- a/torchopt/alias.py +++ b/torchopt/alias.py @@ -130,7 +130,7 @@ def _scale_by_neg_lr(lr: ScalarOrSchedule): if callable(lr): def schedule_wrapper(count): - return -lr(count) + return -lr(count) # type: ignore[operator] # pylint: disable-next=protected-access return transform._scale_by_schedule(schedule_wrapper, already_flattened=True) diff --git a/torchopt/base.py b/torchopt/base.py index 98074204..64104167 100644 --- a/torchopt/base.py +++ b/torchopt/base.py @@ -34,12 +34,7 @@ import itertools from abc import abstractmethod from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Tuple - - -try: - from typing import Protocol # pylint: disable=unused-import -except ImportError: - from typing_extensions import Protocol # type: ignore[assignment] +from typing_extensions import Protocol # Python 3.8+ if TYPE_CHECKING: @@ -229,7 +224,7 @@ def __new__(cls): @staticmethod def init_fn(params: 'Params') -> 'OptState': # pylint: disable=unused-argument """Returns empty state.""" - return EmptyState() + return EmptyState() # type: ignore[return-value] @staticmethod def update_fn( diff --git a/torchopt/distributed/api.py b/torchopt/distributed/api.py index 80f96311..b782b24d 100644 --- a/torchopt/distributed/api.py +++ b/torchopt/distributed/api.py @@ -35,7 +35,7 @@ import torchopt.pytree as pytree from torchopt.distributed.world import get_worker_id, get_world_rank, get_world_size -from torchopt.typing import Future, PyTree +from torchopt.typing import Future __all__ = [ @@ -116,11 +116,12 @@ def __call__( workers = list(map(get_worker_id, self.workers)) num_workers = len(workers) - args_tree = cast(PyTree[Any], (args, kwargs)) - flattened_args, treedef = pytree.tree_flatten(args_tree) + args_tree = (args, kwargs) + flat_args: List[Any] + flat_args, treedef = pytree.tree_flatten(args_tree) # type: ignore[arg-type] batch_size = None - for arg in flattened_args: + for arg in flat_args: if isinstance(arg, torch.Tensor): if batch_size is None: batch_size = arg.shape[self.dim] @@ -134,7 +135,6 @@ def __call__( return [(get_world_rank(), args, kwargs.copy())] dim_slices: List[Union[int, slice]] - # pylint: disable-next=line-too-long batch_slices: List[Tuple[Union[int, slice, Ellipsis.__class__], ...]] # type: ignore[name-defined] if self.exclusive: num_replicas = batch_size @@ -169,18 +169,18 @@ def __call__( for dim_slice in dim_slices ] - flattened_args_replicas: List[List[Any]] = [[] for _ in range(num_replicas)] - for arg in flattened_args: + flat_args_replicas: List[List[Any]] = [[] for _ in range(num_replicas)] + for arg in flat_args: if isinstance(arg, torch.Tensor): for i, batch_slice in enumerate(batch_slices): - flattened_args_replicas[i].append(arg[batch_slice]) + flat_args_replicas[i].append(arg[batch_slice]) else: for i in range(num_replicas): - flattened_args_replicas[i].append(arg) + flat_args_replicas[i].append(arg) args_replicas: List[Tuple[Args, KwArgs]] = [ pytree.tree_unflatten(treedef, args_replica) # type: ignore[misc] - for args_replica in flattened_args_replicas + for args_replica in flat_args_replicas ] return [ @@ -237,8 +237,6 @@ def dim_partitioner( return TensorDimensionPartitioner(dim, exclusive=exclusive, keepdim=keepdim, workers=workers) -# fmt: off -# pylint: disable=line-too-long batch_partitioner: PartitionFunction = dim_partitioner(dim=0, keepdim=True, exclusive=False) """Partitioner for batch dimension. Divide and replicates the arguments to all workers along the first dimension. @@ -249,7 +247,7 @@ def dim_partitioner( All tensors in the ``args`` and ``kwargs`` will be partitioned along the dimension ``dim``, while the non-tensor values will be broadcasted to partitions. """ -exclusive_batch_partitioner: PartitionFunction = dim_partitioner(dim=0, keepdim=True, exclusive=True) +exclusive_batch_partitioner: PartitionFunction = dim_partitioner(dim=0, keepdim=True, exclusive=True) # fmt: skip """Partitioner for batch dimension. Divide and replicates the arguments to all workers along the first dimension. Each batch sample will be assigned to a separate RPC call. @@ -257,8 +255,6 @@ def dim_partitioner( All tensors in the ``args`` and ``kwargs`` will be partitioned along the dimension ``dim``, while the non-tensor values will be broadcasted to partitions. """ -# pylint: enable=line-too-long -# fmt: on def mean_reducer(results: Iterable[torch.Tensor]) -> torch.Tensor: @@ -280,7 +276,6 @@ def remote_async_call( reducer: Optional[Callable[[Iterable[T]], U]] = None, timeout: Optional[float] = UNSET_RPC_TIMEOUT, ) -> Union[Future[List[T]], Future[U]]: - # pylint: disable=line-too-long """Asynchronously do an RPC on remote workers and return the a :class:`torch.Future` instance at the current worker. Args: diff --git a/torchopt/implicit_diff.py b/torchopt/implicit_diff.py index 6a97e3fb..e6e2c815 100644 --- a/torchopt/implicit_diff.py +++ b/torchopt/implicit_diff.py @@ -34,74 +34,100 @@ KwArgs = Dict[str, Any] +class MaskedOptimalityFn: # pylint: disable=missing-class-docstring,too-few-public-methods + def __init__( + self, + optimality_fn: Callable, + solution: Any, + result_is_tensor: bool, + argnums: Tuple[int, ...], + *args, + ) -> None: + self.optimality_fn = optimality_fn + self.solution = solution + self.result_is_tensor = result_is_tensor + self.argnums = argnums + + pre_filled = [] + post_filled = [] + for idx, arg in enumerate(args): + if idx + 1 in argnums: # plus 1 because we exclude the first argument + post_filled.append(arg) + else: + pre_filled.append(arg) + self.len_args = len(pre_filled) + len(post_filled) + self.pre_filled = tuple(pre_filled) + self.post_filled = tuple(post_filled) + + def __call__(self, *args) -> Any: + true_args = [] + pre_filled_counter = 0 + for idx in range(self.len_args): + if idx + 1 in self.argnums: # plus 1 because we exclude the first argument + arg = args[idx] + else: + arg = self.pre_filled[pre_filled_counter] + pre_filled_counter += 1 + true_args.append(arg) + if self.result_is_tensor: + return self.optimality_fn(self.solution[0], *true_args) + return self.optimality_fn(self.solution, *true_args) + + # pylint: disable-next=too-many-arguments,too-many-locals def _root_vjp( - optimality_fun: Callable, - sol: Any, + optimality_fn: Callable, + solution: Any, args: Args, - cotangent: Any, - res_is_tensor: bool, + grad_outputs: Any, + result_is_tensor: bool, argnums: Tuple[int, ...], solve: Callable = linear_solve.solve_normal_cg(), ) -> Tuple[Any, ...]: - def fun_sol(sol): - # We close over the arguments. - if res_is_tensor: - return optimality_fun(sol[0], *args) - return optimality_fun(sol, *args) - _, vjp_fun_sol, *_ = functorch.vjp(fun_sol, sol) + if result_is_tensor: + + def optimality_cond(solution): + return optimality_fn(solution[0], *args) + + else: + + def optimality_cond(solution): + return optimality_fn(solution, *args) + + _, vjp_optimality_cond, *_ = functorch.vjp(optimality_cond, solution) # Compute the multiplication A^T u = (u^T A)^T. - def matvec(u): - if res_is_tensor: - return vjp_fun_sol(u[0])[0] - return vjp_fun_sol(u)[0] + if result_is_tensor: - # The solution of A^T u = v, where - # A = jacobian(optimality_fun, argnums=0) - # v = -cotangent. - v = pytree.tree_map(torch.neg, cotangent) - u = solve(matvec, v) + def matvec(u): + return vjp_optimality_cond(u[0])[0] - class MaskArgs: # pylint: disable=missing-class-docstring,too-few-public-methods - def __init__(self, argnums: Tuple[int, ...], *args) -> None: - self.argnums = argnums + else: - self.pre_filled = [] - self.post_filled = [] - for idx, arg in enumerate(args): - if idx + 1 in argnums: # plus 1 because we exclude the first argument - self.post_filled.append(arg) - else: - self.pre_filled.append(arg) - self.len_args = len(self.pre_filled) + len(self.post_filled) - - def __call__(self, *args) -> Any: - true_args = [] - pre_filled_counter = 0 - for idx in range(self.len_args): - if idx + 1 in self.argnums: # plus 1 because we exclude the first argument - arg = args[idx] - else: - arg = self.pre_filled[pre_filled_counter] - pre_filled_counter += 1 - true_args.append(arg) - if res_is_tensor: - return optimality_fun(sol[0], *true_args) - return optimality_fun(sol, *true_args) + def matvec(u): + return vjp_optimality_cond(u)[0] - fun_args = MaskArgs(argnums, *args) + # The solution of A^T u = v, where + # A = jacobian(optimality_fn, argnums=0) + # v = -grad_outputs. + v = pytree.tree_map(torch.neg, grad_outputs) + u = solve(matvec, v) - _, vjp_fun_args, *_ = functorch.vjp(fun_args, *fun_args.post_filled) + masked_optimality_fn = MaskedOptimalityFn( + optimality_fn, solution, result_is_tensor, argnums, *args + ) + _, vjp_optimality_fn, *_ = functorch.vjp( + masked_optimality_fn, *masked_optimality_fn.post_filled + ) - if res_is_tensor: - result = vjp_fun_args(u[0]) + if result_is_tensor: + result = vjp_optimality_fn(u[0]) else: - result = vjp_fun_args(u) + result = vjp_optimality_fn(u) true_result = [None] - for idx in range(fun_args.len_args): + for idx in range(masked_optimality_fn.len_args): if idx + 1 in argnums: # plus 1 because we exclude the first argument true_result.append(result[idx]) else: @@ -110,7 +136,7 @@ def __call__(self, *args) -> Any: return tuple(true_result) -def _extract_kwargs(kwarg_keys: Sequence[Any], flat_args: Tuple[Any, ...]) -> Tuple[Args, KwArgs]: +def _extract_kwargs(kwarg_keys: Sequence[str], flat_args: Tuple[Any, ...]) -> Tuple[Args, KwArgs]: nargs = len(flat_args) - len(kwarg_keys) args, kwarg_vals = flat_args[:nargs], flat_args[nargs:] kwargs = dict(zip(kwarg_keys, kwarg_vals)) @@ -166,12 +192,12 @@ def _split_tensor_and_others( non_tensors: List[Any] = [] is_tensor_mask: List[bool] = [] for item in flattened: - if isinstance(item, torch.Tensor): + is_tensor = isinstance(item, torch.Tensor) + is_tensor_mask.append(is_tensor) + if is_tensor: tensors.append(item.data) - is_tensor_mask.append(True) else: non_tensors.append(item) - is_tensor_mask.append(False) return treedef, tuple(is_tensor_mask), tuple(tensors), tuple(non_tensors) @@ -196,24 +222,24 @@ def _merge_tensor_and_others( # pylint: disable-next=too-many-arguments,too-many-statements def _custom_root( - solver_fun: Callable, - optimality_fun: Callable, + solver_fn: Callable, + optimality_fn: Callable, solve: Callable, argnums: Tuple[int, ...], has_aux: bool, reference_signature: Optional[Union[inspect.Signature, Callable]] = None, ) -> Callable: - solver_fun_signature = inspect.signature(solver_fun) + solver_fn_signature = inspect.signature(solver_fn) if reference_signature is None: - reference_signature = inspect.signature(optimality_fun) + reference_signature = inspect.signature(optimality_fn) elif not isinstance(reference_signature, inspect.Signature): - # If is a CompositeLinearFunction, accesses subfun. + # If is a CompositeLinearFunction, accesses subfn. # Otherwise, assumes a Callable. - fun = getattr(reference_signature, 'subfun', reference_signature) - reference_signature = inspect.signature(fun) + fn = getattr(reference_signature, 'subfn', reference_signature) + reference_signature = inspect.signature(fn) - def make_custom_vjp_solver_fun(solver_fun, kwarg_keys, args_sign): + def make_custom_vjp_solver_fn(solver_fn, kwarg_keys, args_sign): # pylint: disable-next=missing-class-docstring,abstract-method class ImplicitMetaGradient(Function): @staticmethod @@ -227,7 +253,7 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ args = tuple(args) args, kwargs = _extract_kwargs(kwarg_keys, args) - res = solver_fun(*args, **kwargs) + res = solver_fn(*args, **kwargs) ( args_treedef, args_is_tensor_mask, @@ -241,27 +267,30 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ res, aux = res if torch.is_tensor(res): ctx.save_for_backward(res, *args_tensors) - ctx.res_is_tensor = True + ctx.result_is_tensor = True return (res, aux, True, torch.tensor) ctx.save_for_backward(*res, *args_tensors) - ctx.res_is_tensor = False + ctx.result_is_tensor = False return (*res, aux, False, type(res)) if isinstance(res, torch.Tensor): ctx.save_for_backward(res, *args_tensors) else: ctx.save_for_backward(*res, *args_tensors) - ctx.res_is_tensor = isinstance(res, torch.Tensor) + ctx.result_is_tensor = isinstance(res, torch.Tensor) return res @staticmethod - def backward(ctx, *cotangent): # pylint: disable=too-many-locals + def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals if has_aux: - cotangent = cotangent[:-3] + grad_outputs = grad_outputs[:-3] saved_tensors = ctx.saved_tensors - res, args_tensors = saved_tensors[: len(cotangent)], saved_tensors[len(cotangent) :] + res, args_tensors = ( + saved_tensors[: len(grad_outputs)], + saved_tensors[len(grad_outputs) :], + ) args_treedef = ctx.args_treedef args_is_tensor_mask = ctx.args_is_tensor_mask args_non_tensors = ctx.args_non_tensors @@ -271,34 +300,33 @@ def backward(ctx, *cotangent): # pylint: disable=too-many-locals args, kwargs = _extract_kwargs(kwarg_keys, args) - sol = res + solution = res bound_args, bound_kwargs, map_args_back = _signature_bind_and_match( reference_signature, *args, **kwargs # type: ignore[arg-type] ) if bound_kwargs: raise TypeError( - 'keyword arguments to solver_fun could not be resolved to ' - 'positional arguments based on the signature ' - f'{reference_signature}. This can happen under custom_root if ' - 'optimality_fun takes catch-all **kwargs, or under ' - 'custom_fixed_point if fixed_point_fun takes catch-all **kwargs, ' - 'both of which are currently unsupported.' + f'keyword arguments to solver_fn could not be resolved to positional ' + f'arguments based on the signature {reference_signature}. This can ' + f'happen under custom_root if optimality_fn takes catch-all **kwargs, or ' + f'under custom_fixed_point if fixed_point_fn takes catch-all **kwargs, ' + f'both of which are currently unsupported.' ) # Compute VJPs w.r.t. args. vjps = _root_vjp( - optimality_fun=optimality_fun, - sol=sol, + optimality_fn=optimality_fn, + solution=solution, args=bound_args[1:], - cotangent=cotangent, - res_is_tensor=ctx.res_is_tensor, + grad_outputs=grad_outputs, + result_is_tensor=ctx.result_is_tensor, argnums=argnums, solve=solve, ) # Prepend None as the vjp for init_params. - arg_vjps, kwargs_vjps = map_args_back(vjps) - ordered_vjps = tuple(arg_vjps) + tuple(kwargs_vjps[k] for k in kwargs.keys()) + args_vjps, kwargs_vjps = map_args_back(vjps) + ordered_vjps = tuple(args_vjps) + tuple(kwargs_vjps[k] for k in kwargs.keys()) true_vjps = [] for (_, is_tuple), vjp in zip(args_sign, ordered_vjps): if is_tuple: @@ -310,48 +338,48 @@ def backward(ctx, *cotangent): # pylint: disable=too-many-locals return ImplicitMetaGradient - def wrapped_solver_fun(*args, **kwargs): - args, kwargs = _signature_bind(solver_fun_signature, *args, **kwargs) + def wrapped_solver_fn(*args, **kwargs): + args, kwargs = _signature_bind(solver_fn_signature, *args, **kwargs) keys, vals = list(kwargs.keys()), list(kwargs.values()) args_sign = [] - flatten_args = [] + flat_args = [] args_counter = 0 for idx, arg in enumerate(args): if idx in argnums: if isinstance(arg, torch.Tensor): args_sign.append((args_counter, False)) # start position, is_tuple - flatten_args.append(arg) + flat_args.append(arg) args_counter += 1 elif isinstance(arg, tuple): args_sign.append((args_counter, True)) # start position, is_tuple for arg_item in arg: - flatten_args.append(arg_item) + flat_args.append(arg_item) args_counter += len(arg) else: raise RuntimeError('must be tensor or tensor tuple') else: args_sign.append((args_counter, False)) # start position, is_tuple - flatten_args.append(arg) + flat_args.append(arg) args_counter += 1 args_sign = tuple(args_sign) - flatten_args = tuple(flatten_args) + flat_args = tuple(flat_args) - result = make_custom_vjp_solver_fun(solver_fun, keys, args_sign).apply(*flatten_args, *vals) + result = make_custom_vjp_solver_fn(solver_fn, keys, args_sign).apply(*flat_args, *vals) if has_aux: - *res, aux, res_is_tensor, res_type = result - if res_is_tensor: + *res, aux, result_is_tensor, res_type = result + if result_is_tensor: return res[0], aux res = res_type(res) return res, aux return result - return wrapped_solver_fun + return wrapped_solver_fn def custom_root( - optimality_fun: Callable, + optimality_fn: Callable, argnums: Union[int, Tuple[int, ...]] = 0, has_aux: bool = False, solve: Callable = linear_solve.solve_normal_cg(), @@ -362,30 +390,30 @@ def custom_root( .. code-block:: python - def optimality_fun(optimal_params, ...): + def optimality_fn(optimal_params, ...): ... return residual - @custom_root(optimality_fun, argnums=argnums) - def solver_fun(params, arg1, arg2, ...): + @custom_root(optimality_fn, argnums=argnums) + def solver_fn(params, arg1, arg2, ...): ... return optimal_params - The first argument to ``optimality_fun`` and ``solver_fun`` is preserved as the parameter input. - The ``argnums`` argument refers to the indices of the variables in ``solver_fun``'s signature. + The first argument to ``optimality_fn`` and ``solver_fn`` is preserved as the parameter input. + The ``argnums`` argument refers to the indices of the variables in ``solver_fn``'s signature. For example, setting ``argnums=(1, 2)`` will compute the gradient of ``optimal_params`` with respect to ``arg1`` and ``arg2`` in the above snippet. Note that, except the first argument, the - keyword arguments of the ``optimality_fun`` should be a subset of the ones of ``solver_fun``. - **In best practice, the ``optimality_fun`` should have the same signature as ``solver_fun``.** + keyword arguments of the ``optimality_fn`` should be a subset of the ones of ``solver_fn``. + **In best practice, the ``optimality_fn`` should have the same signature as ``solver_fn``.** Args: - optimality_fun: (callable) - An equation function, ``optimality_fun(params, *args)``. The invariant is - ``optimality_fun(sol, *args) == 0`` at the solution / root of ``sol``. + optimality_fn: (callable) + An equation function, ``optimality_fn(params, *args)``. The invariant is + ``optimality_fn(solution, *args) == 0`` at the solution / root of ``solution``. argnums: (int or tuple of int, default: :const:`0`) Specifies arguments to compute gradients with respect to. The ``argnums`` can be an integer or a tuple of integers, which respect to the zero-based indices of the arguments - of the ``solver_fun(params, *args)`` function. The argument ``params`` is included + of the ``solver_fn(params, *args)`` function. The argument ``params`` is included for the counting, while it is indexed as ``argnums=0``. has_aux: (default: :data:`False`) Whether the decorated solver function returns auxiliary data. @@ -393,7 +421,7 @@ def solver_fun(params, arg1, arg2, ...): a linear solver of the form ``solve(matvec, b)``. Returns: - A solver function decorator, i.e., ``custom_root(optimality_fun)(solver_fun)``. + A solver function decorator, i.e., ``custom_root(optimality_fn)(solver_fn)``. """ if isinstance(argnums, int): assert argnums != 0 @@ -403,7 +431,7 @@ def solver_fun(params, arg1, arg2, ...): return functools.partial( _custom_root, - optimality_fun=optimality_fun, + optimality_fn=optimality_fn, solve=solve, argnums=argnums, has_aux=has_aux, diff --git a/torchopt/linalg.py b/torchopt/linalg.py index 12bcb3a8..68caa928 100644 --- a/torchopt/linalg.py +++ b/torchopt/linalg.py @@ -76,7 +76,7 @@ def _normalize_matvec( assert isinstance(f, torch.Tensor) if f.ndim != 2 or f.shape[0] != f.shape[1]: raise ValueError(f'linear operator must be a square matrix, but has shape: {f.shape}') - return partial(torch.matmul, f) + return partial(torch.matmul, f) # type: ignore[return-value] # pylint: disable-next=too-many-locals @@ -96,12 +96,12 @@ def _cg_solve( bs = tree_inner_product(b, b) atol2 = max(rtol**2 * bs, atol**2) - def cond_fun(value): + def cond_fn(value): _, r, gamma, _, k = value rs = gamma if M is _identity else tree_inner_product(r, r) return rs > atol2 and k < maxiter - def body_fun(value): + def body_fn(value): x, r, gamma, p, k = value Ap = A(p) alpha = gamma / tree_inner_product(p, Ap) @@ -118,8 +118,8 @@ def body_fun(value): gamma0 = tree_inner_product(r0, z0) value = (x0, r0, gamma0, p0, 0) - while cond_fun(value): - value = body_fun(value) + while cond_fn(value): + value = body_fn(value) x_final, *_ = value @@ -177,9 +177,9 @@ def cg( ) -> TensorTree: """Use Conjugate Gradient iteration to solve ``Ax = b``. - The numerics of JAX's ``cg`` should exact match SciPy's ``cg`` (up to numerical precision), but - note that the interface is slightly different: you need to supply the linear operator ``A`` as a - function instead of a sparse matrix or ``LinearOperator``. + The numerics of TorchOpt's ``cg`` should exact match SciPy's ``cg`` (up to numerical precision), + but note that the interface is slightly different: you need to supply the linear operator ``A`` + as a function instead of a sparse matrix or ``LinearOperator``. Derivatives of :func:`cg` are implemented via implicit differentiation with another :func:`cg` solve, rather than by differentiating *through* the solver. They will be accurate only if both @@ -197,12 +197,12 @@ def cg( Starting guess for the solution. Must have the same structure as ``b``. rtol: (float, optional, default: :const:`1e-5`) Tolerances for convergence, ``norm(residual) <= max(rtol*norm(b), atol)``. We do not - implement SciPy's "legacy" behavior, so JAX's tolerance will differ from SciPy unless - you explicitly pass ``atol`` to SciPy's ``cg``. + implement SciPy's "legacy" behavior, so TorchOpt's tolerance will differ from SciPy + unless you explicitly pass ``atol`` to SciPy's ``cg``. atol: (float, optional, default: :const:`0.0`) Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``. We do not - implement SciPy's "legacy" behavior, so JAX's tolerance will differ from SciPy unless - you explicitly pass ``atol`` to SciPy's ``cg``. + implement SciPy's "legacy" behavior, so TorchOpt's tolerance will differ from SciPy + unless you explicitly pass ``atol`` to SciPy's ``cg``. maxiter: (integer, optional) Maximum number of iterations. Iteration will stop after maxiter steps even if the specified tolerance has not been achieved. diff --git a/torchopt/optim/base.py b/torchopt/optim/base.py index 572eb8a8..e85438e4 100644 --- a/torchopt/optim/base.py +++ b/torchopt/optim/base.py @@ -14,12 +14,16 @@ # ============================================================================== """The base class for optimizers.""" -from typing import Callable, Iterable, List, Optional, Sequence, Tuple, cast +from typing import Callable, Iterable, List, Optional, Sequence, Tuple import torch from torchopt import pytree -from torchopt.typing import GradientTransformation, OptState, Params, TensorTree +from torchopt.typing import ( # pylint: disable=unused-import + GradientTransformation, + OptState, + Params, +) from torchopt.update import apply_updates @@ -49,9 +53,9 @@ def __init__(self, params: Iterable[torch.Tensor], impl: GradientTransformation) self.param_treedefs: List[pytree.PyTreeDef] = [] self.state_groups: List[OptState] = [] - if not isinstance(params, list): - params = list(params) - self.add_param_group(params) + if not isinstance(params, (list, tuple)): + params = tuple(params) + self.add_param_group(params) # type: ignore[arg-type] def zero_grad(self, set_to_none: bool = False) -> None: r"""Sets the gradients of all optimized :class:`torch.Tensor`\s to zero. @@ -77,7 +81,7 @@ def f(p): p.grad.requires_grad_(False) p.grad.zero_() - pytree.tree_map(f, cast(TensorTree, self.param_groups)) + pytree.tree_map(f, self.param_groups) # type: ignore[arg-type] def state_dict(self) -> Tuple['OptState', ...]: """Returns the state of the optimizer.""" @@ -109,17 +113,17 @@ def f(p): return p.grad for i, (params, state) in enumerate(zip(self.param_groups, self.state_groups)): - grads = pytree.tree_map(f, cast(Params, params)) - updates, new_state = self.impl.update(grads, state, params=params, inplace=True) - self.param_groups[i] = apply_updates(params, updates, inplace=True) + grads = pytree.tree_map(f, params) # type: ignore[arg-type] + updates, new_state = self.impl.update(grads, state, params=params, inplace=True) # type: ignore[arg-type] + self.param_groups[i] = apply_updates(params, updates, inplace=True) # type: ignore[arg-type,call-overload] self.state_groups[i] = new_state return loss def add_param_group(self, params: 'Params') -> None: """Add a param group to the optimizer's :attr:`param_groups`.""" - flattened_params, params_treedef = pytree.tree_flatten(params) - flattened_params: Tuple[torch.Tensor] = tuple(flattened_params) # type: ignore[assignment] - self.param_groups.append(flattened_params) + flat_params, params_treedef = pytree.tree_flatten(params) + flat_params: Tuple[torch.Tensor] = tuple(flat_params) # type: ignore[assignment] + self.param_groups.append(flat_params) self.param_treedefs.append(params_treedef) - self.state_groups.append(self.impl.init(flattened_params)) + self.state_groups.append(self.impl.init(flat_params)) # type: ignore[arg-type] diff --git a/torchopt/optim/func/base.py b/torchopt/optim/func/base.py index f1d0b684..fa59fc5a 100644 --- a/torchopt/optim/func/base.py +++ b/torchopt/optim/func/base.py @@ -55,7 +55,7 @@ def __init__(self, impl: GradientTransformation, *, inplace: bool = False) -> No raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') self.impl: GradientTransformation = impl - self.optim_state: Optional[OptState] = self.__NOT_INITIALIZED + self.optim_state: Optional[OptState] = self.__NOT_INITIALIZED # type: ignore[assignment] self.inplace: bool = bool(inplace) def step( @@ -86,9 +86,9 @@ def step( inplace = self.inplace # Step parameter only - grads = torch.autograd.grad(loss, params, create_graph=True, allow_unused=True) + grads = torch.autograd.grad(loss, params, create_graph=True, allow_unused=True) # type: ignore[arg-type] updates, self.optim_state = self.impl.update( - grads, self.optim_state, params=params, inplace=inplace + grads, self.optim_state, params=params, inplace=inplace # type: ignore[arg-type] ) new_params = apply_updates(params, updates, inplace=inplace) return new_params diff --git a/torchopt/optim/meta/base.py b/torchopt/optim/meta/base.py index 9dd525f6..668c46a4 100644 --- a/torchopt/optim/meta/base.py +++ b/torchopt/optim/meta/base.py @@ -62,41 +62,40 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals Args: loss: (torch.Tensor) The loss that is used to compute the gradients to the network parameters. - """ # pylint: disable=line-too-long + """ # Step parameter only for i, (param_container, new_state) in enumerate( zip(self.param_containers_groups, self.state_groups) ): - flattened_params_or_none: List[Optional[torch.Tensor]] - flattened_params_or_none, container_treedef = pytree.tree_flatten(param_container) # type: ignore[arg-type] - flattened_params = cast( - Tuple[torch.Tensor, ...], - tuple(filter(torch.is_tensor, flattened_params_or_none)), + flat_params_or_none: List[Optional[torch.Tensor]] + flat_params_or_none, container_treedef = pytree.tree_flatten(param_container) # type: ignore[arg-type] + flat_params: Tuple[torch.Tensor, ...] = tuple( + filter(torch.is_tensor, flat_params_or_none) # type: ignore[arg-type] ) grads = torch.autograd.grad( loss, - flattened_params, + flat_params, create_graph=True, allow_unused=True, ) updates, new_state = self.impl.update( - grads, + grads, # type: ignore[arg-type] new_state, - params=flattened_params, + params=flat_params, # type: ignore[arg-type] inplace=False, ) self.state_groups[i] = new_state - flattened_new_params = apply_updates(flattened_params, updates, inplace=False) - new_params_iter = iter(flattened_new_params) - flattened_new_params_or_none = [ + flat_new_params = apply_updates(flat_params, updates, inplace=False) # type: ignore[arg-type] + new_params_iter = iter(flat_new_params) # type: ignore[call-overload] + flat_new_params_or_none = [ next(new_params_iter) if isinstance(old_param_or_none, torch.Tensor) else old_param_or_none - for old_param_or_none in flattened_params_or_none + for old_param_or_none in flat_params_or_none ] new_params = cast( Tuple[Dict[str, Optional[torch.Tensor]], ...], - pytree.tree_unflatten(container_treedef, flattened_new_params_or_none), + pytree.tree_unflatten(container_treedef, flat_new_params_or_none), ) for container, new_param in zip(param_container, new_params): container.update(new_param) @@ -107,14 +106,13 @@ def add_param_group(self, net: nn.Module) -> None: from torchopt.utils import _extract_container params_container, _ = _extract_container(net, with_buffers=False) - flattened_params = tuple( + flat_params = tuple( filter( torch.is_tensor, # type: ignore[arg-type] - # pylint: disable-next=line-too-long - cast(List[Optional[torch.Tensor]], pytree.tree_leaves(params_container)), # type: ignore[arg-type] + pytree.tree_leaves(params_container), # type: ignore[arg-type] ) ) - optimizer_state = self.impl.init(flattened_params) + optimizer_state = self.impl.init(flat_params) # type: ignore[arg-type] self.param_containers_groups.append(params_container) self.state_groups.append(optimizer_state) diff --git a/torchopt/transform.py b/torchopt/transform.py index ac98d8bf..adb02c87 100644 --- a/torchopt/transform.py +++ b/torchopt/transform.py @@ -33,18 +33,18 @@ # pylint: disable=invalid-name -from typing import Any, Callable, List, NamedTuple, Optional, Sequence, Tuple, Union, cast +from typing import Any, Callable, List, NamedTuple, Optional, Sequence, Union import torch from torchopt import pytree from torchopt.base import EmptyState, GradientTransformation, identity -from torchopt.typing import Params, PyTree, Schedule, TensorTree, Updates +from torchopt.typing import Params, Schedule, TensorTree, Updates ScaleState = EmptyState INT64_MAX = torch.iinfo(torch.int64).max -TRIPLE_PYTREEDEF = pytree.tree_structure(cast(PyTree[int], (0, 1, 2))) +TRIPLE_PYTREEDEF = pytree.tree_structure((0, 1, 2)) # type: ignore[arg-type] def map_flattened(func: Callable, *args: Any) -> List[Any]: @@ -53,21 +53,21 @@ def map_flattened(func: Callable, *args: Any) -> List[Any]: def with_flattened_tree(inner: GradientTransformation) -> GradientTransformation: - # pylint: disable-next=line-too-long """Wraps around the inner transformation that manipulates the flattened tree structure (:class:``list``).""" def init_fn(params): - return inner.init(pytree.tree_leaves(params)) + return inner.init(pytree.tree_leaves(params)) # type: ignore[arg-type] def update_fn(updates, state, *, params=None, inplace=True): - flattened_updates, treedef = pytree.tree_flatten(updates) + flat_updates, treedef = pytree.tree_flatten(updates) if params is not None: params = pytree.tree_leaves(params) - flattened_updates, state = inner.update( - flattened_updates, state, params=params, inplace=inplace + flat_updates, state = inner.update( + flat_updates, state, params=params, inplace=inplace # type: ignore[arg-type] ) - updates = pytree.tree_unflatten(treedef, flattened_updates) + updates: Updates + updates = pytree.tree_unflatten(treedef, flat_updates) # type: ignore[arg-type] return updates, state @@ -90,7 +90,7 @@ def f(c, g): return c + (c != INT64_MAX).to(torch.int64) if g is not None else c if already_flattened: - return map_flattened(f, count, updates) + return map_flattened(f, count, updates) # type: ignore[return-value] return pytree.tree_map(f, count, updates) @@ -183,7 +183,7 @@ def f(g, c): return ( updates, ScaleByScheduleState( - count=_inc_count(updates, state.count, already_flattened=already_flattened) + count=_inc_count(updates, state.count, already_flattened=already_flattened) # type: ignore[arg-type] ), ) @@ -313,7 +313,7 @@ def init_fn(params): nu = tree_map( # second moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params ) - return ScaleByAdamState(mu=mu, nu=nu, count=zero) + return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument mu = _update_moment( @@ -337,7 +337,7 @@ def f(g, m, v): return m.div(v.add(eps_root).sqrt_().add(eps)) if g is not None else None updates = tree_map(f, updates, mu_hat, nu_hat) - return updates, ScaleByAdamState(mu=mu, nu=nu, count=count_inc) + return updates, ScaleByAdamState(mu=mu, nu=nu, count=count_inc) # type: ignore[arg-type] return GradientTransformation(init_fn, update_fn) @@ -413,7 +413,7 @@ def update_fn(updates, state, *, params=None, inplace=True): out = map_flattened(op, state.mu, state.nu, updates, count_inc) new_mu, new_nu, new_updates = tuple(zip(*out)) # transpose - return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) + return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) # type: ignore[arg-type] else: tree_map = pytree.tree_map # type: ignore[assignment] @@ -427,11 +427,11 @@ def update_fn(updates, state, *, params=None, inplace=True): op = AdamOp(b1=b1, b2=b2, eps=eps, eps_root=eps_root, inplace=inplace) out = pytree.tree_map(op, state.mu, state.nu, updates, count_inc) - new_mu, new_nu, new_updates = cast( - Tuple[TensorTree, TensorTree, TensorTree], - pytree.tree_transpose(treedef, TRIPLE_PYTREEDEF, out), - ) - return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) + new_mu: Updates + new_nu: Updates + new_updates: Updates + new_mu, new_nu, new_updates = pytree.tree_transpose(treedef, TRIPLE_PYTREEDEF, out) # type: ignore[misc] + return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) # type: ignore[arg-type] def init_fn(params): zero = tree_map( # count init @@ -443,7 +443,7 @@ def init_fn(params): nu = tree_map( # second moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params ) - return ScaleByAdamState(mu=mu, nu=nu, count=zero) + return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] return GradientTransformation(init_fn, update_fn) @@ -513,7 +513,7 @@ def _trace( def init_fn(params): return TraceState( - trace=tree_map( + trace=tree_map( # type: ignore[arg-type] lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params ) ) @@ -572,7 +572,7 @@ def f(g, t): updates = tree_map(torch.clone, new_trace) first_call = False - return updates, TraceState(trace=new_trace) + return updates, TraceState(trace=new_trace) # type: ignore[arg-type] return GradientTransformation(init_fn, update_fn) @@ -631,7 +631,7 @@ def _scale_by_rms( def init_fn(params): nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment - return ScaleByRmsState(nu=nu) + return ScaleByRmsState(nu=nu) # type: ignore[arg-type] def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument nu = _update_moment( @@ -710,7 +710,7 @@ def _scale_by_stddev( def init_fn(params): mu = tree_map(torch.zeros_like, params) # first moment nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment - return ScaleByRStdDevState(mu=mu, nu=nu) + return ScaleByRStdDevState(mu=mu, nu=nu) # type: ignore[arg-type] def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument mu = _update_moment( diff --git a/torchopt/typing.py b/torchopt/typing.py index 440b78b1..315cefc0 100644 --- a/torchopt/typing.py +++ b/torchopt/typing.py @@ -15,6 +15,7 @@ """Typing utilities.""" from typing import Callable, Optional, TypeVar, Union +from typing_extensions import TypeAlias # Python 3.10+ import torch.distributed.rpc as rpc from optree.typing import PyTree @@ -24,12 +25,6 @@ from torchopt.base import ChainedGradientTransformation, EmptyState, GradientTransformation -try: - from typing import TypeAlias # type: ignore[attr-defined] -except ImportError: - from typing_extensions import TypeAlias - - __all__ = [ 'GradientTransformation', 'ChainedGradientTransformation', diff --git a/torchopt/utils.py b/torchopt/utils.py index d5d7d6d3..211bcdd6 100644 --- a/torchopt/utils.py +++ b/torchopt/utils.py @@ -28,6 +28,8 @@ cast, overload, ) +from typing_extensions import Literal # Python 3.8+ +from typing_extensions import TypeAlias # Python 3.10+ import torch import torch.nn as nn @@ -36,12 +38,6 @@ from torchopt.typing import OptState, TensorTree # pylint: disable=unused-import -try: - from typing import Literal # type: ignore[attr-defined] -except ImportError: - from typing_extensions import Literal - - if TYPE_CHECKING: from torchopt.optim.meta.base import MetaOptimizer @@ -65,6 +61,9 @@ class ModuleState(NamedTuple): detach_buffers: bool = False +CopyMode: TypeAlias = Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] + + def stop_gradient(target: Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer']) -> None: """Stop the gradient for the input object. @@ -106,8 +105,7 @@ def f(obj): def extract_state_dict( target: nn.Module, *, - # pylint: disable-next=line-too-long - by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + by: CopyMode = 'reference', device: Optional[Union[int, str, torch.device]] = None, with_buffers: bool = True, enable_visual: bool = False, @@ -120,8 +118,7 @@ def extract_state_dict( def extract_state_dict( target: 'MetaOptimizer', *, - # pylint: disable-next=line-too-long - by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + by: CopyMode = 'reference', device: Optional[Union[int, str, torch.device]] = None, with_buffers: bool = True, enable_visual: bool = False, @@ -134,8 +131,7 @@ def extract_state_dict( def extract_state_dict( target: Union[nn.Module, 'MetaOptimizer'], *, - # pylint: disable-next=line-too-long - by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + by: CopyMode = 'reference', device: Optional[Union[int, str, torch.device]] = None, with_buffers: bool = True, detach_buffers: bool = False, @@ -361,8 +357,7 @@ def clone_detach_(t: torch.Tensor) -> torch.Tensor: def module_clone( target: nn.Module, *, - # pylint: disable-next=line-too-long - by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + by: CopyMode = 'reference', detach_buffers: bool = False, device: Optional[Union[int, str, torch.device]] = None, ) -> nn.Module: @@ -373,8 +368,7 @@ def module_clone( def module_clone( target: 'MetaOptimizer', *, - # pylint: disable-next=line-too-long - by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + by: CopyMode = 'reference', detach_buffers: bool = False, device: Optional[Union[int, str, torch.device]] = None, ) -> 'MetaOptimizer': @@ -385,8 +379,7 @@ def module_clone( def module_clone( target: TensorTree, *, - # pylint: disable-next=line-too-long - by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + by: CopyMode = 'reference', detach_buffers: bool = False, device: Optional[Union[int, str, torch.device]] = None, ) -> TensorTree: @@ -397,8 +390,7 @@ def module_clone( def module_clone( target: Union[nn.Module, 'MetaOptimizer', TensorTree], *, - # pylint: disable-next=line-too-long - by: Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] = 'reference', # type: ignore[name-defined] + by: CopyMode = 'reference', detach_buffers: bool = False, device: Optional[Union[int, str, torch.device]] = None, ) -> Union[nn.Module, 'MetaOptimizer', TensorTree]: diff --git a/torchopt/zero_order_diff.py b/torchopt/zero_order_diff.py new file mode 100644 index 00000000..d4982292 --- /dev/null +++ b/torchopt/zero_order_diff.py @@ -0,0 +1,347 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Zero-Order Gradient Estimation.""" + +import functools +from typing import Any, Callable, List, Sequence, Tuple, Union +from typing_extensions import Literal # Python 3.8+ +from typing_extensions import Protocol # Python 3.8+ +from typing_extensions import TypeAlias # Python 3.10+ + +import torch +from torch.autograd import Function +from torch.distributions import Distribution + +from torchopt import pytree +from torchopt.typing import Numeric + + +class Samplable(Protocol): # pylint: disable=too-few-public-methods + """Abstract protocol class that supports sampling.""" + + def sample( + self, sample_shape: torch.Size = torch.Size() # pylint: disable=unused-argument + ) -> Union[torch.Tensor, Sequence[Numeric]]: + # pylint: disable-next=line-too-long + """Generates a sample_shape shaped sample or sample_shape shaped batch of samples if the distribution parameters are batched.""" + raise NotImplementedError + + +Samplable.register(Distribution) + + +def _zero_order_naive( + fn: Callable[..., torch.Tensor], + distribution: Samplable, + argnums: Tuple[int, ...], + sigma: Numeric, +) -> Callable[..., torch.Tensor]: + def apply(*args: Any) -> torch.Tensor: + diff_params = [args[argnum] for argnum in argnums] + flat_diff_params: List[Any] + flat_diff_params, diff_params_treedef = pytree.tree_flatten(diff_params) # type: ignore[arg-type] + + class ZeroOrder(Function): # pylint: disable=missing-class-docstring,abstract-method + @staticmethod + def forward(ctx, *args, **kwargs): + flat_diff_params = args[:-1] + origin_args = list(args[-1][0]) + flat_args: List[Any] + flat_args, args_treedef = pytree.tree_flatten(origin_args) # type: ignore[arg-type] + ctx.args_treedef = args_treedef + + is_tensor_mask = [] + tensors = [] + non_tensors = [] + for origin_arg in flat_args: + is_tensor = isinstance(origin_arg, torch.Tensor) + is_tensor_mask.append(is_tensor) + if is_tensor: + tensors.append(origin_arg) + else: + non_tensors.append(origin_arg) + + ctx.non_tensors = non_tensors + ctx.is_tensor_mask = is_tensor_mask + + ctx.save_for_backward(*flat_diff_params, *tensors) + ctx.len_args = len(args) + ctx.len_params = len(flat_diff_params) + return fn(*origin_args) + + @staticmethod + def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals + saved_tensors = ctx.saved_tensors + flat_diff_params = saved_tensors[: ctx.len_params] + tensors = saved_tensors[ctx.len_params :] + non_tensors = ctx.non_tensors + + flat_args = [] + tensors_counter = 0 + non_tensors_counter = 0 + for is_tensor in ctx.is_tensor_mask: + if is_tensor: + flat_args.append(tensors[tensors_counter]) + tensors_counter += 1 + else: + flat_args.append(non_tensors[non_tensors_counter]) + non_tensors_counter += 1 + + args: List[Any] = pytree.tree_unflatten(ctx.args_treedef, flat_args) # type: ignore[assignment] + + def add_perturbation(tensor, noise): + return tensor.add(noise, alpha=sigma) + + noise = [distribution.sample(sample_shape=p.shape) for p in flat_diff_params] + flat_noisy_params = [ + add_perturbation(t, n) for t, n in zip(flat_diff_params, noise) + ] + noisy_params: List[Any] = pytree.tree_unflatten( # type: ignore[assignment] + diff_params_treedef, flat_noisy_params + ) + + for argnum, noisy_param in zip(argnums, noisy_params): + args[argnum] = noisy_param + + loss = fn(*args) + weighted_grad = grad_outputs[0].mul(loss).mul_(1 / sigma) + + out_grads = [None for _ in range(ctx.len_args)] + for i in range(len(flat_diff_params)): + out_grads[i] = weighted_grad * noise[i] + return tuple(out_grads) + + return ZeroOrder.apply(*flat_diff_params, (args,)) + + return apply + + +def _zero_order_forward( + fn: Callable[..., torch.Tensor], + distribution: Samplable, + argnums: Tuple[int, ...], + sigma: Numeric, +) -> Callable[..., torch.Tensor]: + def apply(*args: Any) -> torch.Tensor: + diff_params = [args[argnum] for argnum in argnums] + flat_diff_params: List[Any] + flat_diff_params, diff_params_treedef = pytree.tree_flatten(diff_params) # type: ignore[arg-type] + + class ZeroOrder(Function): # pylint: disable=missing-class-docstring,abstract-method + @staticmethod + def forward( + ctx: Any, *args: Any, **kwargs: Any + ) -> Any: # pylint: disable=arguments-differ + flat_diff_params = args[:-1] + origin_args = list(args[-1][0]) + flat_args: List[Any] + flat_args, args_treedef = pytree.tree_flatten(origin_args) # type: ignore[arg-type] + ctx.args_treedef = args_treedef + + is_tensor_mask = [] + tensors = [] + non_tensors = [] + for origin_arg in flat_args: + is_tensor = isinstance(origin_arg, torch.Tensor) + is_tensor_mask.append(is_tensor) + if is_tensor: + tensors.append(origin_arg) + else: + non_tensors.append(origin_arg) + + ctx.non_tensors = non_tensors + ctx.is_tensor_mask = is_tensor_mask + + loss = fn(*origin_args) + ctx.save_for_backward(*flat_diff_params, *tensors, loss) + ctx.len_args = len(args) + ctx.len_params = len(flat_diff_params) + return loss + + @staticmethod + def backward(ctx: Any, *grad_outputs: Any) -> Any: # pylint: disable=too-many-locals + saved_tensors = ctx.saved_tensors + flat_diff_params = saved_tensors[: ctx.len_params] + tensors = saved_tensors[ctx.len_params : -1] + loss = saved_tensors[-1] + non_tensors = ctx.non_tensors + + flat_args = [] + tensors_counter = 0 + non_tensors_counter = 0 + for is_tensor in ctx.is_tensor_mask: + if is_tensor: + flat_args.append(tensors[tensors_counter]) + tensors_counter += 1 + else: + flat_args.append(non_tensors[non_tensors_counter]) + non_tensors_counter += 1 + + args: List[Any] = pytree.tree_unflatten(ctx.args_treedef, flat_args) # type: ignore[assignment] + + def add_perturbation(tensor, noise): + return tensor.add(noise, alpha=sigma) + + noise = [distribution.sample(sample_shape=p.shape) for p in flat_diff_params] + flat_noisy_params = [ + add_perturbation(t, n) for t, n in zip(flat_diff_params, noise) + ] + noisy_params: List[Any] = pytree.tree_unflatten( # type: ignore[assignment] + diff_params_treedef, flat_noisy_params + ) + + for argnum, noisy_param in zip(argnums, noisy_params): + args[argnum] = noisy_param + + noisy_loss = fn(*args) + loss = noisy_loss - loss + weighted_grad = grad_outputs[0].mul(loss).mul_(1 / sigma) + + out_grads = [None for _ in range(ctx.len_args)] + for i in range(len(flat_diff_params)): + out_grads[i] = weighted_grad * noise[i] + return tuple(out_grads) + + return ZeroOrder.apply(*flat_diff_params, (args,)) + + return apply + + +def _zero_order_antithetic( + fn: Callable[..., torch.Tensor], + distribution: Samplable, + argnums: Tuple[int, ...], + sigma: Numeric, +) -> Callable[..., torch.Tensor]: + def apply(*args: Any) -> torch.Tensor: + diff_params = [args[argnum] for argnum in argnums] + flat_diff_params: List[Any] + flat_diff_params, diff_params_treedef = pytree.tree_flatten(diff_params) # type: ignore[arg-type] + + class ZeroOrder(Function): # pylint: disable=missing-class-docstring,abstract-method + @staticmethod + def forward(ctx, *args, **kwargs): + flat_diff_params = args[:-1] + origin_args = list(args[-1][0]) + flat_args: List[Any] + flat_args, args_treedef = pytree.tree_flatten(origin_args) # type: ignore[arg-type] + ctx.args_treedef = args_treedef + + is_tensor_mask = [] + tensors = [] + non_tensors = [] + for origin_arg in flat_args: + is_tensor = isinstance(origin_arg, torch.Tensor) + is_tensor_mask.append(is_tensor) + if is_tensor: + tensors.append(origin_arg) + else: + non_tensors.append(origin_arg) + + ctx.non_tensors = non_tensors + ctx.is_tensor_mask = is_tensor_mask + + ctx.save_for_backward(*flat_diff_params, *tensors) + ctx.len_args = len(args) + ctx.len_params = len(flat_diff_params) + return fn(*origin_args) + + @staticmethod + def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals + saved_tensors = ctx.saved_tensors + flat_diff_params = saved_tensors[: ctx.len_params] + tensors = saved_tensors[ctx.len_params :] + non_tensors = ctx.non_tensors + + flat_args = [] + tensors_counter = 0 + non_tensors_counter = 0 + for is_tensor in ctx.is_tensor_mask: + if is_tensor: + flat_args.append(tensors[tensors_counter]) + tensors_counter += 1 + else: + flat_args.append(non_tensors[non_tensors_counter]) + non_tensors_counter += 1 + + args: List[Any] = pytree.tree_unflatten(ctx.args_treedef, flat_args) # type: ignore[assignment] + + noise = [distribution.sample(sample_shape=p.shape) for p in flat_diff_params] + + def get_loss(add_perturbation_fn) -> torch.Tensor: + flat_noisy_params = [ + add_perturbation_fn(t, n, alpha=sigma) + for t, n in zip(flat_diff_params, noise) + ] + noisy_params: List[Any] = pytree.tree_unflatten( # type: ignore[assignment] + diff_params_treedef, flat_noisy_params + ) + + for argnum, noisy_param in zip(argnums, noisy_params): + args[argnum] = noisy_param + + return fn(*args) + + loss = get_loss(torch.add) - get_loss(torch.sub) + weighted_grad = grad_outputs[0].mul(loss).mul_(0.5 / sigma) + + out_grads = [None for _ in range(ctx.len_args)] + for i in range(len(flat_diff_params)): + out_grads[i] = weighted_grad * noise[i] + return tuple(out_grads) + + return ZeroOrder.apply(*flat_diff_params, (args,)) + + return apply + + +Algorithm: TypeAlias = Literal['naive', 'forward', 'antithetic'] + + +def zero_order( + distribution: Samplable, + algo: Algorithm = 'naive', + argnums: Union[int, Tuple[int, ...]] = (0,), + sigma: Numeric = 1.0, +) -> Callable[[Callable[..., torch.Tensor]], Callable[..., torch.Tensor]]: + """Decorator for applying zero order differentiation. + + Args: + distribution: (object) + A sampler object, it should have method ``sample(sample_shape)`` to sample perturbations + from the given distribution. + algo: (str) + The algorithm to use. The currently supported algorithms are :const:`'naive'`, + :const:`'forward'`, and :const:`'antithetic'`. Defaults to :const:`'naive'`. + argnums: (int or tuple of int, default: :const:`0`) + Specifies arguments to compute gradients with respect to. + sigma: (Numeric) + The standard deviation of the perturbation. Defaults to :const:`1.0`. + + Returns: + A zero order function decorator. + """ + assert algo in ('naive', 'forward', 'antithetic') + if algo == 'naive': + algo_fn = _zero_order_naive + elif algo == 'forward': + algo_fn = _zero_order_forward + else: + algo_fn = _zero_order_antithetic + + if isinstance(argnums, int): + argnums = (argnums,) + + return functools.partial(algo_fn, distribution=distribution, argnums=argnums, sigma=sigma) From c610104ce0294b01d19aa3e168afbe4a7f0230ea Mon Sep 17 00:00:00 2001 From: Hello_World Date: Wed, 12 Oct 2022 22:33:11 +0800 Subject: [PATCH 28/69] feat(implicit): add option for matrix is sdp (#99) Co-authored-by: Xuehai Pan --- torchopt/implicit_diff.py | 21 +++++++---- torchopt/linear_solve.py | 76 ++++++++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/torchopt/implicit_diff.py b/torchopt/implicit_diff.py index e6e2c815..7fdf58a8 100644 --- a/torchopt/implicit_diff.py +++ b/torchopt/implicit_diff.py @@ -74,7 +74,7 @@ def __call__(self, *args) -> Any: return self.optimality_fn(self.solution, *true_args) -# pylint: disable-next=too-many-arguments,too-many-locals +# pylint: disable-next=too-many-arguments,too-many-locals,too-many-branches def _root_vjp( optimality_fn: Callable, solution: Any, @@ -117,14 +117,21 @@ def matvec(u): masked_optimality_fn = MaskedOptimalityFn( optimality_fn, solution, result_is_tensor, argnums, *args ) - _, vjp_optimality_fn, *_ = functorch.vjp( - masked_optimality_fn, *masked_optimality_fn.post_filled - ) - if result_is_tensor: - result = vjp_optimality_fn(u[0]) + if getattr(solve, 'is_sdp', False): + if result_is_tensor: + result = u[0] + else: + result = u else: - result = vjp_optimality_fn(u) + _, vjp_optimality_fn, *_ = functorch.vjp( + masked_optimality_fn, *masked_optimality_fn.post_filled + ) + + if result_is_tensor: + result = vjp_optimality_fn(u[0]) + else: + result = vjp_optimality_fn(u) true_result = [None] for idx in range(masked_optimality_fn.len_args): diff --git a/torchopt/linear_solve.py b/torchopt/linear_solve.py index 6bb7e011..8ba497bb 100644 --- a/torchopt/linear_solve.py +++ b/torchopt/linear_solve.py @@ -50,6 +50,20 @@ def tree_add(tree_x: TensorTree, tree_y: TensorTree, alpha: float = 1.0) -> Tens return pytree.tree_map(lambda x, y: x.add(y, alpha=alpha), tree_x, tree_y) +def _make_rmatvec( + matvec: Callable[[TensorTree], TensorTree], x: TensorTree +) -> Callable[[TensorTree], TensorTree]: + """Returns a function that computes A^T y from matvec(x) = A x.""" + _, vjp, *_ = functorch.vjp(matvec, x) + return lambda y: vjp(y)[0] + + +def _normal_matvec(matvec: Callable[[TensorTree], TensorTree], x: TensorTree) -> TensorTree: + """Computes A^T A x from matvec(x) = A x.""" + matvec_x, vjp, *_ = functorch.vjp(matvec, x) + return vjp(matvec_x)[0] + + def _make_ridge_matvec( matvec: Callable[[TensorTree], TensorTree], ridge: float = 0.0 ) -> Callable[[TensorTree], TensorTree]: @@ -60,7 +74,7 @@ def ridge_matvec(v: TensorTree) -> TensorTree: def solve_cg( - matvec: Callable[['TensorTree'], 'TensorTree'], + matvec: Callable[['TensorTree'], 'TensorTree'], # (x) -> A @ x b: 'TensorTree', ridge: Optional[float] = None, init: Optional['TensorTree'] = None, @@ -71,36 +85,28 @@ def solve_cg( It assumes that ``A`` is a hermitian, positive definite matrix. Args: - matvec: a function that returns the product between ``A`` and a vector. - b: a tree of tensors. - ridge: optional ridge regularization. - init: optional initialization to be used by conjugate gradient. - **kwargs: additional keyword arguments for solver. + matvec: A function that returns the product between ``A`` and a vector. + b: A tree of tensors for the right hand side of the equation. + ridge: Optional ridge regularization. + init: Optional initialization to be used by conjugate gradient. + **kwargs: Additional keyword arguments for the conjugate gradient solver. Returns: The solution with the same structure as ``b``. """ if ridge is not None: + # (x) -> A @ x + ridge * x + # i.e. (x) -> (A + ridge * I) @ x matvec = _make_ridge_matvec(matvec, ridge=ridge) - return linalg.cg(matvec, b, x0=init, **kwargs) - -def _make_rmatvec( - matvec: Callable[[TensorTree], TensorTree], x: TensorTree -) -> Callable[[TensorTree], TensorTree]: - _, vjp, *_ = functorch.vjp(matvec, x) - return lambda y: vjp(y)[0] - - -def _normal_matvec(matvec: Callable[[TensorTree], TensorTree], x: TensorTree) -> TensorTree: - """Computes A^T A x from matvec(x) = A x.""" - matvec_x, vjp, *_ = functorch.vjp(matvec, x) - return vjp(matvec_x)[0] + # Returns solution for `(A + ridge * I) @ x = b`. + return linalg.cg(matvec, b, x0=init, **kwargs) def _solve_normal_cg( - matvec: Callable[[TensorTree], TensorTree], + matvec: Callable[[TensorTree], TensorTree], # (x) -> A @ x b: TensorTree, + is_sdp: bool = False, ridge: Optional[float] = None, init: Optional[TensorTree] = None, **kwargs, @@ -111,11 +117,12 @@ def _solve_normal_cg( positive definite. Args: - matvec: product between ``A`` and a vector. - b: pytree. - ridge: optional ridge regularization. - init: optional initialization to be used by normal conjugate gradient. - **kwargs: additional keyword arguments for solver. + matvec: A function that returns the product between ``A`` and a vector. + b: A tree of tensors for the right hand side of the equation. + is_sdp: Whether to assume matrix ``A`` is symmetric definite positive to speedup computation. + ridge: Optional ridge regularization. Solves the equation for ``(A.T @ A + ridge * I) @ x = A.T @ b``. + init: Optional initialization to be used by normal conjugate gradient. + **kwargs: Additional keyword arguments for the conjugate gradient solver. Returns: The solution with the same structure as ``b``. @@ -125,19 +132,30 @@ def _solve_normal_cg( else: example_x = init - rmatvec = _make_rmatvec(matvec, example_x) + if is_sdp: + if ridge is not None: + raise ValueError('ridge must be specified with `is_sdp=False`.') + # Returns solution for `A @ x = b`. + return linalg.cg(matvec, b, x0=init, **kwargs) + + rmatvec = _make_rmatvec(matvec, example_x) # (x) -> A.T @ x - def normal_matvec(x): + def normal_matvec(x): # (x) -> A.T @ A @ x return _normal_matvec(matvec, x) if ridge is not None: + # (x) -> A.T @ A @ x + ridge * x + # i.e. (x) -> (A.T @ A + ridge * I) @ x normal_matvec = _make_ridge_matvec(normal_matvec, ridge=ridge) - Ab = rmatvec(b) # A.T b + Ab = rmatvec(b) # A.T @ b + # Returns solution for `(A.T @ A + ridge * I) @ x = A.T @ b`. return linalg.cg(normal_matvec, Ab, x0=init, **kwargs) def solve_normal_cg(**kwargs): """Wrapper for :func:`solve_normal_cg`.""" - return functools.partial(_solve_normal_cg, **kwargs) + partial_fn = functools.partial(_solve_normal_cg, **kwargs) + setattr(partial_fn, 'is_sdp', kwargs.get('is_sdp', False)) + return partial_fn From 660462520605eac5bfc3bd4204aa0837b1dd07ba Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Thu, 13 Oct 2022 19:24:30 +0800 Subject: [PATCH 29/69] refactor: reorganize code structure (#100) --- CHANGELOG.md | 2 +- docs/source/api/api.rst | 2 +- tests/test_implicit.py | 10 +- torchopt/__init__.py | 5 +- torchopt/alias.py | 480 ---------- torchopt/alias/__init__.py | 40 + torchopt/alias/adam.py | 123 +++ torchopt/alias/adamw.py | 136 +++ torchopt/alias/rmsprop.py | 124 +++ torchopt/alias/sgd.py | 105 ++ torchopt/alias/utils.py | 118 +++ torchopt/combine.py | 55 +- torchopt/diff/__init__.py | 17 + torchopt/diff/implicit/__init__.py | 17 + .../implicit/decorator.py} | 0 .../zero_order.py} | 13 + torchopt/linalg/__init__.py | 37 + torchopt/{linalg.py => linalg/cg.py} | 30 +- torchopt/linear_solve/__init__.py | 38 + torchopt/linear_solve/cg.py | 79 ++ .../normal_cg.py} | 81 +- torchopt/linear_solve/utils.py | 80 ++ torchopt/optim/adam.py | 4 +- torchopt/optim/adamw.py | 4 +- torchopt/optim/meta/adam.py | 4 +- torchopt/optim/meta/adamw.py | 4 +- torchopt/optim/meta/rmsprop.py | 4 +- torchopt/optim/meta/sgd.py | 4 +- torchopt/optim/rmsprop.py | 4 +- torchopt/optim/sgd.py | 4 +- torchopt/schedule/__init__.py | 37 + .../{schedule.py => schedule/polynomial.py} | 2 +- torchopt/transform.py | 904 ------------------ torchopt/transform/__init__.py | 52 + torchopt/transform/add_decayed_weights.py | 230 +++++ torchopt/transform/scale.py | 88 ++ torchopt/transform/scale_by_adam.py | 317 ++++++ torchopt/transform/scale_by_rms.py | 136 +++ torchopt/transform/scale_by_schedule.py | 114 +++ torchopt/transform/scale_by_stddev.py | 143 +++ torchopt/transform/trace.py | 194 ++++ torchopt/transform/utils.py | 127 +++ tutorials/5_Implicit_Differentiation.ipynb | 11 +- 43 files changed, 2471 insertions(+), 1508 deletions(-) delete mode 100644 torchopt/alias.py create mode 100644 torchopt/alias/__init__.py create mode 100644 torchopt/alias/adam.py create mode 100644 torchopt/alias/adamw.py create mode 100644 torchopt/alias/rmsprop.py create mode 100644 torchopt/alias/sgd.py create mode 100644 torchopt/alias/utils.py create mode 100644 torchopt/diff/__init__.py create mode 100644 torchopt/diff/implicit/__init__.py rename torchopt/{implicit_diff.py => diff/implicit/decorator.py} (100%) rename torchopt/{zero_order_diff.py => diff/zero_order.py} (96%) create mode 100644 torchopt/linalg/__init__.py rename torchopt/{linalg.py => linalg/cg.py} (91%) create mode 100644 torchopt/linear_solve/__init__.py create mode 100644 torchopt/linear_solve/cg.py rename torchopt/{linear_solve.py => linear_solve/normal_cg.py} (57%) create mode 100644 torchopt/linear_solve/utils.py create mode 100644 torchopt/schedule/__init__.py rename torchopt/{schedule.py => schedule/polynomial.py} (99%) delete mode 100644 torchopt/transform.py create mode 100644 torchopt/transform/__init__.py create mode 100644 torchopt/transform/add_decayed_weights.py create mode 100644 torchopt/transform/scale.py create mode 100644 torchopt/transform/scale_by_adam.py create mode 100644 torchopt/transform/scale_by_rms.py create mode 100644 torchopt/transform/scale_by_schedule.py create mode 100644 torchopt/transform/scale_by_stddev.py create mode 100644 torchopt/transform/trace.py create mode 100644 torchopt/transform/utils.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a978e0e..7b537d9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Refactor code organization by [@XuehaiPan](https://github.com/XuehaiPan) in [#92](https://github.com/metaopt/torchopt/pull/92). +- Refactor code organization by [@XuehaiPan](https://github.com/XuehaiPan) in [#92](https://github.com/metaopt/torchopt/pull/92) and [#100](https://github/metaopt/torchopt/pull/100). ### Fixed diff --git a/docs/source/api/api.rst b/docs/source/api/api.rst index 5b632e9f..d0366f60 100644 --- a/docs/source/api/api.rst +++ b/docs/source/api/api.rst @@ -134,7 +134,7 @@ Differentiable Meta-RMSProp Optimizer Implicit differentiation ======================== -.. currentmodule:: torchopt.implicit_diff +.. currentmodule:: torchopt.diff.implicit .. autosummary:: diff --git a/tests/test_implicit.py b/tests/test_implicit.py index e4c7c3bf..d5113e35 100644 --- a/tests/test_implicit.py +++ b/tests/test_implicit.py @@ -115,7 +115,7 @@ def imaml_objective_torchopt(optimal_params, init_params, data): loss = F.cross_entropy(y_pred, y) + regularization_loss return loss - @torchopt.implicit_diff.custom_root( + @torchopt.diff.implicit.custom_root( functorch.grad(imaml_objective_torchopt, argnums=0), argnums=1, has_aux=True ) def inner_solver_torchopt(init_params_copy, init_params, data): @@ -257,7 +257,7 @@ def ridge_objective_torch(params, l2reg, data): regularization_loss = 0.5 * l2reg * torch.sum(torch.square(params)) return 0.5 * torch.mean(torch.square(residuals)) + regularization_loss - @torchopt.implicit_diff.custom_root(functorch.grad(ridge_objective_torch, argnums=0), argnums=1) + @torchopt.diff.implicit.custom_root(functorch.grad(ridge_objective_torch, argnums=0), argnums=1) def ridge_solver_torch(init_params, l2reg, data): """Solve ridge regression by conjugate gradient.""" X_tr, y_tr = data @@ -265,14 +265,14 @@ def ridge_solver_torch(init_params, l2reg, data): def matvec(u): return X_tr.T @ (X_tr @ u) - return torchopt.linear_solve.solve_cg( - matvec=matvec, - b=X_tr.T @ y_tr, + solve = torchopt.linear_solve.solve_cg( ridge=len(y_tr) * l2reg.item(), init=init_params, maxiter=20, ) + return solve(matvec=matvec, b=X_tr.T @ y_tr) + def ridge_objective_jax(params, l2reg, X_tr, y_tr): """Ridge objective function.""" residuals = X_tr @ params - y_tr diff --git a/torchopt/__init__.py b/torchopt/__init__.py index f9b81614..edb093d0 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -17,16 +17,14 @@ from torchopt import ( clip, combine, + diff, distributed, hook, - implicit_diff, - linalg, linear_solve, pytree, schedule, typing, visual, - zero_order_diff, ) from torchopt.accelerated_op import is_available as accelerated_op_available from torchopt.alias import adam, adamw, rmsprop, sgd @@ -55,6 +53,7 @@ __all__ = [ 'accelerated_op_available', + 'diff', 'adam', 'adamw', 'rmsprop', diff --git a/torchopt/alias.py b/torchopt/alias.py deleted file mode 100644 index 07fdd96a..00000000 --- a/torchopt/alias.py +++ /dev/null @@ -1,480 +0,0 @@ -# Copyright 2022 MetaOPT Team. 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. -# ============================================================================== -# This file is modified from: -# https://github.com/deepmind/optax/blob/master/optax/_src/alias.py -# ============================================================================== -# Copyright 2019 DeepMind Technologies Limited. 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. -# ============================================================================== -r"""The aliases of preset ``GradientTransformation``\s for optimizers.""" - -# pylint: disable=invalid-name - -from typing import Any, Callable, Optional, Tuple, Union - -from torchopt import base, combine, transform -from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import - - -__all__ = ['adam', 'adamw', 'rmsprop', 'sgd'] - - -def _flip_sign_and_weight_decay(weight_decay: float = 0.0, maximize=False): - if not 0.0 <= weight_decay: # pylint: disable=unneeded-not - raise ValueError(f'Invalid weight_decay value: {weight_decay}') - - if not maximize and weight_decay == 0.0: - return base.identity() - - def init_fn(params): # pylint: disable=unused-argument - return base.EmptyState() - - if not maximize: # gradient descent - - def update_fn(updates, state, *, params=None, inplace=True): - assert params is not None, ( - 'Parameters are required for weight decay. ' - 'Call `update(updates, state, params=params)` instead.' - ) - - if inplace: - - def f(g, p): - if g is not None: - if g.requires_grad: - return g.add_(p, alpha=weight_decay) - return g.add_(p.data, alpha=weight_decay) - return None - - else: - - def f(g, p): - return g.add(p, alpha=weight_decay) if g is not None else None - - updates = transform.map_flattened(f, updates, params) - return updates, state - - else: # gradient ascent - - if weight_decay == 0.0: - # pylint: disable-next=unused-argument - def update_fn(updates, state, *, params=None, inplace=True): - if inplace: - - def f(g): - return g.neg_() if g is not None else None - - else: - - def f(g): - return g.neg() if g is not None else None - - updates = transform.map_flattened(f, updates) - return updates, state - - else: - - def update_fn(updates, state, *, params=None, inplace=True): - assert params is not None, ( - 'Parameters are required for weight decay. ' - 'Call `update(updates, state, params=params)` instead.' - ) - - if inplace: - - def f(g, p): - if g is not None: - if g.requires_grad: - return g.neg_().add_(p, alpha=weight_decay) - return g.neg_().add_(p.data, alpha=weight_decay) - return None - - else: - - def f(g, p): - return g.neg().add_(p, alpha=weight_decay) if g is not None else None - - updates = transform.map_flattened(f, updates, params) - return updates, state - - return base.GradientTransformation(init_fn, update_fn) - - -def _scale_by_neg_lr(lr: ScalarOrSchedule): - if not (callable(lr) or 0.0 <= lr): - raise ValueError(f'Invalid learning rate: {lr}') - - if callable(lr): - - def schedule_wrapper(count): - return -lr(count) # type: ignore[operator] - - # pylint: disable-next=protected-access - return transform._scale_by_schedule(schedule_wrapper, already_flattened=True) - return transform._scale(-lr, already_flattened=True) # pylint: disable=protected-access - - -# pylint: disable-next=too-many-arguments -def adam( - lr: ScalarOrSchedule = 1e-3, - betas: Tuple[float, float] = (0.9, 0.999), - eps: float = 1e-8, - weight_decay: float = 0.0, - *, - eps_root: float = 0.0, - moment_requires_grad: bool = False, - maximize: bool = False, - use_accelerated_op: bool = False, -) -> base.GradientTransformation: - """The functional Adam optimizer. - - Adam is an SGD variant with learning rate adaptation. The *learning rate* used for each weight - is computed from estimates of first- and second-order moments of the gradients (using suitable - exponential moving averages). - - References: - - Kingma et al, 2014: https://arxiv.org/abs/1412.6980 - - Args: - lr: (default: :const:`1e-3`) - This is a fixed global scaling factor. - betas: (default: :const:`(0.9, 0.999)`) - Coefficients used for computing running averages of gradient and its square. - eps: (default: :const:`1e-8`) - A small constant applied to denominator outside of the square root (as in the Adam - paper) to avoid dividing by zero when rescaling. - weight_decay: (default: :const:`0.0`) - Weight decay, add L2 penalty to parameters. - eps_root: (default: :data:`0.0`) - A small constant applied to denominator inside the square root (as in RMSProp), to avoid - dividing by zero when rescaling. This is needed for example when computing - (meta-)gradients through Adam. - moment_requires_grad: (default: :data:`False`) - If :data:`True` the momentums will be created with flag ``requires_grad=True``, this - flag is often used in Meta-Learning algorithms. - maximize: (default: :data:`False`) - Maximize the params based on the objective, instead of minimizing. - use_accelerated_op: (default: :data:`False`) - If :data:`True` use our implemented fused operator. - - Returns: - The corresponding :class:`GradientTransformation` instance. - - See Also: - The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. - """ - b1, b2 = betas - # pylint: disable=unneeded-not - if not (callable(lr) or 0.0 <= lr): - raise ValueError(f'Invalid learning rate: {lr}') - if not 0.0 <= eps: - raise ValueError(f'Invalid epsilon value: {eps}') - if not 0.0 <= b1 < 1.0: - raise ValueError(f'Invalid beta parameter at index 0: {b1}') - if not 0.0 <= b2 < 1.0: - raise ValueError(f'Invalid beta parameter at index 1: {b2}') - if not 0.0 <= weight_decay: - raise ValueError(f'Invalid weight_decay value: {weight_decay}') - # pylint: enable=unneeded-not - - if use_accelerated_op: - adam_scaler = transform._scale_by_accelerated_adam # pylint: disable=protected-access - else: - adam_scaler = transform._scale_by_adam # pylint: disable=protected-access - - return transform.with_flattened_tree( - combine.chain( - _flip_sign_and_weight_decay(weight_decay=weight_decay, maximize=maximize), - adam_scaler( - b1=b1, - b2=b2, - eps=eps, - eps_root=eps_root, - moment_requires_grad=moment_requires_grad, - already_flattened=True, - ), - _scale_by_neg_lr(lr), - ) - ) - - -# pylint: disable-next=too-many-arguments -def adamw( - lr: ScalarOrSchedule = 1e-3, - betas: Tuple[float, float] = (0.9, 0.999), - eps: float = 1e-8, - weight_decay: float = 1e-2, - *, - eps_root: float = 0.0, - mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, - moment_requires_grad: bool = False, - maximize: bool = False, - use_accelerated_op: bool = False, -) -> base.GradientTransformation: - """Adam with weight decay regularization. - - AdamW uses weight decay to regularize learning towards small weights, as - this leads to better generalization. In SGD you can also use L2 regularization - to implement this as an additive loss term, however L2 regularization - does not behave as intended for adaptive gradient algorithms such as Adam. - - References: - - Loshchilov et al, 2019: https://arxiv.org/abs/1711.05101 - - Args: - lr: (default: :const:`1e-3`) - This is a fixed global scaling factor. - betas: (default: :const:`(0.9, 0.999)`) - Coefficients used for computing running averages of gradient and its square. - eps: (default: :const:`1e-8`) - A small constant applied to denominator outside of the square root (as in the Adam - paper) to avoid dividing by zero when rescaling. - weight_decay: (default: :const:`1e-2`) - Strength of the weight decay regularization. Note that this weight decay is multiplied - with the learning rate. This is consistent with other frameworks such as PyTorch, but - different from (Loshchilov et al, 2019) where the weight decay is only multiplied with - the "schedule multiplier", but not the base learning rate. - eps_root: (default: :data:`0.0`) - A small constant applied to denominator inside the square root (as in RMSProp), to avoid - dividing by zero when rescaling. This is needed for example when computing - (meta-)gradients through Adam. - mask: (default: :data:`None`) - A tree with same structure as (or a prefix of) the params PyTree, or a Callable that - returns such a pytree given the params/updates. The leaves should be booleans, - :data:`True` for leaves/subtrees you want to apply the weight decay to, and - :data:`False` for those you want to skip. Note that the Adam gradient - transformations are applied to all parameters. - moment_requires_grad: (default: :data:`False`) - If :data:`True` the momentums will be created with flag ``requires_grad=True``, this - flag is often used in Meta-Learning algorithms. - maximize: (default: :data:`False`) - Maximize the params based on the objective, instead of minimizing. - use_accelerated_op: (default: :data:`False`) - If :data:`True` use our implemented fused operator. - - Returns: - The corresponding :class:`GradientTransformation` instance. - - See Also: - The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. - """ - b1, b2 = betas - # pylint: disable=unneeded-not - if not (callable(lr) or 0.0 <= lr): - raise ValueError(f'Invalid learning rate: {lr}') - if not 0.0 <= eps: - raise ValueError(f'Invalid epsilon value: {eps}') - if not 0.0 <= b1 < 1.0: - raise ValueError(f'Invalid beta parameter at index 0: {b1}') - if not 0.0 <= b2 < 1.0: - raise ValueError(f'Invalid beta parameter at index 1: {b2}') - if not 0.0 <= weight_decay: - raise ValueError(f'Invalid weight_decay value: {weight_decay}') - # pylint: enable=unneeded-not - - if use_accelerated_op: - adam_scaler = transform._scale_by_accelerated_adam # pylint: disable=protected-access - else: - adam_scaler = transform._scale_by_adam # pylint: disable=protected-access - - return transform.with_flattened_tree( - combine.chain( - _flip_sign_and_weight_decay(weight_decay=0.0, maximize=maximize), - adam_scaler( - b1=b1, - b2=b2, - eps=eps, - eps_root=eps_root, - moment_requires_grad=moment_requires_grad, - already_flattened=True, - ), - transform._add_decayed_weights( # pylint: disable=protected-access - weight_decay=weight_decay, - mask=mask, - already_flattened=True, - ), - _scale_by_neg_lr(lr), - ) - ) - - -# pylint: disable-next=too-many-arguments -def rmsprop( - lr: ScalarOrSchedule = 1e-2, - alpha: float = 0.99, - eps: float = 1e-8, - weight_decay: float = 0.0, - momentum: float = 0.0, - centered: bool = False, - *, - initial_scale: float = 0.0, - nesterov: bool = False, - maximize: bool = False, -) -> base.GradientTransformation: - """The functional version of the RMSProp optimizer. - - RMSProp is an SGD variant with learning rate adaptation. The *learning rate* used for each - weight is scaled by a suitable estimate of the magnitude of the gradients on previous steps. - Several variants of RMSProp can be found in the literature. This alias provides an easy to - configure RMSProp optimizer that can be used to switch between several of these variants. - - References: - - Tieleman and Hinton, 2012: http://www.cs.toronto.edu/~hinton/coursera/lecture6/lec6.pdf - - Graves, 2013: https://arxiv.org/abs/1308.0850 - - Args: - lr: (default: :const:`1e-2`) - This is a fixed global scaling factor. - alpha: (default: :const:`0.99`) - Smoothing constant, the decay used to track the magnitude of previous gradients. - eps: (default: :const:`1e-8`) - A small numerical constant to avoid dividing by zero when rescaling. - weight_decay: (default: :const:`0.0`) - Weight decay, add L2 penalty to parameters. - momentum: (default: :const:`0.0`) - The decay rate used by the momentum term. The momentum is not used when it is set to - :const:`0.0`. - centered: (default: :data:`False`) - If :data:`True`, use the variance of the past gradients to rescale the latest - gradients. - initial_scale: (default: :data:`0.0`) - Initialization of accumulators tracking the magnitude of previous updates. PyTorch - uses :data:`0.0`, TensorFlow 1.x uses :data:`1.0`. When reproducing results from a - paper, verify the value used by the authors. - nesterov: (default: :data:`False`) - Whether to use Nesterov momentum. - maximize: (default: :data:`False`) - Maximize the params based on the objective, instead of minimizing. - - Returns: - The corresponding :class:`GradientTransformation` instance. - - See Also: - The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. - """ - # pylint: disable=unneeded-not - if not (callable(lr) or 0.0 <= lr): - raise ValueError(f'Invalid learning rate: {lr}') - if not 0.0 <= alpha: - raise ValueError(f'Invalid alpha value: {alpha}') - if not 0.0 <= eps: - raise ValueError(f'Invalid epsilon value: {eps}') - if not 0.0 <= momentum: - raise ValueError(f'Invalid momentum value: {momentum}') - if not 0.0 <= weight_decay: - raise ValueError(f'Invalid weight_decay value: {weight_decay}') - # pylint: enable=unneeded-not - - if centered: - rmsprop_scaler = transform._scale_by_stddev # pylint: disable=protected-access - else: - rmsprop_scaler = transform._scale_by_rms # pylint: disable=protected-access - - return transform.with_flattened_tree( - combine.chain( - _flip_sign_and_weight_decay(weight_decay=weight_decay, maximize=maximize), - rmsprop_scaler( - alpha=alpha, - eps=eps, - initial_scale=initial_scale, - already_flattened=True, - ), - transform._trace( # pylint: disable=protected-access - momentum=momentum, - nesterov=nesterov, - already_flattened=True, - ), - _scale_by_neg_lr(lr), - ) - ) - - -def sgd( - lr: ScalarOrSchedule, - momentum: float = 0.0, - dampening: float = 0.0, - weight_decay: float = 0.0, - nesterov: bool = False, - *, - moment_requires_grad: bool = False, - maximize: bool = False, -) -> base.GradientTransformation: - """The functional version of the canonical Stochastic Gradient Descent optimizer. - - This implements stochastic gradient descent. It also includes support for momentum, and nesterov - acceleration, as these are standard practice when using stochastic gradient descent to train - deep neural networks. - - References: - - Sutskever et al, 2013: http://proceedings.mlr.press/v28/sutskever13.pdf - - Args: - lr: This is a fixed global scaling factor. - momentum: (default: :const:`0.0`) - The decay rate used by the momentum term. The momentum is not used when it is set to - :const:`0.0`. - weight_decay: (default: :const:`0.0`) - Weight decay, add L2 penalty to parameters. - dampening: (default: :const:`0.0`) - Dampening for momentum. - nesterov: (default: :data:`False`) - Whether to use Nesterov momentum. - moment_requires_grad: (default: :data:`False`) - If :data:`True` the momentums will be created with flag ``requires_grad=True``, this - flag is often used in Meta-Learning algorithms. - maximize: (default: :data:`False`) - Maximize the params based on the objective, instead of minimizing. - - Returns: - The corresponding :class:`GradientTransformation` instance. - - See Also: - The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. - """ - # pylint: disable=unneeded-not - if not (callable(lr) or 0.0 <= lr): - raise ValueError(f'Invalid learning rate: {lr}') - if not 0.0 <= momentum: - raise ValueError(f'Invalid momentum value: {momentum}') - if not 0.0 <= weight_decay: - raise ValueError(f'Invalid weight_decay value: {weight_decay}') - if nesterov and (momentum <= 0.0 or dampening != 0.0): - raise ValueError('Nesterov momentum requires a momentum and zero dampening') - # pylint: enable=unneeded-not - - return transform.with_flattened_tree( - combine.chain( - _flip_sign_and_weight_decay(weight_decay=weight_decay, maximize=maximize), - transform._trace( # pylint: disable=protected-access - momentum=momentum, - dampening=dampening, - nesterov=nesterov, - moment_requires_grad=moment_requires_grad, - already_flattened=True, - ), - _scale_by_neg_lr(lr), - ) - ) diff --git a/torchopt/alias/__init__.py b/torchopt/alias/__init__.py new file mode 100644 index 00000000..b00b3c35 --- /dev/null +++ b/torchopt/alias/__init__.py @@ -0,0 +1,40 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/alias.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +r"""The aliases of preset :class:`GradientTransformation`\s for optimizers.""" + +from torchopt.alias.adam import adam +from torchopt.alias.adamw import adamw +from torchopt.alias.rmsprop import rmsprop +from torchopt.alias.sgd import sgd + + +__all__ = ['adam', 'adamw', 'rmsprop', 'sgd'] diff --git a/torchopt/alias/adam.py b/torchopt/alias/adam.py new file mode 100644 index 00000000..637b40c7 --- /dev/null +++ b/torchopt/alias/adam.py @@ -0,0 +1,123 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/alias.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset :class:`GradientTransformation` for the Adam optimizer.""" + +from typing import Tuple + +from torchopt.alias.utils import flip_sign_and_add_weight_decay, scale_by_neg_lr +from torchopt.combine import chain_flat +from torchopt.transform import scale_by_accelerated_adam, scale_by_adam +from torchopt.typing import GradientTransformation, ScalarOrSchedule + + +__all__ = ['adam'] + + +# pylint: disable-next=too-many-arguments +def adam( + lr: ScalarOrSchedule = 1e-3, + betas: Tuple[float, float] = (0.9, 0.999), + eps: float = 1e-8, + weight_decay: float = 0.0, + *, + eps_root: float = 0.0, + moment_requires_grad: bool = False, + maximize: bool = False, + use_accelerated_op: bool = False, +) -> GradientTransformation: + """The functional Adam optimizer. + + Adam is an SGD variant with learning rate adaptation. The *learning rate* used for each weight + is computed from estimates of first- and second-order moments of the gradients (using suitable + exponential moving averages). + + References: + - Kingma et al, 2014: https://arxiv.org/abs/1412.6980 + + Args: + lr: (default: :const:`1e-3`) + This is a fixed global scaling factor. + betas: (default: :const:`(0.9, 0.999)`) + Coefficients used for computing running averages of gradient and its square. + eps: (default: :const:`1e-8`) + A small constant applied to denominator outside of the square root (as in the Adam + paper) to avoid dividing by zero when rescaling. + weight_decay: (default: :const:`0.0`) + Weight decay, add L2 penalty to parameters. + eps_root: (default: :data:`0.0`) + A small constant applied to denominator inside the square root (as in RMSProp), to avoid + dividing by zero when rescaling. This is needed for example when computing + (meta-)gradients through Adam. + moment_requires_grad: (default: :data:`False`) + If :data:`True` the momentums will be created with flag ``requires_grad=True``, this + flag is often used in Meta-Learning algorithms. + maximize: (default: :data:`False`) + Maximize the params based on the objective, instead of minimizing. + use_accelerated_op: (default: :data:`False`) + If :data:`True` use our implemented fused operator. + + Returns: + The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. + """ + b1, b2 = betas # pylint: disable=invalid-name + # pylint: disable=unneeded-not + if not (callable(lr) or 0.0 <= lr): + raise ValueError(f'Invalid learning rate: {lr}') + if not 0.0 <= eps: + raise ValueError(f'Invalid epsilon value: {eps}') + if not 0.0 <= b1 < 1.0: + raise ValueError(f'Invalid beta parameter at index 0: {b1}') + if not 0.0 <= b2 < 1.0: + raise ValueError(f'Invalid beta parameter at index 1: {b2}') + if not 0.0 <= weight_decay: + raise ValueError(f'Invalid weight_decay value: {weight_decay}') + # pylint: enable=unneeded-not + + if use_accelerated_op: + adam_scaler = scale_by_accelerated_adam.flat # type: ignore[attr-defined] + else: + adam_scaler = scale_by_adam.flat # type: ignore[attr-defined] + + return chain_flat( + flip_sign_and_add_weight_decay(weight_decay=weight_decay, maximize=maximize), + adam_scaler( + b1=b1, + b2=b2, + eps=eps, + eps_root=eps_root, + moment_requires_grad=moment_requires_grad, + ), + scale_by_neg_lr(lr), + ) diff --git a/torchopt/alias/adamw.py b/torchopt/alias/adamw.py new file mode 100644 index 00000000..4c8d96b4 --- /dev/null +++ b/torchopt/alias/adamw.py @@ -0,0 +1,136 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/alias.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset :class:`GradientTransformation` for the AdamW optimizer.""" + +from typing import Any, Callable, Optional, Tuple, Union + +from torchopt.alias.utils import flip_sign_and_add_weight_decay, scale_by_neg_lr +from torchopt.combine import chain_flat +from torchopt.transform import add_decayed_weights, scale_by_accelerated_adam, scale_by_adam +from torchopt.typing import Params # pylint: disable=unused-import +from torchopt.typing import GradientTransformation, ScalarOrSchedule + + +__all__ = ['adamw'] + + +# pylint: disable-next=too-many-arguments +def adamw( + lr: ScalarOrSchedule = 1e-3, + betas: Tuple[float, float] = (0.9, 0.999), + eps: float = 1e-8, + weight_decay: float = 1e-2, + *, + eps_root: float = 0.0, + mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, + moment_requires_grad: bool = False, + maximize: bool = False, + use_accelerated_op: bool = False, +) -> GradientTransformation: + """Adam with weight decay regularization. + + AdamW uses weight decay to regularize learning towards small weights, as + this leads to better generalization. In SGD you can also use L2 regularization + to implement this as an additive loss term, however L2 regularization + does not behave as intended for adaptive gradient algorithms such as Adam. + + References: + - Loshchilov et al, 2019: https://arxiv.org/abs/1711.05101 + + Args: + lr: (default: :const:`1e-3`) + This is a fixed global scaling factor. + betas: (default: :const:`(0.9, 0.999)`) + Coefficients used for computing running averages of gradient and its square. + eps: (default: :const:`1e-8`) + A small constant applied to denominator outside of the square root (as in the Adam + paper) to avoid dividing by zero when rescaling. + weight_decay: (default: :const:`1e-2`) + Strength of the weight decay regularization. Note that this weight decay is multiplied + with the learning rate. This is consistent with other frameworks such as PyTorch, but + different from (Loshchilov et al, 2019) where the weight decay is only multiplied with + the "schedule multiplier", but not the base learning rate. + eps_root: (default: :data:`0.0`) + A small constant applied to denominator inside the square root (as in RMSProp), to avoid + dividing by zero when rescaling. This is needed for example when computing + (meta-)gradients through Adam. + mask: (default: :data:`None`) + A tree with same structure as (or a prefix of) the params PyTree, or a Callable that + returns such a pytree given the params/updates. The leaves should be booleans, + :data:`True` for leaves/subtrees you want to apply the weight decay to, and + :data:`False` for those you want to skip. Note that the Adam gradient + transformations are applied to all parameters. + moment_requires_grad: (default: :data:`False`) + If :data:`True` the momentums will be created with flag ``requires_grad=True``, this + flag is often used in Meta-Learning algorithms. + maximize: (default: :data:`False`) + Maximize the params based on the objective, instead of minimizing. + use_accelerated_op: (default: :data:`False`) + If :data:`True` use our implemented fused operator. + + Returns: + The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. + """ + b1, b2 = betas # pylint: disable=invalid-name + # pylint: disable=unneeded-not + if not (callable(lr) or 0.0 <= lr): + raise ValueError(f'Invalid learning rate: {lr}') + if not 0.0 <= eps: + raise ValueError(f'Invalid epsilon value: {eps}') + if not 0.0 <= b1 < 1.0: + raise ValueError(f'Invalid beta parameter at index 0: {b1}') + if not 0.0 <= b2 < 1.0: + raise ValueError(f'Invalid beta parameter at index 1: {b2}') + if not 0.0 <= weight_decay: + raise ValueError(f'Invalid weight_decay value: {weight_decay}') + # pylint: enable=unneeded-not + + if use_accelerated_op: + adam_scaler = scale_by_accelerated_adam.flat # type: ignore[attr-defined] + else: + adam_scaler = scale_by_adam.flat # type: ignore[attr-defined] + + return chain_flat( + flip_sign_and_add_weight_decay(weight_decay=0.0, maximize=maximize), + adam_scaler( + b1=b1, + b2=b2, + eps=eps, + eps_root=eps_root, + moment_requires_grad=moment_requires_grad, + ), + add_decayed_weights.flat(weight_decay=weight_decay, mask=mask), # type: ignore[attr-defined] + scale_by_neg_lr(lr), + ) diff --git a/torchopt/alias/rmsprop.py b/torchopt/alias/rmsprop.py new file mode 100644 index 00000000..6d2ddeb3 --- /dev/null +++ b/torchopt/alias/rmsprop.py @@ -0,0 +1,124 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/alias.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset :class:`GradientTransformation` for the RMSProp optimizer.""" + +from torchopt.alias.utils import flip_sign_and_add_weight_decay, scale_by_neg_lr +from torchopt.combine import chain_flat +from torchopt.transform import scale_by_rms, scale_by_stddev, trace +from torchopt.typing import GradientTransformation, ScalarOrSchedule + + +__all__ = ['rmsprop'] + + +# pylint: disable-next=too-many-arguments +def rmsprop( + lr: ScalarOrSchedule = 1e-2, + alpha: float = 0.99, + eps: float = 1e-8, + weight_decay: float = 0.0, + momentum: float = 0.0, + centered: bool = False, + *, + initial_scale: float = 0.0, + nesterov: bool = False, + maximize: bool = False, +) -> GradientTransformation: + """The functional version of the RMSProp optimizer. + + RMSProp is an SGD variant with learning rate adaptation. The *learning rate* used for each + weight is scaled by a suitable estimate of the magnitude of the gradients on previous steps. + Several variants of RMSProp can be found in the literature. This alias provides an easy to + configure RMSProp optimizer that can be used to switch between several of these variants. + + References: + - Tieleman and Hinton, 2012: http://www.cs.toronto.edu/~hinton/coursera/lecture6/lec6.pdf + - Graves, 2013: https://arxiv.org/abs/1308.0850 + + Args: + lr: (default: :const:`1e-2`) + This is a fixed global scaling factor. + alpha: (default: :const:`0.99`) + Smoothing constant, the decay used to track the magnitude of previous gradients. + eps: (default: :const:`1e-8`) + A small numerical constant to avoid dividing by zero when rescaling. + weight_decay: (default: :const:`0.0`) + Weight decay, add L2 penalty to parameters. + momentum: (default: :const:`0.0`) + The decay rate used by the momentum term. The momentum is not used when it is set to + :const:`0.0`. + centered: (default: :data:`False`) + If :data:`True`, use the variance of the past gradients to rescale the latest + gradients. + initial_scale: (default: :data:`0.0`) + Initialization of accumulators tracking the magnitude of previous updates. PyTorch + uses :data:`0.0`, TensorFlow 1.x uses :data:`1.0`. When reproducing results from a + paper, verify the value used by the authors. + nesterov: (default: :data:`False`) + Whether to use Nesterov momentum. + maximize: (default: :data:`False`) + Maximize the params based on the objective, instead of minimizing. + + Returns: + The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. + """ + # pylint: disable=unneeded-not + if not (callable(lr) or 0.0 <= lr): + raise ValueError(f'Invalid learning rate: {lr}') + if not 0.0 <= alpha: + raise ValueError(f'Invalid alpha value: {alpha}') + if not 0.0 <= eps: + raise ValueError(f'Invalid epsilon value: {eps}') + if not 0.0 <= momentum: + raise ValueError(f'Invalid momentum value: {momentum}') + if not 0.0 <= weight_decay: + raise ValueError(f'Invalid weight_decay value: {weight_decay}') + # pylint: enable=unneeded-not + + if centered: + rmsprop_scaler = scale_by_stddev.flat # type: ignore[attr-defined] + else: + rmsprop_scaler = scale_by_rms.flat # type: ignore[attr-defined] + + return chain_flat( + flip_sign_and_add_weight_decay(weight_decay=weight_decay, maximize=maximize), + rmsprop_scaler( + alpha=alpha, + eps=eps, + initial_scale=initial_scale, + ), + trace.flat(momentum=momentum, nesterov=nesterov), # type: ignore[attr-defined] + scale_by_neg_lr(lr), + ) diff --git a/torchopt/alias/sgd.py b/torchopt/alias/sgd.py new file mode 100644 index 00000000..af87587f --- /dev/null +++ b/torchopt/alias/sgd.py @@ -0,0 +1,105 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/alias.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset :class:`GradientTransformation` for the SGD optimizer.""" + +from torchopt.alias.utils import flip_sign_and_add_weight_decay, scale_by_neg_lr +from torchopt.combine import chain_flat +from torchopt.transform import trace +from torchopt.typing import GradientTransformation, ScalarOrSchedule + + +__all__ = ['sgd'] + + +def sgd( + lr: ScalarOrSchedule, + momentum: float = 0.0, + dampening: float = 0.0, + weight_decay: float = 0.0, + nesterov: bool = False, + *, + moment_requires_grad: bool = False, + maximize: bool = False, +) -> GradientTransformation: + """The functional version of the canonical Stochastic Gradient Descent optimizer. + + This implements stochastic gradient descent. It also includes support for momentum, and nesterov + acceleration, as these are standard practice when using stochastic gradient descent to train + deep neural networks. + + References: + - Sutskever et al, 2013: http://proceedings.mlr.press/v28/sutskever13.pdf + + Args: + lr: This is a fixed global scaling factor. + momentum: (default: :const:`0.0`) + The decay rate used by the momentum term. The momentum is not used when it is set to + :const:`0.0`. + weight_decay: (default: :const:`0.0`) + Weight decay, add L2 penalty to parameters. + dampening: (default: :const:`0.0`) + Dampening for momentum. + nesterov: (default: :data:`False`) + Whether to use Nesterov momentum. + moment_requires_grad: (default: :data:`False`) + If :data:`True` the momentums will be created with flag ``requires_grad=True``, this + flag is often used in Meta-Learning algorithms. + maximize: (default: :data:`False`) + Maximize the params based on the objective, instead of minimizing. + + Returns: + The corresponding :class:`GradientTransformation` instance. + + See Also: + The functional optimizer wrapper :class:`torchopt.FuncOptimizer`. + """ + # pylint: disable=unneeded-not + if not (callable(lr) or 0.0 <= lr): + raise ValueError(f'Invalid learning rate: {lr}') + if not 0.0 <= momentum: + raise ValueError(f'Invalid momentum value: {momentum}') + if not 0.0 <= weight_decay: + raise ValueError(f'Invalid weight_decay value: {weight_decay}') + if nesterov and (momentum <= 0.0 or dampening != 0.0): + raise ValueError('Nesterov momentum requires a momentum and zero dampening') + # pylint: enable=unneeded-not + + return chain_flat( + flip_sign_and_add_weight_decay(weight_decay=weight_decay, maximize=maximize), + trace.flat( # type: ignore[attr-defined] + momentum=momentum, + dampening=dampening, + nesterov=nesterov, + moment_requires_grad=moment_requires_grad, + ), + scale_by_neg_lr(lr), + ) diff --git a/torchopt/alias/utils.py b/torchopt/alias/utils.py new file mode 100644 index 00000000..9a037224 --- /dev/null +++ b/torchopt/alias/utils.py @@ -0,0 +1,118 @@ +# Copyright 2022 MetaOPT Team. 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. +r"""Utilities for the aliases of preset :class:`GradientTransformation`\s for optimizers.""" + +from torchopt.base import EmptyState, GradientTransformation, identity +from torchopt.transform import scale, scale_by_schedule +from torchopt.transform.utils import tree_map_flat +from torchopt.typing import ScalarOrSchedule + + +__all__ = ['flip_sign_and_add_weight_decay', 'scale_by_neg_lr'] + + +def flip_sign_and_add_weight_decay(weight_decay: float = 0.0, maximize=False): + """Flips the sign of the updates and adds weight decay.""" + if not 0.0 <= weight_decay: # pylint: disable=unneeded-not + raise ValueError(f'Invalid weight_decay value: {weight_decay}') + + if not maximize and weight_decay == 0.0: + return identity() + + def init_fn(params): # pylint: disable=unused-argument + return EmptyState() + + if not maximize: # gradient descent + + def update_fn(updates, state, *, params=None, inplace=True): + assert params is not None, ( + 'Parameters are required for weight decay. ' + 'Call `update(updates, state, params=params)` instead.' + ) + + if inplace: + + def f(g, p): + if g is not None: + if g.requires_grad: + return g.add_(p, alpha=weight_decay) + return g.add_(p.data, alpha=weight_decay) + return None + + else: + + def f(g, p): + return g.add(p, alpha=weight_decay) if g is not None else None + + updates = tree_map_flat(f, updates, params) + return updates, state + + else: # gradient ascent + + if weight_decay == 0.0: + # pylint: disable-next=unused-argument + def update_fn(updates, state, *, params=None, inplace=True): + if inplace: + + def f(g): + return g.neg_() if g is not None else None + + else: + + def f(g): + return g.neg() if g is not None else None + + updates = tree_map_flat(f, updates) + return updates, state + + else: + + def update_fn(updates, state, *, params=None, inplace=True): + assert params is not None, ( + 'Parameters are required for weight decay. ' + 'Call `update(updates, state, params=params)` instead.' + ) + + if inplace: + + def f(g, p): + if g is not None: + if g.requires_grad: + return g.neg_().add_(p, alpha=weight_decay) + return g.neg_().add_(p.data, alpha=weight_decay) + return None + + else: + + def f(g, p): + return g.neg().add_(p, alpha=weight_decay) if g is not None else None + + updates = tree_map_flat(f, updates, params) + return updates, state + + return GradientTransformation(init_fn, update_fn) + + +def scale_by_neg_lr(lr: ScalarOrSchedule): + """Scales the updates by the negative learning rate.""" + if not (callable(lr) or 0.0 <= lr): + raise ValueError(f'Invalid learning rate: {lr}') + + if callable(lr): + + def schedule_wrapper(count): + return -lr(count) # type: ignore[operator] + + return scale_by_schedule.flat(schedule_wrapper) # type: ignore[attr-defined] + return scale.flat(-lr) # type: ignore[attr-defined] diff --git a/torchopt/combine.py b/torchopt/combine.py index e3145020..c7923bb6 100644 --- a/torchopt/combine.py +++ b/torchopt/combine.py @@ -31,13 +31,15 @@ # ============================================================================== """Utilities to define a chained transformation.""" -from torchopt.base import ChainedGradientTransformation, GradientTransformation +from torchopt import pytree +from torchopt.base import ChainedGradientTransformation, GradientTransformation, identity +from torchopt.typing import Updates -__all__ = ['chain'] +__all__ = ['chain', 'chain_flat'] -def chain(*args: GradientTransformation) -> GradientTransformation: +def chain(*transformations: GradientTransformation) -> GradientTransformation: """Applies a list of chainable update transformations. Given a sequence of chainable transforms, :func:`chain` returns an :func:`init_fn` that @@ -45,10 +47,53 @@ def chain(*args: GradientTransformation) -> GradientTransformation: :func:`update_fn` which chains the update transformations feeding the appropriate state to each. Args: - *args: + *transformations: A sequence of chainable ``(init_fn, update_fn)`` tuples. Returns: A single ``(init_fn, update_fn)`` tuple. """ - return ChainedGradientTransformation(*args) + if len(transformations) == 0: + return identity() + if len(transformations) == 1: + return transformations[0] + return ChainedGradientTransformation(*transformations) + + +def chain_flat(*transformations: GradientTransformation) -> GradientTransformation: + """Wraps around the inner transformations that manipulates the flattened tree structure (:class:``list``). + + Args: + *transformations: + A sequence of chainable ``(init_fn, update_fn)`` tuples. + + Returns: + A single ``(init_fn, update_fn)`` tuple. + """ + if len(transformations) == 0: + return identity() + if len(transformations) == 1: + inner = transformations[0] + else: + inner = chain(*transformations) + + def init_fn(params): + return inner.init(pytree.tree_leaves(params)) # type: ignore[arg-type] + + def update_fn(updates, state, *, params=None, inplace=True): + flat_updates, treedef = pytree.tree_flatten(updates) + if params is not None: + params = pytree.tree_leaves(params) + + flat_updates, state = inner.update( + flat_updates, state, params=params, inplace=inplace # type: ignore[arg-type] + ) + updates: Updates + updates = pytree.tree_unflatten(treedef, flat_updates) # type: ignore[arg-type] + + return updates, state + + return GradientTransformation(init_fn, update_fn) + + +chain.flat = chain_flat # type: ignore[attr-defined] diff --git a/torchopt/diff/__init__.py b/torchopt/diff/__init__.py new file mode 100644 index 00000000..a8d26450 --- /dev/null +++ b/torchopt/diff/__init__.py @@ -0,0 +1,17 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Differentiable Gradient Estimation.""" + +from torchopt.diff import implicit, zero_order diff --git a/torchopt/diff/implicit/__init__.py b/torchopt/diff/implicit/__init__.py new file mode 100644 index 00000000..2f3f184c --- /dev/null +++ b/torchopt/diff/implicit/__init__.py @@ -0,0 +1,17 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Implicit Meta-Gradient.""" + +from torchopt.diff.implicit.decorator import custom_root diff --git a/torchopt/implicit_diff.py b/torchopt/diff/implicit/decorator.py similarity index 100% rename from torchopt/implicit_diff.py rename to torchopt/diff/implicit/decorator.py diff --git a/torchopt/zero_order_diff.py b/torchopt/diff/zero_order.py similarity index 96% rename from torchopt/zero_order_diff.py rename to torchopt/diff/zero_order.py index d4982292..a8d8b0ee 100644 --- a/torchopt/zero_order_diff.py +++ b/torchopt/diff/zero_order.py @@ -15,6 +15,8 @@ """Zero-Order Gradient Estimation.""" import functools +import sys as _sys +from types import ModuleType as _ModuleType from typing import Any, Callable, List, Sequence, Tuple, Union from typing_extensions import Literal # Python 3.8+ from typing_extensions import Protocol # Python 3.8+ @@ -345,3 +347,14 @@ def zero_order( argnums = (argnums,) return functools.partial(algo_fn, distribution=distribution, argnums=argnums, sigma=sigma) + + +class _CallableModule(_ModuleType): # pylint: disable=too-few-public-methods + def __call__(self, *args, **kwargs): + return self.zero_order(*args, **kwargs) + + +# Replace entry in sys.modules for this module with an instance of _CallableModule +_modself = _sys.modules[__name__] +_modself.__class__ = _CallableModule +del _sys, _ModuleType, _modself, _CallableModule diff --git a/torchopt/linalg/__init__.py b/torchopt/linalg/__init__.py new file mode 100644 index 00000000..4fff4df2 --- /dev/null +++ b/torchopt/linalg/__init__.py @@ -0,0 +1,37 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/google/jax/blob/main/jax/_src/scipy/sparse/linalg.py +# ============================================================================== +# Copyright 2020 Google LLC +# +# 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 +# +# https://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. +# ============================================================================== +"""Linear algebra functions.""" + +from torchopt.linalg.cg import cg + + +__all__ = ['cg'] diff --git a/torchopt/linalg.py b/torchopt/linalg/cg.py similarity index 91% rename from torchopt/linalg.py rename to torchopt/linalg/cg.py index 68caa928..f5fb93dc 100644 --- a/torchopt/linalg.py +++ b/torchopt/linalg/cg.py @@ -29,7 +29,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Linear algebra functions.""" +"""Conjugate Gradient iteration to solve ``Ax = b``.""" # pylint: disable=invalid-name @@ -45,21 +45,21 @@ __all__ = ['cg'] -def _inner_product_kernel(x: torch.Tensor, y: torch.Tensor) -> float: - """Computes (x.conj() * y).real.""" - x = x.reshape(-1) - y = y.reshape(-1) +def _vdot_real_kernel(x: torch.Tensor, y: torch.Tensor) -> float: + """Computes dot(x.conj(), y).real.""" + x = x.contiguous().view(-1) + y = y.contiguous().view(-1) prod = torch.dot(x.real, y.real).item() - if x.is_complex() or y.is_complex(): + if x.is_complex() and y.is_complex(): prod += torch.dot(x.imag, y.imag).item() return prod -def tree_inner_product(tree_x: TensorTree, tree_y: TensorTree) -> float: - """Computes (tree_x.conj() * tree_y).real.sum().""" +def tree_vdot_real(tree_x: TensorTree, tree_y: TensorTree) -> float: + """Computes dot(tree_x.conj(), tree_y).real.sum().""" leaves_x, treedef = pytree.tree_flatten(tree_x) leaves_y = treedef.flatten_up_to(tree_y) - return sum(map(_inner_product_kernel, leaves_x, leaves_y)) # type: ignore[arg-type] + return sum(map(_vdot_real_kernel, leaves_x, leaves_y)) # type: ignore[arg-type] def _identity(x: TensorTree) -> TensorTree: @@ -93,29 +93,29 @@ def _cg_solve( # https://en.wikipedia.org/wiki/Conjugate_gradient_method#The_preconditioned_conjugate_gradient_method # tolerance handling uses the "non-legacy" behavior of `scipy.sparse.linalg.cg` - bs = tree_inner_product(b, b) - atol2 = max(rtol**2 * bs, atol**2) + b2 = tree_vdot_real(b, b) + atol2 = max(rtol**2 * b2, atol**2) def cond_fn(value): _, r, gamma, _, k = value - rs = gamma if M is _identity else tree_inner_product(r, r) + rs = gamma if M is _identity else tree_vdot_real(r, r) return rs > atol2 and k < maxiter def body_fn(value): x, r, gamma, p, k = value Ap = A(p) - alpha = gamma / tree_inner_product(p, Ap) + alpha = gamma / tree_vdot_real(p, Ap) x_ = pytree.tree_map(lambda a, b: a.add(b, alpha=alpha), x, p) r_ = pytree.tree_map(lambda a, b: a.sub(b, alpha=alpha), r, Ap) z_ = M(r_) - gamma_ = tree_inner_product(r_, z_) + gamma_ = tree_vdot_real(r_, z_) beta_ = gamma_ / gamma p_ = pytree.tree_map(lambda a, b: a.add(b, alpha=beta_), z_, p) return x_, r_, gamma_, p_, k + 1 r0 = pytree.tree_map(torch.sub, b, A(x0)) p0 = z0 = M(r0) - gamma0 = tree_inner_product(r0, z0) + gamma0 = tree_vdot_real(r0, z0) value = (x0, r0, gamma0, p0, 0) while cond_fn(value): diff --git a/torchopt/linear_solve/__init__.py b/torchopt/linear_solve/__init__.py new file mode 100644 index 00000000..e27ba4c0 --- /dev/null +++ b/torchopt/linear_solve/__init__.py @@ -0,0 +1,38 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/google/jaxopt/blob/main/jaxopt/_src/linear_solve.py +# ============================================================================== +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. +# ============================================================================== +"""Linear algebra solvers.""" + +from torchopt.linear_solve.cg import solve_cg +from torchopt.linear_solve.normal_cg import solve_normal_cg + + +__all__ = ['solve_cg', 'solve_normal_cg'] diff --git a/torchopt/linear_solve/cg.py b/torchopt/linear_solve/cg.py new file mode 100644 index 00000000..9c150038 --- /dev/null +++ b/torchopt/linear_solve/cg.py @@ -0,0 +1,79 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/google/jaxopt/blob/main/jaxopt/_src/linear_solve.py +# ============================================================================== +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. +# ============================================================================== +"""Linear algebra solver for ``A x = b`` using conjugate gradient.""" + +# pylint: disable=invalid-name + +import functools +from typing import Callable, Optional + +from torchopt import linalg +from torchopt.linear_solve.utils import make_ridge_matvec +from torchopt.typing import TensorTree + + +__all__ = ['solve_cg'] + + +def _solve_cg( + matvec: Callable[[TensorTree], TensorTree], # (x) -> A @ x + b: TensorTree, + ridge: Optional[float] = None, + init: Optional[TensorTree] = None, + **kwargs, +) -> TensorTree: + """Solves ``A x = b`` using conjugate gradient. + + It assumes that ``A`` is a hermitian, positive definite matrix. + + Args: + matvec: A function that returns the product between ``A`` and a vector. + b: A tree of tensors for the right hand side of the equation. + ridge: Optional ridge regularization. + init: Optional initialization to be used by conjugate gradient. + **kwargs: Additional keyword arguments for the conjugate gradient solver. + + Returns: + The solution with the same structure as ``b``. + """ + if ridge is not None: + # (x) -> A @ x + ridge * x + # i.e. (x) -> (A + ridge * I) @ x + matvec = make_ridge_matvec(matvec, ridge=ridge) + + # Returns solution for `(A + ridge * I) @ x = b`. + return linalg.cg(matvec, b, x0=init, **kwargs) + + +def solve_cg(**kwargs): + """Wrapper for :func:`solve_cg`.""" + return functools.partial(_solve_cg, **kwargs) diff --git a/torchopt/linear_solve.py b/torchopt/linear_solve/normal_cg.py similarity index 57% rename from torchopt/linear_solve.py rename to torchopt/linear_solve/normal_cg.py index 8ba497bb..63e74e80 100644 --- a/torchopt/linear_solve.py +++ b/torchopt/linear_solve/normal_cg.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================== # This file is modified from: -# https://github.com/google/jaxopt/blob/main/jaxopt/_src/implicit_diff.py +# https://github.com/google/jaxopt/blob/main/jaxopt/_src/linear_solve.py # ============================================================================== # Copyright 2021 Google LLC # @@ -29,78 +29,19 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Linear algebra solvers.""" +"""Linear algebra solver for ``A^T A x = A^T b`` using conjugate gradient.""" # pylint: disable=invalid-name import functools from typing import Callable, Optional -import functorch - -from torchopt import linalg, pytree +from torchopt import linalg +from torchopt.linear_solve.utils import make_normal_matvec, make_ridge_matvec, make_rmatvec from torchopt.typing import TensorTree -__all__ = ['solve_cg', 'solve_normal_cg'] - - -def tree_add(tree_x: TensorTree, tree_y: TensorTree, alpha: float = 1.0) -> TensorTree: - """Computes tree_x + alpha * tree_y.""" - return pytree.tree_map(lambda x, y: x.add(y, alpha=alpha), tree_x, tree_y) - - -def _make_rmatvec( - matvec: Callable[[TensorTree], TensorTree], x: TensorTree -) -> Callable[[TensorTree], TensorTree]: - """Returns a function that computes A^T y from matvec(x) = A x.""" - _, vjp, *_ = functorch.vjp(matvec, x) - return lambda y: vjp(y)[0] - - -def _normal_matvec(matvec: Callable[[TensorTree], TensorTree], x: TensorTree) -> TensorTree: - """Computes A^T A x from matvec(x) = A x.""" - matvec_x, vjp, *_ = functorch.vjp(matvec, x) - return vjp(matvec_x)[0] - - -def _make_ridge_matvec( - matvec: Callable[[TensorTree], TensorTree], ridge: float = 0.0 -) -> Callable[[TensorTree], TensorTree]: - def ridge_matvec(v: TensorTree) -> TensorTree: - return tree_add(matvec(v), v, alpha=ridge) - - return ridge_matvec - - -def solve_cg( - matvec: Callable[['TensorTree'], 'TensorTree'], # (x) -> A @ x - b: 'TensorTree', - ridge: Optional[float] = None, - init: Optional['TensorTree'] = None, - **kwargs, -) -> 'TensorTree': - """Solves ``A x = b`` using conjugate gradient. - - It assumes that ``A`` is a hermitian, positive definite matrix. - - Args: - matvec: A function that returns the product between ``A`` and a vector. - b: A tree of tensors for the right hand side of the equation. - ridge: Optional ridge regularization. - init: Optional initialization to be used by conjugate gradient. - **kwargs: Additional keyword arguments for the conjugate gradient solver. - - Returns: - The solution with the same structure as ``b``. - """ - if ridge is not None: - # (x) -> A @ x + ridge * x - # i.e. (x) -> (A + ridge * I) @ x - matvec = _make_ridge_matvec(matvec, ridge=ridge) - - # Returns solution for `(A + ridge * I) @ x = b`. - return linalg.cg(matvec, b, x0=init, **kwargs) +__all__ = ['solve_normal_cg'] def _solve_normal_cg( @@ -138,20 +79,18 @@ def _solve_normal_cg( # Returns solution for `A @ x = b`. return linalg.cg(matvec, b, x0=init, **kwargs) - rmatvec = _make_rmatvec(matvec, example_x) # (x) -> A.T @ x - - def normal_matvec(x): # (x) -> A.T @ A @ x - return _normal_matvec(matvec, x) + rmatvec = make_rmatvec(matvec, example_x) # (x) -> A.T @ x + normal_matvec = make_normal_matvec(matvec) # (x) -> A.T @ A @ x if ridge is not None: # (x) -> A.T @ A @ x + ridge * x # i.e. (x) -> (A.T @ A + ridge * I) @ x - normal_matvec = _make_ridge_matvec(normal_matvec, ridge=ridge) + normal_matvec = make_ridge_matvec(normal_matvec, ridge=ridge) - Ab = rmatvec(b) # A.T @ b + rhs = rmatvec(b) # A.T @ b # Returns solution for `(A.T @ A + ridge * I) @ x = A.T @ b`. - return linalg.cg(normal_matvec, Ab, x0=init, **kwargs) + return linalg.cg(normal_matvec, rhs, x0=init, **kwargs) def solve_normal_cg(**kwargs): diff --git a/torchopt/linear_solve/utils.py b/torchopt/linear_solve/utils.py new file mode 100644 index 00000000..5fede71d --- /dev/null +++ b/torchopt/linear_solve/utils.py @@ -0,0 +1,80 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/google/jaxopt/blob/main/jaxopt/_src/linear_solve.py +# ============================================================================== +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. +# ============================================================================== +"""Utilities for linear algebra solvers.""" + +# pylint: disable=invalid-name + +from typing import Callable + +import functorch + +from torchopt import pytree +from torchopt.typing import TensorTree + + +def tree_add(tree_x: TensorTree, tree_y: TensorTree, alpha: float = 1.0) -> TensorTree: + """Computes tree_x + alpha * tree_y.""" + return pytree.tree_map(lambda x, y: x.add(y, alpha=alpha), tree_x, tree_y) + + +def make_rmatvec( + matvec: Callable[[TensorTree], TensorTree], example_x: TensorTree +) -> Callable[[TensorTree], TensorTree]: + """Returns a function that computes ``rmatvec(y) = A.T @ y`` from ``matvec(x) = A @ x``.""" + _, vjp, *_ = functorch.vjp(matvec, example_x) + + return lambda y: vjp(y)[0] + + +def make_normal_matvec( + matvec: Callable[[TensorTree], TensorTree] +) -> Callable[[TensorTree], TensorTree]: + """Returns a function that computes ``normal_matvec(y) = A.T @ A @ y`` from ``matvec(x) = A @ x``.""" + + def normal_matvec(y: TensorTree) -> TensorTree: + """Computes ``A.T @ A @ y`` from ``matvec(x) = A @ x``.""" + matvec_y, vjp, *_ = functorch.vjp(matvec, y) + return vjp(matvec_y)[0] + + return normal_matvec + + +def make_ridge_matvec( + matvec: Callable[[TensorTree], TensorTree], ridge: float = 0.0 +) -> Callable[[TensorTree], TensorTree]: + """Returns a function that computes ``ridge_matvec(y) = A.T @ A @ y + ridge * y`` from ``matvec(x) = A @ x``.""" + + def ridge_matvec(y: TensorTree) -> TensorTree: + """Computes ``A.T @ A @ v + ridge * v`` from ``matvec(x) = A @ x``.""" + return tree_add(matvec(y), y, alpha=ridge) + + return ridge_matvec diff --git a/torchopt/optim/adam.py b/torchopt/optim/adam.py index 4ac12db8..8fcdff90 100644 --- a/torchopt/optim/adam.py +++ b/torchopt/optim/adam.py @@ -18,7 +18,7 @@ import torch -from torchopt.alias import adam +from torchopt import alias from torchopt.optim.base import Optimizer from torchopt.typing import ScalarOrSchedule @@ -72,7 +72,7 @@ def __init__( """ super().__init__( params, - adam( + alias.adam( lr=lr, betas=betas, eps=eps, diff --git a/torchopt/optim/adamw.py b/torchopt/optim/adamw.py index 3b45bbe1..9613cab4 100644 --- a/torchopt/optim/adamw.py +++ b/torchopt/optim/adamw.py @@ -18,7 +18,7 @@ import torch -from torchopt.alias import adamw +from torchopt import alias from torchopt.optim.base import Optimizer from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import @@ -82,7 +82,7 @@ def __init__( """ super().__init__( params, - adamw( + alias.adamw( lr=lr, betas=betas, eps=eps, diff --git a/torchopt/optim/meta/adam.py b/torchopt/optim/meta/adam.py index bb578f23..8d934e2c 100644 --- a/torchopt/optim/meta/adam.py +++ b/torchopt/optim/meta/adam.py @@ -18,7 +18,7 @@ import torch.nn as nn -from torchopt.alias import adam +from torchopt import alias from torchopt.optim.meta.base import MetaOptimizer from torchopt.typing import ScalarOrSchedule @@ -76,7 +76,7 @@ def __init__( """ super().__init__( net, - adam( + alias.adam( lr=lr, betas=betas, eps=eps, diff --git a/torchopt/optim/meta/adamw.py b/torchopt/optim/meta/adamw.py index 0e40dcd4..65e154d3 100644 --- a/torchopt/optim/meta/adamw.py +++ b/torchopt/optim/meta/adamw.py @@ -18,7 +18,7 @@ import torch.nn as nn -from torchopt.alias import adamw +from torchopt import alias from torchopt.optim.meta.base import MetaOptimizer from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import @@ -86,7 +86,7 @@ def __init__( """ super().__init__( net, - adamw( + alias.adamw( lr=lr, betas=betas, eps=eps, diff --git a/torchopt/optim/meta/rmsprop.py b/torchopt/optim/meta/rmsprop.py index 533d3219..e7bc9b37 100644 --- a/torchopt/optim/meta/rmsprop.py +++ b/torchopt/optim/meta/rmsprop.py @@ -16,7 +16,7 @@ import torch.nn as nn -from torchopt.alias import rmsprop +from torchopt import alias from torchopt.optim.meta.base import MetaOptimizer from torchopt.typing import ScalarOrSchedule @@ -77,7 +77,7 @@ def __init__( """ super().__init__( net, - rmsprop( + alias.rmsprop( lr=lr, alpha=alpha, eps=eps, diff --git a/torchopt/optim/meta/sgd.py b/torchopt/optim/meta/sgd.py index 44810725..78b8e2fc 100644 --- a/torchopt/optim/meta/sgd.py +++ b/torchopt/optim/meta/sgd.py @@ -16,7 +16,7 @@ import torch.nn as nn -from torchopt.alias import sgd +from torchopt import alias from torchopt.optim.meta.base import MetaOptimizer from torchopt.typing import ScalarOrSchedule @@ -67,7 +67,7 @@ def __init__( """ super().__init__( net, - sgd( + alias.sgd( lr=lr, momentum=momentum, weight_decay=weight_decay, diff --git a/torchopt/optim/rmsprop.py b/torchopt/optim/rmsprop.py index cc770834..dc649722 100644 --- a/torchopt/optim/rmsprop.py +++ b/torchopt/optim/rmsprop.py @@ -18,7 +18,7 @@ import torch -from torchopt.alias import rmsprop +from torchopt import alias from torchopt.optim.base import Optimizer from torchopt.typing import ScalarOrSchedule @@ -79,7 +79,7 @@ def __init__( """ super().__init__( params, - rmsprop( + alias.rmsprop( lr=lr, alpha=alpha, eps=eps, diff --git a/torchopt/optim/sgd.py b/torchopt/optim/sgd.py index 9161a49b..d83786ae 100644 --- a/torchopt/optim/sgd.py +++ b/torchopt/optim/sgd.py @@ -18,7 +18,7 @@ import torch -from torchopt.alias import sgd +from torchopt import alias from torchopt.optim.base import Optimizer from torchopt.typing import ScalarOrSchedule @@ -65,7 +65,7 @@ def __init__( """ super().__init__( params, - sgd( + alias.sgd( lr=lr, momentum=momentum, weight_decay=weight_decay, diff --git a/torchopt/schedule/__init__.py b/torchopt/schedule/__init__.py new file mode 100644 index 00000000..46f59550 --- /dev/null +++ b/torchopt/schedule/__init__.py @@ -0,0 +1,37 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/schedule.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Learning rate schedules.""" + +from torchopt.schedule.polynomial import linear_schedule, polynomial_schedule + + +__all__ = ['polynomial_schedule', 'linear_schedule'] diff --git a/torchopt/schedule.py b/torchopt/schedule/polynomial.py similarity index 99% rename from torchopt/schedule.py rename to torchopt/schedule/polynomial.py index 4effb95b..8d2c2056 100644 --- a/torchopt/schedule.py +++ b/torchopt/schedule/polynomial.py @@ -29,7 +29,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Learning rate schedules.""" +"""Polynomial learning rate schedules.""" import logging diff --git a/torchopt/transform.py b/torchopt/transform.py deleted file mode 100644 index adb02c87..00000000 --- a/torchopt/transform.py +++ /dev/null @@ -1,904 +0,0 @@ -# Copyright 2022 MetaOPT Team. 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. -# ============================================================================== -# This file is modified from: -# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py -# ============================================================================== -# Copyright 2019 DeepMind Technologies Limited. 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. -# ============================================================================== -"""Preset transformations.""" - -# pylint: disable=invalid-name - -from typing import Any, Callable, List, NamedTuple, Optional, Sequence, Union - -import torch - -from torchopt import pytree -from torchopt.base import EmptyState, GradientTransformation, identity -from torchopt.typing import Params, Schedule, TensorTree, Updates - - -ScaleState = EmptyState -INT64_MAX = torch.iinfo(torch.int64).max -TRIPLE_PYTREEDEF = pytree.tree_structure((0, 1, 2)) # type: ignore[arg-type] - - -def map_flattened(func: Callable, *args: Any) -> List[Any]: - """Apply a function to each element of a flattened list.""" - return list(map(func, *args)) - - -def with_flattened_tree(inner: GradientTransformation) -> GradientTransformation: - """Wraps around the inner transformation that manipulates the flattened tree structure (:class:``list``).""" - - def init_fn(params): - return inner.init(pytree.tree_leaves(params)) # type: ignore[arg-type] - - def update_fn(updates, state, *, params=None, inplace=True): - flat_updates, treedef = pytree.tree_flatten(updates) - if params is not None: - params = pytree.tree_leaves(params) - - flat_updates, state = inner.update( - flat_updates, state, params=params, inplace=inplace # type: ignore[arg-type] - ) - updates: Updates - updates = pytree.tree_unflatten(treedef, flat_updates) # type: ignore[arg-type] - - return updates, state - - return GradientTransformation(init_fn, update_fn) - - -def inc_count(updates: Updates, count: TensorTree) -> TensorTree: - """Increments int counter by one. - - Returns: - A counter incremeted by one, or max_int if the maximum precision is reached. - """ - return _inc_count(updates=updates, count=count, already_flattened=False) - - -def _inc_count( - updates: Updates, count: TensorTree, *, already_flattened: bool = False -) -> TensorTree: - def f(c, g): - return c + (c != INT64_MAX).to(torch.int64) if g is not None else c - - if already_flattened: - return map_flattened(f, count, updates) # type: ignore[return-value] - return pytree.tree_map(f, count, updates) - - -def scale(step_size: float) -> GradientTransformation: - """Scale updates by some fixed scalar ``step_size``. - - Args: - step_size: A scalar corresponding to a fixed scaling factor for updates. - - Returns: - An ``(init_fn, update_fn)`` tuple. - """ - return _scale(step_size=step_size, already_flattened=False) - - -def _scale(step_size: float, *, already_flattened: bool = False) -> GradientTransformation: - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def init_fn(params): # pylint: disable=unused-argument - return ScaleState() - - def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument - if inplace: - - def f(g): - return g.mul_(step_size) if g is not None else None - - else: - - def f(g): - return g.mul(step_size) if g is not None else None - - updates = tree_map(f, updates) - return updates, state - - return GradientTransformation(init_fn, update_fn) - - -class ScaleByScheduleState(NamedTuple): - """Maintains count for scale scheduling.""" - - count: Sequence[torch.Tensor] # type: ignore - - -def scale_by_schedule(step_size_fn: Schedule) -> GradientTransformation: - """Scale updates using a custom schedule for the ``step_size``. - - Args: - step_size_fn: - A function that takes an update count as input and proposes the ``step_size`` to - multiply the updates by. - - Returns: - An ``(init_fn, update_fn)`` tuple. - """ - return _scale_by_schedule(step_size_fn=step_size_fn, already_flattened=False) - - -def _scale_by_schedule( - step_size_fn: Schedule, *, already_flattened: bool = False -) -> GradientTransformation: - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def init_fn(params): - zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params - ) - return ScaleByScheduleState(count=zero) - - def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument - if inplace: - - def f(g, c): - step_size = step_size_fn(c) - return g.mul_(step_size) if g is not None else None - - else: - - def f(g, c): - step_size = step_size_fn(c) - return g.mul(step_size) if g is not None else None - - updates = tree_map(f, updates, state.count) - return ( - updates, - ScaleByScheduleState( - count=_inc_count(updates, state.count, already_flattened=already_flattened) # type: ignore[arg-type] - ), - ) - - return GradientTransformation(init_fn, update_fn) - - -def _update_moment(updates, moments, decay, *, order, inplace=True, already_flattened=False): - """Compute the exponential moving average of the ``order``-th moment.""" - assert order in (1, 2) - - if inplace: - - if order == 2: - - def f(g, t): - return t.mul_(decay).addcmul_(g, g, value=1 - decay) if g is not None else t - - else: - - def f(g, t): - return t.mul_(decay).add_(g, alpha=1 - decay) if g is not None else t - - else: - - if order == 2: - - def f(g, t): - return t.mul(decay).addcmul_(g, g, value=1 - decay) if g is not None else t - - else: - - def f(g, t): - return t.mul(decay).add_(g, alpha=1 - decay) if g is not None else t - - if already_flattened: - return map_flattened(f, updates, moments) - return pytree.tree_map(f, updates, moments) - - -class ScaleByAdamState(NamedTuple): - """State for the Adam algorithm.""" - - mu: Updates - nu: Updates - count: Sequence[torch.Tensor] # type: ignore - - -def _bias_correction(moment, decay, count, *, already_flattened=False): - """Perform bias correction. This becomes a no-op as count goes to infinity.""" - - def f(t, c): - return t.div(1 - decay**c) - - if already_flattened: - return map_flattened(f, moment, count) - return pytree.tree_map(f, moment, count) - - -def scale_by_adam( - b1: float = 0.9, - b2: float = 0.999, - eps: float = 1e-8, - eps_root: float = 0.0, - moment_requires_grad: bool = False, -) -> GradientTransformation: - """Rescale updates according to the Adam algorithm. - - References: - [Kingma et al, 2014](https://arxiv.org/abs/1412.6980) - - Args: - b1: (default: :const:`0.9`) - Decay rate for the exponentially weighted average of grads. - b2: (default: :const:`0.999`) - Decay rate for the exponentially weighted average of squared grads. - eps: (default: :const:`1e-8`) - Term added to the denominator to improve numerical stability. - eps_root: (default: :const:`0.0`) - Term added to the denominator inside the square-root to improve - numerical stability when back-propagating gradients through the rescaling. - moment_requires_grad: (default: :data:`False`) - if :data:`True`, states will be created with flag `requires_grad = True`. - - Returns: - An (init_fn, update_fn) tuple. - """ - return _scale_by_adam( - b1=b1, - b2=b2, - eps=eps, - eps_root=eps_root, - moment_requires_grad=moment_requires_grad, - already_flattened=False, - ) - - -def _scale_by_adam( - b1: float = 0.9, - b2: float = 0.999, - eps: float = 1e-8, - eps_root: float = 0.0, - moment_requires_grad: bool = False, - *, - already_flattened: bool = False, -) -> GradientTransformation: - # pylint: disable=unneeded-not - if not 0.0 <= eps: - raise ValueError(f'Invalid epsilon value: {eps}') - if not 0.0 <= b1 < 1.0: - raise ValueError(f'Invalid beta parameter at index 0: {b1}') - if not 0.0 <= b2 < 1.0: - raise ValueError(f'Invalid beta parameter at index 1: {b2}') - # pylint: enable=unneeded-not - - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def init_fn(params): - zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params - ) - mu = tree_map( # first moment - lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params - ) - nu = tree_map( # second moment - lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params - ) - return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] - - def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument - mu = _update_moment( - updates, state.mu, b1, order=1, inplace=inplace, already_flattened=already_flattened - ) - nu = _update_moment( - updates, state.nu, b2, order=2, inplace=inplace, already_flattened=already_flattened - ) - count_inc = _inc_count(updates, state.count, already_flattened=already_flattened) - mu_hat = _bias_correction(mu, b1, count_inc, already_flattened=already_flattened) - nu_hat = _bias_correction(nu, b2, count_inc, already_flattened=already_flattened) - - if inplace: - - def f(g, m, v): - return m.div_(v.add_(eps_root).sqrt_().add(eps)) if g is not None else None - - else: - - def f(g, m, v): - return m.div(v.add(eps_root).sqrt_().add(eps)) if g is not None else None - - updates = tree_map(f, updates, mu_hat, nu_hat) - return updates, ScaleByAdamState(mu=mu, nu=nu, count=count_inc) # type: ignore[arg-type] - - return GradientTransformation(init_fn, update_fn) - - -def scale_by_accelerated_adam( - b1: float = 0.9, - b2: float = 0.999, - eps: float = 1e-8, - eps_root: float = 0.0, - moment_requires_grad: bool = False, -) -> GradientTransformation: - """Rescale updates according to the Adam algorithm. - - This function is accelerated by using some fused accelerated operators. - - References: - [Kingma et al, 2014](https://arxiv.org/abs/1412.6980) - - Args: - b1: (default: :const:`0.9`) - Decay rate for the exponentially weighted average of grads. - b2: (default: :const:`0.999`) - Decay rate for the exponentially weighted average of squared grads. - eps: (default: :const:`1e-8`) - Term added to the denominator to improve numerical stability. - eps_root: (default: :const:`0.0`) - Term added to the denominator inside the square-root to improve - numerical stability when back-propagating gradients through the rescaling. - moment_requires_grad: (default: :data:`False`) - if :data:`True`, states will be created with flag `requires_grad = True`. - - Returns: - An (init_fn, update_fn) tuple. - """ - return _scale_by_accelerated_adam( - b1=b1, - b2=b2, - eps=eps, - eps_root=eps_root, - moment_requires_grad=moment_requires_grad, - already_flattened=False, - ) - - -def _scale_by_accelerated_adam( - b1: float = 0.9, - b2: float = 0.999, - eps: float = 1e-8, - eps_root: float = 0.0, - moment_requires_grad: bool = False, - *, - already_flattened: bool = False, -) -> GradientTransformation: - # pylint: disable=unneeded-not - if not 0.0 <= eps: - raise ValueError(f'Invalid epsilon value: {eps}') - if not 0.0 <= b1 < 1.0: - raise ValueError(f'Invalid beta parameter at index 0: {b1}') - if not 0.0 <= b2 < 1.0: - raise ValueError(f'Invalid beta parameter at index 1: {b2}') - # pylint: enable=unneeded-not - - from torchopt.accelerated_op import AdamOp # pylint: disable=import-outside-toplevel - - if already_flattened: - tree_map = map_flattened - - # pylint: disable-next=unused-argument - def update_fn(updates, state, *, params=None, inplace=True): - count_inc = _inc_count(updates, state.count, already_flattened=True) - - op = AdamOp(b1=b1, b2=b2, eps=eps, eps_root=eps_root, inplace=inplace) - out = map_flattened(op, state.mu, state.nu, updates, count_inc) - - new_mu, new_nu, new_updates = tuple(zip(*out)) # transpose - return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) # type: ignore[arg-type] - - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - # pylint: disable-next=unused-argument - def update_fn(updates, state, *, params=None, inplace=True): - count_inc = _inc_count(updates, state.count, already_flattened=False) - - treedef = pytree.tree_structure(updates) - - op = AdamOp(b1=b1, b2=b2, eps=eps, eps_root=eps_root, inplace=inplace) - out = pytree.tree_map(op, state.mu, state.nu, updates, count_inc) - - new_mu: Updates - new_nu: Updates - new_updates: Updates - new_mu, new_nu, new_updates = pytree.tree_transpose(treedef, TRIPLE_PYTREEDEF, out) # type: ignore[misc] - return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) # type: ignore[arg-type] - - def init_fn(params): - zero = tree_map( # count init - lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params - ) - mu = tree_map( # first moment - lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params - ) - nu = tree_map( # second moment - lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params - ) - return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] - - return GradientTransformation(init_fn, update_fn) - - -class TraceState(NamedTuple): - """Holds an aggregation of past updates.""" - - trace: Params - - -def trace( - momentum: float = 0.9, - dampening: float = 0.0, - nesterov: bool = False, - moment_requires_grad: bool = False, -) -> GradientTransformation: - """Compute a trace of past updates. - - Note: `trace` and `ema` have very similar but distinct updates; - `trace = decay * trace + t`, while `ema = decay * ema + (1 - decay) * t`. - Both are frequently found in the optimization literature. - - Args: - momentum: (default: :const:`0.9`) - The decay rate for the trace of past updates. - dampening: (default: :const:`0.0`) - Dampening for momentum. - nesterov: (default: :data:`False`) - Whether to use Nesterov momentum. - moment_requires_grad: (default: :data:`False`) - if :data:`True`, states will be created with flag `requires_grad = True`. - - Returns: - An (init_fn, update_fn) tuple. - """ - return _trace( - momentum=momentum, - dampening=dampening, - nesterov=nesterov, - moment_requires_grad=moment_requires_grad, - already_flattened=False, - ) - - -def _trace( - momentum: float = 0.9, - dampening: float = 0.0, - nesterov: bool = False, - moment_requires_grad: bool = False, - *, - already_flattened: bool = False, -) -> GradientTransformation: - # pylint: disable=unneeded-not - if not 0.0 <= momentum: - raise ValueError(f'Invalid momentum value: {momentum}') - if nesterov and (momentum <= 0.0 or dampening != 0.0): - raise ValueError('Nesterov momentum requires a momentum and zero dampening') - # pylint: enable=unneeded-not - - if momentum == 0.0: - return identity() - - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def init_fn(params): - return TraceState( - trace=tree_map( # type: ignore[arg-type] - lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params - ) - ) - - first_call = True - - def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument - nonlocal first_call - - if nesterov: - if inplace: - - def f1(g, t): - if first_call: - return t.add_(g) - return t.mul_(momentum).add_(g) - - def f2(g, t): - return g.add_(t, alpha=momentum) - - new_trace = tree_map(f1, updates, state.trace) - updates = tree_map(f2, updates, new_trace) - else: - - def f1(g, t): - if first_call: - return t.add(g) - return t.mul(momentum).add_(g) - - def f2(g, t): - return g.add(t, alpha=momentum) - - new_trace = tree_map(f1, updates, state.trace) - updates = tree_map(f2, updates, new_trace) - else: - if inplace: - - def f(g, t): - if first_call: - return t.add(g) - return t.mul_(momentum).add_(g, alpha=1.0 - dampening) - - def copy_(g, t): - return g.copy_(t) - - new_trace = tree_map(f, updates, state.trace) - updates = tree_map(copy_, updates, new_trace) - else: - - def f(g, t): - if first_call: - return t.add(g) - return t.mul(momentum).add_(g, alpha=1.0 - dampening) - - new_trace = tree_map(f, updates, state.trace) - updates = tree_map(torch.clone, new_trace) - - first_call = False - return updates, TraceState(trace=new_trace) # type: ignore[arg-type] - - return GradientTransformation(init_fn, update_fn) - - -class ScaleByRmsState(NamedTuple): - """State for exponential root mean-squared (RMS)-normalized updates.""" - - nu: Updates - - -def scale_by_rms( - alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 -) -> GradientTransformation: - """Rescale updates by the root of the exp. moving avg of the square. - - References: - [Hinton](www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf) - - Args: - alpha: (default: :const:`0.9`) - Decay rate for the exponentially weighted average of squared grads. - eps: (default: :const:`1e-8`) - Term added to the denominator to improve numerical stability. - initial_scale: (default: :const:`0.0`) - Initial value for second moment - - Returns: - An (init_fn, update_fn) tuple. - """ - return _scale_by_rms( - alpha=alpha, - eps=eps, - initial_scale=initial_scale, - already_flattened=False, - ) - - -def _scale_by_rms( - alpha: float = 0.9, - eps: float = 1e-8, - initial_scale: float = 0.0, - *, - already_flattened: bool = False, -) -> GradientTransformation: - # pylint: disable=unneeded-not - if not 0.0 <= alpha: - raise ValueError(f'Invalid alpha value: {alpha}') - if not 0.0 <= eps: - raise ValueError(f'Invalid epsilon value: {eps}') - # pylint: enable=unneeded-not - - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def init_fn(params): - nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment - return ScaleByRmsState(nu=nu) # type: ignore[arg-type] - - def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument - nu = _update_moment( - updates, state.nu, alpha, order=2, inplace=inplace, already_flattened=already_flattened - ) - - if inplace: - - def f(g, n): - return g.div_(n.sqrt().add_(eps)) - - else: - - def f(g, n): - return g.div(n.sqrt().add(eps)) - - updates = tree_map(f, updates, nu) - return updates, ScaleByRmsState(nu=nu) - - return GradientTransformation(init_fn, update_fn) - - -class ScaleByRStdDevState(NamedTuple): - """State for centered exponential moving average of squares of updates.""" - - mu: Updates - nu: Updates - - -def scale_by_stddev( - alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 -) -> GradientTransformation: - """Rescale updates by the root of the centered exp. moving average of squares. - - References: - [Hinton](www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf) - - Args: - alpha: (default: :const:`0.9`) - Decay rate for the exponentially weighted average of squared grads. - eps: (default: :const:`1e-8`) - Term added to the denominator to improve numerical stability. - initial_scale: (default: :const:`0.0`) - Initial value for second moment - - Returns: - An (init_fn, update_fn) tuple. - """ - return _scale_by_stddev( - alpha=alpha, - eps=eps, - initial_scale=initial_scale, - already_flattened=False, - ) - - -def _scale_by_stddev( - alpha: float = 0.9, - eps: float = 1e-8, - initial_scale: float = 0.0, - *, - already_flattened: bool = False, -) -> GradientTransformation: - # pylint: disable=unneeded-not - if not 0.0 <= alpha: - raise ValueError(f'Invalid alpha value: {alpha}') - if not 0.0 <= eps: - raise ValueError(f'Invalid epsilon value: {eps}') - # pylint: enable=unneeded-not - - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def init_fn(params): - mu = tree_map(torch.zeros_like, params) # first moment - nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment - return ScaleByRStdDevState(mu=mu, nu=nu) # type: ignore[arg-type] - - def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument - mu = _update_moment( - updates, state.mu, alpha, order=1, inplace=inplace, already_flattened=already_flattened - ) - nu = _update_moment( - updates, state.nu, alpha, order=2, inplace=inplace, already_flattened=already_flattened - ) - - if inplace: - - def f(g, m, n): - return g.div_(n.addcmul(m, m, value=-1.0).sqrt_().add(eps)) - - else: - - def f(g, m, n): - return g.div(n.addcmul(m, m, value=-1.0).sqrt_().add(eps)) - - updates = tree_map(f, updates, mu, nu) - return updates, ScaleByRStdDevState(mu=mu, nu=nu) - - return GradientTransformation(init_fn, update_fn) - - -class MaskedState(NamedTuple): - """Maintains inner transform state for masked transformations.""" - - inner_state: Any - - -class MaskedNode(NamedTuple): - """A node used to mask out unspecified parts of a tree. - - This node is ignored when mapping functions across the tree e.g. using - :func:`pytree.tree_map` since it is a container without children. It can - therefore be used to mask out parts of a tree. - """ - - -def masked( - inner: GradientTransformation, - mask: Union[Any, Callable[[Params], Any]], -) -> GradientTransformation: - """Mask updates so only some are transformed, the rest are passed through. - - For example, it is common to skip weight decay for BatchNorm scale and all - bias parameters. In many networks, these are the only parameters with only - one dimension. So, you may create a mask function to mask these out as - follows:: - mask_fn = lambda p: pytree.tree_map(lambda x: x.ndim != 1, p) - weight_decay = torchopt.masked(torchopt.add_decayed_weights(0.001), mask_fn) - You may alternatively create the mask pytree upfront:: - mask = pytree.tree_map(lambda x: x.ndim != 1, params) - weight_decay = torchopt.masked(torchopt.add_decayed_weights(0.001), mask) - For the ``inner`` transform, state will only be stored for the parameters that - have a mask value of ``True``. - - Args: - inner: Inner transformation to mask. - mask: a PyTree with same structure as (or a prefix of) the params PyTree, or - a Callable that returns such a pytree given the params/updates. The leaves - should be booleans, ``True`` for leaves/subtrees you want to apply the - transformation to, and ``False`` for those you want to skip. The mask must - be static for the gradient transformation to be jit-compilable. - - Returns: - New GradientTransformation wrapping ``inner``. - """ - return _masked( - inner=inner, - mask=mask, - already_flattened=False, - ) - - -def _masked( - inner: GradientTransformation, - mask: Union[Any, Callable[[Params], Any]], - *, - already_flattened: bool = False, -) -> GradientTransformation: - - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def tree_mask(params, mask_tree): - return tree_map(lambda p, m: p if m else MaskedNode(), params, mask_tree) - - def init_fn(params): - mask_tree = mask(params) if callable(mask) else mask - masked_params = tree_mask(params, mask_tree) - return MaskedState(inner_state=inner.init(masked_params)) - - def update_fn(updates, state, params=None, inplace=True): # pylint: disable=unused-argument - mask_tree = mask(updates) if callable(mask) else mask - masked_updates = tree_mask(updates, mask_tree) - masked_params = None if params is None else tree_mask(params, mask_tree) - - new_masked_updates, new_inner_state = inner.update( - masked_updates, state.inner_state, params=masked_params, inplace=inplace - ) - - new_updates = tree_map( - lambda new_u, old_u, m: new_u if m else old_u, new_masked_updates, updates, mask_tree - ) - return new_updates, MaskedState(inner_state=new_inner_state) - - return GradientTransformation(init_fn, update_fn) - - -AddDecayedWeightsState = EmptyState - - -def add_decayed_weights( - weight_decay: float = 0.0, - mask: Optional[Union[Any, Callable[[Params], Any]]] = None, -) -> GradientTransformation: - """Add parameter scaled by `weight_decay`. - - Args: - weight_decay: a scalar weight decay rate. - mask: a tree with same structure as (or a prefix of) the params PyTree, - or a Callable that returns such a pytree given the params/updates. - The leaves should be booleans, `True` for leaves/subtrees you want to - apply the transformation to, and `False` for those you want to skip. - - Returns: - An (init_fn, update_fn) tuple. - """ - return _add_decayed_weights( - weight_decay=weight_decay, - mask=mask, - already_flattened=False, - ) - - -def _add_decayed_weights( - weight_decay: float = 0.0, - mask: Optional[Union[Any, Callable[[Params], Any]]] = None, - *, - already_flattened: bool = False, -) -> GradientTransformation: - if not 0.0 <= weight_decay: # pylint: disable=unneeded-not - raise ValueError(f'Invalid weight_decay value: {weight_decay}') - - if weight_decay == 0.0 and mask is None: - return identity() - - if already_flattened: - tree_map = map_flattened - else: - tree_map = pytree.tree_map # type: ignore[assignment] - - def init_fn(params): # pylint: disable=unused-argument - return AddDecayedWeightsState() - - def update_fn(updates, state, params=None, inplace=True): # pylint: disable=unused-argument - assert params is not None, ( - 'Parameters are required for weight decay. ' - 'Call `update(updates, state, params=params)` instead.' - ) - - if inplace: - - def f(g, p): - if g is not None: - if g.requires_grad: - return g.add_(p, alpha=weight_decay) - return g.add_(p.data, alpha=weight_decay) - return None - - else: - - def f(g, p): - return g.add(p, alpha=weight_decay) if g is not None else None - - updates = tree_map(f, updates, params) - return updates, state - - # If mask is not `None`, apply mask to the gradient transformation. - # E.g. it is common to skip weight decay on bias units and batch stats. - if mask is not None: - return _masked( - inner=GradientTransformation(init_fn, update_fn), - mask=mask, - already_flattened=already_flattened, - ) - return GradientTransformation(init_fn, update_fn) diff --git a/torchopt/transform/__init__.py b/torchopt/transform/__init__.py new file mode 100644 index 00000000..5db2be48 --- /dev/null +++ b/torchopt/transform/__init__.py @@ -0,0 +1,52 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformations.""" + +from torchopt.transform.add_decayed_weights import add_decayed_weights +from torchopt.transform.scale import scale +from torchopt.transform.scale_by_adam import scale_by_accelerated_adam, scale_by_adam +from torchopt.transform.scale_by_rms import scale_by_rms +from torchopt.transform.scale_by_schedule import scale_by_schedule +from torchopt.transform.scale_by_stddev import scale_by_stddev +from torchopt.transform.trace import trace + + +__all__ = [ + 'trace', + 'scale', + 'scale_by_schedule', + 'add_decayed_weights', + 'scale_by_adam', + 'scale_by_accelerated_adam', + 'scale_by_rms', + 'scale_by_stddev', +] diff --git a/torchopt/transform/add_decayed_weights.py b/torchopt/transform/add_decayed_weights.py new file mode 100644 index 00000000..0554726c --- /dev/null +++ b/torchopt/transform/add_decayed_weights.py @@ -0,0 +1,230 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# https://github.com/deepmind/optax/blob/master/optax/_src/wrappers.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformations for adding weight decay to updates.""" + +from typing import Any, Callable, NamedTuple, Optional, Union + +from torchopt import pytree +from torchopt.base import EmptyState, GradientTransformation, identity +from torchopt.transform.utils import tree_map_flat +from torchopt.typing import Params + + +__all__ = ['masked', 'add_decayed_weights'] + + +class MaskedState(NamedTuple): + """Maintains inner transform state for masked transformations.""" + + inner_state: Any + + +class MaskedNode(NamedTuple): + """A node used to mask out unspecified parts of a tree. + + This node is ignored when mapping functions across the tree e.g. using :func:`pytree.tree_map` + since it is a container without children. It can therefore be used to mask out parts of a tree. + """ + + +def masked( + inner: GradientTransformation, + mask: Union[Any, Callable[[Params], Any]], +) -> GradientTransformation: + """Mask updates so only some are transformed, the rest are passed through. + + For example, it is common to skip weight decay for BatchNorm scale and all bias parameters. In + many networks, these are the only parameters with only one dimension. So, you may create a mask + function to mask these out as follows:: + mask_fn = lambda p: pytree.tree_map(lambda x: x.ndim != 1, p) + weight_decay = torchopt.masked(torchopt.add_decayed_weights(0.001), mask_fn) + You may alternatively create the mask pytree upfront:: + mask = pytree.tree_map(lambda x: x.ndim != 1, params) + weight_decay = torchopt.masked(torchopt.add_decayed_weights(0.001), mask) + For the ``inner`` transform, state will only be stored for the parameters that have a mask value + of :data:`True`. + + Args: + inner: Inner transformation to mask. + mask: A tree with same structure as (or a prefix of) the params tree, or a Callable that + returns such a tree given the params/updates. The leaves should be booleans, :data:`True` + for leaves/subtrees you want to apply the transformation to, and :data:`False` for those + you want to skip. The mask must be static for the gradient transformation to be jit-compilable. + + Returns: + A :class:`GradientTransformation` wrapping ``inner``. + """ + return _masked(inner=inner, mask=mask, already_flattened=False) + + +def _masked_flat( + inner: GradientTransformation, + mask: Union[Any, Callable[[Params], Any]], +) -> GradientTransformation: + return _masked(inner, mask, already_flattened=True) + + +def _masked( + inner: GradientTransformation, + mask: Union[Any, Callable[[Params], Any]], + *, + already_flattened: bool = False, +) -> GradientTransformation: + + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def tree_mask(params, mask_tree): + return tree_map(lambda p, m: p if m else MaskedNode(), params, mask_tree) + + def init_fn(params): + mask_tree = mask(params) if callable(mask) else mask + masked_params = tree_mask(params, mask_tree) + return MaskedState(inner_state=inner.init(masked_params)) + + def update_fn(updates, state, params=None, inplace=True): # pylint: disable=unused-argument + mask_tree = mask(updates) if callable(mask) else mask + masked_updates = tree_mask(updates, mask_tree) + masked_params = None if params is None else tree_mask(params, mask_tree) + + new_masked_updates, new_inner_state = inner.update( + masked_updates, state.inner_state, params=masked_params, inplace=inplace + ) + + new_updates = tree_map( + lambda new_u, old_u, m: new_u if m else old_u, new_masked_updates, updates, mask_tree + ) + return new_updates, MaskedState(inner_state=new_inner_state) + + return GradientTransformation(init_fn, update_fn) + + +masked.flat = _masked_flat # type: ignore[attr-defined] +masked.impl = _masked # type: ignore[attr-defined] + + +AddDecayedWeightsState = EmptyState + + +def add_decayed_weights( + weight_decay: float = 0.0, + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, +) -> GradientTransformation: + """Add parameter scaled by `weight_decay`. + + Args: + weight_decay: a scalar weight decay rate. + mask: a tree with same structure as (or a prefix of) the params tree, or a Callable that + returns such a pytree given the params/updates. The leaves should be booleans, + :data:`True` for leaves/subtrees you want to apply the transformation to, and + :data:`False` for those you want to skip. + + Returns: + An (init_fn, update_fn) tuple. + """ + return _add_decayed_weights( + weight_decay=weight_decay, + mask=mask, + already_flattened=False, + ) + + +def _add_decayed_weights_flat( + weight_decay: float = 0.0, + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, +) -> GradientTransformation: + return _add_decayed_weights( + weight_decay=weight_decay, + mask=mask, + already_flattened=True, + ) + + +def _add_decayed_weights( + weight_decay: float = 0.0, + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, + *, + already_flattened: bool = False, +) -> GradientTransformation: + if not 0.0 <= weight_decay: # pylint: disable=unneeded-not + raise ValueError(f'Invalid weight_decay value: {weight_decay}') + + if weight_decay == 0.0 and mask is None: + return identity() + + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def init_fn(params): # pylint: disable=unused-argument + return AddDecayedWeightsState() + + def update_fn(updates, state, params=None, inplace=True): # pylint: disable=unused-argument + assert params is not None, ( + 'Parameters are required for weight decay. ' + 'Call `update(updates, state, params=params)` instead.' + ) + + if inplace: + + def f(g, p): + if g is not None: + if g.requires_grad: + return g.add_(p, alpha=weight_decay) + return g.add_(p.data, alpha=weight_decay) + return None + + else: + + def f(g, p): + return g.add(p, alpha=weight_decay) if g is not None else None + + updates = tree_map(f, updates, params) + return updates, state + + # If mask is not `None`, apply mask to the gradient transformation. + # E.g. it is common to skip weight decay on bias units and batch stats. + if mask is not None: + return masked.impl( # type: ignore[attr-defined] + inner=GradientTransformation(init_fn, update_fn), + mask=mask, + already_flattened=already_flattened, + ) + return GradientTransformation(init_fn, update_fn) + + +add_decayed_weights.flat = _add_decayed_weights_flat # type: ignore[attr-defined] +add_decayed_weights.impl = _add_decayed_weights # type: ignore[attr-defined] diff --git a/torchopt/transform/scale.py b/torchopt/transform/scale.py new file mode 100644 index 00000000..0f8e494c --- /dev/null +++ b/torchopt/transform/scale.py @@ -0,0 +1,88 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformation for scaling updates by learning rate.""" + +from torchopt import pytree +from torchopt.base import EmptyState, GradientTransformation +from torchopt.transform.utils import tree_map_flat + + +__all__ = ['scale'] + + +ScaleState = EmptyState + + +def scale(step_size: float) -> GradientTransformation: + """Scale updates by some fixed scalar ``step_size``. + + Args: + step_size: A scalar corresponding to a fixed scaling factor for updates. + + Returns: + An ``(init_fn, update_fn)`` tuple. + """ + return _scale(step_size=step_size, already_flattened=False) + + +def _scale_flat(step_size: float) -> GradientTransformation: + return _scale(step_size=step_size, already_flattened=True) + + +def _scale(step_size: float, *, already_flattened: bool = False) -> GradientTransformation: + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def init_fn(params): # pylint: disable=unused-argument + return ScaleState() + + def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument + if inplace: + + def f(g): + return g.mul_(step_size) if g is not None else None + + else: + + def f(g): + return g.mul(step_size) if g is not None else None + + updates = tree_map(f, updates) + return updates, state + + return GradientTransformation(init_fn, update_fn) + + +scale.flat = _scale_flat # type: ignore[attr-defined] +scale.impl = _scale # type: ignore[attr-defined] diff --git a/torchopt/transform/scale_by_adam.py b/torchopt/transform/scale_by_adam.py new file mode 100644 index 00000000..ddd48cd2 --- /dev/null +++ b/torchopt/transform/scale_by_adam.py @@ -0,0 +1,317 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformations for scaling updates by Adam.""" + +# pylint: disable=invalid-name + +from typing import NamedTuple, Sequence + +import torch + +from torchopt import pytree +from torchopt.base import GradientTransformation +from torchopt.transform.utils import inc_count, tree_map_flat, update_moment +from torchopt.typing import Updates + + +__all__ = ['scale_by_adam', 'scale_by_accelerated_adam'] + + +TRIPLE_PYTREEDEF = pytree.tree_structure((0, 1, 2)) # type: ignore[arg-type] + + +class ScaleByAdamState(NamedTuple): + """State for the Adam algorithm.""" + + mu: Updates + nu: Updates + count: Sequence[torch.Tensor] # type: ignore + + +def _bias_correction(moment, decay, count, *, already_flattened=False): + """Perform bias correction. This becomes a no-op as count goes to infinity.""" + + def f(t, c): # pylint: disable=invalid-name + return t.div(1 - decay**c) + + if already_flattened: + return tree_map_flat(f, moment, count) + return pytree.tree_map(f, moment, count) + + +def scale_by_adam( + b1: float = 0.9, + b2: float = 0.999, + eps: float = 1e-8, + eps_root: float = 0.0, + moment_requires_grad: bool = False, +) -> GradientTransformation: + """Rescale updates according to the Adam algorithm. + + References: + [Kingma et al, 2014](https://arxiv.org/abs/1412.6980) + + Args: + b1: (default: :const:`0.9`) + Decay rate for the exponentially weighted average of grads. + b2: (default: :const:`0.999`) + Decay rate for the exponentially weighted average of squared grads. + eps: (default: :const:`1e-8`) + Term added to the denominator to improve numerical stability. + eps_root: (default: :const:`0.0`) + Term added to the denominator inside the square-root to improve + numerical stability when back-propagating gradients through the rescaling. + moment_requires_grad: (default: :data:`False`) + If :data:`True`, states will be created with flag `requires_grad = True`. + + Returns: + An (init_fn, update_fn) tuple. + """ + return _scale_by_adam( + b1=b1, + b2=b2, + eps=eps, + eps_root=eps_root, + moment_requires_grad=moment_requires_grad, + already_flattened=False, + ) + + +def _scale_by_adam_flat( + b1: float = 0.9, + b2: float = 0.999, + eps: float = 1e-8, + eps_root: float = 0.0, + moment_requires_grad: bool = False, +) -> GradientTransformation: + return _scale_by_adam( + b1=b1, + b2=b2, + eps=eps, + eps_root=eps_root, + moment_requires_grad=moment_requires_grad, + already_flattened=True, + ) + + +def _scale_by_adam( + b1: float = 0.9, + b2: float = 0.999, + eps: float = 1e-8, + eps_root: float = 0.0, + moment_requires_grad: bool = False, + *, + already_flattened: bool = False, +) -> GradientTransformation: + # pylint: disable=unneeded-not + if not 0.0 <= eps: + raise ValueError(f'Invalid epsilon value: {eps}') + if not 0.0 <= b1 < 1.0: + raise ValueError(f'Invalid beta parameter at index 0: {b1}') + if not 0.0 <= b2 < 1.0: + raise ValueError(f'Invalid beta parameter at index 1: {b2}') + # pylint: enable=unneeded-not + + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def init_fn(params): + zero = tree_map( # count init + lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params + ) + mu = tree_map( # first moment + lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params + ) + nu = tree_map( # second moment + lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params + ) + return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] + + def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument + mu = update_moment.impl( # type: ignore[attr-defined] + updates, state.mu, b1, order=1, inplace=inplace, already_flattened=already_flattened + ) + nu = update_moment.impl( # type: ignore[attr-defined] + updates, state.nu, b2, order=2, inplace=inplace, already_flattened=already_flattened + ) + # pylint: disable=line-too-long + count_inc = inc_count.impl(updates, state.count, already_flattened=already_flattened) # type: ignore[attr-defined] + mu_hat = _bias_correction(mu, b1, count_inc, already_flattened=already_flattened) + nu_hat = _bias_correction(nu, b2, count_inc, already_flattened=already_flattened) + + if inplace: + + def f(g, m, v): + return m.div_(v.add_(eps_root).sqrt_().add(eps)) if g is not None else None + + else: + + def f(g, m, v): + return m.div(v.add(eps_root).sqrt_().add(eps)) if g is not None else None + + updates = tree_map(f, updates, mu_hat, nu_hat) + return updates, ScaleByAdamState(mu=mu, nu=nu, count=count_inc) + + return GradientTransformation(init_fn, update_fn) + + +scale_by_adam.flat = _scale_by_adam_flat # type: ignore[attr-defined] +scale_by_adam.impl = _scale_by_adam # type: ignore[attr-defined] + + +def scale_by_accelerated_adam( + b1: float = 0.9, + b2: float = 0.999, + eps: float = 1e-8, + eps_root: float = 0.0, + moment_requires_grad: bool = False, +) -> GradientTransformation: + """Rescale updates according to the Adam algorithm. + + This function is accelerated by using some fused accelerated operators. + + References: + [Kingma et al, 2014](https://arxiv.org/abs/1412.6980) + + Args: + b1: (default: :const:`0.9`) + Decay rate for the exponentially weighted average of grads. + b2: (default: :const:`0.999`) + Decay rate for the exponentially weighted average of squared grads. + eps: (default: :const:`1e-8`) + Term added to the denominator to improve numerical stability. + eps_root: (default: :const:`0.0`) + Term added to the denominator inside the square-root to improve + numerical stability when back-propagating gradients through the rescaling. + moment_requires_grad: (default: :data:`False`) + If :data:`True`, states will be created with flag `requires_grad = True`. + + Returns: + An (init_fn, update_fn) tuple. + """ + return _scale_by_accelerated_adam( + b1=b1, + b2=b2, + eps=eps, + eps_root=eps_root, + moment_requires_grad=moment_requires_grad, + already_flattened=False, + ) + + +def _scale_by_accelerated_adam_flat( + b1: float = 0.9, + b2: float = 0.999, + eps: float = 1e-8, + eps_root: float = 0.0, + moment_requires_grad: bool = False, +) -> GradientTransformation: + return _scale_by_accelerated_adam( + b1=b1, + b2=b2, + eps=eps, + eps_root=eps_root, + moment_requires_grad=moment_requires_grad, + already_flattened=True, + ) + + +def _scale_by_accelerated_adam( + b1: float = 0.9, + b2: float = 0.999, + eps: float = 1e-8, + eps_root: float = 0.0, + moment_requires_grad: bool = False, + *, + already_flattened: bool = False, +) -> GradientTransformation: + # pylint: disable=unneeded-not + if not 0.0 <= eps: + raise ValueError(f'Invalid epsilon value: {eps}') + if not 0.0 <= b1 < 1.0: + raise ValueError(f'Invalid beta parameter at index 0: {b1}') + if not 0.0 <= b2 < 1.0: + raise ValueError(f'Invalid beta parameter at index 1: {b2}') + # pylint: enable=unneeded-not + + from torchopt.accelerated_op import AdamOp # pylint: disable=import-outside-toplevel + + if already_flattened: + tree_map = tree_map_flat + + # pylint: disable-next=unused-argument + def update_fn(updates, state, *, params=None, inplace=True): + count_inc = inc_count.impl(updates, state.count, already_flattened=True) # type: ignore[attr-defined] + + op = AdamOp(b1=b1, b2=b2, eps=eps, eps_root=eps_root, inplace=inplace) + out = tree_map_flat(op, state.mu, state.nu, updates, count_inc) + + new_mu, new_nu, new_updates = tuple(zip(*out)) # transpose + return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) + + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + # pylint: disable-next=unused-argument + def update_fn(updates, state, *, params=None, inplace=True): + count_inc = inc_count.impl(updates, state.count, already_flattened=False) # type: ignore[attr-defined] + + treedef = pytree.tree_structure(updates) + + op = AdamOp(b1=b1, b2=b2, eps=eps, eps_root=eps_root, inplace=inplace) + out = pytree.tree_map(op, state.mu, state.nu, updates, count_inc) + + new_mu: Updates + new_nu: Updates + new_updates: Updates + new_mu, new_nu, new_updates = pytree.tree_transpose(treedef, TRIPLE_PYTREEDEF, out) # type: ignore[misc] + return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) + + def init_fn(params): + zero = tree_map( # count init + lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params + ) + mu = tree_map( # first moment + lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params + ) + nu = tree_map( # second moment + lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params + ) + return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] + + return GradientTransformation(init_fn, update_fn) + + +scale_by_accelerated_adam.flat = _scale_by_accelerated_adam_flat # type: ignore[attr-defined] +scale_by_accelerated_adam.impl = _scale_by_accelerated_adam # type: ignore[attr-defined] diff --git a/torchopt/transform/scale_by_rms.py b/torchopt/transform/scale_by_rms.py new file mode 100644 index 00000000..926e306f --- /dev/null +++ b/torchopt/transform/scale_by_rms.py @@ -0,0 +1,136 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformations for scaling updates by exponential root mean-squared (RMS).""" + +from typing import NamedTuple + +import torch + +from torchopt import pytree +from torchopt.base import GradientTransformation +from torchopt.transform.utils import tree_map_flat, update_moment +from torchopt.typing import Updates + + +__all__ = ['scale_by_rms'] + + +class ScaleByRmsState(NamedTuple): + """State for exponential root mean-squared (RMS)-normalized updates.""" + + nu: Updates + + +def scale_by_rms( + alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 +) -> GradientTransformation: + """Rescale updates by the root of the exp. moving avg of the square. + + References: + [Hinton](www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf) + + Args: + alpha: (default: :const:`0.9`) + Decay rate for the exponentially weighted average of squared grads. + eps: (default: :const:`1e-8`) + Term added to the denominator to improve numerical stability. + initial_scale: (default: :const:`0.0`) + Initial value for second moment + + Returns: + An (init_fn, update_fn) tuple. + """ + return _scale_by_rms( + alpha=alpha, + eps=eps, + initial_scale=initial_scale, + already_flattened=False, + ) + + +def _scale_by_rms_flat( + alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 +) -> GradientTransformation: + return _scale_by_rms( + alpha=alpha, + eps=eps, + initial_scale=initial_scale, + already_flattened=True, + ) + + +def _scale_by_rms( + alpha: float = 0.9, + eps: float = 1e-8, + initial_scale: float = 0.0, + *, + already_flattened: bool = False, +) -> GradientTransformation: + # pylint: disable=unneeded-not + if not 0.0 <= alpha: + raise ValueError(f'Invalid alpha value: {alpha}') + if not 0.0 <= eps: + raise ValueError(f'Invalid epsilon value: {eps}') + # pylint: enable=unneeded-not + + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def init_fn(params): + nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment + return ScaleByRmsState(nu=nu) # type: ignore[arg-type] + + def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument + nu = update_moment.impl( # type: ignore[attr-defined] + updates, state.nu, alpha, order=2, inplace=inplace, already_flattened=already_flattened + ) + + if inplace: + + def f(g, n): # pylint: disable=invalid-name + return g.div_(n.sqrt().add_(eps)) + + else: + + def f(g, n): # pylint: disable=invalid-name + return g.div(n.sqrt().add(eps)) + + updates = tree_map(f, updates, nu) + return updates, ScaleByRmsState(nu=nu) + + return GradientTransformation(init_fn, update_fn) + + +scale_by_rms.flat = _scale_by_rms_flat # type: ignore[attr-defined] +scale_by_rms.impl = _scale_by_rms # type: ignore[attr-defined] diff --git a/torchopt/transform/scale_by_schedule.py b/torchopt/transform/scale_by_schedule.py new file mode 100644 index 00000000..71378337 --- /dev/null +++ b/torchopt/transform/scale_by_schedule.py @@ -0,0 +1,114 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformation for scaling updates by learning rate schedules.""" + +from typing import NamedTuple, Sequence + +import torch + +from torchopt import pytree +from torchopt.base import GradientTransformation +from torchopt.transform.utils import inc_count, tree_map_flat +from torchopt.typing import Schedule + + +__all__ = ['scale_by_schedule'] + + +class ScaleByScheduleState(NamedTuple): + """Maintains count for scale scheduling.""" + + count: Sequence[torch.Tensor] # type: ignore + + +def scale_by_schedule(step_size_fn: Schedule) -> GradientTransformation: + """Scale updates using a custom schedule for the ``step_size``. + + Args: + step_size_fn: + A function that takes an update count as input and proposes the ``step_size`` to + multiply the updates by. + + Returns: + An ``(init_fn, update_fn)`` tuple. + """ + return _scale_by_schedule(step_size_fn=step_size_fn, already_flattened=False) + + +def _scale_by_schedule_flat(step_size_fn: Schedule) -> GradientTransformation: + return _scale_by_schedule(step_size_fn=step_size_fn, already_flattened=True) + + +def _scale_by_schedule( + step_size_fn: Schedule, *, already_flattened: bool = False +) -> GradientTransformation: + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def init_fn(params): + zero = tree_map( # count init + lambda t: torch.zeros(1, dtype=torch.int64, device=t.device).squeeze_(), params + ) + return ScaleByScheduleState(count=zero) + + def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument + if inplace: + + def f(g, c): # pylint: disable=invalid-name + step_size = step_size_fn(c) + return g.mul_(step_size) if g is not None else None + + else: + + def f(g, c): # pylint: disable=invalid-name + step_size = step_size_fn(c) + return g.mul(step_size) if g is not None else None + + updates = tree_map(f, updates, state.count) + return ( + updates, + ScaleByScheduleState( + count=inc_count.impl( # type: ignore[attr-defined] + updates, + state.count, + already_flattened=already_flattened, + ) + ), + ) + + return GradientTransformation(init_fn, update_fn) + + +scale_by_schedule.flat = _scale_by_schedule_flat # type: ignore[attr-defined] +scale_by_schedule.impl = _scale_by_schedule # type: ignore[attr-defined] diff --git a/torchopt/transform/scale_by_stddev.py b/torchopt/transform/scale_by_stddev.py new file mode 100644 index 00000000..3689b83b --- /dev/null +++ b/torchopt/transform/scale_by_stddev.py @@ -0,0 +1,143 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformations for scaling updates by the root of the centered exponential moving average.""" + +# pylint: disable=invalid-name + +from typing import NamedTuple + +import torch + +from torchopt import pytree +from torchopt.base import GradientTransformation +from torchopt.transform.utils import tree_map_flat, update_moment +from torchopt.typing import Updates + + +__all__ = ['scale_by_stddev'] + + +class ScaleByRStdDevState(NamedTuple): + """State for centered exponential moving average of squares of updates.""" + + mu: Updates + nu: Updates + + +def scale_by_stddev( + alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 +) -> GradientTransformation: + """Rescale updates by the root of the centered exponential moving average of squares. + + References: + [Hinton](www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf) + + Args: + alpha: (default: :const:`0.9`) + Decay rate for the exponentially weighted average of squared grads. + eps: (default: :const:`1e-8`) + Term added to the denominator to improve numerical stability. + initial_scale: (default: :const:`0.0`) + Initial value for second moment + + Returns: + An (init_fn, update_fn) tuple. + """ + return _scale_by_stddev( + alpha=alpha, + eps=eps, + initial_scale=initial_scale, + already_flattened=False, + ) + + +def _scale_by_stddev_flat( + alpha: float = 0.9, eps: float = 1e-8, initial_scale: float = 0.0 +) -> GradientTransformation: + return _scale_by_stddev( + alpha=alpha, + eps=eps, + initial_scale=initial_scale, + already_flattened=True, + ) + + +def _scale_by_stddev( + alpha: float = 0.9, + eps: float = 1e-8, + initial_scale: float = 0.0, + *, + already_flattened: bool = False, +) -> GradientTransformation: + # pylint: disable=unneeded-not + if not 0.0 <= alpha: + raise ValueError(f'Invalid alpha value: {alpha}') + if not 0.0 <= eps: + raise ValueError(f'Invalid epsilon value: {eps}') + # pylint: enable=unneeded-not + + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def init_fn(params): + mu = tree_map(torch.zeros_like, params) # first moment + nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment + return ScaleByRStdDevState(mu=mu, nu=nu) # type: ignore[arg-type] + + def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument + mu = update_moment.impl( # type: ignore[attr-defined] + updates, state.mu, alpha, order=1, inplace=inplace, already_flattened=already_flattened + ) + nu = update_moment.impl( # type: ignore[attr-defined] + updates, state.nu, alpha, order=2, inplace=inplace, already_flattened=already_flattened + ) + + if inplace: + + def f(g, m, n): + return g.div_(n.addcmul(m, m, value=-1.0).sqrt_().add(eps)) + + else: + + def f(g, m, n): + return g.div(n.addcmul(m, m, value=-1.0).sqrt_().add(eps)) + + updates = tree_map(f, updates, mu, nu) + return updates, ScaleByRStdDevState(mu=mu, nu=nu) + + return GradientTransformation(init_fn, update_fn) + + +scale_by_stddev.flat = _scale_by_stddev_flat # type: ignore[attr-defined] +scale_by_stddev.impl = _scale_by_stddev # type: ignore[attr-defined] diff --git a/torchopt/transform/trace.py b/torchopt/transform/trace.py new file mode 100644 index 00000000..aecb7366 --- /dev/null +++ b/torchopt/transform/trace.py @@ -0,0 +1,194 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Preset transformations for scaling updates by Adam.""" + +# pylint: disable=invalid-name + +from typing import NamedTuple + +import torch + +from torchopt import pytree +from torchopt.base import GradientTransformation, identity +from torchopt.transform.utils import tree_map_flat +from torchopt.typing import Params + + +__all__ = ['trace'] + + +class TraceState(NamedTuple): + """Holds an aggregation of past updates.""" + + trace: Params + + +def trace( + momentum: float = 0.9, + dampening: float = 0.0, + nesterov: bool = False, + moment_requires_grad: bool = False, +) -> GradientTransformation: + """Compute a trace of past updates. + + Note: `trace` and `ema` have very similar but distinct updates; + `trace = decay * trace + t`, while `ema = decay * ema + (1 - decay) * t`. + Both are frequently found in the optimization literature. + + Args: + momentum: (default: :const:`0.9`) + The decay rate for the trace of past updates. + dampening: (default: :const:`0.0`) + Dampening for momentum. + nesterov: (default: :data:`False`) + Whether to use Nesterov momentum. + moment_requires_grad: (default: :data:`False`) + If :data:`True`, states will be created with flag `requires_grad = True`. + + Returns: + An (init_fn, update_fn) tuple. + """ + return _trace( + momentum=momentum, + dampening=dampening, + nesterov=nesterov, + moment_requires_grad=moment_requires_grad, + already_flattened=False, + ) + + +def _trace_flat( + momentum: float = 0.9, + dampening: float = 0.0, + nesterov: bool = False, + moment_requires_grad: bool = False, +) -> GradientTransformation: + return _trace( + momentum=momentum, + dampening=dampening, + nesterov=nesterov, + moment_requires_grad=moment_requires_grad, + already_flattened=True, + ) + + +def _trace( + momentum: float = 0.9, + dampening: float = 0.0, + nesterov: bool = False, + moment_requires_grad: bool = False, + *, + already_flattened: bool = False, +) -> GradientTransformation: + # pylint: disable=unneeded-not + if not 0.0 <= momentum: + raise ValueError(f'Invalid momentum value: {momentum}') + if nesterov and (momentum <= 0.0 or dampening != 0.0): + raise ValueError('Nesterov momentum requires a momentum and zero dampening') + # pylint: enable=unneeded-not + + if momentum == 0.0: + return identity() + + if already_flattened: + tree_map = tree_map_flat + else: + tree_map = pytree.tree_map # type: ignore[assignment] + + def init_fn(params): + return TraceState( + trace=tree_map( # type: ignore[arg-type] + lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params + ) + ) + + first_call = True + + def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument + nonlocal first_call + + if nesterov: + if inplace: + + def f1(g, t): + if first_call: + return t.add_(g) + return t.mul_(momentum).add_(g) + + def f2(g, t): + return g.add_(t, alpha=momentum) + + new_trace = tree_map(f1, updates, state.trace) + updates = tree_map(f2, updates, new_trace) + else: + + def f1(g, t): + if first_call: + return t.add(g) + return t.mul(momentum).add_(g) + + def f2(g, t): + return g.add(t, alpha=momentum) + + new_trace = tree_map(f1, updates, state.trace) + updates = tree_map(f2, updates, new_trace) + else: + if inplace: + + def f(g, t): + if first_call: + return t.add(g) + return t.mul_(momentum).add_(g, alpha=1.0 - dampening) + + def copy_(g, t): + return g.copy_(t) + + new_trace = tree_map(f, updates, state.trace) + updates = tree_map(copy_, updates, new_trace) + else: + + def f(g, t): + if first_call: + return t.add(g) + return t.mul(momentum).add_(g, alpha=1.0 - dampening) + + new_trace = tree_map(f, updates, state.trace) + updates = tree_map(torch.clone, new_trace) + + first_call = False + return updates, TraceState(trace=new_trace) # type: ignore[arg-type] + + return GradientTransformation(init_fn, update_fn) + + +trace.flat = _trace_flat # type: ignore[attr-defined] +trace.impl = _trace # type: ignore[attr-defined] diff --git a/torchopt/transform/utils.py b/torchopt/transform/utils.py new file mode 100644 index 00000000..ffae2d1f --- /dev/null +++ b/torchopt/transform/utils.py @@ -0,0 +1,127 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/deepmind/optax/blob/master/optax/_src/transform.py +# ============================================================================== +# Copyright 2019 DeepMind Technologies Limited. 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. +# ============================================================================== +"""Utilities for the preset transformations.""" + +from typing import Any, Callable, List + +import torch + +from torchopt import pytree +from torchopt.typing import TensorTree, Updates + + +__all__ = ['tree_map_flat', 'inc_count', 'update_moment'] + + +INT64_MAX = torch.iinfo(torch.int64).max + + +def tree_map_flat(func: Callable, *args: Any) -> List[Any]: + """Apply a function to each element of a flattened list.""" + return list(map(func, *args)) + + +def inc_count(updates: Updates, count: TensorTree) -> TensorTree: + """Increments int counter by one. + + Returns: + A counter incremented by one, or :data:`INT64_MAX` if the maximum precision is reached. + """ + return _inc_count(updates=updates, count=count, already_flattened=False) + + +def _inc_count_flat(updates: Updates, count: TensorTree) -> TensorTree: + return _inc_count(updates=updates, count=count, already_flattened=True) + + +def _inc_count( + updates: Updates, count: TensorTree, *, already_flattened: bool = False +) -> TensorTree: + def f(c, g): # pylint: disable=invalid-name + return c + (c != INT64_MAX).to(torch.int64) if g is not None else c + + if already_flattened: + return tree_map_flat(f, count, updates) # type: ignore[return-value] + return pytree.tree_map(f, count, updates) + + +inc_count.flat = _inc_count_flat # type: ignore[attr-defined] +inc_count.impl = _inc_count # type: ignore[attr-defined] + + +def update_moment(updates, moments, decay, *, order, inplace=True): + """Compute the exponential moving average of the ``order``-th moment.""" + return _update_moment( + updates, moments, decay, order=order, inplace=inplace, already_flattened=False + ) + + +def _update_moment_flat(updates, moments, decay, *order, inplace=True): + return _update_moment( + updates, moments, decay, order=order, inplace=inplace, already_flattened=True + ) + + +def _update_moment(updates, moments, decay, *, order, inplace=True, already_flattened=False): + assert order in (1, 2) + + if inplace: + + if order == 2: + + def f(g, t): + return t.mul_(decay).addcmul_(g, g, value=1 - decay) if g is not None else t + + else: + + def f(g, t): + return t.mul_(decay).add_(g, alpha=1 - decay) if g is not None else t + + else: + + if order == 2: + + def f(g, t): + return t.mul(decay).addcmul_(g, g, value=1 - decay) if g is not None else t + + else: + + def f(g, t): + return t.mul(decay).add_(g, alpha=1 - decay) if g is not None else t + + if already_flattened: + return tree_map_flat(f, updates, moments) + return pytree.tree_map(f, updates, moments) + + +update_moment.flat = _update_moment_flat # type: ignore[attr-defined] +update_moment.impl = _update_moment # type: ignore[attr-defined] diff --git a/tutorials/5_Implicit_Differentiation.ipynb b/tutorials/5_Implicit_Differentiation.ipynb index 0bc0e59e..f52aceb1 100644 --- a/tutorials/5_Implicit_Differentiation.ipynb +++ b/tutorials/5_Implicit_Differentiation.ipynb @@ -36,8 +36,7 @@ "import torch.nn as nn\n", "import torch.nn.functional as F\n", "\n", - "import torchopt\n", - "from torchopt import implicit_diff, sgd" + "import torchopt" ] }, { @@ -47,7 +46,7 @@ "source": [ "## 1. Basic API\n", "\n", - "The basic API is `torchopt.implicit_diff`, which is used as the decorator for the forward process implicit gradient procedures." + "The basic API is `torchopt.diff.implicit.custom_root`, which is used as the decorator for the forward process implicit gradient procedures." ] }, { @@ -68,7 +67,7 @@ "{\\left. \\nabla_{\\boldsymbol{\\phi}'} G \\left( \\boldsymbol{\\phi}', \\boldsymbol{\\theta} \\right) \\right|}_{\\boldsymbol{\\phi}' = \\boldsymbol{\\phi}^{\\star}} = 0\n", "$$\n", "\n", - "Thus we can define the optimality function by defining `imaml_objective` and make it first-order gradient w.r.t the inner-loop parameter as $0$. We achieve so by calling out `functorch.grad(imaml_objective, argnums=0)`. Finally, the forward function is decorated by the `@implicit_diff.custom_root` and the optimality condition we define." + "Thus we can define the optimality function by defining `imaml_objective` and make it first-order gradient w.r.t the inner-loop parameter as $0$. We achieve so by calling out `functorch.grad(imaml_objective, argnums=0)`. Finally, the forward function is decorated by the `@torchopt.diff.implicit.custom_root` decorator and the optimality condition we define." ] }, { @@ -96,13 +95,13 @@ "\n", "# Here we pass argnums=1 to the custom_root. That means we want to compute the gradient of\n", "# optimal_params w.r.t. the 1-indexed argument in inner_solver, i.e., init_params.\n", - "@implicit_diff.custom_root(functorch.grad(imaml_objective, argnums=0), argnums=1)\n", + "@torchopt.diff.implicit.custom_root(functorch.grad(imaml_objective, argnums=0), argnums=1)\n", "def inner_solver(init_params_copy, init_params, data):\n", " \"\"\"Solve ridge regression by conjugate gradient.\"\"\"\n", " # Initial functional optimizer based on TorchOpt\n", " x, y, fmodel = data\n", " params = init_params_copy\n", - " optimizer = sgd(lr=2e-2)\n", + " optimizer = torchopt.sgd(lr=2e-2)\n", " opt_state = optimizer.init(params)\n", " with torch.enable_grad():\n", " # Temporarily enable gradient computation for conducting the optimization\n", From aaec9a91be955039ac01f70959cae79c306f1a94 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 21 Oct 2022 14:26:06 +0800 Subject: [PATCH 30/69] chore(.github): update issue and PR templates and workflows --- .github/ISSUE_TEMPLATE/bug_report.md | 8 +++--- .github/ISSUE_TEMPLATE/feature_request.md | 6 ++--- .../ISSUE_TEMPLATE/questions_help_support.md | 4 +-- .github/PULL_REQUEST_TEMPLATE.md | 8 +++--- .github/workflows/build.yml | 26 +++++++++++++++---- .github/workflows/set_release.py | 18 +++++++++++++ conda-recipe.yaml | 2 +- 7 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/set_release.py diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 86dcfbcb..ab9ae0e4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,5 +1,5 @@ --- -name: Bug report +name: Bug Report about: Create a report to help us improve title: "[BUG]" labels: ["bug"] @@ -59,6 +59,6 @@ If you know or suspect the reason for this bug, paste the code lines and suggest ## Checklist -- [ ] I have checked that there is no similar issue in the repo (**required**) -- [ ] I have read the [documentation](https://torchopt.readthedocs.io/) (**required**) -- [ ] I have provided a minimal working example to reproduce the bug (**required**) +- [ ] I have checked that there is no similar issue in the repo. (**required**) +- [ ] I have read the [documentation](https://torchopt.readthedocs.io). (**required**) +- [ ] I have provided a minimal working example to reproduce the bug. (**required**) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index b61aa154..30524018 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,5 +1,5 @@ --- -name: Feature request +name: Feature Request about: Suggest an idea for this project title: "[Feature Request]" labels: ["enhancement"] @@ -10,7 +10,7 @@ assignees: Benjamin-eecs ## Motivation Please outline the motivation for the proposal. -Is your feature request related to a problem? e.g., "I'm always frustrated when [...]". +Is your feature request related to a problem? E.g., "I'm always frustrated when [...]". If this is related to another issue, please link here too. ## Solution @@ -27,4 +27,4 @@ Add any other context or screenshots about the feature request here. ## Checklist -- [ ] I have checked that there is no similar issue in the repo (**required**) +- [ ] I have checked that there is no similar issue in the repo. (**required**) diff --git a/.github/ISSUE_TEMPLATE/questions_help_support.md b/.github/ISSUE_TEMPLATE/questions_help_support.md index 072d2e52..cc183bf1 100644 --- a/.github/ISSUE_TEMPLATE/questions_help_support.md +++ b/.github/ISSUE_TEMPLATE/questions_help_support.md @@ -13,5 +13,5 @@ assignees: Benjamin-eecs ## Checklist -- [ ] I have checked that there is no similar issue in the repo (**required**) -- [ ] I have read the [documentation](https://torchopt.readthedocs.io/) (**required**) +- [ ] I have checked that there is no similar issue in the repo. (**required**) +- [ ] I have read the [documentation](https://torchopt.readthedocs.io). (**required**) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 807bd4bb..2709e055 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -31,10 +31,10 @@ What types of changes does your code introduce? Put an `x` in all the boxes that Go over all the following points, and put an `x` in all the boxes that apply. If you are unsure about any of these, don't hesitate to ask. We are here to help! -- [ ] I have read the [CONTRIBUTION](https://torchopt.readthedocs.io/en/latest/developer/contributing.html) guide (**required**) +- [ ] I have read the [CONTRIBUTION](https://torchopt.readthedocs.io/en/latest/developer/contributing.html) guide. (**required**) - [ ] My change requires a change to the documentation. -- [ ] I have updated the tests accordingly (*required for a bug fix or a new feature*). +- [ ] I have updated the tests accordingly. (*required for a bug fix or a new feature*) - [ ] I have updated the documentation accordingly. -- [ ] I have reformatted the code using `make format` (**required**) -- [ ] I have checked the code using `make lint` (**required**) +- [ ] I have reformatted the code using `make format`. (**required**) +- [ ] I have checked the code using `make lint`. (**required**) - [ ] I have ensured `make test` pass. (**required**) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 78d89f4b..00ccf2e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,9 +59,11 @@ jobs: update-environment: true - name: Set __release__ - if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' + if: | + startsWith(github.ref, 'refs/tags/') || + (github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'build-and-publish') run: | - sed -i -E 's/^__release__\s*=.*$/__release__ = True/' torchopt/version.py + python .github/workflows/set_release.py - name: Print version run: python setup.py --version @@ -99,15 +101,17 @@ jobs: update-environment: true - name: Set __release__ - if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' + if: | + startsWith(github.ref, 'refs/tags/') || + (github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'build-and-publish') run: | - sed -i -E 's/^__release__\s*=.*$/__release__ = True/' torchopt/version.py + python .github/workflows/set_release.py - name: Print version run: python setup.py --version - name: Build wheels - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 with: package-dir: . output-dir: wheelhouse @@ -141,6 +145,14 @@ jobs: python-version: "3.7 - 3.10" # sync with requires-python in pyproject.toml update-environment: true + - name: Set __release__ + if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' + run: | + python .github/workflows/set_release.py + + - name: Print version + run: python setup.py --version + - name: Check consistency between the package version and release tag if: startsWith(github.ref, 'refs/tags/') run: | @@ -167,6 +179,10 @@ jobs: name: wheels path: dist + - name: List distributions + run: + ls -lh dist/* + - name: Publish to TestPyPI if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' uses: pypa/gh-action-pypi-publish@v1.5.0 diff --git a/.github/workflows/set_release.py b/.github/workflows/set_release.py new file mode 100644 index 00000000..aa91df84 --- /dev/null +++ b/.github/workflows/set_release.py @@ -0,0 +1,18 @@ +import pathlib +import re + + +ROOT = pathlib.Path(__file__).absolute().parent.parent.parent + +VERSION_FILE = ROOT / 'torchopt' / 'version.py' + +VERSION_CONTENT = VERSION_FILE.read_text() + +VERSION_FILE.write_text( + data=re.sub( + r'__release__\s*=.*', + '__release__ = True', + string=VERSION_CONTENT, + ), + encoding='UTF-8', +) diff --git a/conda-recipe.yaml b/conda-recipe.yaml index 4b6989b2..374bae9d 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -79,7 +79,7 @@ dependencies: - flake8-bugbear - doc8 < 1.0.0a0 - pydocstyle - - clang-format + - clang-format >= 14 - clang-tools # clang-tidy - cpplint - pre-commit From 73983d593c208567257f31b5403f901a7500d3c4 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Wed, 26 Oct 2022 19:21:13 +0800 Subject: [PATCH 31/69] deps: bump optree to 0.3.0 (#103) --- .github/workflows/build.yml | 83 ++++++++++++++++++++--- .github/workflows/set_cibw_build.py | 10 +++ .github/workflows/tests.yml | 4 +- Makefile | 12 +++- docs/source/developer/contributing.rst | 2 +- pyproject.toml | 2 +- requirements.txt | 2 +- tests/helpers.py | 27 +++++++- tests/test_alias.py | 12 ++-- tests/test_schedule.py | 2 +- torchopt/alias/utils.py | 16 ++--- torchopt/base.py | 2 +- torchopt/clip.py | 4 +- torchopt/combine.py | 15 ++-- torchopt/diff/implicit/decorator.py | 18 ++--- torchopt/diff/zero_order.py | 30 ++++---- torchopt/distributed/api.py | 4 +- torchopt/hook.py | 2 +- torchopt/linalg/cg.py | 6 +- torchopt/optim/base.py | 14 ++-- torchopt/optim/func/base.py | 6 +- torchopt/optim/meta/base.py | 32 +++------ torchopt/pytree.py | 4 +- torchopt/transform/add_decayed_weights.py | 10 ++- torchopt/transform/scale.py | 4 +- torchopt/transform/scale_by_adam.py | 18 ++--- torchopt/transform/scale_by_rms.py | 2 +- torchopt/transform/scale_by_schedule.py | 4 +- torchopt/transform/scale_by_stddev.py | 2 +- torchopt/transform/trace.py | 4 +- torchopt/transform/utils.py | 15 ++-- torchopt/typing.py | 6 +- 32 files changed, 232 insertions(+), 142 deletions(-) create mode 100644 .github/workflows/set_cibw_build.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 00ccf2e9..1c624654 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,11 +81,16 @@ jobs: path: dist/*.tar.gz if-no-files-found: error - build-wheels: + build-wheels-py37: + name: Build wheels for Python ${{ matrix.python-version }} runs-on: ubuntu-latest needs: [build-sdist] if: github.repository == 'metaopt/torchopt' && (github.event_name != 'push' || startsWith(github.ref, 'refs/tags/')) - timeout-minutes: 90 + strategy: + matrix: + python-version: ["3.7"] # sync with requires-python in pyproject.toml + fail-fast: false + timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v3 @@ -94,24 +99,77 @@ jobs: fetch-depth: 0 - name: Set up Python - id: py uses: actions/setup-python@v4 with: - python-version: "3.7 - 3.10" # sync with requires-python in pyproject.toml + python-version: ${{ matrix.python-version }} update-environment: true - name: Set __release__ if: | startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'build-and-publish') - run: | - python .github/workflows/set_release.py + run: python .github/workflows/set_release.py + + - name: Print version + run: python setup.py --version + + - name: Set CIBW_BUILD + run: python .github/workflows/set_cibw_build.py + + - name: Build wheels + uses: pypa/cibuildwheel@v2.11.1 + env: + CIBW_BUILD: ${{ env.CIBW_BUILD }} + with: + package-dir: . + output-dir: wheelhouse + config-file: "{package}/pyproject.toml" + + - uses: actions/upload-artifact@v3 + with: + name: wheels-py37 + path: wheelhouse/*.whl + if-no-files-found: error + + build-wheels: + name: Build wheels for Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + needs: [build-sdist, build-wheels-py37] + if: github.repository == 'metaopt/torchopt' && (github.event_name != 'push' || startsWith(github.ref, 'refs/tags/')) + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10"] # sync with requires-python in pyproject.toml + fail-fast: false + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + update-environment: true + + - name: Set __release__ + if: | + startsWith(github.ref, 'refs/tags/') || + (github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'build-and-publish') + run: python .github/workflows/set_release.py - name: Print version run: python setup.py --version + - name: Set CIBW_BUILD + run: python .github/workflows/set_cibw_build.py + - name: Build wheels uses: pypa/cibuildwheel@v2.11.1 + env: + CIBW_BUILD: ${{ env.CIBW_BUILD }} with: package-dir: . output-dir: wheelhouse @@ -125,7 +183,7 @@ jobs: publish: runs-on: ubuntu-latest - needs: [build-sdist, build-wheels] + needs: [build-sdist, build-wheels-py37, build-wheels] if: | github.repository == 'metaopt/torchopt' && github.event_name != 'pull_request' && (github.event_name != 'workflow_dispatch' || github.event.inputs.task == 'build-and-publish') && @@ -171,6 +229,14 @@ jobs: name: sdist path: dist + - name: Download built wheels + uses: actions/download-artifact@v3 + with: + # unpacks default artifact into dist/ + # if `name: artifact` is omitted, the action will create extra parent dir + name: wheels-py37 + path: dist + - name: Download built wheels uses: actions/download-artifact@v3 with: @@ -180,8 +246,7 @@ jobs: path: dist - name: List distributions - run: - ls -lh dist/* + run: ls -lh dist/* - name: Publish to TestPyPI if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' diff --git a/.github/workflows/set_cibw_build.py b/.github/workflows/set_cibw_build.py new file mode 100644 index 00000000..7753fd0b --- /dev/null +++ b/.github/workflows/set_cibw_build.py @@ -0,0 +1,10 @@ +import os +import sys + + +# pylint: disable-next=consider-using-f-string +CIBW_BUILD = 'CIBW_BUILD=*cp%d%d-*manylinux*' % sys.version_info[:2] + +print(CIBW_BUILD) +with open(os.getenv('GITHUB_ENV'), mode='at', encoding='UTF-8') as file: + print(CIBW_BUILD, file=file) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7aafa905..ac64044a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -81,9 +81,9 @@ jobs: make pytest - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 with: - token: ${{ secrets.CODECOV }} + token: ${{ secrets.CODECOV_TOKEN }} file: ./tests/coverage.xml flags: unittests name: codecov-umbrella diff --git a/Makefile b/Makefile index f4e5f7ea..1342e8e0 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ CXX_FILES = $(shell find $(SOURCE_FOLDERS) -type f -name "*.h" -o -name "*. COMMIT_HASH = $(shell git log -1 --format=%h) PATH := $(HOME)/go/bin:$(PATH) PYTHON ?= $(shell command -v python3 || command -v python) +CLANG_FORMAT ?= $(shell command -v clang-format-14 || command -v clang-format) .PHONY: default default: install @@ -24,6 +25,9 @@ install-editable: install-e: install-editable # alias +uninstall: + $(PYTHON) -m pip uninstall -y $(PROJECT_NAME) + build: $(PYTHON) -m pip install --upgrade pip $(PYTHON) -m pip install --upgrade setuptools wheel build @@ -79,7 +83,9 @@ cpplint-install: $(call check_pip_install,cpplint) clang-format-install: - command -v clang-format || sudo apt-get install -y clang-format + command -v clang-format-14 || command -v clang-format || \ + sudo apt-get install -y clang-format-14 || \ + sudo apt-get install -y clang-format clang-tidy-install: command -v clang-tidy || sudo apt-get install -y clang-tidy @@ -125,7 +131,7 @@ cpplint: cpplint-install $(PYTHON) -m cpplint $(CXX_FILES) clang-format: clang-format-install - clang-format --style=file -i $(CXX_FILES) -n --Werror + $(CLANG_FORMAT) --style=file -i $(CXX_FILES) -n --Werror # Documentation @@ -153,7 +159,7 @@ lint: flake8 py-format mypy pylint clang-format cpplint docstyle spelling format: py-format-install clang-format-install addlicense-install $(PYTHON) -m isort --project $(PROJECT_NAME) $(PYTHON_FILES) $(PYTHON) -m black $(PYTHON_FILES) tutorials - clang-format -style=file -i $(CXX_FILES) + $(CLANG_FORMAT) -style=file -i $(CXX_FILES) addlicense -c $(COPYRIGHT) -l apache -y 2022 $(SOURCE_FOLDERS) clean-py: diff --git a/docs/source/developer/contributing.rst b/docs/source/developer/contributing.rst index 93d0cc50..13f7c30b 100644 --- a/docs/source/developer/contributing.rst +++ b/docs/source/developer/contributing.rst @@ -43,7 +43,7 @@ in the main directory. This installation is removable by: .. code-block:: bash - pip3 uninstall torchopt + make uninstall Lint Check diff --git a/pyproject.toml b/pyproject.toml index f5eaaf82..5fb08617 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ classifiers = [ dependencies = [ "torch >= 1.12", # see also build-system.requires and project.requires-python "functorch >= 0.2", - "optree >= 0.2.0", + "optree >= 0.3.0", "numpy", "graphviz", "typing-extensions", diff --git a/requirements.txt b/requirements.txt index a1d24b21..a7aac2fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Sync with project.dependencies torch >= 1.12 functorch >= 0.2 -optree >= 0.2.0 +optree >= 0.3.0 numpy graphviz typing-extensions diff --git a/tests/helpers.py b/tests/helpers.py index af5587ed..a84d78bc 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -54,6 +54,8 @@ def parametrize(**argvalues) -> pytest.mark.parametrize: argvalues = list(itertools.product(*tuple(map(argvalues.get, arguments)))) first_product = argvalues[0] argvalues.extend((dtype,) + first_product[1:] for dtype in dtypes[1:]) + else: + argvalues = list(itertools.product(*tuple(map(argvalues.get, arguments)))) ids = tuple( '-'.join(f'{arg}({val})' for arg, val in zip(arguments, values)) for values in argvalues @@ -77,6 +79,25 @@ def seed_everything(seed: int) -> None: pass +class MyLinear(nn.Module): + def __init__( + self, in_features: int, out_features: int, bias: bool = True, device=None, dtype=None + ) -> None: + super().__init__() + self.linear = nn.Linear( + in_features=in_features, + out_features=out_features, + bias=bias, + device=device, + dtype=dtype, + ) + self.unused_module = nn.Linear(1, 1, bias=False) + self.unused_parameter = nn.Parameter(torch.zeros(1, 1), requires_grad=True) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + return self.linear(x) + + @torch.no_grad() def get_models( device: Optional[Union[str, torch.device]] = None, dtype: torch.dtype = torch.float32 @@ -84,7 +105,7 @@ def get_models( seed_everything(seed=42) model_base = nn.Sequential( - nn.Linear( + MyLinear( in_features=MODEL_NUM_INPUTS, out_features=MODEL_HIDDEN_SIZE, bias=True, @@ -178,8 +199,8 @@ def assert_all_close( from torch.testing._comparison import get_tolerances rtol, atol = get_tolerances(actual, expected, rtol=rtol, atol=atol) - rtol *= 4 * NUM_UPDATES - atol *= 4 * NUM_UPDATES + rtol *= 5 * NUM_UPDATES + atol *= 5 * NUM_UPDATES torch.testing.assert_close( actual, diff --git a/tests/test_alias.py b/tests/test_alias.py index 6f37e939..1da08b35 100644 --- a/tests/test_alias.py +++ b/tests/test_alias.py @@ -76,7 +76,7 @@ def test_sgd( loss = F.cross_entropy(pred, ys) loss_ref = F.cross_entropy(pred_ref, ys) - grads = torch.autograd.grad(loss, params) + grads = torch.autograd.grad(loss, params, allow_unused=True) updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) params = torchopt.apply_updates(params, updates, inplace=inplace) @@ -134,7 +134,7 @@ def test_adam( loss = F.cross_entropy(pred, ys) loss_ref = F.cross_entropy(pred_ref, ys) - grads = torch.autograd.grad(loss, params) + grads = torch.autograd.grad(loss, params, allow_unused=True) updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) params = torchopt.apply_updates(params, updates, inplace=inplace) @@ -192,7 +192,7 @@ def test_adamw( loss = F.cross_entropy(pred, ys) loss_ref = F.cross_entropy(pred_ref, ys) - grads = torch.autograd.grad(loss, params) + grads = torch.autograd.grad(loss, params, allow_unused=True) updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) params = torchopt.apply_updates(params, updates, inplace=inplace) @@ -251,7 +251,7 @@ def test_adam_accelerated_cpu( loss = F.cross_entropy(pred, ys) loss_ref = F.cross_entropy(pred_ref, ys) - grads = torch.autograd.grad(loss, params) + grads = torch.autograd.grad(loss, params, allow_unused=True) updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) params = torchopt.apply_updates(params, updates, inplace=inplace) @@ -313,7 +313,7 @@ def test_adam_accelerated_cuda( loss = F.cross_entropy(pred, ys) loss_ref = F.cross_entropy(pred_ref, ys) - grads = torch.autograd.grad(loss, params) + grads = torch.autograd.grad(loss, params, allow_unused=True) updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) params = torchopt.apply_updates(params, updates, inplace=inplace) @@ -374,7 +374,7 @@ def test_rmsprop( loss = F.cross_entropy(pred, ys) loss_ref = F.cross_entropy(pred_ref, ys) - grads = torch.autograd.grad(loss, params) + grads = torch.autograd.grad(loss, params, allow_unused=True) updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) params = torchopt.apply_updates(params, updates, inplace=inplace) diff --git a/tests/test_schedule.py b/tests/test_schedule.py index a048c57f..67e3429a 100644 --- a/tests/test_schedule.py +++ b/tests/test_schedule.py @@ -92,7 +92,7 @@ def test_lr_linear_schedule( loss = F.cross_entropy(pred, ys) loss_ref = F.cross_entropy(pred_ref, ys) - grads = torch.autograd.grad(loss, params) + grads = torch.autograd.grad(loss, params, allow_unused=True) updates, optim_state = optim.update(grads, optim_state, params=params, inplace=inplace) params = torchopt.apply_updates(params, updates, inplace=inplace) diff --git a/torchopt/alias/utils.py b/torchopt/alias/utils.py index 9a037224..3ba3b6dc 100644 --- a/torchopt/alias/utils.py +++ b/torchopt/alias/utils.py @@ -44,16 +44,14 @@ def update_fn(updates, state, *, params=None, inplace=True): if inplace: def f(g, p): - if g is not None: - if g.requires_grad: - return g.add_(p, alpha=weight_decay) - return g.add_(p.data, alpha=weight_decay) - return None + if g.requires_grad: + return g.add_(p, alpha=weight_decay) + return g.add_(p.data, alpha=weight_decay) else: def f(g, p): - return g.add(p, alpha=weight_decay) if g is not None else None + return g.add(p, alpha=weight_decay) updates = tree_map_flat(f, updates, params) return updates, state @@ -66,12 +64,12 @@ def update_fn(updates, state, *, params=None, inplace=True): if inplace: def f(g): - return g.neg_() if g is not None else None + return g.neg_() else: def f(g): - return g.neg() if g is not None else None + return g.neg() updates = tree_map_flat(f, updates) return updates, state @@ -96,7 +94,7 @@ def f(g, p): else: def f(g, p): - return g.neg().add_(p, alpha=weight_decay) if g is not None else None + return g.neg().add_(p, alpha=weight_decay) updates = tree_map_flat(f, updates, params) return updates, state diff --git a/torchopt/base.py b/torchopt/base.py index 64104167..db80ce12 100644 --- a/torchopt/base.py +++ b/torchopt/base.py @@ -224,7 +224,7 @@ def __new__(cls): @staticmethod def init_fn(params: 'Params') -> 'OptState': # pylint: disable=unused-argument """Returns empty state.""" - return EmptyState() # type: ignore[return-value] + return EmptyState() @staticmethod def update_fn( diff --git a/torchopt/clip.py b/torchopt/clip.py index 02fe9003..f41b40af 100644 --- a/torchopt/clip.py +++ b/torchopt/clip.py @@ -75,12 +75,12 @@ def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable= if inplace: def f(g): - return g.mul_(clip_coef_clamped) if g is not None else None + return g.mul_(clip_coef_clamped) else: def f(g): - return g.mul(clip_coef_clamped) if g is not None else None + return g.mul(clip_coef_clamped) new_updates = pytree.tree_map(f, updates) return new_updates, state diff --git a/torchopt/combine.py b/torchopt/combine.py index c7923bb6..26f66214 100644 --- a/torchopt/combine.py +++ b/torchopt/combine.py @@ -78,19 +78,18 @@ def chain_flat(*transformations: GradientTransformation) -> GradientTransformati inner = chain(*transformations) def init_fn(params): - return inner.init(pytree.tree_leaves(params)) # type: ignore[arg-type] + return inner.init(pytree.tree_leaves(params, none_is_leaf=True)) def update_fn(updates, state, *, params=None, inplace=True): - flat_updates, treedef = pytree.tree_flatten(updates) + flat_updates, treespec = pytree.tree_flatten(updates, none_is_leaf=True) if params is not None: - params = pytree.tree_leaves(params) + flat_params = pytree.tree_leaves(params, none_is_leaf=True) + else: + flat_params = None - flat_updates, state = inner.update( - flat_updates, state, params=params, inplace=inplace # type: ignore[arg-type] - ) + flat_updates, state = inner.update(flat_updates, state, params=flat_params, inplace=inplace) updates: Updates - updates = pytree.tree_unflatten(treedef, flat_updates) # type: ignore[arg-type] - + updates = pytree.tree_unflatten(treespec, flat_updates) return updates, state return GradientTransformation(init_fn, update_fn) diff --git a/torchopt/diff/implicit/decorator.py b/torchopt/diff/implicit/decorator.py index 7fdf58a8..3e1ebcad 100644 --- a/torchopt/diff/implicit/decorator.py +++ b/torchopt/diff/implicit/decorator.py @@ -192,9 +192,9 @@ def map_args_back(out_args): def _split_tensor_and_others( mixed_tuple: Tuple[Any, ...], -) -> Tuple[pytree.PyTreeDef, Tuple[bool, ...], Tuple[torch.Tensor, ...], Tuple[Any, ...]]: +) -> Tuple[pytree.PyTreeSpec, Tuple[bool, ...], Tuple[torch.Tensor, ...], Tuple[Any, ...]]: flattened: List[Any] - flattened, treedef = pytree.tree_flatten(mixed_tuple) # type: ignore[arg-type] + flattened, treespec = pytree.tree_flatten(mixed_tuple, none_is_leaf=True) # type: ignore[arg-type] tensors: List[torch.Tensor] = [] non_tensors: List[Any] = [] is_tensor_mask: List[bool] = [] @@ -205,11 +205,11 @@ def _split_tensor_and_others( tensors.append(item.data) else: non_tensors.append(item) - return treedef, tuple(is_tensor_mask), tuple(tensors), tuple(non_tensors) + return treespec, tuple(is_tensor_mask), tuple(tensors), tuple(non_tensors) def _merge_tensor_and_others( - treedef: pytree.PyTreeDef, + treespec: pytree.PyTreeSpec, is_tensor_mask: Tuple[bool, ...], tensors: Tuple[torch.Tensor, ...], non_tensors: Tuple[Any, ...], @@ -224,7 +224,7 @@ def _merge_tensor_and_others( else: results.append(non_tensors[non_tensor_counter]) non_tensor_counter += 1 - return pytree.tree_unflatten(treedef, results) + return pytree.tree_unflatten(treespec, results) # pylint: disable-next=too-many-arguments,too-many-statements @@ -262,12 +262,12 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ args, kwargs = _extract_kwargs(kwarg_keys, args) res = solver_fn(*args, **kwargs) ( - args_treedef, + args_treespec, args_is_tensor_mask, args_tensors, args_non_tensors, ) = _split_tensor_and_others(args) - ctx.args_treedef = args_treedef + ctx.args_treespec = args_treespec ctx.args_is_tensor_mask = args_is_tensor_mask ctx.args_non_tensors = args_non_tensors if has_aux: @@ -298,11 +298,11 @@ def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals saved_tensors[: len(grad_outputs)], saved_tensors[len(grad_outputs) :], ) - args_treedef = ctx.args_treedef + args_treespec = ctx.args_treespec args_is_tensor_mask = ctx.args_is_tensor_mask args_non_tensors = ctx.args_non_tensors args = _merge_tensor_and_others( - args_treedef, args_is_tensor_mask, args_tensors, args_non_tensors + args_treespec, args_is_tensor_mask, args_tensors, args_non_tensors ) args, kwargs = _extract_kwargs(kwarg_keys, args) diff --git a/torchopt/diff/zero_order.py b/torchopt/diff/zero_order.py index a8d8b0ee..dc9559aa 100644 --- a/torchopt/diff/zero_order.py +++ b/torchopt/diff/zero_order.py @@ -53,7 +53,7 @@ def _zero_order_naive( def apply(*args: Any) -> torch.Tensor: diff_params = [args[argnum] for argnum in argnums] flat_diff_params: List[Any] - flat_diff_params, diff_params_treedef = pytree.tree_flatten(diff_params) # type: ignore[arg-type] + flat_diff_params, diff_params_treespec = pytree.tree_flatten(diff_params) # type: ignore[arg-type] class ZeroOrder(Function): # pylint: disable=missing-class-docstring,abstract-method @staticmethod @@ -61,8 +61,8 @@ def forward(ctx, *args, **kwargs): flat_diff_params = args[:-1] origin_args = list(args[-1][0]) flat_args: List[Any] - flat_args, args_treedef = pytree.tree_flatten(origin_args) # type: ignore[arg-type] - ctx.args_treedef = args_treedef + flat_args, args_treespec = pytree.tree_flatten(origin_args, none_is_leaf=True) # type: ignore[arg-type] + ctx.args_treespec = args_treespec is_tensor_mask = [] tensors = [] @@ -101,7 +101,7 @@ def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals flat_args.append(non_tensors[non_tensors_counter]) non_tensors_counter += 1 - args: List[Any] = pytree.tree_unflatten(ctx.args_treedef, flat_args) # type: ignore[assignment] + args: List[Any] = pytree.tree_unflatten(ctx.args_treespec, flat_args) # type: ignore[assignment] def add_perturbation(tensor, noise): return tensor.add(noise, alpha=sigma) @@ -111,7 +111,7 @@ def add_perturbation(tensor, noise): add_perturbation(t, n) for t, n in zip(flat_diff_params, noise) ] noisy_params: List[Any] = pytree.tree_unflatten( # type: ignore[assignment] - diff_params_treedef, flat_noisy_params + diff_params_treespec, flat_noisy_params ) for argnum, noisy_param in zip(argnums, noisy_params): @@ -139,7 +139,7 @@ def _zero_order_forward( def apply(*args: Any) -> torch.Tensor: diff_params = [args[argnum] for argnum in argnums] flat_diff_params: List[Any] - flat_diff_params, diff_params_treedef = pytree.tree_flatten(diff_params) # type: ignore[arg-type] + flat_diff_params, diff_params_treespec = pytree.tree_flatten(diff_params) # type: ignore[arg-type] class ZeroOrder(Function): # pylint: disable=missing-class-docstring,abstract-method @staticmethod @@ -149,8 +149,8 @@ def forward( flat_diff_params = args[:-1] origin_args = list(args[-1][0]) flat_args: List[Any] - flat_args, args_treedef = pytree.tree_flatten(origin_args) # type: ignore[arg-type] - ctx.args_treedef = args_treedef + flat_args, args_treespec = pytree.tree_flatten(origin_args, none_is_leaf=True) # type: ignore[arg-type] + ctx.args_treespec = args_treespec is_tensor_mask = [] tensors = [] @@ -191,7 +191,7 @@ def backward(ctx: Any, *grad_outputs: Any) -> Any: # pylint: disable=too-many-l flat_args.append(non_tensors[non_tensors_counter]) non_tensors_counter += 1 - args: List[Any] = pytree.tree_unflatten(ctx.args_treedef, flat_args) # type: ignore[assignment] + args: List[Any] = pytree.tree_unflatten(ctx.args_treespec, flat_args) # type: ignore[assignment] def add_perturbation(tensor, noise): return tensor.add(noise, alpha=sigma) @@ -201,7 +201,7 @@ def add_perturbation(tensor, noise): add_perturbation(t, n) for t, n in zip(flat_diff_params, noise) ] noisy_params: List[Any] = pytree.tree_unflatten( # type: ignore[assignment] - diff_params_treedef, flat_noisy_params + diff_params_treespec, flat_noisy_params ) for argnum, noisy_param in zip(argnums, noisy_params): @@ -230,7 +230,7 @@ def _zero_order_antithetic( def apply(*args: Any) -> torch.Tensor: diff_params = [args[argnum] for argnum in argnums] flat_diff_params: List[Any] - flat_diff_params, diff_params_treedef = pytree.tree_flatten(diff_params) # type: ignore[arg-type] + flat_diff_params, diff_params_treespec = pytree.tree_flatten(diff_params) # type: ignore[arg-type] class ZeroOrder(Function): # pylint: disable=missing-class-docstring,abstract-method @staticmethod @@ -238,8 +238,8 @@ def forward(ctx, *args, **kwargs): flat_diff_params = args[:-1] origin_args = list(args[-1][0]) flat_args: List[Any] - flat_args, args_treedef = pytree.tree_flatten(origin_args) # type: ignore[arg-type] - ctx.args_treedef = args_treedef + flat_args, args_treespec = pytree.tree_flatten(origin_args, none_is_leaf=True) # type: ignore[arg-type] + ctx.args_treespec = args_treespec is_tensor_mask = [] tensors = [] @@ -278,7 +278,7 @@ def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals flat_args.append(non_tensors[non_tensors_counter]) non_tensors_counter += 1 - args: List[Any] = pytree.tree_unflatten(ctx.args_treedef, flat_args) # type: ignore[assignment] + args: List[Any] = pytree.tree_unflatten(ctx.args_treespec, flat_args) # type: ignore[assignment] noise = [distribution.sample(sample_shape=p.shape) for p in flat_diff_params] @@ -288,7 +288,7 @@ def get_loss(add_perturbation_fn) -> torch.Tensor: for t, n in zip(flat_diff_params, noise) ] noisy_params: List[Any] = pytree.tree_unflatten( # type: ignore[assignment] - diff_params_treedef, flat_noisy_params + diff_params_treespec, flat_noisy_params ) for argnum, noisy_param in zip(argnums, noisy_params): diff --git a/torchopt/distributed/api.py b/torchopt/distributed/api.py index b782b24d..446ff8a3 100644 --- a/torchopt/distributed/api.py +++ b/torchopt/distributed/api.py @@ -118,7 +118,7 @@ def __call__( args_tree = (args, kwargs) flat_args: List[Any] - flat_args, treedef = pytree.tree_flatten(args_tree) # type: ignore[arg-type] + flat_args, treespec = pytree.tree_flatten(args_tree) # type: ignore[arg-type] batch_size = None for arg in flat_args: @@ -179,7 +179,7 @@ def __call__( flat_args_replicas[i].append(arg) args_replicas: List[Tuple[Args, KwArgs]] = [ - pytree.tree_unflatten(treedef, args_replica) # type: ignore[misc] + pytree.tree_unflatten(treespec, args_replica) # type: ignore[misc] for args_replica in flat_args_replicas ] diff --git a/torchopt/hook.py b/torchopt/hook.py index 76e1d73d..7dd9a66a 100644 --- a/torchopt/hook.py +++ b/torchopt/hook.py @@ -42,7 +42,7 @@ def init_fn(params): # pylint: disable=unused-argument def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument def f(g): - return g.register_hook(hook) if g is not None else None + return g.register_hook(hook) pytree.tree_map(f, updates) return updates, state diff --git a/torchopt/linalg/cg.py b/torchopt/linalg/cg.py index f5fb93dc..28307666 100644 --- a/torchopt/linalg/cg.py +++ b/torchopt/linalg/cg.py @@ -57,8 +57,8 @@ def _vdot_real_kernel(x: torch.Tensor, y: torch.Tensor) -> float: def tree_vdot_real(tree_x: TensorTree, tree_y: TensorTree) -> float: """Computes dot(tree_x.conj(), tree_y).real.sum().""" - leaves_x, treedef = pytree.tree_flatten(tree_x) - leaves_y = treedef.flatten_up_to(tree_y) + leaves_x, treespec = pytree.tree_flatten(tree_x) + leaves_y = treespec.flatten_up_to(tree_y) return sum(map(_vdot_real_kernel, leaves_x, leaves_y)) # type: ignore[arg-type] @@ -76,7 +76,7 @@ def _normalize_matvec( assert isinstance(f, torch.Tensor) if f.ndim != 2 or f.shape[0] != f.shape[1]: raise ValueError(f'linear operator must be a square matrix, but has shape: {f.shape}') - return partial(torch.matmul, f) # type: ignore[return-value] + return partial(torch.matmul, f) # pylint: disable-next=too-many-locals diff --git a/torchopt/optim/base.py b/torchopt/optim/base.py index e85438e4..0f666cc1 100644 --- a/torchopt/optim/base.py +++ b/torchopt/optim/base.py @@ -50,12 +50,12 @@ def __init__(self, params: Iterable[torch.Tensor], impl: GradientTransformation) self.impl: GradientTransformation = impl self.param_groups: List[Tuple[torch.Tensor]] = [] - self.param_treedefs: List[pytree.PyTreeDef] = [] + self.param_treespecs: List[pytree.PyTreeSpec] = [] self.state_groups: List[OptState] = [] if not isinstance(params, (list, tuple)): params = tuple(params) - self.add_param_group(params) # type: ignore[arg-type] + self.add_param_group(params) def zero_grad(self, set_to_none: bool = False) -> None: r"""Sets the gradients of all optimized :class:`torch.Tensor`\s to zero. @@ -114,16 +114,16 @@ def f(p): for i, (params, state) in enumerate(zip(self.param_groups, self.state_groups)): grads = pytree.tree_map(f, params) # type: ignore[arg-type] - updates, new_state = self.impl.update(grads, state, params=params, inplace=True) # type: ignore[arg-type] - self.param_groups[i] = apply_updates(params, updates, inplace=True) # type: ignore[arg-type,call-overload] + updates, new_state = self.impl.update(grads, state, params=params, inplace=True) + self.param_groups[i] = apply_updates(params, updates, inplace=True) self.state_groups[i] = new_state return loss def add_param_group(self, params: 'Params') -> None: """Add a param group to the optimizer's :attr:`param_groups`.""" - flat_params, params_treedef = pytree.tree_flatten(params) + flat_params, params_treespec = pytree.tree_flatten(params) flat_params: Tuple[torch.Tensor] = tuple(flat_params) # type: ignore[assignment] self.param_groups.append(flat_params) - self.param_treedefs.append(params_treedef) - self.state_groups.append(self.impl.init(flat_params)) # type: ignore[arg-type] + self.param_treespecs.append(params_treespec) + self.state_groups.append(self.impl.init(flat_params)) diff --git a/torchopt/optim/func/base.py b/torchopt/optim/func/base.py index fa59fc5a..f1d0b684 100644 --- a/torchopt/optim/func/base.py +++ b/torchopt/optim/func/base.py @@ -55,7 +55,7 @@ def __init__(self, impl: GradientTransformation, *, inplace: bool = False) -> No raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') self.impl: GradientTransformation = impl - self.optim_state: Optional[OptState] = self.__NOT_INITIALIZED # type: ignore[assignment] + self.optim_state: Optional[OptState] = self.__NOT_INITIALIZED self.inplace: bool = bool(inplace) def step( @@ -86,9 +86,9 @@ def step( inplace = self.inplace # Step parameter only - grads = torch.autograd.grad(loss, params, create_graph=True, allow_unused=True) # type: ignore[arg-type] + grads = torch.autograd.grad(loss, params, create_graph=True, allow_unused=True) updates, self.optim_state = self.impl.update( - grads, self.optim_state, params=params, inplace=inplace # type: ignore[arg-type] + grads, self.optim_state, params=params, inplace=inplace ) new_params = apply_updates(params, updates, inplace=inplace) return new_params diff --git a/torchopt/optim/meta/base.py b/torchopt/optim/meta/base.py index 668c46a4..89505111 100644 --- a/torchopt/optim/meta/base.py +++ b/torchopt/optim/meta/base.py @@ -67,11 +67,9 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals for i, (param_container, new_state) in enumerate( zip(self.param_containers_groups, self.state_groups) ): - flat_params_or_none: List[Optional[torch.Tensor]] - flat_params_or_none, container_treedef = pytree.tree_flatten(param_container) # type: ignore[arg-type] - flat_params: Tuple[torch.Tensor, ...] = tuple( - filter(torch.is_tensor, flat_params_or_none) # type: ignore[arg-type] - ) + flat_params: Tuple[torch.Tensor, ...] + flat_params, container_treespec = pytree.tree_flatten(param_container) # type: ignore[arg-type,assignment] + flat_params = tuple(flat_params) grads = torch.autograd.grad( loss, flat_params, @@ -79,23 +77,16 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals allow_unused=True, ) updates, new_state = self.impl.update( - grads, # type: ignore[arg-type] + grads, new_state, - params=flat_params, # type: ignore[arg-type] + params=flat_params, inplace=False, ) self.state_groups[i] = new_state - flat_new_params = apply_updates(flat_params, updates, inplace=False) # type: ignore[arg-type] - new_params_iter = iter(flat_new_params) # type: ignore[call-overload] - flat_new_params_or_none = [ - next(new_params_iter) - if isinstance(old_param_or_none, torch.Tensor) - else old_param_or_none - for old_param_or_none in flat_params_or_none - ] + flat_new_params = apply_updates(flat_params, updates, inplace=False) new_params = cast( Tuple[Dict[str, Optional[torch.Tensor]], ...], - pytree.tree_unflatten(container_treedef, flat_new_params_or_none), + pytree.tree_unflatten(container_treespec, flat_new_params), ) for container, new_param in zip(param_container, new_params): container.update(new_param) @@ -106,13 +97,8 @@ def add_param_group(self, net: nn.Module) -> None: from torchopt.utils import _extract_container params_container, _ = _extract_container(net, with_buffers=False) - flat_params = tuple( - filter( - torch.is_tensor, # type: ignore[arg-type] - pytree.tree_leaves(params_container), # type: ignore[arg-type] - ) - ) - optimizer_state = self.impl.init(flat_params) # type: ignore[arg-type] + flat_params: Tuple[torch.Tensor, ...] = tuple(pytree.tree_leaves(params_container)) # type: ignore[arg-type] + optimizer_state = self.impl.init(flat_params) self.param_containers_groups.append(params_container) self.state_groups.append(optimizer_state) diff --git a/torchopt/pytree.py b/torchopt/pytree.py index 2b25b027..3d4dd3c1 100644 --- a/torchopt/pytree.py +++ b/torchopt/pytree.py @@ -29,11 +29,11 @@ def tree_wait(future_tree: PyTree[Future[T]]) -> PyTree[T]: r"""Convert a tree of :class:`Future`\s to a tree of results.""" import torch # pylint: disable=import-outside-toplevel - futures, treedef = tree_flatten(future_tree) + futures, treespec = tree_flatten(future_tree) results = torch.futures.wait_all(futures) - return tree_unflatten(treedef, results) + return tree_unflatten(treespec, results) if rpc.is_available(): diff --git a/torchopt/transform/add_decayed_weights.py b/torchopt/transform/add_decayed_weights.py index 0554726c..700e9c7b 100644 --- a/torchopt/transform/add_decayed_weights.py +++ b/torchopt/transform/add_decayed_weights.py @@ -201,16 +201,14 @@ def update_fn(updates, state, params=None, inplace=True): # pylint: disable=unu if inplace: def f(g, p): - if g is not None: - if g.requires_grad: - return g.add_(p, alpha=weight_decay) - return g.add_(p.data, alpha=weight_decay) - return None + if g.requires_grad: + return g.add_(p, alpha=weight_decay) + return g.add_(p.data, alpha=weight_decay) else: def f(g, p): - return g.add(p, alpha=weight_decay) if g is not None else None + return g.add(p, alpha=weight_decay) updates = tree_map(f, updates, params) return updates, state diff --git a/torchopt/transform/scale.py b/torchopt/transform/scale.py index 0f8e494c..828b4b2f 100644 --- a/torchopt/transform/scale.py +++ b/torchopt/transform/scale.py @@ -71,12 +71,12 @@ def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable= if inplace: def f(g): - return g.mul_(step_size) if g is not None else None + return g.mul_(step_size) else: def f(g): - return g.mul(step_size) if g is not None else None + return g.mul(step_size) updates = tree_map(f, updates) return updates, state diff --git a/torchopt/transform/scale_by_adam.py b/torchopt/transform/scale_by_adam.py index ddd48cd2..d618ba91 100644 --- a/torchopt/transform/scale_by_adam.py +++ b/torchopt/transform/scale_by_adam.py @@ -46,7 +46,7 @@ __all__ = ['scale_by_adam', 'scale_by_accelerated_adam'] -TRIPLE_PYTREEDEF = pytree.tree_structure((0, 1, 2)) # type: ignore[arg-type] +TRIPLE_PYTREE_SPEC = pytree.tree_structure((0, 1, 2)) # type: ignore[arg-type] class ScaleByAdamState(NamedTuple): @@ -156,7 +156,7 @@ def init_fn(params): nu = tree_map( # second moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params ) - return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] + return ScaleByAdamState(mu=mu, nu=nu, count=zero) def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument mu = update_moment.impl( # type: ignore[attr-defined] @@ -172,13 +172,13 @@ def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable= if inplace: - def f(g, m, v): - return m.div_(v.add_(eps_root).sqrt_().add(eps)) if g is not None else None + def f(g, m, v): # pylint: disable=unused-argument + return m.div_(v.add_(eps_root).sqrt_().add(eps)) else: - def f(g, m, v): - return m.div(v.add(eps_root).sqrt_().add(eps)) if g is not None else None + def f(g, m, v): # pylint: disable=unused-argument + return m.div(v.add(eps_root).sqrt_().add(eps)) updates = tree_map(f, updates, mu_hat, nu_hat) return updates, ScaleByAdamState(mu=mu, nu=nu, count=count_inc) @@ -287,7 +287,7 @@ def update_fn(updates, state, *, params=None, inplace=True): def update_fn(updates, state, *, params=None, inplace=True): count_inc = inc_count.impl(updates, state.count, already_flattened=False) # type: ignore[attr-defined] - treedef = pytree.tree_structure(updates) + treespec = pytree.tree_structure(updates) op = AdamOp(b1=b1, b2=b2, eps=eps, eps_root=eps_root, inplace=inplace) out = pytree.tree_map(op, state.mu, state.nu, updates, count_inc) @@ -295,7 +295,7 @@ def update_fn(updates, state, *, params=None, inplace=True): new_mu: Updates new_nu: Updates new_updates: Updates - new_mu, new_nu, new_updates = pytree.tree_transpose(treedef, TRIPLE_PYTREEDEF, out) # type: ignore[misc] + new_mu, new_nu, new_updates = pytree.tree_transpose(treespec, TRIPLE_PYTREE_SPEC, out) # type: ignore[misc] return new_updates, ScaleByAdamState(mu=new_mu, nu=new_nu, count=count_inc) def init_fn(params): @@ -308,7 +308,7 @@ def init_fn(params): nu = tree_map( # second moment lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params ) - return ScaleByAdamState(mu=mu, nu=nu, count=zero) # type: ignore[arg-type] + return ScaleByAdamState(mu=mu, nu=nu, count=zero) return GradientTransformation(init_fn, update_fn) diff --git a/torchopt/transform/scale_by_rms.py b/torchopt/transform/scale_by_rms.py index 926e306f..3451fafe 100644 --- a/torchopt/transform/scale_by_rms.py +++ b/torchopt/transform/scale_by_rms.py @@ -109,7 +109,7 @@ def _scale_by_rms( def init_fn(params): nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment - return ScaleByRmsState(nu=nu) # type: ignore[arg-type] + return ScaleByRmsState(nu=nu) def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument nu = update_moment.impl( # type: ignore[attr-defined] diff --git a/torchopt/transform/scale_by_schedule.py b/torchopt/transform/scale_by_schedule.py index 71378337..5ec85899 100644 --- a/torchopt/transform/scale_by_schedule.py +++ b/torchopt/transform/scale_by_schedule.py @@ -87,13 +87,13 @@ def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable= def f(g, c): # pylint: disable=invalid-name step_size = step_size_fn(c) - return g.mul_(step_size) if g is not None else None + return g.mul_(step_size) else: def f(g, c): # pylint: disable=invalid-name step_size = step_size_fn(c) - return g.mul(step_size) if g is not None else None + return g.mul(step_size) updates = tree_map(f, updates, state.count) return ( diff --git a/torchopt/transform/scale_by_stddev.py b/torchopt/transform/scale_by_stddev.py index 3689b83b..37138566 100644 --- a/torchopt/transform/scale_by_stddev.py +++ b/torchopt/transform/scale_by_stddev.py @@ -113,7 +113,7 @@ def _scale_by_stddev( def init_fn(params): mu = tree_map(torch.zeros_like, params) # first moment nu = tree_map(lambda n: torch.full_like(n, initial_scale), params) # second moment - return ScaleByRStdDevState(mu=mu, nu=nu) # type: ignore[arg-type] + return ScaleByRStdDevState(mu=mu, nu=nu) def update_fn(updates, state, *, params=None, inplace=True): # pylint: disable=unused-argument mu = update_moment.impl( # type: ignore[attr-defined] diff --git a/torchopt/transform/trace.py b/torchopt/transform/trace.py index aecb7366..1d741d04 100644 --- a/torchopt/transform/trace.py +++ b/torchopt/transform/trace.py @@ -126,7 +126,7 @@ def _trace( def init_fn(params): return TraceState( - trace=tree_map( # type: ignore[arg-type] + trace=tree_map( lambda t: torch.zeros_like(t, requires_grad=moment_requires_grad), params ) ) @@ -185,7 +185,7 @@ def f(g, t): updates = tree_map(torch.clone, new_trace) first_call = False - return updates, TraceState(trace=new_trace) # type: ignore[arg-type] + return updates, TraceState(trace=new_trace) return GradientTransformation(init_fn, update_fn) diff --git a/torchopt/transform/utils.py b/torchopt/transform/utils.py index ffae2d1f..dcb8cf96 100644 --- a/torchopt/transform/utils.py +++ b/torchopt/transform/utils.py @@ -45,9 +45,16 @@ INT64_MAX = torch.iinfo(torch.int64).max -def tree_map_flat(func: Callable, *args: Any) -> List[Any]: +def tree_map_flat(func: Callable, *flat_args: Any, none_is_leaf: bool = False) -> List[Any]: """Apply a function to each element of a flattened list.""" - return list(map(func, *args)) + if none_is_leaf: + fn = func + else: + + def fn(x, *xs): + return func(x, *xs) if x is not None else None + + return list(map(fn, *flat_args)) def inc_count(updates: Updates, count: TensorTree) -> TensorTree: @@ -70,7 +77,7 @@ def f(c, g): # pylint: disable=invalid-name return c + (c != INT64_MAX).to(torch.int64) if g is not None else c if already_flattened: - return tree_map_flat(f, count, updates) # type: ignore[return-value] + return tree_map_flat(f, count, updates) return pytree.tree_map(f, count, updates) @@ -120,7 +127,7 @@ def f(g, t): if already_flattened: return tree_map_flat(f, updates, moments) - return pytree.tree_map(f, updates, moments) + return pytree.tree_map(f, updates, moments, none_is_leaf=True) update_moment.flat = _update_moment_flat # type: ignore[attr-defined] diff --git a/torchopt/typing.py b/torchopt/typing.py index 315cefc0..12751f96 100644 --- a/torchopt/typing.py +++ b/torchopt/typing.py @@ -18,7 +18,7 @@ from typing_extensions import TypeAlias # Python 3.10+ import torch.distributed.rpc as rpc -from optree.typing import PyTree +from optree.typing import PyTree, PyTreeTypeVar from torch import Tensor from torch.futures import Future @@ -51,8 +51,8 @@ Schedule: TypeAlias = Callable[[Numeric], Numeric] ScalarOrSchedule: TypeAlias = Union[float, Schedule] -TensorTree: TypeAlias = PyTree[Tensor] -OptionalTensorTree: TypeAlias = PyTree[Optional[Tensor]] +TensorTree: TypeAlias = PyTreeTypeVar('TensorTree', Tensor) # type: ignore[valid-type] +OptionalTensorTree: TypeAlias = PyTreeTypeVar('OptionalTensorTree', Optional[Tensor]) # type: ignore[valid-type] # Parameters are arbitrary nests of `torch.Tensor`. Params: TypeAlias = TensorTree From 235da74f264634dc1ddcb21f35dbbc0aeed581f1 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Oct 2022 15:09:36 +0800 Subject: [PATCH 32/69] deps: bump PyTorch version to 1.13 (#104) --- .github/workflows/build.yml | 12 ++++++------ .github/workflows/lint.yml | 4 ++-- .github/workflows/tests.yml | 4 ++-- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 1 + Dockerfile | 2 +- README.md | 4 ++-- conda-recipe.yaml | 27 +++++++++++++++++++------- docs/conda-recipe.yaml | 11 +++++------ docs/requirements.txt | 3 +-- docs/source/developer/contributing.rst | 4 ++-- examples/requirements.txt | 5 ++--- pyproject.toml | 16 +++++++-------- requirements.txt | 5 ++--- tests/requirements.txt | 5 ++--- tests/test_alias.py | 2 +- tests/test_clip.py | 2 +- tests/test_optim.py | 2 +- tutorials/requirements.txt | 5 ++--- 19 files changed, 62 insertions(+), 54 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c624654..b443142f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,8 +37,8 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: - CUDA_VERSION: "11.6" - TEST_TORCH_SPECS: "cpu cu113 cu116" + CUDA_VERSION: "11.7" + TEST_TORCH_SPECS: "cpu cu116" jobs: build-sdist: @@ -55,7 +55,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.7 - 3.10" # sync with requires-python in pyproject.toml + python-version: "3.7 - 3.11" # sync with requires-python in pyproject.toml update-environment: true - name: Set __release__ @@ -117,7 +117,7 @@ jobs: run: python .github/workflows/set_cibw_build.py - name: Build wheels - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_BUILD: ${{ env.CIBW_BUILD }} with: @@ -167,7 +167,7 @@ jobs: run: python .github/workflows/set_cibw_build.py - name: Build wheels - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_BUILD: ${{ env.CIBW_BUILD }} with: @@ -200,7 +200,7 @@ jobs: uses: actions/setup-python@v4 if: startsWith(github.ref, 'refs/tags/') with: - python-version: "3.7 - 3.10" # sync with requires-python in pyproject.toml + python-version: "3.7 - 3.11" # sync with requires-python in pyproject.toml update-environment: true - name: Set __release__ diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index eb94beff..8ed36d36 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -33,10 +33,10 @@ jobs: update-environment: true - name: Setup CUDA Toolkit - uses: Jimver/cuda-toolkit@v0.2.7 + uses: Jimver/cuda-toolkit@v0.2.8 id: cuda-toolkit with: - cuda: "11.6.2" + cuda: "11.7.0" method: network sub-packages: '["nvcc"]' - run: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ac64044a..611913de 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,10 +44,10 @@ jobs: update-environment: true - name: Setup CUDA Toolkit - uses: Jimver/cuda-toolkit@v0.2.7 + uses: Jimver/cuda-toolkit@v0.2.8 id: cuda-toolkit with: - cuda: "11.6.2" + cuda: "11.7.0" method: network sub-packages: '["nvcc"]' - run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 90bedada..2d1a126a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: - id: isort stages: [commit, push, manual] - repo: https://github.com/psf/black - rev: 22.8.0 + rev: 22.10.0 hooks: - id: black-jupyter stages: [commit, push, manual] diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b537d9c..f20480a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Bump PyTorch version to 1.13.0 by [@XuehaiPan](https://github.com/XuehaiPan) in [#104](https://github.com/metaopt/torchopt/pull/104). - Add zero-order gradient estimation by [@JieRen98](https://github.com/JieRen98) in [#93](https://github.com/metaopt/torchopt/pull/93). - Add RPC-based distributed training support and add distributed MAML example by [@XuehaiPan](https://github.com/XuehaiPan) in [#83](https://github.com/metaopt/torchopt/pull/83). - Add full type hints by [@XuehaiPan](https://github.com/XuehaiPan) in [#92](https://github.com/metaopt/torchopt/pull/92). diff --git a/Dockerfile b/Dockerfile index 82434eed..d34eda03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ # $ docker build --target devel --tag torchopt-devel:latest . # -ARG cuda_docker_tag="11.6.2-cudnn8-devel-ubuntu20.04" +ARG cuda_docker_tag="11.7.1-cudnn8-devel-ubuntu22.04" FROM nvidia/cuda:"${cuda_docker_tag}" AS builder ENV DEBIAN_FRONTEND=noninteractive diff --git a/README.md b/README.md index 3af9d667..be7497ac 100644 --- a/README.md +++ b/README.md @@ -240,10 +240,10 @@ Requirements pip3 install torchopt ``` -If the minimum version of PyTorch is not satisfied, `pip` will install/upgrade it for you. Please be careful about the `torch` build for CPU / CUDA support (e.g. `cpu`, `cu102`, `cu113`). You may need to specify the extra index URL for the `torch` package: +If the minimum version of PyTorch is not satisfied, `pip` will install/upgrade it for you. Please be careful about the `torch` build for CPU / CUDA support (e.g. `cpu`, `cu116`, `cu117`). You may need to specify the extra index URL for the `torch` package: ```bash -pip3 install torchopt --extra-index-url https://download.pytorch.org/whl/cu116 +pip3 install torchopt --extra-index-url https://download.pytorch.org/whl/cu117 ``` See for more information about installing PyTorch. diff --git a/conda-recipe.yaml b/conda-recipe.yaml index 374bae9d..0ebf0229 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# # Create virtual environment with command: # # $ CONDA_OVERRIDE_CUDA=11.7 conda env create --file conda-recipe.yaml @@ -8,7 +23,6 @@ name: torchopt channels: - pytorch - defaults - - nvidia/label/cuda-11.6.2 - nvidia - conda-forge @@ -17,11 +31,10 @@ dependencies: - pip # Learning - - pytorch::pytorch >= 1.12 # sync with project.dependencies + - pytorch::pytorch >= 1.13 # sync with project.dependencies - pytorch::torchvision - pytorch::pytorch-mutex = *=*cuda* - pip: - - functorch >= 0.2 # sync with project.dependencies - torchviz - sphinxcontrib-katex # for documentation - jax # for tutorials @@ -31,7 +44,7 @@ dependencies: - wandb # Device select - - nvidia::cudatoolkit = 11.6 + - pytorch::pytorch-cuda = 11.7 - cudnn # Build toolchain @@ -39,13 +52,13 @@ dependencies: - make - cxx-compiler - gxx = 10 - - nvidia/label/cuda-11.6.2::cuda-nvcc - - nvidia/label/cuda-11.6.2::cuda-cudart-dev + - nvidia::cuda-nvcc + - nvidia::cuda-cudart-dev - patchelf >= 0.9 - pybind11 # Misc - - typing-extensions + - typing-extensions >= 4.0.0 - numpy - matplotlib-base - seaborn diff --git a/docs/conda-recipe.yaml b/docs/conda-recipe.yaml index 476dc1a2..0ecce9b3 100644 --- a/docs/conda-recipe.yaml +++ b/docs/conda-recipe.yaml @@ -30,10 +30,9 @@ dependencies: - pip # Learning - - pytorch::pytorch >= 1.12 # sync with project.dependencies - - pytorch::pytorch-mutex = *=*cpu* + - pytorch::pytorch >= 1.13 # sync with project.dependencies + - pytorch::cpuonly - pip: - - functorch >= 0.2 # sync with project.dependencies - torchviz - sphinxcontrib-katex # for documentation - tensorboard @@ -44,12 +43,12 @@ dependencies: - make - cxx-compiler - gxx = 10 - - nvidia/label/cuda-11.6.2::cuda-nvcc - - nvidia/label/cuda-11.6.2::cuda-cudart-dev + - nvidia/label/cuda-11.7.1::cuda-nvcc + - nvidia/label/cuda-11.7.1::cuda-cudart-dev - pybind11 # Misc - - typing-extensions + - typing-extensions >= 4.0.0 - numpy - matplotlib-base - seaborn diff --git a/docs/requirements.txt b/docs/requirements.txt index 9060c0ec..9ac98898 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,6 @@ --extra-index-url https://download.pytorch.org/whl/cpu # Sync with project.dependencies -torch >= 1.12 -functorch >= 0.2 +torch >= 1.13 --requirement ../requirements.txt diff --git a/docs/source/developer/contributing.rst b/docs/source/developer/contributing.rst index 13f7c30b..b4c4c825 100644 --- a/docs/source/developer/contributing.rst +++ b/docs/source/developer/contributing.rst @@ -91,8 +91,8 @@ To build compatible **manylinux2014** (:pep:`599`) wheels for distribution, you pip3 install --upgrade cibuildwheel - export TEST_TORCH_SPECS="cpu cu113 cu116" # `torch` builds for testing - export CUDA_VERSION="11.6" # version of `nvcc` for compilation + export TEST_TORCH_SPECS="cpu cu116" # `torch` builds for testing + export CUDA_VERSION="11.7" # version of `nvcc` for compilation python3 -m cibuildwheel --platform=linux --output-dir=wheelhouse --config-file=pyproject.toml It will install the CUDA compiler with ``CUDA_VERSION`` in the build container. Then build wheel binaries for all supported CPython versions. The outputs will be placed in the ``wheelhouse`` directory. diff --git a/examples/requirements.txt b/examples/requirements.txt index a36da3aa..76bed365 100644 --- a/examples/requirements.txt +++ b/examples/requirements.txt @@ -1,7 +1,6 @@ ---extra-index-url https://download.pytorch.org/whl/cu116 -torch >= 1.12 +--extra-index-url https://download.pytorch.org/whl/cu117 +torch >= 1.13 torchvision -functorch >= 0.2 --requirement ../requirements.txt diff --git a/pyproject.toml b/pyproject.toml index 5fb08617..97bf5ee7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [build-system] # Sync with project.dependencies -requires = ["setuptools", "torch >= 1.12", "numpy", "pybind11"] +requires = ["setuptools", "torch >= 1.13", "numpy", "pybind11"] build-backend = "setuptools.build_meta" [project] @@ -11,7 +11,7 @@ description = "A Jax-style optimizer for PyTorch." readme = "README.md" # Change this if wheels for `torch` is available # Search "requires-python" and update all corresponding items -requires-python = ">= 3.7, < 3.11.0a0" +requires-python = ">= 3.7" authors = [ { name = "TorchOpt Contributors" }, { name = "Jie Ren", email = "jieren9806@gmail.com" }, @@ -38,6 +38,7 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Operating System :: POSIX :: Linux", "Environment :: GPU", "Environment :: GPU :: NVIDIA CUDA", @@ -48,12 +49,11 @@ classifiers = [ "Topic :: Scientific/Engineering :: Artificial Intelligence", ] dependencies = [ - "torch >= 1.12", # see also build-system.requires and project.requires-python - "functorch >= 0.2", + "torch >= 1.13", # see also build-system.requires and project.requires-python "optree >= 0.3.0", "numpy", "graphviz", - "typing-extensions", + "typing-extensions >= 4.0.0", ] dynamic = ["version"] @@ -100,8 +100,8 @@ build-verbosity = 3 environment.USE_FP16 = "ON" environment.CUDACXX = "/usr/local/cuda/bin/nvcc" environment.TORCH_CUDA_ARCH_LIST = "Common" -environment.DEFAULT_CUDA_VERSION = "11.6" -environment.DEFAULT_TEST_TORCH_SPECS = "cpu cu113 cu116" +environment.DEFAULT_CUDA_VERSION = "11.7" +environment.DEFAULT_TEST_TORCH_SPECS = "cpu cu116" environment-pass = ["CUDA_VERSION", "TEST_TORCH_SPECS"] container-engine = "docker" @@ -168,7 +168,7 @@ safe = true line-length = 100 skip-string-normalization = true # Sync with requires-python -target-version = ["py37", "py38", "py39", "py310"] +target-version = ["py37", "py38", "py39", "py310", "py311"] [tool.isort] atomic = true diff --git a/requirements.txt b/requirements.txt index a7aac2fa..72fbc9eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ # Sync with project.dependencies -torch >= 1.12 -functorch >= 0.2 +torch >= 1.13 optree >= 0.3.0 numpy graphviz -typing-extensions +typing-extensions >= 4.0.0 diff --git a/tests/requirements.txt b/tests/requirements.txt index 4cebb171..56650cc8 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,6 +1,5 @@ ---extra-index-url https://download.pytorch.org/whl/cu116 -torch >= 1.12 -functorch >= 0.2 +--extra-index-url https://download.pytorch.org/whl/cu117 +torch >= 1.13 --requirement ../requirements.txt diff --git a/tests/test_alias.py b/tests/test_alias.py index 1da08b35..50b42835 100644 --- a/tests/test_alias.py +++ b/tests/test_alias.py @@ -32,7 +32,7 @@ nesterov=[False, True], inplace=[True, False], weight_decay=[0.0, 1e-2], - maximize=[False], # TODO: test maximize after PyTorch 1.13 + maximize=[False, True], ) def test_sgd( dtype: torch.dtype, diff --git a/tests/test_clip.py b/tests/test_clip.py index 420cfdaa..f8d3b289 100644 --- a/tests/test_clip.py +++ b/tests/test_clip.py @@ -30,7 +30,7 @@ dampening=[0.0, 0.5], nesterov=[False, True], weight_decay=[0.0, 1e-2], - maximize=[False], # TODO: test maximize after PyTorch 1.13 + maximize=[False, True], ) def test_sgd( dtype: torch.dtype, diff --git a/tests/test_optim.py b/tests/test_optim.py index f8fff9a3..fe1697c9 100644 --- a/tests/test_optim.py +++ b/tests/test_optim.py @@ -31,7 +31,7 @@ dampening=[0.0, 0.5], nesterov=[False, True], weight_decay=[0.0, 1e-2], - maximize=[False], # TODO: test maximize after PyTorch 1.13 + maximize=[False, True], ) def test_SGD( dtype: torch.dtype, diff --git a/tutorials/requirements.txt b/tutorials/requirements.txt index 7531b8f8..026d23a5 100644 --- a/tutorials/requirements.txt +++ b/tutorials/requirements.txt @@ -1,8 +1,7 @@ ---extra-index-url https://download.pytorch.org/whl/cu116 +--extra-index-url https://download.pytorch.org/whl/cu117 # Sync with project.dependencies -torch >= 1.12 +torch >= 1.13 torchvision -functorch >= 0.2 --requirement ../requirements.txt From 9def086114d07e037eaa72980408b24fdbfdc6e8 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Oct 2022 23:13:39 +0800 Subject: [PATCH 33/69] chore: update conda recipes and badges --- Makefile | 2 +- README.md | 17 ++++++++--------- conda-recipe.yaml | 13 +++++++------ docs/conda-recipe.yaml | 6 +++--- docs/source/index.rst | 6 +++--- tests/requirements.txt | 7 ++++--- tutorials/requirements.txt | 3 +++ 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 1342e8e0..07cd00ca 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ pylint-install: flake8-install: $(call check_pip_install,flake8) - $(call check_pip_install_extra,bugbear,flake8_bugbear) + $(call check_pip_install_extra,flake8-bugbear,flake8-bugbear) py-format-install: $(call check_pip_install,isort) diff --git a/README.md b/README.md index be7497ac..719f4442 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,14 @@ ![Python 3.7+](https://img.shields.io/badge/Python-3.7%2B-brightgreen.svg) -[![PyPI](https://img.shields.io/pypi/v/torchopt?label=PyPI)](https://pypi.org/project/torchopt) -![Status](https://img.shields.io/pypi/status/torchopt?label=Status) +[![PyPI](https://img.shields.io/pypi/v/torchopt?logo=pypi)](https://pypi.org/project/torchopt) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/metaopt/torchopt/Tests?label=tests&logo=github) -[![Documentation Status](https://readthedocs.org/projects/torchopt/badge/?version=latest)](https://torchopt.readthedocs.io/en/latest/?badge=latest) -[![Downloads](https://static.pepy.tech/personalized-badge/torchopt?period=month&left_color=grey&right_color=blue&left_text=Downloads/month)](https://pepy.tech/project/torchopt) -[![GitHub Repo Stars](https://img.shields.io/github/stars/metaopt/torchopt?label=Stars&logo=github&color=brightgreen)](https://github.com/metaopt/torchopt/stargazers) -[![License](https://img.shields.io/github/license/metaopt/torchopt?label=License)](#license) +[![Documentation Status](https://img.shields.io/readthedocs/torchopt?logo=readthedocs)](https://torchopt.readthedocs.io) +[![Downloads](https://static.pepy.tech/personalized-badge/torchopt?period=total&left_color=grey&right_color=blue&left_text=downloads)](https://pepy.tech/project/torchopt) +[![GitHub Repo Stars](https://img.shields.io/github/stars/metaopt/torchopt?color=brightgreen&logo=github)](https://github.com/metaopt/torchopt/stargazers) +[![License](https://img.shields.io/github/license/metaopt/torchopt?label=license)](#license) -**TorchOpt** is a high-performance optimizer library built upon [PyTorch](https://pytorch.org/) for easy implementation of functional optimization and gradient-based meta-learning. It consists of two main features: +**TorchOpt** is a high-performance optimizer library built upon [PyTorch](https://pytorch.org) for easy implementation of functional optimization and gradient-based meta-learning. It consists of two main features: - TorchOpt provides functional optimizer which enables [JAX-like](https://github.com/google/jax) composable functional optimizer for PyTorch. With TorchOpt, one can easily conduct neural network optimization in PyTorch with functional style optimizer, similar to [Optax](https://github.com/deepmind/optax) in JAX. - With the design of functional programing, TorchOpt provides efficient, flexible, and easy-to-implement differentiable optimizer for gradient-based meta-learning research. It largely reduces the efforts required to implement sophisticated meta-learning algorithms. @@ -232,9 +231,9 @@ Requirements - PyTorch - (Optional) For visualizing computation graphs - - [Graphviz](https://graphviz.org/download/) (for Linux users use `apt/yum install graphviz` or `conda install -c anaconda python-graphviz`) + - [Graphviz](https://graphviz.org/download) (for Linux users use `apt/yum install graphviz` or `conda install -c anaconda python-graphviz`) -**Please follow the instructions at to install PyTorch in your Python environment first.** Then run the following command to install TorchOpt from PyPI ([![PyPI](https://img.shields.io/pypi/v/torchopt?label=PyPI)](https://pypi.org/project/torchopt) / ![Status](https://img.shields.io/pypi/status/torchopt?label=Status)): +**Please follow the instructions at to install PyTorch in your Python environment first.** Then run the following command to install TorchOpt from PyPI ([![PyPI](https://img.shields.io/pypi/v/torchopt?label=pypi&logo=pypi)](https://pypi.org/project/torchopt) / ![Status](https://img.shields.io/pypi/status/torchopt?label=status)): ```bash pip3 install torchopt diff --git a/conda-recipe.yaml b/conda-recipe.yaml index 0ebf0229..edc0767b 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -22,12 +22,12 @@ name: torchopt channels: - pytorch + - nvidia/label/cuda-11.7.1 - defaults - - nvidia - conda-forge dependencies: - - python = 3.8 + - python = 3.9 - pip # Learning @@ -40,20 +40,20 @@ dependencies: - jax # for tutorials - jaxlib >= 0.3=*cuda* # for tutorials - optax # for tutorials + - jaxopt # for tests - tensorboard # for examples - wandb # Device select - - pytorch::pytorch-cuda = 11.7 - - cudnn + - nvidia/label/cuda-11.7.1::cuda-toolkit = 11.7 # Build toolchain - cmake >= 3.4 - make - cxx-compiler - gxx = 10 - - nvidia::cuda-nvcc - - nvidia::cuda-cudart-dev + - nvidia/label/cuda-11.7.1::cuda-nvcc + - nvidia/label/cuda-11.7.1::cuda-cudart-dev - patchelf >= 0.9 - pybind11 @@ -75,6 +75,7 @@ dependencies: - sphinxcontrib-bibtex - sphinx-autodoc-typehints - pyenchant + - hunspell-en - myst-nb - ipykernel - pandoc diff --git a/docs/conda-recipe.yaml b/docs/conda-recipe.yaml index 0ecce9b3..4c6dba21 100644 --- a/docs/conda-recipe.yaml +++ b/docs/conda-recipe.yaml @@ -22,11 +22,12 @@ name: torchopt-docs channels: - pytorch + - nvidia/label/cuda-11.7.1 - defaults - conda-forge dependencies: - - python = 3.8 + - python = 3.9 - pip # Learning @@ -35,8 +36,6 @@ dependencies: - pip: - torchviz - sphinxcontrib-katex # for documentation - - tensorboard - - wandb # Build toolchain - cmake >= 3.4 @@ -64,6 +63,7 @@ dependencies: - sphinxcontrib-bibtex - sphinx-autodoc-typehints - pyenchant + - hunspell-en - myst-nb - ipykernel - pandoc diff --git a/docs/source/index.rst b/docs/source/index.rst index b68717a7..6d169f58 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -3,7 +3,7 @@ TorchOpt -------- -**TorchOpt** is a high-performance optimizer library built upon `PyTorch `_ for easy implementation of functional optimization and gradient-based meta-learning. It consists of two main features: +**TorchOpt** is a high-performance optimizer library built upon `PyTorch `_ for easy implementation of functional optimization and gradient-based meta-learning. It consists of two main features: * TorchOpt provides functional optimizer which enables `JAX-like `_ composable functional optimizer for PyTorch. With TorchOpt, one can easily conduct neural network optimization in PyTorch with functional style optimizer, similar to `Optax `_ in JAX. * With the design of functional programming, TorchOpt provides efficient, flexible, and easy-to-implement differentiable optimizer for gradient-based meta-learning research. It largely reduces the efforts required to implement sophisticated meta-learning algorithms. @@ -13,8 +13,8 @@ Installation Requirements: -* `PyTorch `_ -* (Optional) `Graphviz `_ +* `PyTorch `_ +* (Optional) `Graphviz `_ Please follow the instructions at https://pytorch.org to install PyTorch in your Python environment first. Then run the following command to install TorchOpt from PyPI: diff --git a/tests/requirements.txt b/tests/requirements.txt index 56650cc8..9edc2964 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,6 +3,10 @@ torch >= 1.13 --requirement ../requirements.txt +jax[cpu] >= 0.3 +jaxopt +optax + pytest pytest-cov pytest-xdist @@ -18,6 +22,3 @@ pydocstyle pyenchant cpplint pre-commit -jax[cpu] >= 0.3 -jaxopt -optax diff --git a/tutorials/requirements.txt b/tutorials/requirements.txt index 026d23a5..ff5a5c42 100644 --- a/tutorials/requirements.txt +++ b/tutorials/requirements.txt @@ -6,3 +6,6 @@ torchvision --requirement ../requirements.txt ipykernel +jax[cpu] >= 0.3 +jaxopt +optax From 02da71995990e79e84fcc2869e5f22262596474c Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 1 Nov 2022 14:32:46 +0800 Subject: [PATCH 34/69] feat: meta-gradient module (#101) --- CHANGELOG.md | 1 + conda-recipe.yaml | 3 +- docs/conda-recipe.yaml | 2 + docs/source/api/api.rst | 10 + docs/source/conf.py | 22 +- docs/source/spelling_wordlist.txt | 4 + torchopt/alias/adamw.py | 5 +- torchopt/diff/implicit/__init__.py | 5 + torchopt/diff/implicit/decorator.py | 244 +++++++------ torchopt/diff/implicit/nn/__init__.py | 20 ++ torchopt/diff/implicit/nn/module.py | 283 +++++++++++++++ torchopt/distributed/autograd.py | 35 +- torchopt/linear_solve/normal_cg.py | 10 +- torchopt/nn/__init__.py | 17 + torchopt/nn/module.py | 458 ++++++++++++++++++++++++ torchopt/optim/adamw.py | 4 +- torchopt/optim/base.py | 16 +- torchopt/optim/func/base.py | 6 +- torchopt/optim/meta/adamw.py | 4 +- torchopt/optim/meta/base.py | 19 +- torchopt/pytree.py | 27 +- torchopt/transform/scale_by_adam.py | 6 +- torchopt/transform/scale_by_schedule.py | 6 +- torchopt/typing.py | 24 +- torchopt/update.py | 4 +- torchopt/utils.py | 25 +- torchopt/visual.py | 5 +- 27 files changed, 1083 insertions(+), 182 deletions(-) create mode 100644 torchopt/diff/implicit/nn/__init__.py create mode 100644 torchopt/diff/implicit/nn/module.py create mode 100644 torchopt/nn/__init__.py create mode 100644 torchopt/nn/module.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f20480a7..9e3934ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add object-oriented modules support for implicit meta-gradient by [@XuehaiPan](https://github.com/XuehaiPan) in [#101](https://github.com/metaopt/torchopt/pull/101). - Bump PyTorch version to 1.13.0 by [@XuehaiPan](https://github.com/XuehaiPan) in [#104](https://github.com/metaopt/torchopt/pull/104). - Add zero-order gradient estimation by [@JieRen98](https://github.com/JieRen98) in [#93](https://github.com/metaopt/torchopt/pull/93). - Add RPC-based distributed training support and add distributed MAML example by [@XuehaiPan](https://github.com/XuehaiPan) in [#83](https://github.com/metaopt/torchopt/pull/83). diff --git a/conda-recipe.yaml b/conda-recipe.yaml index edc0767b..97a9dcca 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -54,10 +54,11 @@ dependencies: - gxx = 10 - nvidia/label/cuda-11.7.1::cuda-nvcc - nvidia/label/cuda-11.7.1::cuda-cudart-dev - - patchelf >= 0.9 + - patchelf >= 0.14 - pybind11 # Misc + - optree >= 0.3.0 - typing-extensions >= 4.0.0 - numpy - matplotlib-base diff --git a/docs/conda-recipe.yaml b/docs/conda-recipe.yaml index 4c6dba21..ad28ac50 100644 --- a/docs/conda-recipe.yaml +++ b/docs/conda-recipe.yaml @@ -33,6 +33,7 @@ dependencies: # Learning - pytorch::pytorch >= 1.13 # sync with project.dependencies - pytorch::cpuonly + - pytorch::pytorch-mutex = *=*cpu* - pip: - torchviz - sphinxcontrib-katex # for documentation @@ -47,6 +48,7 @@ dependencies: - pybind11 # Misc + - optree >= 0.3.0 - typing-extensions >= 4.0.0 - numpy - matplotlib-base diff --git a/docs/source/api/api.rst b/docs/source/api/api.rst index d0366f60..1ec8e1d2 100644 --- a/docs/source/api/api.rst +++ b/docs/source/api/api.rst @@ -139,12 +139,22 @@ Implicit differentiation .. autosummary:: custom_root + nn.ImplicitMetaGradientModule Custom solvers ~~~~~~~~~~~~~~ .. autofunction:: custom_root + +Implicit Meta-Gradient Module +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. currentmodule:: torchopt.diff.implicit.nn + +.. autoclass:: ImplicitMetaGradientModule + :members: + ------ Linear system solving diff --git a/docs/source/conf.py b/docs/source/conf.py index 694086fe..b213cfaa 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,6 +25,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +import logging import os import pathlib import sys @@ -43,6 +44,24 @@ def get_version() -> str: return version.__version__ +try: + import sphinx_autodoc_typehints +except ImportError: + pass +else: + + class RecursiveForwardRefFilter(logging.Filter): + def filter(self, record): + if ( + "name 'TensorTree' is not defined" in record.getMessage() + or "name 'OptionalTensorTree' is not defined" in record.getMessage() + ): + return False + return super().filter(record) + + sphinx_autodoc_typehints._LOGGER.logger.addFilter(RecursiveForwardRefFilter()) + + # -- Project information ----------------------------------------------------- project = 'TorchOpt' @@ -75,7 +94,7 @@ def get_version() -> str: 'sphinxcontrib.bibtex', 'sphinxcontrib.katex', 'sphinx_autodoc_typehints', - 'myst_nb', # This is used for the .ipynb notebooks + 'myst_nb', # this is used for the .ipynb notebooks ] if not os.getenv('READTHEDOCS', None): @@ -120,6 +139,7 @@ def get_version() -> str: 'exclude-members': '__module__, __dict__, __repr__, __str__, __weakref__', } autoclass_content = 'both' +simplify_optional_unions = False # -- Options for bibtex ----------------------------------------------------- diff --git a/docs/source/spelling_wordlist.txt b/docs/source/spelling_wordlist.txt index f590b546..25f11953 100644 --- a/docs/source/spelling_wordlist.txt +++ b/docs/source/spelling_wordlist.txt @@ -88,3 +88,7 @@ deepcopy deepclone RRef rref +ints +Karush +Kuhn +Tucker diff --git a/torchopt/alias/adamw.py b/torchopt/alias/adamw.py index 4c8d96b4..b088be60 100644 --- a/torchopt/alias/adamw.py +++ b/torchopt/alias/adamw.py @@ -36,8 +36,7 @@ from torchopt.alias.utils import flip_sign_and_add_weight_decay, scale_by_neg_lr from torchopt.combine import chain_flat from torchopt.transform import add_decayed_weights, scale_by_accelerated_adam, scale_by_adam -from torchopt.typing import Params # pylint: disable=unused-import -from torchopt.typing import GradientTransformation, ScalarOrSchedule +from torchopt.typing import GradientTransformation, Params, ScalarOrSchedule __all__ = ['adamw'] @@ -51,7 +50,7 @@ def adamw( weight_decay: float = 1e-2, *, eps_root: float = 0.0, - mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, moment_requires_grad: bool = False, maximize: bool = False, use_accelerated_op: bool = False, diff --git a/torchopt/diff/implicit/__init__.py b/torchopt/diff/implicit/__init__.py index 2f3f184c..4e50b615 100644 --- a/torchopt/diff/implicit/__init__.py +++ b/torchopt/diff/implicit/__init__.py @@ -14,4 +14,9 @@ # ============================================================================== """Implicit Meta-Gradient.""" +from torchopt.diff.implicit import nn from torchopt.diff.implicit.decorator import custom_root +from torchopt.diff.implicit.nn import ImplicitMetaGradientModule + + +__all__ = ['custom_root', 'ImplicitMetaGradientModule'] diff --git a/torchopt/diff/implicit/decorator.py b/torchopt/diff/implicit/decorator.py index 3e1ebcad..6f19c196 100644 --- a/torchopt/diff/implicit/decorator.py +++ b/torchopt/diff/implicit/decorator.py @@ -18,13 +18,14 @@ import functools import inspect -from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, Union import functorch import torch from torch.autograd import Function from torchopt import linear_solve, pytree +from torchopt.typing import ListOfTensors, TensorOrTensors, TupleOfTensors __all__ = ['custom_root'] @@ -37,15 +38,15 @@ class MaskedOptimalityFn: # pylint: disable=missing-class-docstring,too-few-public-methods def __init__( self, - optimality_fn: Callable, - solution: Any, - result_is_tensor: bool, + optimality_fn: Callable[..., TensorOrTensors], + solution: TensorOrTensors, + output_is_tensor: bool, argnums: Tuple[int, ...], - *args, + *args: Any, ) -> None: self.optimality_fn = optimality_fn self.solution = solution - self.result_is_tensor = result_is_tensor + self.output_is_tensor = output_is_tensor self.argnums = argnums pre_filled = [] @@ -59,7 +60,7 @@ def __init__( self.pre_filled = tuple(pre_filled) self.post_filled = tuple(post_filled) - def __call__(self, *args) -> Any: + def __call__(self, *args: Any) -> TensorOrTensors: true_args = [] pre_filled_counter = 0 for idx in range(self.len_args): @@ -69,78 +70,80 @@ def __call__(self, *args) -> Any: arg = self.pre_filled[pre_filled_counter] pre_filled_counter += 1 true_args.append(arg) - if self.result_is_tensor: + if self.output_is_tensor: return self.optimality_fn(self.solution[0], *true_args) return self.optimality_fn(self.solution, *true_args) # pylint: disable-next=too-many-arguments,too-many-locals,too-many-branches def _root_vjp( - optimality_fn: Callable, - solution: Any, + optimality_fn: Callable[..., TensorOrTensors], + solution: TupleOfTensors, args: Args, - grad_outputs: Any, - result_is_tensor: bool, + grad_outputs: TupleOfTensors, + output_is_tensor: bool, argnums: Tuple[int, ...], - solve: Callable = linear_solve.solve_normal_cg(), -) -> Tuple[Any, ...]: + solve: Callable[..., TensorOrTensors] = linear_solve.solve_normal_cg(), +) -> Tuple[Optional[torch.Tensor], ...]: - if result_is_tensor: + if output_is_tensor: - def optimality_cond(solution): + def optimality_cond(solution: TupleOfTensors) -> TensorOrTensors: return optimality_fn(solution[0], *args) else: - def optimality_cond(solution): + def optimality_cond(solution: TupleOfTensors) -> TensorOrTensors: return optimality_fn(solution, *args) - _, vjp_optimality_cond, *_ = functorch.vjp(optimality_cond, solution) + _, optimality_cond_vjp_fn, *_ = functorch.vjp(optimality_cond, solution) # Compute the multiplication A^T u = (u^T A)^T. - if result_is_tensor: + if output_is_tensor: - def matvec(u): - return vjp_optimality_cond(u[0])[0] + def matvec(u: TupleOfTensors) -> TupleOfTensors: + return optimality_cond_vjp_fn(u[0])[0] else: - def matvec(u): - return vjp_optimality_cond(u)[0] + def matvec(u: TupleOfTensors) -> TupleOfTensors: + return optimality_cond_vjp_fn(u)[0] # The solution of A^T u = v, where # A = jacobian(optimality_fn, argnums=0) # v = -grad_outputs. - v = pytree.tree_map(torch.neg, grad_outputs) - u = solve(matvec, v) + v: TupleOfTensors = pytree.tree_map(torch.neg, grad_outputs) # type: ignore[arg-type,assignment] + u: TupleOfTensors = solve(matvec, v) # type: ignore[assignment] masked_optimality_fn = MaskedOptimalityFn( - optimality_fn, solution, result_is_tensor, argnums, *args + optimality_fn, solution, output_is_tensor, argnums, *args ) - if getattr(solve, 'is_sdp', False): - if result_is_tensor: - result = u[0] + output: TupleOfTensors + if getattr(solve, 'is_spd', False): + if output_is_tensor: + output = u else: - result = u + output = (u,) # type: ignore[assignment] else: - _, vjp_optimality_fn, *_ = functorch.vjp( + _, optimality_vjp_fn, *_ = functorch.vjp( masked_optimality_fn, *masked_optimality_fn.post_filled ) - if result_is_tensor: - result = vjp_optimality_fn(u[0]) + if output_is_tensor: + output = optimality_vjp_fn(u[0]) else: - result = vjp_optimality_fn(u) + output = optimality_vjp_fn(u) - true_result = [None] + # Prepend None as the vjp for init_params. + true_output: List[Optional[torch.Tensor]] = [None] for idx in range(masked_optimality_fn.len_args): if idx + 1 in argnums: # plus 1 because we exclude the first argument - true_result.append(result[idx]) + true_output.append(output[idx]) else: - true_result.append(None) + true_output.append(None) - return tuple(true_result) + return tuple(true_output) def _extract_kwargs(kwarg_keys: Sequence[str], flat_args: Tuple[Any, ...]) -> Tuple[Args, KwArgs]: @@ -150,14 +153,14 @@ def _extract_kwargs(kwarg_keys: Sequence[str], flat_args: Tuple[Any, ...]) -> Tu return args, kwargs -def _signature_bind(signature: inspect.Signature, *args, **kwargs) -> Tuple[Args, KwArgs]: +def _signature_bind(signature: inspect.Signature, *args: Any, **kwargs: Any) -> Tuple[Args, KwArgs]: bound = signature.bind(*args, **kwargs) bound.apply_defaults() return bound.args, bound.kwargs def _signature_bind_and_match( - signature: inspect.Signature, *args, **kwargs + signature: inspect.Signature, *args: Any, **kwargs: Any ) -> Tuple[Args, KwArgs, Callable[[Args], Tuple[Args, KwArgs]]]: # We want to bind *args and **kwargs based on the provided signature, but also to associate the # resulting positional arguments back. To achieve this, we lift arguments to a triple: @@ -192,10 +195,10 @@ def map_args_back(out_args): def _split_tensor_and_others( mixed_tuple: Tuple[Any, ...], -) -> Tuple[pytree.PyTreeSpec, Tuple[bool, ...], Tuple[torch.Tensor, ...], Tuple[Any, ...]]: +) -> Tuple[pytree.PyTreeSpec, Tuple[bool, ...], TupleOfTensors, Tuple[Any, ...]]: flattened: List[Any] flattened, treespec = pytree.tree_flatten(mixed_tuple, none_is_leaf=True) # type: ignore[arg-type] - tensors: List[torch.Tensor] = [] + tensors: ListOfTensors = [] non_tensors: List[Any] = [] is_tensor_mask: List[bool] = [] for item in flattened: @@ -211,9 +214,9 @@ def _split_tensor_and_others( def _merge_tensor_and_others( treespec: pytree.PyTreeSpec, is_tensor_mask: Tuple[bool, ...], - tensors: Tuple[torch.Tensor, ...], + tensors: TupleOfTensors, non_tensors: Tuple[Any, ...], -) -> Any: +) -> Tuple[Any, ...]: tensor_counter = 0 non_tensor_counter = 0 results = [] @@ -224,18 +227,18 @@ def _merge_tensor_and_others( else: results.append(non_tensors[non_tensor_counter]) non_tensor_counter += 1 - return pytree.tree_unflatten(treespec, results) + return pytree.tree_unflatten(treespec, results) # type: ignore[return-value] # pylint: disable-next=too-many-arguments,too-many-statements def _custom_root( - solver_fn: Callable, - optimality_fn: Callable, - solve: Callable, + solver_fn: Callable[..., Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]], + optimality_fn: Callable[..., TensorOrTensors], + solve: Callable[..., TensorOrTensors], argnums: Tuple[int, ...], has_aux: bool, reference_signature: Optional[Union[inspect.Signature, Callable]] = None, -) -> Callable: +) -> Callable[..., Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]]: solver_fn_signature = inspect.signature(solver_fn) if reference_signature is None: @@ -246,21 +249,45 @@ def _custom_root( fn = getattr(reference_signature, 'subfn', reference_signature) reference_signature = inspect.signature(fn) - def make_custom_vjp_solver_fn(solver_fn, kwarg_keys, args_sign): + def make_custom_vjp_solver_fn( + solver_fn: Callable[..., Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]], + kwarg_keys: Sequence[str], + args_signs: Tuple[Tuple[int, Optional[Union[Type[tuple], Type[list]]]], ...], + ) -> Type[Function]: # pylint: disable-next=missing-class-docstring,abstract-method class ImplicitMetaGradient(Function): @staticmethod - def forward(ctx, *flat_args): # pylint: disable=arguments-differ + def forward( # type: ignore[override] # pylint: disable=arguments-differ + ctx, *flat_args: Any + ) -> Tuple[Any, ...]: + output, aux, output_is_tensor = None, None, False + args = [] - for idx, (start_point, is_tuple) in enumerate(args_sign): - if is_tuple: - args.append(tuple(flat_args[start_point : args_sign[idx + 1][0]])) + for idx, (offset, arg_seq_type) in enumerate(args_signs): + if arg_seq_type is not None: + args.append(arg_seq_type(flat_args[offset : args_signs[idx + 1][0]])) else: - args.append(flat_args[start_point]) + args.append(flat_args[offset]) args = tuple(args) args, kwargs = _extract_kwargs(kwarg_keys, args) - res = solver_fn(*args, **kwargs) + output = solver_fn(*args, **kwargs) + if has_aux: + if not (isinstance(output, tuple) and len(output) == 2): + raise RuntimeError( + 'custom_root(optimality_fn)(solver_fn)(*args): output of function ' + 'solver_fn should be a tuple: (output, aux) if has_aux is True' + ) + output, aux = output + if isinstance(output, torch.Tensor): + output_is_tensor = True + output = (output,) + elif not (isinstance(output, tuple) and all(map(torch.is_tensor, output))): + raise RuntimeError( + 'custom_root(optimality_fn)(solver_fn)(*args): output of function ' + 'solver_fn should be a torch.Tensor or a tuple of torch.Tensor' + ) + ( args_treespec, args_is_tensor_mask, @@ -270,34 +297,21 @@ def forward(ctx, *flat_args): # pylint: disable=arguments-differ ctx.args_treespec = args_treespec ctx.args_is_tensor_mask = args_is_tensor_mask ctx.args_non_tensors = args_non_tensors - if has_aux: - res, aux = res - if torch.is_tensor(res): - ctx.save_for_backward(res, *args_tensors) - ctx.result_is_tensor = True - return (res, aux, True, torch.tensor) - - ctx.save_for_backward(*res, *args_tensors) - ctx.result_is_tensor = False - return (*res, aux, False, type(res)) - - if isinstance(res, torch.Tensor): - ctx.save_for_backward(res, *args_tensors) - else: - ctx.save_for_backward(*res, *args_tensors) - ctx.result_is_tensor = isinstance(res, torch.Tensor) - return res + + ctx.save_for_backward(*output, *args_tensors) + ctx.output_is_tensor = output_is_tensor + + return (*output, aux, output_is_tensor, type(output)) @staticmethod - def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals - if has_aux: - grad_outputs = grad_outputs[:-3] + def backward( # pylint: disable=too-many-locals + ctx, *grad_outputs: Any + ) -> TupleOfTensors: + grad_outputs: TupleOfTensors = grad_outputs[:-3] saved_tensors = ctx.saved_tensors - res, args_tensors = ( - saved_tensors[: len(grad_outputs)], - saved_tensors[len(grad_outputs) :], - ) + output = saved_tensors[: len(grad_outputs)] + args_tensors = saved_tensors[len(grad_outputs) :] args_treespec = ctx.args_treespec args_is_tensor_mask = ctx.args_is_tensor_mask args_non_tensors = ctx.args_non_tensors @@ -307,7 +321,6 @@ def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals args, kwargs = _extract_kwargs(kwarg_keys, args) - solution = res bound_args, bound_kwargs, map_args_back = _signature_bind_and_match( reference_signature, *args, **kwargs # type: ignore[arg-type] ) @@ -323,74 +336,81 @@ def backward(ctx, *grad_outputs): # pylint: disable=too-many-locals # Compute VJPs w.r.t. args. vjps = _root_vjp( optimality_fn=optimality_fn, - solution=solution, + solution=output, args=bound_args[1:], grad_outputs=grad_outputs, - result_is_tensor=ctx.result_is_tensor, + output_is_tensor=ctx.output_is_tensor, argnums=argnums, solve=solve, ) - # Prepend None as the vjp for init_params. args_vjps, kwargs_vjps = map_args_back(vjps) ordered_vjps = tuple(args_vjps) + tuple(kwargs_vjps[k] for k in kwargs.keys()) true_vjps = [] - for (_, is_tuple), vjp in zip(args_sign, ordered_vjps): - if is_tuple: - for item in vjp: - true_vjps.append(item) + for (_, arg_seq_type), vjp in zip(args_signs, ordered_vjps): + if arg_seq_type is not None: + true_vjps.extend(vjp) else: true_vjps.append(vjp) return tuple(true_vjps) return ImplicitMetaGradient - def wrapped_solver_fn(*args, **kwargs): + def wrapped_solver_fn( + *args: Any, **kwargs: Any + ) -> Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]: args, kwargs = _signature_bind(solver_fn_signature, *args, **kwargs) keys, vals = list(kwargs.keys()), list(kwargs.values()) - args_sign = [] - flat_args = [] + args_signs: List[Tuple[int, Optional[Union[Type[tuple], Type[list]]]]] = [] + flat_args: List[Any] = [] args_counter = 0 for idx, arg in enumerate(args): if idx in argnums: if isinstance(arg, torch.Tensor): - args_sign.append((args_counter, False)) # start position, is_tuple + args_signs.append((args_counter, None)) # start position, None flat_args.append(arg) args_counter += 1 - elif isinstance(arg, tuple): - args_sign.append((args_counter, True)) # start position, is_tuple - for arg_item in arg: - flat_args.append(arg_item) + elif isinstance(arg, (tuple, list)) and all(map(torch.is_tensor, arg)): + args_signs.append((args_counter, type(arg))) # start position, sequence type + flat_args.extend(arg) args_counter += len(arg) else: - raise RuntimeError('must be tensor or tensor tuple') + raise RuntimeError( + 'custom_root(optimality_fn)(solver_fn)(*args): argument of function ' + 'solver_fn specified with `argnums` should be a torch.Tensor or a tuple of ' + 'torch.Tensor' + ) else: - args_sign.append((args_counter, False)) # start position, is_tuple + args_signs.append((args_counter, None)) # start position, None flat_args.append(arg) args_counter += 1 - args_sign = tuple(args_sign) + args_signs = tuple(args_signs) flat_args = tuple(flat_args) - result = make_custom_vjp_solver_fn(solver_fn, keys, args_sign).apply(*flat_args, *vals) + result = make_custom_vjp_solver_fn(solver_fn, keys, args_signs).apply(*flat_args, *vals) + *output, aux, output_is_tensor, output_type = result + if output_is_tensor: + output = output[0] + else: + output = output_type(output) if has_aux: - *res, aux, result_is_tensor, res_type = result - if result_is_tensor: - return res[0], aux - res = res_type(res) - return res, aux - return result + return output, aux + return output return wrapped_solver_fn def custom_root( - optimality_fn: Callable, - argnums: Union[int, Tuple[int, ...]] = 0, + optimality_fn: Callable[..., TensorOrTensors], + argnums: Union[int, Tuple[int, ...]], has_aux: bool = False, - solve: Callable = linear_solve.solve_normal_cg(), -) -> Callable[[Callable], Callable]: + solve: Callable[..., TensorOrTensors] = linear_solve.solve_normal_cg(), +) -> Callable[ + [Callable[..., Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]]], + Callable[..., Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]], +]: """Decorator for adding implicit differentiation to a root solver. This wrapper should be used as a decorator: @@ -406,6 +426,8 @@ def solver_fn(params, arg1, arg2, ...): ... return optimal_params + optimal_params = solver_fn(init_params, ...) + The first argument to ``optimality_fn`` and ``solver_fn`` is preserved as the parameter input. The ``argnums`` argument refers to the indices of the variables in ``solver_fn``'s signature. For example, setting ``argnums=(1, 2)`` will compute the gradient of ``optimal_params`` with @@ -417,7 +439,7 @@ def solver_fn(params, arg1, arg2, ...): optimality_fn: (callable) An equation function, ``optimality_fn(params, *args)``. The invariant is ``optimality_fn(solution, *args) == 0`` at the solution / root of ``solution``. - argnums: (int or tuple of int, default: :const:`0`) + argnums: (int or tuple of ints) Specifies arguments to compute gradients with respect to. The ``argnums`` can be an integer or a tuple of integers, which respect to the zero-based indices of the arguments of the ``solver_fn(params, *args)`` function. The argument ``params`` is included diff --git a/torchopt/diff/implicit/nn/__init__.py b/torchopt/diff/implicit/nn/__init__.py new file mode 100644 index 00000000..6d30ffc2 --- /dev/null +++ b/torchopt/diff/implicit/nn/__init__.py @@ -0,0 +1,20 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""The base class for differentiable implicit meta-gradient models.""" + +from torchopt.diff.implicit.nn.module import ImplicitMetaGradientModule + + +__all__ = ['ImplicitMetaGradientModule'] diff --git a/torchopt/diff/implicit/nn/module.py b/torchopt/diff/implicit/nn/module.py new file mode 100644 index 00000000..3b08118a --- /dev/null +++ b/torchopt/diff/implicit/nn/module.py @@ -0,0 +1,283 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""The base class for differentiable implicit meta-gradient models.""" + +import functools +import itertools +from typing import Callable, Dict, Optional, Tuple + +import functorch +import torch + +import torchopt.nn +from torchopt import pytree +from torchopt.diff.implicit.decorator import custom_root +from torchopt.typing import TensorTree, TupleOfTensors +from torchopt.utils import extract_module_containers + + +__all__ = ['ImplicitMetaGradientModule'] + + +def make_optimality_from_objective( + objective: Callable[..., torch.Tensor] +) -> Callable[..., TupleOfTensors]: + """Make a function that computes the optimality function of the objective function.""" + # pylint: disable-next=redefined-builtin + def optimality(self: 'ImplicitMetaGradientModule', *input, **kwargs) -> TupleOfTensors: + params_containers = extract_module_containers(self, with_buffers=False)[0] + params_containers_backups = [container.copy() for container in params_containers] + flat_params: TupleOfTensors + # pylint: disable-next=line-too-long + flat_params, params_containers_treespec = pytree.tree_flatten_as_tuple(params_containers) # type: ignore[arg-type] + + # pylint: disable-next=redefined-builtin + def objective_fn(flat_params: TupleOfTensors, *input, **kwargs) -> torch.Tensor: + flat_grad_tracking_params = flat_params + grad_tracking_params_containers: Tuple[ + Dict[str, Optional[torch.Tensor]], ... + ] = pytree.tree_unflatten( # type: ignore[assignment] + params_containers_treespec, flat_grad_tracking_params + ) + + try: + for container, grad_tracking_container in zip( + params_containers, grad_tracking_params_containers + ): + container.update(grad_tracking_container) + + return objective(self, *input, **kwargs) + finally: + for container, container_backup in zip( + params_containers, params_containers_backups + ): + container.update(container_backup) + + objective_grad_fn = functorch.grad(objective_fn, argnums=0) + flat_grads = objective_grad_fn(flat_params, *input, **kwargs) + return flat_grads + + return optimality + + +def enable_implicit_gradients( + solve: Callable[..., 'ImplicitMetaGradientModule'] +) -> Callable[..., 'ImplicitMetaGradientModule']: + """Enable implicit gradients for the :func:`solve` function.""" + if getattr(solve, '__implicit_gradients_enabled__', False): + raise ValueError('Implicit gradients are already enabled for the solve function.') + + @functools.wraps(solve) + def wrapped( # pylint: disable=too-many-locals + self: 'ImplicitMetaGradientModule', *input, **kwargs # pylint: disable=redefined-builtin + ) -> 'ImplicitMetaGradientModule': + """Solve the optimization problem.""" + params_containers = extract_module_containers(self, with_buffers=False)[0] + meta_params_containers = [self._meta_parameters] # pylint: disable=protected-access + for meta_module in self.meta_children(): + meta_params_containers.extend( + extract_module_containers(meta_module, with_buffers=False)[0] + ) + meta_params_containers = tuple(meta_params_containers) + params_containers_backups = tuple(container.copy() for container in params_containers) + meta_params_containers_backups = tuple( + container.copy() for container in meta_params_containers + ) + + flat_params: TupleOfTensors + flat_meta_params: TupleOfTensors + flat_params, params_containers_treespec = pytree.tree_flatten_as_tuple( + params_containers # type: ignore[arg-type] + ) + flat_meta_params, meta_params_containers_treespec = pytree.tree_flatten_as_tuple( + meta_params_containers # type: ignore[arg-type] + ) + + def optimality_fn( + flat_params: TupleOfTensors, + flat_meta_params: TupleOfTensors, + *input, # pylint: disable=redefined-builtin + **kwargs, + ) -> TupleOfTensors: + flat_grad_tracking_params = flat_params + grad_tracking_params_containers: Tuple[ + Dict[str, Optional[torch.Tensor]], ... + ] = pytree.tree_unflatten( # type: ignore[assignment] + params_containers_treespec, flat_grad_tracking_params + ) + flat_grad_tracking_meta_params = flat_meta_params + grad_tracking_meta_params_containers: Tuple[ + Dict[str, Optional[torch.Tensor]], ... + ] = pytree.tree_unflatten( # type: ignore[assignment] + meta_params_containers_treespec, flat_grad_tracking_meta_params + ) + + try: + for container, grad_tracking_container in itertools.chain( + zip(params_containers, grad_tracking_params_containers), + zip(meta_params_containers, grad_tracking_meta_params_containers), + ): + container.update(grad_tracking_container) + + return self.optimality(*input, **kwargs) + finally: + for container, container_backup in itertools.chain( + zip(params_containers, params_containers_backups), + zip(meta_params_containers, meta_params_containers_backups), + ): + container.update(container_backup) + + @custom_root(optimality_fn, argnums=1) + def solve_fn( + flat_params: TupleOfTensors, # pylint: disable=unused-argument + flat_meta_params: TupleOfTensors, # pylint: disable=unused-argument + *input, # pylint: disable=redefined-builtin + **kwargs, + ) -> TupleOfTensors: + solve(self, *input, **kwargs) + return tuple(pytree.tree_leaves(params_containers)) # type: ignore[arg-type] + + # pylint: disable-next=unused-variable + flat_optimal_params = solve_fn(flat_params, flat_meta_params, *input, **kwargs) + return self + + wrapped.__implicit_gradients_enabled__ = True # type: ignore[attr-defined] + return wrapped + + +class ImplicitMetaGradientModule(torchopt.nn.MetaGradientModule): + """The base class for differentiable implicit meta-gradient models.""" + + _custom_optimality: bool + _custom_objective: bool + + def __init_subclass__(cls) -> None: + """Initialize the subclass.""" + super().__init_subclass__() + + optimality = getattr(cls, 'optimality', ImplicitMetaGradientModule.optimality) + objective = getattr(cls, 'objective', ImplicitMetaGradientModule.objective) + cls._custom_optimality = optimality is not ImplicitMetaGradientModule.optimality + cls._custom_objective = objective is not ImplicitMetaGradientModule.objective + + if cls._custom_optimality: + if isinstance(optimality, staticmethod): + raise TypeError('optimality() must not be a staticmethod.') + if isinstance(optimality, classmethod): + raise TypeError('optimality() must not be a classmethod.') + if not callable(optimality): + raise TypeError('optimality() must be callable.') + elif not cls._custom_objective: + raise TypeError( + 'ImplicitMetaGradientModule requires either an optimality() or an objective() function' + ) + else: + if isinstance(objective, staticmethod): + raise TypeError('objective() must not be a staticmethod.') + if isinstance(objective, classmethod): + raise TypeError('objective() must not be a classmethod.') + if not callable(objective): + raise TypeError('objective() must be callable.') + + cls.optimality = make_optimality_from_objective(objective) # type: ignore[assignment] + + cls.solve = enable_implicit_gradients(cls.solve) # type: ignore[assignment] + + # pylint: disable-next=redefined-builtin + def solve(self, *input, **kwargs) -> 'ImplicitMetaGradientModule': + """Solves the inner optimization problem. + + .. warning:: + + For gradient-based optimization methods, the parameter inputs should be explicitly + specified in the :func:`torch.autograd.backward` function as argument ``inputs``. + Otherwise, if not provided, the gradient is accumulated into all the leaf Tensors + (including the meta-parameters) that were used to compute the objective output. + Alternatively, please use :func:`torch.autograd.grad` instead. + + Example:: + + def solve(self, batch, labels): + parameters = tuple(self.parameters()) + optimizer = torch.optim.Adam(parameters, lr=1e-3) + with torch.enable_grad(): + for _ in range(100): + loss = self.objective(batch, labels) + optimizer.zero_grad() + # Only update the `.grad` attribute for parameters + # and leave the meta-parameters unchanged + loss.backward(inputs=parameters) + optimizer.step() + return self + + Returns: + The module itself after solving the inner optimization problem. + """ + raise NotImplementedError # update parameters + + # pylint: disable-next=redefined-builtin + def optimality(self, *input, **kwargs) -> TensorTree: + r"""Computes the optimality residual. + + This method stands for the optimality residual to the optimal parameters after solving the + inner optimization problem (:meth:`solve`), i.e.: + + .. code-block:: python + + module.solve(*input, **kwargs) + module.optimality(*input, **kwargs) # -> 0 + + 1. For gradient-based optimization, the :meth:`optimality` function is the KKT condition, + usually it is the gradients of the :meth:`objective` function with respect to the module + parameters (not the meta-parameters). If this method is not implemented, it will be + automatically derived from the gradient of the :meth:`objective` function. + + .. math:: + + \text{optimality residual} = \nabla_{\boldsymbol{x}} f (\boldsymbol{x}, \boldsymbol{\theta}) \to \boldsymbol{0} + + where :math:`\boldsymbol{x}` is the joint vector of the module parameters and + :math:`\boldsymbol{\theta}` is the joint vector of the meta-parameters. + + References: + - Karush-Kuhn-Tucker (KKT) conditions: https://en.wikipedia.org/wiki/Karush-Kuhn-Tucker_conditions + + 2. For fixed point iteration, the :meth:`optimality` function can be the residual of the + parameters between iterations, i.e.: + + .. math:: + + \text{optimality residual} = f (\boldsymbol{x}, \boldsymbol{\theta}) - \boldsymbol{x} \to \boldsymbol{0} + + where :math:`\boldsymbol{x}` is the joint vector of the module parameters and + :math:`\boldsymbol{\theta}` is the joint vector of the meta-parameters. + + Returns: + A tree of tensors, the optimality residual to the optimal parameters after solving the + inner optimization problem. + """ # pylint: disable=line-too-long + raise NotImplementedError + + # pylint: disable-next=redefined-builtin + def objective(self, *input, **kwargs) -> torch.Tensor: + """Computes the objective function value. + + This method is used to calculate the :meth:`optimality` if it is not implemented. + Otherwise, this method is optional. + + Returns: + A scalar tensor (``dim=0``), the objective function value. + """ + raise NotImplementedError diff --git a/torchopt/distributed/autograd.py b/torchopt/distributed/autograd.py index 9425b4a5..41b6b461 100644 --- a/torchopt/distributed/autograd.py +++ b/torchopt/distributed/autograd.py @@ -15,12 +15,14 @@ """Distributed Autograd.""" from threading import Lock -from typing import Optional, Sequence, Tuple, Union +from typing import Optional, overload import torch import torch.distributed.autograd as autograd from torch.distributed.autograd import context +from torchopt.typing import TensorOrTensors, TupleOfOptionalTensors, TupleOfTensors + __all__ = ['is_available', 'context'] @@ -34,14 +36,14 @@ def is_available(): if is_available(): - # pylint: disable-next=unused-import + # pylint: disable-next=unused-import,ungrouped-imports from torch.distributed.autograd import DistAutogradContext, get_gradients def backward( autograd_ctx_id: int, - tensors: Union[torch.Tensor, Sequence[torch.Tensor]], + tensors: TensorOrTensors, retain_graph: bool = False, - inputs: Optional[Union[torch.Tensor, Sequence[torch.Tensor]]] = None, + inputs: Optional[TensorOrTensors] = None, ) -> None: """Perform distributed backward pass for local parameters. @@ -83,13 +85,32 @@ def backward( else: p.grad = g + @overload + def grad( + autograd_ctx_id: int, + outputs: TensorOrTensors, + inputs: TensorOrTensors, + retain_graph: bool = False, + ) -> TupleOfTensors: + ... + + @overload + def grad( + autograd_ctx_id: int, + outputs: TensorOrTensors, + inputs: TensorOrTensors, + retain_graph: bool = False, + allow_unused: bool = False, + ) -> TupleOfOptionalTensors: + ... + def grad( autograd_ctx_id: int, - outputs: Union[torch.Tensor, Sequence[torch.Tensor]], - inputs: Union[torch.Tensor, Sequence[torch.Tensor]], + outputs: TensorOrTensors, + inputs: TensorOrTensors, retain_graph: bool = False, allow_unused: bool = False, - ) -> Tuple[torch.Tensor, ...]: + ) -> TupleOfOptionalTensors: """Computes and returns the sum of gradients of outputs with respect to the inputs. Args: diff --git a/torchopt/linear_solve/normal_cg.py b/torchopt/linear_solve/normal_cg.py index 63e74e80..78ca75f2 100644 --- a/torchopt/linear_solve/normal_cg.py +++ b/torchopt/linear_solve/normal_cg.py @@ -47,7 +47,7 @@ def _solve_normal_cg( matvec: Callable[[TensorTree], TensorTree], # (x) -> A @ x b: TensorTree, - is_sdp: bool = False, + is_spd: bool = False, ridge: Optional[float] = None, init: Optional[TensorTree] = None, **kwargs, @@ -60,7 +60,7 @@ def _solve_normal_cg( Args: matvec: A function that returns the product between ``A`` and a vector. b: A tree of tensors for the right hand side of the equation. - is_sdp: Whether to assume matrix ``A`` is symmetric definite positive to speedup computation. + is_spd: Whether to assume matrix ``A`` is symmetric definite positive to speedup computation. ridge: Optional ridge regularization. Solves the equation for ``(A.T @ A + ridge * I) @ x = A.T @ b``. init: Optional initialization to be used by normal conjugate gradient. **kwargs: Additional keyword arguments for the conjugate gradient solver. @@ -73,9 +73,9 @@ def _solve_normal_cg( else: example_x = init - if is_sdp: + if is_spd: if ridge is not None: - raise ValueError('ridge must be specified with `is_sdp=False`.') + raise ValueError('ridge must be specified with `is_spd=False`.') # Returns solution for `A @ x = b`. return linalg.cg(matvec, b, x0=init, **kwargs) @@ -96,5 +96,5 @@ def _solve_normal_cg( def solve_normal_cg(**kwargs): """Wrapper for :func:`solve_normal_cg`.""" partial_fn = functools.partial(_solve_normal_cg, **kwargs) - setattr(partial_fn, 'is_sdp', kwargs.get('is_sdp', False)) + setattr(partial_fn, 'is_spd', kwargs.get('is_spd', False)) return partial_fn diff --git a/torchopt/nn/__init__.py b/torchopt/nn/__init__.py new file mode 100644 index 00000000..3cb7fc78 --- /dev/null +++ b/torchopt/nn/__init__.py @@ -0,0 +1,17 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Base class for neural network modules that hold meta-parameters and meta-modules.""" + +from torchopt.nn.module import MetaGradientModule diff --git a/torchopt/nn/module.py b/torchopt/nn/module.py new file mode 100644 index 00000000..982fd57c --- /dev/null +++ b/torchopt/nn/module.py @@ -0,0 +1,458 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Base class for neural network modules that hold meta-parameters and meta-modules.""" + +from collections import OrderedDict +from typing import Any, Dict, Iterator, List, NamedTuple, Optional, Set, Tuple, Union + +import torch +import torch.nn as nn + +from torchopt import pytree + + +class MetaInputsContainer(NamedTuple): + """Container for parameters and modules in the constructor input arguments.""" + + meta_parameters: Set[torch.Tensor] + meta_modules: Set[nn.Module] + + +class MetaGradientModule(nn.Module): # pylint: disable=abstract-method + """Base class for neural network modules that hold meta-parameters and meta-modules.""" + + _meta_inputs: MetaInputsContainer + _meta_parameters: Dict[str, Optional[torch.Tensor]] + _meta_modules: Dict[str, Optional[nn.Module]] + + def __new__(cls, *args, **kwargs) -> 'MetaGradientModule': + """Creates a new module instance.""" + instance = super().__new__(cls) + flat_args: List[Any] + flat_args = pytree.tree_leaves((args, kwargs)) # type: ignore[arg-type] + meta_parameters = set( + x for x in flat_args if isinstance(x, torch.Tensor) and x.requires_grad + ) + meta_modules = set(x for x in flat_args if isinstance(x, nn.Module) and x.training) + for meta_module in tuple(meta_modules): + meta_parameters.update(meta_module.parameters()) + meta_modules.update(meta_module.modules()) + + instance._meta_inputs = MetaInputsContainer(meta_parameters, meta_modules) + instance._meta_parameters: Dict[str, Optional[torch.Tensor]] = OrderedDict() # type: ignore[misc] + instance._meta_modules: Dict[str, Optional[nn.Module]] = OrderedDict() # type: ignore[misc] + return instance + + def __getattr__(self, name: str) -> Union[torch.Tensor, nn.Module]: + """Gets an attribute of the module.""" + if '_parameters' in self.__dict__: + _parameters = self.__dict__['_parameters'] + if name in _parameters: + return _parameters[name] + if '_buffers' in self.__dict__: + _buffers = self.__dict__['_buffers'] + if name in _buffers: + return _buffers[name] + if '_modules' in self.__dict__: + modules = self.__dict__['_modules'] + if name in modules: + return modules[name] + if '_meta_parameters' in self.__dict__: + _meta_parameters = self.__dict__['_meta_parameters'] + if name in _meta_parameters: + return _meta_parameters[name] + if '_meta_modules' in self.__dict__: + _meta_modules = self.__dict__['_meta_modules'] + if name in _meta_modules: + return _meta_modules[name] + raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") + + # pylint: disable-next=too-many-branches,too-many-statements + def __setattr__(self, name: str, value: Union[torch.Tensor, nn.Module]) -> None: + """Sets an attribute of the module.""" + + def remove_from(*dicts_or_sets): + for dict_or_set in dicts_or_sets: + if name in dict_or_set: + if isinstance(dict_or_set, dict): + del dict_or_set[name] + else: + dict_or_set.discard(name) + + params = self.__dict__.get('_parameters') + meta_params = self.__dict__.get('_meta_parameters') + if isinstance(value, torch.Tensor) and value.requires_grad: + if params is None: + raise AttributeError('cannot assign parameters before Module.__init__() call') + if meta_params is None: + raise AttributeError( + 'cannot assign meta-parameters before MetaGradientModule.__init__() call' + ) + remove_from( + self.__dict__, + self._buffers, + self._modules, + self._non_persistent_buffers_set, + self._meta_parameters, + self._meta_modules, + ) + if value in self._meta_inputs.meta_parameters: + self.register_meta_parameter(name, value) + else: + self.register_parameter(name, value) + elif params is not None and name in params: + if value is not None: + raise TypeError( + f"cannot assign '{torch.typename(value)}' as parameter '{name}' " + f'(torch.Tensor or None expected)' + ) + self.register_parameter(name, value) # type: ignore[unreachable] + elif meta_params is not None and name in meta_params: + if value is not None: + raise TypeError( + f"cannot assign '{torch.typename(value)}' as meta-parameter '{name}' " + f'(torch.Tensor or None expected)' + ) + self.register_meta_parameter(name, value) # type: ignore[unreachable] + else: + modules = self.__dict__.get('_modules') + meta_modules = self.__dict__.get('_meta_modules') + if isinstance(value, nn.Module): + if modules is None: + raise AttributeError('cannot assign module before Module.__init__() call') + if meta_modules is None: + raise AttributeError( + 'cannot assign module before MetaGradientModule.__init__() call' + ) + remove_from( + self.__dict__, + self._parameters, + self._buffers, + self._non_persistent_buffers_set, + self._meta_parameters, + self._meta_modules, + ) + if value in self._meta_inputs.meta_modules: + meta_modules[name] = value + else: + modules[name] = value + elif modules is not None and name in modules: + if value is not None: + raise TypeError( + f"cannot assign '{torch.typename(value)}' as child module '{name}' " + f'(torch.nn.Module or None expected)' + ) + modules[name] = value # type: ignore[unreachable] + else: + buffers = self.__dict__.get('_buffers') + if buffers is not None and name in buffers: + if value is not None and not isinstance(value, torch.Tensor): + raise TypeError( + f"cannot assign '{torch.typename(value)}' as buffer '{name}' " + f'(torch.Tensor or None expected)' + ) + buffers[name] = value + else: + object.__setattr__(self, name, value) + + def __delattr__(self, name: str) -> None: + """Deletes an attribute of the module.""" + if name in self._parameters: + del self._parameters[name] + elif name in self._buffers: + del self._buffers[name] + self._non_persistent_buffers_set.discard(name) + elif name in self._modules: + del self._modules[name] + elif name in self._meta_parameters: + del self._meta_parameters[name] + elif name in self._meta_modules: + del self._meta_modules[name] + else: + object.__delattr__(self, name) + + def register_parameter(self, name: str, param: Optional[torch.Tensor]) -> None: + r"""Adds a parameter to the module. + + The parameter can be accessed as an attribute using given name. + + Args: + name (string): name of the parameter. The parameter can be accessed + from this module using the given name + param (torch.Tensor or None): parameter to be added to the module. If + ``None``, then operations that run on parameters, such as :attr:`cuda`, + are ignored. If ``None``, the parameter is **not** included in the + module's :attr:`state_dict`. + """ + if '_parameters' not in self.__dict__: + raise AttributeError('cannot assign parameter before Module.__init__() call') + if not isinstance(name, str): + raise TypeError(f'parameter name should be a string. Got {torch.typename(name)}') + if '.' in name: + raise KeyError("parameter name can't contain \".\"") + if name == '': + raise KeyError("parameter name can't be empty string \"\"") + if hasattr(self, name) and name not in self._parameters: + raise KeyError(f"attribute '{name}' already exists") + + if param is None: + self._parameters[name] = None + return + + if not isinstance(param, torch.Tensor): + raise TypeError( + f"cannot assign '{torch.typename(param)}' object to parameter '{name}' " + f'(torch.Tensor or None required)' + ) + if not param.requires_grad: + raise ValueError( + f"cannot assign Tensor that `requires_grad=False` to parameter '{name}'" + ) + if param in self._meta_inputs.meta_parameters: + raise ValueError( + f"cannot assign Tensor that is a meta-parameter to parameter '{name}'. " + f'Use self.register_meta_parameter() instead.' + ) + + self._parameters[name] = param # type: ignore + + def register_meta_parameter(self, name: str, param: Optional[torch.Tensor]) -> None: + r"""Adds a meta-parameter to the module. + + The meta-parameter can be accessed as an attribute using given name. + + Args: + name (string): name of the parameter. The parameter can be accessed + from this module using the given name + param (torch.Tensor or None): parameter to be added to the module. If + ``None``, then operations that run on parameters, such as :attr:`cuda`, + are ignored. If ``None``, the parameter is **not** included in the + module's :attr:`state_dict`. + """ + if '_meta_parameters' not in self.__dict__: + raise AttributeError( + 'cannot assign meta-parameter before MetaGradientModule.__init__() call' + ) + if not isinstance(name, str): + raise TypeError(f'meta-parameter name should be a string. Got {torch.typename(name)}') + if '.' in name: + raise KeyError("meta-parameter name can't contain \".\"") + if name == '': + raise KeyError("meta-parameter name can't be empty string \"\"") + if hasattr(self, name) and name not in self._meta_parameters: + raise KeyError(f"attribute '{name}' already exists") + + if param is None: + self._meta_parameters[name] = None + return + + if not isinstance(param, torch.Tensor): + raise TypeError( + f"cannot assign '{torch.typename(param)}' object to meta-parameter '{name}' " + f'(torch.Tensor or None required)' + ) + if not param.requires_grad: + raise ValueError( + f"cannot assign Tensor that `requires_grad=False` to meta-parameter '{name}'" + ) + + self._meta_parameters[name] = param + + def add_module(self, name: str, module: Optional[nn.Module]) -> None: + r"""Adds a child module to the current module. + + The module can be accessed as an attribute using the given name. + + Args: + name (string): name of the child module. The child module can be + accessed from this module using the given name + module (Module): child module to be added to the module. + """ + if not isinstance(module, nn.Module) and module is not None: + raise TypeError(f'{torch.typename(module)} is not a Module subclass') + if not isinstance(name, str): + raise TypeError(f'module name should be a string. Got {torch.typename(name)}') + if hasattr(self, name) and name not in self._modules: + raise KeyError(f"attribute '{name}' already exists") + if '.' in name: + raise KeyError(f"module name can't contain \".\", got: {name}") + if name == '': + raise KeyError("module name can't be empty string \"\"") + if module in self._meta_inputs.meta_modules: + raise ValueError( + f"cannot add module that is a meta-module to module '{name}'. " + f'Use self.add_meta_module() instead.' + ) + + self._modules[name] = module + + def register_module(self, name: str, module: Optional[nn.Module]) -> None: + r"""Alias for :func:`add_module`.""" + self.add_module(name, module) + + def add_meta_module(self, name: str, meta_module: Optional[nn.Module]) -> None: + r"""Adds a child meta-module to the current module. + + The meta-module can be accessed as an attribute using the given name. + + Args: + name (string): name of the child meta-module. The child meta-module can be + accessed from this module using the given name + meta_module (Module): child meta-module to be added to the module. + """ + if not isinstance(meta_module, nn.Module) and meta_module is not None: + raise TypeError(f'{torch.typename(meta_module)} is not a Module subclass') + if not isinstance(name, str): + raise TypeError(f'meta-module name should be a string. Got {torch.typename(name)}') + if hasattr(self, name) and name not in self._meta_modules: + raise KeyError(f"attribute '{name}' already exists") + if '.' in name: + raise KeyError(f"meta-module name can't contain \".\", got: {name}") + if name == '': + raise KeyError("meta-module name can't be empty string \"\"") + + self._meta_modules[name] = meta_module + + def register_meta_module(self, name: str, meta_module: Optional[nn.Module]) -> None: + r"""Alias for :func:`add_meta_module`.""" + self.add_meta_module(name, meta_module) + + def meta_parameters(self, recurse: bool = True) -> Iterator[torch.Tensor]: + r"""Returns an iterator over module meta-parameters. + + This is typically passed to an optimizer. + + Args: + recurse (bool): if True, then yields parameters of this module + and all submodules. Otherwise, yields only meta-parameters that + are direct members of this module. + + Yields: + Parameter: module meta-parameter + + Example:: + + >>> for param in model.meta_parameters(): + >>> print(type(param), param.size()) + (20L,) + (20L, 1L, 5L, 5L) + + """ + for _, meta_param in self.named_meta_parameters(recurse=recurse): + yield meta_param + + def named_meta_parameters( + self, prefix: str = '', recurse: bool = True + ) -> Iterator[Tuple[str, torch.Tensor]]: + r"""Returns an iterator over module meta-parameters, yielding both the name of the meta-parameter as well as the meta-parameter itself. + + Args: + prefix (str): prefix to prepend to all meta-parameter names. + recurse (bool): if True, then yields meta-parameters of this module + and all submodules. Otherwise, yields only meta-parameters that + are direct members of this module. + + Yields: + (string, Parameter): Tuple containing the name and parameter + + Example:: + + >>> for name, meta_param in self.named_meta_parameters(): + >>> if name in ['bias']: + >>> print(meta_param.size()) + + """ # pylint: disable=line-too-long + memo = set() + for name, param in getattr(self, '_meta_parameters', {}).items(): + if param is None or param in memo: + continue + memo.add(param) + yield prefix + name, param + for name, meta_module in getattr(self, '_meta_modules', {}).items(): + if meta_module is None: + continue + submodule_prefix = prefix + name + yield from meta_module.named_parameters(submodule_prefix, recurse) + + def meta_children(self) -> Iterator[nn.Module]: + r"""Returns an iterator over immediate children meta-modules. + + Yields: + Module: a child meta-module + """ + for _, module in self.named_meta_children(): + yield module + + def named_meta_children(self) -> Iterator[Tuple[str, nn.Module]]: + r"""Returns an iterator over immediate children meta-modules, yielding both the name of the meta-module as well as the meta-module itself. + + Yields: + (string, Module): Tuple containing a name and child meta-module + + Example:: + + >>> for name, meta_module in model.named_meta_children(): + >>> if name in ['conv4', 'conv5']: + >>> print(meta_module) + + """ # pylint: disable=line-too-long + memo = set() + for name, meta_module in self._meta_modules.items(): + if meta_module is not None and meta_module not in memo: + memo.add(meta_module) + yield name, meta_module + + def meta_modules(self) -> Iterator[nn.Module]: + r"""Returns an iterator over all meta-modules in the network. + + Yields: + Module: a meta-module in the network + + Note: + Duplicate meta-modules are returned only once. + """ + for _, meta_module in self.named_meta_modules(): + yield meta_module + + def named_meta_modules( + self, memo: Optional[Set[nn.Module]] = None, prefix: str = '', remove_duplicate: bool = True + ) -> Iterator[Tuple[str, nn.Module]]: + r"""Returns an iterator over all meta-modules in the network, yielding both the name of the meta-module as well as the meta-module itself. + + Args: + memo: a memo to store the set of meta-modules already added to the result + prefix: a prefix that will be added to the name of the meta-module + remove_duplicate: whether to remove the duplicated meta-module instances in the result + or not + + Yields: + (string, Module): Tuple of name and meta-module + + Note: + Duplicate modules are returned only once. + """ # pylint: disable=line-too-long + if memo is None: + memo = set() + if self in memo: + return + + if remove_duplicate: + memo.add(self) + + for name, meta_module in self._meta_modules.items(): + if meta_module is None: + continue + submodule_prefix = prefix + ('.' if prefix else '') + name + yield from meta_module.named_modules(memo, submodule_prefix, remove_duplicate) diff --git a/torchopt/optim/adamw.py b/torchopt/optim/adamw.py index 9613cab4..24362d59 100644 --- a/torchopt/optim/adamw.py +++ b/torchopt/optim/adamw.py @@ -20,7 +20,7 @@ from torchopt import alias from torchopt.optim.base import Optimizer -from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import +from torchopt.typing import Params, ScalarOrSchedule __all__ = ['AdamW'] @@ -44,7 +44,7 @@ def __init__( weight_decay: float = 1e-2, *, eps_root: float = 0.0, - mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, maximize: bool = False, use_accelerated_op: bool = False, ) -> None: diff --git a/torchopt/optim/base.py b/torchopt/optim/base.py index 0f666cc1..e19f1187 100644 --- a/torchopt/optim/base.py +++ b/torchopt/optim/base.py @@ -19,11 +19,7 @@ import torch from torchopt import pytree -from torchopt.typing import ( # pylint: disable=unused-import - GradientTransformation, - OptState, - Params, -) +from torchopt.typing import GradientTransformation, OptState, Params, TupleOfTensors from torchopt.update import apply_updates @@ -49,7 +45,7 @@ def __init__(self, params: Iterable[torch.Tensor], impl: GradientTransformation) raise TypeError(f'{impl} (type: {type(impl).__name__}) is not a GradientTransformation') self.impl: GradientTransformation = impl - self.param_groups: List[Tuple[torch.Tensor]] = [] + self.param_groups: List[TupleOfTensors] = [] self.param_treespecs: List[pytree.PyTreeSpec] = [] self.state_groups: List[OptState] = [] @@ -83,11 +79,11 @@ def f(p): pytree.tree_map(f, self.param_groups) # type: ignore[arg-type] - def state_dict(self) -> Tuple['OptState', ...]: + def state_dict(self) -> Tuple[OptState, ...]: """Returns the state of the optimizer.""" return tuple(self.state_groups) - def load_state_dict(self, state_dict: Sequence['OptState']) -> None: + def load_state_dict(self, state_dict: Sequence[OptState]) -> None: """Loads the optimizer state. Args: @@ -120,10 +116,10 @@ def f(p): return loss - def add_param_group(self, params: 'Params') -> None: + def add_param_group(self, params: Params) -> None: """Add a param group to the optimizer's :attr:`param_groups`.""" flat_params, params_treespec = pytree.tree_flatten(params) - flat_params: Tuple[torch.Tensor] = tuple(flat_params) # type: ignore[assignment] + flat_params: TupleOfTensors = tuple(flat_params) self.param_groups.append(flat_params) self.param_treespecs.append(params_treespec) self.state_groups.append(self.impl.init(flat_params)) diff --git a/torchopt/optim/func/base.py b/torchopt/optim/func/base.py index f1d0b684..bb7ebf8b 100644 --- a/torchopt/optim/func/base.py +++ b/torchopt/optim/func/base.py @@ -19,7 +19,7 @@ import torch from torchopt.base import GradientTransformation -from torchopt.typing import OptState, Params # pylint: disable=unused-import +from torchopt.typing import OptState, Params from torchopt.update import apply_updates @@ -61,9 +61,9 @@ def __init__(self, impl: GradientTransformation, *, inplace: bool = False) -> No def step( self, loss: torch.Tensor, - params: 'Params', + params: Params, inplace: Optional[bool] = None, - ) -> 'Params': + ) -> Params: r"""Compute the gradients of loss to the network parameters and update network parameters. Graph of the derivative will be constructed, allowing to compute higher order derivative diff --git a/torchopt/optim/meta/adamw.py b/torchopt/optim/meta/adamw.py index 65e154d3..cb91f38f 100644 --- a/torchopt/optim/meta/adamw.py +++ b/torchopt/optim/meta/adamw.py @@ -20,7 +20,7 @@ from torchopt import alias from torchopt.optim.meta.base import MetaOptimizer -from torchopt.typing import Params, ScalarOrSchedule # pylint: disable=unused-import +from torchopt.typing import Params, ScalarOrSchedule __all__ = ['MetaAdamW'] @@ -44,7 +44,7 @@ def __init__( weight_decay: float = 1e-2, *, eps_root: float = 0.0, - mask: Optional[Union[Any, Callable[['Params'], Any]]] = None, + mask: Optional[Union[Any, Callable[[Params], Any]]] = None, moment_requires_grad: bool = False, maximize: bool = False, use_accelerated_op: bool = False, diff --git a/torchopt/optim/meta/base.py b/torchopt/optim/meta/base.py index 89505111..b83d3fd2 100644 --- a/torchopt/optim/meta/base.py +++ b/torchopt/optim/meta/base.py @@ -20,8 +20,9 @@ import torch.nn as nn from torchopt import pytree -from torchopt.typing import GradientTransformation, OptState +from torchopt.typing import GradientTransformation, OptState, TupleOfTensors from torchopt.update import apply_updates +from torchopt.utils import extract_module_containers __all__ = ['MetaOptimizer'] @@ -67,9 +68,8 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals for i, (param_container, new_state) in enumerate( zip(self.param_containers_groups, self.state_groups) ): - flat_params: Tuple[torch.Tensor, ...] - flat_params, container_treespec = pytree.tree_flatten(param_container) # type: ignore[arg-type,assignment] - flat_params = tuple(flat_params) + flat_params: TupleOfTensors + flat_params, container_treespec = pytree.tree_flatten_as_tuple(param_container) # type: ignore[arg-type] grads = torch.autograd.grad( loss, flat_params, @@ -93,16 +93,13 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals def add_param_group(self, net: nn.Module) -> None: """Add a param group to the optimizer's :attr:`state_groups`.""" - # pylint: disable-next=import-outside-toplevel - from torchopt.utils import _extract_container - - params_container, _ = _extract_container(net, with_buffers=False) - flat_params: Tuple[torch.Tensor, ...] = tuple(pytree.tree_leaves(params_container)) # type: ignore[arg-type] + params_container = extract_module_containers(net, with_buffers=False)[0] + flat_params: TupleOfTensors = tuple(pytree.tree_leaves(params_container)) # type: ignore[arg-type] optimizer_state = self.impl.init(flat_params) self.param_containers_groups.append(params_container) self.state_groups.append(optimizer_state) - def state_dict(self) -> Tuple['OptState', ...]: + def state_dict(self) -> Tuple[OptState, ...]: """Extract the references of the optimizer states. Note that the states are references, so any in-place operations will change the states @@ -110,6 +107,6 @@ def state_dict(self) -> Tuple['OptState', ...]: """ return tuple(self.state_groups) - def load_state_dict(self, state_dict: Sequence['OptState']) -> None: + def load_state_dict(self, state_dict: Sequence[OptState]) -> None: """Load the references of the optimizer states.""" self.state_groups[:] = list(state_dict) diff --git a/torchopt/pytree.py b/torchopt/pytree.py index 3d4dd3c1..65aba6a2 100644 --- a/torchopt/pytree.py +++ b/torchopt/pytree.py @@ -14,6 +14,8 @@ # ============================================================================== """The PyTree utilities.""" +from typing import Callable, List, Optional, Tuple + import optree import optree.typing as typing # pylint: disable=unused-import import torch.distributed.rpc as rpc @@ -22,7 +24,28 @@ from torchopt.typing import Future, PyTree, RRef, T -__all__ = [*optree.__all__, 'tree_wait'] +__all__ = [*optree.__all__, 'tree_flatten_as_tuple', 'tree_wait'] + + +def tree_flatten_as_tuple( + tree: PyTree[T], + is_leaf: Optional[Callable[[T], bool]] = None, + *, + none_is_leaf: bool = False, +) -> Tuple[Tuple[T, ...], PyTreeSpec]: + """Flatten a pytree to a tuple of leaves and a PyTreeSpec. + + Args: + tree: The pytree to flatten. + is_leaf: A function that returns True if a given node is a leaf. + none_is_leaf: If :data:`True`, None is considered a leaf rather than a internal node with no + children. + + Returns: + A tuple of (leaves, treespec). + """ + leaves, treespec = tree_flatten(tree, is_leaf, none_is_leaf=none_is_leaf) + return tuple(leaves), treespec def tree_wait(future_tree: PyTree[Future[T]]) -> PyTree[T]: @@ -59,4 +82,4 @@ def tree_local_value(rref_tree: 'PyTree[RRef[T]]'): __all__.extend(['tree_as_rref', 'tree_to_here']) -del optree, rpc, PyTree, T, RRef +del Callable, List, Optional, Tuple, optree, rpc, PyTree, T, RRef diff --git a/torchopt/transform/scale_by_adam.py b/torchopt/transform/scale_by_adam.py index d618ba91..4ccbdbeb 100644 --- a/torchopt/transform/scale_by_adam.py +++ b/torchopt/transform/scale_by_adam.py @@ -33,14 +33,14 @@ # pylint: disable=invalid-name -from typing import NamedTuple, Sequence +from typing import NamedTuple import torch from torchopt import pytree from torchopt.base import GradientTransformation from torchopt.transform.utils import inc_count, tree_map_flat, update_moment -from torchopt.typing import Updates +from torchopt.typing import SequenceOfTensors, Updates __all__ = ['scale_by_adam', 'scale_by_accelerated_adam'] @@ -54,7 +54,7 @@ class ScaleByAdamState(NamedTuple): mu: Updates nu: Updates - count: Sequence[torch.Tensor] # type: ignore + count: SequenceOfTensors # type: ignore def _bias_correction(moment, decay, count, *, already_flattened=False): diff --git a/torchopt/transform/scale_by_schedule.py b/torchopt/transform/scale_by_schedule.py index 5ec85899..49b6abb7 100644 --- a/torchopt/transform/scale_by_schedule.py +++ b/torchopt/transform/scale_by_schedule.py @@ -31,14 +31,14 @@ # ============================================================================== """Preset transformation for scaling updates by learning rate schedules.""" -from typing import NamedTuple, Sequence +from typing import NamedTuple import torch from torchopt import pytree from torchopt.base import GradientTransformation from torchopt.transform.utils import inc_count, tree_map_flat -from torchopt.typing import Schedule +from torchopt.typing import Schedule, SequenceOfTensors __all__ = ['scale_by_schedule'] @@ -47,7 +47,7 @@ class ScaleByScheduleState(NamedTuple): """Maintains count for scale scheduling.""" - count: Sequence[torch.Tensor] # type: ignore + count: SequenceOfTensors # type: ignore def scale_by_schedule(step_size_fn: Schedule) -> GradientTransformation: diff --git a/torchopt/typing.py b/torchopt/typing.py index 12751f96..f1dcd1dd 100644 --- a/torchopt/typing.py +++ b/torchopt/typing.py @@ -14,7 +14,7 @@ # ============================================================================== """Typing utilities.""" -from typing import Callable, Optional, TypeVar, Union +from typing import Callable, List, Optional, Sequence, Tuple, TypeVar, Union from typing_extensions import TypeAlias # Python 3.10+ import torch.distributed.rpc as rpc @@ -38,7 +38,16 @@ 'ScalarOrSchedule', 'PyTree', 'Tensor', + 'OptionalTensor', + 'ListOfTensors', + 'TupleOfTensors', + 'SequenceOfTensors', + 'TensorOrTensors', 'TensorTree', + 'ListOfOptionalTensors', + 'TupleOfOptionalTensors', + 'SequenceOfOptionalTensors', + 'OptionalTensorOrOptionalTensors', 'OptionalTensorTree', 'Future', ] @@ -51,8 +60,19 @@ Schedule: TypeAlias = Callable[[Numeric], Numeric] ScalarOrSchedule: TypeAlias = Union[float, Schedule] +OptionalTensor = Optional[Tensor] + +ListOfTensors = List[Tensor] +TupleOfTensors = Tuple[Tensor, ...] +SequenceOfTensors = Sequence[Tensor] +TensorOrTensors = Union[Tensor, SequenceOfTensors] TensorTree: TypeAlias = PyTreeTypeVar('TensorTree', Tensor) # type: ignore[valid-type] -OptionalTensorTree: TypeAlias = PyTreeTypeVar('OptionalTensorTree', Optional[Tensor]) # type: ignore[valid-type] + +ListOfOptionalTensors = List[OptionalTensor] +TupleOfOptionalTensors = Tuple[OptionalTensor, ...] +SequenceOfOptionalTensors = Sequence[OptionalTensor] +OptionalTensorOrOptionalTensors = Union[OptionalTensor, SequenceOfOptionalTensors] +OptionalTensorTree: TypeAlias = PyTreeTypeVar('OptionalTensorTree', OptionalTensor) # type: ignore[valid-type] # Parameters are arbitrary nests of `torch.Tensor`. Params: TypeAlias = TensorTree diff --git a/torchopt/update.py b/torchopt/update.py index bdcdc301..85e93673 100644 --- a/torchopt/update.py +++ b/torchopt/update.py @@ -32,13 +32,13 @@ """Helper functions for applying updates.""" from torchopt import pytree -from torchopt.typing import Params, Updates # pylint: disable=unused-import +from torchopt.typing import Params, Updates __all__ = ['apply_updates'] -def apply_updates(params: 'Params', updates: 'Updates', *, inplace: bool = True) -> 'Params': +def apply_updates(params: Params, updates: Updates, *, inplace: bool = True) -> Params: """Applies an update to the corresponding parameters. This is a utility functions that applies an update to a set of parameters, and then returns the diff --git a/torchopt/utils.py b/torchopt/utils.py index 211bcdd6..3301f92c 100644 --- a/torchopt/utils.py +++ b/torchopt/utils.py @@ -35,7 +35,7 @@ import torch.nn as nn from torchopt import pytree -from torchopt.typing import OptState, TensorTree # pylint: disable=unused-import +from torchopt.typing import OptState, TensorTree if TYPE_CHECKING: @@ -64,7 +64,7 @@ class ModuleState(NamedTuple): CopyMode: TypeAlias = Literal['reference', 'copy', 'deepcopy', 'ref', 'clone', 'deepclone'] -def stop_gradient(target: Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer']) -> None: +def stop_gradient(target: Union[TensorTree, ModuleState, nn.Module, 'MetaOptimizer']) -> None: """Stop the gradient for the input object. Since a tensor use :attr:`grad_fn` to connect itself with the previous computation graph, the @@ -123,7 +123,7 @@ def extract_state_dict( with_buffers: bool = True, enable_visual: bool = False, visual_prefix: str = '', -) -> Tuple['OptState', ...]: +) -> Tuple[OptState, ...]: ... @@ -137,7 +137,7 @@ def extract_state_dict( detach_buffers: bool = False, enable_visual: bool = False, visual_prefix: str = '', -) -> Union[ModuleState, Tuple['OptState', ...]]: +) -> Union[ModuleState, Tuple[OptState, ...]]: """Extract target state. Since a tensor use :attr:`grad_fn` to connect itself with the previous computation graph, the @@ -277,12 +277,13 @@ def get_variable(t): raise RuntimeError(f'Unexpected class of {target}') -def _extract_container( +def extract_module_containers( module: nn.Module, with_buffers: bool = True ) -> Tuple[ Tuple[Dict[str, Optional[torch.Tensor]], ...], Tuple[Dict[str, Optional[torch.Tensor]], ...], ]: + """Extract the references to the containers of parameters and buffers from a module.""" if isinstance(module, nn.Module): params: List[Dict[str, Optional[torch.Tensor]]] = [] buffers: List[Dict[str, Optional[torch.Tensor]]] = [] @@ -311,7 +312,7 @@ def update_container(container, items): def recover_state_dict( target: Union[nn.Module, 'MetaOptimizer'], - state: Union[ModuleState, Sequence['OptState']], + state: Union[ModuleState, Sequence[OptState]], ) -> None: """Recover state. @@ -329,7 +330,7 @@ def recover_state_dict( if isinstance(target, nn.Module): params, buffers, *_ = state = cast(ModuleState, state) - params_container, buffers_container = _extract_container(target, with_buffers=True) + params_containers, buffers_containers = extract_module_containers(target, with_buffers=True) if state.detach_buffers: @@ -342,8 +343,8 @@ def clone_detach_(t: torch.Tensor) -> torch.Tensor: ) for tgt, src in itertools.chain( - zip(params_container, params), - zip(buffers_container, buffers), + zip(params_containers, params), + zip(buffers_containers, buffers), ): tgt.update(src) elif isinstance(target, MetaOptimizer): @@ -426,7 +427,7 @@ def module_clone( if isinstance(target, (nn.Module, MetaOptimizer)): if isinstance(target, nn.Module): - containers = cast(TensorTree, _extract_container(target, with_buffers=True)) + containers = cast(TensorTree, extract_module_containers(target, with_buffers=True)) else: containers = cast(TensorTree, target.state_dict()) tensors = pytree.tree_leaves(containers) @@ -477,8 +478,8 @@ def clone_detach_(t: torch.Tensor) -> torch.Tensor: def module_detach_( - target: Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer'] -) -> Union['TensorTree', ModuleState, nn.Module, 'MetaOptimizer']: + target: Union[TensorTree, ModuleState, nn.Module, 'MetaOptimizer'] +) -> Union[TensorTree, ModuleState, nn.Module, 'MetaOptimizer']: """Detach a module from the computation graph. Args: diff --git a/torchopt/visual.py b/torchopt/visual.py index 90f161b5..25a66ada 100644 --- a/torchopt/visual.py +++ b/torchopt/visual.py @@ -19,12 +19,13 @@ import warnings from collections import namedtuple -from typing import Generator, Iterable, Mapping, Optional, Sequence, Union, cast +from typing import Generator, Iterable, Mapping, Optional, Union, cast import torch from graphviz import Digraph from pkg_resources import parse_version +from torchopt.typing import TensorOrTensors from torchopt.utils import ModuleState @@ -71,7 +72,7 @@ def truncate(s): # pylint: disable=invalid-name # pylint: disable-next=too-many-branches,too-many-statements,too-many-locals def make_dot( - var: Union[torch.Tensor, Sequence[torch.Tensor]], + var: TensorOrTensors, params: Optional[ Union[ Mapping[str, torch.Tensor], From 7777f3df47e145ccd0ff5f39c351b4f860891b32 Mon Sep 17 00:00:00 2001 From: Hello_World Date: Tue, 1 Nov 2022 18:00:06 +0800 Subject: [PATCH 35/69] fix(implicit): type mismatch for `is_spd` (#102) Co-authored-by: Xuehai Pan --- torchopt/diff/implicit/decorator.py | 32 ++++++++++++++--------------- torchopt/linear_solve/normal_cg.py | 12 +---------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/torchopt/diff/implicit/decorator.py b/torchopt/diff/implicit/decorator.py index 6f19c196..37a3675a 100644 --- a/torchopt/diff/implicit/decorator.py +++ b/torchopt/diff/implicit/decorator.py @@ -25,7 +25,13 @@ from torch.autograd import Function from torchopt import linear_solve, pytree -from torchopt.typing import ListOfTensors, TensorOrTensors, TupleOfTensors +from torchopt.typing import ( + ListOfOptionalTensors, + ListOfTensors, + TensorOrTensors, + TupleOfOptionalTensors, + TupleOfTensors, +) __all__ = ['custom_root'] @@ -84,7 +90,7 @@ def _root_vjp( output_is_tensor: bool, argnums: Tuple[int, ...], solve: Callable[..., TensorOrTensors] = linear_solve.solve_normal_cg(), -) -> Tuple[Optional[torch.Tensor], ...]: +) -> TupleOfOptionalTensors: if output_is_tensor: @@ -119,24 +125,18 @@ def matvec(u: TupleOfTensors) -> TupleOfTensors: optimality_fn, solution, output_is_tensor, argnums, *args ) + _, optimality_vjp_fn, *_ = functorch.vjp( + masked_optimality_fn, *masked_optimality_fn.post_filled + ) + output: TupleOfTensors - if getattr(solve, 'is_spd', False): - if output_is_tensor: - output = u - else: - output = (u,) # type: ignore[assignment] + if output_is_tensor: + output = optimality_vjp_fn(u[0]) else: - _, optimality_vjp_fn, *_ = functorch.vjp( - masked_optimality_fn, *masked_optimality_fn.post_filled - ) - - if output_is_tensor: - output = optimality_vjp_fn(u[0]) - else: - output = optimality_vjp_fn(u) + output = optimality_vjp_fn(u) # Prepend None as the vjp for init_params. - true_output: List[Optional[torch.Tensor]] = [None] + true_output: ListOfOptionalTensors = [None] for idx in range(masked_optimality_fn.len_args): if idx + 1 in argnums: # plus 1 because we exclude the first argument true_output.append(output[idx]) diff --git a/torchopt/linear_solve/normal_cg.py b/torchopt/linear_solve/normal_cg.py index 78ca75f2..38cb2834 100644 --- a/torchopt/linear_solve/normal_cg.py +++ b/torchopt/linear_solve/normal_cg.py @@ -47,7 +47,6 @@ def _solve_normal_cg( matvec: Callable[[TensorTree], TensorTree], # (x) -> A @ x b: TensorTree, - is_spd: bool = False, ridge: Optional[float] = None, init: Optional[TensorTree] = None, **kwargs, @@ -60,7 +59,6 @@ def _solve_normal_cg( Args: matvec: A function that returns the product between ``A`` and a vector. b: A tree of tensors for the right hand side of the equation. - is_spd: Whether to assume matrix ``A`` is symmetric definite positive to speedup computation. ridge: Optional ridge regularization. Solves the equation for ``(A.T @ A + ridge * I) @ x = A.T @ b``. init: Optional initialization to be used by normal conjugate gradient. **kwargs: Additional keyword arguments for the conjugate gradient solver. @@ -73,12 +71,6 @@ def _solve_normal_cg( else: example_x = init - if is_spd: - if ridge is not None: - raise ValueError('ridge must be specified with `is_spd=False`.') - # Returns solution for `A @ x = b`. - return linalg.cg(matvec, b, x0=init, **kwargs) - rmatvec = make_rmatvec(matvec, example_x) # (x) -> A.T @ x normal_matvec = make_normal_matvec(matvec) # (x) -> A.T @ A @ x @@ -95,6 +87,4 @@ def _solve_normal_cg( def solve_normal_cg(**kwargs): """Wrapper for :func:`solve_normal_cg`.""" - partial_fn = functools.partial(_solve_normal_cg, **kwargs) - setattr(partial_fn, 'is_spd', kwargs.get('is_spd', False)) - return partial_fn + return functools.partial(_solve_normal_cg, **kwargs) From f66107db6953975432a9932b09a03aa44009e613 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Wed, 2 Nov 2022 17:32:09 +0800 Subject: [PATCH 36/69] feat(examples): implicit MAML omniglot example (#48) * feat(examples): implicit MAML omniglot example * chore: update CHANGELOG Co-authored-by: Xuehai Pan --- CHANGELOG.md | 1 + examples/iMAML/README.md | 18 ++ examples/iMAML/imaml-accs.png | Bin 0 -> 179218 bytes examples/iMAML/imaml_omniglot.py | 341 +++++++++++++++++++++ examples/iMAML/support/omniglot_loaders.py | 327 ++++++++++++++++++++ 5 files changed, 687 insertions(+) create mode 100644 examples/iMAML/README.md create mode 100644 examples/iMAML/imaml-accs.png create mode 100644 examples/iMAML/imaml_omniglot.py create mode 100644 examples/iMAML/support/omniglot_loaders.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e3934ec..e6c23138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add implicit MAML omniglot few-shot classification example by [@Benjamin-eecs](https://github.com/Benjamin-eecs) in [#48](https://github.com/metaopt/torchopt/pull/48). - Add object-oriented modules support for implicit meta-gradient by [@XuehaiPan](https://github.com/XuehaiPan) in [#101](https://github.com/metaopt/torchopt/pull/101). - Bump PyTorch version to 1.13.0 by [@XuehaiPan](https://github.com/XuehaiPan) in [#104](https://github.com/metaopt/torchopt/pull/104). - Add zero-order gradient estimation by [@JieRen98](https://github.com/JieRen98) in [#93](https://github.com/metaopt/torchopt/pull/93). diff --git a/examples/iMAML/README.md b/examples/iMAML/README.md new file mode 100644 index 00000000..91f95f69 --- /dev/null +++ b/examples/iMAML/README.md @@ -0,0 +1,18 @@ +# implicit MAML few-shot Omniglot classification-examples + +Code on implicit MAML few-shot Omniglot classification in paper [Meta-Learning with Implicit Gradients](https://arxiv.org/abs/1909.04630) using TorchOpt. We use `torchopt.sgd` as the inner-loop optimizer. + +## Usage + +```bash +### Run +python3 imaml_omniglot.py --inner_steps 5 +``` + +## Results + +The figure illustrate the experimental result. + +

    diff --git a/examples/iMAML/imaml-accs.png b/examples/iMAML/imaml-accs.png new file mode 100644 index 0000000000000000000000000000000000000000..1d5134a4d7f50db54d7129e45b71032c538804f8 GIT binary patch literal 179218 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�IW4KOp7X1AA0-(omWbU*sPD3RP+DN8N{NO~ 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 =28-;6a(1S)T?W2Fsur(&hfzn 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 literal 0 HcmV?d00001 diff --git a/examples/iMAML/imaml_omniglot.py b/examples/iMAML/imaml_omniglot.py new file mode 100644 index 00000000..7b165ac0 --- /dev/null +++ b/examples/iMAML/imaml_omniglot.py @@ -0,0 +1,341 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +""" +This example shows how to use TorchOpt to do iMAML-GD (see [1] for more details) +for few-shot Omniglot classification. + +[1] Rajeswaran, A., Finn, C., Kakade, S. M., & Levine, S. (2019). + Meta-learning with implicit gradients. In Advances in Neural Information Processing Systems (pp. 113-124). + https://arxiv.org/abs/1909.04630 +""" + +import argparse +import time + +import functorch +import matplotlib as mpl +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim + +import torchopt +from torchopt import pytree + + +from support.omniglot_loaders import OmniglotNShot # isort: skip + + +mpl.use('Agg') +plt.style.use('bmh') + + +def main(): + argparser = argparse.ArgumentParser() + argparser.add_argument('--n_way', type=int, help='n way', default=5) + argparser.add_argument('--k_spt', type=int, help='k shot for support set', default=5) + argparser.add_argument('--k_qry', type=int, help='k shot for query set', default=5) + argparser.add_argument('--inner_steps', type=int, help='number of inner steps', default=5) + argparser.add_argument( + '--reg_params', type=float, help='regularization parameters', default=2.0 + ) + argparser.add_argument( + '--task_num', type=int, help='meta batch size, namely task num', default=16 + ) + argparser.add_argument('--seed', type=int, help='random seed', default=1) + args = argparser.parse_args() + + torch.manual_seed(args.seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(args.seed) + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + np.random.seed(args.seed) + rng = np.random.default_rng(args.seed) + + # Set up the Omniglot loader. + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + db = OmniglotNShot( + '/tmp/omniglot-data', + batchsz=args.task_num, + n_way=args.n_way, + k_shot=args.k_spt, + k_query=args.k_qry, + imgsz=28, + rng=rng, + device=device, + ) + + # Create a vanilla PyTorch neural network. + net = nn.Sequential( + nn.Conv2d(1, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True, track_running_stats=False), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True, track_running_stats=False), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True, track_running_stats=False), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Flatten(), + nn.Linear(64, args.n_way), + ).to(device) + + # We will use Adam to (meta-)optimize the initial parameters + # to be adapted. + net.train() + fnet, params = functorch.make_functional(net) + meta_opt = torchopt.adam(lr=1e-3) + meta_opt_state = meta_opt.init(params) + + log = [] + test(db, [params, fnet], epoch=-1, log=log, args=args) + for epoch in range(10): + meta_opt, meta_opt_state = train( + db, [params, fnet], (meta_opt, meta_opt_state), epoch, log, args + ) + test(db, [params, fnet], epoch, log, args) + plot(log) + + +def train(db, net, meta_opt_and_state, epoch, log, args): + n_train_iter = db.x_train.shape[0] // db.batchsz + params, fnet = net + meta_opt, meta_opt_state = meta_opt_and_state + # Given this module we've created, rip out the parameters and buffers + # and return a functional version of the module. `fnet` is stateless + # and can be called with `fnet(params, buffers, args, kwargs)` + # fnet, params, buffers = functorch.make_functional_with_buffers(net) + + for batch_idx in range(n_train_iter): + start_time = time.time() + # Sample a batch of support and query images and labels. + x_spt, y_spt, x_qry, y_qry = db.next() + + task_num, setsz, c_, h, w = x_spt.size() + querysz = x_qry.size(1) + + n_inner_iter = args.inner_steps + reg_param = args.reg_params + qry_losses = [] + qry_accs = [] + + init_params_copy = pytree.tree_map( + lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params + ) + + for i in range(task_num): + # Optimize the likelihood of the support set by taking + # gradient steps w.r.t. the model's parameters. + # This adapts the model's meta-parameters to the task. + + optimal_params = train_imaml_inner_solver( + init_params_copy, + params, + (x_spt[i], y_spt[i]), + (fnet, n_inner_iter, reg_param), + ) + # The final set of adapted parameters will induce some + # final loss and accuracy on the query dataset. + # These will be used to update the model's meta-parameters. + qry_logits = fnet(optimal_params, x_qry[i]) + qry_loss = F.cross_entropy(qry_logits, y_qry[i]) + # Update the model's meta-parameters to optimize the query + # losses across all of the tasks sampled in this batch. + # qry_loss = qry_loss / task_num # scale gradients + meta_grads = torch.autograd.grad(qry_loss / task_num, params) + meta_updates, meta_opt_state = meta_opt.update(meta_grads, meta_opt_state) + params = torchopt.apply_updates(params, meta_updates) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).sum().item() / querysz + + qry_losses.append(qry_loss.detach()) + qry_accs.append(qry_acc) + + qry_losses = sum(qry_losses) / task_num + qry_accs = 100.0 * sum(qry_accs) / task_num + i = epoch + float(batch_idx) / n_train_iter + iter_time = time.time() - start_time + + print( + f'[Epoch {i:.2f}] Train Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f} | Time: {iter_time:.2f}' + ) + + log.append( + { + 'epoch': i, + 'loss': qry_losses, + 'acc': qry_accs, + 'mode': 'train', + 'time': time.time(), + } + ) + + return (meta_opt, meta_opt_state) + + +def test(db, net, epoch, log, args): + # Crucially in our testing procedure here, we do *not* fine-tune + # the model during testing for simplicity. + # Most research papers using MAML for this task do an extra + # stage of fine-tuning here that should be added if you are + # adapting this code for research. + params, fnet = net + # fnet, params, buffers = functorch.make_functional_with_buffers(net) + n_test_iter = db.x_test.shape[0] // db.batchsz + + qry_losses = [] + qry_accs = [] + + # TODO: Maybe pull this out into a separate module so it + # doesn't have to be duplicated between `train` and `test`? + n_inner_iter = args.inner_steps + reg_param = args.reg_params + init_params_copy = pytree.tree_map( + lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params + ) + + for batch_idx in range(n_test_iter): + x_spt, y_spt, x_qry, y_qry = db.next('test') + + task_num, setsz, c_, h, w = x_spt.size() + querysz = x_qry.size(1) + + for i in range(task_num): + # Optimize the likelihood of the support set by taking + # gradient steps w.r.t. the model's parameters. + # This adapts the model's meta-parameters to the task. + + optimal_params = test_imaml_inner_solver( + init_params_copy, + params, + (x_spt[i], y_spt[i]), + (fnet, n_inner_iter, reg_param), + ) + + # The query loss and acc induced by these parameters. + qry_logits = fnet(optimal_params, x_qry[i]) + qry_loss = F.cross_entropy(qry_logits, y_qry[i], reduction='none') + qry_losses.append(qry_loss.detach()) + qry_accs.append((qry_logits.argmax(dim=1) == y_qry[i]).detach()) + + qry_losses = torch.cat(qry_losses).mean().item() + qry_accs = 100.0 * torch.cat(qry_accs).float().mean().item() + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') + log.append( + { + 'epoch': epoch + 1, + 'loss': qry_losses, + 'acc': qry_accs, + 'mode': 'test', + 'time': time.time(), + } + ) + + +def imaml_objective(optimal_params, init_params, data, aux): + x_spt, y_spt = data + fnet, n_inner_iter, reg_param = aux + fnet.eval() + y_pred = fnet(optimal_params, x_spt) + fnet.train() + regularization_loss = 0 + for p1, p2 in zip(optimal_params, init_params): + regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) + loss = F.cross_entropy(y_pred, y_spt) + regularization_loss + return loss + + +@torchopt.diff.implicit.custom_root( + functorch.grad(imaml_objective, argnums=0), + argnums=1, + has_aux=False, + solve=torchopt.linear_solve.solve_normal_cg(maxiter=5, atol=0), +) +def train_imaml_inner_solver(init_params_copy, init_params, data, aux): + x_spt, y_spt = data + fnet, n_inner_iter, reg_param = aux + # Initial functional optimizer based on TorchOpt + params = init_params_copy + inner_opt = torchopt.sgd(lr=1e-1) + inner_opt_state = inner_opt.init(params) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(n_inner_iter): + pred = fnet(params, x_spt) + loss = F.cross_entropy(pred, y_spt) # compute loss + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params, init_params): + regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) + final_loss = loss + regularization_loss + grads = torch.autograd.grad(final_loss, params) # compute gradients + updates, inner_opt_state = inner_opt.update(grads, inner_opt_state) # get updates + params = torchopt.apply_updates(params, updates) + return params + + +def test_imaml_inner_solver(init_params_copy, init_params, data, aux): + x_spt, y_spt = data + fnet, n_inner_iter, reg_param = aux + # Initial functional optimizer based on TorchOpt + params = init_params_copy + inner_opt = torchopt.sgd(lr=1e-1) + inner_opt_state = inner_opt.init(params) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(n_inner_iter): + pred = fnet(params, x_spt) + loss = F.cross_entropy(pred, y_spt) # compute loss + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params, init_params): + regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) + final_loss = loss + regularization_loss + grads = torch.autograd.grad(final_loss, params) # compute gradients + updates, inner_opt_state = inner_opt.update(grads, inner_opt_state) # get updates + params = torchopt.apply_updates(params, updates) + return params + + +def plot(log): + # Generally you should pull your plotting code out of your training + # script but we are doing it here for brevity. + df = pd.DataFrame(log) + + fig, ax = plt.subplots(figsize=(8, 4), dpi=250) + train_df = df[df['mode'] == 'train'] + test_df = df[df['mode'] == 'test'] + ax.plot(train_df['epoch'], train_df['acc'], label='Train') + ax.plot(test_df['epoch'], test_df['acc'], label='Test') + ax.set_xlabel('Epoch') + ax.set_ylabel('Accuracy') + ax.set_ylim(80, 100) + ax.set_title('iMAML Omniglot') + ax.legend(ncol=2, loc='lower right') + fig.tight_layout() + fname = 'imaml-accs.png' + print(f'--- Plotting accuracy to {fname}') + fig.savefig(fname) + plt.close(fig) + + +if __name__ == '__main__': + main() diff --git a/examples/iMAML/support/omniglot_loaders.py b/examples/iMAML/support/omniglot_loaders.py new file mode 100644 index 00000000..d857d386 --- /dev/null +++ b/examples/iMAML/support/omniglot_loaders.py @@ -0,0 +1,327 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# 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. +# ============================================================================== +# These Omniglot loaders are from Jackie Loong's PyTorch MAML implementation: +# https://github.com/dragen1860/MAML-Pytorch +# https://github.com/dragen1860/MAML-Pytorch/blob/master/omniglot.py +# https://github.com/dragen1860/MAML-Pytorch/blob/master/omniglotNShot.py +# ============================================================================== + +import errno +import os + +import numpy as np +import torch +import torch.utils.data as data +import torchvision.transforms as transforms +from PIL import Image + + +class Omniglot(data.Dataset): + """ + The items are ``(filename, category)``. The index of all the categories can be found in + :attr:`idx_classes`. + + Args: + root: the directory where the dataset will be stored + transform: how to transform the input + target_transform: how to transform the target + download: need to download the dataset + """ + + urls = [ + 'https://github.com/brendenlake/omniglot/raw/master/python/images_background.zip', + 'https://github.com/brendenlake/omniglot/raw/master/python/images_evaluation.zip', + ] + raw_folder = 'raw' + processed_folder = 'processed' + training_file = 'training.pt' + test_file = 'test.pt' + + def __init__(self, root, transform=None, target_transform=None, download=False): + self.root = root + self.transform = transform + self.target_transform = target_transform + + if not self._check_exists(): + if download: + self.download() + else: + raise RuntimeError('Dataset not found. You can use download=True to download it') + + self.all_items = find_classes(os.path.join(self.root, self.processed_folder)) + self.idx_classes = index_classes(self.all_items) + + def __getitem__(self, index): + filename = self.all_items[index][0] + img = str.join('/', [self.all_items[index][2], filename]) + + target = self.idx_classes[self.all_items[index][1]] + if self.transform is not None: + img = self.transform(img) + if self.target_transform is not None: + target = self.target_transform(target) + + return img, target + + def __len__(self): + return len(self.all_items) + + def _check_exists(self): + return os.path.exists( + os.path.join(self.root, self.processed_folder, 'images_evaluation') + ) and os.path.exists(os.path.join(self.root, self.processed_folder, 'images_background')) + + def download(self): + import zipfile + + from six.moves import urllib + + if self._check_exists(): + return + + # download files + try: + os.makedirs(os.path.join(self.root, self.raw_folder)) + os.makedirs(os.path.join(self.root, self.processed_folder)) + except OSError as e: + if e.errno == errno.EEXIST: + pass + else: + raise + + for url in self.urls: + print('== Downloading ' + url) + data = urllib.request.urlopen(url) + filename = url.rpartition('/')[2] + file_path = os.path.join(self.root, self.raw_folder, filename) + with open(file_path, 'wb') as f: + f.write(data.read()) + file_processed = os.path.join(self.root, self.processed_folder) + print('== Unzip from ' + file_path + ' to ' + file_processed) + zip_ref = zipfile.ZipFile(file_path, 'r') + zip_ref.extractall(file_processed) + zip_ref.close() + print('Download finished.') + + +def find_classes(root_dir): + retour = [] + for (root, dirs, files) in os.walk(root_dir): + for f in files: + if f.endswith('png'): + r = root.split('/') + lr = len(r) + retour.append((f, r[lr - 2] + '/' + r[lr - 1], root)) + print('== Found %d items ' % len(retour)) + return retour + + +def index_classes(items): + idx = {} + for i in items: + if i[1] not in idx: + idx[i[1]] = len(idx) + print('== Found %d classes' % len(idx)) + return idx + + +class OmniglotNShot: + def __init__(self, root, batchsz, n_way, k_shot, k_query, imgsz, rng, device=None): + """ + Different from mnistNShot, the + :param root: + :param batchsz: task num + :param n_way: + :param k_shot: + :param k_qry: + :param imgsz: + """ + + self.resize = imgsz + self.rng = rng + self.device = device + if not os.path.isfile(os.path.join(root, 'omniglot.npy')): + # if root/data.npy does not exist, just download it + self.x = Omniglot( + root, + download=True, + transform=transforms.Compose( + [ + lambda x: Image.open(x).convert('L'), + lambda x: x.resize((imgsz, imgsz)), + lambda x: np.reshape(x, (imgsz, imgsz, 1)), + lambda x: np.transpose(x, [2, 0, 1]), + lambda x: x / 255.0, + ] + ), + ) + + # {label: [img1, img2..., img20], label2: [img1, img2, ...], ... 1623 labels in total} + temp = {} + for (img, label) in self.x: + if label in temp.keys(): + temp[label].append(img) + else: + temp[label] = [img] + + self.x = [] + for ( + label, + imgs, + ) in temp.items(): # labels info deserted , each label contains 20imgs + self.x.append(np.array(imgs)) + + # as different class may have different number of imgs + self.x = np.array(self.x).astype(np.float) # [[20 imgs],..., 1623 classes in total] + # each character contains 20 imgs + print('data shape:', self.x.shape) # [1623, 20, 84, 84, 1] + temp = [] # Free memory + # save all dataset into npy file. + np.save(os.path.join(root, 'omniglot.npy'), self.x) + print('write into omniglot.npy.') + else: + # if data.npy exists, just load it. + self.x = np.load(os.path.join(root, 'omniglot.npy')) + print('load from omniglot.npy.') + + # [1623, 20, 84, 84, 1] + # TODO: can not shuffle here, we must keep training and test set distinct! + self.x_train, self.x_test = self.x[:1200], self.x[1200:] + + # self.normalization() + + self.batchsz = batchsz + self.n_cls = self.x.shape[0] # 1623 + self.n_way = n_way # n way + self.k_shot = k_shot # k shot + self.k_query = k_query # k query + assert (k_shot + k_query) <= 20 + + # save pointer of current read batch in total cache + self.indexes = {'train': 0, 'test': 0} + self.datasets = { + 'train': self.x_train, + 'test': self.x_test, + } # original data cached + print('DB: train', self.x_train.shape, 'test', self.x_test.shape) + + self.datasets_cache = { + 'train': self.load_data_cache(self.datasets['train']), # current epoch data cached + 'test': self.load_data_cache(self.datasets['test']), + } + + def normalization(self): + """ + Normalizes our data, to have a mean of 0 and sdt of 1 + """ + self.mean = np.mean(self.x_train) + self.std = np.std(self.x_train) + self.max = np.max(self.x_train) + self.min = np.min(self.x_train) + # print("before norm:", "mean", self.mean, "max", self.max, "min", self.min, "std", self.std) + self.x_train = (self.x_train - self.mean) / self.std + self.x_test = (self.x_test - self.mean) / self.std + + self.mean = np.mean(self.x_train) + self.std = np.std(self.x_train) + self.max = np.max(self.x_train) + self.min = np.min(self.x_train) + + # print("after norm:", "mean", self.mean, "max", self.max, "min", self.min, "std", self.std) + + def load_data_cache(self, data_pack): + """ + Collects several batches data for N-shot learning + :param data_pack: [cls_num, 20, 84, 84, 1] + :return: A list with [support_set_x, support_set_y, target_x, target_y] ready to be fed to our networks + """ + + # take 5 way 1 shot as example: 5 * 1 + setsz = self.k_shot * self.n_way + querysz = self.k_query * self.n_way + data_cache = [] + + # print('preload next 50 caches of batchsz of batch.') + for sample in range(10): # num of episodes + + x_spts, y_spts, x_qrys, y_qrys = [], [], [], [] + for i in range(self.batchsz): # one batch means one set + + x_spt, y_spt, x_qry, y_qry = [], [], [], [] + selected_cls = self.rng.choice(data_pack.shape[0], self.n_way, False) + + for j, cur_class in enumerate(selected_cls): + + selected_img = self.rng.choice(20, self.k_shot + self.k_query, False) + + # meta-training and meta-test + x_spt.append(data_pack[cur_class][selected_img[: self.k_shot]]) + x_qry.append(data_pack[cur_class][selected_img[self.k_shot :]]) + y_spt.append([j for _ in range(self.k_shot)]) + y_qry.append([j for _ in range(self.k_query)]) + + # shuffle inside a batch + perm = self.rng.permutation(self.n_way * self.k_shot) + x_spt = np.array(x_spt).reshape( + self.n_way * self.k_shot, 1, self.resize, self.resize + )[perm] + y_spt = np.array(y_spt).reshape(self.n_way * self.k_shot)[perm] + perm = self.rng.permutation(self.n_way * self.k_query) + x_qry = np.array(x_qry).reshape( + self.n_way * self.k_query, 1, self.resize, self.resize + )[perm] + y_qry = np.array(y_qry).reshape(self.n_way * self.k_query)[perm] + + # append [sptsz, 1, 84, 84] => [b, setsz, 1, 84, 84] + x_spts.append(x_spt) + y_spts.append(y_spt) + x_qrys.append(x_qry) + y_qrys.append(y_qry) + + # [b, setsz, 1, 84, 84] + x_spts = np.array(x_spts, dtype=np.float32).reshape( + self.batchsz, setsz, 1, self.resize, self.resize + ) + y_spts = np.array(y_spts, dtype=np.int).reshape(self.batchsz, setsz) + # [b, qrysz, 1, 84, 84] + x_qrys = np.array(x_qrys, dtype=np.float32).reshape( + self.batchsz, querysz, 1, self.resize, self.resize + ) + y_qrys = np.array(y_qrys, dtype=np.int).reshape(self.batchsz, querysz) + + x_spts, y_spts, x_qrys, y_qrys = [ + torch.from_numpy(z).to(self.device) for z in [x_spts, y_spts, x_qrys, y_qrys] + ] + + data_cache.append([x_spts, y_spts, x_qrys, y_qrys]) + + return data_cache + + def next(self, mode='train'): + """ + Gets next batch from the dataset with name. + :param mode: The name of the splitting (one of "train", "val", "test") + :return: + """ + + # update cache if indexes is larger cached num + if self.indexes[mode] >= len(self.datasets_cache[mode]): + self.indexes[mode] = 0 + self.datasets_cache[mode] = self.load_data_cache(self.datasets[mode]) + + next_batch = self.datasets_cache[mode][self.indexes[mode]] + self.indexes[mode] += 1 + + return next_batch From 60d42a5a76f15dcd1b40144d6e0e72a3b7ae3ec3 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Wed, 2 Nov 2022 19:16:21 +0800 Subject: [PATCH 37/69] test(implicit): add tests for implicit OOP APIs (#106) --- tests/test_implicit.py | 159 ++++++++++++++++++++++++---- torchopt/diff/implicit/decorator.py | 10 +- torchopt/diff/implicit/nn/module.py | 58 +++++++--- 3 files changed, 184 insertions(+), 43 deletions(-) diff --git a/tests/test_implicit.py b/tests/test_implicit.py index d5113e35..399ee025 100644 --- a/tests/test_implicit.py +++ b/tests/test_implicit.py @@ -32,6 +32,7 @@ import helpers import torchopt from torchopt import pytree +from torchopt.diff.implicit import ImplicitMetaGradientModule BATCH_SIZE = 8 @@ -41,6 +42,17 @@ MODEL_NUM_CLASSES = 10 +class FcNet(nn.Module): + def __init__(self, dim, out): + super().__init__() + self.fc = nn.Linear(in_features=dim, out_features=out, bias=True) + nn.init.ones_(self.fc.weight) + nn.init.zeros_(self.fc.bias) + + def forward(self, x): + return self.fc(x) + + def get_model_jax(dtype: np.dtype = np.float32) -> Tuple[FunctionType, OrderedDict]: helpers.seed_everything(seed=42) @@ -62,16 +74,6 @@ def get_model_torch( ) -> Tuple[nn.Module, data.DataLoader]: helpers.seed_everything(seed=42) - class FcNet(nn.Module): - def __init__(self, dim, out): - super().__init__() - self.fc = nn.Linear(in_features=dim, out_features=out, bias=True) - nn.init.ones_(self.fc.weight) - nn.init.zeros_(self.fc.bias) - - def forward(self, x): - return self.fc(x) - model = FcNet(MODEL_NUM_INPUTS, MODEL_NUM_CLASSES).to(dtype=dtype) if device is not None: @@ -87,6 +89,23 @@ def forward(self, x): return model, loader +@torch.no_grad() +def get_rr_dataset_torch() -> data.DataLoader: + helpers.seed_everything(seed=42) + + BATCH_SIZE = 1024 + NUM_UPDATES = 4 + dataset = data.TensorDataset( + torch.randn((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), + torch.randn((BATCH_SIZE * NUM_UPDATES)), + torch.randn((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), + torch.randn((BATCH_SIZE * NUM_UPDATES)), + ) + loader = data.DataLoader(dataset, BATCH_SIZE, shuffle=False) + + return loader + + @helpers.parametrize( dtype=[torch.float64, torch.float32], lr=[1e-3, 1e-4], @@ -207,21 +226,117 @@ def outer_level(p, xs, ys): helpers.assert_all_close(p, p_ref) -@torch.no_grad() -def get_rr_dataset_torch() -> data.DataLoader: - helpers.seed_everything(seed=42) +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-3, 1e-4], + inner_lr=[2e-2, 2e-3], + inner_update=[20, 50, 100], +) +def test_imaml_module(dtype: torch.dtype, lr: float, inner_lr: float, inner_update: int) -> None: + np_dtype = helpers.dtype_torch2numpy(dtype) - BATCH_SIZE = 1024 - NUM_UPDATES = 4 - dataset = data.TensorDataset( - torch.randn((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), - torch.randn((BATCH_SIZE * NUM_UPDATES)), - torch.randn((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), - torch.randn((BATCH_SIZE * NUM_UPDATES)), + jax_model, jax_params = get_model_jax(dtype=np_dtype) + model, loader = get_model_torch(device='cpu', dtype=dtype) + + class InnerNet(ImplicitMetaGradientModule, has_aux=True): + def __init__(self, meta_model): + super().__init__() + self.meta_model = meta_model + self.model = copy.deepcopy(meta_model) + + def forward(self, x): + return self.model(x) + + def objective(self, x, y): + y_pred = self.model(x) + loss = F.cross_entropy(y_pred, y) + regularization_loss = 0 + for p1, p2 in zip(self.parameters(), self.meta_parameters()): + regularization_loss += 0.5 * torch.sum(torch.square(p1 - p2)) + loss = loss + regularization_loss + return loss + + def solve(self, x, y): + params = tuple(self.parameters()) + optim_inner = torchopt.SGD(params, lr=inner_lr) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(inner_update): + loss = self.objective(x, y) + optim_inner.zero_grad() + loss.backward(inputs=params) + optim_inner.step() + + return self, (0, {'a': 1, 'b': 2}) + + outer_optim = torchopt.SGD(model.parameters(), lr) + + optim_jax = optax.sgd(lr) + optim_state_jax = optim_jax.init(jax_params) + + def imaml_objective_jax(optimal_params, init_params, x, y): + y_pred = jax_model(optimal_params, x) + loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(y_pred, y)) + regularization_loss = 0 + for p1, p2 in zip(optimal_params.values(), init_params.values()): + regularization_loss += 0.5 * jnp.sum(jnp.square((p1 - p2))) + loss = loss + regularization_loss + return loss + + @jaxopt.implicit_diff.custom_root(jax.grad(imaml_objective_jax, argnums=0), has_aux=True) + def inner_solver_jax(init_params_copy, init_params, x, y): + """Solve ridge regression by conjugate gradient.""" + # Initial functional optimizer based on torchopt + params = init_params_copy + optimizer = optax.sgd(inner_lr) + opt_state = optimizer.init(params) + + def compute_loss(params, init_params, x, y): + pred = jax_model(params, x) + loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(pred, y)) + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params.values(), init_params.values()): + regularization_loss += 0.5 * jnp.sum(jnp.square((p1 - p2))) + final_loss = loss + regularization_loss + return final_loss + + for i in range(inner_update): + grads = jax.grad(compute_loss)(params, init_params, x, y) # compute gradients + updates, opt_state = optimizer.update(grads, opt_state) # get updates + params = optax.apply_updates(params, updates) + return params, (0, {'a': 1, 'b': 2}) + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + inner_model = InnerNet(model) + optimal_inner_model, aux = inner_model.solve(xs, ys) + assert aux == (0, {'a': 1, 'b': 2}) + outer_loss = optimal_inner_model(xs).mean() + + outer_optim.zero_grad() + outer_loss.backward() + outer_optim.step() + + xs = xs.numpy() + ys = ys.numpy() + + def outer_level(p, xs, ys): + optimal_params, aux = inner_solver_jax(copy.deepcopy(p), p, xs, ys) + assert aux == (0, {'a': 1, 'b': 2}) + outer_loss = jax_model(optimal_params, xs).mean() + return outer_loss + + grads_jax = jax.grad(outer_level, argnums=0)(jax_params, xs, ys) + updates_jax, optim_state_jax = optim_jax.update(grads_jax, optim_state_jax) # get updates + jax_params = optax.apply_updates(jax_params, updates_jax) + + jax_params_as_tensor = tuple( + nn.Parameter(torch.tensor(np.asarray(jax_params[j]), dtype=dtype)) for j in jax_params ) - loader = data.DataLoader(dataset, BATCH_SIZE, shuffle=False) - return loader + for p, p_ref in zip(model.parameters(), jax_params_as_tensor): + helpers.assert_all_close(p, p_ref) @helpers.parametrize( diff --git a/torchopt/diff/implicit/decorator.py b/torchopt/diff/implicit/decorator.py index 37a3675a..1f944576 100644 --- a/torchopt/diff/implicit/decorator.py +++ b/torchopt/diff/implicit/decorator.py @@ -275,8 +275,9 @@ def forward( # type: ignore[override] # pylint: disable=arguments-differ if has_aux: if not (isinstance(output, tuple) and len(output) == 2): raise RuntimeError( - 'custom_root(optimality_fn)(solver_fn)(*args): output of function ' - 'solver_fn should be a tuple: (output, aux) if has_aux is True' + f'custom_root(optimality_fn)(solver_fn)(*args): output of function ' + f'solver_fn should be a tuple: (output, aux) if has_aux is True. ' + f'Got {output}' ) output, aux = output if isinstance(output, torch.Tensor): @@ -284,8 +285,9 @@ def forward( # type: ignore[override] # pylint: disable=arguments-differ output = (output,) elif not (isinstance(output, tuple) and all(map(torch.is_tensor, output))): raise RuntimeError( - 'custom_root(optimality_fn)(solver_fn)(*args): output of function ' - 'solver_fn should be a torch.Tensor or a tuple of torch.Tensor' + f'custom_root(optimality_fn)(solver_fn)(*args): output of function ' + f'solver_fn should be a torch.Tensor or a tuple of torch.Tensor. ' + f'Got {output}' ) ( diff --git a/torchopt/diff/implicit/nn/module.py b/torchopt/diff/implicit/nn/module.py index 3b08118a..3ddaf296 100644 --- a/torchopt/diff/implicit/nn/module.py +++ b/torchopt/diff/implicit/nn/module.py @@ -16,7 +16,7 @@ import functools import itertools -from typing import Callable, Dict, Optional, Tuple +from typing import Any, Callable, Dict, Optional, Tuple, Type, Union import functorch import torch @@ -73,16 +73,18 @@ def objective_fn(flat_params: TupleOfTensors, *input, **kwargs) -> torch.Tensor: def enable_implicit_gradients( - solve: Callable[..., 'ImplicitMetaGradientModule'] -) -> Callable[..., 'ImplicitMetaGradientModule']: + cls: Type['ImplicitMetaGradientModule'], +) -> Type['ImplicitMetaGradientModule']: """Enable implicit gradients for the :func:`solve` function.""" + solve = cls.solve + has_aux = cls.has_aux if getattr(solve, '__implicit_gradients_enabled__', False): raise ValueError('Implicit gradients are already enabled for the solve function.') @functools.wraps(solve) def wrapped( # pylint: disable=too-many-locals self: 'ImplicitMetaGradientModule', *input, **kwargs # pylint: disable=redefined-builtin - ) -> 'ImplicitMetaGradientModule': + ) -> Union['ImplicitMetaGradientModule', Tuple['ImplicitMetaGradientModule', Any]]: """Solve the optimization problem.""" params_containers = extract_module_containers(self, with_buffers=False)[0] meta_params_containers = [self._meta_parameters] # pylint: disable=protected-access @@ -139,22 +141,41 @@ def optimality_fn( ): container.update(container_backup) - @custom_root(optimality_fn, argnums=1) - def solve_fn( + @custom_root(optimality_fn, argnums=1, has_aux=has_aux) + def solver_fn( flat_params: TupleOfTensors, # pylint: disable=unused-argument flat_meta_params: TupleOfTensors, # pylint: disable=unused-argument *input, # pylint: disable=redefined-builtin **kwargs, - ) -> TupleOfTensors: - solve(self, *input, **kwargs) - return tuple(pytree.tree_leaves(params_containers)) # type: ignore[arg-type] - - # pylint: disable-next=unused-variable - flat_optimal_params = solve_fn(flat_params, flat_meta_params, *input, **kwargs) + ) -> Union[TupleOfTensors, Tuple[TupleOfTensors, Any]]: + output = solve(self, *input, **kwargs) + if has_aux: + if not (isinstance(output, tuple) and len(output) == 2): + raise RuntimeError( + f'Output of method ImplicitMetaGradientModule.solve should be a ' + f'tuple: (self, aux) if has_aux is True. Got {output}' + ) + output, aux = output + if not isinstance(output, ImplicitMetaGradientModule): + raise RuntimeError( + f'Output of method ImplicitMetaGradientModule.solve should be a ' + f'instance of class ImplicitMetaGradientModule. Got {output}' + ) + + flat_optimal_params: TupleOfTensors = tuple(pytree.tree_leaves(params_containers)) # type: ignore[arg-type] + if has_aux: + return flat_optimal_params, aux + return flat_optimal_params + + output = solver_fn(flat_params, flat_meta_params, *input, **kwargs) + if has_aux: + _, aux = output + return self, aux return self wrapped.__implicit_gradients_enabled__ = True # type: ignore[attr-defined] - return wrapped + cls.solve = wrapped # type: ignore[assignment] + return cls class ImplicitMetaGradientModule(torchopt.nn.MetaGradientModule): @@ -162,10 +183,12 @@ class ImplicitMetaGradientModule(torchopt.nn.MetaGradientModule): _custom_optimality: bool _custom_objective: bool + has_aux: bool - def __init_subclass__(cls) -> None: + def __init_subclass__(cls, has_aux=False) -> None: """Initialize the subclass.""" super().__init_subclass__() + cls.has_aux = has_aux optimality = getattr(cls, 'optimality', ImplicitMetaGradientModule.optimality) objective = getattr(cls, 'objective', ImplicitMetaGradientModule.objective) @@ -193,10 +216,11 @@ def __init_subclass__(cls) -> None: cls.optimality = make_optimality_from_objective(objective) # type: ignore[assignment] - cls.solve = enable_implicit_gradients(cls.solve) # type: ignore[assignment] + enable_implicit_gradients(cls) - # pylint: disable-next=redefined-builtin - def solve(self, *input, **kwargs) -> 'ImplicitMetaGradientModule': + def solve( + self, *input, **kwargs # pylint: disable=redefined-builtin + ) -> Union['ImplicitMetaGradientModule', Tuple['ImplicitMetaGradientModule', Any]]: """Solves the inner optimization problem. .. warning:: From 920bc4ad769760ef36dbbf7a1a636f92891b2268 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Thu, 3 Nov 2022 00:51:54 +0800 Subject: [PATCH 38/69] feat(examples/implicit): add iMAML example with OOP APIs (#107) --- CHANGELOG.md | 1 + README.md | 6 +- docs/source/examples/MAML.rst | 29 +- examples/FuncTorch/maml_omniglot_vmap.py | 38 +- examples/L2R/{helper => helpers}/argument.py | 0 examples/L2R/{helper => helpers}/model.py | 0 examples/L2R/{helper => helpers}/utils.py | 0 examples/L2R/l2r.py | 6 +- examples/LOLA/{helper => helpers}/agent.py | 0 examples/LOLA/{helper => helpers}/argument.py | 0 examples/LOLA/{helper => helpers}/env.py | 0 examples/LOLA/{helper => helpers}/utils.py | 0 examples/LOLA/lola_dice.py | 8 +- .../{support => helpers}/omniglot_loaders.py | 0 .../distributed/few-shot/maml_omniglot.py | 9 +- .../few-shot/maml_omniglot_local_loader.py | 9 +- .../{support => helpers}/omniglot_loaders.py | 0 examples/few-shot/maml_omniglot.py | 29 +- examples/iMAML/README.md | 7 +- .../{support => helpers}/omniglot_loaders.py | 0 examples/iMAML/imaml-accs-functional.png | Bin 0 -> 183882 bytes examples/iMAML/imaml-accs.png | Bin 179218 -> 169952 bytes examples/iMAML/imaml_omniglot.py | 200 ++++------- examples/iMAML/imaml_omniglot_functional.py | 338 ++++++++++++++++++ setup.py | 3 +- tests/helpers.py | 3 +- tests/test_implicit.py | 7 +- torchopt/diff/implicit/nn/module.py | 30 +- torchopt/typing.py | 6 + torchopt/utils.py | 16 +- 30 files changed, 525 insertions(+), 220 deletions(-) rename examples/L2R/{helper => helpers}/argument.py (100%) rename examples/L2R/{helper => helpers}/model.py (100%) rename examples/L2R/{helper => helpers}/utils.py (100%) rename examples/LOLA/{helper => helpers}/agent.py (100%) rename examples/LOLA/{helper => helpers}/argument.py (100%) rename examples/LOLA/{helper => helpers}/env.py (100%) rename examples/LOLA/{helper => helpers}/utils.py (100%) rename examples/distributed/few-shot/{support => helpers}/omniglot_loaders.py (100%) rename examples/few-shot/{support => helpers}/omniglot_loaders.py (100%) rename examples/iMAML/{support => helpers}/omniglot_loaders.py (100%) create mode 100644 examples/iMAML/imaml-accs-functional.png create mode 100644 examples/iMAML/imaml_omniglot_functional.py diff --git a/CHANGELOG.md b/CHANGELOG.md index e6c23138..644cd7eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add implicit MAML omniglot few-shot classification example with OOP APIs by [@XuehaiPan](https://github.com/XuehaiPan) in [#107](https://github.com/metaopt/torchopt/pull/107). - Add implicit MAML omniglot few-shot classification example by [@Benjamin-eecs](https://github.com/Benjamin-eecs) in [#48](https://github.com/metaopt/torchopt/pull/48). - Add object-oriented modules support for implicit meta-gradient by [@XuehaiPan](https://github.com/XuehaiPan) in [#101](https://github.com/metaopt/torchopt/pull/101). - Bump PyTorch version to 1.13.0 by [@XuehaiPan](https://github.com/XuehaiPan) in [#104](https://github.com/metaopt/torchopt/pull/104). diff --git a/README.md b/README.md index 719f4442..1bcbf548 100644 --- a/README.md +++ b/README.md @@ -273,10 +273,10 @@ make install-editable # or run `pip3 install --no-build-isolation --editable .` ## Future Plan - [X] CPU-accelerated optimizer -- [X] Support general implicit differentiation with functional programing - [X] Support more optimizers such as AdamW, RMSProp -- [ ] Zero order optimization -- [ ] Distributed optimizers +- [X] Support general implicit differentiation +- [X] Zero order optimization +- [X] Distributed optimization - [ ] Support `complex` data type ## Changelog diff --git a/docs/source/examples/MAML.rst b/docs/source/examples/MAML.rst index 390e45cc..87891c6a 100644 --- a/docs/source/examples/MAML.rst +++ b/docs/source/examples/MAML.rst @@ -99,8 +99,7 @@ Define the ``train`` function: # Sample a batch of support and query images and labels. x_spt, y_spt, x_qry, y_qry = db.next() - task_num, setsz, c_, h, w = x_spt.size() - querysz = x_qry.size(1) + task_num = x_spt.size(0) # TODO: Maybe pull this out into a separate module so it # doesn't have to be duplicated between `train` and `test`? @@ -129,9 +128,9 @@ Define the ``train`` function: # These will be used to update the model's meta-parameters. qry_logits = net(x_qry[i]) qry_loss = F.cross_entropy(qry_logits, y_qry[i]) - qry_losses.append(qry_loss.detach()) - qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).sum().item() / querysz - qry_accs.append(qry_acc) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() + qry_losses.append(qry_loss) + qry_accs.append(qry_acc.item()) torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) @@ -139,15 +138,14 @@ Define the ``train`` function: qry_losses = torch.mean(torch.stack(qry_losses)) qry_losses.backward() meta_opt.step() - qry_losses = sum(qry_losses) / task_num - qry_accs = 100. * sum(qry_accs) / task_num + qry_losses = qry_losses.item() + qry_accs = 100.0 * np.mean(qry_accs) i = epoch + float(batch_idx) / n_train_iter iter_time = time.time() - start_time print( f'[Epoch {i:.2f}] Train Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f} | Time: {iter_time:.2f}' ) - log.append( { 'epoch': i, @@ -181,8 +179,7 @@ Define the ``test`` function: for batch_idx in range(n_test_iter): x_spt, y_spt, x_qry, y_qry = db.next('test') - task_num, setsz, c_, h, w = x_spt.size() - querysz = x_qry.size(1) + task_num = x_spt.size(0) # TODO: Maybe pull this out into a separate module so it # doesn't have to be duplicated between `train` and `test`? @@ -201,15 +198,17 @@ Define the ``test`` function: # The query loss and acc induced by these parameters. qry_logits = net(x_qry[i]).detach() - qry_loss = F.cross_entropy(qry_logits, y_qry[i], reduction='none') - qry_losses.append(qry_loss.detach()) - qry_accs.append((qry_logits.argmax(dim=1) == y_qry[i]).detach()) + qry_loss = F.cross_entropy(qry_logits, y_qry[i]) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() + qry_losses.append(qry_loss.item()) + qry_accs.append(qry_acc.item()) torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) - qry_losses = torch.mean(torch.stack(qry_losses)).item() - qry_accs = 100. * torch.cat(qry_accs).float().mean().item() + qry_losses = np.mean(qry_losses) + qry_accs = 100.0 * np.mean(qry_accs) + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( { diff --git a/examples/FuncTorch/maml_omniglot_vmap.py b/examples/FuncTorch/maml_omniglot_vmap.py index 9bbb30ce..9f3c1d92 100644 --- a/examples/FuncTorch/maml_omniglot_vmap.py +++ b/examples/FuncTorch/maml_omniglot_vmap.py @@ -39,16 +39,10 @@ https://github.com/bamos/HowToTrainYourMAMLPytorch """ - -import os -import sys - - -cur = os.path.abspath(os.path.dirname(__file__)) -root = os.path.split(cur)[0] -sys.path.append(root + '/few-shot') import argparse import functools +import pathlib +import sys import time import functorch @@ -59,12 +53,17 @@ import torch import torch.nn.functional as F import torch.optim as optim -from support.omniglot_loaders import OmniglotNShot from torch import nn import torchopt +CWD = pathlib(__file__).absolute().parent +sys.path.append(str(CWD.parent / 'few-shot')) + +from helpers.omniglot_loaders import OmniglotNShot + + mpl.use('Agg') plt.style.use('bmh') @@ -148,8 +147,6 @@ def loss_for_task(net, n_inner_iter, x_spt, y_spt, x_qry, y_qry): opt = torchopt.sgd(lr=1e-1) opt_state = opt.init(params) - querysz = x_qry.size(0) - def compute_loss(new_params, buffers, x, y): logits = fnet(new_params, buffers, x) loss = F.cross_entropy(logits, y) @@ -167,7 +164,7 @@ def compute_loss(new_params, buffers, x, y): # These will be used to update the model's meta-parameters. qry_logits = fnet(new_params, buffers, x_qry) qry_loss = F.cross_entropy(qry_logits, y_qry) - qry_acc = (qry_logits.argmax(dim=1) == y_qry).sum() / querysz + qry_acc = (qry_logits.argmax(dim=1) == y_qry).mean() return qry_loss, qry_acc @@ -192,18 +189,19 @@ def train(db, net, device, meta_opt, epoch, log): qry_losses, qry_accs = functorch.vmap(compute_loss_for_task)(x_spt, y_spt, x_qry, y_qry) # Compute the maml loss by summing together the returned losses. - qry_losses.sum().backward() - + qry_losses = torch.mean(torch.stack(qry_losses)) + qry_losses.backward() meta_opt.step() - qry_losses = qry_losses.detach().sum() / task_num - qry_accs = 100.0 * qry_accs.sum() / task_num + qry_losses = qry_losses.item() + qry_accs = 100.0 * torch.mean(torch.stack(qry_accs)).item() i = epoch + float(batch_idx) / n_train_iter iter_time = time.time() - start_time + torch.cuda.empty_cache() + if batch_idx % 4 == 0: print( f'[Epoch {i:.2f}] Train Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f} | Time: {iter_time:.2f}' ) - log.append( { 'epoch': i, @@ -249,8 +247,10 @@ def test(db, net, device, epoch, log): qry_losses.append(qry_loss.detach()) qry_accs.append((qry_logits.argmax(dim=1) == y_qry[i]).detach()) - qry_losses = torch.cat(qry_losses).mean().item() - qry_accs = 100.0 * torch.cat(qry_accs).float().mean().item() + qry_losses = torch.mean(torch.stack(qry_losses)).item() + qry_accs = 100.0 * torch.mean(torch.stack(qry_accs)).item() + torch.cuda.empty_cache() + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( { diff --git a/examples/L2R/helper/argument.py b/examples/L2R/helpers/argument.py similarity index 100% rename from examples/L2R/helper/argument.py rename to examples/L2R/helpers/argument.py diff --git a/examples/L2R/helper/model.py b/examples/L2R/helpers/model.py similarity index 100% rename from examples/L2R/helper/model.py rename to examples/L2R/helpers/model.py diff --git a/examples/L2R/helper/utils.py b/examples/L2R/helpers/utils.py similarity index 100% rename from examples/L2R/helper/utils.py rename to examples/L2R/helpers/utils.py diff --git a/examples/L2R/l2r.py b/examples/L2R/l2r.py index 989b71cc..e77faa14 100644 --- a/examples/L2R/l2r.py +++ b/examples/L2R/l2r.py @@ -39,9 +39,9 @@ # isort: off -from helper.argument import parse_args -from helper.model import LeNet5 -from helper.utils import get_imbalance_dataset, plot, set_seed +from helpers.argument import parse_args +from helpers.model import LeNet5 +from helpers.utils import get_imbalance_dataset, plot, set_seed def run_baseline(args, mnist_train, mnist_test): diff --git a/examples/LOLA/helper/agent.py b/examples/LOLA/helpers/agent.py similarity index 100% rename from examples/LOLA/helper/agent.py rename to examples/LOLA/helpers/agent.py diff --git a/examples/LOLA/helper/argument.py b/examples/LOLA/helpers/argument.py similarity index 100% rename from examples/LOLA/helper/argument.py rename to examples/LOLA/helpers/argument.py diff --git a/examples/LOLA/helper/env.py b/examples/LOLA/helpers/env.py similarity index 100% rename from examples/LOLA/helper/env.py rename to examples/LOLA/helpers/env.py diff --git a/examples/LOLA/helper/utils.py b/examples/LOLA/helpers/utils.py similarity index 100% rename from examples/LOLA/helper/utils.py rename to examples/LOLA/helpers/utils.py diff --git a/examples/LOLA/lola_dice.py b/examples/LOLA/lola_dice.py index 7b1417a4..4b6b2567 100644 --- a/examples/LOLA/lola_dice.py +++ b/examples/LOLA/lola_dice.py @@ -21,10 +21,10 @@ # isort: off -from helper.agent import Agent -from helper.argument import parse_args -from helper.env import IPD -from helper.utils import sample, step +from helpers.agent import Agent +from helpers.argument import parse_args +from helpers.env import IPD +from helpers.utils import sample, step def main(args): diff --git a/examples/distributed/few-shot/support/omniglot_loaders.py b/examples/distributed/few-shot/helpers/omniglot_loaders.py similarity index 100% rename from examples/distributed/few-shot/support/omniglot_loaders.py rename to examples/distributed/few-shot/helpers/omniglot_loaders.py diff --git a/examples/distributed/few-shot/maml_omniglot.py b/examples/distributed/few-shot/maml_omniglot.py index 22c8bda1..78a85d71 100644 --- a/examples/distributed/few-shot/maml_omniglot.py +++ b/examples/distributed/few-shot/maml_omniglot.py @@ -58,7 +58,7 @@ import torchopt.distributed as todist -from support.omniglot_loaders import OmniglotNShot # isort: skip +from helpers.omniglot_loaders import OmniglotNShot # isort: skip mpl.use('Agg') @@ -187,7 +187,6 @@ def inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter): x_qry = x_qry.to(device) y_qry = y_qry.to(device) - querysz = x_qry.size(0) inner_opt = torchopt.MetaSGD(net, lr=1e-1) for _ in range(n_inner_iter): @@ -197,7 +196,7 @@ def inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter): qry_logits = net(x_qry) qry_loss = F.cross_entropy(qry_logits, y_qry).cpu() - qry_acc = (qry_logits.argmax(dim=1) == y_qry).sum().cpu().item() / querysz + qry_acc = (qry_logits.argmax(dim=1) == y_qry).mean().cpu().item() return qry_loss, qry_acc @@ -232,11 +231,11 @@ def train(db: OmniglotNShot, net: nn.Module, meta_opt: optim.Adam, epoch: int, l qry_acc = 100.0 * qry_acc i = epoch + float(batch_idx) / n_train_iter iter_time = time.time() - start_time + torch.cuda.empty_cache() print( f'[Epoch {i:.2f}] Train Loss: {qry_loss:.2f} | Acc: {qry_acc:.2f} | Time: {iter_time:.2f}' ) - log.append( { 'epoch': i, @@ -275,6 +274,8 @@ def test(db, net, epoch, log): qry_losses = np.mean(qry_losses) qry_accs = 100.0 * np.mean(qry_accs) + torch.cuda.empty_cache() + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( { diff --git a/examples/distributed/few-shot/maml_omniglot_local_loader.py b/examples/distributed/few-shot/maml_omniglot_local_loader.py index 9c36c6ad..d41a7dae 100644 --- a/examples/distributed/few-shot/maml_omniglot_local_loader.py +++ b/examples/distributed/few-shot/maml_omniglot_local_loader.py @@ -60,7 +60,7 @@ import torchopt.distributed as todist -from support.omniglot_loaders import OmniglotNShot # isort: skip +from helpers.omniglot_loaders import OmniglotNShot # isort: skip mpl.use('Agg') @@ -228,7 +228,6 @@ def inner_loop(net_rref, n_inner_iter, task_id, task_num, mode): x_qry = x_qry.to(device) y_qry = y_qry.to(device) - querysz = x_qry.size(0) inner_opt = torchopt.MetaSGD(net, lr=1e-1) for _ in range(n_inner_iter): @@ -238,7 +237,7 @@ def inner_loop(net_rref, n_inner_iter, task_id, task_num, mode): qry_logits = net(x_qry) qry_loss = F.cross_entropy(qry_logits, y_qry).cpu() - qry_acc = (qry_logits.argmax(dim=1) == y_qry).sum().cpu().item() / querysz + qry_acc = (qry_logits.argmax(dim=1) == y_qry).mean().cpu().item() return qry_loss, qry_acc @@ -275,11 +274,11 @@ def train(net: nn.Module, meta_opt: optim.Adam, epoch: int, log: list): qry_acc = 100.0 * qry_acc i = epoch + float(batch_idx) / n_train_iter iter_time = time.time() - start_time + torch.cuda.empty_cache() print( f'[Epoch {i:.2f}] Train Loss: {qry_loss:.2f} | Acc: {qry_acc:.2f} | Time: {iter_time:.2f}' ) - log.append( { 'epoch': i, @@ -319,6 +318,8 @@ def test(net, epoch, log): qry_losses = np.mean(qry_losses) qry_accs = 100.0 * np.mean(qry_accs) + torch.cuda.empty_cache() + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( { diff --git a/examples/few-shot/support/omniglot_loaders.py b/examples/few-shot/helpers/omniglot_loaders.py similarity index 100% rename from examples/few-shot/support/omniglot_loaders.py rename to examples/few-shot/helpers/omniglot_loaders.py diff --git a/examples/few-shot/maml_omniglot.py b/examples/few-shot/maml_omniglot.py index 766391db..879a235a 100644 --- a/examples/few-shot/maml_omniglot.py +++ b/examples/few-shot/maml_omniglot.py @@ -54,7 +54,7 @@ import torchopt -from support.omniglot_loaders import OmniglotNShot # isort: skip +from helpers.omniglot_loaders import OmniglotNShot # isort: skip mpl.use('Agg') @@ -133,8 +133,7 @@ def train(db, net, meta_opt, epoch, log): # Sample a batch of support and query images and labels. x_spt, y_spt, x_qry, y_qry = db.next() - task_num, setsz, c_, h, w = x_spt.size() - querysz = x_qry.size(1) + task_num = x_spt.size(0) # TODO: Maybe pull this out into a separate module so it # doesn't have to be duplicated between `train` and `test`? @@ -165,9 +164,9 @@ def train(db, net, meta_opt, epoch, log): # These will be used to update the model's meta-parameters. qry_logits = net(x_qry[i]) qry_loss = F.cross_entropy(qry_logits, y_qry[i]) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() qry_losses.append(qry_loss) - qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).sum().item() / querysz - qry_accs.append(qry_acc) + qry_accs.append(qry_acc.item()) torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) @@ -176,14 +175,14 @@ def train(db, net, meta_opt, epoch, log): qry_losses.backward() meta_opt.step() qry_losses = qry_losses.item() - qry_accs = 100.0 * sum(qry_accs) / task_num + qry_accs = 100.0 * np.mean(qry_accs) i = epoch + float(batch_idx) / n_train_iter iter_time = time.time() - start_time + torch.cuda.empty_cache() print( f'[Epoch {i:.2f}] Train Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f} | Time: {iter_time:.2f}' ) - log.append( { 'epoch': i, @@ -211,8 +210,7 @@ def test(db, net, epoch, log): for batch_idx in range(n_test_iter): x_spt, y_spt, x_qry, y_qry = db.next('test') - task_num, setsz, c_, h, w = x_spt.size() - querysz = x_qry.size(1) + task_num = x_spt.size(0) # TODO: Maybe pull this out into a separate module so it # doesn't have to be duplicated between `train` and `test`? @@ -231,15 +229,18 @@ def test(db, net, epoch, log): # The query loss and acc induced by these parameters. qry_logits = net(x_qry[i]).detach() - qry_loss = F.cross_entropy(qry_logits, y_qry[i], reduction='none') - qry_losses.append(qry_loss.detach()) - qry_accs.append((qry_logits.argmax(dim=1) == y_qry[i]).detach()) + qry_loss = F.cross_entropy(qry_logits, y_qry[i]) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() + qry_losses.append(qry_loss.item()) + qry_accs.append(qry_acc.item()) torchopt.recover_state_dict(net, net_state_dict) torchopt.recover_state_dict(inner_opt, optim_state_dict) - qry_losses = torch.mean(torch.stack(qry_losses)).item() - qry_accs = 100.0 * torch.cat(qry_accs).float().mean().item() + qry_losses = np.mean(qry_losses) + qry_accs = 100.0 * np.mean(qry_accs) + torch.cuda.empty_cache() + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( { diff --git a/examples/iMAML/README.md b/examples/iMAML/README.md index 91f95f69..6208bc81 100644 --- a/examples/iMAML/README.md +++ b/examples/iMAML/README.md @@ -6,7 +6,8 @@ Code on implicit MAML few-shot Omniglot classification in paper [Meta-Learning w ```bash ### Run -python3 imaml_omniglot.py --inner_steps 5 +python3 imaml_omniglot.py --inner_steps 5 # use OOP APIs +python3 imaml_omniglot_functional.py --inner_steps 5 # use functional APIs ``` ## Results @@ -16,3 +17,7 @@ The figure illustrate the experimental result.
    + +
    + +
    diff --git a/examples/iMAML/support/omniglot_loaders.py b/examples/iMAML/helpers/omniglot_loaders.py similarity index 100% rename from examples/iMAML/support/omniglot_loaders.py rename to examples/iMAML/helpers/omniglot_loaders.py diff --git a/examples/iMAML/imaml-accs-functional.png b/examples/iMAML/imaml-accs-functional.png new file mode 100644 index 0000000000000000000000000000000000000000..a23132cfa22de512b09d6c52813f13fc0f603aff GIT binary patch literal 183882 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

    T#qHT68_G1dgkxpI8rp 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 literal 0 HcmV?d00001 diff --git a/examples/iMAML/imaml-accs.png b/examples/iMAML/imaml-accs.png index 1d5134a4d7f50db54d7129e45b71032c538804f8..c0296be8c7c7b33c2b74121392fbe96dc4c56833 100644 GIT binary patch literal 169952 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�h|Q~EmCNQrX0N==s6xGCOY(1 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

    T#qHT68_G1dgkxpI8rp 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 diff --git a/examples/iMAML/imaml-accs.png b/examples/iMAML/imaml-accs.png index c0296be8c7c7b33c2b74121392fbe96dc4c56833..1a6a56365391eb29a7bd2a9e27a8dccd5f39180a 100644 GIT binary patch literal 168922 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�h3&{o{Fv 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 k+K6h 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 V?OyvUL9qeHg@=_L>;h>08aqUU?9 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�h|Q~EmCNQrX0N==s6xGCOY(1 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ⅇ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 a3VG~W{pAgr$c^+G%uU None: + """Update the tensor containers in ``dst_containers`` with the ones in ``src_containers``.""" + for src_container, dst_container in zip(src_containers, dst_containers): + dst_container.update(src_container) + + +@contextlib.contextmanager +def container_context( + orig_containers: Iterable[Dict[str, Optional[torch.Tensor]]], + args_containers: Iterable[Dict[str, Optional[torch.Tensor]]], +) -> Generator[None, None, None]: + # pylint: disable-next=line-too-long + """A context manager that temporarily updates the containers in ``orig_containers`` with the ones in ``args_containers``.""" + if not isinstance(orig_containers, (list, tuple)): + orig_containers = list(orig_containers) + orig_containers_backups = [container.copy() for container in orig_containers] + try: + update_containers(orig_containers, args_containers) + yield + finally: + update_containers(orig_containers, orig_containers_backups) + + def make_optimality_from_objective( objective: Callable[..., torch.Tensor] ) -> Callable[..., TupleOfTensors]: """Make a function that computes the optimality function of the objective function.""" - # pylint: disable-next=redefined-builtin + def optimality(self: 'ImplicitMetaGradientModule', *input, **kwargs) -> TupleOfTensors: params_containers = extract_module_containers(self, with_buffers=False)[0] - params_containers_backups = [container.copy() for container in params_containers] flat_params: TupleOfTensors # pylint: disable-next=line-too-long flat_params, params_containers_treespec = pytree.tree_flatten_as_tuple(params_containers) # type: ignore[arg-type] - # pylint: disable-next=redefined-builtin def objective_fn(flat_params: TupleOfTensors, *input, **kwargs) -> torch.Tensor: flat_grad_tracking_params = flat_params grad_tracking_params_containers: Tuple[ @@ -52,18 +79,8 @@ def objective_fn(flat_params: TupleOfTensors, *input, **kwargs) -> torch.Tensor: params_containers_treespec, flat_grad_tracking_params ) - try: - for container, grad_tracking_container in zip( - params_containers, grad_tracking_params_containers - ): - container.update(grad_tracking_container) - + with container_context(params_containers, grad_tracking_params_containers): return objective(self, *input, **kwargs) - finally: - for container, container_backup in zip( - params_containers, params_containers_backups - ): - container.update(container_backup) objective_grad_fn = functorch.grad(objective_fn, argnums=0) flat_grads = objective_grad_fn(flat_params, *input, **kwargs) @@ -87,7 +104,7 @@ def enable_implicit_gradients( @functools.wraps(cls_solve) def wrapped( # pylint: disable=too-many-locals - self: 'ImplicitMetaGradientModule', *input, **kwargs # pylint: disable=redefined-builtin + self: 'ImplicitMetaGradientModule', *input, **kwargs ) -> Union['ImplicitMetaGradientModule', Tuple['ImplicitMetaGradientModule', Any]]: """Solve the optimization problem.""" params_containers = extract_module_containers(self, with_buffers=False)[0] @@ -97,10 +114,6 @@ def wrapped( # pylint: disable=too-many-locals extract_module_containers(meta_module, with_buffers=False)[0] ) meta_params_containers = tuple(meta_params_containers) - params_containers_backups = tuple(container.copy() for container in params_containers) - meta_params_containers_backups = tuple( - container.copy() for container in meta_params_containers - ) flat_params: TupleOfTensors flat_meta_params: TupleOfTensors @@ -114,7 +127,7 @@ def wrapped( # pylint: disable=too-many-locals def optimality_fn( flat_params: TupleOfTensors, flat_meta_params: TupleOfTensors, - *input, # pylint: disable=redefined-builtin + *input, **kwargs, ) -> TupleOfTensors: flat_grad_tracking_params = flat_params @@ -130,26 +143,23 @@ def optimality_fn( meta_params_containers_treespec, flat_grad_tracking_meta_params ) - try: - for container, grad_tracking_container in itertools.chain( - zip(params_containers, grad_tracking_params_containers), - zip(meta_params_containers, grad_tracking_meta_params_containers), - ): - container.update(grad_tracking_container) - + with container_context( + itertools.chain( + params_containers, + meta_params_containers, + ), + itertools.chain( + grad_tracking_params_containers, + grad_tracking_meta_params_containers, + ), + ): return self.optimality(*input, **kwargs) - finally: - for container, container_backup in itertools.chain( - zip(params_containers, params_containers_backups), - zip(meta_params_containers, meta_params_containers_backups), - ): - container.update(container_backup) @custom_root(optimality_fn, argnums=1, **custom_root_kwargs) # type: ignore[arg-type] def solver_fn( flat_params: TupleOfTensors, # pylint: disable=unused-argument flat_meta_params: TupleOfTensors, # pylint: disable=unused-argument - *input, # pylint: disable=redefined-builtin + *input, **kwargs, ) -> Union[TupleOfTensors, Tuple[TupleOfTensors, Any]]: output = cls_solve(self, *input, **kwargs) @@ -227,7 +237,7 @@ def __init_subclass__( enable_implicit_gradients(cls) def solve( - self, *input, **kwargs # pylint: disable=redefined-builtin + self, *input, **kwargs ) -> Union['ImplicitMetaGradientModule', Tuple['ImplicitMetaGradientModule', Any]]: """Solves the inner optimization problem. @@ -259,7 +269,6 @@ def solve(self, batch, labels): """ raise NotImplementedError # update parameters - # pylint: disable-next=redefined-builtin def optimality(self, *input, **kwargs) -> TensorTree: r"""Computes the optimality residual. @@ -302,7 +311,6 @@ def optimality(self, *input, **kwargs) -> TensorTree: """ # pylint: disable=line-too-long raise NotImplementedError - # pylint: disable-next=redefined-builtin def objective(self, *input, **kwargs) -> torch.Tensor: """Computes the objective function value. diff --git a/torchopt/optim/meta/adam.py b/torchopt/optim/meta/adam.py index 8d934e2c..9340b513 100644 --- a/torchopt/optim/meta/adam.py +++ b/torchopt/optim/meta/adam.py @@ -37,7 +37,7 @@ class MetaAdam(MetaOptimizer): # pylint: disable-next=too-many-arguments def __init__( self, - net: nn.Module, + module: nn.Module, lr: ScalarOrSchedule = 1e-3, betas: Tuple[float, float] = (0.9, 0.999), eps: float = 1e-8, @@ -51,7 +51,7 @@ def __init__( """The :meth:`init` function. Args: - net: (nn.Module) + module: (nn.Module) A network whose parameters should be optimized. lr: (default: :const:`1e-3`) This is a fixed global scaling factor. @@ -75,7 +75,7 @@ def __init__( If :data:`True` use our implemented fused operator. """ super().__init__( - net, + module, alias.adam( lr=lr, betas=betas, diff --git a/torchopt/optim/meta/adamw.py b/torchopt/optim/meta/adamw.py index cb91f38f..70f3a80a 100644 --- a/torchopt/optim/meta/adamw.py +++ b/torchopt/optim/meta/adamw.py @@ -37,7 +37,7 @@ class MetaAdamW(MetaOptimizer): # pylint: disable-next=too-many-arguments def __init__( self, - net: nn.Module, + module: nn.Module, lr: ScalarOrSchedule = 1e-3, betas: Tuple[float, float] = (0.9, 0.999), eps: float = 1e-8, @@ -52,7 +52,7 @@ def __init__( """The :meth:`init` function. Args: - net: (nn.Module) + module: (nn.Module) A network whose parameters should be optimized. lr: (default: :const:`1e-3`) This is a fixed global scaling factor. @@ -85,7 +85,7 @@ def __init__( If :data:`True` use our implemented fused operator. """ super().__init__( - net, + module, alias.adamw( lr=lr, betas=betas, diff --git a/torchopt/optim/meta/base.py b/torchopt/optim/meta/base.py index b83d3fd2..7af32e17 100644 --- a/torchopt/optim/meta/base.py +++ b/torchopt/optim/meta/base.py @@ -14,7 +14,7 @@ # ============================================================================== """The base class for differentiable meta-optimizers.""" -from typing import Dict, List, Optional, Sequence, Tuple, cast +from typing import Dict, List, Optional, Sequence, Tuple import torch import torch.nn as nn @@ -31,11 +31,11 @@ class MetaOptimizer: """The base class for high-level differentiable optimizers.""" - def __init__(self, net: nn.Module, impl: GradientTransformation): + def __init__(self, module: nn.Module, impl: GradientTransformation) -> None: """The :meth:`init` function. Args: - net: (nn.Module) + module: (nn.Module) A network whose parameters should be optimized. impl: (GradientTransformation) A low level optimizer function, it could be a optimizer function provided by @@ -51,9 +51,9 @@ def __init__(self, net: nn.Module, impl: GradientTransformation): self.param_containers_groups: List[Tuple[Dict[str, Optional[torch.Tensor]], ...]] = [] self.state_groups: List[OptState] = [] - self.add_param_group(net) + self.add_param_group(module) - def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals + def step(self, loss: torch.Tensor) -> None: # pylint: disable=too-many-locals """Compute the gradients of the loss to the network parameters and update network parameters. Graph of the derivative will be constructed, allowing to compute higher order derivative @@ -84,16 +84,17 @@ def step(self, loss: torch.Tensor): # pylint: disable=too-many-locals ) self.state_groups[i] = new_state flat_new_params = apply_updates(flat_params, updates, inplace=False) - new_params = cast( - Tuple[Dict[str, Optional[torch.Tensor]], ...], - pytree.tree_unflatten(container_treespec, flat_new_params), + new_params: Tuple[ + Dict[str, Optional[torch.Tensor]], ... + ] = pytree.tree_unflatten( # type: ignore[assignment] + container_treespec, flat_new_params ) for container, new_param in zip(param_container, new_params): container.update(new_param) - def add_param_group(self, net: nn.Module) -> None: + def add_param_group(self, module: nn.Module) -> None: """Add a param group to the optimizer's :attr:`state_groups`.""" - params_container = extract_module_containers(net, with_buffers=False)[0] + params_container = extract_module_containers(module, with_buffers=False)[0] flat_params: TupleOfTensors = tuple(pytree.tree_leaves(params_container)) # type: ignore[arg-type] optimizer_state = self.impl.init(flat_params) self.param_containers_groups.append(params_container) diff --git a/torchopt/optim/meta/rmsprop.py b/torchopt/optim/meta/rmsprop.py index e7bc9b37..47c3e983 100644 --- a/torchopt/optim/meta/rmsprop.py +++ b/torchopt/optim/meta/rmsprop.py @@ -35,7 +35,7 @@ class MetaRMSProp(MetaOptimizer): # pylint: disable-next=too-many-arguments def __init__( self, - net: nn.Module, + module: nn.Module, lr: ScalarOrSchedule = 1e-2, alpha: float = 0.99, eps: float = 1e-8, @@ -50,7 +50,7 @@ def __init__( """The :meth:`init` function. Args: - net: (nn.Module) + module: (nn.Module) A network whose parameters should be optimized. lr: (default: :const:`1e-2`) This is a fixed global scaling factor. @@ -76,7 +76,7 @@ def __init__( Maximize the params based on the objective, instead of minimizing. """ super().__init__( - net, + module, alias.rmsprop( lr=lr, alpha=alpha, diff --git a/torchopt/optim/meta/sgd.py b/torchopt/optim/meta/sgd.py index 78b8e2fc..f46158a6 100644 --- a/torchopt/optim/meta/sgd.py +++ b/torchopt/optim/meta/sgd.py @@ -35,7 +35,7 @@ class MetaSGD(MetaOptimizer): # pylint: disable-next=too-many-arguments def __init__( self, - net: nn.Module, + module: nn.Module, lr: ScalarOrSchedule, momentum: float = 0.0, weight_decay: float = 0.0, @@ -47,7 +47,7 @@ def __init__( """The :meth:`init` function. Args: - net: (nn.Module) + module: (nn.Module) A network whose parameters should be optimized. lr: This is a fixed global scaling factor. momentum: (default: :const:`0.0`) @@ -66,7 +66,7 @@ def __init__( Maximize the params based on the objective, instead of minimizing. """ super().__init__( - net, + module, alias.sgd( lr=lr, momentum=momentum, diff --git a/torchopt/utils.py b/torchopt/utils.py index cfe25e32..404dfee1 100644 --- a/torchopt/utils.py +++ b/torchopt/utils.py @@ -85,9 +85,10 @@ def stop_gradient(target: Union[TensorTree, ModuleState, nn.Module, 'MetaOptimiz # pylint: disable-next=import-outside-toplevel from torchopt.optim.meta.base import MetaOptimizer - def f(obj): + def fn_(obj): if isinstance(obj, torch.Tensor): - obj.detach_().requires_grad_(obj.requires_grad) + requires_grad = obj.requires_grad + obj.detach_().requires_grad_(requires_grad) if isinstance(target, ModuleState): true_target = cast(TensorTree, (target.params, target.buffers)) @@ -98,7 +99,7 @@ def f(obj): else: true_target = cast(TensorTree, target) # tree of tensors - pytree.tree_map(f, true_target) + pytree.tree_map(fn_, true_target) @overload diff --git a/tutorials/5_Implicit_Differentiation.ipynb b/tutorials/5_Implicit_Differentiation.ipynb index f52aceb1..c83e69b8 100644 --- a/tutorials/5_Implicit_Differentiation.ipynb +++ b/tutorials/5_Implicit_Differentiation.ipynb @@ -78,11 +78,11 @@ "outputs": [], "source": [ "# Optimality function\n", - "def imaml_objective(optimal_params, init_params, data):\n", + "def imaml_objective(params, meta_params, data):\n", " x, y, fmodel = data\n", - " y_pred = fmodel(optimal_params, x)\n", + " y_pred = fmodel(params, x)\n", " regularization_loss = 0.0\n", - " for p1, p2 in zip(optimal_params, init_params):\n", + " for p1, p2 in zip(params, meta_params):\n", " regularization_loss += 0.5 * torch.sum(torch.square(p1.view(-1) - p2.view(-1)))\n", " loss = F.mse_loss(y_pred, y) + regularization_loss\n", " return loss\n", @@ -94,13 +94,12 @@ "# You can also set argnums as (1, 2) if you want to backpropogate through multiple meta parameters\n", "\n", "# Here we pass argnums=1 to the custom_root. That means we want to compute the gradient of\n", - "# optimal_params w.r.t. the 1-indexed argument in inner_solver, i.e., init_params.\n", + "# optimal_params w.r.t. the 1-indexed argument in inner_solver, i.e., params.\n", "@torchopt.diff.implicit.custom_root(functorch.grad(imaml_objective, argnums=0), argnums=1)\n", - "def inner_solver(init_params_copy, init_params, data):\n", + "def inner_solver(params, meta_params, data):\n", " \"\"\"Solve ridge regression by conjugate gradient.\"\"\"\n", " # Initial functional optimizer based on TorchOpt\n", " x, y, fmodel = data\n", - " params = init_params_copy\n", " optimizer = torchopt.sgd(lr=2e-2)\n", " opt_state = optimizer.init(params)\n", " with torch.enable_grad():\n", @@ -111,13 +110,13 @@ "\n", " # Compute regularization loss\n", " regularization_loss = 0.0\n", - " for p1, p2 in zip(params, init_params):\n", + " for p1, p2 in zip(params, meta_params):\n", " regularization_loss += 0.5 * torch.sum(torch.square(p1.view(-1) - p2.view(-1)))\n", " final_loss = loss + regularization_loss\n", "\n", " grads = torch.autograd.grad(final_loss, params) # compute gradients\n", - " updates, opt_state = optimizer.update(grads, opt_state) # get updates\n", - " params = torchopt.apply_updates(params, updates)\n", + " updates, opt_state = optimizer.update(grads, opt_state, inplace=True) # get updates\n", + " params = torchopt.apply_updates(params, updates, inplace=True)\n", "\n", " optimal_params = params\n", " return optimal_params" From 824934bc4410e70af5c53750a8ed20b1d831ad69 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 5 Nov 2022 19:45:29 +0800 Subject: [PATCH 40/69] fix(examples): fix mean over boolean tensor --- examples/FuncTorch/maml_omniglot_vmap.py | 2 +- examples/distributed/few-shot/maml_omniglot.py | 2 +- examples/distributed/few-shot/maml_omniglot_local_loader.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/FuncTorch/maml_omniglot_vmap.py b/examples/FuncTorch/maml_omniglot_vmap.py index 9f3c1d92..41c17db8 100644 --- a/examples/FuncTorch/maml_omniglot_vmap.py +++ b/examples/FuncTorch/maml_omniglot_vmap.py @@ -164,7 +164,7 @@ def compute_loss(new_params, buffers, x, y): # These will be used to update the model's meta-parameters. qry_logits = fnet(new_params, buffers, x_qry) qry_loss = F.cross_entropy(qry_logits, y_qry) - qry_acc = (qry_logits.argmax(dim=1) == y_qry).mean() + qry_acc = (qry_logits.argmax(dim=1) == y_qry).float().mean() return qry_loss, qry_acc diff --git a/examples/distributed/few-shot/maml_omniglot.py b/examples/distributed/few-shot/maml_omniglot.py index 78a85d71..879792ff 100644 --- a/examples/distributed/few-shot/maml_omniglot.py +++ b/examples/distributed/few-shot/maml_omniglot.py @@ -196,7 +196,7 @@ def inner_loop(net_rref, x_spt, y_spt, x_qry, y_qry, n_inner_iter): qry_logits = net(x_qry) qry_loss = F.cross_entropy(qry_logits, y_qry).cpu() - qry_acc = (qry_logits.argmax(dim=1) == y_qry).mean().cpu().item() + qry_acc = (qry_logits.argmax(dim=1) == y_qry).float().mean().item() return qry_loss, qry_acc diff --git a/examples/distributed/few-shot/maml_omniglot_local_loader.py b/examples/distributed/few-shot/maml_omniglot_local_loader.py index d41a7dae..f7f9e4f0 100644 --- a/examples/distributed/few-shot/maml_omniglot_local_loader.py +++ b/examples/distributed/few-shot/maml_omniglot_local_loader.py @@ -237,7 +237,7 @@ def inner_loop(net_rref, n_inner_iter, task_id, task_num, mode): qry_logits = net(x_qry) qry_loss = F.cross_entropy(qry_logits, y_qry).cpu() - qry_acc = (qry_logits.argmax(dim=1) == y_qry).mean().cpu().item() + qry_acc = (qry_logits.argmax(dim=1) == y_qry).float().mean().item() return qry_loss, qry_acc From 23253b16e5e5f0dbf0d063f991cd4a41568c26ab Mon Sep 17 00:00:00 2001 From: Hello_World Date: Sun, 6 Nov 2022 23:04:54 +0800 Subject: [PATCH 41/69] perf(acc_op): add if condition for the element number small situations (#105) Co-authored-by: Xuehai Pan --- CHANGELOG.md | 1 + src/adam_op/adam_op_impl_cpu.cpp | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a01f6751..d0747f6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add if condition of number of threads for CPU OPs by [@JieRen98](https://github.com/JieRen98) in [#105](https://github.com/metaopt/torchopt/pull/105). - Add implicit MAML omniglot few-shot classification example with OOP APIs by [@XuehaiPan](https://github.com/XuehaiPan) in [#107](https://github.com/metaopt/torchopt/pull/107). - Add implicit MAML omniglot few-shot classification example by [@Benjamin-eecs](https://github.com/Benjamin-eecs) in [#48](https://github.com/metaopt/torchopt/pull/48). - Add object-oriented modules support for implicit meta-gradient by [@XuehaiPan](https://github.com/XuehaiPan) in [#101](https://github.com/metaopt/torchopt/pull/101). diff --git a/src/adam_op/adam_op_impl_cpu.cpp b/src/adam_op/adam_op_impl_cpu.cpp index 82accd8c..c2ae4ae0 100644 --- a/src/adam_op/adam_op_impl_cpu.cpp +++ b/src/adam_op/adam_op_impl_cpu.cpp @@ -27,6 +27,8 @@ using std::size_t; namespace adam_op { +constexpr size_t MIN_NUMEL_USE_OMP = 1000; + template void adamForwardInplaceCPUKernel(const other_t b1, const other_t inv_one_minus_pow_b1, @@ -38,7 +40,9 @@ void adamForwardInplaceCPUKernel(const other_t b1, scalar_t *__restrict__ updates_ptr, scalar_t *__restrict__ mu_ptr, scalar_t *__restrict__ nu_ptr) { -#pragma omp parallel for num_threads(omp_get_num_procs()) +#pragma omp parallel for num_threads( \ + std::min(n / MIN_NUMEL_USE_OMP, \ + static_cast (omp_get_num_procs()))) if (n > MIN_NUMEL_USE_OMP) // NOLINT for (size_t tid = 0; tid < n; ++tid) { const scalar_t updates = updates_ptr[tid]; const scalar_t mu = mu_ptr[tid]; @@ -90,7 +94,9 @@ void adamForwardMuCPUKernel(const scalar_t *__restrict__ updates_ptr, const other_t b1, const size_t n, scalar_t *__restrict__ mu_out_ptr) { -#pragma omp parallel for num_threads(omp_get_num_procs()) +#pragma omp parallel for num_threads( \ + std::min(n / MIN_NUMEL_USE_OMP, \ + static_cast (omp_get_num_procs()))) if (n > MIN_NUMEL_USE_OMP) // NOLINT for (size_t tid = 0; tid < n; ++tid) { const scalar_t updates = updates_ptr[tid]; const scalar_t mu = mu_ptr[tid]; @@ -122,7 +128,9 @@ void adamForwardNuCPUKernel(const scalar_t *__restrict__ updates_ptr, const other_t b2, const size_t n, scalar_t *__restrict__ nu_out_ptr) { -#pragma omp parallel for num_threads(omp_get_num_procs()) +#pragma omp parallel for num_threads( \ + std::min(n / MIN_NUMEL_USE_OMP, \ + static_cast (omp_get_num_procs()))) if (n > MIN_NUMEL_USE_OMP) // NOLINT for (size_t tid = 0; tid < n; ++tid) { const scalar_t updates = updates_ptr[tid]; const scalar_t nu = nu_ptr[tid]; @@ -158,7 +166,9 @@ void adamForwardUpdatesCPUKernel(const scalar_t *__restrict__ new_mu_ptr, const other_t eps_root, const size_t n, scalar_t *__restrict__ updates_out_ptr) { -#pragma omp parallel for num_threads(omp_get_num_procs()) +#pragma omp parallel for num_threads( \ + std::min(n / MIN_NUMEL_USE_OMP, \ + static_cast (omp_get_num_procs()))) if (n > MIN_NUMEL_USE_OMP) // NOLINT for (size_t tid = 0; tid < n; ++tid) { const scalar_t new_mu = new_mu_ptr[tid]; const scalar_t new_nu = new_nu_ptr[tid]; @@ -205,7 +215,9 @@ void adamBackwardMuCPUKernel(const scalar_t *__restrict__ dmu_ptr, const size_t n, scalar_t *__restrict__ dupdates_out_ptr, scalar_t *__restrict__ dmu_out_ptr) { -#pragma omp parallel for num_threads(omp_get_num_procs()) +#pragma omp parallel for num_threads( \ + std::min(n / MIN_NUMEL_USE_OMP, \ + static_cast (omp_get_num_procs()))) if (n > MIN_NUMEL_USE_OMP) // NOLINT for (size_t tid = 0; tid < n; ++tid) { const scalar_t dmu = dmu_ptr[tid]; @@ -240,7 +252,9 @@ void adamBackwardNuCPUKernel(const scalar_t *__restrict__ dnu_ptr, const size_t n, scalar_t *__restrict__ dupdates_out_ptr, scalar_t *__restrict__ dnu_out_ptr) { -#pragma omp parallel for num_threads(omp_get_num_procs()) +#pragma omp parallel for num_threads( \ + std::min(n / MIN_NUMEL_USE_OMP, \ + static_cast (omp_get_num_procs()))) if (n > MIN_NUMEL_USE_OMP) // NOLINT for (size_t tid = 0; tid < n; ++tid) { const scalar_t dnu = dnu_ptr[tid]; const scalar_t updates = updates_ptr[tid]; @@ -279,7 +293,9 @@ void adamBackwardUpdatesCPUKernel(const scalar_t *__restrict__ dupdates_ptr, const size_t n, scalar_t *__restrict__ dnew_mu_out_ptr, scalar_t *__restrict__ dnew_nu_out_ptr) { -#pragma omp parallel for num_threads(omp_get_num_procs()) +#pragma omp parallel for num_threads( \ + std::min(n / MIN_NUMEL_USE_OMP, \ + static_cast (omp_get_num_procs()))) if (n > MIN_NUMEL_USE_OMP) // NOLINT for (size_t tid = 0; tid < n; ++tid) { const scalar_t dupdates = dupdates_ptr[tid]; const scalar_t updates = updates_ptr[tid]; From 37e82681f78b72851c5bf8ad1c4416f3ec8b7ec8 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Wed, 9 Nov 2022 15:54:19 +0800 Subject: [PATCH 42/69] feat(linear_solve): matrix inversion linear solver with neumann series approximation (#98) * feat(linear_solve): matrix inversion linear solver with neumann series approximation Co-authored-by: Xuehai Pan --- .pylintrc | 3 +- CHANGELOG.md | 1 + docs/source/api/api.rst | 4 +- docs/source/spelling_wordlist.txt | 1 + tests/test_implicit.py | 260 ++++++++++++++++++++++++++++- torchopt/linalg/__init__.py | 3 +- torchopt/linalg/cg.py | 57 ++----- torchopt/linalg/ns.py | 161 ++++++++++++++++++ torchopt/linalg/utils.py | 55 ++++++ torchopt/linear_solve/__init__.py | 3 +- torchopt/linear_solve/cg.py | 32 +++- torchopt/linear_solve/inv.py | 122 ++++++++++++++ torchopt/linear_solve/normal_cg.py | 34 +++- torchopt/linear_solve/utils.py | 52 +++++- torchopt/pytree.py | 122 +++++++++++++- 15 files changed, 831 insertions(+), 79 deletions(-) create mode 100644 torchopt/linalg/ns.py create mode 100644 torchopt/linalg/utils.py create mode 100644 torchopt/linear_solve/inv.py diff --git a/.pylintrc b/.pylintrc index 73dbcdf0..6b86faaf 100644 --- a/.pylintrc +++ b/.pylintrc @@ -267,7 +267,8 @@ good-names=i, lr, mu, nu, - x + x, + y # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted diff --git a/CHANGELOG.md b/CHANGELOG.md index d0747f6c..278ad1d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add matrix inversion linear solver with neumann series approximation by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@XuehaiPan](https://github.com/XuehaiPan) in [#98](https://github.com/metaopt/torchopt/pull/98). - Add if condition of number of threads for CPU OPs by [@JieRen98](https://github.com/JieRen98) in [#105](https://github.com/metaopt/torchopt/pull/105). - Add implicit MAML omniglot few-shot classification example with OOP APIs by [@XuehaiPan](https://github.com/XuehaiPan) in [#107](https://github.com/metaopt/torchopt/pull/107). - Add implicit MAML omniglot few-shot classification example by [@Benjamin-eecs](https://github.com/Benjamin-eecs) in [#48](https://github.com/metaopt/torchopt/pull/48). diff --git a/docs/source/api/api.rst b/docs/source/api/api.rst index 1ec8e1d2..97d8af30 100644 --- a/docs/source/api/api.rst +++ b/docs/source/api/api.rst @@ -157,7 +157,7 @@ Implicit Meta-Gradient Module ------ -Linear system solving +Linear system solvers ===================== .. currentmodule:: torchopt.linear_solve @@ -166,12 +166,14 @@ Linear system solving solve_cg solve_normal_cg + solve_inv Indirect solvers ~~~~~~~~~~~~~~~~ .. autofunction:: solve_cg .. autofunction:: solve_normal_cg +.. autofunction:: solve_inv ------ diff --git a/docs/source/spelling_wordlist.txt b/docs/source/spelling_wordlist.txt index 25f11953..cd8bb152 100644 --- a/docs/source/spelling_wordlist.txt +++ b/docs/source/spelling_wordlist.txt @@ -92,3 +92,4 @@ ints Karush Kuhn Tucker +Neumann diff --git a/tests/test_implicit.py b/tests/test_implicit.py index 661a6627..5655988a 100644 --- a/tests/test_implicit.py +++ b/tests/test_implicit.py @@ -24,6 +24,7 @@ import jaxopt import numpy as np import optax +import pytest import torch import torch.nn as nn import torch.nn.functional as F @@ -82,7 +83,6 @@ def get_model_torch( dataset = data.TensorDataset( torch.randint(0, 1, (BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS)), - # torch.empty((BATCH_SIZE * NUM_UPDATES, MODEL_NUM_INPUTS), dtype=dtype).uniform_(-1.0, +1.0), torch.randint(0, MODEL_NUM_CLASSES, (BATCH_SIZE * NUM_UPDATES,)), ) loader = data.DataLoader(dataset, BATCH_SIZE, shuffle=False) @@ -113,7 +113,9 @@ def get_rr_dataset_torch() -> data.DataLoader: inner_lr=[2e-2, 2e-3], inner_update=[20, 50, 100], ) -def test_imaml(dtype: torch.dtype, lr: float, inner_lr: float, inner_update: int) -> None: +def test_imaml_solve_normal_cg( + dtype: torch.dtype, lr: float, inner_lr: float, inner_update: int +) -> None: np_dtype = helpers.dtype_torch2numpy(dtype) jax_model, jax_params = get_model_jax(dtype=np_dtype) @@ -136,7 +138,10 @@ def imaml_objective_torchopt(params, meta_params, data): return loss @torchopt.diff.implicit.custom_root( - functorch.grad(imaml_objective_torchopt, argnums=0), argnums=1, has_aux=True + functorch.grad(imaml_objective_torchopt, argnums=0), + argnums=1, + has_aux=True, + solve=torchopt.linear_solve.solve_normal_cg(), ) def inner_solver_torchopt(params, meta_params, data): # Initial functional optimizer based on TorchOpt @@ -167,7 +172,11 @@ def imaml_objective_jax(params, meta_params, x, y): loss = loss + regularization_loss return loss - @jaxopt.implicit_diff.custom_root(jax.grad(imaml_objective_jax, argnums=0), has_aux=True) + @jaxopt.implicit_diff.custom_root( + jax.grad(imaml_objective_jax, argnums=0), + has_aux=True, + solve=jaxopt.linear_solve.solve_normal_cg, + ) def inner_solver_jax(params, meta_params, x, y): """Solve ridge regression by conjugate gradient.""" # Initial functional optimizer based on torchopt @@ -225,6 +234,134 @@ def outer_level(p, xs, ys): helpers.assert_all_close(p, p_ref) +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-3, 1e-4], + inner_lr=[2e-2, 2e-3], + inner_update=[20, 50, 100], + ns=[False, True], +) +def test_imaml_solve_inv( + dtype: torch.dtype, + lr: float, + inner_lr: float, + inner_update: int, + ns: bool, +) -> None: + np_dtype = helpers.dtype_torch2numpy(dtype) + + jax_model, jax_params = get_model_jax(dtype=np_dtype) + model, loader = get_model_torch(device='cpu', dtype=dtype) + + fmodel, params = functorch.make_functional(model) + optim = torchopt.sgd(lr) + optim_state = optim.init(params) + + optim_jax = optax.sgd(lr) + optim_state_jax = optim_jax.init(jax_params) + + def imaml_objective_torchopt(params, meta_params, data): + x, y, f = data + y_pred = f(params, x) + regularization_loss = 0 + for p1, p2 in zip(params, meta_params): + regularization_loss += 0.5 * torch.sum(torch.square(p1 - p2)) + loss = F.cross_entropy(y_pred, y) + regularization_loss + return loss + + @torchopt.diff.implicit.custom_root( + functorch.grad(imaml_objective_torchopt, argnums=0), + argnums=1, + solve=torchopt.linear_solve.solve_inv(ns=ns), + ) + def inner_solver_torchopt(params, meta_params, data): + # Initial functional optimizer based on TorchOpt + x, y, f = data + optimizer = torchopt.sgd(lr=inner_lr) + opt_state = optimizer.init(params) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(inner_update): + pred = f(params, x) + loss = F.cross_entropy(pred, y) # compute loss + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params, meta_params): + regularization_loss += 0.5 * torch.sum(torch.square(p1 - p2)) + final_loss = loss + regularization_loss + grads = torch.autograd.grad(final_loss, params) # compute gradients + updates, opt_state = optimizer.update(grads, opt_state, inplace=True) # get updates + params = torchopt.apply_updates(params, updates, inplace=True) + return params + + def imaml_objective_jax(params, meta_params, x, y): + y_pred = jax_model(params, x) + loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(y_pred, y)) + regularization_loss = 0 + for p1, p2 in zip(params.values(), meta_params.values()): + regularization_loss += 0.5 * jnp.sum(jnp.square((p1 - p2))) + loss = loss + regularization_loss + return loss + + @jaxopt.implicit_diff.custom_root( + jax.grad(imaml_objective_jax, argnums=0), + solve=jaxopt.linear_solve.solve_normal_cg, + ) + def inner_solver_jax(params, meta_params, x, y): + """Solve ridge regression by conjugate gradient.""" + # Initial functional optimizer based on torchopt + optimizer = optax.sgd(inner_lr) + opt_state = optimizer.init(params) + + def compute_loss(params, meta_params, x, y): + pred = jax_model(params, x) + loss = jnp.mean(optax.softmax_cross_entropy_with_integer_labels(pred, y)) + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params.values(), meta_params.values()): + regularization_loss += 0.5 * jnp.sum(jnp.square((p1 - p2))) + final_loss = loss + regularization_loss + return final_loss + + for i in range(inner_update): + grads = jax.grad(compute_loss)(params, meta_params, x, y) # compute gradients + updates, opt_state = optimizer.update(grads, opt_state) # get updates + params = optax.apply_updates(params, updates) + return params + + for xs, ys in loader: + xs = xs.to(dtype=dtype) + data = (xs, ys, fmodel) + meta_params_copy = pytree.tree_map( + lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params + ) + optimal_params = inner_solver_torchopt(meta_params_copy, params, data) + outer_loss = fmodel(optimal_params, xs).mean() + + grads = torch.autograd.grad(outer_loss, params) + updates, optim_state = optim.update(grads, optim_state) + params = torchopt.apply_updates(params, updates) + + xs = xs.numpy() + ys = ys.numpy() + + def outer_level(p, xs, ys): + optimal_params = inner_solver_jax(copy.deepcopy(p), p, xs, ys) + outer_loss = jax_model(optimal_params, xs).mean() + return outer_loss + + grads_jax = jax.grad(outer_level, argnums=0)(jax_params, xs, ys) + updates_jax, optim_state_jax = optim_jax.update(grads_jax, optim_state_jax) # get updates + jax_params = optax.apply_updates(jax_params, updates_jax) + + jax_params_as_tensor = tuple( + nn.Parameter(torch.tensor(np.asarray(jax_params[j]), dtype=dtype)) for j in jax_params + ) + + for p, p_ref in zip(params, jax_params_as_tensor): + helpers.assert_all_close(p, p_ref) + + @helpers.parametrize( dtype=[torch.float64, torch.float32], lr=[1e-3, 1e-4], @@ -341,7 +478,7 @@ def outer_level(p, xs, ys): dtype=[torch.float64, torch.float32], lr=[1e-3, 1e-4], ) -def test_rr( +def test_rr_solve_cg( dtype: torch.dtype, lr: float, ) -> None: @@ -371,7 +508,7 @@ def ridge_objective_torch(params, l2reg, data): return 0.5 * torch.mean(torch.square(residuals)) + regularization_loss @torchopt.diff.implicit.custom_root(functorch.grad(ridge_objective_torch, argnums=0), argnums=1) - def ridge_solver_torch(params, l2reg, data): + def ridge_solver_torch_cg(params, l2reg, data): """Solve ridge regression by conjugate gradient.""" X_tr, y_tr = data @@ -393,7 +530,7 @@ def ridge_objective_jax(params, l2reg, X_tr, y_tr): return 0.5 * jnp.mean(jnp.square(residuals)) + regularization_loss @jaxopt.implicit_diff.custom_root(jax.grad(ridge_objective_jax, argnums=0)) - def ridge_solver_jax(params, l2reg, X_tr, y_tr): + def ridge_solver_jax_cg(params, l2reg, X_tr, y_tr): """Solve ridge regression by conjugate gradient.""" def matvec(u): @@ -413,7 +550,112 @@ def matvec(u): xq = xq.to(dtype=dtype) yq = yq.to(dtype=dtype) - w_fit = ridge_solver_torch(init_params_torch, l2reg_torch, (xs, ys)) + w_fit = ridge_solver_torch_cg(init_params_torch, l2reg_torch, (xs, ys)) + outer_loss = F.mse_loss(xq @ w_fit, yq) + + grads, *_ = torch.autograd.grad(outer_loss, l2reg_torch) + updates, optim_state = optim.update(grads, optim_state) + l2reg_torch = torchopt.apply_updates(l2reg_torch, updates) + + xs = jnp.array(xs.numpy(), dtype=np_dtype) + ys = jnp.array(ys.numpy(), dtype=np_dtype) + xq = jnp.array(xq.numpy(), dtype=np_dtype) + yq = jnp.array(yq.numpy(), dtype=np_dtype) + + def outer_level(params_jax, l2reg_jax, xs, ys, xq, yq): + w_fit = ridge_solver_jax_cg(params_jax, l2reg_jax, xs, ys) + y_pred = xq @ w_fit + loss_value = jnp.mean(jnp.square(y_pred - yq)) + return loss_value + + grads_jax = jax.grad(outer_level, argnums=1)(init_params_jax, l2reg_jax, xs, ys, xq, yq) + updates_jax, optim_state_jax = optim_jax.update(grads_jax, optim_state_jax) # get updates + l2reg_jax = optax.apply_updates(l2reg_jax, updates_jax) + + l2reg_jax_as_tensor = torch.tensor(np.asarray(l2reg_jax), dtype=dtype) + helpers.assert_all_close(l2reg_torch, l2reg_jax_as_tensor) + + +@helpers.parametrize( + dtype=[torch.float64, torch.float32], + lr=[1e-3, 1e-4], + ns=[True, False], +) +def test_rr_solve_inv( + dtype: torch.dtype, + lr: float, + ns: bool, +) -> None: + if dtype == torch.float64 and ns: + pytest.skip('Neumann Series test skips torch.float64 due to numerical stability.') + helpers.seed_everything(42) + np_dtype = helpers.dtype_torch2numpy(dtype) + input_size = 10 + + init_params_torch = torch.randn(input_size, dtype=dtype) + l2reg_torch = torch.rand(1, dtype=dtype).squeeze_().requires_grad_(True) + + init_params_jax = jnp.array(init_params_torch.detach().numpy(), dtype=np_dtype) + l2reg_jax = jnp.array(l2reg_torch.detach().numpy(), dtype=np_dtype) + + loader = get_rr_dataset_torch() + + optim = torchopt.sgd(lr) + optim_state = optim.init(l2reg_torch) + + optim_jax = optax.sgd(lr) + optim_state_jax = optim_jax.init(l2reg_jax) + + def ridge_objective_torch(params, l2reg, data): + """Ridge objective function.""" + X_tr, y_tr = data + residuals = X_tr @ params - y_tr + regularization_loss = 0.5 * l2reg * torch.sum(torch.square(params)) + return 0.5 * torch.mean(torch.square(residuals)) + regularization_loss + + @torchopt.diff.implicit.custom_root(functorch.grad(ridge_objective_torch, argnums=0), argnums=1) + def ridge_solver_torch_inv(params, l2reg, data): + """Solve ridge regression by conjugate gradient.""" + X_tr, y_tr = data + + def matvec(u): + return X_tr.T @ (X_tr @ u) + + solve = torchopt.linear_solve.solve_inv( + matvec=matvec, + b=X_tr.T @ y_tr, + ridge=len(y_tr) * l2reg.item(), + ns=ns, + ) + + return solve(matvec=matvec, b=X_tr.T @ y_tr) + + def ridge_objective_jax(params, l2reg, X_tr, y_tr): + """Ridge objective function.""" + residuals = X_tr @ params - y_tr + regularization_loss = 0.5 * l2reg * jnp.sum(jnp.square(params)) + return 0.5 * jnp.mean(jnp.square(residuals)) + regularization_loss + + @jaxopt.implicit_diff.custom_root(jax.grad(ridge_objective_jax, argnums=0)) + def ridge_solver_jax_inv(params, l2reg, X_tr, y_tr): + """Solve ridge regression by conjugate gradient.""" + + def matvec(u): + return X_tr.T @ ((X_tr @ u)) + + return jaxopt.linear_solve.solve_inv( + matvec=matvec, + b=X_tr.T @ y_tr, + ridge=len(y_tr) * l2reg.item(), + ) + + for xs, ys, xq, yq in loader: + xs = xs.to(dtype=dtype) + ys = ys.to(dtype=dtype) + xq = xq.to(dtype=dtype) + yq = yq.to(dtype=dtype) + + w_fit = ridge_solver_torch_inv(init_params_torch, l2reg_torch, (xs, ys)) outer_loss = F.mse_loss(xq @ w_fit, yq) grads, *_ = torch.autograd.grad(outer_loss, l2reg_torch) @@ -426,7 +668,7 @@ def matvec(u): yq = jnp.array(yq.numpy(), dtype=np_dtype) def outer_level(params_jax, l2reg_jax, xs, ys, xq, yq): - w_fit = ridge_solver_jax(params_jax, l2reg_jax, xs, ys) + w_fit = ridge_solver_jax_inv(params_jax, l2reg_jax, xs, ys) y_pred = xq @ w_fit loss_value = jnp.mean(jnp.square(y_pred - yq)) return loss_value diff --git a/torchopt/linalg/__init__.py b/torchopt/linalg/__init__.py index 4fff4df2..20dc16aa 100644 --- a/torchopt/linalg/__init__.py +++ b/torchopt/linalg/__init__.py @@ -32,6 +32,7 @@ """Linear algebra functions.""" from torchopt.linalg.cg import cg +from torchopt.linalg.ns import ns, ns_inv -__all__ = ['cg'] +__all__ = ['cg', 'ns', 'ns_inv'] diff --git a/torchopt/linalg/cg.py b/torchopt/linalg/cg.py index 28307666..94daee53 100644 --- a/torchopt/linalg/cg.py +++ b/torchopt/linalg/cg.py @@ -34,51 +34,23 @@ # pylint: disable=invalid-name from functools import partial -from typing import Callable, List, Optional, Union +from typing import Callable, Optional, Union import torch from torchopt import pytree +from torchopt.linalg.utils import cat_shapes, normalize_matvec +from torchopt.pytree import tree_vdot_real from torchopt.typing import TensorTree __all__ = ['cg'] -def _vdot_real_kernel(x: torch.Tensor, y: torch.Tensor) -> float: - """Computes dot(x.conj(), y).real.""" - x = x.contiguous().view(-1) - y = y.contiguous().view(-1) - prod = torch.dot(x.real, y.real).item() - if x.is_complex() and y.is_complex(): - prod += torch.dot(x.imag, y.imag).item() - return prod - - -def tree_vdot_real(tree_x: TensorTree, tree_y: TensorTree) -> float: - """Computes dot(tree_x.conj(), tree_y).real.sum().""" - leaves_x, treespec = pytree.tree_flatten(tree_x) - leaves_y = treespec.flatten_up_to(tree_y) - return sum(map(_vdot_real_kernel, leaves_x, leaves_y)) # type: ignore[arg-type] - - def _identity(x: TensorTree) -> TensorTree: return x -def _normalize_matvec( - f: Union[Callable[[TensorTree], TensorTree], torch.Tensor] -) -> Callable[[TensorTree], TensorTree]: - """Normalize an argument for computing matrix-vector products.""" - if callable(f): - return f - - assert isinstance(f, torch.Tensor) - if f.ndim != 2 or f.shape[0] != f.shape[1]: - raise ValueError(f'linear operator must be a square matrix, but has shape: {f.shape}') - return partial(torch.matmul, f) - - # pylint: disable-next=too-many-locals def _cg_solve( A: Callable[[TensorTree], TensorTree], @@ -126,37 +98,32 @@ def body_fn(value): return x_final -def _shapes(tree: TensorTree) -> List[int]: - flattened = pytree.tree_leaves(tree) - return pytree.tree_leaves([tuple(term.shape) for term in flattened]) # type: ignore[arg-type] - - def _isolve( _isolve_solve: Callable, - A: Union[torch.Tensor, Callable[[TensorTree], TensorTree]], + A: Union[TensorTree, Callable[[TensorTree], TensorTree]], b: TensorTree, x0: Optional[TensorTree] = None, *, rtol: float = 1e-5, atol: float = 0.0, maxiter: Optional[int] = None, - M: Optional[Union[torch.Tensor, Callable[[TensorTree], TensorTree]]] = None, + M: Optional[Union[TensorTree, Callable[[TensorTree], TensorTree]]] = None, ) -> TensorTree: if x0 is None: x0 = pytree.tree_map(torch.zeros_like, b) if maxiter is None: - size = sum(_shapes(b)) + size = sum(cat_shapes(b)) maxiter = 10 * size # copied from SciPy if M is None: M = _identity - A = _normalize_matvec(A) - M = _normalize_matvec(M) + A = normalize_matvec(A) + M = normalize_matvec(M) - if _shapes(x0) != _shapes(b): + if cat_shapes(x0) != cat_shapes(b): raise ValueError( - 'arrays in x0 and b must have matching shapes: ' f'{_shapes(x0)} vs {_shapes(b)}' + f'Tensors in x0 and b must have matching shapes: {cat_shapes(x0)} vs. {cat_shapes(b)}.' ) isolve_solve = partial(_isolve_solve, x0=x0, rtol=rtol, atol=atol, maxiter=maxiter, M=M) @@ -166,14 +133,14 @@ def _isolve( def cg( - A: Union[torch.Tensor, Callable[[TensorTree], TensorTree]], + A: Union[TensorTree, Callable[[TensorTree], TensorTree]], b: TensorTree, x0: Optional[TensorTree] = None, *, rtol: float = 1e-5, atol: float = 0.0, maxiter: Optional[int] = None, - M: Optional[Union[torch.Tensor, Callable[[TensorTree], TensorTree]]] = None, + M: Optional[Union[TensorTree, Callable[[TensorTree], TensorTree]]] = None, ) -> TensorTree: """Use Conjugate Gradient iteration to solve ``Ax = b``. diff --git a/torchopt/linalg/ns.py b/torchopt/linalg/ns.py new file mode 100644 index 00000000..4da8ef9f --- /dev/null +++ b/torchopt/linalg/ns.py @@ -0,0 +1,161 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Neumann Series Matrix Inversion Approximation to solve ``Ax = b``.""" + +# pylint: disable=invalid-name + +import functools +from typing import Callable, Optional, Union + +import torch + +from torchopt import pytree +from torchopt.linalg.utils import cat_shapes, normalize_matvec +from torchopt.typing import TensorTree + + +__all__ = ['ns', 'ns_inv'] + + +def _ns_solve( + A: torch.Tensor, + b: torch.Tensor, + maxiter: int, + alpha: Optional[float] = None, +) -> torch.Tensor: + """Uses Neumann Series Matrix Inversion Approximation to solve ``Ax = b``.""" + if A.ndim != 2 or A.shape[0] != A.shape[1]: + raise ValueError(f'`A` must be a square matrix, but has shape: {A.shape}') + + inv_A_hat_b = b + v = b + if alpha is not None: + # A^{-1} = a [I - (I - a A)]^{-1} = a [I + (I - a A) + (I - a A)^2 + (I - a A)^3 + ...] + for _ in range(maxiter): + v = v - alpha * (A @ v) + inv_A_hat_b = inv_A_hat_b + v + inv_A_hat_b = alpha * inv_A_hat_b + else: + # A^{-1} = [I - (I - A)]^{-1} = I + (I - A) + (I - A)^2 + (I - A)^3 + ... + for _ in range(maxiter): + v = v - A @ v + inv_A_hat_b = inv_A_hat_b + v + + return inv_A_hat_b + + +def ns( + A: Union[TensorTree, Callable[[TensorTree], TensorTree]], + b: TensorTree, + maxiter: Optional[int] = None, + *, + alpha: Optional[float] = None, +) -> TensorTree: + """Uses Neumann Series Matrix Inversion Approximation to solve ``Ax = b``. + + Args: + A: (tensor or tree of tensors or function) + 2D array or function that calculates the linear map (matrix-vector product) ``Ax`` when + called like ``A(x)``. ``A`` must represent a hermitian, positive definite matrix, and + must return array(s) with the same structure and shape as its argument. + b: (tensor or tree of tensors) + Right hand side of the linear system representing a single vector. Can be stored as an + array or Python container of array(s) with any shape. + maxiter: (integer, optional) + Maximum number of iterations. Iteration will stop after maxiter steps even if the + specified tolerance has not been achieved. + alpha: (float, optional) + Decay coefficient. + + Returns: + The Neumann Series (NS) matrix inversion approximation. + """ + if maxiter is None: + maxiter = 10 + + if not callable(A): + return pytree.tree_map(functools.partial(_ns_solve, maxiter=maxiter, alpha=alpha), A, b) + + matvec = normalize_matvec(A) + inv_A_hat_b = b + v = b + if alpha is not None: + # A^{-1} = a [I - (I - a A)]^{-1} = a [I + (I - a A) + (I - a A)^2 + (I - a A)^3 + ...] + for _ in range(maxiter): + # v = v - alpha * (A @ v) + v = pytree.tree_sub_scalar_mul(v, matvec(v), alpha=alpha) + # inv_A_hat_b = inv_A_hat_b + v + inv_A_hat_b = pytree.tree_add(inv_A_hat_b, v) + # inv_A_hat_b = alpha * inv_A_hat_b + inv_A_hat_b = pytree.tree_scalar_mul(alpha, inv_A_hat_b) + else: + # A^{-1} = [I - (I - A)]^{-1} = I + (I - A) + (I - A)^2 + (I - A)^3 + ... + for _ in range(maxiter): + # v = v - A @ v + v = pytree.tree_sub(v, matvec(v)) + # inv_A_hat_b = inv_A_hat_b + v + inv_A_hat_b = pytree.tree_add(inv_A_hat_b, v) + + return inv_A_hat_b + + +def _ns_inv(A: torch.Tensor, maxiter: int, alpha: Optional[float] = None): + """Uses Neumann Series iteration to solve ``A^{-1}``.""" + if A.ndim != 2 or A.shape[0] != A.shape[1]: + raise ValueError(f'`A` must be a square matrix, but has shape: {A.shape}') + + I = torch.eye(*A.shape, out=torch.empty_like(A)) + inv_A_hat = torch.zeros_like(A) + if alpha is not None: + # A^{-1} = a [I - (I - a A)]^{-1} = a [I + (I - a A) + (I - a A)^2 + (I - a A)^3 + ...] + M = I - alpha * A + for rank in range(maxiter): + inv_A_hat = inv_A_hat + torch.linalg.matrix_power(M, rank) + inv_A_hat = alpha * inv_A_hat + else: + # A^{-1} = [I - (I - A)]^{-1} = I + (I - A) + (I - A)^2 + (I - A)^3 + ... + M = I - A + for rank in range(maxiter): + inv_A_hat = inv_A_hat + torch.linalg.matrix_power(M, rank) + return inv_A_hat + + +def ns_inv( + A: TensorTree, + maxiter: Optional[int] = None, + *, + alpha: Optional[float] = None, +) -> TensorTree: + """Uses Neumann Series iteration to solve ``A^{-1}``. + + Args: + A: (tensor or tree of tensors or function) + 2D array or function that calculates the linear map (matrix-vector product) ``Ax`` when + called like ``A(x)``. ``A`` must represent a hermitian, positive definite matrix, and + must return array(s) with the same structure and shape as its argument. + maxiter: (integer, optional) + Maximum number of iterations. Iteration will stop after maxiter steps even if the + specified tolerance has not been achieved. + alpha: (float, optional) + Decay coefficient. + + Returns: + The Neumann Series (NS) matrix inversion approximation. + """ + if maxiter is None: + size = sum(cat_shapes(A)) + maxiter = 10 * size # copied from SciPy + + return pytree.tree_map(functools.partial(_ns_inv, maxiter=maxiter, alpha=alpha), A) diff --git a/torchopt/linalg/utils.py b/torchopt/linalg/utils.py new file mode 100644 index 00000000..f2440b9a --- /dev/null +++ b/torchopt/linalg/utils.py @@ -0,0 +1,55 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +"""Utilities for linear algebra.""" + +import itertools +from typing import Callable, Tuple, Union + +import torch + +from torchopt import pytree +from torchopt.typing import TensorTree + + +def cat_shapes(tree: TensorTree) -> Tuple[int, ...]: + """Concatenates the shapes of the leaves of a tree of tensors.""" + leaves = pytree.tree_leaves(tree) + return tuple(itertools.chain.from_iterable(tuple(leaf.shape) for leaf in leaves)) + + +def normalize_matvec( + matvec: Union[TensorTree, Callable[[TensorTree], TensorTree]] +) -> Callable[[TensorTree], TensorTree]: + """Normalizes an argument for computing matrix-vector product.""" + if callable(matvec): + return matvec + + mat_flat, treespec = pytree.tree_flatten(matvec) + for mat in mat_flat: + if not isinstance(mat, torch.Tensor) or mat.ndim != 2 or mat.shape[0] != mat.shape[1]: + raise TypeError(f'Linear operator must be a square matrix, but has shape: {mat.shape}') + + def _matvec(x: TensorTree) -> TensorTree: + x_flat = pytree.tree_leaves(x) + if len(x_flat) != len(mat_flat): + raise ValueError( + f'`x` must have the same number of leaves as `matvec`, ' + f'but has {len(x_flat)} leaves and `matvec` has {len(mat_flat)} leaves' + ) + + y_flat = map(torch.matmul, mat_flat, x_flat) + return pytree.tree_unflatten(treespec, y_flat) + + return _matvec diff --git a/torchopt/linear_solve/__init__.py b/torchopt/linear_solve/__init__.py index e27ba4c0..8d9115d3 100644 --- a/torchopt/linear_solve/__init__.py +++ b/torchopt/linear_solve/__init__.py @@ -32,7 +32,8 @@ """Linear algebra solvers.""" from torchopt.linear_solve.cg import solve_cg +from torchopt.linear_solve.inv import solve_inv from torchopt.linear_solve.normal_cg import solve_normal_cg -__all__ = ['solve_cg', 'solve_normal_cg'] +__all__ = ['solve_cg', 'solve_normal_cg', 'solve_inv'] diff --git a/torchopt/linear_solve/cg.py b/torchopt/linear_solve/cg.py index 9c150038..2ffc8217 100644 --- a/torchopt/linear_solve/cg.py +++ b/torchopt/linear_solve/cg.py @@ -53,7 +53,7 @@ def _solve_cg( ) -> TensorTree: """Solves ``A x = b`` using conjugate gradient. - It assumes that ``A`` is a hermitian, positive definite matrix. + This assumes that ``A`` is a hermitian, positive definite matrix. Args: matvec: A function that returns the product between ``A`` and a vector. @@ -75,5 +75,33 @@ def _solve_cg( def solve_cg(**kwargs): - """Wrapper for :func:`solve_cg`.""" + """A wrapper that returns a solver function to solve ``A x = b`` using conjugate gradient. + + This assumes that ``A`` is a hermitian, positive definite matrix. + + Args: + ridge: Optional ridge regularization. Solves the equation for ``(A + ridge * I) @ x = b``. + init: Optional initialization to be used by conjugate gradient. + **kwargs: Additional keyword arguments for the conjugate gradient solver + :func:`torchopt.linalg.cg`. + + Returns: + A solver function with signature ``(matvec, b) -> x`` that solves ``A x = b`` using + conjugate gradient where ``matvec(v) = A v``. + + See Also: + Conjugate gradient iteration :func:`torchopt.linalg.cg`. + + Example:: + + >>> A = {'a': torch.eye(5, 5), 'b': torch.eye(3, 3)} + >>> x = {'a': torch.randn(5), 'b': torch.randn(3)} + >>> def matvec(x: TensorTree) -> TensorTree: + ... return {'a': A['a'] @ x['a'], 'b': A['b'] @ x['b']} + >>> b = matvec(x) + >>> solver = solve_cg(init={'a': torch.zeros(5), 'b': torch.zeros(3)}) + >>> x_hat = solver(matvec, b) + >>> assert torch.allclose(x_hat['a'], x['a']) and torch.allclose(x_hat['b'], x['b']) + + """ return functools.partial(_solve_cg, **kwargs) diff --git a/torchopt/linear_solve/inv.py b/torchopt/linear_solve/inv.py new file mode 100644 index 00000000..bf36f40e --- /dev/null +++ b/torchopt/linear_solve/inv.py @@ -0,0 +1,122 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +# This file is modified from: +# https://github.com/google/jaxopt/blob/main/jaxopt/_src/linear_solve.py +# ============================================================================== +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. +# ============================================================================== +"""Linear algebra solver for ``A x = b`` using matrix inversion.""" + +# pylint: disable=invalid-name + +import functools +from typing import Callable, Optional + +import torch + +from torchopt import linalg, pytree +from torchopt.linear_solve.utils import make_ridge_matvec, materialize_matvec +from torchopt.typing import TensorTree + + +__all__ = ['solve_inv'] + + +def _solve_inv( + matvec: Callable[[TensorTree], TensorTree], # (x) -> A @ x + b: TensorTree, + ridge: Optional[float] = None, + ns: bool = False, + **kwargs, +) -> TensorTree: + """Solves ``A x = b`` using matrix inversion. + + If ``ns = False``, this assumes the matrix ``A`` is a constant matrix and will materialize it + in memory. + + Args: + matvec: A function that returns the product between ``A`` and a vector. + b: A tensor for the right hand side of the equation. + ridge: Optional ridge regularization. Solves the equation for ``(A + ridge * I) @ x = b``. + ns: Whether to use Neumann Series matrix inversion approximation. If :data:`False`, + materialize the matrix ``A`` in memory and use :func:`torch.linalg.solve` instead. + **kwargs: Additional keyword arguments for the Neumann Series matrix inversion approximation + solver :func:`torchopt.linalg.ns`. + + Returns: + The solution with the same shape as ``b``. + """ + if ridge is not None: + # (x) -> A @ x + ridge * x + # i.e. (x) -> (A + ridge * I) @ x + matvec = make_ridge_matvec(matvec, ridge=ridge) + + b_flat = pytree.tree_leaves(b) + if len(b_flat) == 1 and b_flat[0].ndim == 0: + A, *_ = materialize_matvec(matvec, b) + return pytree.tree_truediv(b, A) + + if ns: + return linalg.ns(matvec, b, **kwargs) + + A, _, tree_ravel, tree_unravel = materialize_matvec(matvec, b) + return tree_unravel(pytree.tree_map(torch.linalg.solve, A, tree_ravel(b))) + + +def solve_inv(**kwargs): + """A wrapper that returns a solver function to solve ``A x = b`` using matrix inversion. + + If ``ns = False``, this assumes the matrix ``A`` is a constant matrix and will materialize it + in memory. + + Args: + ridge: Optional ridge regularization. Solves the equation for ``(A + ridge * I) @ x = b``. + ns: Whether to use Neumann Series matrix inversion approximation. If :data:`False`, + materialize the matrix ``A`` in memory and use :func:`torch.linalg.solve` instead. + **kwargs: Additional keyword arguments for the Neumann Series matrix inversion approximation + solver :func:`torchopt.linalg.ns`. + + Returns: + A solver function with signature ``(matvec, b) -> x`` that solves ``A x = b`` using matrix + inversion where ``matvec(v) = A v``. + + See Also: + Neumann Series matrix inversion approximation :func:`torchopt.linalg.ns`. + + Example:: + + >>> A = {'a': torch.eye(5, 5), 'b': torch.eye(3, 3)} + >>> x = {'a': torch.randn(5), 'b': torch.randn(3)} + >>> def matvec(x: TensorTree) -> TensorTree: + ... return {'a': A['a'] @ x['a'], 'b': A['b'] @ x['b']} + >>> b = matvec(x) + >>> solver = solve_inv(ns=True, maxiter=10) + >>> x_hat = solver(matvec, b) + >>> assert torch.allclose(x_hat['a'], x['a']) and torch.allclose(x_hat['b'], x['b']) + + """ + return functools.partial(_solve_inv, **kwargs) diff --git a/torchopt/linear_solve/normal_cg.py b/torchopt/linear_solve/normal_cg.py index 38cb2834..3646d7f4 100644 --- a/torchopt/linear_solve/normal_cg.py +++ b/torchopt/linear_solve/normal_cg.py @@ -61,7 +61,8 @@ def _solve_normal_cg( b: A tree of tensors for the right hand side of the equation. ridge: Optional ridge regularization. Solves the equation for ``(A.T @ A + ridge * I) @ x = A.T @ b``. init: Optional initialization to be used by normal conjugate gradient. - **kwargs: Additional keyword arguments for the conjugate gradient solver. + **kwargs: Additional keyword arguments for the conjugate gradient solver + :func:`torchopt.linalg.cg`. Returns: The solution with the same structure as ``b``. @@ -86,5 +87,34 @@ def _solve_normal_cg( def solve_normal_cg(**kwargs): - """Wrapper for :func:`solve_normal_cg`.""" + """A wrapper that returns a solver function to solve ``A^T A x = A^T b`` using conjugate gradient. + + This can be used to solve ``A x = b`` using conjugate gradient when ``A`` is not hermitian, + positive definite. + + Args: + ridge: Optional ridge regularization. Solves the equation for ``(A.T @ A + ridge * I) @ x = A.T @ b``. + init: Optional initialization to be used by normal conjugate gradient. + **kwargs: Additional keyword arguments for the conjugate gradient solver + :func:`torchopt.linalg.cg`. + + Returns: + A solver function with signature ``(matvec, b) -> x`` that solves ``A^T A x = A^T b`` using + conjugate gradient where ``matvec(v) = A v``. + + See Also: + Conjugate gradient iteration :func:`torchopt.linalg.cg`. + + Example:: + + >>> A = {'a': torch.randn(5, 5), 'b': torch.randn(3, 3)} + >>> x = {'a': torch.randn(5), 'b': torch.randn(3)} + >>> def matvec(x: TensorTree) -> TensorTree: + ... return {'a': A['a'] @ x['a'], 'b': A['b'] @ x['b']} + >>> b = matvec(x) + >>> solver = solve_normal_cg(init={'a': torch.zeros(5), 'b': torch.zeros(3)}) + >>> x_hat = solver(matvec, b) + >>> assert torch.allclose(x_hat['a'], x['a']) and torch.allclose(x_hat['b'], x['b']) + + """ return functools.partial(_solve_normal_cg, **kwargs) diff --git a/torchopt/linear_solve/utils.py b/torchopt/linear_solve/utils.py index 5fede71d..a7e93e65 100644 --- a/torchopt/linear_solve/utils.py +++ b/torchopt/linear_solve/utils.py @@ -31,9 +31,7 @@ # ============================================================================== """Utilities for linear algebra solvers.""" -# pylint: disable=invalid-name - -from typing import Callable +from typing import Callable, Tuple import functorch @@ -41,11 +39,6 @@ from torchopt.typing import TensorTree -def tree_add(tree_x: TensorTree, tree_y: TensorTree, alpha: float = 1.0) -> TensorTree: - """Computes tree_x + alpha * tree_y.""" - return pytree.tree_map(lambda x, y: x.add(y, alpha=alpha), tree_x, tree_y) - - def make_rmatvec( matvec: Callable[[TensorTree], TensorTree], example_x: TensorTree ) -> Callable[[TensorTree], TensorTree]: @@ -75,6 +68,47 @@ def make_ridge_matvec( def ridge_matvec(y: TensorTree) -> TensorTree: """Computes ``A.T @ A @ v + ridge * v`` from ``matvec(x) = A @ x``.""" - return tree_add(matvec(y), y, alpha=ridge) + return pytree.tree_add_scalar_mul(matvec(y), y, alpha=ridge) return ridge_matvec + + +def materialize_matvec( + matvec: Callable[[TensorTree], TensorTree], x: TensorTree +) -> Tuple[ + TensorTree, + Callable[[TensorTree], TensorTree], + Callable[[TensorTree], TensorTree], + Callable[[TensorTree], TensorTree], +]: + """Materializes the matrix ``A`` used in ``matvec(x) = A @ x``.""" + x_flat, treespec = pytree.tree_flatten(x) + shapes = tuple(t.shape for t in x_flat) + + if all(t.ndim == 1 for t in x_flat): + + def tree_ravel(x: TensorTree) -> TensorTree: + return x + + def tree_unravel(y: TensorTree) -> TensorTree: + return y + + matvec_ravel = matvec + + else: + + def tree_ravel(x: TensorTree) -> TensorTree: + return pytree.tree_map(lambda t: t.contiguous().view(-1), x) + + def tree_unravel(y: TensorTree) -> TensorTree: + shapes_iter = iter(shapes) + return pytree.tree_map(lambda t: t.contiguous().view(next(shapes_iter)), y) + + def matvec_ravel(y: TensorTree) -> TensorTree: + return tree_ravel(matvec(tree_unravel(y))) + + nargs = len(x_flat) + jacobian_tree = functorch.jacfwd(matvec_ravel)(tree_ravel(x)) + jacobian_flat = pytree.tree_leaves(jacobian_tree) + jacobian_diag = [jacobian_flat[i + i * nargs] for i in range(nargs)] + return pytree.tree_unflatten(treespec, jacobian_diag), matvec_ravel, tree_ravel, tree_unravel diff --git a/torchopt/pytree.py b/torchopt/pytree.py index 65aba6a2..f1dd26e0 100644 --- a/torchopt/pytree.py +++ b/torchopt/pytree.py @@ -14,17 +14,35 @@ # ============================================================================== """The PyTree utilities.""" +import functools +import operator from typing import Callable, List, Optional, Tuple import optree import optree.typing as typing # pylint: disable=unused-import +import torch import torch.distributed.rpc as rpc from optree import * # pylint: disable=wildcard-import,unused-wildcard-import -from torchopt.typing import Future, PyTree, RRef, T +from torchopt.typing import Future, RRef, Scalar, T, TensorTree -__all__ = [*optree.__all__, 'tree_flatten_as_tuple', 'tree_wait'] +__all__ = [ + *optree.__all__, + 'tree_flatten_as_tuple', + 'tree_pos', + 'tree_neg', + 'tree_add', + 'tree_add_scalar_mul', + 'tree_sub', + 'tree_sub_scalar_mul', + 'tree_mul', + 'tree_matmul', + 'tree_scalar_mul', + 'tree_truediv', + 'tree_vdot_real', + 'tree_wait', +] def tree_flatten_as_tuple( @@ -48,10 +66,98 @@ def tree_flatten_as_tuple( return tuple(leaves), treespec +def acc_add(*args: T) -> T: + """Accumulate addition.""" + return functools.reduce(operator.add, args) + + +def acc_mul(*args: T) -> T: + """Accumulate multiplication.""" + return functools.reduce(operator.mul, args) + + +def acc_matmul(*args: T) -> T: + """Accumulate matrix multiplication.""" + return functools.reduce(operator.matmul, args) + + +def tree_pos(tree: PyTree[T]) -> PyTree[T]: + """Applies `operator.pos` over leaves.""" + return tree_map(operator.pos, tree) + + +def tree_neg(tree: PyTree[T]) -> PyTree[T]: + """Applies `operator.neg` over leaves.""" + return tree_map(operator.neg, tree) + + +def tree_add(*trees: PyTree[T]) -> PyTree[T]: + """Tree addition over leaves.""" + return tree_map(acc_add, *trees) + + +def tree_add_scalar_mul( + tree_x: TensorTree, tree_y: TensorTree, alpha: Optional[Scalar] = None +) -> TensorTree: + """Computes tree_x + alpha * tree_y.""" + if alpha is None: + return tree_map(lambda x, y: x.add(y), tree_x, tree_y) + return tree_map(lambda x, y: x.add(y, alpha=alpha), tree_x, tree_y) + + +def tree_sub(minuend_tree: PyTree[T], subtrahend_tree: PyTree[T]) -> PyTree[T]: + """Tree subtraction over leaves.""" + return tree_map(operator.sub, minuend_tree, subtrahend_tree) + + +def tree_sub_scalar_mul( + tree_x: TensorTree, tree_y: TensorTree, alpha: Optional[Scalar] = None +) -> TensorTree: + """Computes tree_x - alpha * tree_y.""" + if alpha is None: + return tree_map(lambda x, y: x.sub(y), tree_x, tree_y) + return tree_map(lambda x, y: x.sub(y, alpha=alpha), tree_x, tree_y) + + +def tree_mul(*trees: PyTree[T]) -> PyTree[T]: + """Tree multiplication over leaves.""" + return tree_map(acc_mul, *trees) + + +def tree_matmul(*trees: PyTree[T]) -> PyTree[T]: + """Tree matrix multiplication over leaves.""" + return tree_map(acc_matmul, *trees) + + +def tree_scalar_mul(scalar: Scalar, multiplicand_tree: PyTree[T]) -> PyTree[T]: + """Tree scalar multiplication over leaves.""" + return tree_map(lambda x: scalar * x, multiplicand_tree) + + +def tree_truediv(dividend_tree: PyTree[T], divisor_tree: PyTree[T]) -> PyTree[T]: + """Tree division over leaves.""" + return tree_map(operator.truediv, dividend_tree, divisor_tree) + + +def _vdot_real_kernel(x: torch.Tensor, y: torch.Tensor) -> float: + """Computes dot(x.conj(), y).real.""" + x = x.contiguous().view(-1) + y = y.contiguous().view(-1) + vdot = torch.dot(x.real, y.real).item() + if x.is_complex() and y.is_complex(): + vdot += torch.dot(x.imag, y.imag).item() + return vdot + + +def tree_vdot_real(tree_x: TensorTree, tree_y: TensorTree) -> float: + """Computes dot(tree_x.conj(), tree_y).real.sum().""" + leaves_x, treespec = tree_flatten(tree_x) + leaves_y = treespec.flatten_up_to(tree_y) + return sum(map(_vdot_real_kernel, leaves_x, leaves_y)) # type: ignore[arg-type] + + def tree_wait(future_tree: PyTree[Future[T]]) -> PyTree[T]: r"""Convert a tree of :class:`Future`\s to a tree of results.""" - import torch # pylint: disable=import-outside-toplevel - futures, treespec = tree_flatten(future_tree) results = torch.futures.wait_all(futures) @@ -61,7 +167,7 @@ def tree_wait(future_tree: PyTree[Future[T]]) -> PyTree[T]: if rpc.is_available(): - def tree_as_rref(tree: PyTree[T]) -> 'PyTree[RRef[T]]': + def tree_as_rref(tree: PyTree[T]) -> PyTree[RRef[T]]: r"""Convert a tree of local objects to a tree of :class:`RRef`\s.""" # pylint: disable-next=import-outside-toplevel,redefined-outer-name,reimported from torch.distributed.rpc import RRef @@ -69,17 +175,17 @@ def tree_as_rref(tree: PyTree[T]) -> 'PyTree[RRef[T]]': return tree_map(RRef, tree) def tree_to_here( - rref_tree: 'PyTree[RRef[T]]', + rref_tree: PyTree[RRef[T]], timeout: float = rpc.api.UNSET_RPC_TIMEOUT, ) -> PyTree[T]: r"""Convert a tree of :class:`RRef`\s to a tree of local objects.""" return tree_map(lambda x: x.to_here(timeout=timeout), rref_tree) - def tree_local_value(rref_tree: 'PyTree[RRef[T]]'): + def tree_local_value(rref_tree: PyTree[RRef[T]]) -> PyTree[T]: r"""Return the local value of a tree of :class:`RRef`\s.""" return tree_map(lambda x: x.local_value(), rref_tree) __all__.extend(['tree_as_rref', 'tree_to_here']) -del Callable, List, Optional, Tuple, optree, rpc, PyTree, T, RRef +del Callable, List, Optional, Tuple, optree, rpc, Scalar, T, RRef From 5b6aa336fbf76a6e5abf823782c032e705aa330f Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Wed, 9 Nov 2022 17:22:07 +0800 Subject: [PATCH 43/69] deps: bump mypy to v0.990 --- .github/workflows/lint.yml | 5 ----- Makefile | 1 + conda-recipe.yaml | 3 ++- pyproject.toml | 3 ++- tests/requirements.txt | 3 ++- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8ed36d36..92d6036f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -90,11 +90,6 @@ jobs: run: | make addlicense - - name: Install dev version of mypy - run: | - python -m pip install git+https://github.com/python/mypy.git - python -m pip install types-setuptools - - name: mypy run: | make mypy diff --git a/Makefile b/Makefile index 07cd00ca..9ec1cead 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,7 @@ py-format-install: mypy-install: $(call check_pip_install,mypy) + $(call check_pip_install,types-setuptools) pre-commit-install: $(call check_pip_install,pre-commit) diff --git a/conda-recipe.yaml b/conda-recipe.yaml index 97a9dcca..53fb7698 100644 --- a/conda-recipe.yaml +++ b/conda-recipe.yaml @@ -89,7 +89,8 @@ dependencies: - isort - conda-forge::black-jupyter >= 22.6.0 - pylint - - mypy + - mypy >= 0.990 + - types-setuptools - flake8 - flake8-bugbear - doc8 < 1.0.0a0 diff --git a/pyproject.toml b/pyproject.toml index 97bf5ee7..ff593bd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,8 @@ lint = [ "isort", "black[jupyter] >= 22.6.0", "pylint", - "mypy", + "mypy >= 0.990", + "types-setuptools", "flake8", "flake8-bugbear", "doc8 < 1.0.0a0", diff --git a/tests/requirements.txt b/tests/requirements.txt index 9edc2964..c86cc16d 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -13,7 +13,8 @@ pytest-xdist isort black[jupyter] >= 22.6.0 pylint -mypy +mypy >= 0.990 +types-setuptools flake8 flake8-bugbear # https://github.com/PyCQA/doc8/issues/112 From a6b795b003905690da927b1bdc9e06ea076d92a7 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Wed, 9 Nov 2022 22:49:51 +0800 Subject: [PATCH 44/69] feat(tutorial): update implicit_differentiation tutorial (#110) * feat(tutorial): add oop api in implicit_differentiation * fix: pass lint * chore: cleanup * feat: add solve_inv example in tutorial * fix: revert tutorial changes * fix: fix typos Co-authored-by: Xuehai Pan --- torchopt/__init__.py | 5 + torchopt/diff/__init__.py | 1 + tutorials/5_Implicit_Differentiation.ipynb | 254 +++++++++++++++++++-- 3 files changed, 246 insertions(+), 14 deletions(-) diff --git a/torchopt/__init__.py b/torchopt/__init__.py index edb093d0..ff260b87 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -21,6 +21,7 @@ distributed, hook, linear_solve, + nn, pytree, schedule, typing, @@ -30,6 +31,8 @@ from torchopt.alias import adam, adamw, rmsprop, sgd from torchopt.clip import clip_grad_norm from torchopt.combine import chain +from torchopt.diff import ImplicitMetaGradientModule +from torchopt.nn import MetaGradientModule from torchopt.optim import SGD, Adam, AdamW, Optimizer, RMSProp, RMSprop, meta from torchopt.optim.func import FuncOptimizer from torchopt.optim.meta import ( @@ -79,4 +82,6 @@ 'stop_gradient', 'module_clone', 'module_detach_', + 'MetaGradientModule', + 'ImplicitMetaGradientModule', ] diff --git a/torchopt/diff/__init__.py b/torchopt/diff/__init__.py index a8d26450..45674fcf 100644 --- a/torchopt/diff/__init__.py +++ b/torchopt/diff/__init__.py @@ -15,3 +15,4 @@ """Differentiable Gradient Estimation.""" from torchopt.diff import implicit, zero_order +from torchopt.diff.implicit import ImplicitMetaGradientModule diff --git a/tutorials/5_Implicit_Differentiation.ipynb b/tutorials/5_Implicit_Differentiation.ipynb index c83e69b8..d07d374c 100644 --- a/tutorials/5_Implicit_Differentiation.ipynb +++ b/tutorials/5_Implicit_Differentiation.ipynb @@ -18,10 +18,18 @@ }, { "cell_type": "markdown", - "id": "01214059-78d9-4cde-9b08-007c2eb078b3", + "id": "8d7f9865-dc02-43d4-be90-da1160c4e4dd", "metadata": {}, "source": [ - "In this tutorial, we will introduce how TorchOpt can be used to conduct implicit differentiation. Here we use the example of [IMAML](https://arxiv.org/abs/1909.04630) as the illustrative example." + "By treating the solution $\\phi^{\\star}$ as an implicit function of $\\theta$, the idea of implicit differentiation is to directly get analytical best-response derivatives $\\partial \\phi^{\\star}(\\theta)/ \\partial \\theta$ by implicit function theorem. This is suitable for algorithms when the inner-level optimal solution is achieved ${\\left. \\frac{\\partial F (\\phi, \\theta)}{\\partial \\phi} \\right\\rvert}_{\\phi = \\phi^{\\star}} = 0$ or reaches some stationary conditions $F (\\phi^{\\star}, \\theta) = 0$, such as [IMAML](https://arxiv.org/abs/1909.04630) and [DEQ](https://arxiv.org/abs/1909.01377)." + ] + }, + { + "cell_type": "markdown", + "id": "d7e4b9e1-115f-45ad-a9b3-ea338bcfe6dd", + "metadata": {}, + "source": [ + "In this tutorial, we will introduce how TorchOpt can be used to conduct implicit differentiation." ] }, { @@ -44,9 +52,36 @@ "id": "0cdaac49-4b94-4900-9bb5-a39057ac8b21", "metadata": {}, "source": [ - "## 1. Basic API\n", + "## 1. Functional API\n", + "\n", + "The basic functional API is `torchopt.diff.implicit.custom_root`, which is used as the decorator for the forward process implicit gradient procedures. Users are required to implement the stationary conditions for the inner-loop process, which will be used as the input of custom_root decorator. We show the pseudo code in the following part." + ] + }, + { + "cell_type": "markdown", + "id": "c0b4400b-a491-4f07-926c-c421ac5a2069", + "metadata": {}, + "source": [ + "```python\n", + "# Functional API for implicit gradient\n", + "def stationary(params, meta_params, data):\n", + " # stationary condition construction\n", + " return stationary condition\n", "\n", - "The basic API is `torchopt.diff.implicit.custom_root`, which is used as the decorator for the forward process implicit gradient procedures." + "# Decorator that wraps the function\n", + "# Optionally specify the linear solver (conjugate gradient or Neumann series)\n", + "@torchopt.diff.implicit.custom_root(stationary, solve=linear_solver)\n", + "def solve(params, meta_params, data):\n", + " # Forward optimization process for params\n", + " return optimal_params\n", + "\n", + "# Define params, meta params and get data\n", + "params, meta_prams, data = ..., ..., ...\n", + "optimal_params = solve(params, meta_params, data)\n", + "loss = outer_loss(optimal_params)\n", + "\n", + "meta_grads = torch.autograd.grad(loss, meta_params)\n", + "```" ] }, { @@ -54,17 +89,16 @@ "id": "dbef87df-2164-4f1d-8919-37a6fbdc5011", "metadata": {}, "source": [ - "## 1.1 Forward Process, Backward Process with Optimality Conditions\n", - "For IMAML, the inner-loop objective is described by the following equation.\n", + "Here we use the example of [IMAML](https://arxiv.org/abs/1909.04630) as a real example. For IMAML, the inner-loop objective is described by the following equation.\n", "\n", "$$\n", - "{\\mathcal{Alg}}^{\\star} \\left( \\boldsymbol{\\theta}, \\mathcal{D}_{i}^{\\text{tr}} \\right) = \\underset{\\phi' \\in \\Phi}{\\operatorname{\\arg \\min}} ~ G \\left( \\boldsymbol{\\phi}', \\boldsymbol{\\theta} \\right) \\triangleq \\mathcal{L} \\left( \\boldsymbol{\\phi}', \\mathcal{D}_{i}^{\\text{tr}} \\right) + \\frac{\\lambda}{2} {\\left\\| \\boldsymbol{\\phi}' - \\boldsymbol{\\theta} \\right\\|}^{2}\n", + "{\\mathcal{Alg}}^{\\star} \\left( \\boldsymbol{\\theta}, \\mathcal{D}_{i}^{\\text{tr}} \\right) = \\underset{\\phi'}{\\operatorname{\\arg \\min}} ~ G \\left( \\boldsymbol{\\phi}', \\boldsymbol{\\theta} \\right) \\triangleq \\mathcal{L} \\left( \\boldsymbol{\\phi}', \\mathcal{D}_{i}^{\\text{tr}} \\right) + \\frac{\\lambda}{2} {\\left\\| \\boldsymbol{\\phi}' - \\boldsymbol{\\theta} \\right\\|}^{2}\n", "$$\n", "\n", "According to this function, we can define the forward function `inner_solver`, where we solve this equation based on sufficient gradient descents. For such inner-loop process, the optimality condition is that the gradient w.r.t inner-loop parameter is $0$.\n", "\n", "$$\n", - "{\\left. \\nabla_{\\boldsymbol{\\phi}'} G \\left( \\boldsymbol{\\phi}', \\boldsymbol{\\theta} \\right) \\right|}_{\\boldsymbol{\\phi}' = \\boldsymbol{\\phi}^{\\star}} = 0\n", + "{\\left. \\nabla_{\\boldsymbol{\\phi}'} G \\left( \\boldsymbol{\\phi}', \\boldsymbol{\\theta} \\right) \\right\\rvert}_{\\boldsymbol{\\phi}' = \\boldsymbol{\\phi}^{\\star}} = 0\n", "$$\n", "\n", "Thus we can define the optimality function by defining `imaml_objective` and make it first-order gradient w.r.t the inner-loop parameter as $0$. We achieve so by calling out `functorch.grad(imaml_objective, argnums=0)`. Finally, the forward function is decorated by the `@torchopt.diff.implicit.custom_root` decorator and the optimality condition we define." @@ -77,7 +111,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Optimality function\n", + "# Inner-loop objective function\n", + "# The optimality function: grad(imaml_objective)\n", "def imaml_objective(params, meta_params, data):\n", " x, y, fmodel = data\n", " y_pred = fmodel(params, x)\n", @@ -95,9 +130,44 @@ "\n", "# Here we pass argnums=1 to the custom_root. That means we want to compute the gradient of\n", "# optimal_params w.r.t. the 1-indexed argument in inner_solver, i.e., params.\n", - "@torchopt.diff.implicit.custom_root(functorch.grad(imaml_objective, argnums=0), argnums=1)\n", + "# torchopt.linear_solve.solve_normal_cg specify that we use the conjugate gradient based linear solver\n", + "@torchopt.diff.implicit.custom_root(\n", + " functorch.grad(imaml_objective, argnums=0), # optimality function\n", + " argnums=1,\n", + " solve=torchopt.linear_solve.solve_normal_cg(maxiter=5, atol=0),\n", + ")\n", "def inner_solver(params, meta_params, data):\n", - " \"\"\"Solve ridge regression by conjugate gradient.\"\"\"\n", + " # Initial functional optimizer based on TorchOpt\n", + " x, y, fmodel = data\n", + " optimizer = torchopt.sgd(lr=2e-2)\n", + " opt_state = optimizer.init(params)\n", + " with torch.enable_grad():\n", + " # Temporarily enable gradient computation for conducting the optimization\n", + " for i in range(100):\n", + " pred = fmodel(params, x)\n", + " loss = F.mse_loss(pred, y) # compute loss\n", + "\n", + " # Compute regularization loss\n", + " regularization_loss = 0.0\n", + " for p1, p2 in zip(params, meta_params):\n", + " regularization_loss += 0.5 * torch.sum(torch.square(p1.view(-1) - p2.view(-1)))\n", + " final_loss = loss + regularization_loss\n", + "\n", + " grads = torch.autograd.grad(final_loss, params) # compute gradients\n", + " updates, opt_state = optimizer.update(grads, opt_state, inplace=True) # get updates\n", + " params = torchopt.apply_updates(params, updates, inplace=True)\n", + "\n", + " optimal_params = params\n", + " return optimal_params\n", + "\n", + "\n", + "# torchopt.linear_solve.solve_inv specify that we use the Neumann Series inversion linear solver\n", + "@torchopt.diff.implicit.custom_root(\n", + " functorch.grad(imaml_objective, argnums=0), # optimality function\n", + " argnums=1,\n", + " solve=torchopt.linear_solve.solve_inv(ns=True, maxiter=100, alpha=0.1),\n", + ")\n", + "def inner_solver_inv_ns(params, meta_params, data):\n", " # Initial functional optimizer based on TorchOpt\n", " x, y, fmodel = data\n", " optimizer = torchopt.sgd(lr=2e-2)\n", @@ -149,7 +219,7 @@ "id": "eeb1823a-2231-4471-bb68-cce7724f2578", "metadata": {}, "source": [ - "We instantiate an one layer neural network, where the weights and bias are initialised with constant." + "We instantiate an one layer neural network, where the weights and bias are initialized with constant." ] }, { @@ -176,7 +246,7 @@ "fmodel, meta_params = functorch.make_functional(model)\n", "data = (x, y, fmodel)\n", "\n", - "# clone function for parameters\n", + "# Clone function for parameters\n", "def clone(params):\n", " cloned = []\n", " for item in params:\n", @@ -234,11 +304,167 @@ "source": [ "torch.autograd.grad(outer_loss, meta_params)" ] + }, + { + "cell_type": "markdown", + "id": "926ae8bb", + "metadata": {}, + "source": [ + "Also we can switch to the Neumann Series inversion linear solver." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "43df0374", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(tensor([[-0.0369, 0.0248, 0.0347, 0.0067]]), tensor([0.3156]))\n" + ] + } + ], + "source": [ + "optimal_params = inner_solver_inv_ns(clone(meta_params), meta_params, data)\n", + "outer_loss = fmodel(optimal_params, x).mean()\n", + "torch.autograd.grad(outer_loss, meta_params)" + ] + }, + { + "cell_type": "markdown", + "id": "c92e67ea-b220-4a14-a1ea-4eb3c5f52b6b", + "metadata": {}, + "source": [ + "## 2. OOP API\n", + "\n", + "The basic OOP class is the class `ImplicitMetaGradientModule`. We make the network as an `nn.Module` following a classical PyTorch style. Users need to define the stationary condition/objective function and the inner-loop solve function to enable implicit gradient computation. We show the pseudo code in the following part.\n", + "\n", + "```python\n", + "from torchopt.diff.implicit import ImplicitMetaGradientModule\n", + "\n", + "# Inherited from the class ImplicitMetaGradientModule\n", + "# Optionally specify the linear solver (conjugate gradient or Neumann series)\n", + "class InnerNet(ImplicitMetaGradientModule, linear_solve=linear_solver):\n", + " def __init__(self, meta_module):\n", + " ...\n", + "\n", + " def forward(self, batch):\n", + " # Forward process\n", + " ...\n", + "\n", + " def optimality(self, batch, labels):\n", + " # Stationary condition construction for calculating implicit gradient\n", + " # NOTE: If this method is not implemented, it will be automatically derived from the\n", + " # gradient of the `objective` function.\n", + " ...\n", + "\n", + " def objective(self, batch, labels):\n", + " # Define the inner-loop optimization objective\n", + " # NOTE: This method is optional if method `optimality` is implemented.\n", + " ...\n", + "\n", + " def solve(self, batch, labels):\n", + " # Conduct the inner-loop optimization\n", + " ...\n", + " return self # optimized module\n", + "\n", + "# Get meta_params and data\n", + "meta_params, data = ..., ...\n", + "inner_net = InnerNet()\n", + "\n", + "# Solve for inner-loop process related with the meta parameters\n", + "optimal_inner_net = inner_net.solve(meta_params, *data)\n", + "\n", + "# Get outer-loss and solve for meta-gradient\n", + "loss = outer_loss(optimal_inner_net)\n", + "meta_grad = torch.autograd.grad(loss, meta_params)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c3999684-f4d3-4bc0-86ab-a7e803b2fe80", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(tensor([[-0.0369, 0.0248, 0.0347, 0.0067]]), tensor([0.3156]))\n" + ] + } + ], + "source": [ + "from torchopt.diff.implicit import ImplicitMetaGradientModule\n", + "\n", + "\n", + "class InnerNet(\n", + " ImplicitMetaGradientModule,\n", + " linear_solve=torchopt.linear_solve.solve_normal_cg(maxiter=5, atol=0),\n", + "):\n", + " def __init__(self, meta_net, n_inner_iter, reg_param):\n", + " super().__init__()\n", + " self.meta_net = meta_net\n", + " # Get a deepcopy\n", + " self.net = torchopt.module_clone(meta_net, by='deepcopy', detach_buffers=True)\n", + " self.n_inner_iter = n_inner_iter\n", + " self.reg_param = reg_param\n", + "\n", + " def forward(self, x):\n", + " return self.net(x)\n", + "\n", + " def objective(self, x, y):\n", + " # We do not implement the optimality conditions, so it will be automatically derived from\n", + " # the gradient of the `objective` function.\n", + " y_pred = self(x)\n", + " loss = F.mse_loss(y_pred, y)\n", + " regularization_loss = 0\n", + " for p1, p2 in zip(\n", + " self.parameters(), # parameters of `self.net`\n", + " self.meta_parameters(), # parameters of `self.meta_net`\n", + " ):\n", + " regularization_loss += (\n", + " 0.5 * self.reg_param * torch.sum(torch.square(p1.view(-1) - p2.view(-1)))\n", + " )\n", + " return loss + regularization_loss\n", + "\n", + " def solve(self, x, y):\n", + " params = tuple(self.parameters())\n", + " inner_optim = torchopt.SGD(params, lr=2e-2)\n", + " with torch.enable_grad():\n", + " # Temporarily enable gradient computation for conducting the optimization\n", + " for _ in range(self.n_inner_iter):\n", + " loss = self.objective(x, y)\n", + " inner_optim.zero_grad()\n", + " # NOTE: The parameter inputs should be explicitly specified in `backward` function\n", + " # as argument `inputs`. Otherwise, if not provided, the gradient is accumulated into\n", + " # all the leaf Tensors (including the meta-parameters) that were used to compute the\n", + " # objective output. Alternatively, please use `torch.autograd.grad` instead.\n", + " loss.backward(inputs=params) # backward pass in inner-loop\n", + " inner_optim.step() # update inner parameters\n", + " return self\n", + "\n", + "\n", + "# Initialize the meta network\n", + "meta_net = Net(4)\n", + "inner_net = InnerNet(meta_net, 100, reg_param=1)\n", + "\n", + "# Solve for inner-loop\n", + "optimal_inner_net = inner_net.solve(x, y)\n", + "outer_loss = optimal_inner_net(x).mean()\n", + "\n", + "# Derive the meta gradient\n", + "torch.autograd.grad(outer_loss, meta_net.parameters())" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3.8.12 ('torchopt')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, From d53ed5084d5c6d6f9d0f46c2d614112faf9164ab Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 11 Nov 2022 03:24:28 +0800 Subject: [PATCH 45/69] fix(diff/implicit): fix argument index out of range --- torchopt/__init__.py | 4 ---- torchopt/diff/implicit/decorator.py | 32 +++++++++++++++------------ torchopt/diff/implicit/nn/__init__.py | 2 ++ torchopt/diff/implicit/nn/module.py | 24 ++++++++++---------- torchopt/nn/__init__.py | 4 ++++ 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/torchopt/__init__.py b/torchopt/__init__.py index ff260b87..40da95f3 100644 --- a/torchopt/__init__.py +++ b/torchopt/__init__.py @@ -31,8 +31,6 @@ from torchopt.alias import adam, adamw, rmsprop, sgd from torchopt.clip import clip_grad_norm from torchopt.combine import chain -from torchopt.diff import ImplicitMetaGradientModule -from torchopt.nn import MetaGradientModule from torchopt.optim import SGD, Adam, AdamW, Optimizer, RMSProp, RMSprop, meta from torchopt.optim.func import FuncOptimizer from torchopt.optim.meta import ( @@ -82,6 +80,4 @@ 'stop_gradient', 'module_clone', 'module_detach_', - 'MetaGradientModule', - 'ImplicitMetaGradientModule', ] diff --git a/torchopt/diff/implicit/decorator.py b/torchopt/diff/implicit/decorator.py index 1f944576..3cf3efd1 100644 --- a/torchopt/diff/implicit/decorator.py +++ b/torchopt/diff/implicit/decorator.py @@ -252,20 +252,20 @@ def _custom_root( def make_custom_vjp_solver_fn( solver_fn: Callable[..., Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]], kwarg_keys: Sequence[str], - args_signs: Tuple[Tuple[int, Optional[Union[Type[tuple], Type[list]]]], ...], + args_signs: Tuple[Tuple[int, int, Optional[Union[Type[tuple], Type[list]]]], ...], ) -> Type[Function]: # pylint: disable-next=missing-class-docstring,abstract-method class ImplicitMetaGradient(Function): @staticmethod def forward( # type: ignore[override] # pylint: disable=arguments-differ - ctx, *flat_args: Any + ctx: Any, *flat_args: Any ) -> Tuple[Any, ...]: output, aux, output_is_tensor = None, None, False args = [] - for idx, (offset, arg_seq_type) in enumerate(args_signs): + for offset, nargs, arg_seq_type in args_signs: if arg_seq_type is not None: - args.append(arg_seq_type(flat_args[offset : args_signs[idx + 1][0]])) + args.append(arg_seq_type(flat_args[offset : offset + nargs])) else: args.append(flat_args[offset]) args = tuple(args) @@ -307,7 +307,7 @@ def forward( # type: ignore[override] # pylint: disable=arguments-differ @staticmethod def backward( # pylint: disable=too-many-locals - ctx, *grad_outputs: Any + ctx: Any, *grad_outputs: Any ) -> TupleOfTensors: grad_outputs: TupleOfTensors = grad_outputs[:-3] @@ -349,7 +349,7 @@ def backward( # pylint: disable=too-many-locals args_vjps, kwargs_vjps = map_args_back(vjps) ordered_vjps = tuple(args_vjps) + tuple(kwargs_vjps[k] for k in kwargs.keys()) true_vjps = [] - for (_, arg_seq_type), vjp in zip(args_signs, ordered_vjps): + for (_, _, arg_seq_type), vjp in zip(args_signs, ordered_vjps): if arg_seq_type is not None: true_vjps.extend(vjp) else: @@ -358,25 +358,29 @@ def backward( # pylint: disable=too-many-locals return ImplicitMetaGradient + @functools.wraps(solver_fn) def wrapped_solver_fn( *args: Any, **kwargs: Any ) -> Union[TensorOrTensors, Tuple[TensorOrTensors, Any]]: args, kwargs = _signature_bind(solver_fn_signature, *args, **kwargs) keys, vals = list(kwargs.keys()), list(kwargs.values()) - args_signs: List[Tuple[int, Optional[Union[Type[tuple], Type[list]]]]] = [] + args_signs: List[Tuple[int, int, Optional[Union[Type[tuple], Type[list]]]]] = [] flat_args: List[Any] = [] - args_counter = 0 + args_offset = 0 for idx, arg in enumerate(args): if idx in argnums: if isinstance(arg, torch.Tensor): - args_signs.append((args_counter, None)) # start position, None + args_signs.append((args_offset, 1, None)) # start position, None flat_args.append(arg) - args_counter += 1 + args_offset += 1 elif isinstance(arg, (tuple, list)) and all(map(torch.is_tensor, arg)): - args_signs.append((args_counter, type(arg))) # start position, sequence type + nargs = len(arg) + args_signs.append( + (args_offset, nargs, type(arg)) # start position, sequence type + ) flat_args.extend(arg) - args_counter += len(arg) + args_offset += nargs else: raise RuntimeError( 'custom_root(optimality_fn)(solver_fn)(*args): argument of function ' @@ -384,9 +388,9 @@ def wrapped_solver_fn( 'torch.Tensor' ) else: - args_signs.append((args_counter, None)) # start position, None + args_signs.append((args_offset, 1, None)) # start position, None flat_args.append(arg) - args_counter += 1 + args_offset += 1 args_signs = tuple(args_signs) flat_args = tuple(flat_args) diff --git a/torchopt/diff/implicit/nn/__init__.py b/torchopt/diff/implicit/nn/__init__.py index 6d30ffc2..95a2ea85 100644 --- a/torchopt/diff/implicit/nn/__init__.py +++ b/torchopt/diff/implicit/nn/__init__.py @@ -14,6 +14,8 @@ # ============================================================================== """The base class for differentiable implicit meta-gradient models.""" +# Preload to resolve circular references +import torchopt.nn.module # pylint: disable=unused-import from torchopt.diff.implicit.nn.module import ImplicitMetaGradientModule diff --git a/torchopt/diff/implicit/nn/module.py b/torchopt/diff/implicit/nn/module.py index 47527b1a..963ff221 100644 --- a/torchopt/diff/implicit/nn/module.py +++ b/torchopt/diff/implicit/nn/module.py @@ -24,9 +24,9 @@ import functorch import torch -import torchopt.nn from torchopt import pytree from torchopt.diff.implicit.decorator import custom_root +from torchopt.nn.module import MetaGradientModule from torchopt.typing import LinearSolver, TensorTree, TupleOfTensors from torchopt.utils import extract_module_containers @@ -92,10 +92,10 @@ def objective_fn(flat_params: TupleOfTensors, *input, **kwargs) -> torch.Tensor: def enable_implicit_gradients( cls: Type['ImplicitMetaGradientModule'], ) -> Type['ImplicitMetaGradientModule']: - """Enable implicit gradients for the :func:`solve` function.""" + """Enables implicit gradients for the :func:`solve` method.""" cls_solve = cls.solve if getattr(cls_solve, '__implicit_gradients_enabled__', False): - raise ValueError('Implicit gradients are already enabled for the solve function.') + raise TypeError('Implicit gradients are already enabled for the `solve` method.') cls_has_aux = cls.has_aux custom_root_kwargs = dict(has_aux=cls_has_aux, solve=cls.linear_solve) @@ -192,7 +192,7 @@ def solver_fn( return cls -class ImplicitMetaGradientModule(torchopt.nn.MetaGradientModule): +class ImplicitMetaGradientModule(MetaGradientModule): """The base class for differentiable implicit meta-gradient models.""" _custom_optimality: bool @@ -203,7 +203,7 @@ class ImplicitMetaGradientModule(torchopt.nn.MetaGradientModule): def __init_subclass__( cls, has_aux: bool = False, linear_solve: Optional[LinearSolver] = None ) -> None: - """Initialize the subclass.""" + """Validates and initializes the subclass.""" super().__init_subclass__() cls.has_aux = has_aux cls.linear_solve = linear_solve @@ -215,22 +215,22 @@ def __init_subclass__( if cls._custom_optimality: if isinstance(optimality, staticmethod): - raise TypeError('optimality() must not be a staticmethod.') + raise TypeError('method optimality() must not be a staticmethod.') if isinstance(optimality, classmethod): - raise TypeError('optimality() must not be a classmethod.') + raise TypeError('method optimality() must not be a classmethod.') if not callable(optimality): - raise TypeError('optimality() must be callable.') + raise TypeError('method optimality() must be callable.') elif not cls._custom_objective: raise TypeError( - 'ImplicitMetaGradientModule requires either an optimality() or an objective() function' + 'ImplicitMetaGradientModule requires either an optimality() method or an objective() method' ) else: if isinstance(objective, staticmethod): - raise TypeError('objective() must not be a staticmethod.') + raise TypeError('method objective() must not be a staticmethod.') if isinstance(objective, classmethod): - raise TypeError('objective() must not be a classmethod.') + raise TypeError('method objective() must not be a classmethod.') if not callable(objective): - raise TypeError('objective() must be callable.') + raise TypeError('method objective() must be callable.') cls.optimality = make_optimality_from_objective(objective) # type: ignore[assignment] diff --git a/torchopt/nn/__init__.py b/torchopt/nn/__init__.py index 3cb7fc78..57a8e802 100644 --- a/torchopt/nn/__init__.py +++ b/torchopt/nn/__init__.py @@ -14,4 +14,8 @@ # ============================================================================== """Base class for neural network modules that hold meta-parameters and meta-modules.""" +from torchopt.diff.implicit.nn.module import ImplicitMetaGradientModule # circular reference from torchopt.nn.module import MetaGradientModule + + +__all__ = ['MetaGradientModule', 'ImplicitMetaGradientModule'] From b77da08ade24c4ec02d5e0848ebc2a8f34b89544 Mon Sep 17 00:00:00 2001 From: waterhorse1 <1098616530@qq.com> Date: Sat, 12 Nov 2022 01:15:31 +0800 Subject: [PATCH 46/69] docs(README):update README.md --- README.md | 257 ++++++++++++++++++++++++++------------------- image/diffmode.png | Bin 0 -> 94962 bytes 2 files changed, 151 insertions(+), 106 deletions(-) create mode 100755 image/diffmode.png diff --git a/README.md b/README.md index 1bcbf548..434578a7 100644 --- a/README.md +++ b/README.md @@ -13,32 +13,34 @@ [![GitHub Repo Stars](https://img.shields.io/github/stars/metaopt/torchopt?color=brightgreen&logo=github)](https://github.com/metaopt/torchopt/stargazers) [![License](https://img.shields.io/github/license/metaopt/torchopt?label=license)](#license) -**TorchOpt** is a high-performance optimizer library built upon [PyTorch](https://pytorch.org) for easy implementation of functional optimization and gradient-based meta-learning. It consists of two main features: +**TorchOpt** is an efficient library for differentiable optimization built upon [PyTorch](https://pytorch.org). TorchOpt is: -- TorchOpt provides functional optimizer which enables [JAX-like](https://github.com/google/jax) composable functional optimizer for PyTorch. With TorchOpt, one can easily conduct neural network optimization in PyTorch with functional style optimizer, similar to [Optax](https://github.com/deepmind/optax) in JAX. -- With the design of functional programing, TorchOpt provides efficient, flexible, and easy-to-implement differentiable optimizer for gradient-based meta-learning research. It largely reduces the efforts required to implement sophisticated meta-learning algorithms. +- **Comprehensive**: TorchOpt provides three differentiation mode - explicit differentiation, implicit differentiation and zero-order differentiation for handling different differenable optimization situations. +- **Flexible**: TorchOpt provides both functional and objective-oriented API for user different preferences. Users can implement differentiable optimization in JAX-like or PyTorch-like style. +- **Efficient**: TorchOpt provides (1) CPU/GPU acceleration differentiable optimizer (2) RPC-based distributed training framework (3) Tree Operation parallelism, to largely increase the training efficiency for bi-level optimization problem. + +Beyond differentiable optimization, torchopt can also be regarded as a functional optimizer which enables [JAX-like](https://github.com/google/jax) composable functional optimizer for PyTorch. With TorchOpt, one can easily conduct neural network optimization in PyTorch with functional style optimizer, similar to [Optax](https://github.com/deepmind/optax) in JAX. -------------------------------------------------------------------------------- The README is organized as follows: - - [TorchOpt as Functional Optimizer](#torchopt-as-functional-optimizer) - [Optax-Like API](#optax-like-api) - [PyTorch-Like API](#pytorch-like-api) - [Differentiable](#differentiable) -- [TorchOpt as Differentiable Optimizer for Meta-Learning](#torchopt-as-differentiable-optimizer-for-meta-learning) - - [Meta-Learning API](#meta-learning-api) -- [Examples](#examples) -- [High-Performance](#high-performance) +- [TorchOpt for Differentiable topimization](#torchopt-for-differentiable-optimization) + - [Explicit Gradient](#explicit-gradient) + - [Implicit Gradient](#implicit-gradient) + - [Zero-order Gradient](#zero-order-gradient) +- [High-Performance and Distributed Training](#high-performance-and-distributed-training) - [Visualization](#visualization) +- [Examples](#examples) - [Installation](#installation) -- [Future Plan](#future-plan) - [Changelog](#changelog) - [The Team](#the-team) - [Citing TorchOpt](#citing-torchopt) -------------------------------------------------------------------------------- - ## TorchOpt as Functional Optimizer The design of TorchOpt follows the philosophy of functional programming. Aligned with [`functorch`](https://github.com/pytorch/functorch), users can conduct functional style programing with models, optimizers and training in PyTorch. We use the Adam optimizer as an example in the following illustration. You can also check out the tutorial notebook [Functional Optimizer](tutorials/1_Functional_Optimizer.ipynb) for more details. @@ -48,13 +50,6 @@ The design of TorchOpt follows the philosophy of functional programming. Aligned For those users who prefer fully functional programing, we offer Optax-Like API by passing gradients and optimizers states to the optimizer function. We design base class `torchopt.Optimizer` that has the same interface as `torch.optim.Optimizer`. Here is an example coupled with `functorch`: ```python -import functorch -import torch -import torch.nn as nn -import torch.nn.functional as F -from torch.utils.data import DataLoader - -import torchopt class Net(nn.Module): ... @@ -112,119 +107,178 @@ optimizer.step() # step updates ### Differentiable -On top of the same optimization function as `torch.optim`, an important benefit of functional optimizer is that one can implement differentiable optimization easily. This is particularly helpful when the algorithm requires to differentiate through optimization update (such as meta learning practices). We take as the inputs the gradients and optimizer states, use non-in-place operators to compute and output the updates. The processes can be automatically implemented, with the only need from users being to pass the argument `inplace=False` to the functions: - -```python -# Get updates -updates, opt_state = optimizer.update(grad, opt_state, inplace=False) -# Update network parameters -params = torchopt.apply_updates(params, updates, inplace=False) -``` +On top of the same optimization function as `torch.optim`, an important benefit of functional optimizer is that one can implement differentiable optimization easily. This is particularly helpful when the algorithm requires to differentiate through optimization update (such as meta learning practices). We take as the inputs the gradients and optimizer states, use non-in-place operators to compute and output the updates. The processes can be automatically implemented, with the only need from users being to pass the argument `inplace=False` to the functions. You can check [Explicit Gradient](#explicit-gradient) functional API for example. -------------------------------------------------------------------------------- -## TorchOpt as Differentiable Optimizer for Meta-Learning +## TorchOpt for Differentiable Optimization -Meta-Learning has gained enormous attention in both Supervised Learning and Reinforcement Learning. Meta-Learning algorithms often contain a bi-level optimization process with *inner loop* updating the network parameters and *outer loop* updating meta parameters. The figure below illustrates the basic formulation for meta-optimization in Meta-Learning. The main feature is that the gradients of *outer loss* will back-propagate through all `inner.step` operations. +We design a bilevel-optimization updating scheme, which can be easily extended to realize various differentiable optimization processes.

    -Since network parameters become a node of computation graph, a flexible Meta-Learning library should enable users manually control the gradient graph connection which means that users should have access to the network parameters and optimizer states for manually detaching or connecting the computation graph. In PyTorch designing, the network parameters or optimizer states are members of network (a.k.a. `torch.nn.Module`) or optimizer (a.k.a. `torch.optim.Optimizer`), this design significantly introducing difficulty for user control network parameters or optimizer states. Previous differentiable optimizer Repo [`higher`](https://github.com/facebookresearch/higher), [`learn2learn`](https://github.com/learnables/learn2learn) follows the PyTorch designing which leads to inflexible API. - -In contrast to them, TorchOpt realizes differentiable optimizer with functional programing, where Meta-Learning researchers could control the network parameters or optimizer states as normal variables (a.k.a. `torch.Tensor`). This functional optimizer design of TorchOpt is beneficial for implementing complex gradient flow Meta-Learning algorithms and allow us to improve computational efficiency by using techniques like operator fusion. +As shown above, the scheme contains an outer level that has parameters $\phi$ that can be learned end-to-end through the inner level parameters solution $\theta^{\star}(\phi)$ by using the best-response derivatives $\partial \theta^{\star}(\phi)/ \partial \phi$. TorchOpt supports three differentiation modes. It can be seen that the key component of this algorithm is to calculate the best-response (BR) Jacobian. From the BR-based perspective, existing gradient methods can be categorized into three groups: explicit gradient over unrolled optimization, implicit differentiation, and zero-order gradient differentiation. -### Meta-Learning API - -- We design a base class `torchopt.MetaOptimizer` for managing network updates in Meta-Learning. The constructor of `MetaOptimizer` takes as input the network rather than network parameters. `MetaOptimizer` exposed interface `step(loss)` takes as input the loss for step the network parameter. Refer to the tutorial notebook [Meta Optimizer](tutorials/3_Meta_Optimizer.ipynb) for more details. -- We offer `torchopt.chain` which can apply a list of chainable update transformations. Combined with `MetaOptimizer`, it can help you conduct gradient transformation such as gradient clip before the Meta optimizer steps. Refer to the tutorial notebook [Meta Optimizer](tutorials/3_Meta_Optimizer.ipynb) for more details. -- We observe that different Meta-Learning algorithms vary in inner-loop parameter recovery. TorchOpt provides basic functions for users to extract or recover network parameters and optimizer states anytime anywhere they want. -- Some algorithms such as MGRL ([arXiv:1805.09801](https://arxiv.org/abs/1805.09801)) initialize the inner-loop parameters inherited from previous inner-loop process when conducting a new bi-level process. TorchOpt also provides a finer function `stop_gradient` for manipulating the gradient graph, which is helpful for this kind of algorithms. Refer to the notebook [Stop Gradient](tutorials/4_Stop_Gradient.ipynb) for more details. - -We give an example of MAML ([arXiv:1703.03400](https://arxiv.org/abs/1703.03400)) with inner-loop Adam optimizer to illustrate TorchOpt APIs: +### Explicit Gradient +The idea of explicit gradient is to treat the gradient step as a differentiable function and try to backpropagate through the unrolled optimization path. This differentiation mode is suitable for algorithms when the inner-level optimization solution is obtained by a few gradient steps, such as [MAML](https://arxiv.org/abs/1703.03400), [MGRL](https://arxiv.org/abs/1805.09801). TorchOpt offers both functional and object-oriented API for EG to fit different user applications. +#### Functional API +The functional API is to conduct optimization in a functional programming style. Note that we pass the argument `inplace=False` to the functions to make the optimization differentiable. Refer to the notebook [Functional Optimizer](tutorials/1_Functional_Optimizer.ipynb) for more guidances. +```python +# Functional API +optimizer = torchopt.adam() +# Define meta and inner parameters +meta_params = ... +fmodel, params = make_functional(model) +# Initial state +state = optimizer.init(params) + +for iter in range(iter_times): + loss = inner_loss(fmodel, params, meta_params) + grads = torch.autograd.grad(loss, params) + # Apply non-inplace parameter update + updates, state = optimizer.update(grads, state, inplace=False) + params = torchopt.apply_updates(params, updates) + +loss = outer_loss(fmodel, params, meta_params) +meta_grads = torch.autograd.grad(loss, meta_params) +``` +#### OOP API +TorchOpt also provides OOP API compatible with PyTorch programming style. Refer to the example and the notebook [Meta Optimizer](tutorials/3_Meta_Optimizer.ipynb), [Stop Gradient](tutorials/4_Stop_Gradient.ipynb) for more guidances. ```python -net = Net() # init +# OOP API +# Define meta and inner parameters +meta_params = ... +model = ... +# Define differentiable optimizer +optimizer = torchopt.MetaAdam(model.parameters()) + +for iter in range(iter_times): + # perform inner update + loss = inner_loss(model, meta_params) + optimizer.step(loss) + +loss = outer_loss(model, meta_params) +loss.backward() +``` -# The constructor `MetaOptimizer` takes as input the network -inner_optim = torchopt.MetaAdam(net) -outer_optim = torchopt.Adam(net.parameters()) - -for train_iter in range(train_iters): - outer_loss = 0 - for task in range(num_tasks): - loader = Loader(num_tasks) - - # Store states at the initial points - net_state = torchopt.extract_state_dict(net) # extract state - optim_state = torchopt.extract_state_dict(inner_optim) - for inner_iter in range(inner_iters): - # Compute inner loss and perform inner update - xs, ys = next(loader) - pred = net(xs) - inner_loss = F.cross_entropy(pred, ys) - inner_optim.step(inner_loss) - - # Compute outer loss and back-propagate - xs, ys = next(loader) - pred = net(xs) - outer_loss = outer_loss + F.cross_entropy(pred, ys) - - # Recover network and optimizer states at the initial point for the next task - torchopt.recover_state_dict(inner_optim, optim_state) - torchopt.recover_state_dict(net, net_state) - - outer_loss = outer_loss / num_tasks # task average - outer_optim.zero_grad() - outer_loss.backward() - outer_optim.step() - - # Stop gradient if necessary - torchopt.stop_gradient(net) - torchopt.stop_gradient(inner_optim) +### Implicit Gradient +By treating the solution $\theta^{\star}$ as an implicit function of $\phi$, the idea of IG is to directly get analytical best-response derivatives $\partial \theta^{\star}(\phi)/ \partial \phi$ by [implicit function theorem](https://en.wikipedia.org/wiki/Implicit_function_theorem). This is suitable for algorithms when the inner-level optimal solution is achieved $\frac{\partial F(\theta, \phi)}{\partial \theta} |_{\theta^{\star}} = 0$ or reaches some stationary conditions $F(\theta^{\star}, \phi)=0$, such as [iMAML](https://arxiv.org/abs/1909.04630), [DEQ](https://arxiv.org/abs/1909.01377). TorchOpt offers functional/OOP API for supporting both [conjugate gradient-based](https://arxiv.org/abs/1909.04630) and [Neumann series](https://arxiv.org/abs/1911.02590) based IG method. Refer to the example [IMAML](https://github.com/waterhorse1/torchopt/tree/readme/examples/iMAML) and the notebook [Implicit Gradient](tutorials/5_Implicit_Differentiation.ipynb) for more guidances. +#### Functional API +For implicit gradient, users need to define the stationary condition and TorchOpt provides the decorator to warp the solve function for enabling implicit gradient computation. +```python +# Functional API for implicit gradient +def stationary(params, meta_params, data): + # stationary condition construction + return stationary condition + +# Decorator for warpping the function +# and specify the linear solver (conjugate gradient or neumann series) +@torchopt.diff.implicit.custom_root(stationary, linear_solver) +def solve(params, meta_params, data): + # forward optimization process for params + return output + +# Define params, meta params and get data +params, meta_prams, data = ..., ..., ... +optimal_params = solve(params, meta_params, data) +loss = outer_loss(optimal_params) + +meta_grads = torch.autograd.grad(loss, meta_params) +``` +#### OOP API +Torchopt also offer an OOP API, users need to inherit from the class ImplicitMetaGradientModule to construct the inner-loop network. Users need to define the stationary condition/objective function and the inner-loop solve function to enable implicit gradient computation. +```python +# Inherited from the class ImplicitMetaGradientModule +# and specify the linear solver (conjugate gradient or neumann series) +class InnerNet(ImplicitMetaGradientModule, linear_solver): + def __init__(self): + ... + def forward(self): + # forward process + ... + def optimality(self): + # stationary condition construction for calculateing implicit gradient + # If this method is not implemented, it will be + # automatically derived from the gradient of the `objective` function. + ... + def objective(self): + # define the inner-loop optimization objective + ... + def solve(self, data): + # conduct the inner-loop optimization + ... + +# get meta_params and data +meta_params, data = ..., ... +inner_net = InnerNet() + +# solve for inner-loop process +# related with the meta parameters +optimal_inner_net = inner_net.solve(meta_params, data) + +# get outer loss and solve for meta gradient +loss = outer_loss(optimal_inner_net) +meta_grad = torch.autograd.grad(loss, meta_params) ``` +### Zero-order gradient +When the inner-loop process is non-differentiable or one wants to eliminate the heavy computation burdens in the previous two modes (brought by Hessian), one can choose Zero-order gradient (ZD). ZD typically gets gradients based on zero-order estimation, such as finite-difference, or [Evolutionary Strategy](https://arxiv.org/abs/1703.03864). Instead of optimizing the objective $F$, ES optimize a smoothed objective. TorchOpt provides functional and OOP API for the ES method. Refer to the notebook [Zero-order gradient](tutorials/6_zero_order.ipynb) for more guidances. +#### Functional API +```python +# Functional API +# Specify method and hyper-parameter of ES +@torchopt.diff.zero_order(method, params) +def forward(meta_params, data): + # forward process + return output +``` -------------------------------------------------------------------------------- +## High-Performance and Distributed Training +### CPU/GPU accelerated differentiable optimizer +We take the optimizer as a whole instead of separating it into several basic operators (e.g., *sqrt* and *div*}). Therefore, by manually writing the forward and backward functions, we can perform the symbolic reduction. In addition, we can store some intermediate data that can be reused during the back-propagation. We write the accelerated functions in C++ OpenMP and CUDA, bind them by `pybind11` to allow they can be called by Python, and then we define the forward and backward behavior using `torch.autograd.Function`. User can use by simply setting the `use_accelerated_op` flag as `True`. Refer to the correpsonding sections in [Functional Optimizer](tutorials/1_Functional_Optimizer.ipynb) and [Meta Optimizer](tutorials/3_Meta_Optimizer.ipynb) -## Examples +```python +optimizer = torchopt.MetaAdam(net, lr, use_accelerated_op=True) +``` -In [`examples`](examples), we offer several examples of functional optimizer and 5 light-weight meta-learning examples with TorchOpt. The meta-learning examples covers 2 Supervised Learning and 3 Reinforcement Learning algorithms. +### Distributed Training +`TorchOpt` provides distributed training features based on the PyTorch RPC module for better training speed and multi-node multi-GPU support. Different from the MPI-like parallelization paradigm, which uses multiple homogenous workers and requires carefully designed communication hooks, the RPC APIs allow users to build their optimization pipeline more flexibly. Experimental results show that we achieve approximately linear relationship between the speed-up ratio and the number of workers. Check the [distributed MAML example](https://github.com/metaopt/torchopt/tree/main/examples/distributed/few-shot) for more specific guidance. -- [Model Agnostic Meta Learning (MAML) - Supervised Learning](https://arxiv.org/abs/1703.03400) (ICML 2017) -- [Learning to Reweight Examples for Robust Deep Learning](https://arxiv.org/abs/1803.09050) (ICML 2018) -- [Model Agnostic Meta Learning (MAML) - Reinforcement Learning](https://arxiv.org/abs/1703.03400) (ICML 2017) -- [Meta Gradient Reinforcement Learning (MGRL)](https://arxiv.org/abs/1805.09801) (NeurIPS 2018) -- [Learning through opponent learning process (LOLA)](https://arxiv.org/abs/1709.04326) (AAMAS 2018) +### OpTree +We implement the *PyTree* to enable fast nested structure flatten using C++. The tree operations (e.g., flatten and unflatten) are very important in enabling functional and Just-In-Time (JIT) features of deep learning frameworks. By implementing it in C++, we can use some cache/memory friendly structures (e.g., `absl::InlinedVector`) to improve the performance. For more guidance and comparison results, refer to our open source project [`OpTree`](https://github.com/metaopt/optree). -------------------------------------------------------------------------------- -## High-Performance +## Visualization -One can think of the scale procedures on gradients of optimizer algorithms as a combination of several operations. For example, the implementation of the Adam algorithm often includes addition, multiplication, power and square operations, one can fuse these operations into several compound functions. The operator fusion could greatly simplify the computation graph and reduce the GPU function launching stall. In addition, one can also implement the optimizer backward function and manually reuse some intermediate tensors to improve the backward performance. Users can pass argument `use_accelerated_op=True` to `adam`, `Adam` and `MetaAdam` to enable the fused accelerated operator. The arguments are the same between the two kinds of implementations. +Complex gradient flow in meta-learning brings in a great challenge for managing the gradient flow and verifying the correctness of it. TorchOpt provides a visualization tool that draw variable (e.g. network parameters or meta parameters) names on the gradient graph for better analyzing. The visualization tool is modified from [`torchviz`](https://github.com/szagoruyko/pytorchviz). Refer to the example [visualization code](examples/visualize.py) and the notebook [Visualization](tutorials/2_Visualization.ipynb) for more details. -Here we evaluate the performance using the MAML-Omniglot code with the inner-loop Adam optimizer on GPU. We comparable the run time of the overall algorithm and the meta-optimization (outer-loop optimization) under different network architecture/inner-step numbers. We choose [`higher`](https://github.com/facebookresearch/higher) as our baseline. The figure below illustrate that our accelerated Adam can achieve at least $1/3$ efficiency improvement over the baseline. +The figure below show the visualization result. Compared with [`torchviz`](https://github.com/szagoruyko/pytorchviz), TorchOpt fuses the operations within the `Adam` together (orange) to reduce the complexity and provide simpler visualization.
    - +
    -Notably, the operator fusion not only increases performance but also help simplify the computation graph, which will be discussed in the next section. - -------------------------------------------------------------------------------- +## Examples -## Visualization - -Complex gradient flow in meta-learning brings in a great challenge for managing the gradient flow and verifying the correctness of it. TorchOpt provides a visualization tool that draw variable (e.g. network parameters or meta parameters) names on the gradient graph for better analyzing. The visualization tool is modified from [`torchviz`](https://github.com/szagoruyko/pytorchviz). We provide an example using the [visualization code](examples/visualize.py). Also refer to the notebook [Visualization](tutorials/2_Visualization.ipynb) for more details. +In [`examples`](examples), we offer several examples of functional optimizer and light-weight meta-learning examples with TorchOpt. -The figure below show the visualization result. Compared with [`torchviz`](https://github.com/szagoruyko/pytorchviz), TorchOpt fuses the operations within the `Adam` together (orange) to reduce the complexity and provide simpler visualization. +- [Model Agnostic Meta Learning (MAML) - Supervised Learning](https://arxiv.org/abs/1703.03400) (ICML 2017) +- [Learning to Reweight Examples for Robust Deep Learning](https://arxiv.org/abs/1803.09050) (ICML 2018) +- [Model Agnostic Meta Learning (MAML) - Reinforcement Learning](https://arxiv.org/abs/1703.03400) (ICML 2017) +- [Meta Gradient Reinforcement Learning (MGRL)](https://arxiv.org/abs/1805.09801) (NeurIPS 2018) +- [Learning through opponent learning process (LOLA)](https://arxiv.org/abs/1709.04326) (AAMAS 2018) +- [Meta-Learning with Implicit Gradients](https://arxiv.org/abs/1909.04630) (NeurIPS 2019) -
    - -
    +Also check [`examples`](examples) for more distributed/visuaization/functorch-compatible examples. -------------------------------------------------------------------------------- + ## Installation Requirements @@ -270,15 +324,6 @@ make install-editable # or run `pip3 install --no-build-isolation --editable .` -------------------------------------------------------------------------------- -## Future Plan - -- [X] CPU-accelerated optimizer -- [X] Support more optimizers such as AdamW, RMSProp -- [X] Support general implicit differentiation -- [X] Zero order optimization -- [X] Distributed optimization -- [ ] Support `complex` data type - ## Changelog See [CHANGELOG.md](CHANGELOG.md). @@ -287,7 +332,7 @@ See [CHANGELOG.md](CHANGELOG.md). ## The Team -TorchOpt is a work by Jie Ren, Xidong Feng, [Bo Liu](https://github.com/Benjamin-eecs), [Xuehai Pan](https://github.com/XuehaiPan), [Luo Mai](https://luomai.github.io/) and [Yaodong Yang](https://www.yangyaodong.com/). +TorchOpt is a work by Jie Ren, [Xidong Feng](https://github.com/waterhorse1), [Bo Liu](https://github.com/Benjamin-eecs), [Xuehai Pan](https://github.com/XuehaiPan), [Luo Mai](https://luomai.github.io/) and [Yaodong Yang](https://www.yangyaodong.com/). ## Citing TorchOpt diff --git a/image/diffmode.png b/image/diffmode.png new file mode 100755 index 0000000000000000000000000000000000000000..3f2613f3e84afe915d58132a8c52dcae70e13305 GIT binary patch literal 94962 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ⅇ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�IW4KOp7X1AA0-(omWbU*sPD3RP+DN8N{NO~ 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 =28-;6a(1S)T?W2Fsur(&hfzn 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 diff --git a/examples/iMAML/imaml_omniglot.py b/examples/iMAML/imaml_omniglot.py index 7b165ac0..2b0c9738 100644 --- a/examples/iMAML/imaml_omniglot.py +++ b/examples/iMAML/imaml_omniglot.py @@ -24,7 +24,6 @@ import argparse import time -import functorch import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np @@ -32,19 +31,53 @@ import torch import torch.nn as nn import torch.nn.functional as F -import torch.optim as optim import torchopt -from torchopt import pytree +from torchopt.diff.implicit import ImplicitMetaGradientModule -from support.omniglot_loaders import OmniglotNShot # isort: skip +from helpers.omniglot_loaders import OmniglotNShot # isort: skip mpl.use('Agg') plt.style.use('bmh') +class InnerNet( + ImplicitMetaGradientModule, + linear_solve=torchopt.linear_solve.solve_normal_cg(maxiter=5, atol=0), +): + def __init__(self, meta_net, n_inner_iter, reg_param): + super().__init__() + self.meta_net = meta_net + self.net = torchopt.module_clone(meta_net, by='deepcopy', detach_buffers=True) + self.n_inner_iter = n_inner_iter + self.reg_param = reg_param + + def forward(self, x): + return self.net(x) + + def objective(self, x, y): + y_pred = self(x) + loss = F.cross_entropy(y_pred, y) + regularization_loss = 0 + for p1, p2 in zip(self.parameters(), self.meta_parameters()): + regularization_loss += 0.5 * self.reg_param * torch.sum(torch.square(p1 - p2)) + return loss + regularization_loss + + def solve(self, x, y): + params = tuple(self.parameters()) + inner_optim = torchopt.SGD(params, lr=1e-1) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(self.n_inner_iter): + loss = self.objective(x, y) + inner_optim.zero_grad() + loss.backward(inputs=params) + inner_optim.step() + return self + + def main(): argparser = argparse.ArgumentParser() argparser.add_argument('--n_way', type=int, help='n way', default=5) @@ -102,24 +135,18 @@ def main(): # We will use Adam to (meta-)optimize the initial parameters # to be adapted. net.train() - fnet, params = functorch.make_functional(net) - meta_opt = torchopt.adam(lr=1e-3) - meta_opt_state = meta_opt.init(params) + meta_opt = torchopt.Adam(net.parameters(), lr=1e-3) log = [] - test(db, [params, fnet], epoch=-1, log=log, args=args) + test(db, net, epoch=-1, log=log, args=args) for epoch in range(10): - meta_opt, meta_opt_state = train( - db, [params, fnet], (meta_opt, meta_opt_state), epoch, log, args - ) - test(db, [params, fnet], epoch, log, args) + train(db, net, meta_opt, epoch, log, args) + test(db, net, epoch, log, args) plot(log) -def train(db, net, meta_opt_and_state, epoch, log, args): +def train(db, net, meta_opt, epoch, log, args): n_train_iter = db.x_train.shape[0] // db.batchsz - params, fnet = net - meta_opt, meta_opt_state = meta_opt_and_state # Given this module we've created, rip out the parameters and buffers # and return a functional version of the module. `fnet` is stateless # and can be called with `fnet(params, buffers, args, kwargs)` @@ -130,54 +157,44 @@ def train(db, net, meta_opt_and_state, epoch, log, args): # Sample a batch of support and query images and labels. x_spt, y_spt, x_qry, y_qry = db.next() - task_num, setsz, c_, h, w = x_spt.size() - querysz = x_qry.size(1) + task_num = x_spt.size(0) n_inner_iter = args.inner_steps reg_param = args.reg_params + qry_losses = [] qry_accs = [] - - init_params_copy = pytree.tree_map( - lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params - ) + meta_opt.zero_grad() for i in range(task_num): # Optimize the likelihood of the support set by taking # gradient steps w.r.t. the model's parameters. # This adapts the model's meta-parameters to the task. - optimal_params = train_imaml_inner_solver( - init_params_copy, - params, - (x_spt[i], y_spt[i]), - (fnet, n_inner_iter, reg_param), - ) + inner_net = InnerNet(net, n_inner_iter, reg_param) + optimal_inner_net = inner_net.solve(x_spt[i], y_spt[i]) + # The final set of adapted parameters will induce some # final loss and accuracy on the query dataset. # These will be used to update the model's meta-parameters. - qry_logits = fnet(optimal_params, x_qry[i]) + qry_logits = optimal_inner_net(x_qry[i]) qry_loss = F.cross_entropy(qry_logits, y_qry[i]) - # Update the model's meta-parameters to optimize the query - # losses across all of the tasks sampled in this batch. - # qry_loss = qry_loss / task_num # scale gradients - meta_grads = torch.autograd.grad(qry_loss / task_num, params) - meta_updates, meta_opt_state = meta_opt.update(meta_grads, meta_opt_state) - params = torchopt.apply_updates(params, meta_updates) - qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).sum().item() / querysz - - qry_losses.append(qry_loss.detach()) - qry_accs.append(qry_acc) - - qry_losses = sum(qry_losses) / task_num - qry_accs = 100.0 * sum(qry_accs) / task_num + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() + qry_losses.append(qry_loss) + qry_accs.append(qry_acc.item()) + + qry_losses = torch.mean(torch.stack(qry_losses)) + qry_losses.backward() + meta_opt.step() + qry_losses = qry_losses.item() + qry_accs = 100.0 * np.mean(qry_accs) i = epoch + float(batch_idx) / n_train_iter iter_time = time.time() - start_time + torch.cuda.empty_cache() print( f'[Epoch {i:.2f}] Train Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f} | Time: {iter_time:.2f}' ) - log.append( { 'epoch': i, @@ -188,8 +205,6 @@ def train(db, net, meta_opt_and_state, epoch, log, args): } ) - return (meta_opt, meta_opt_state) - def test(db, net, epoch, log, args): # Crucially in our testing procedure here, we do *not* fine-tune @@ -197,8 +212,6 @@ def test(db, net, epoch, log, args): # Most research papers using MAML for this task do an extra # stage of fine-tuning here that should be added if you are # adapting this code for research. - params, fnet = net - # fnet, params, buffers = functorch.make_functional_with_buffers(net) n_test_iter = db.x_test.shape[0] // db.batchsz qry_losses = [] @@ -208,36 +221,32 @@ def test(db, net, epoch, log, args): # doesn't have to be duplicated between `train` and `test`? n_inner_iter = args.inner_steps reg_param = args.reg_params - init_params_copy = pytree.tree_map( - lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params - ) for batch_idx in range(n_test_iter): x_spt, y_spt, x_qry, y_qry = db.next('test') - task_num, setsz, c_, h, w = x_spt.size() - querysz = x_qry.size(1) + task_num = x_spt.size(0) for i in range(task_num): # Optimize the likelihood of the support set by taking # gradient steps w.r.t. the model's parameters. # This adapts the model's meta-parameters to the task. - optimal_params = test_imaml_inner_solver( - init_params_copy, - params, - (x_spt[i], y_spt[i]), - (fnet, n_inner_iter, reg_param), - ) + inner_net = InnerNet(net, n_inner_iter, reg_param) + with torch.no_grad(): + optimal_inner_net = inner_net.solve(x_spt[i], y_spt[i]) # The query loss and acc induced by these parameters. - qry_logits = fnet(optimal_params, x_qry[i]) - qry_loss = F.cross_entropy(qry_logits, y_qry[i], reduction='none') - qry_losses.append(qry_loss.detach()) - qry_accs.append((qry_logits.argmax(dim=1) == y_qry[i]).detach()) + qry_logits = optimal_inner_net(x_qry[i]) + qry_loss = F.cross_entropy(qry_logits, y_qry[i]) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() + qry_losses.append(qry_loss.item()) + qry_accs.append(qry_acc.item()) + + qry_losses = np.mean(qry_losses) + qry_accs = 100.0 * np.mean(qry_accs) + torch.cuda.empty_cache() - qry_losses = torch.cat(qry_losses).mean().item() - qry_accs = 100.0 * torch.cat(qry_accs).float().mean().item() print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') log.append( { @@ -250,71 +259,6 @@ def test(db, net, epoch, log, args): ) -def imaml_objective(optimal_params, init_params, data, aux): - x_spt, y_spt = data - fnet, n_inner_iter, reg_param = aux - fnet.eval() - y_pred = fnet(optimal_params, x_spt) - fnet.train() - regularization_loss = 0 - for p1, p2 in zip(optimal_params, init_params): - regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) - loss = F.cross_entropy(y_pred, y_spt) + regularization_loss - return loss - - -@torchopt.diff.implicit.custom_root( - functorch.grad(imaml_objective, argnums=0), - argnums=1, - has_aux=False, - solve=torchopt.linear_solve.solve_normal_cg(maxiter=5, atol=0), -) -def train_imaml_inner_solver(init_params_copy, init_params, data, aux): - x_spt, y_spt = data - fnet, n_inner_iter, reg_param = aux - # Initial functional optimizer based on TorchOpt - params = init_params_copy - inner_opt = torchopt.sgd(lr=1e-1) - inner_opt_state = inner_opt.init(params) - with torch.enable_grad(): - # Temporarily enable gradient computation for conducting the optimization - for _ in range(n_inner_iter): - pred = fnet(params, x_spt) - loss = F.cross_entropy(pred, y_spt) # compute loss - # Compute regularization loss - regularization_loss = 0 - for p1, p2 in zip(params, init_params): - regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) - final_loss = loss + regularization_loss - grads = torch.autograd.grad(final_loss, params) # compute gradients - updates, inner_opt_state = inner_opt.update(grads, inner_opt_state) # get updates - params = torchopt.apply_updates(params, updates) - return params - - -def test_imaml_inner_solver(init_params_copy, init_params, data, aux): - x_spt, y_spt = data - fnet, n_inner_iter, reg_param = aux - # Initial functional optimizer based on TorchOpt - params = init_params_copy - inner_opt = torchopt.sgd(lr=1e-1) - inner_opt_state = inner_opt.init(params) - with torch.enable_grad(): - # Temporarily enable gradient computation for conducting the optimization - for _ in range(n_inner_iter): - pred = fnet(params, x_spt) - loss = F.cross_entropy(pred, y_spt) # compute loss - # Compute regularization loss - regularization_loss = 0 - for p1, p2 in zip(params, init_params): - regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) - final_loss = loss + regularization_loss - grads = torch.autograd.grad(final_loss, params) # compute gradients - updates, inner_opt_state = inner_opt.update(grads, inner_opt_state) # get updates - params = torchopt.apply_updates(params, updates) - return params - - def plot(log): # Generally you should pull your plotting code out of your training # script but we are doing it here for brevity. diff --git a/examples/iMAML/imaml_omniglot_functional.py b/examples/iMAML/imaml_omniglot_functional.py new file mode 100644 index 00000000..080541c6 --- /dev/null +++ b/examples/iMAML/imaml_omniglot_functional.py @@ -0,0 +1,338 @@ +# Copyright 2022 MetaOPT Team. 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. +# ============================================================================== +""" +This example shows how to use TorchOpt to do iMAML-GD (see [1] for more details) +for few-shot Omniglot classification. + +[1] Rajeswaran, A., Finn, C., Kakade, S. M., & Levine, S. (2019). + Meta-learning with implicit gradients. In Advances in Neural Information Processing Systems (pp. 113-124). + https://arxiv.org/abs/1909.04630 +""" + +import argparse +import time + +import functorch +import matplotlib as mpl +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import torch +import torch.nn as nn +import torch.nn.functional as F + +import torchopt +from torchopt import pytree + + +from helpers.omniglot_loaders import OmniglotNShot # isort: skip + + +mpl.use('Agg') +plt.style.use('bmh') + + +def main(): + argparser = argparse.ArgumentParser() + argparser.add_argument('--n_way', type=int, help='n way', default=5) + argparser.add_argument('--k_spt', type=int, help='k shot for support set', default=5) + argparser.add_argument('--k_qry', type=int, help='k shot for query set', default=5) + argparser.add_argument('--inner_steps', type=int, help='number of inner steps', default=5) + argparser.add_argument( + '--reg_params', type=float, help='regularization parameters', default=2.0 + ) + argparser.add_argument( + '--task_num', type=int, help='meta batch size, namely task num', default=16 + ) + argparser.add_argument('--seed', type=int, help='random seed', default=1) + args = argparser.parse_args() + + torch.manual_seed(args.seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(args.seed) + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + np.random.seed(args.seed) + rng = np.random.default_rng(args.seed) + + # Set up the Omniglot loader. + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + db = OmniglotNShot( + '/tmp/omniglot-data', + batchsz=args.task_num, + n_way=args.n_way, + k_shot=args.k_spt, + k_query=args.k_qry, + imgsz=28, + rng=rng, + device=device, + ) + + # Create a vanilla PyTorch neural network. + net = nn.Sequential( + nn.Conv2d(1, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True, track_running_stats=False), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True, track_running_stats=False), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Conv2d(64, 64, 3), + nn.BatchNorm2d(64, momentum=1.0, affine=True, track_running_stats=False), + nn.ReLU(inplace=False), + nn.MaxPool2d(2, 2), + nn.Flatten(), + nn.Linear(64, args.n_way), + ).to(device) + + # We will use Adam to (meta-)optimize the initial parameters + # to be adapted. + net.train() + fnet, params = functorch.make_functional(net) + meta_opt = torchopt.adam(lr=1e-3) + meta_opt_state = meta_opt.init(params) + + log = [] + test(db, [params, fnet], epoch=-1, log=log, args=args) + for epoch in range(10): + meta_opt, meta_opt_state = train( + db, [params, fnet], (meta_opt, meta_opt_state), epoch, log, args + ) + test(db, [params, fnet], epoch, log, args) + plot(log) + + +def train(db, net, meta_opt_and_state, epoch, log, args): + n_train_iter = db.x_train.shape[0] // db.batchsz + params, fnet = net + meta_opt, meta_opt_state = meta_opt_and_state + # Given this module we've created, rip out the parameters and buffers + # and return a functional version of the module. `fnet` is stateless + # and can be called with `fnet(params, buffers, args, kwargs)` + # fnet, params, buffers = functorch.make_functional_with_buffers(net) + + for batch_idx in range(n_train_iter): + start_time = time.time() + # Sample a batch of support and query images and labels. + x_spt, y_spt, x_qry, y_qry = db.next() + + task_num = x_spt.size(0) + + n_inner_iter = args.inner_steps + reg_param = args.reg_params + qry_losses = [] + qry_accs = [] + + init_params_copy = pytree.tree_map( + lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params + ) + + for i in range(task_num): + # Optimize the likelihood of the support set by taking + # gradient steps w.r.t. the model's parameters. + # This adapts the model's meta-parameters to the task. + + optimal_params = train_imaml_inner_solver( + init_params_copy, + params, + (x_spt[i], y_spt[i]), + (fnet, n_inner_iter, reg_param), + ) + # The final set of adapted parameters will induce some + # final loss and accuracy on the query dataset. + # These will be used to update the model's meta-parameters. + qry_logits = fnet(optimal_params, x_qry[i]) + qry_loss = F.cross_entropy(qry_logits, y_qry[i]) + # Update the model's meta-parameters to optimize the query + # losses across all of the tasks sampled in this batch. + # qry_loss = qry_loss / task_num # scale gradients + meta_grads = torch.autograd.grad(qry_loss / task_num, params) + meta_updates, meta_opt_state = meta_opt.update(meta_grads, meta_opt_state) + params = torchopt.apply_updates(params, meta_updates) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() + qry_losses.append(qry_loss.item()) + qry_accs.append(qry_acc.item()) + + qry_losses = np.mean(qry_losses) + qry_accs = 100.0 * np.mean(qry_accs) + i = epoch + float(batch_idx) / n_train_iter + iter_time = time.time() - start_time + torch.cuda.empty_cache() + + print( + f'[Epoch {i:.2f}] Train Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f} | Time: {iter_time:.2f}' + ) + log.append( + { + 'epoch': i, + 'loss': qry_losses, + 'acc': qry_accs, + 'mode': 'train', + 'time': time.time(), + } + ) + + return (meta_opt, meta_opt_state) + + +def test(db, net, epoch, log, args): + # Crucially in our testing procedure here, we do *not* fine-tune + # the model during testing for simplicity. + # Most research papers using MAML for this task do an extra + # stage of fine-tuning here that should be added if you are + # adapting this code for research. + params, fnet = net + # fnet, params, buffers = functorch.make_functional_with_buffers(net) + n_test_iter = db.x_test.shape[0] // db.batchsz + + qry_losses = [] + qry_accs = [] + + # TODO: Maybe pull this out into a separate module so it + # doesn't have to be duplicated between `train` and `test`? + n_inner_iter = args.inner_steps + reg_param = args.reg_params + init_params_copy = pytree.tree_map( + lambda t: t.clone().detach_().requires_grad_(requires_grad=t.requires_grad), params + ) + + for batch_idx in range(n_test_iter): + x_spt, y_spt, x_qry, y_qry = db.next('test') + + task_num = x_spt.size(0) + + for i in range(task_num): + # Optimize the likelihood of the support set by taking + # gradient steps w.r.t. the model's parameters. + # This adapts the model's meta-parameters to the task. + + optimal_params = test_imaml_inner_solver( + init_params_copy, + params, + (x_spt[i], y_spt[i]), + (fnet, n_inner_iter, reg_param), + ) + + # The query loss and acc induced by these parameters. + qry_logits = fnet(optimal_params, x_qry[i]) + qry_loss = F.cross_entropy(qry_logits, y_qry[i]) + qry_acc = (qry_logits.argmax(dim=1) == y_qry[i]).float().mean() + qry_losses.append(qry_loss.item()) + qry_accs.append(qry_acc.item()) + + qry_losses = np.mean(qry_losses) + qry_accs = 100.0 * np.mean(qry_accs) + torch.cuda.empty_cache() + + print(f'[Epoch {epoch+1:.2f}] Test Loss: {qry_losses:.2f} | Acc: {qry_accs:.2f}') + log.append( + { + 'epoch': epoch + 1, + 'loss': qry_losses, + 'acc': qry_accs, + 'mode': 'test', + 'time': time.time(), + } + ) + + +def imaml_objective(optimal_params, init_params, data, aux): + x_spt, y_spt = data + fnet, n_inner_iter, reg_param = aux + y_pred = fnet(optimal_params, x_spt) + regularization_loss = 0 + for p1, p2 in zip(optimal_params, init_params): + regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) + loss = F.cross_entropy(y_pred, y_spt) + regularization_loss + return loss + + +@torchopt.diff.implicit.custom_root( + functorch.grad(imaml_objective, argnums=0), + argnums=1, + has_aux=False, + solve=torchopt.linear_solve.solve_normal_cg(maxiter=5, atol=0), +) +def train_imaml_inner_solver(init_params_copy, init_params, data, aux): + x_spt, y_spt = data + fnet, n_inner_iter, reg_param = aux + # Initial functional optimizer based on TorchOpt + params = init_params_copy + inner_opt = torchopt.sgd(lr=1e-1) + inner_opt_state = inner_opt.init(params) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(n_inner_iter): + pred = fnet(params, x_spt) + loss = F.cross_entropy(pred, y_spt) # compute loss + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params, init_params): + regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) + final_loss = loss + regularization_loss + grads = torch.autograd.grad(final_loss, params) # compute gradients + updates, inner_opt_state = inner_opt.update(grads, inner_opt_state) # get updates + params = torchopt.apply_updates(params, updates) + return params + + +def test_imaml_inner_solver(init_params_copy, init_params, data, aux): + x_spt, y_spt = data + fnet, n_inner_iter, reg_param = aux + # Initial functional optimizer based on TorchOpt + params = init_params_copy + inner_opt = torchopt.sgd(lr=1e-1) + inner_opt_state = inner_opt.init(params) + with torch.enable_grad(): + # Temporarily enable gradient computation for conducting the optimization + for _ in range(n_inner_iter): + pred = fnet(params, x_spt) + loss = F.cross_entropy(pred, y_spt) # compute loss + # Compute regularization loss + regularization_loss = 0 + for p1, p2 in zip(params, init_params): + regularization_loss += 0.5 * reg_param * torch.sum(torch.square(p1 - p2)) + final_loss = loss + regularization_loss + grads = torch.autograd.grad(final_loss, params) # compute gradients + updates, inner_opt_state = inner_opt.update(grads, inner_opt_state) # get updates + params = torchopt.apply_updates(params, updates) + return params + + +def plot(log): + # Generally you should pull your plotting code out of your training + # script but we are doing it here for brevity. + df = pd.DataFrame(log) + + fig, ax = plt.subplots(figsize=(8, 4), dpi=250) + train_df = df[df['mode'] == 'train'] + test_df = df[df['mode'] == 'test'] + ax.plot(train_df['epoch'], train_df['acc'], label='Train') + ax.plot(test_df['epoch'], test_df['acc'], label='Test') + ax.set_xlabel('Epoch') + ax.set_ylabel('Accuracy') + ax.set_ylim(80, 100) + ax.set_title('iMAML Omniglot (Functional)') + ax.legend(ncol=2, loc='lower right') + fig.tight_layout() + fname = 'imaml-accs-functional.png' + print(f'--- Plotting accuracy to {fname}') + fig.savefig(fname) + plt.close(fig) + + +if __name__ == '__main__': + main() diff --git a/setup.py b/setup.py index f457b32e..966bdb32 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ import os import pathlib +import re import shutil import sys import sysconfig @@ -84,8 +85,6 @@ def build_extension(self, ext): VERSION_CONTENT = None if not version.__release__: - import re - VERSION_CONTENT = VERSION_FILE.read_text(encoding='UTF-8') VERSION_FILE.write_text( data=re.sub( diff --git a/tests/helpers.py b/tests/helpers.py index a84d78bc..6c7c4f01 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -23,6 +23,7 @@ import pytest import torch import torch.nn as nn +import torch.types from torch.utils import data @@ -100,7 +101,7 @@ def forward(self, x: torch.Tensor) -> torch.Tensor: @torch.no_grad() def get_models( - device: Optional[Union[str, torch.device]] = None, dtype: torch.dtype = torch.float32 + device: torch.types.Device = None, dtype: torch.dtype = torch.float32 ) -> Tuple[nn.Module, nn.Module, nn.Module, data.DataLoader]: seed_everything(seed=42) diff --git a/tests/test_implicit.py b/tests/test_implicit.py index 399ee025..06d180d4 100644 --- a/tests/test_implicit.py +++ b/tests/test_implicit.py @@ -16,7 +16,7 @@ import copy from collections import OrderedDict from types import FunctionType -from typing import Optional, Tuple, Union +from typing import Tuple import functorch import jax @@ -27,6 +27,7 @@ import torch import torch.nn as nn import torch.nn.functional as F +import torch.types from torch.utils import data import helpers @@ -70,7 +71,7 @@ def func(params, x): @torch.no_grad() def get_model_torch( - device: Optional[Union[str, torch.device]] = None, dtype: torch.dtype = torch.float32 + device: torch.types.Device = None, dtype: torch.dtype = torch.float32 ) -> Tuple[nn.Module, data.DataLoader]: helpers.seed_everything(seed=42) @@ -242,7 +243,7 @@ class InnerNet(ImplicitMetaGradientModule, has_aux=True): def __init__(self, meta_model): super().__init__() self.meta_model = meta_model - self.model = copy.deepcopy(meta_model) + self.model = torchopt.module_clone(meta_model, by='deepcopy', detach_buffers=True) def forward(self, x): return self.model(x) diff --git a/torchopt/diff/implicit/nn/module.py b/torchopt/diff/implicit/nn/module.py index 3ddaf296..4ad48d32 100644 --- a/torchopt/diff/implicit/nn/module.py +++ b/torchopt/diff/implicit/nn/module.py @@ -24,7 +24,7 @@ import torchopt.nn from torchopt import pytree from torchopt.diff.implicit.decorator import custom_root -from torchopt.typing import TensorTree, TupleOfTensors +from torchopt.typing import LinearSolver, TensorTree, TupleOfTensors from torchopt.utils import extract_module_containers @@ -76,12 +76,16 @@ def enable_implicit_gradients( cls: Type['ImplicitMetaGradientModule'], ) -> Type['ImplicitMetaGradientModule']: """Enable implicit gradients for the :func:`solve` function.""" - solve = cls.solve - has_aux = cls.has_aux - if getattr(solve, '__implicit_gradients_enabled__', False): + cls_solve = cls.solve + if getattr(cls_solve, '__implicit_gradients_enabled__', False): raise ValueError('Implicit gradients are already enabled for the solve function.') - @functools.wraps(solve) + cls_has_aux = cls.has_aux + custom_root_kwargs = dict(has_aux=cls_has_aux, solve=cls.linear_solve) + if cls.linear_solve is None: + custom_root_kwargs.pop('solve') + + @functools.wraps(cls_solve) def wrapped( # pylint: disable=too-many-locals self: 'ImplicitMetaGradientModule', *input, **kwargs # pylint: disable=redefined-builtin ) -> Union['ImplicitMetaGradientModule', Tuple['ImplicitMetaGradientModule', Any]]: @@ -141,15 +145,15 @@ def optimality_fn( ): container.update(container_backup) - @custom_root(optimality_fn, argnums=1, has_aux=has_aux) + @custom_root(optimality_fn, argnums=1, **custom_root_kwargs) # type: ignore[arg-type] def solver_fn( flat_params: TupleOfTensors, # pylint: disable=unused-argument flat_meta_params: TupleOfTensors, # pylint: disable=unused-argument *input, # pylint: disable=redefined-builtin **kwargs, ) -> Union[TupleOfTensors, Tuple[TupleOfTensors, Any]]: - output = solve(self, *input, **kwargs) - if has_aux: + output = cls_solve(self, *input, **kwargs) + if cls_has_aux: if not (isinstance(output, tuple) and len(output) == 2): raise RuntimeError( f'Output of method ImplicitMetaGradientModule.solve should be a ' @@ -163,12 +167,12 @@ def solver_fn( ) flat_optimal_params: TupleOfTensors = tuple(pytree.tree_leaves(params_containers)) # type: ignore[arg-type] - if has_aux: + if cls_has_aux: return flat_optimal_params, aux return flat_optimal_params output = solver_fn(flat_params, flat_meta_params, *input, **kwargs) - if has_aux: + if cls_has_aux: _, aux = output return self, aux return self @@ -184,11 +188,15 @@ class ImplicitMetaGradientModule(torchopt.nn.MetaGradientModule): _custom_optimality: bool _custom_objective: bool has_aux: bool + linear_solve: Optional[LinearSolver] - def __init_subclass__(cls, has_aux=False) -> None: + def __init_subclass__( + cls, has_aux: bool = False, linear_solve: Optional[LinearSolver] = None + ) -> None: """Initialize the subclass.""" super().__init_subclass__() cls.has_aux = has_aux + cls.linear_solve = linear_solve optimality = getattr(cls, 'optimality', ImplicitMetaGradientModule.optimality) objective = getattr(cls, 'objective', ImplicitMetaGradientModule.objective) diff --git a/torchopt/typing.py b/torchopt/typing.py index f1dcd1dd..e6e01690 100644 --- a/torchopt/typing.py +++ b/torchopt/typing.py @@ -21,6 +21,7 @@ from optree.typing import PyTree, PyTreeTypeVar from torch import Tensor from torch.futures import Future +from torch.types import Device from torchopt.base import ChainedGradientTransformation, EmptyState, GradientTransformation @@ -50,6 +51,8 @@ 'OptionalTensorOrOptionalTensors', 'OptionalTensorTree', 'Future', + 'LinearSolver', + 'Device', ] T = TypeVar('T') @@ -85,3 +88,6 @@ __all__.extend(['RRef']) else: RRef = None # type: ignore[misc,assignment] # pylint: disable=invalid-name + +# solver(matvec, b) -> solution +LinearSolver: TypeAlias = Callable[[Callable[[TensorTree], TensorTree], TensorTree], TensorTree] diff --git a/torchopt/utils.py b/torchopt/utils.py index 3301f92c..cfe25e32 100644 --- a/torchopt/utils.py +++ b/torchopt/utils.py @@ -35,7 +35,7 @@ import torch.nn as nn from torchopt import pytree -from torchopt.typing import OptState, TensorTree +from torchopt.typing import Device, OptState, TensorTree if TYPE_CHECKING: @@ -106,7 +106,7 @@ def extract_state_dict( target: nn.Module, *, by: CopyMode = 'reference', - device: Optional[Union[int, str, torch.device]] = None, + device: Device = None, with_buffers: bool = True, enable_visual: bool = False, visual_prefix: str = '', @@ -119,7 +119,7 @@ def extract_state_dict( target: 'MetaOptimizer', *, by: CopyMode = 'reference', - device: Optional[Union[int, str, torch.device]] = None, + device: Device = None, with_buffers: bool = True, enable_visual: bool = False, visual_prefix: str = '', @@ -132,7 +132,7 @@ def extract_state_dict( target: Union[nn.Module, 'MetaOptimizer'], *, by: CopyMode = 'reference', - device: Optional[Union[int, str, torch.device]] = None, + device: Device = None, with_buffers: bool = True, detach_buffers: bool = False, enable_visual: bool = False, @@ -360,7 +360,7 @@ def module_clone( *, by: CopyMode = 'reference', detach_buffers: bool = False, - device: Optional[Union[int, str, torch.device]] = None, + device: Device = None, ) -> nn.Module: ... @@ -371,7 +371,7 @@ def module_clone( *, by: CopyMode = 'reference', detach_buffers: bool = False, - device: Optional[Union[int, str, torch.device]] = None, + device: Device = None, ) -> 'MetaOptimizer': ... @@ -382,7 +382,7 @@ def module_clone( *, by: CopyMode = 'reference', detach_buffers: bool = False, - device: Optional[Union[int, str, torch.device]] = None, + device: Device = None, ) -> TensorTree: ... @@ -393,7 +393,7 @@ def module_clone( *, by: CopyMode = 'reference', detach_buffers: bool = False, - device: Optional[Union[int, str, torch.device]] = None, + device: Device = None, ) -> Union[nn.Module, 'MetaOptimizer', TensorTree]: """Clone a module. From 89e7912a519197d5f902322a26041bb1ba10a2cd Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Thu, 3 Nov 2022 21:07:46 +0800 Subject: [PATCH 39/69] fix(examples/implicit): fix iMAML example with functional APIs (#108) --- CHANGELOG.md | 1 + examples/iMAML/imaml-accs-functional.png | Bin 183882 -> 176305 bytes examples/iMAML/imaml-accs.png | Bin 169952 -> 168922 bytes examples/iMAML/imaml_omniglot_functional.py | 94 ++++++++++---------- tests/test_implicit.py | 61 ++++++------- torchopt/diff/implicit/nn/module.py | 84 +++++++++-------- torchopt/optim/meta/adam.py | 6 +- torchopt/optim/meta/adamw.py | 6 +- torchopt/optim/meta/base.py | 21 ++--- torchopt/optim/meta/rmsprop.py | 6 +- torchopt/optim/meta/sgd.py | 6 +- torchopt/utils.py | 7 +- tutorials/5_Implicit_Differentiation.ipynb | 17 ++-- 13 files changed, 156 insertions(+), 153 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 644cd7eb..a01f6751 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fix implicit MAML omniglot few-shot classification example by [@XuehaiPan](https://github.com/XuehaiPan) in [#108](https://github.com/metaopt/torchopt/pull/108). - Align results of distributed examples by [@XuehaiPan](https://github.com/XuehaiPan) in [#95](https://github.com/metaopt/torchopt/pull/95). - Fix `None` in module containers by [@XuehaiPan](https://github.com/XuehaiPan). - Fix backward errors when using inplace `sqrt_` and `add_` by [@Benjamin-eecs](https://github.com/Benjamin-eecs) and [@JieRen98](https://github.com/JieRen98) and [@XuehaiPan](https://github.com/XuehaiPan). diff --git a/examples/iMAML/imaml-accs-functional.png b/examples/iMAML/imaml-accs-functional.png index a23132cfa22de512b09d6c52813f13fc0f603aff..34922bc04c19a8879719e56b5f6768f9fddc4cb5 100644 GIT binary patch literal 176305 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%0AwK*4iPo8ess_3 zf(!xxTO7eGAG!w2YyuAT!NCD<^Ew!w?*e1r$kSRNGfKIl|XJs%civ9*Ux)99y3&apB8(grP>|89f$H+8nMDvVrWM)>e)r}T0& zv||uaCaN3C&_Q^H;A0pTH8k3LUR8qCieCT519>}c+|l+&_$7}U`Jf6a&n6vKm3}-= zJp-&c`4j1`84PQLe3&)h#US0z$A536nc|9u-@7$PK2!pwRS>Fy@BcWsG&~rth5hP} zB843UqW*<%?yb5_4brQ50O<#gzpj6@ay=f58*X4P_-I1&J*r0mv2yT*lA5`o0~F>f zX}+%^tLRx&!z*(rIK zkR2^c_OgVJid5nSXk^wEzY%tDOdQn%E!Jq9aHu%V!d=MTaQ1t)DTF5h4NF;+_TO&z^7i;dn0M;Dur9mZA;dmt}?s zi3#@sS1|MetXZm4mK}EL=nbMtdwA)GbB^0DY9iITns<6*B&szFA6}6*&*Nd^Y=}c{D0y|g%KO%b=YXelv;KRI} z>m#RIoLb_J+=^q4N#dDf1j1=Rsw}g^&-Y$Ze4y(mk{Ca#=UAXROPn~arv@`Z4XfY; zjb)Q_>->4|mUWk0a<>4qf`Te%P-g&s9gRt^18jpX5WT4egW-dLS`2~?;Mi2e&YyMy zUK5~fi7cWvhTB_H7e`zEfAw#sgApyO_JARywVFC@5|lMnb`?%DnnWaW{`pjE9wR@UWu%5L~+X5&@Y0WcM$6758d97hf7rczR=~(s1Dn9lFb#6p{ zxo_`tbpl5 zT{yt((bgNyoa*_U;@OWgyK2EX@)oK#c;f<;Y4Ir9TRXS*os#T`5^aR0;EgDk)a_m4 zQd69`5_nN8eguapfK#~Rl8yPl&XYG^7F%*gcH zw||rQ0J?(Td*-{cQiR`{XlTeZzzwv}ywIeJ(VrjsxZAJQ)cD34KNO}?30<(#=)V1Ju_XOz!`j*z0W2yP zPkT-!MV{K5HtD6S1#B@LXVHET6ky%G*TCpClOo&f)~eGKpxzx`vdM=?rC#;H#A^j5X$t4uZlyN!4bL?L-Yei{u^0d6wzpxhbcf_7t$a4950$(!UZ>33fmSXB~g7&?}{=npC-|G9I%dNngjA~n^nOo%6E3n|P`v75TRBNj_)YIl5>oAuYV zUEjv@N#`RQJ6sxGy|sLvJ-+xzkz8D5Pe74T!8?_(7J(?%3Tw__X$Md`>u5RbPeo(@ zo}g@bHZ$LMXN?+(N(SX~X{($24Q4vH8R`ibfChmG3>6Vfy@vwif^g!4M~_yPg6TRz zJkA}+e=8Cu_m%LQ9~iqInGpy49mSywko+@r@$maEKpptV!9{s|fEP&JSZ<4_}hhZDBg8CssoC={B3(p!n_UZpNgo(^R;>GKjVl2Mi{ zJkKdj-)rDBzUXjyNOsQrqQq67Kefh;5HZn>OKTQrF01vO>mct^mQGXA6eXq}-odjr zs1iJK(43V(!w$UHj$MfbR7b4PIXyf#@p*X6vggqu*MNk=E3z=_f$RS2?A~r`eCra| z+gxhX<>_Wobg2fCg?|xlMI|Ksb>}r$`x^IPI1CMUWi?~RZMc(7>g7M~ecnE;EVoj2 zT^}>ncR)F@*Ifzan>ps@5jY1ykvm;hU^;_V-mciGhX~(6L`O;GGd9KBpw~}}xgcek z&p=^WG4(*I#R9f_x`*j*-ru270z54Y78|jGNdW@+HcogMPzivcs_;Jlh#}WPVD?8Z z54sr~$vGeQ0zOpQ4G50>3u5dxPlXG86jfB@JUu=C=QTc3XKl*=%=|TvuWAURNgIG4qAod^w}9yp)P^3EwDgkZYK}^PxMfO zQ47Wn+1CsD)rFTWqf|-bu^nsC+Bj{K1dpiAeDbY^;ZgiV^hce%r^R+BidHG8d{Ue3A*_U(`4fywFg9_AuWEepxjQ- zM8CNjO-6|oll+yHrRN$yJ2x_GypkZ)IgrVVt`j0Fgu`vM9UK2RWhL&B;~f$>TR;rn z({(45@Nb@`W}GgZxFsaC*=DmX?ZgDk3oRocz62qC*ZiDy=k|P_*N0l3IMU}MC#4kU z26M^Goa=}7qHvG@^Jxk?$0Q~X?X3_Nf;fgTL_s2;Y2F55-VjXs?=m3!9@wD4f{n>` zKivQ2aX3_-sn5a<=7@8&l7$sUYZ(V61UQ%(@srLEy=qa-RZNof1Kp`lD%-gHxOrKA zI%_;7Od-vIG!C*g0J-=PDC#MwZ$-dmW0#66A&{fjVKFUJ-(6R9MiV_qtJyZkA&pVj zrF^W)eZPixyzR6dzNr1gMsjz3PB^6pGm0;vNXpo4zBnO{NNUwb_Ga(&a7VfgyF5hZ zf#FU{_m2UHw_>)r6HRdBSv7|sBOH!la*pI{=`QTAD6#k|$=VE+G^=c7cMU#5!IL_rC98*h^IaN`bh+gv)@(cmi?gb%YE6v~D4~ za-E7lyC?(#Awq{+iNTZMg2cphy}H#Y3q9gG(AMjWyXrtq zp4_7Xs<>Tx#;whdIe*kdfhC~hd&aizwRWrk(Cr^I) z-=##8O>Gf7OayUHc?P^}F?B5-E6bYg2HFkItx-K&F=zl+3<;9*5m25&{f!!;BymcQ zhzjBdBoePKM{yqFLy^ADylwpw6HWvGR=rCkN|E2lGsL%T!~SFG*tUtsEK3B66b7DW z4NeW-BI;YJ|mwrhOSR27x9Zn$OuG6fKILmuCO25moUqP8D3gq zgZB}w`=xo+^H0*CoH~HR$NfPX>p?qUf^o{rjGn@5i8fNhtp%cv=OGT-6iDBrNTLq8 zDXa7?!uPZOL*-|M3vrGb3i ziLctvimC7mK_U&}24qTnH~a^p!V)JCtEc%XnIUfRQ0MZMlCmagsNrB)T`lcK_O=T@5WL(H6`rEH(S;8>mG#Ua^U#CThz%bRT zk*KJ=Uu}W?m9oIL96q}9A!JCcuA#9f44AXY!H8^7>~X0S@$f+V(XywrN=RTwp0Rf( zN64__Ww{w%3=kaDh?>|U^|6u``Yf*Hr*n9k_Fnn{{&W;_2JhzZ(R zQVCL<9SlCgC43C!jT9!HE|Lnbs>_baCXzoiR^sJ)xkwVnyXb5aeSb8@!0{Zr{q3^o zg}s_<$#|+M7zev-`JnyJR?1u#+Sny0r8e5v9o}09y+BxvQ6llA@!Z&b!j&N1nfG@d zHbI{$P#SY5bJn^AZhFALY+1!J4*0#&NlHM|l1vJ)uV5WvjO%4t2YRutHd__cuB9*h4(^pQa+;Cst>LiKtE^SQh|T21gY)8Jlbv2FwvmZ{jK>et*lhk57~&0@ zaXV!_8s%M4a^V3Qn?yNBMr&!R9T7EanVi1!E$}5rLq%LxX!G!U0bXX?8rGj8WSNK@ zB4UZm7Po{3;Y8+F@w*#Qn72e-nAZvSva;~ z*hpBhRW-q$%?7bRX4yf$ReB1^6uJa5Q~@Y(ZPkP+6JukqoAYYNkApY%SGrto4{4X^ zEOFml09;U^2Mz2J6q;QQAcPKhV6#AOD8Mj+fGcK9w|0v*sLUNucxjPRU>vO+kq_;cC0~iF1_oAxA%y8=t zsbg2QZ@tyqO#g*Dy9K~e0*uTZkL3E&`Ua^+A4D6Zg+1*_T@K4JKF_}YtFE=X!S-#d zG>}{@CG1O@NU!*>4s>4Wm12?k zIXndB->zbjgLJ6SMW@Vi*}Dt@Wtlcz2|rb(Ew6DWIyG=M{oxS9LNcFKm4*Q3?#rbn z+tC}xl|~!er$7q&bh!R&E_*Q^b$+&E`gz?&Z<}c29D5As-nn|<*t)9o!0S?(two3^ zwA42ZI@h|J#8hnHl0urC6`2A${=OC5?Lw_SpYSl2e|@paU?Y_CGoFwisFn}R_}6uH z_rTQP=Colt7GrIPPvMEn=EfU#*V`3pEzziifP4361UTj2OPeRez@QS9i2SOj zJ}}mJV)qb2&-fT0WAVsl*^gyER$fm**_P@~G|rU=RIyT~?@E<>hR-3~oSeVo;bD;@ zku90Ce(EWZ0jU1;NAVkRaadU0Y1*+M-1C|2N(ZZ)v2k6()5i@$Lp3$q0p;8u){wOB zdw(Q3lmAXI1M$c4)Z$rMw8Q0+XZ11cqn{-E^)Iomb6T&b(kl(DU*5S#fAW9BGpwM9 z=f$34N0g}{GGk5IhIRhXI+SM`PI0V?p!lOO`5s-ZOFcMzMy&FSmd!e`X=gjnBJralVbB$>X#h`twMLi#zZ;L6NC zjh&mYzA}oVyK>+}*o`Fy%nRc-`k{_$?V8*AQ_NE_^iciaE4w}l(}a!8=Q5Gw_jdpx z1xb_v?KI8m(>NTuuwrtJquZWVSg(rb@N-xMHw2WqmoJveQ2Ir-)k|Qp`VwF5CZERo zx#ohqcqSv*HF%ku9!@7ChJ6tLED*kD&8sJ=BMZ4zD2WKrPjPpuvjF}SzydhCO0h*a zBuWsn>Bi{>z@xq)DHl(zQn!Y~z9iW6)FNKX0(x4S)rp|VR4?$jy% zpQ^(NkfDDB7QCU5?w%e=7>p8-y_b&90Y_P<&OW`5d#eAq76|G;&H5f9Rz!B{r4EIw zH^)nImNLE_< zQWdAi+-We|6@ZIHGG{mgrcITgT1Ad00ab- zEn`x(W<)KA=#Nk{6GN_viHQu)p2^iHW8m7Rrr)zsVj#MEb8E|`MudZ7P}iVs!4<^J zO$&W)zrI2*sWv1fSh)e5WR-OX2wYTs`!=U(PCZXa5-@>NQc@g`kZMxX=`k_c)8$rn zZZa~r0mj}=zKNJx5YjYvC^rG}6^1dm`roJMH(B+AhuG8Ws(_NgZl6SssF?%AKtXU? z1~YR%Uj7sb#x9w3!HzZ*!c$XIv$VHA5k^{r=osWlyRt;GYca~9ibkGQwRKgea)s>M zJEBBaXv^s-$d4tVp+UJd;S!MhgI5fN0J5X#^Gb*WVAFHG|9c0_8~KWbg^S8@)!Dh3 znK1%rxl5fFK+ed&d6Qs$it~bT9*{tmMra3;IP=#2Gz0vdj7)~)G4Qb2vT4HC=QGql z+cg3DdSUY%fHHg(8JBqk7FuLja`L&AXfIQDWwTabL(-qF?=d8$t0RImFt$@~PKiBvUT(`;1HQBCd zhTG)!BH_K?HO5YjfJ-*^7?-m-I1u2c<#ceG8fzb(WxsC+(JSvN+RtwV;{&#@sBsa|!Jw z1_+*@`wfDma3Pa4(+mIRuW*OiJFDhEM!Jl;x?-!Y#cfmj6+S)z2JoE*jm~ZLA66jM z+q;+EaI9Fn83O=vjEEpeY}Fn|?y_Ptf^Ta0{1IVcCq?T26mWe(eAq(6uRKFE8n9@V z++RZ*Q~J~lcPRF(n_3kW6dXay>ew-0BTGG(@T`@!z-gR|s;;h1aLG#DbWjk*_qjFH zr>JNgu4Qa`bF2CmyWVa#-%Nndc_(c&MSf+BPN6Z#{s6O72%pAUg-yM@0m_-CyOmC3 z;(81vLa>mwf%74!zUy$P2U6FIvZ+`3r|?VhaLicVd^KI<0Lh(Bk7jf?3%QTdwy66Z zQ9oqt*iQD^D757yeIPrlAm<@$;bwTHi;KQxZ9X%hE%Gzt4|zqW=HQ{)IV$dB;wPl` zP4#9orKfDkj9Uh846*j4G&2s0HvR1^x&m^UU%%DZ)iqc2Esv>4VdFoWq08tOi?kmT zzph;oRkTCdH$TFl?-L#b}>8tLY$Ib1~rH8`LQ~!6sb;N$$oZ zIuTF;65?X*jQzh~L=;kA2-<+G5)7oNoW@2d<0m34!4DJX=#`($C22_3zVqEkMRnoe`xu2 zWyZFqTLqk6FC^WHIQ|TIq>9Al8deIT!tfeuK8kO;t$W~T>P^Hfke}Vv7NxuT^5jZ4 z+Kxi-wy^ZS#q&n(#|m$4XWmp9i+ll!-a7-zJgjdAVAN^tgr6*U2cf7|N}+7{rqtxY z$9NJ-HrMiGTo3UyCkiozG(Vq{uG1IzudG9ZXK2F8B09zuroDWg4z7;gOeSLH1C#qa zD;18bjo?E6EDz@ddU1kN8L4c?Nka70kykIzcY<5vdmdHo8>_FL)=eK?7P@9VtI*q0 zgpsNp9ody?a+mm?bj{;*lb_GshKTe=pww&3vk?4eZl&+EvxFDr@2XKtt1RT?zYXl? zV(_}8@)W(7hZl}HZWDMm%RFfr7}aiQPglDAt*Yiic(XRsPpjrelM;5`8xqZpg@+|S z{L$lu3zHxL(M2t-92k$YtT;2Yv|)^v&@yMX8TTWqJ1K1HYd%GJ^(x;Pw=yu{yFUG1 z0DowZk0sF@^)ClykpqZX!`ZP0CbL4DgUy*+O29=hb|ND9bu7x8#w$S3NWMSstaU+% z|A&bQjwddUY4<&lYbWXsaOe;SNPqq>9|@d3NWqigDpvme`z;Ki_dnjQOM#hD=r6#X zAG`r@_a9%(yqjizc~nibCMz-NI}giDR$GzowBGn$f{>%zL$M790N{>Ec&b^L0s6AD zxo%hlttgBS?brSFF(#q}K5?=+b{9k%9Gs^C*!Eco$54?AZ^Mhy-0wcGm6b6;?{I{> z&1qW@?uWCzcOc2{Hh^lso7lmSs^!kSOiY^qVV2eV&Ci)R*yG=il3j^uU+N@nF#OvA zdG+nnqUQbNOHQWKb09y|A}>y$5@kO?dC0 zba}fr#qJrMw8)j2)ql-jIcL|(&`iN=`E?J?4id*%Sj5e_Ys{sUL8f3se~4>%Z{&E# zQ-FE~IO#+dL;dfC7PeRtnQiTyCV!)MWoqZ_7K#N*(RxCjcVJRf@piFBv!`x)yMFN- zPNJe{BFCt-+pE)aDaYG8xyx~oU$~;+Bh2M-AdOf7-CvPYv*szBvn1Din^RiQpt}S4 z%`|DW@=Qs>+6~?y)LhfVe!B8ER*%rV@ZqxkWI;tpsMYJ#@X*j0;Wx0V_OWmFs_s{`5LIR9d<#XV;%rBHO+9>v#J(E|X5qL^H7MsU!*F`NZm1rOBZ6 zY*+@>OuF6ye~^xLD%7(7m38$b2_V;ZBXzQLZ|HZ%eR#dk94$JYLb`=D*lHGPLZThc z=K-iVcC%Hln5VEJ!CmXthY3pe&AEJH$jyRckn(=<9N-i|+|4_y6==B0WLzH7FQ6AW zPEp!p*5#W5*4yp`yD^IuziO;0A)w_8efIPsvH+RT(hvzwzQR>=zg{aS9Js$2ws-?k z_Km2=^M9?L|4!+mKM15sYn_bi` z+7@V`xJxPS?q0OGyF+ky_u^2XxI=L(?p~}&LUDHp4#oXGyx({4oyo7vWRl4_&)H|M zwf0&Xc$YvdlF&p{fc5s*mcvmIO{2bPt0{DRWBFl0UBsX||L}ArfD9ye0*oQE(`Ei1`eL)|RMYhobkrl~Wv(j6WAP7b zy>z)D>x4=!C+c7SYE5|g4=r(VJ{b6t`hQeht<*}Oqv?!(srZ4=u1Jzmpg1O*|A6=E z63*m{Bx`R^C=93+C@Tu}QE^5Fjh(F+B7AlJ6W{$gXk9L3%HZngY3s&R%tR9=h_+&_ z{>5l44YFju0BqDe8svlc5_nOKF;<3*2L+CREOaw_lD6pY9c!Q3M2)sPRtnti ztfOf{ia38+dC>IL`3!=xtbp;1hKt0v(KI&w`7{w9e-I^&Xc0_)hSe7OlQqY+1mR@* z3Jhs}yX(Aq1F=Ju@T_!=ysLFBIU>6DW`kTUV@N=#9dT8)3Z_VCwpc(TshUEz!x>!_>B4d{e* zVS^XZuP1(*w)mMqej*E-Ie5padmYkrRa54|RCrT*h4l>i@bAZIg%(4k|}+zW`L;<8_k0PdiCA$zZ$^{)YK zsl2UAAk&f82SMfoIL%=4C`8 z;Towaf;+d%D_3tmG{)3P?oHFJM%a)2K(X(_69tb)L#10sH7A|+6yN;hpOn{HgLPdy zW_daDNGEhFxTy?FA!Lv|8Fi%c&Sm2k9K+zAEI{Or&~^A16^Fz)6e8C?J%1E+wp%Jc z^kK-mUjO2}vV@^%R#X7U-_rPanbcXv#D69}Dz8IL3eSr*@UosUz(fL>`g-hDKu1?# zXH#_b)I=idecv>DBwnA(UDj#GPZW}FH*$11d)moI3~xRS#dn-af$BBzW0k?GG1W|- zvyNQ$*F9w=ghxX8D6t3_Q1>sUmUs(q{M;g0ce%<_MD4xj0@~_EEDWE{Y}c^o8vyUi ze4DIuUL8BMJDLUM27(6E-#iB7+>kuC?>`2>F!wgXSJ?@BnlSojz&g4#90JU|cY9-0 z!lWJ?l;92b{Xui=<8g7DU9&&a_n?hyU@0ZY-V%7WgJ`j{nkCy^Jw29%sz_fIZMP#7 zzk6wk34u5TH5C;Mp}TF&*U+!mP|w$_f!Fw8R#w(m<)1$gRcrcme|5Vaf~KUZy2U2d zQX1o=J3c;s3*=E|$Kx{U0CAb%I@5f|5z5pS0U@uyK6gfdh`{u>V6r11fAr5IO(i;4 z6sE&njsfI78^De8=W8M(8Jvb9(aAB@21;=c#OT$ zg4!9!2{gmxn9v_1B+19@VcJQ6c|V`<7eo=K>{CJ^I|rI!kSaaQ0q3f~tP7@!4NTz( zUDrNCrXV??C7>AzgD+UVJD|kA4d|aW@sPGqD?4U>VS_X_>)Tvw+KhMzu3=V*qP?&~ zW(-LqDy2Td)3R}Y1Y|?gMp)X<8e<9jvJ$7GexwJ;d859<($(|Bc`@BVeIk|(i$!lg zm1VyGYHO01#E-wnT`A(9LmR7)6_40aEr^pM%d3nE!)35PtcQz4R3rTcK!n@{hypkYxD_YIb_m?=aIQ)=-8$R)%cM|9pe1AZBHm!GCicPk)@x02gbAcHt zwg-zK!Zxd00|@&+LmOd=q4Xmr{6A8_)J$K69M^5AU?tAGT`LBvrAgVXb7gU1k&pr_I8)Z(A$`nK6Eiz@EN z(Ec1S3Z25yyjvCVDZIaH5=#ww-g+VA01Q96>fy5+570#{zJuv)GOg6$GJ~r9kA83> zaKm>VduY$KNOR12#I0QfVZ_aN5A$@W$^&Ut(HAeTS+W4`^3!ms$@c+(3><-2cKk)I z01mD;1DJ4Gkbts93g8xdRYK=fyciSd*S>yGD>x~*nnvipVQVPL*pyW*W?uLq>4ADP z!>Kd0P@tdENAG9(NR&fd>Xs)Uj0en|c0T(UsWHzzYk)$1B(>ouh^HBq#*ZAuU6x>b zA`>NFNs77dXgE=}B?x(EDJo%Ixsr-Q?~iAhG;TJDId7oqd~{0XN+oX{-C0V z;l;EB(dmAB0!%$~*1m_hy!9AZMyCam>HNpfp~sJBC8LI<39pFCm@Uq}@%FpS!Ty(ylja zo-7?%&^Dt-A)B&I-pu1HL$u_TeeyeUD(j@Bc{_UTx7XJ1IN446Q3?IJ8NxELC_C+x z_GN=&&GiSmDKHh6 zt@_MucmZ$0!Y~oWtS56<;e7s-rM-q%}_IL&%LX{i*_z$@S zWcs!mk5*`}g9Cd=F@9|8#1ti^Ip__dcJBthpNi*OQ#gIM2;>KGGd!U$;_QgNM?tE< zXZZV2%_>V=*y1KA%W4+F2UEU}$8XfKk8X1x=21goVfr81h*54LEsH4$4Yh(K-n3zt za>njanG{d=eM4y5!U6ckQznhGt<*ioy)J*(TS_UH!^T|(%u#&blhm!aDpi!AD4xU! z&EIkzwaB-PZ*CTKmK>2TFNo?GwldcqL3cOJ-A~8Uxq==iM8Nr*^Y8T3caNVlS$(_@ zi1=2!@^Nr*NNV~$03>Q7k*jxiY2eRhMfDdg`=&xz26#@xZ0@4WPLmu7I?lM9G`Dz z((@;cMc##6E>b|U30^Gue#p$;{tUkGWqYfw+{50|EbM3kOB!(IdY9$vPX6s7PM4lY zVW95ziIljao=ZR=={GojV#~BbK!fg3W^b=mUn2zLk2FUiY?6M9+Q4g>K_=AQHIaZTuRl@6tE~jUUVM zXz7tB4Oo+toUBk`Q6E}B)WWjX?)(HBbzFZxt z-8sZ(8w{eTIz5iK5gt?nc3h648Xx8N&iRD}f=8f#TD(us5g&IdxHkV?&D>BD6eygw z2yiq-#0xt9`P<2x&Ny#>shl79A&7)K|K1O}jX}cK8oK2|`?!n!rRg1SRV{7C#8$sB zZ(MB{@Le9H`aQV@-LRStw%q!88kww>dbp9cy(w(UVXL0~CJT+Fw(mzqk)NNtRMod3 zokKWhhYxcbRX+DHFwF8p=Ox1Y%BzEWRHmM1zsZH1E;J5Y=v9p@HtgrBQ(c8{7?;O+ z{T+i5dY0WMKN^6lSD1yon;tLVsd0cm;Hm8f_KJW{U-awCV`)7?4YBW5566{H$(FWU zs$R0clQWXkUZUs2s()X}<@s&8`6Kv(eaH0tasiKoME5tY!`in9Me%B~t(sH8Na~@& z9q_V;FFI+9??>aBKt*BS!E+0ay!m(hRa;b)jy;x&Fy!E%y?FuluVUw|T$|YGy6C{h zKu62c`W^Q4sdyAIYVO4tzQTub{u5yJO0CtA`#|}m6PWH}%Q(2Jy3Ji>@;xI;o6};Z zAdjZyW*$!H9Ac%K%ib2iBQp(mmA+>)1JW4-)t-zYz0Vc+cJ`0_UqR?joIQhwyK!qh zp=`F`@a;%J8=C*iJ0Xw5(!#G#TH}p=&Y!~2Ubb6I52wDEPif8v-Ns&gIA}cjM{0w4 zg6*8MMQ?bAOhrvS+TDHAd0O;*G}m>_iG@56l)J^#aglv$*5&7}w1BsMaras!Ih|}K z9Nwd%a`|BDHNbQ|ZkuIiFQpf8_P zd*#16F}KbG^m__8K~u>f1xt;)zgw7YVM+U*IBQD{FjU#>UvPcwT z6sNGpT4bHdqC4x(&Fnko_i-&`JNgI(u|bl4;6q_py0Qi}>4#mg(P9}lnzE7flvJgg zRgMy|f$tpGNZ325d%lW9(&Hj3v;J88>7XGlx&UhrUgPu_RHYZ2k%9fkB?f{0x`?jp z<}ZUmcg2v#QOIo5%jK{ywpVr6=~`~aZ*{^&ISc>ty-IZy4=!Zacwn`SpFuJ_MpXL{IPT`A}NUtC(oB&Sa1#h(26a7Q zXF>HN^5Br*@r7w?eY<$2hiTd7o|f)gGtnMB^6(cw|3&ww{&$V2NNWN-$I{b5=oC32 zQl(0H{5iCKkifcSNffT0p>YeNd-D5#H=->5=xr|e}XGwrPT1DZ`Qn6lc(%-ZgckzkzCmy zz(8c5HJprQszh*9;*1;|N*}{703Q8ynGeS+_FUI0a`1NVTE zrFYj`{VrDsZAI@d3o@ipEK=Fi;w&afuTx$mlPb#G^nmhgNBeJ#g9K&}=L8vgGD-pA zh_T$rF-4i?J=cNIaS8M13w~1+XXoL{Emt*4$OEP6DqB<5vDJlIq7p!LTk3O{)Du5| z_m|P?5fN`l4SVRDT{k6&8+SbnvIYi1jK}A!6GleIY~7FPA+cbojKSi?xvDIFj;2lb z;rOh|b>N#a4i5Lg+PQD5Bp+{gcy~u1C-cdJ{O63H%J$9b=(ecos zl$vS7bgFE{E^HGFoGFecOtcWc0wJqp$Kh|jj6J2T^2%6CHwc16*|Iw1e6iBbB`!%e zrxF!2pbTa#2)7eKzo}HM|IxeIY+fW*2YZ8K*^>24BB?dAPW862i-;ySqt-&g{Z#|$ zC8=MW$BdXq90zVXKb_f}5%Cjyz9?e}7*9?1AzLHjRM;)sOH`_Ryv3Dh(HtiD4Up%r zWO>Jddd*)yFc4oC-Q2Omn3kQ52y=OPxt^5!NO8rNsS4KoRX;0@pV2`v-7b)Q#1kJcrAS%QJjMxV8 z;esO~3TgGgRL=9WUplQaJfDet8Y9q=zfPVkzZZ4w`!@5b3R&xvk4*a}T{Z8p8|U-K z0F)6u_4-hJSy9a(1B7um8I^b(tT6krF&w$mn}@hVOsEy%&t;Q8o(yFSv*{z3mFi)d zn?ab-x5HP2<#VRSLbX5s9O^8?Ni@gP!L1a)J$;w)(aJC<=wiK~M#!bhGBJYu7iW($y~9=}+YqIbbqxvS=Fhjb(@vg>hpvY>W|J4k z-;UZ1u?!M$+2hM#1q~LFuC9MrvGR>;{K=oBj;Dj^PzR~*&KviNIgl>llVY!O3Eu)2$!$-7SJ(IdINwQ?-9%IycR69y; zvfQ9BpU;_$8iX+!QJ4$Crc7wjID~z%jLU?XL0vl54p|I^H_JTVhN6%!dZ&gqMl!l< z{syO-H!x2W`ZduO*l4lRcIgjI^lDJX2t)cA99*)4`H*|&dq#cP54>UZ#-)BUB@GLUJ0 zyMY#<)nphiPJVkH9}rVr&2-?VRt|;_f;nl~Lfu^}!~y6f<}RQj8v&qE%iV6K6Ht$h zJw5R@9PuK>;iTe-deQvP;Fkklp44+6Zij^90G$C}mmkw*ZO8I$93O5~*u~X3c%uK- z`j;bjuvUV+Y(1%^dPl_vU{itAVkGY_IKmFK;Y}iO+)4(X%nNx zH|>+xlQ}~gO4>Xe6+gM)>47jWI~zMagjhIz*>P(R4il@T@vlMlZnogjD8@PDdgNuT zVx#-z;ZbB2uIoFD{IbwD_sFi)Y>@pX587;aMLZv?ndgPzF@}=alNK=oS#>G6&(k|& zIA(Z0qSGP8ynQFjpvH1EO%#J1yKHH?LLYxhtBEKPO>F3#z4g!>njAjHZB?kNg8ePK zOOam}NyhnOgN_jgh~In-Rm;Je#e3G}-m7tfxJdmJwl3ymf25A`0aCVgR#e5^QvZ!P zSv=t2{XI2!x>G}~#-sZCLH3H)36ySWz@}`ja9^MePGxFvBv7qF#Dj79Sgf;2@7dI@ zj}kJ+GB`MR)(ZBUI1~K*`Sa~;b5|J9x%}{MZPi0vyB*~I)7`xlT3ki zJD6lr@u42cTV*MNBA-@osg_71KUMRDqRy+;7(dA!8_Mz9{97UeCxMIf&(V#2Yq*sd z;wEDLU7hWB>Hq3fd_}GzVoB+xf0D)~y-^NgqE{QJQd8jST#H2xQ26dlM;9HU&=#xp z2_h3#vFMce&2pMg@hDCT#3&?#bHacntuf@j_>D|3jqzEM-AfjsEqgF;;K!3s$*Sj; z+?)G9wcET;7jCr4)DwzU*+_rA($mMQ^#_FaeHr*dz7L)(g45PeGfZtL%L{O1%ZL`A zCU)9$z`qW;`YDgbnSpWu!cxgn&1Wd83` z)?1JL4W8kxtc6=KM!5;raM45&QHJpH>ywYg8{KZR-X>MC`)7zMcM64H5Aeohl?Djz zplQ&~rSiA2&JllE8_-3+`gR};ftkjD8qf8uaOpJh4j^K_RtE8a0O40bqrg41P`aeC z-uKO$H)kgv-Gl+x76IRkSS+pYJXYLrcXu_MvybMRGkYIaZ-kaT*8G4xUL$S68pQ6k z_~x#ws@p>0`_D(qt@WRlcKgCmOtVTJTdUwWqmi`OZ+s8~6slZDw|CkEsBo|HMuatu z8&0i|=YXteL5@NgGl@?|>N9e(w)@zf>{xT&#bi^okPoY3Dow=I%9|PZAzC^uQ{OfA zJM@~6?I?zkU86wn`urJbTw6!?1y*>Kkv?-~U^YSMDs@^i5m8Laa2mf-WjLuGw#?gE zvO8?pv!u{Y9MS7+n;}NUUS($MN=$i8xs?0%l8kh(=fSNY4dwh9{O+Dx+Ws^`#7h#! zMaq?_SxQ7~DYEr!jG*FzC2y))1-J5*?#;MwV3^MNnH+{@OoRGU)i|}zpKCYe*u_>g zcH`+W6`2elL`me!s2$s*%dK3)ZsJMTE`hGci$aU@u~7eI$$H3pT#jTO;aqH}L+dYG z+$xl<&%#qiL`Wh5I8Xkf{X>&xZQ zSn8(rpN$l13As7OI8&s62-g-E_fN~fhJHg&U_9!PUdrmfUOH?_9+t`9>mXL1E`A|4;|=GS)?%<8%G z-+w`DTMrCtR|>$8@HOGpZKj6KLe*}6Z(dX@zwxF=hoaZ?EE5QBV%HXOTSC1H-kKt| zh2WfoY9Yw1!)CXBsm`-(6XeMWGN^SS6ud!UWHfo2PpD(`G4q<7yc+1Y!&_^?w&1o$ z)FeMz!r6l~vBY180YPkwaQ(#vN+J(^M2on)Fz{FRDi(^#jE~M1v_323HJF#vIxWpY zg7XJ-caj5d+bmIa9*$g$QG{~Q=JZ_T>$yXC#qvKIoJVPL_^|7>Xf+ORn~zb|Y2lvh zFma?0+%3jPkwd@?MXY$|){7~CZ*&RH6yE+BKFJpq)SdJJjyFpUbBb{L+BJy`d5v}8 zA9b-Mo7$m*aAKTE+h$FHMXn_9#_?7~XU=@_at4x$N(IkHdgQtqJ|2h^m)~>>&rB77 zSv~^!jm5FH%U?QJ(DYzVb@nQKI|JqKV>rLk{+Q~U?GP0!cbQ#WvjfNVovmo^ycqJ5 zchrP903Ina7LRVXdw&QQ5L*ecXGoF~&=m=gejw1mLLAx~8L&u6IR}X(y$+;I4Afa( zM7j+i1@`snE0?l`R?$FUjo30KiN45uz;Rcq67c|uk39(nD<`lk=`- zOi1y=U)FglPtQcT(gOewEq3GyCJPAWkM-1pc*JNMOwgA8La1L}zU^^3yM-dg%XUT!iR}(w>bo*?h&c-Iwq9_|fM zsi~kj6DS}q=kz^)DVoUn2bMgz0-hVg!>JI-1l%f^xjsL;!mFB(z%fzj-O$|34WKZ2 z(!0+WrWQ^&lU`;h$bAN|FMCm+I-F%owho0Hu%V$cw?5r|c%t!v{LCjqgdR5Fx?3wqKhuyQomz%G z=Mq`TsE!LELJZTcL!dEmF|KI^``!%T`|h73mESzite9#^?~u`pc!>0o8nlz(qDhwi zD6;yB;_=xaWU$}?;%X8m!hQGgcJRfUWXUHaO>4r4DIFdR`w&k4+ROAf^#}`j5-4VA zGX=Z|xB9~~5owM1`D~7{3Ehl3jj7UbXR7B>EsP4YqxbW7ovYkE7KqYs61MJ~>^={}EK%TKCOdDr*o5ua58l)ZUSGG* zgg8)H*P#8?GT-U2410h1$Av0oWQ+7fcqi@2$=vi^S&DFfDU71e=}!qZ&C<5rI56dZ z|M|ksdl(}R!;b;ie`2A?(-r|qC$wHs#YxPE+(6$sE<^!u%g39N#FrSiHtRdG(S@}unt9YXY31gqJ;u8!`d(1eZ z13cF$;>K(3IIbwS@PxeH_nS(DdCeVRP3_E)A75-8NhY(94(OeVxY_5S^PujFyaQfS zUp~VGni+lsb{BxY1%da_wGC)6j!^0?nQ7pHP#4ucsAP5p6*FX}UDO5l1i%2xG@ z^b8N6Vj|FL?;3BxCN`a15#~5Frk7f-4PY9p#c_kD$$n+=NZt{4{S|zRN2_rS8e~KC zee9iz@RT?rjpJ!Mxlo@L`TSSL4CQqh-+3W)fEuJjN2A29Sg^;j&K7_bYgeqSH$i~% zWlVYDzdX)sBM8D7G$wbY2md%X9q4;v@7CI{OvYX>t5<%U5j1`0gZTJw+WD@rRU9?I z{|4!C>Ub%_>{{xSHxjpab7u{JqaQc)ht5bH7RszB(}r=*!i9y3tqi?Ew6Oqo%kz9J zzchJL!`x%t8+i`?0jD2Mkxv^ ziqUg_jWW@sERt>yeH2w{rjSrf34YSdR*+a|!;%Pg#sCxma==B#_|BY+DRrzm3k-wB zzZBgm;ArsOE}=dPSZg7MPcWH_D8z>r`6xG$u~S=-@OQ>23hLGTF^c`dj`a8(AFmS6 zSmq1c^QXlsJO=TgX6>|tCFI55zDOy3Y~;3EQI70LKV25jn6pCOrUs3AVkK+*y(egi;i}-b)Z*+>jkw|q^DqJ{pp)mVFshFdZwgd-!NpjBd%i6hLa!iGG00L_|12yR z$K2`UqpwPq9Oe^p)IhhFD=gdwle2a9P@`q|Oo$QI7&K>m30C_PWpHNrP{z@+$!0Lx7X_B9(4i!qw;=w zSK(%B)-`@AXB4vQ)6-AxuG%zQ+2GpyCyxNnP#M!8>g+zCkpv1v@J4MRG}~n9oo009 zP;}&nOefG3*K3(L>iKRy>dXkNMs}wtK(-)gW7SU2L>E;X!0?x^mC~G1Vp6JfUOLoT zqO3Ksggd$->7j5H-zOp6CLvuaW>x#h-*rTU&!LgA)S*6K9j=pVhgS{NYaKx)8wy8j zkKFiKoR2IKOXuoF11jZP*ztfO(!zrVl}B4CmxwY%BquCQIqO+-UQ103lxp4h8_7 zbvvK?LjxZWxpmr8Yu3cpem$$|Llo!OcH$u|WPE;UoD$%qEWko#W{&zN%G1 z61IS&NrJQn%%%H^WGdzO4Zljl%19J+T2*e>9PyPv^0}_*2RI$MSj=&9NY(c|#jHpZ z*7Pq@`vl~6?Uj&YpY|c@?9}tVNP zC?l^1N!^%?Z8y69AYEp-tVOzTGf#0c?i+s^DGtn?7}ff^LqrJ<+U)$S?JQ50O*mB> zQ@CV;Jrd;^kxQIjLk?EY(vjPO+SdIEE0vBT46s-nq@s2N*CKZ8B?dWfQC0X{jMk5^ z0Ub0lYsQFGs2^PY;UFTu0u4kWG3z4ZK1TwSleX5=mhHU!t zvk}Vi?o8UcPM&1QIL4F#S2_aS%MrxvAK}~L^BmdP{jTTj^wJZXm(wzr3F1T!e{Q7gErgWEE2foUWq#*SeW*f7Ji~(*mg)MbmzKGLN9OzNo z2LRkidBUdi(n$A}ydCVd>acj>^WBrMJLDDQ812iJ3^G7L>@l@Sak{uJP$!|)DJ0`& z%DsOG2aO`|$$t)4|AFNCHg2h~Bz45W8qOMwO<#+VTuKq?f{0&&(^y3@(~7WfFwys> zO}n&HXsj(9Qr)j`fm=b9>#8saZz?O7A|b|+R6-8XRSz;);JI;7JgC@=8&}7Kx}MV< z4ekW~&Llv&s0$tfi#w^(R?~u^t9tlvr;$H!+8InzLI@+iR#>6+dS|~$>_I=}UlBbV zZ?QpwYc}yXMPMB#APMR}^tf4<7>v~`FM2WhZR4$1`FnB!Au##v3?_=L-5;wB^cW;p z!E;zbL_STGy+xO9bQkUSS-g=ONfNTx&-Eo_JhuW`9}%($S0m123wi3TuvGgAl|GKg zV@}KpbBi<&RCp!Ce$<@`!GMMQ5 zqL+=Nr>NDuO>{y?bb6mvrCGCwh&~xN!Is~(JgHvyjrlnT7!qD6)^OlaIV}9I?qWcJ zqsEbFZz3CheN`kQ5=7rK{&B}uE`gQKlJfcdWWDvPcDmL8;L)LN$9q(xijQ*O;6TZGQAN3DVNPmxwzU=WK}9Qyzbd^YFwxr8!SKeTkOWV6L> z4|zdsDoaCYn9fZHK`?m#u0LA!oGoa=n*Xo5JnuLuT3ZN7*0j}o=U$TJ-;5|e_Maat zv31+wq3>H_G5oD0ln;}143n9W1g<|wu4D5QH~lLw5*~8$9Jj>ndP!^r>0sZG82%2g zS%S$c6%uY=CTgrnHQT684Vo|#qCygw^|*EP9$Ciwvv&a%_CY=ziu;dYi^&a5^EkQx z;YFev@|iO1j!Uk3EwrOVNCnK$N74%sRYEK15ykMl4DaMIbzYmy6F!3FK`k@F175&} z7_Irx>~((Xuo}7ca2=f{;NMiLXUMQqlNxb-Qsm{hKike66(+#92ZHc&7v6cZ;gt{T zGAA4r$p2 zu_VJ!2v)&_{w7*Oe$y#KM7PLjc076XAW7qLWhBXqIu90kJ7!)zS5+c|5Q>fB!9JJW z_lq{Nc!VseWOR#@z}Yer-x(2+B*6x+7i4Z&Y*+48)q^TSt%j8%GwSsB>&iO{^A6%t z7a01vBJ>RN9mSAEyL!dE8s8jO#wj{$O?vCoUInwfJrv}m4yAVKJu^>&pGs<{b3b_% zD(E2ULxD14{h|S-ZCbenmI|ZnYI)%T!TVn7l%IYdq?gw@$y3bDwpwDh~=r4 z&U?l6JLvPq#IFP#bX0wSnHfi^5Dj8FCkiHk?RHuqd%l~jH*(sB!!R_zdznRfINQEu zqbj7oNsZ8C@gw#3nq6qY{Ol=F?S*qfN&n9f+JaHOj*NJjO*nKGNp39Ud5`cj%jL#3 zY>S1RCG=dr5O0kqs-Cckr$7N!hY}*YXXK&e93gUZ&{dqXB+C|GbRxvyb~DqtSK+V{ z=^*6#9xUY6KT$DHcD{HV7&(jU1Y;&OrsQ zFS?jFX{)OUqgu<5LOh`(zq9iVox$3ac*O6gw!9Dp#n-v{PhuTk^<7W~8b{cudYF-l zvDK(|lK>h*JV)O}cgLTM_yXKzPhVFT>>w;0QZjKc^mzg30UB)keY)07x$Oo4YGEs^ zjOT9r&3Di0^4j>+O;KoRzMf~y&*1)!M+Ku38tI@vyy^D@ zkxM>3{~=nN5y`6<$7w!3>IEip<8urKZy3r4)WxkcmfM3dUS$&JPpKd$Z`QDUE>eTe zM$DJ99$KPwc>*R`jFvi|*-wL97oc@Yv%Evv@pP@03nF)GbFWc0?_w$z-+wf-0QJ5O zuo$2$bq?@#mF}l8ZhMJAQb$)mn2-N-T%6B-#A(KV`Jg8#iUjx8l6X^#3Qa=!BYWv_ z!vp2x1Y`TzdYs$sJp7f$ff$qKgn@%D%}xz-^~d8J+e1!)#OcFGqn1B7K!NaZ57ET( zL_kGV?6m96?yuDUp9_Ot)>|_4w2`bBuD3|8IN6OA=%8-*CN&y!^-}iswQ()CBJD zANy6s6WqpfU5R4)B^)jHiE`y;CO9L&ATm#?ho9-7=AKY~*Qq*>EQOYA6VoXTA|e5w zYbn2RfbIE3G^z`3<+=9eoj{Z8!zU*ZGwZr6VmpJKj(1rTQfJi zJerzD8Ux4Y{@1)}jRD|KnHy2)XWS%S3dWVW#^@!9V_JCjS0GD^_>>l5ymC9zHkWhP z5z5`{VUpj80*IL?cf2*v1A@Ifm9?r|EOE{L|880tO47bRvY{u#wlI3XtP4`IPM;jYdFc^WwxH=K=FVt zsvwcWuE(c4vz*PG7*YFKJ6R^vK2C?9?4YC;gpKjz+nLb^e&o%sht3$Ht3YR$JFHnY zGbTo?2|)1hiAIY^Llg7c90zQWV>*cZN9c%Nkms8IIAYG?T{z~PoPx&t(`NKs%QEFr z27vLJf8UGTfPASD#@F>73p$b^Ns?icWImOmMi-SS=zum(!Lo>HR4QV)fF?QA;jHKW zYmNZD2Bv2Cvwd&!u5V9VV%zlSIvG$Xc0F+Lq1UOOD*JQ-%YWj?k0tnW{`{r5onW^y zh|Z|aIkFQQ8WDeT(SZB}h+P2aFBQq!jX(=OcLt2lnFs~tEm=jWU^RfjCjALhJg#$^ z=UorE!Q8tsvJp{5aZFh&JW=eKlCKR#q%?n92!{V@)5>~I7R=x=_g$LAFk6s;KzCNu zMXkPhu7D6L5^rDK4&Gy&p%#Z!LU@H04@BPSLclS4VY`E`f+5}lKC(=YHy)E}X&s$Mz}p*t(v<`k zHMF)%UwCSa!7}5$NjjYRZr-Gp;-T&Nf?-VI3bP5-DxULSWF$UJ@a7Wpm=Rq{?{y9t z6LH*n>j<7fR+Q$h%`Na) z$&87ynGJj(f^kmZSq06VMTQ?7zt=?^V~3yspDH?^-!~U<_g*;b9I2G+IOXae2*Rc+ zz<)(sv!X$@?ZTF{bs?c}qCq6r$d(9mNq?{-(r+sB79;s)^jN2N2W$nRW4<8xk?V@E z>GqUKY_)n+VZIq}}9KaWhgmZj_< zU#mlhcVEZ$igCqCc56Ivk{zx1w4u$AG~2iGF18Z!m)K7;V!Ll5H_l!w&z4|3FI=4)&a|jKxhVE+% z&68WpDRSU?PWD|9Yo&b_68(IqXbOn+-AO4`W;*CSsBN{P(pX>W&z z@3|UQxLFyk^xz=BUAI~bgv@?W4+yxAMDl&OvqHeA#n!z=wz+kSlsI!ivE}}T9(;}$ z>|}T4ZGaWsbVeE6$>k$>YV2~gjT{A_Ez1A5abE58$?Qbh6O;xkYp_|42TJF0e;3V_ zH#;8^<~3*%xt}y%ZwG{oTigz{RehRRh=xA)$cBEi8RK^8BF##VciUe|oYu~<58Gcn zz5iaajeXRnfb0C1Wux(iZ@=TgH}-0|*)XkGB`?$Josr7H29{m|p9X8k-kB08i5^=Js== zR=aY&XpUb!X5(5ky6iIaMYO2ZW)-({#a44JI_$;}`sId*ohi6fy9^Z7->4KFB8d-$jWnET z+H5QZYd3L&Gh#sJy{DaW5<*mUh?{;MoJn#PDSuzFSeQUkqPo=n@^CqW*~Xb42&h5{ zQlI}?{q<_QMa78#4NoAtuVZ?}TqD@+aUXt4PjWJ2l5t-tZ^a?ppin|e*kdePy+sVa*UKhC zaLDx+cqH_oG_-7isOteQ*(IrHaTY!Dv1SwBDJ}-LtH5d2(pADE0s47Sh{>C_MWUlD zIDHm@xl>NhH?JFzSEyW>O=o_A5P=7EL8C>H^O7d&MlK1#7c-}PI)~0g%T(v8 zy^mD87toAs$+^ld?@mjU?!?Y6y*~!rg$7`3EI>9{=!oR{KY(9eiI}>v+B66@k=X1r zd)>>LYLeTXC~!S}++*K6lokMT;=gC}9;%@U>!y#;->twrH19>>$_miMz?R$C$;*<#E%~ z88sTwX3x1j0Z_gp(c9eLA@HTkqLsk?jS%z}Uw)665<(f&Kd~C2{js=EH*xA)ak{D_|%@v-}Zm#dceP(UNf)AX@FJhL9^If!289j1Quk zF(>r)9+UNbw!pV5Q>kC)(@x@`%DEKF@7Hg?nt3Uk3$5{sP>k8+`yYd7A^jSR%d&(M zi;eGLc(AewEHfpnm1{&SnjPR1pPv^eEf_F9dZBuagoLg7GhANJb&D#0jF6ga;)%b$ zTfi6*GNfAg!rHWjNnd(!)yr<`RP4qY45GJuS%> z(lkj_sZr|EJ1R5#cYk~+OW&y@c^RXJEHFr+fU{yZ%0C?6=EuP~l4tZfC9%G#G!mcQ z|CE$!XV|X*oZsBmlGdCi8UtoOvN`Q3QO79&{yM)OEU6BmNi3R)ke^YRlXKES@zVYT z%B$JcJJC@i8Im;gaf%ua*Wd^1e2A9u!%%2E+Tlg@kMw9b|D2sl=>9Cu?zKDHo&3=& zM=Px{#H>27A8XvMaZ9Oi>pjIPK@cj;&|cCoJKcmv9IRw)e)71gg7ate8cW$o`hQuU zXn$oW?|X08Te+Z3SA=WRA;A3Tdj(_v&iJ zIZ45W7CF(AouA1HB)x;d_K$oEcA6e1Z!GPU)H+$rlX~&=K#a-FTzU+(N!|MXzWEcr z{nVHNZoRg6%5L=a8C`1^i!S;6-ltvN8YG3WJqRa%She;sD8-XTMWaGd(e{hGADVCf z6Lh8X!|E!N`SgMNHx^{J-kg~?? z8Ye`xW9!f5U@@_@cQn`_+F~5P6ex|Uatfme z3Ph8`+JPyyKTUiRagH>r@JBTHPZ(%u@XoC>WamUo6^%4TyI4Gc(^Ks&{_)b2Ppy2!Q0{}6n;L+gU9RJ9v%bu83yCw}l|O-HSb4iC70 zeiSi9a;5*Ekk}Kn$J5_hM<+BqgsJ8GNVZGrg@Y0=5Hf1WgFMlzBcqVW!dmybCA_ev z;QN&jn#Luq-+0$EEPuhlhW4sVVGlV$k-Qy2k=a{8bZ7HstO}J}{Q5>bLW$&f291rX zQwBNkEQ`dy8c#ZgfKvdL;SzPayOieLV4(!PCucyXEvE2V-NBWTKosx-jsPuzGYYlV z*-tPX;1HDVvs7sJ@i<0m_^IR~kg>96j1B<>`h;KGZo{sJl8Ny90lsF;_w%1thjv zxeU_HTO~3FPoJ#tVPCD3-&h5zJCVWDWuY3*wx2ML)KIsCzl_C{{GwNZ0ph?v z)99_USbtQ{!;NNek4(y{#EW|ii-xA?ee4P?p^Gyu%wSf7U^Ng{wdu>g(<}|v(mA#M zluXZYwEBaYCQfo%S|HrLJCv}=5*KuAk`*lQ_G>I0Vym1d=W<{69wR2mC6b|@*OH3) ziw4#ikyLKb$;V#&f5;zgX)XZ%=1=z zT>*11QlN)f{nd^u?B&%p5ef1L_;|SF2P208C0LVR=hbU2BNpc2u<#~)=qEWUaQ)nB zMiUdE`HNT(L}fql=PJ)YRc9_JZQNufoi&1aIeaLNRP?fER0)}WE&QsKF8cp4_0~~Q zhua%33=PuV-5}i|EunOGcY|~|Qqm=z0)li)r*sb8B{hI__x<`i=iGbOV)6gXys_VB zKhI~=FoX-32W&GSyEqj``W))@Z=%8e5AH@^9%lP!^%!`v?9|(JyxA zQXQb2wNCn$s17^t_&w3%KRujk-<{FOB4nD;BV9=u-t+5p(4CV7-TgYg8+#QG!{x|k z+pny~I<71=PMgt_&vDGWH{vDyf2G&21ScOSBwX+)73cz)k4JO9D4q#ufCbZr%p3&n z1B+RbX>%D7wpl2-Eb*Q~$IdgDj_t0?!PQ3XvkSf^D};1KUS`Hs+F#roiN5$Yrt!0)h;r(PBzw^%H#d5w$ByMv z?SQoDkD8Yr*6@TOJht7d8+dyA_XM;>?yT^BWjzywKodgyX@bH1LlzlOcLphN((V30 z)NL-80WXB(EHmo6eE8XaYAhDRAtpX`^?3d%Yxx|=hiN^JpL7uYY}#Qc#kO(q!XG4a(@=#4B;Z@V#B94Q=~Kr@2%dj z=t~$nG^arx2+EPmH&Bku&kuonC5tE!Y^5{spr@Sh>2|DQD=}4 zech%ka4tI*H$==KMxvT(oV4<$xZZW)9RX#h7kr45vF8K5JSgIy{UtT4=@8ova2UD~ zL+`)*`KgiY7l;>;TQvm=FyKzs)kv*?@b0!)|fPAZhnuao;u8`ZciQcF=? zTLdSfHcH?LcZ|#td=$^Z0mw-0Mrm)0BHp5!)T0vdFE-cX0WaWT6PES50n0F2|7CK$ z6<@?ZK$w- zif8f%dJ`towL87+yCWIA!g}+q(uqJ)g zNQNQ#kY5fAy=o0-XN81NjOXc5sV4Gtwy=KYSmlq}xZhGcoD?aOC~1ygt@(iqm}t!c zghKM^Ol!v5E_}i7zxQ}Bej=KV_1p5LqdAtBS>|dnQ(7A}=htAEiS|8WX%RP2uNK+< zI;cPs04Em5wjyis-$Kug;bZP!LMAz`ueaeb zeX(k5BGhQi$gUiVHHr73jnCG|fNj=*1!IyfgS{LFXVT2U8wNJgo7dzQPGu&xGoqhG zprjZ7$}g>2682St$|*@L#bx&8eN=9o&^Mku#08acBbW4Zn-(NW$@`viEz9DOgK_Hx z9f$T&Tef(bqsIAMs8@1pS?+azpaCB%S~~r|Wh9vSn?xeR;l|D}Cf{i;WL6hIReJBjI^H-XY?qtAA*HCQVuK`?>&3Yas zoeA%gZFda5N!TP7c4n5qSd$7tw6#Wx`Kmmi09636ymuw#;PsA=o! zqz)wz9W-lT{LF3?M3yHIhglx>e)9t#b3!(!pq|`hOFiH$h6j!U^RrnLpE_bPxbC!< z+JO(Rriq*z4d}SES&8R5lnWykc&^R0Drf>vsrWM?)1};@$b$$>RhTuG#%A6C z7UN!b{zMDXkLn~PF*lOOL{w*g>7izM_FK*>;C~^GNv+&{k~AJ|II%`*w6Kz%}eT*#1ky2w_-N~n5Wf_^YDvhkH>Kfw6+wY-6Z;7%hzEN--0oy40Bv*dk%Q8bUyVjjLs(C+2&|aRJJXxSfAoz( z#TY?}bXQ;0gFoukZ;vc)oWAz$pMED1f7i#Vf{#far~v2~2=z5#C~se>lh7WEueP|r z06Cs&e~!^}4#h+VgJ{jF&m7|1aS;Oq?17zns+8S1+P7K-YC`qOQj@(MbMi}aVEQQt z6TVxyEXvPYlc{1c2W}mR)&+tXNHESo1NCa;^2Zdx3GcYJ+=`}be)acaL~Udp{brFW z2@a~2{JpC73c-0FWFi3z2(SH53v4uZiNKSVN2q9S&etX5Tw-~CWY78A3re!g{%8%i z7>*+W?RkQcoEoTBBq&o3RqRftGxx3zCcZmGA;tOz^8mer%{iG3Z@g?@UYPI92VTY-xh;d@&g~M7v2C$^Z%?@OCJpq zk(*#))_q3#i>ssVH--gbO(Q3Cp?*dXi&J6D1-<61 zhi2-(6eZT8q~GwN=wuvVbJ`rDE82Doo?a1tIG7;6Exmx(A4`8oEs4J`x-XHu45(r} zPx%&2e4q*3BLmSozufDC|0`_!h>p)*wZaVL6vi1et6v0xqN-p{V7`Ax=HI#Pc6O1>8(=0@8b`R`DLoQ zyL!{6>;ZTbxEqC~5;kw~WDK>GJm>{f^{niPRELS%?(TIqQ$jAh@r`7{M zm%=hU`Wfe0G)Qeu9e~YFoM-pIsLKRtV^26Uo?iSH{mACP*|T^Lxmm*XnS3gUt)wf2 zti`592v`8+_<%qx&HQ@leWw>Cxs`^3ZJlQRBU9n*2yh!iL-2hkrge?V1xv)<(SM&k zQ(EMJjsJuoJPG?-8;fY z(=BHL5x)?09Sghf%&1ocv~MdVT;3R<9s04FW*B91*R)$lYKvfMf!3V2tc8BO3o2!a zZIsDpW#Tuum%(6;*w@uI<)tjsN(Jm2dQC8zaz$X&D;aHPTg3Y0SSdi3E5?J~-1^cO zbQ^I@E*Zz+e+3~`*ZHmTAL2nV99v1EO(Pbs0r?_4b;P4KBeW_vM+hy;gK>Zz_^GrT zTnT;S4u$4pXzEK*J(0K}(WlfL3#j)-(Fud1VO#izYs^xk(e%CTKe=5D^lLhtns-Ev&k+FIP1qpT6{i{)9fVPkv`9TtQBG%maD|wM!v}!M4SqwL@VCa%`Zl0UH$# z8@XRPueb7-@tmxYK4^$`Ha3FIyV7Vd!J1-Ut}VrGEiL93wSj8cVKA`gmjAcsL|>mS z|9=t)@>S?>VkjMcJ{ueWCkQ<`@+Qyy?SHc}8UG!i>od5s=SxfuqXHIFDdTNs(6D-g zyAHo!S8lWw7x^fEKnK!fzgj{{*%wmaG|lu%?FK|0AV;A8MMB4$del$?2YB0n9&IPX zrB1)O@Tvb&Gc7H4Ob2!JXOfSgdS>+}C8OD`Eoi2M)3$hhlwnJbP`PTzW`Bp$Sfo}s zM*);iZ#+vPFgyf!VRE7f`u_m*`k0eK2ygDVt69HXENw3T%~>S!J>o)(3*kf9K|vJ_Ih$itGtKM%Q@38u~*Lw&eQZf`d|p6I@natNF0!}(8L0p z9Ro?%-L|bo1&F0Z-#c#tZbk9L5*nj&wpBeA2s8WZ-0zJThxDco`3rgRYm%4~Y{Zl3 zGGOI%V}CNixDXSZpV{vmj#prRp&Joa(#GS<*&>1`(s&@G6%q?~RdN>QRa8KbmL%*y zM`gb+jJnvm8-nmuuThVbdY8Q5uLScta=PiJdx8`9xz};2;{4CNmB1803oDb6kBij@ z0kFOu61GS{fVnVQGNOYZTRYzyiH_mMk1b!EZf==OIP!xec*ujP!W_})RDZOJ8x)VP zyLZnY1@Gi(%#UIWjxF2i7J44Y-uh)OIXnD8EORe?bm9HkT?SMArwMv@K&H_@Nl#Ms zuUJs$?=W&@VhPa{bm~}vwk0NSXV-@LTkt?sIQS!g*#tfO91L%`2My307rJoE{??R9 zGy#*i=)fr8pmWpaCl4NcsGrPivGTiz-xMGE4~t8=XAPMneUWcmF6uwT41Bg{k`}0-5zdBam5CzeSB6js;7uWtjf+- z(-LHw7|ZRk3SY}jgMHN(P|fob$PtTcm7U(0vIeIbcdeXa*4oS)I2#4YzOzoJrDb{JcBi0^cWJ8mq7Fz$N{`2_;< z@=(g_Z2?u4C{K-TgFPRbcb=~2UTcsC5`~~zPGlfpL~=a2NDC(Xu*kC@zEaa1{|4~- zl~pbaEvL9Df|Xmf>2jsBHpHJdv3*v3-QK^&KjY}UI@QK?{Z_Z7C9&l_@fM3Gb zI(&9!xl@^P{2OQxY|Rnrz=igAbMB+xKV?CL!z)fYTvk?G9*vjqKpj8upbvvwItjI9 zj^T!?zyIexgF&B693$8~7m>*a-chmdR7SRo5xC&i`c2Y zW5cfLZ`XjHw0Huk%K?@KJpKP|b%LoUbOy%Et<-KDKWVa2>!i{7rmasRt!@ijLfOWO z7D{Q9KqhAE1wbC0Z|zx*9D+-M%)r2|_K^}00Kgz%^GZeW+^_Nmf`=gR`X25-E$0tl zWOg;>jw|#~_~UK@pu27lFjD=e?Q{im(^8`J z2xk%18Qax z4&uJI*(I^yLV}_yj*-y)Q&e*dVND*ZA4gOF2IAUui^!+%%c3M73H%u=1~QqvQ3pNP zL-+1Y%wT<;H$E>)}B$)2zgEIGQYlkgmh5T|ry3}N-cDdc+X>#uOHcs!^%AlL- zQ6K#jKM<+1BUENX!_Ek^{9G#AIV0>D<9SErO2+@`!S#2lvS{$zIDi&qdmGtotsw%q z<)WP>5nV4bR51^E6N|T!4*d9l*^phq+S)JzHvu1kfc}3hjxY*a=rDjy&FkH{Q>uh! zKCZD1-$xo2h?A&Kttxt%rAj@Is~y|UF#N+vr(-x@CtEV9Kz6rbZ%aYNC46f{*<~xX zZmp}!Uum3=TjeR=1ybwi&VYjf;hEYHVnTjZ)Ala(SPVAcaEoVb-inZoeN_YFeNF?5 zE;HmB>jIgG#i~{KhXkQu>v0-91z_5_H5LZOjCOltlJ3z}NBh+N7>)Ojx9h4}$DA(z zyIQ)Yqr6Q2vS8r7wVMGS^g1XkQrnMJT03Xx000x#aDX)yTde{%U{0#1Ln4VK?|_9V zKWZ-}Ps<@HrZrBHXzDb1qH!tzz6QA7_`azx+yaqe7hEx@a!>;}vqNzZS~&hG>Nr3d!QgFBum z-qlfX;DN`9zURh+Cb#0y9$g2+0>e)U5hyZ1J^F?_M_(;j-L!z~V31zga`Z-DS0jIg zvih&M3Bfcmo7giA0fjHYCD1Fm@`yMq&i0t>N097p`HsH(=F;OgsanESS4gW#PPVj@_|wVU5iE?$;{#eacA^=2mM00LxY}l^ zIeJ6pv+e1#{$RE?_~pA!#o&#)1viY+Hav>5ob$nVJyg$+Xx{3DV~07#t(^Zg9sxxM ziI!CoP5dB>JiKsZy?Kd*K#*yz^i`c|tj$MpT_J?b>*R|aR&OgF!Qn3joW8ES(RxTu zLWLLx&44ftNTK#{E0>!IMEv2x?eVXJYL@Y!*Thf^>zT{dGLn6* z9~Dt^GNIGm!*bNyZ#=i3bxQ?Ne=P2|y^qo*owSv`ox4&p7`@`JccxAG z@-?C;D3!T#ELK9Kxa<ndDYt%sSKT+jKTTGgh@E_7dkT<8hw4e9aEj(bhqtZ8@N-$${$7D>M z@p0yk^XmHA0Y@FG*l(l0hpRw6X&)y?6L_o}R6_hAwGM%}u7H=mtqq4b>Wvo;b;-B5 z(rG%@>n|0&Rv;0BLJ1q87d|OKDFuhMa}UD#oRz8|Ag9?Ke4}OSkN59#J}=Q-fz^a9DEiO zU|xWU_3%z*4P2X{k*^&CVIZ;c6&2CuEOUns!42a~=yR=K+K4U?B zx-rT?g6Mck8S33^%#dEU^aIM?yW&cs|LUgK_?1MjlZ|Z&c>%+-7r^T%E>W_qh;lb<&6UR!9*I{!AnTvG+@K(u<=I)6qK*N#sdGU44gd(_ah zE|;*viyAPmtCla|wWj~ctB@$yP}1!_o)7gu4U=tKfFF6oP(cj9gaWQ|x!QSim|l;g z68WF*(MjL17Xm&ATz(JCuIDG-m+Rr-i&H=)&TIBX3+|D^T7d7^&*i3KH80 zxFE~d$WL}}pVi6wVdHea0g22t!IBV?4|#33fzmE=(O6|x9` z)w-GAS9SgP_R=zC-xt2_lL^E>3BB{WqcvD>r$@tS@1k{_*;vUb#X3T}x?aB>jP*7m zs_1ELkJYZJz0dbB6`PF|eV@{y_ekFOmz=e>p5v=mUQn%5@vQ1@5&JLPpNxpAg);jn5PqtO1FF5uHep-maTOE9%46N@t58rqi zKX;wOx29-?d+yyf5JQWK-(f6!7%Zn_e?$=8?P$XO_~zrdgv(j$M^=bc|L(harvFOh z+So78rNb;2WHA4dsV?N%1J%Z&`Hw=G5ATjGjnO!i`^$$sV04xD&(pl)x4PC_ljRMQ zDO7DyH+ZQMXS}{m^OiZ`)FHGS+#JIQg%}l6mCU7OeHTaiEL9Ic11AM%iDE7G7WWq5IrLD#eh*_4)m(uWn29;Fat!h)ns$wx^cJF{$=df z1BZp#N-qE9)#UVzme1a z`&kDcY|KL;$Sj(SN8AHd&yj7Ne|?c5GdHt}$z^?R>uni#@ZF(988!ucXGFuM$n7-J zBbJ-vMbuW)XV%kameW|sLThic!Hik3b;NY3X@|xu4(39rgIj+GpVLv0sKdWl$+i=r zN+2WXXkOq~qu_VlzMU|qps6#ayhw`pscG61>2(L+7oXktL_2A|m1t9Qw&*d$&bDGw z1542A&jqLp1}1^TzuGU<1NLf#$|e;+NZ{?C@JuYTTx(EcZSDLlI>-Sx!~u|fKjdG2 z9Fu5LcbIlaK=*@(r(1{6OW@qK+9vDY(HqwX*)hW9l&m(z+M3%c&Icy5t&ZE|S6A7H z6JGtt{va3!3_65?xj9)|nLXA$W*R~b^0imEYy>iU=qUfR5Yn>b!AaY9Fdql&1sl^D zlpPf?nJS8H>C6}7KsgPLBs-{z4p`7or+hWbvccI2@kW3R;f$&voW_L1a7dRocV}a{ zF~L%A7^r(>2MaO^l=qa%Ai6^Sx?)RYZ#5M41)z(@3BU6s&ZexCbF|fK2BxjPSGL=z z|0fQ5o77>%=jnM3U*de5mLGAG9hFM`s76cP*-Dd$>$?JK4D-MC;aNR_%QxB7N?XGJ z#)(_)ZJmH`N}VFj($zYUCC3WU!OhTh*qSICE??vLbA^*Ey95|sJ)Z+*g^}7*{s{<^ zkb*kBp%wV+RIOQl@pSbjX4E3bVg>=xCQ+i8%%`&RkKqJnJu7=y4&l zQ;06!NTO@xXIFTyw>O>y!KWt@{5U<7PwoVfs_DY@_x>&`7|c0x;)ycisS@JGPhG0l z{y6tOpfDdC74i%z;mpq^GTr`)mhImZq^bHET1+vO)$;q2hk!rR`K$d6!}IzvHxheq zlaxP!_U=Tb6RsIWgi3uKs*LGMSS{NN@&nBX02m+_(3Ki0?+Xw(1RV4FCIr8)n zTMJP=`H7+BV2P5Y0c%#s%*W;UI(1EG869o;`Q(s##|($rTRRuA6+h5!UK{h@(d=-) zaUGUlx@PRSP=MUrB^oq8^=Y-e(%`mHo0h*};K@>XAStfyZq~fk^djv20Qp+g94Hs= zmuF=RdIicA`x>~li+D-YKvwOe%z0<#r-kKFoj*D^Hz~mfax(%t%)LlTl&4sS`)t6GIGlT#vsUV+Lk)P|Y zm3euMeYQ&LSTQ=PzpeJXn)M#+kEc7KPeVDhS8_e5gI-MO`ikI?Bk z!uiMafy*@0T(4{LQkK*&p0J&b7SF&=!qXD(8$SjKa$i@m`-Xm_j zwomWlPcB+RlBmINFUZdIWUCLr^NmbD-JWd8g-9ix1wtfr`tjF+eaWY-b0nt~3Dkg= ze(qz33vcz2D$k4lalr`Reyx#qotbSrw$4BLPQ}`Hjf)Zl!1#nfrHV7Q`AGc0Rb86y z$SZH}M}p8gZHeH=LyB#Ut0$dOg%9901I^-{K+iyQR<_h6o9AEk=gW&KzFxm@ zo@kMpsXL8BjyPP$gBU>MqJ?4~(m2cH{vKb^L2Z<)C9IFEC=IUys%XoJ3??iRS4fSk zw>(bvS8d2xk+#ncgsE;hvHL$7zcx(9TQYsIrU3kzwPI| z(|naqfv06@sPhc!AT@_?LYgSDGl^86+)Q}^)7^x|_T4hA#hE3y7R&A7E67SM|W*p{6MNNtbTq?QUoP#_4- z(;XuGxRDCVneXj@C59?Dhb86*RfpT;JN%vegw64UQ@!L#GD*Oh2J06XyC_T;8~R^) zoJDd~j-TdZIIa^#vK}Nsq3GB`OPP@w;-uHi1EgJ)gp3-=Lq)wwl1#*k?iuhoGg~Nu z7J{Qq=Z8S49{|rrX~q+nhHW?-50_k9cH8Bygyg)@G9CHR&(#rLvo3mD@afute=9!N zo$Qi73tm$&V}?B8u6S=TbNGk{Epq>CO2n2{#V$YJ-qU?LoIHNiDvM9)?{BBqu{MNNQqKcSVZ-;OT*B7q- zXsdfph?4(sg#c?*M1kGQ-P$z z6V&-yC;5TR=Ilwc{e*|`CgLpdNMMtEBVbBjI+N{pnlg?@-&~%U9zdzpzI?o=D*Gb? zn|p%6<`a^B4X;S&(_wD--1b2=G7F({8jDjU-=B^5c~(xxw&$cH3-EKnQYLNj(_KIE z9#D-Yxa(OYi6zUmB}r4KLdGI*EvJ!pxHo48wqwxtseXk``R>Zf_CA#bB0Ftp^2I%P z(!e_acG#JmTNW;RuTF!OfPefm>xS$K)rHmB$6N|xgUIDQjep0H{RW_b9Px>{9AIqT zR#6P>2MZZ{NkHFxy@QtXlf>1^eXND41R42v-7`60WfDVYfldKsh+IWsP)`4=U9N&I zDoI0UdAG;nJZ?95_~D)uCR@Q3dfoET&;kAbJDE5~BpATfFQ)IeoZ(5d1R~@4G~_u! zk#~(&TN4ts>Eoj^7p>S-iIcqWt(g)*;w+H;H$%=xqr9s5q&q%y1&mBv$xV*^N*Zp! zX|%YG+c%(Wq9s|t#|_a5GTu1({px>-0X)RIOT+N+@F>|h$dI=pBKFRn)5dmRh3t4J zu8_x&uUO@l&lc@GzNt%Ur;GExJiL4&a=xWW)^P>ORWrCzZhY8Ca_~#865`o|k=Ujn z2Eck&OTZ7f+{7CofTCs!#nwg@J#jji{lyk~n$Y^)474$n$4bshBPP=y0?IeNt10CA zSpV!U!TU*5{5`>(!|#=kLaT?=g?mOxFn*-yNu%XJDgTCNd3$J?8AD!Dc|EFTO~;U^*kCVf`4d$OlW`HrlvRd$9YJb%6UEO5+X72_>sj|SfMeL43@roWyzb@_Z4OSu|_rM5qY=lgd-+l*9&98r#LCTOWf$5|+ z3UG;6G&Va+DXW55p|4{Vm4--11pqv3%8?Ef=Vxu=Q``KR%R1L$!Shv%cA+M#$$PtQ zi(gcPST;+guc{NP76T&vvs@meLUx*2CgIY}Ma7486(N=$RZD(4>yWf3G{tc~W{>T6 z`vaK6U<3*j9o|Z++FS56s`+1Ykwuc%NfZT$nJBO2OBGXT=n@iZ)u`sz`{gp&Q*kex8+bh{YGUHImD4q^#})YKP}_L#}U*dRUSXx zDuLb-M{Op3m!I3{AQC}1+35e$UrKKeoO9HXp4B`eh~=19S#6-jRs8OM5R?jq=>}}bsHGPGEjF822%a) z0XQFgCWY)QnUZ}+FyJc5t4BJD8fNvP#+3>xx|FpS(8L_$ zEW8T{9dnaMkg}q`+x36Hd2rJGI~vt^LW%x|&y=DV5FF(=h@VMAe-H89-D~Xwx{L4YDvHTP7D|Kxf_rEgW)Z&}C;VhVE2uXh@~d%c z+@Mz$B(9c-WZ zrAO(?gGyh0mGJ`DImTdGR0>V^2{shH7Irz0VgMHcu9}EYn6OLgo|}WwYpF!}@xhxL z+ z`02_>CpJ^(xVO-j?R|4NDLqLyiBz3?iTNMb_FyeAyV=^MHxotyAP7AO_>kZW4$sfC z=wd-D93vI_YRKyZMnBhRZ5q;s5GM@T0KW+K_(+Jd0N3y4Y3Cf^nJF`J8+HHyar(Qh zJ>wU?{GzgzJ^xb#M42wIn$0J2jC>F%j)SJ~z{aXksQlVjmH0n!l%fOJv-o)obLVws z-3=77H1ijXHI#Erys*xr!nu&mD1F=X;?ecB!<8*p6hz;9w$>Kr^3?hBD&-5TjI1aC z=)I&_6dXYyU>;Ws8sM1Et7jVuW*t=}9m=*9cLf2iJit~j69LZ6M^a+I2f}^=X>c5) zSeHWbEo^;`1c12cEIH7-&E2~_GsGe1c5z@aH1U>(M~7y3pCBQJ^`*)(R-s1XVB;RN ze%fCk5Ni38=3RR)ONV0)1uE?^rc|kIv)`*f2M8wM6|CWN&{t4;9sX%xjiIldVBu(! z{-ctxHjNb5JJT(S8R&jIR!`>oNayktY2Swcg-gD${VgZV-|rSn9`F5g)4Ms0)2XZW z9bDGKG3dLbx(Abi_y$v7k`~MT#Reej0VzvBBawrptY)%C`ad1 z`cYP-$G>tgd`i6Vrw3*p9hC;>OBIWq(+x?5s7?%tWO570{aYjU@*B^}d)9IruEz6R z`0JJqAym&_d>?SY%JnKBVGsRED9iDrL6fVC%y!z`sS8rde(L+pL{{kJt1kcLrSQh5 z2w1Rq)*fViX3~+=umSOZBDbq+%~Dnk0~ReF7`3iI#LlTKOave7983&|R;wmHmSg}{ zqPM)s>#(fos#{U$B{D*pM=y@t78`m?Zqgk%NXUshDf!*jR&`^B4J5X08prq#x@Q(} zzzItFtmEi7c;uakk4Bfk4Y8AS==qB+_`cFmA)npQhYhP;5^2uQI5C9jjER#7lP+=H zT@}G$xBlPC3hSCb=hGniYK?l=K}pe{LhIDL-D?blH5>_)cE@AM8*hymqY&A!&QZhR z{fZ<}>lJ}&kv-cZC{mzdozMpZRq~5-M6&>}*klL56D$h~wniq}+2ReR4e>ct;NN&H z9oFA}P?$@;7|=jQizFQ4gc@s7z{d5#K5@Tqa$#~aetv|$l~jZ5!cJJtAj_pi!FxN0 zK?yvTrZ?&m>R8`-qoLx|(iKhnN1cw&b#%2?wBMvZ?AXNK_TR&o)}!ZEVfgq9ZylU` zE-8UqKf&;s-DuM>#tngO-y5A=($7nAP~g~Z(?kC;Rx!qB8YxkdPFX|cl>M}>kBq%n zu6;8%u}(!nVlW+;saU>qduG~+qaU#D> zsj4gCnAKZkEXTh(hrg(W|F){w5rqriVAKHjZ;dTzJwk$p5wM=Fs_f`gSs_Zdgn2_D zcrib62a9va%YZqW@7gR2nDvb?O1X3#oF~dMbT$w6UdB~(%k!P&^JSaB<#?*Alttmx z9nUH}CK}|p_LBbZ?E9ReHC4E z+(`gTOeny1lLMT<=AiK)s~m8Zmi(^*^P{t9`Q59m7`ohu0wPKspv3aZ8yfSa*}+a{ zA4TQmfe^<^%OPmnu&pko2{+72v;A5_MX8RP)Gxc!hKopXFkr@0mA6rqFIJPcqAHml znjGZxxzOdCGLqE2B~Ng@qd;+2d^RLWQ{k|fF>HV6z|Wf;=Kck{I6v#sc|#RV^M_v6 zhXqfHhDeeHPmTspj)iDo*MELHm9+_P_W}UqnGp&n|{8_J=;f zv^E6F%#kS3#7W7eP7m67L^y6=nJCp;NuZ0SnKu7N$%KJ?x;Gx(@5~-1K)L-ukXz-2 zEbbNR%Wj*OIBRW4axq;N=5G~}KjoF-Cabn@T(r+p>C3~4;0)mB+AFME7i#D26LPnK z!8wjBka9lA*uoX}shvHo=t8<2U81UryBu)O@f>7Z9@txX{`9^={M3&YVT1E&D&(!U zz<&>)|KBi+;X}D^oLl_r4uKe*eB(|JR*4OUa|_B7OqZ1(_fgZ4fMku%sOn zPn7vSe}(|F5^GEu7+F%Mye(99FyF3??3wzgqf~3($aw}7&3ALrh+oIenWKrJEV}xO zO(eQ2Ap4vR?QfgpK`6;;fgmG1!5ypZ-R0Umd>;(Jl2*KZbKD!KKIPk6;huxf%f8Ak z7--uAUH&9h*{eT3>9M>Ysf`ELyJJh(9K(l3fxag!=-8JlI<9rul!+VMw|*P_^P++u z73wSZDD2B>c4_~d(GFA5#L)UvW_jPFR`b%7~9LkiMJyJDhYE>4Q*k*NuX9J8l&8dm(n!eXL>z!%U%7 z?r(N*`vP42f=0zFeJXk7>(oj4MMu(~=R>lgvBp#E<}#186wuo5nf?Y_qu?=az=OA{ zceQXq=Fh!~!uI153&kRL{iP(M`XDfMFVjVnHe~LNkI2skbw)APx&Q)!|66W^A)SH7n54oE!`fP zkD1!wpz&fafIp$vitY&myi5sl7jx(Y#b_o!Na7~=7>W`N0BsU}v<4U@f|HmV4y0ow zPZ7G4XGVeqIv}5p`f2(`@W9m+>1erKkk`V}=RKl=n<)X%5+<0R+G5W~)w^r+3#EsxUQ+fny-7z5bzr zAKH|<>+`%3U9I&RTjFC}gSy?|LdZsa+0H<0d>wqS4{#R0{1gk15{&>a99KSMb(8K# zuaGM#B$DYv%fC+5Osf_MX!Fu2X`}gNl(U(R|H;jluvruw0s89l3=ovdM*ScB=<*{& zJ^U83{FR4m${t7uOOat&610cGv+#Zg>5!l5THMQH+bYLiM10?3IDV9-mE)WjZGXS! zF1Nu3@Bdsa(Zy<_abXuf`O{N#{3)x)H4Bpmamw#=XH>TJ)0~4$2{8%D+|}H-H&;=o zawJ(9I8ek#&l2$V(D1IPrL3I~ZzS6O=6~|wwTf8d34l#TLOOpR6%|j`>;j^RLW01} zoRystC1jJNDb|uu%m^{~TGJS<2ztH?7@6kI%mHrbi%_eHg{CxL$!ZmWO46Z4y&wOMcWw+eFlvBg+XBH^Ns*xGVy0)$90Np_rd zdZYBSWwdJ!D=h$z8r}0XT#8TJ2X1|*IKSIY*Z?4Joq4pnj?4MvNQ(y@&$g(6cfxHX zM({I97bmD}f6ByNuqB@S(DySdvEZdYb@Z2nXtWS0)7E+1lMy@qRC7jhz-gz zl3VpKY&6`8VTHaALR_TcZ5-MI5btXJg5$h69qIq+Z%=kOe)%MM$3VYizHT24Ukeo9 z@fdGkHkX!VZ2uz;0P5O?#~uO!WK2@8>skCy(iE_Obx(~wq$A8f5ZsRnURVAh;XTny z4)Y}@u1#f!UFcm6uo{qkW!t?B0IRC+`dz(fM0StZ2K35J3QU0`rAEh>3u}xne;T7Nk`?;x?W^HB- z_W!zI{dt3Um@iL}zB^)jk>qU<5=?pNA8U_&tN;xoI5%(LL;HjA6EMqdv&EcEogM%y zRV~e`z2y7=<)p>{2zh}ZcT3~sp*m2#X5w*7ngRLnvOth_>%Pmg7GU12aLQ9|u}T&=Vt^nYKCxUk84`F}E~C=Yi3 zj7|9wjzQ~Fvn!Ql@GhUv+`MwYV^~J(*u%o{-*6KgHiPt;m@dEjYu<%`LPHICMQ>IN z@Xjagw_SiU2Q>K)#sm!D+7y3h5tg>IrLyarcjr<5wPn=5>y-qVQX+%Jc@Jx^cov?@cvgf`b$J~R{fu} z5ChF6+6%Jv&L&KN=>!B;ELc+eCpxLtgO{knR{}jpO%1W8fTr|Da83{^g79$f+Mc(C zRoa2eFOX4*>eY%4I)HcD>cNdp|EgX705nbjh;)#Z3#Ir)J?_IOKM`qZHK{CEAV-Rm zK$eq2HvcO4et*&Z{`Rj4-I+lQ`|xoXRkN;Ag3v$gNA?c$%W2}jo`uYpMP5jpEeq^h zyzb4oDIB47SeHn=TTk!qnI%MJs(4azH0GT=2W6hZ)Qg0l5=}y>Uhs4Q522 zH~`g+$}!2niFN*m9O!uUzaM1pH_d3=T3e&+-RQK&?Q}CGL7KE9ywK9^=(+U`|JY<2!sNU(=8p2L&l&~uN*I*I%`>6 zL0ABPW&nBj$};IqqE%r(?8q=t`b*o~^2iY}(K%$KGKhp;=6657Nr?~5V0-D~ngFOyj%@5Z3b95&@uUUsXEGEb&J}wtiQvD$$8X#nR{vklf-Zvm zt|d)|L!ZYqE)*46>g`Ovo_9EeYqFPI%)yM>dT683a?7~%4WD{4v7~cd*rUEM1u!Zn zH^F{uB3I(}t7y<;nVIDU_la{2C{sJk{MT>2O`-R5IkKR&J28MDIRLOo4e>MFfKR-J zj1J!azhSDt4aM5E&u0=e5jkERk^+iZjt!J3Athxh%azULA)~yCOU`jrO=K)r{L2b4 z;DIyRiB7$9SzL=2_lWod&vu?e>-7wCXNZ;g?Z-3 zl~YaK`h#Z5h^|BD#cM14t)(nxZsxe=bH_!!Z~Q}j=oc#c@X1blC8TxtHAK0INRUN=kw`B>Ki*mZVdD4>FQv6l+t|KO^C`dYHu0rlhL+B} zfH97LPMuc`0(|(&FPpmoKA;<+<-&?&IOY-?F55 zV5+l6{0I}ZlkWuLHvkS-$SU)XYvdLsGX zy$uLLJO|~w2J}DPU7T`rNNfqwtypuB-=s8!;3By0UYEVH1n+NU^#xpV;q3y>5sSyhBdKodaQRZt(FYago>!ckka>e3HqNXKI7-+3(jjFs| z;d9kW(6d%f%<(_( zQ^N;fJsrN|02XfhMug2i4?dmu?ki5!>Usnkzh}z3!8GxbMzWrLX4W=~4AFH<2?p&y z1*1rbio562J$42rYB^~&elPUcU}Y&KU#KU5!;3l5@T=A%es{eW*0Axzy;Hr#C`uOT zjflPSbjQ$PN0q#MdKP5{f)e0I-j3{c>kI#XsCo;itfH=Kn?_0+q(h`bx;rEUq#Km( zF6r(@K)OY`yFt3UOH#T!zRmMJ@Bh8O10A=Bw*${U`|P#Wob&pmI)-Gtqs6vct`k>+ zPN9{%@11uixy?+$K4*D^@T2@Yt5fb`3Ur?xn5mJ{noIpw%tGSJ+B`H;ITV8SWr0oy zt}qO@xyY$M+#~mrvak}HAUE>c*8758Q}OC(0`aVPYR44!0v?IthdHYAe!K=LWuq+2 zvIihkaG7q9Yk1`u{@1Z;xzbb%8jkzIRW|TGEuEq~V3i|4d3tb*dZ12pwHiO{Vse9| z{8tD4M>3huf!MH3tIt1W4MB=+q!sqT7|Woy1uWRd5Uc!veS$Eh(pdezOPSE%g60#+ zeuU7VnllveJZb59;P9gIh5jeQiYc?IZuu(TTT|UD>u0(f!gf_}JM7PyZcCb{T;E|k zr!7zZWUvfj`}x!!+k*nsT!}FS5x;d(`ECY={ql306iie*9b}!rNVchI`}?9B9kTt0 zO#AlG@jJm_B!q~ksL&D1L6Y7RKOYh#jK0DxMsm@~`=mtZ45}TLNuOPAEJEY)LMaxM zm_sB_a@0)2&shgr4O&cZ({x7BN;gL|8|HB6G})okVGBFs-kpWE$SH&o-DT&Xl6z0w@V4Quuy&)`!uhYFvgO%X*J`fQ>4K&zfcQ(+#~%Ze2x{9=W#+DKO}G=x~@VgXaHAE|1=dy zx^7)5aWri@FPuyIh%rN|_C6>jMIw9)y`UgjqWY9{5!c z;-65(ql0eT{xWn6M+uz;Z>0qp9pVCyQi0;vf({Y#G02O-=b1R)Q8A*fkJ|F(6CH@L zvb6T$Sk{QDArI0Ow6m@-CORya9oUF(C^kbPnDnpPl38dnl4&qDlNT@)1gd>RM7$kW zr#q|!^hhuG?Af;*J2yL{Hss!TF}b#*-ek&>pTzECEgRV{Dal0O4xF4nh{ejnYQyVO zAg^|Fy$^%p>jPOOzwu+=>&8k!u9c+*;*jg27ZTn*_uy+%K$^Mgf6uIdO1$~H*#EBe zAyEaEN9KbwLkS-$bY${U1%4kaO!KGeiZx6ekM_#5x4V7S z=M3CA6rh%6yB8sDNzD5EEnDbij*4n<>-+XSJh`sSkc|;QtZP96yL6bJQ-S=~zRrS* zqaKqDnF+;KMr{acEYc;*k6%4GN07)_yaXqog_13IyU7UM?A|H5!zjAHQ`7=4-sz{_ zJHUXKEo)k8)TA0F8M>cyS8N`M`LX4SX|VR`m**;=(v9qfn9OlQ=+XBAj8Vb7b&%r$ zOjcod`s@ysZNi}BDRqX?qZyJ^Hnz3x*tPg@#7Xhs)l$azyN!=_VO`sC!}`LF-dyE5 z=Cd^CO}9CJBALCZS6PTIcHYYLvPUe4lh!yZW&DJ*KUVs-J;bGT)9?Jm+cIm_8kWsJ zL=pWg)Dh%cd}Wa<3j35e)()`rW>3mkeOa}Fl44TT*n9LRoi%IXlV$>y_W_3#zSgxH z&18sBaI@eW~0a5!9N=&=EJYr9Y z;rf=mr%3}u@WIX7sZ&Jq3a9TP0IQlz>ed?y-%q_+tJ(QNoFWNAGbSiw>(IUQC_PW6oT(x3kHa(kUq39rlh0EnKZjAlLQLfi&5j*Iu@>Sc!X%w1x+pc z=%8)ayIMEw`l9u=Z*vfiwO>DK(JO*Ey(g(~Et{itI@h&%Dz^m#Qm-45~0BkgMB7QX9chm)Bh z#*WzZ@|lsfgoT@aD3775_aals$V4E()jp@EBD1R#ynxp&i zlL4d6*n+AuW-U6{Gvs!Smg-^t_7_U)BTd&EC3f&&XXQNc&iCns;t_(n@dlq(p1236+;WyWZ!2c>WY zn~TutVU84O*_ zbm+SP5y)u3aCI#$E!FT`e-fa-6*W@iQy}k(|G=XC#E*?^p_ww5vqIJN9`W-Gm)mYh zvc>8iU$Z4wj?9;toJ6(;YllxVn0suE>uxajKp*R76{EqnRo#Id-dLLIYu)~i9wF_Y z2}kKg!rsorR+PRXhdD#p>Uh}${?T1l{isZEDZAJFhw<{&@n2F|!L5EqsrxHWWHk?B z^ky+54_0gq%6a6TD=}&^&R9(VIHxz751&AX=OmMfi{GQd5yvyCJoRY?j_Hhq9U_OOGN#nHyAb z5G*bm%-?!&avsa^0K+q;fWDMqFuQ&5KJm@vjNt}wD!&S8-&bETd(Bz1SSwbg_{xcA zahj4i!}HHi|LdC<@$~PfP=f!LC z%?%F1)oPMYE_x9qbHRdcJ!o}K_oTZ>blmf>jknG82F~1pV*-wdY4rYTTYq0*uXdqa zHE5p8sn@rmoSh%+M(*EWHTsaWevG_xg=?YrPm;+@FtU}tI^nc7gGYp=hQ*U^gUJ7K zpTr~-JJUX(;;k2AQh_%1BdK!;*4EyRpkcDE0`3tV0k{qLoVDB9BEtx&Xxr0ahROpy@0Db@5a$TzxsNl)iy>~ zx90VuqkzMU4W}2on1!Zh|DJ;%MhprkY3%VRmdYV*&PwnZ0t7v+eFGG348C4db&Pzx z=u;}ToCIt|gKF0Q{;*oX~xC593z_`MBfgjc7CfK$Q zw)OTJiFLdEJIq^>Mlb*E&G)B-0v;=Go_AK`RmS>2Bgj7-e&KhbhPHR}ga0dFjs91} zrp$EZ?Hr>Oe!=d(-OMEJ6S2?lb?lKO zuwGa-IxU=qUg+}Nb^^_*f;pQGz1ax=@}{4+KybL2m3zC(L)fe>1=|o-NaS2-+ac#w*_OMGp``Mj z4KKVqF0g!~T$zHk2XUHhF}vCALR4-}+vFxnpv$^wcFUaurL)_Ty}%#29PI6Q z^2*$<+RcST<*S;H&jV>~w~|BpD`}vw)|w~L3*y?43JDdlu5_AFtQcqC{?A|pQooL2 zIbA7hmnO*y1|OD3N?11ryF16{1FTz*^8_1ngSzKlN(TLIN^q`BT~gAOtDWPVI9H2{ z;HWiWpyD^9WPCyqSA*tblT3b&=y;{xI=uw-_G$uxazZ$Ww8sqv*$=`WfQ_8wX;F87 zyBKWzthf7{n7;(!#UTr*c?`WO(S7KCJSTy$?H4NR#eggy>>NEt)3^ueY#;d*Z;U{X z>@p3Zr&jy)RxkAOh2^*TUxXM_`#M97BF3n~PZ*{-2~F9_eh(E{5w9EJ`I8~Ygd(#n zcw99lB#b?{<~JODuc{6~G9ldoX_JZQVaZgf<^wmkWA3LOdhmHsk_*OOyPdFk`z8Ml z25uz$#1-<*nP$dZfmX4RF|Jms&edL*3AK>N#Rz#eZ%ISy++!i`vIV z-}6@c3@?*sO^`Y=+sVwr{gHh0dbhYYt^YfskK5o+KfQM9URpwsm#32J2==$jV%Y1U z1EGzU7kG?H-##Xlh{;P;4o|u%l<%2I`&xgsVK^mxK3zoDu5X0)e!gJt-kvU^V<+y({>RmJ^%yZql?t8WN%6YKkKX7u=0h`m{_skwJ-D1YO!-?Vx3z2$SXM{o24yjNk5=cG+8+^J|TG(bgGgG4wl#=SB)X+mQp z{7C6#HU^*jD^$zn`m2@=ntb%9&I=(mp)P>SHE7^#Ml=BY$+jUlyMMMYAT$X5{0&G) zCxBaOsY`SR8SgLWK~}Ezd|~;@fNdKDG8RJi1wJ>gIG?5_p#oTMGZ46op2Mkg*AYP? zWHvfs0g`PmAW#6!Z-XP3e(GZlG`a6+)+dv^?&y~j01g7kSIi+Z(53Eb%kD3F&n$%^ zQw#IZ2EL!i9U@m(ON0f#2tb@XocdzxKp2dw%@I-zbk*SYS$raAB(fIOO+1@+#R^S} zkO}IVpDB1*F8dTPnd3~~YODk=!Q=5dj0KLP=Z%o;1TKIu8~bno^w%(BvVYJ{-!xcq zK}A7l;79+}doy;u{}}qKv&O#c1Gq+ei|8%p7F2ID!gHCnI%ll~y&m8{p(Ire~7kab0h<0tF;!F=Gz_iwfyA zN|}duZd28)M+%m&YNMW%9B1BBg^A7^o298>s!_4Cv1mNb1`xWc#3*-#-EFfnJv@WMDuahfT}=9R_iZ`0z*`Fz%? z#O2CZ_K?xM)*Sb?te-_Z-bZ`pBk*P44rLPciO}m%oLQux4Q{oQ`!ivY8nK?{$DRI) zJI#+j{iO(A_q6B7Z_l~*!pv%lGu&nHvIY&L+$`r^EMT9vrl^no4)FMQgT3uu@p$8B zYQxwgg56)$ke@^#tMvOJQU<96M;mX?Cw7&nQM_VV(v)VPm^7&|$Wf|?cNUzIO^VC~VD;y&eE za}N!65mDnjfpyiL-;K`4U3OBIop1ss*=6s{y0L*c@Z=Bq4n{BHu!P^W8@B7!Lv=O! zF9n-oS|^;%Jf5IRkLOx|R*0jAMrT^BD`1pGWFrAL zkon6GkYGTxgHB5&@C|}u$_}ijzB}lTtWuei68qn%`kRkB5iaV-15PG9YA~p8y z6aAI+{K&W26ef^CQaD!*mLeMCUODA`@S?|Uxk&-?d&C(4`eAOp{`iJ3SSESZ_QO8JAjejpOUk~Z zfc?%ut0KpS`dO9abLzJ~vtL}wHD@`^0_mg0*CB)oSBeNxyPaozq{*pqOeBK_v?_zPHyyJU-^Q*THYoxv}<^XsBUoR*|>f>NNHWDn^00@s8-(G z!{-0s3;1@*DET#!mS98|1adrLMlsUT@li06w<*X45Rq=;x>Akcc!qZMnh_mamo3PB z%j}jVAAZkBp|OsYIxe*Dj1thY?DMI#ED%xB3d-@+Yu)hy^+P=^sK{B1g={GNh}{n; z7nGM^|FJ2Sqo;gFGAk2j#kJVBi2G2YyCyg5hL2LZ_a1D}r_CzG3;#mhHUC#j{k68b zUkD-jRcFg7>_<=Oa67TVz3k%Qd(WyGTTo$3MKjD`l(nl3Km?r*KJibu+Sxv_m`nz* z%`I>_CAlB=ySA_82v;3w-kz*P_hfjT!_$7vi<2`(;u6o6E)?7LXCK*G-4|71CGH)b zS4*jsDIF^2h}DsS24mJ_r;LWLUXrfF8kr>EV~@H>fpKBRe}gV4gha&<@6NSKtmspC z-o3tKpramR?2$|*?KwX)Ngzga^Pr2gWFui-n$!8y9aCNB5^-5YO0=&<(2v>Rhm!o?%Nbm zsm&Bcgp|9ZyOc)r8+Wy1t;uR(y7=+DvvUutigCYWhDL1Gvrv4?XfHo1&fnhm$)9*PZd#3gS zHKN;Cqyc#5R6gAmphxssGO+++`rdK4o$E>dPxbbJlqAduf^Sj7A7ll;sL0)#g`Fp2 z@5#EpV^#8IS1KuEIE=IJ9~SvLLNi{PgO2J@lh{l+CK?t%DlP)CXQ=?WUY4|bdKWC; zohqd^KSU*SeNLl2^`kh=8R~Z6L=dc%c&H; zeLhqhmrpcGE$%%Wt@YKW`KwEzHt8c9eXOuse7YUkcHc{}!kUH<9i4~R%p1<79AS8l zp3Jr6J5I0I%tkFv-NxUuEvpoARJX=vy&qqo8CU5F+P<*)DI#7TJaOz}E#?<&s|^&r zYK_3!t;8+#N&V+YOTl2J74hzzGAP#R1ZBfu&9*OoIO=drjQit97QL8h)Tp(tD#JGM zL#>#_^x|FNXAcTdwFJ_dmj#wfC4O{3E&8Lm7_5r5$0v$(BOUXeb(m@D|25A3e>4qM zD$`J{_cA}`TY8&_>1UYCvvF|1XTz;C`uKG}o+jyVqlO)V)@W(Or%Y`^;k0*M4$8k8J1G*jt zU>%~^6HaBIFcw5aRrX4)H_9~gs;LEv18Bhx%ZuokYm7Yk{a`{li{KVR;-%!dX}%?*K@FP$ksYtD+Av@mRq$p<1(a+P_u6JAuTdH}#8Iv>RC5cfEtTFvV zMpnpk=r{d2tH6~yGa7D-7yZL|Yli6@<(g;VpTRX2GjM0YgwIE)!cc{Z|7|Y7%vjCg zSzek7bjLAl`FZi(z^<#U*+zLDs4?Fl8qT!&Cp_8 zhblkeULK4YNnKDW&_SpBs+3Q~xXRVjEDu-1kGL?qw-lB{q_!iaLM`DOQwrE9bDD8T z&TX4lnpwk0-ry8C{E0-XNcKHulQf8R%a~v*ia%PPi*j3JZ1SHK!z&(vTVpzt{MYdN zZT-wza46m$_U@PFOriv-rr`3#Uog0%|Bd;}>50v)A!d4qb!oOTWJXLWC2d>qHA#rd z==VVxClzPU@wtajzeB@+LJcb=pYQ}S`+_!uD>pkZ=O53J&@QeC2ymL+!WwtnuMHZD zb$U_+1hEqNi5IlzWQt*!%)4jUg|9zNv36 zqxwW(|$mvkw=@)-xVY(1cjB@;BSwc0>0&esz$`y)y^`*B18o1f8OHmLKI8x8dJ8F)6^8IzZ2bLtj?=f5IjO!L zX}Bg#6d2=IB^QusjhVMOPnqIg*@MRxWpsV9&|L7!QgrePW&KBAxnUs}gmf0khp@WF z5rlb#EWOIM$c;o(f40#d49j?E^=t))clNq^b!{lG5nMWJZT0du4$87`7#vT4-2VQ| zMqUoQ{bt?$LxsX;j4%8*p!WAwTaTGQ^IowNE-yTypc|KE812Ci`o97K@o;}tY-_^} zYq2u5((u3EK=^yECXPjnePDWpExeCo8-$R^aEI4YAUilX*K5zqP>y56g2BRT@l|;g zXtFN9s1~0OB}~}(mE`SFE0&Td0pU=5so3WN1OxJv%IU0cs=kbx$SRg>+4^-pM88NG zl}-88@5S7pT7mnx7Bu7a#%AOB03Zei;!p=yM6X{7*Ws0FXbt`0Ctd~ZIYDH&944`s z$Tul@_DRQWS(LlgvoM`K1l8gQ@6&O!Wp~T$g*?s%#0B;as8$X~v>Z&#t-n3`os z9W&{V3s@II#mN3B*P&LWXhWx282sL-_ExX`id_4nB~x*fVY5zXNT{7mk0#Z4`O>oQ zi|4nXc{C}J{3a7Xas@qoE|%1q=I=p)uJ{Sn8pXSSsb=u;Z;x0_%0BTM_X?AaTiq(a zjy=u_XiVX5ZW6>N8kzhIXq>t>)o{DmLm(~~D_S6wlVZFUYu{#mMhW{y32D-9f=6D` zK#UG6wS0Lzs+`ZE%zCx8SujKxWjmGFbcev0fKr=Wip077MpGdxo}5WD>r=jw(4tzT z?eT;^NC64uQ-H|{REu`zsSuwbJ;J|o%d1qS(rF^>L)TH(41IJ0Xtr0gSb4Gc_kf%V zF;vH!x6N98Aofjshc1C>D6>)LHjbLc z-@*Ui0=b49o9{}u)?qWhX%usy*N}oyqqKSaP)a+l#El25A-t@T#R|^!uV&b_l?H^& zyB<7xii=Z3!n!M%vqxn@tBYzNW|9KkXe^!`6RUD2rZBF`ClSI`cN#gX6@=s%&LRBD z&%{+Z)3Se1HTnhNA)?g_fpQqXbRv+ix|lV0Ynm47_5*P^jCCAzMJuO|V5`@AH&F~= zE_>kSFZZfvBvh;U@-%h8`Ee-;$DOPQuzo(` z&5(?xkCxN|XL9~uh%BAc2|6fh?5&5Yfh*f8WE&opa`W;LFZp6``BI(p^i3cyrl#pu z>2bx~@f3b^RP7Bw6Dli3!PRRZCh?e|=F9ORAxi0qcEk#WSU)qe<(@#m2q~sqPhi_Yw%ufJIp|fSzH*B!{u%Q^T+99 zBUjvy5hY?@)@4rM+D{~^Lx;)e7Ho4y5;z+-Yx#%`4{>;m^f$VUfQ*9_B>oFH4XJt@ z`YM5C3Nr@j4kvQke?`#YpxsUIAtf0k^zI@^pmdna@en|*BztNpv+jEb3$_@;yqsN9 z09yDP!qY^4&)bCX2pyXc@UKCofBDR@NxFsA1cmXRcYf?tdZ#5Ry2TAP=XGFy`KkFf zy&2OT>E_~xpvl(_xffkcJ7HE3(^=oaK1*wA1k3ZK#*R}o%LPuX#eIzjAY4}(BWZmN zWlN8FLjPvRb4ZU;tDbvQf~^Hrr8 zH}JYJeCNM`qB%XCK|%%EaN^ljAX1XW_ZUc0B>1!{(qdbxIr}NRtLaEL)>dnXY##TK z>XK$?zw8z#y{+FMuvv=)tv?aIpaqhZX!w__hj)Cey@vdo1oeN%S7q!h=fwN(FG)V9 z1(iUAT0(B5h%{qAIA=AP?i$wp)R;-r`RVzE8LZnyc($H|m!}z|qL6#N#@{3$V>h@_ z40xRi%l77g+|Z#uQlBQl|I@lGjgnbMj_WM;={w9l*?QYKuhtnvdd=NpOjuqijF=sN zNqE0s12@NQJB%2yLh#fOJw0DZD z$JGBin{GMKV)A7Zr_h=DMshc=)tGc0$bWlzP=`~`PnG*#C^NkgpfGT4)_#2_F>irt zZQSHA%gEvo8ei4}6I6(ot6}byIe-FwKJRAD5)CE!BH!n-7q zZydl(L0^&=017*)&j0+vWcXr~mAXt)7T7Fsn4xKWow}SR#zPy^J9KgNI1Xi|hsSNp z1_deA0oBhK^om3R+~0A`ANaEYVs44bW2|6Qpkja~?B^wboz6k zOxrQ#pl#-Q1C0NkkD`cv%5R~aBL>yNwwroHmpxgNk8RxORT8&5ZKEYleRs6@y=W$6 z?q*r3v!4_CKS~;Y_iHwHOjUMM08FB1GKWeZ>}mz;&;XW8>YFutGk-!nx~x{c&B?Ey zXj4L4+_#p7X0_zgE-O$)Amb zTh=v(XM~^Uz^1k;+q@=gD*l9g~*1)qZVQ1YK(=D!|S+Y3Z{u=y_ABlpRT zu4j5b+XoJ|YCavyQ!($y+gaOZr`_qU-_bTZUhQ(~vWBh3K39b;Ppu#@t6SRMH!}$q zH1o$gw=;e(6DdX$r^Tuw#e)9Pw-V;bo8>KA5is)`b#{*yy+^fQlEFeUYwxY1R1SiN z9Wuz=h3z7Y6>FOSMKVeIq7^4}=>uAL5IU-q{Csu$ut`Fzt&+!NDKeCNt zuVf-?uRgn*=NKbBL!Qd`;A23QeBNDGxEfggZ*0bOI?( z69*i8_ylY1_3ZDWYZ3mNTY2h=&x>b?4PqT2rh_B+B^L_%lpXs%ufR4DijdZgKwissK zkJB;Q4vOd{I1`_V{nZEbK7$5Q?a#WJV`=srV8V@5eN55Ou@dz|XPfB?u&BW%+0$TS zuffDeO|jW1i}zjCPcSMy@c*%C3=2*J;^8n&=@vh6#sA}&u@og;4xKW%A6lHj{Zrm< zO=tZuC~Sy`2%@dK>{1NQY+eSBS)|P2RCUy(ntc#_<+#^ar!JL3CD@{CQo8*UHudZ5 zVt07sdy7Lv5giM@1`l&0Wmr7BP_dKz7GoZPZ< z`Yh9!Sb{a5w6uIC<3tmMt+`-k=hRpz#e~<1CLVil=jPwtpm&MW|LCkaw3O*HnKPPvR*{H&~#pMZ6VeHLf?Y%rL|HvOJ z{A#p9e+GC6(49|3+Y`*Zfkf~bT~Yq>`rphTkvNi);`zAh98g~;4JI5`{*&w47a>43 zf)MPd{_DQ=lW}}vbU}eIxHw+#EI|Hy!TIMSA8|YO&!lH*s>pGOH*OEDGhxt+vUrDm zWV~ysDhgp@en)#Kew$pE0eoD|X}z*6R&3 zLdwA(X@@s}(OGHNpips9JK~jC*EWd^zM|CIiw(%l+=48eJtW6P4?a)3ng=QKe$g|* z<`s66FCG!pLQ&?vD0U^m2(=7uOU10@-6eRjYwP$hKF1}O&J)PweK*u_()RF?gCnS? zN8HiH#lX-Irhdhl;JD>N4jBbSfx%?6H}coq%T(qw7Uzm%e1a^MzPUN#%U$M6=!y5s z1DDf277i}%#M)Z)(Ng`Um5n>W>iuke*NKhpY-u<)A)hN6M1}XuGo?-Fh2*Z0$6jCG zMpt?$+`qhkuI0A*FLRNtlh@hpt)9CIqRs2;H z2$SKzoOhy+{p^aolnO`zOjW=@RPR*&eAev+cKJ~~8!qNep3V5gqz zS8Ic|dwIFayjczN!{PWKOcQ2eSER(N5Z!a;@B#IyrQ&QF*~~3}71R^o*a|4jv@Pdc6zUQZPkAFG63qGJ)090xM7i())SWJ4)XBeyV@FXrRntcXR^?23;S| z`p#~=Uv6%PO$7XJT2DM>7ZojTcR1TaQ9ah7)pd2t?jQb571-Thnms=53ib&;Zwme; zSi6N|Y}(7Aw8{^^Kp)EtPZ+q62Kwyv{C`}Ggl|%HjWZ^_S0s((z@tl)WsH5OD_tli zKIBa?$W8uQt9rE|zSa1P9s1`h)$?LwxAI~g^Bwmyi|ZmGB=j&c^2X~4Y^zJ=v~{ih ztx3{U|I^902LcOd5pE;ut}=*wwzP7<>GO%A+d>omf4XPdrdHh z)>F69*ts0J#QAC4Y~JjJ1OnEW*XYL4C}ex{k^AB*uu zgHSOW3ns5ZsDyTWsiP<4ETYy5B~j*2^#&!b?3&5eyx7G35mks3$dShJ5=utZ*e?mB z>2r%X$E7dGU5IQb;;PdYc^4%K_^@h7!^c&sUO%qUdxvqFWjV3)xcxBq6aD@Kyy^!cWp1bpUpQ}Eef-)Y%(GgA5F;NL&y+9S5x zeYN&5m$r*^6>kC}qMnWph}V01sz4qZB8rgP@1U&tZM48Wwe!(pj|Z=I!?<7U%FSFx zY8Mp{+18v)Wh#$5Ys60G~4VG}04221c6&t9Q!eAIows``p;) zWj9f2qY0nh*+KKOwrz%G+27o?*PZ4R;~Min#XX?FeVP|l)ktN?;QR-fB4euc#PPm% zZcRD}!fg%?=;Nr))hXL7U_tk-5B2Rx^6ei)b)9Z9D5>8PGci~la)x(tLQTf_g+ey< zzu6Y2|Fu*nW?YC?e>Hk!w@8q4XpQTaN%<9Gyz8Tu6WiCgfL9}A_xSiP_WQ_O+1j$g zbF%R>^ZYNtau@qH+W}jcmxnIU=>uW<)is|n?(*{a2rZ{vJkRUaJqF(Hv5YfNk0T6O zWoPTp2wD7Sbo#{U<*4qy>Il?LCY=3nk^ypbd@pr~lB3Wglvrl?N8P%WG|W_gJPR}% z;@>z9dVc1y(JJ+=#um2EvAn)Jrr?p~=+gya0?>*YnY%`j7!<76Pwx}A09DT%>GSi+ zOIsLU`%a3*X+D!D0*M%cOe$q62-FObzPt!Lz%P|7X$CVOoU-> z9v33K4n6AxU)Z`PJ}eDkial_%jLS`Aj$ zr!rz$k@c?Um@@O+1jOLiRiPLYRHL+k&UL7PYt7?Jd>uAFx!remci%XwB@-zNq2X)2 z(>&MJ1hsNUPFMPVAV|()i~`u&0Mz26v7LaFzbf6=ln>oDYYSFxL?BLytJbtd-V^5G zFh-4(*59<`FG1kNNY|5}FPa~*u*0a+RnYbM7~4&fTzd#mcZ|Hr;B~%PT$FpSJx?M6 znie8OZLxP%SF<344kbVb5<#o^DP^oB;l{TX0_eIgb~()&cP-$Wh)j>F=d2GVfx>ZN z{`eF}qffIRj5)36mwg}P>1Ur>tGJ6avJ?_IyW5CJc`bim2K2!^eQYtC4IlH)QZUmE*0qe#3Ot}~Par23QYirN(X=Nqz<52sfOn3cE&mBUp z+mD$Nh7@i4$@ABxW6)ulvzpPSFs>w3L}~)^;ypGYUVVC>Ex-8!{dM?qqv*tk!-wtG zhKtN+$dktc?~Z4^Rf}-GT`@@h@-{^GwoA^2jlgExGu&swa(o)ar-ftk> z$*nxy*$aiMFMTN1??;H{SLElY(Tf$bs1QaGC4SRePV%*As-&@N`&!#O0nF0pLXkPe z-ZBYT9!x;<2?34bQr;72jOd$VlA2Zz{1!VGrXY)H4{*S~(QT5uVJ%fAtjHC*`B}mK zEU1P|W?5zX1tGC#7FCy9xqw9*_v~*Jl4?jUu^&`=?_XWqMAq@r@;ICtoS`N663*Gy zm#X`xF_!l7gfga%<=Z8a>-9+7pHv@RzOeDcMKO%oy+JRVP+hE#thKdy{xkFb)b+*4 z-|3S)-xBt10Gh}w`g@Qhu-q2j`mj1!XXpB|E$ZZu*Lon*;2h7M z6LJ}m<1*^CexBX*und?<)+_&(Z*1U9%QWcbFf@Euc?^2YeP@Z6mbd#3oToWeS}*>3 zIbz~Jr62&TPzH$#Xf;0^Y*cUW+vOiHG({jRc;S>rwIkx|7^Y(4{;5|;mvYXsbd2go+ zHJB1LAYQTu*?3)~N>ZpcWw+nGI%^+WcInVKj`Es(zM+E4ZrO~_446t*+7Y$ zSDxZ>+(Yxa%q2Hx*Sx2Jh@TV#8*CC0^2Czs^_-z7Z+c^4tfDTi88 zQ#nfpO6`hN`eNLyHfY5(-yeHh_79ytnN(ELxMFWyKOY0ql(Byx56vM%MssG95t5ge zBP5e-AM@mKH(kB6zG(1;>IB3%_K(wlb5=dTD*xINeNW`o;wD2i>#|4Zs3rA1x1NDQ z4O(jbci(w*yE76aKJsQo&|)kOeYj%ty~u4B@P=RHUI5NeWp;NoFXLV*Ee21aP<@!h zFa(8f@TYa;T>?=nT`lw6aJcTeYb%kNWkTQ`dF~i=PV!D`3l}{%2aLY#}B#AT3bE-@x=mg-_(~A zc7docAOQ}fuzi&SmKE8in~H-{31u-x#V?zKM8F-qg#bsifrFIg-OEDr$thP+wblBK zrP|31ZDNUjqszxSGmc-dQ)EIS2mvVp6hb0U6yGmI-o#|IAjF`N#(WWwhDe3Trc_pI z#BCf9uUa2`;G}9L`8iPiCmTIcaJ*Jsuv-&^ZDa$Fc7j@d+V;D#`uw%*J^9 z{L}PDm{DPR_S0ojjKe}|3wnXM7(Zr0S98_9QL8cFdtu+|8z{j`v+(`Yi$$Mo2pIa- z9gXv2qjV(r%hGtz@So?(Rw)*lqNq{H4x7>9E?%eL%A+svMGkSc5=NBv@wqNJ*nyd~ zqqYbn9;d?VYeq&!KiMr*$DgXJsw!+ZL|U#FEg*bep9AL5d*v7! zx*CxBwArkI2IGRsPgawtLMw{z*x1;y)*|yTsTz3TWVpXx5BXtPyz^etI4j)o2G+)1 z{vGQ$Q)XJQ6zr46q(pk(TjcQocjvOLs~pEA%7|i}FlGX^?uBA+k&f61ddn0(B)#?< z+K7}d#Exs2(vw&+O8B0!G3zzoCK?Fo@qY+koHTU{ldz((+4EX9n2Inmro@End}^}o zmLV{@A>nIS-Mpe3sYk~bAT8bbJA?i=M5e|h3;GGt5j~YcuZy1pMD36mtUDD@aYZNS zM1KA^a|uIL_A|#Ts9qtn@2f@bKdbOlR-<@jBg-_M^uWTt!Qp=cEFAZ|+KI_Nsq*xS z%Z!@P{1_jWMfu^UXeZ1*MXP;hiAEo4QZ}T@A?Ibb)f!VI?H1R9i%H44*p9!jy}I;^ z$u#(^>Sv3G#;$^S?;YHPUH@qce@~Mth$cZ$?L7vj@sH0mpF4ka#rhXOi)FraE`2fq zPcDr?4FzMJm#8uM-dlr&pO+Y=@+5~2iWvz$=Ow4g#i3a2dJA7Dd*7*GBu6Q^^-)N5 z`3-)i{~eL8*wS4*jEswfjo8KioRsvpORXT#i}-6IMN-OuOYEQ!uB8dW&F}Zx^{Y@P z-%|Q~ndCVrFP4l*xa$h?NM|A~9JOVTapcdUUArKfdZy>*;Gg;J{)(wYC$pI;g3E6> zfN|^5_Ir3*w+cXK)<6|0Zf}2z)OUVvudJqKaIrH2;nNe2%j!c+hKCoc=S{8cmtGUV zlK z8F|Jc@qMAr%Kd7m;|B`;ivY8EE+ZU#=|M=TuKGT#1D;Ew@^j3BpgBlXjlI1tkDJ=|E{yLUeE2Gc-6TUhrcfKaG@ zNtvgPZNZyCh5ft7BAqznhA+hsW(j*$o03WP5Ump8b=9ioGJVD9R?t7q z@AX=J&5~Av1`ov+*h}GmBS3`<+)P}qnvV#{J1&X{m`qe@i|2*1Y}KTp{^`0Z*E+37 zFv<5brI5ln9PHVK2>9vC=qgDMBbh5(k})+{*@eGXIsOtTs)%Khg~ZwwZG~gZUmf5+ zA0pEbTtI|H_#kMZ53!=Jsi_I|A}6Jgp~J6kzJKOK20l??(Dyb1kG1!-?%&4ELnWx? zI*t~qO^V%?4;QMTAuri2W`9m{gpmaExSjQs;T&51>;2(Q_s)Uq4;JSf+vcxv01M;N88;gnPE(rBmWE=}+ndRw-j}fpEM0 z!R=S#EkF*f)02w6?-Ra4DJGQBXB~OIf%ki~*&-!ZyQ4JlxQA))hFVTJ?Iqk% zOvAf?lFLZ!V>YE4nvfdv8%A0^BH8%L8aW2@J{bk+ z7>-BCW@Dw2#O!*xH$hg#U~|!;T-@5a ztTz$9-eRtd%%Zs%ezMzR9p{aZwYZ;|Glr`QlrCXAYOY4>s1~4kq5J6E9lL zBo5M3r`=PZP-#|h4)Z9dE4^wV9U*R4sG83%!zB0|onZ&7@8`lM;+$r7kpynt#oCZGZJ$ozuT`C*x$*O!E~u&zZB1k2$Q$m8F!NUfC6u&qQSmMj_(QhUX1J{Zl-k zIuW10i}s_QU6Fc3x%${Rs*6Xp65MSk2P8a}opZ^mqL;~1H(Y+k7|?@jGnFu{A|u*!`!VZ$g%m3WgBO%dhj6gtxd+ubua_{@;yljB2_CDy zSQA<&#+O*OQ?0b!!i~~Od<0*+ z%Mtfi-+Sp29sysQNXF{_`+()%W4wQD&h-Ni?xy=YqWKpMOz1rvC1vFRm10%Mj+ls} zuR$mE4!d$21{vRXlF90Md3Y+^Z>(FMu9t4lqP-({Pg*bq?*`<*))TO%TDzu7OG_*B zTc3JeU0t0%JSFlpMq#(Yl_V3Iwcn4G37vX$P+c+H&h3bb&MGs%r~4uUK?I@MbblKD zGQAm%8wH!iAR~_z6S9MR2^q}$aQb@DIKzveZk%ocZJr!D@-UA3;2I;|1=n0%WtUj< zo0}))cuetd`IXES&2AiOTc+_L5m1f&nHaWIiJl-5LKXF9)a2A=geKa{lx4&fg7?W? z@$7eQ7$@FAcI40JI{Jp36@2c34a?~B6>qPS(}(cHzt}l7>sJwCj*q%-n9MsN)LPUF z(G{`S&ZlUZPdFwuD8H$%BFzKv;Zf)C_qxZhgIO(DMB}ES{Kvi9h^#8**fHB9T;;_R zAg3RZLnyb!l(;QRJ^eCHqN(3u$%<{lXpX|`Z``Ym7?!)5^tw~!SZ*}&I2wk!JS6MS5p2vd3kINfM_ob`wvS1%p;vTr`z z->(ZgL)lG;LG%Nm*Y$1*Sqs=Uk(&iMMb}s7Cwk46?iz4Th#u+L6Ps@xqY4y-aOo#pcbxx zAGVG6tS>;qTH*C{AG4&RtsU|B_Ks>yE~-2 zySqW8ySp0(>2A1(-~X<=E}vWrJTqsXz4!anyN{dDlKbhpz~OwAP`%VtzLbz;18NG2 zUB9L0uMx&n#Wy znDe~HJ6?-A6c5R4=p$T&ee}RQT=h;~%q!GxK}Sd%%#)b;_f4XAH+ZV*#~^|+o>I2+ z<CVgGGgq zeCVg~e2hHKI!PrXhI@kwzllY;4p59i_k?j$0?&g&v;cB44PykUybu~JX z(P`NDam3bI9D_zZk{Y8Czl#eO-KS5!^-KG9U_&x?c6Pmk*|O>}cIR{bMomV*?)b#W zH?zk2 ztE+#Jo;ISj7;9-2q1G-BYcU;1tIhVGfcfuR-|__QKRL1%iy)ADT#`!VKqHEzHg4$) z!}Y}oQ8?>4&Z%Ddq~JE+=E@!t8miQwvHw)Rbd<y1+33cT_94x)xXO78Jl{&r zM}2p9*XdA@o2z>`|2&Wq9v(hlV-#7rqET-iWzqNd!6Km>RD+V@2f&R?ja}}zgan*K z*)~A123o&3j9cQq952Gg-rQ)3MG_&?qp{6z2z7V{q8wRuRvU!VFfoZKD`R^-2Oomw z#$6WMfJJx+v|4oYvZWvcYBll1aXwY}9x)fMPT=)TMmx$kX=za@DXDKqM3#@YXWzbm z_nSND8I1d6a6|j)laPbMOSg314L3VGPF`MK=NyYQWA3!2cr>$KFA~g?9%@@#TlHSN z`cj+a3YVRO1K8r``e?}pI-Z60KtW0QW4X~rV6p76MZU!p3p^%6VB9da*A;^GNuQY2 z<=K%jvL#9)x8-dRGqbb zbPD5{?&K=eDDo&#K^#atmvuP?!m*wB^sdyTu>Ll4o`inRUmj&B7!QJpFhcZ zBZ*OA=G#5_{v8~M9fDw34Trrb#Es3&6iQDy#x2{|B6o%o%*-8)_c$HICIK13BjB?eNE)B+5GL$&;WOG!)CSY z#gu;|Nda#9j*p=^uU9OD;AxMsO*`HF46blUsCF7MG% zX~4ITb|5Z0TCFvSF{d}QZgF?t6mRb69j~o--5HEKbrFkr!N$VM%FN`qZ;4yAs?+lX z9UcGsC;uI@tho4nckpE`H#s>7V4E;rz>3gY`{SOx#AD4fxwM2>FjdsDk|P=}_~Qqu z*Os2A%Mt_L14dm7u;Tak_XFx(b?FBUYeWn-KLLgQ*MdR9M!M^J(aQ5-iCp@A+ru2-Ql)A&|H8_TUQ@G8>k>^a;x?ywm(;8 zRvUns7IQoYX_X?1Y(5V}KtK?(Y^bZ-f1ml_#=C%s!f8uAg_$zTP79CM(16Ud|Ao94 z(=>V|xmP(=c6}nY4C}C|`6sypQRN*!ykWw1Mi{g(mN2>_Cfov@qyx2m)ceRg7pDy2 z`#$_l&hC8k?tb9Rl}^VcXX?Byz1enp@=#hU>PWJ1AZ(|M zx<$%}-|PByb*?j9Q(W!Cd;L!w_jc<%3O3GrE8wSmgyh-Hrlj7Cl9ZgDphxvj7j@9NY9)y^V8yI>n`1HXKHusAb!F>x zqpJ}>luA6ivl>=C77Z);cTJ_nx}rZTP2Wu%`dW-Qo%*JQEUh*DFkN5M@pLBtml9X= z6aJ)Rwu|_9r_FHyGItY9u!gqN)}?!w*Sc27XX z5C@qZ?YLlcr=A_$4(#vfsaYQ#1?o<-pAwlWq*0x$9J|7$p5f=Ht8|fB5%J&%%hEezG+24@k zc1XcTonl;E;X6;W8j1| ztB1wYw4RO{56@rPSiL*psls!sTRr}sF=LltuZj`+zX{ZPW~Pw~&&{Q{AWb1GDqrO|~#kcXTHQP-ZO%76a>xWiqvk5{$Pe%uP>_4nBE9YXO z`}-Fg)kdZh8-!f*G0@tLB&Ns{VrIqh$(g_s9o5LuA7(B_6db3+34MXB`RDFdRx!wy zd;opRkB~svPwYCf*zXKyvcjv{7Eud;_iQ#UH5p=hJlOE#d;MAvs>#d0~F=e*jtT{Ar1@T7fI4`(K;w8PO9`uV0k3)1l7F!q5rw13sm<_1d zpXS;t%J{rqVmNWy%;gy^6CreO7(y6zoIMDy8)!3LRy_?l4Y5i}A~@Cqtt@)Zc?Ok; zJzF!8enn_?^`_{qwd=lDSaJGSZ3Awgvh`_0RgoI$gG}XYH3*BBUV3hjG#fe}4+RhP#^K4tI%v|7Z+7$_sb~w>+d}~IuzvG! z7RdJq8_DaU(u-?KA9A9&07-3yhaEbdn@A^xml|KC8!jllK=n-->i5dlPjUk&9Gb(`UAVn`uBRxDpbr1AW;mvRe-Cn$kk>?Px3di(ZS@vDYc`&CGSD0$ zVrn<{gd=6_FX1yhsPbcO(x;GJ_ay0)T(|cX6a|EVzF}|knuSV^vl9x5@s@AkmXwb0 zpxGW$QaxEt)GnwwCU5AYW|+M!1%S$bd)kF+(}m2w-h-oq1bpGCe6#~WE&CZIr^Bkg z-$~AH3?tt5NP|Daxb+`ArLUL$YO~LAXm!wm%rsDO!oe&>mBtUpm-*!AgGu`x-cx!D`p+4qjS)lTm3h-g187Tw%7a_&S0!q59?h4s(qvpk4yY7mjxq?WiXSPgo1&&)`+B`ro%KoD=oCset<)h0!`%KH8Z&`DL1TU$A;8Vgi?F z=0v=h`qqdx8O$b<(N`)=?O|gHCz^L<k*uVVM)tKfG3#kptZlfVjapA$;`CeWT}T{OqVh zz0jdl&h7|%bl|>9VrVUlEbu7<^4ZH$j+U18HPvI?N9ee|Uy#u&M(pkfgo`t4YB2o$ z{S$dy*~;6WU4}FGh>?+zq5GVFpc3N2&*+f_X%6auE)NJ+mzS3`vNZ&ji zgCGw+p*zc2nO&#V+j?~@LJNbDYQ?Zqs#%)iG%7$MpljPqiIod60V&G(E z)bgxnsyi(bJ^Nj;3^cDE&;OC$7~w`QhMUXoy97d>UrRa=G)%C@sbf+S33jBM;5bDa z%;>`M&w~n4-n(*}qc5XqoWeAdJJlC9pD0!$+3oZ>yL%|*RR`XvWPz(V(to-)(MdD{ ze~A7zcsWY-%~fQ1RRWh`Bmk%l#hMU)dV{T2|LR2Q$ro z%E4&8Strug=I;KbCMLs9$5tu|%>PrXB|j-%;>+F5Jn3T5jUJ=y^-k9H(IcH3*TZ-r zRf1iZX1U->btcT(@`@RZpZia`d7ALNDb2I|jz}+INh#h$qr;r6=@K&F)X^E7?`VT? z)#>QZ6QUz9KG3c7b)-MONw`qn_GaLiP#70u&#rGzJ9yps&=LppiM6V_R?F~F3vv|T>f-@yT^hmh zjETTj{f>29C^40eeuIeIUHwaNK|?7!p3yZ**YioEF+&s6y_zEuLMAJS2QO$;;Fd@f z{{N1rD^TwNKj=fFJAe_Oy!mSQMG6IU z$1nE>6*+ZvSTMRZ3)ZX7d$^M*A$-YipgxGn_1_RXAnOsxLJa{q2$MFw!M1+mNa7Sm6boBePAOwAzF{ zrCTV{4=EPQxxFm;6Lk&W^saLB5DdrJe^Mi?zgwqKPzGuqUl>5&~epUJ6= zFyxFs@<-}%J05qhIIa;kx&uTUSN`WFs^=|ewp0zH(Y*r>2g*wYllp6vvwvWq!y5z- z19P+H$*1jcXRzSjrp-j;0?qn+R5Qkl-_+C;Q0u!H8GoB(ELEKT0a)tk2Ig@{m&zd4 z@xAyw_-BT})#y)%rC*K{mnXx3q0`emlGkU4^q=H<&lz?_6rbHrHZY2uabD=&6e5O6 zM*D4kVRvY-JFxUsj{@weg9~LtY8p#PM05&b&1=ub*Rsb0F840qbRWM+54`Z9pWfpF zpf&Lk2U&~7DD*NjQtEBp zk;j5XLHK}d+z-QPJSZlyZFK6q2Zs|3kC;f&jWJ-9VM)1bXjdajS)9lD_U=&!HbDl3 zV-Um)GXqy|wki8&jTjT1-cQQ${gP-5eFHsv;FPpom>}wWyG3)4%Pj0{=(Blpm+J$) zV<4?!EvY`$w20}fA7*aY z675L5Y8)TJMu7)F9{H85<>dbAz~<>{?llh}5V;R9sHL@M?6td5$2T`v*w~xB_*O{w z9OBV$UbI|~>OvkUDJeJL`ECW)uRm3^`m8P_j4wmA{Q7yPRV!d7K&8~|6TT4XA#vyZJx9Wp`|GICnGB%>y zpRsjbdfYkgjy(UNq_bltY_wf4_UWy8eyH%=F~nr#(y|9kI!cT#?t%WoP>Qm?iR2E> zJZ2G_vTd_`92(xytx8&y;<_uRjf;ngEOLB{+bSVi_%aa=5M~w%!6;*#4r8xLjCFKp zJ*-YzJd>+u_EbQTKP_op-*@#j@)rFvST#t8RU4Dah$G!R?_R{n`)UU6TydtVdN7xN z0u6^{jd;I=ZMNVK`SEO<1;a0rI1nYhY+Atb*4V5SPvoU@@puif1YQ&23JMBUPG>*$4F*szudc5*D?Fb*Jp)1FpZAyh98Z^1p8?}! zdv}+Nloa-rT-TXm0a7a`ppVm@ax^T3?`3!rAt3Y`SgtrMSvc+IC7c3C_YDk?P(N93 zyIJj0Qql4UOs~V`CJdRcXWhRclP8T^DBn}qMk?84A1CDhsKk1&5+YJAW2MW;eBeUo za&?DZ-LKa!jW6K1WZD85A$F?0(j#e)^fDUo=(z19q1i9)0AAret+CmObz6RUjvzfy&UYqI{leJS zJ?r0FWJ)Ia5iff(bziti(V z`dNSDXMF4^sJPZ-r^HNn48QjAOXJ6Q_u!+NmWLSDRqPILDo$@x{oDdR=|<-Zsfv@7 z(1d}V=u2XUXMmD;idt+)6=!gi2_{LYAH>PLBZxP+J>x$383id5BPp=G6}#U3!C?XE zs6#?h@~jh)Nf+3yizAwT_Pj4utrBe1@$ldU>~-AX6n2>zn;F|C&D%Y`m*BgLJ-wsF zy8j|XdS{zG)eky0Jy=2#O$z$Cd2nNop$?+uzzh(?cFbUE^)}mqjOQ2~iPl9pxJJbp zBhudTHId-{5-r$z{DG^M4Rgpp8vzvBiN)~whe-{N8~=t4OS75ffQ?k#A`ZLGU{!e* zwD2B->Kr(f6wFDukSWV9D;%Ybft_&GwP`Sr@0t3e&qW0rZ)RQTRNUbIlq z!pLVTLTt3Gdrg_`=gz8ft}AeuGCiSAG1}O%%mv43=&w(w!-MXsH5JGU!P2SPQQoX{ zaWz5Y;s>t!c~@hwkb_Xk)BUi_1LRE5t2~@kdE|URFlo)kZKzYHsnoG^`Dm~tc9r2c08VgBRV=STCZ(0{TvPgnTu~RQN%$-h4 z-+yf}C02&ik`0*jEmucvp-+T7t=Ryq8onT0)Y%Y&cWH*t*}+hbt~@asX9B@6`;Wyb zBtrjhoUmQ_TVjncRgbXYzUQ&zkNgdpz+RE+ale0iIVCeOLzyA2Dl6+{R?&uiv-}G+ zIy%~ir~-%tsOY#uc<;6`%$MpJpnsg5o&W26Sh8v-Tv*smUETo*BnfkSIO!h)F!@n0@Sr@{1N`v!bIGF; zcBYJc8Jowb-2+jdCU{jBH+<)>4_>l2b{Z!B*yF(P%bX4Jwt$xUr2iJN>-Zt;W%y7l zABp93HaC0y;aAHZidd4S!?StW_Q70!{701}<~Lf1;Z_Es$^vI%D;xay5myg;stbGF ztL%O-(h^wVU2e!@5Sm~OfA5Rakjin+S}N+|gRz#XKydymFlLr7aE7tae@Dgwy_L(8 zd*(ZyTnxg?&cNO6`F2zuhY~{zb18E6dm0Hc2tUrjo@bS)VyFA5k)@~{9iYW0uTZQI z)Ia}N(p}p%Mr5OGA*|k$pXeq{wEN9mT47Us%Z*v!%)Ga4w_*`$sLpG8_)^*t_8w=L zAC-}HBG@X`?$Pa$N%Cg12QoPK#|yGnBb-3Up3Y1+Ir0wSp*`!64M9bEq%ZD$-W|Ds zBwG#X6A3xA8R5kc`w(6a?SB;7M>LWs{ASe^RZB}twb_o=;bb)&uv{;J1Pt&z0S}O4 z!w*AOfm4Hzi3wGP@97InW>FD>*=*@6`m+Y|61Da9WSpG13kwUcwz;XP=@-<=JE8s$ z=T2XpZZ`tYUYiwPwP1(i<>1|2!|k1&A3($c&{*p827Bc6i$?fW6ij()kuI4NtX1A| z+4aujL1D&S%n9wvU@vvOMVlbCD`|v<>J8|SI!QUjc4Yg-WLmQ^==;|+jt13t5l2BX z#;-YGwuGrzc^@*vw`*a8nBy)2I1*r&Liy#v0<{NqSImZ{BlKptj`oebR3SAPwNPs? zO)1Aa!!KnAdg_cIty4(-5{&1mJ|!t+4TtBctk5o76Tfr8Q|@p8O+QmiBU24oJbJxW z5{hu1VqAwHxRD6~X+={szTKlb8|Sfc^A00H$-MZ*mY96w%Lfu(45Ef5erW*SlEN!G zZm+;ECd`fqIxhN7Gu*T(P%cppO6IeBVIA`+@+x74Rjwt`b!cucTqiX%0m>cMJ;j)?jGQ{cpkwT4(cy!d_-g zw-Tl0RPMxtNCD(LEd5SQB9*{x5nYtltdeFkq@4K${AC6$ zG-H8NE>{?kJiP2w03ot$LbAj1<#qAooRP*uh)X^>JS9;nHOTC{ztbs2i@QAu>j?hs z#W9bsrxRL8qMl9G!D;&@6Y5Ao1h%Z}h5|R_yJ!Q$Al&|fopMo_l6;ZJ0rmL#{-GU8 zUA_yU@v{7j^ZlgTP~P!LGU|VuEHxRrY>HeFnMXwWM^%s(t?t@FNvb{ih#=|pPfb|G7opE9_K8oI=_ zBw=R6qhTYTnht~Q^1*B%?VD%?yL<#eO$6RRJMQD`B0=aM?9RhxA>(Om;&UQ#(A!|f zmLC~B@zyv~_n+(41M(aF2(9n7zdqisEg3YdakYHAB`~ET-`~d<@g-q1*}h?%M!Ez5 zmY@qkPr4-a?&eF`3RBCGUvw>VL+{7z6EffA#RUoy?tx(6Bk~gT*j!hABGO~eQkJNV z;-b6Thhq2YrBUJpjNMt;+$0-X#(Ua^ew6`c(^XVyOo~a-%M_kl^#cHxHQrd_8Tpfn;g(1cs{Fv4GSAXHk_5wVtZ2REO2v#?6f%Fu{IwmH;& zfw#!qGJdU&NhRfBoG=I+V$9(^&ibaiPFKsc~UzlrLePrF%0zwk}b8 zCyaX&*~RwrJmKxSFxHbyF6;OXRW8!YYKdI(#%J?Rbdh#osPsWlTm%$F18UJsk$Z$W z{s!e6Z0u-?9}ePptMg9Q-SwP#=NJrv1L~0?H6aQHAgEffG|-qJoGF4S9@WpkCp?)o zoqBQ3Kn@H~8t!8ZfR^D9r17}|!{HYxbVZ{EKNIF>9`rg3{-?L1C5`SQF$7^UOqUCk z8@3qFN-;U_YEp4L5${okfrt|N^ zz9IO~YDy8x<)g{74$uUNAbqTL`(3vjz;4X@tFk#kJk$eNlUvc64vhqCcCK-sNWy@X z_n7GN63~fcx7W{a&_C8wB1Af3mZ?GCNpX+2WP$z_1>d8&lHjJThKJdCgbH?zuMYE$ z?#-a-AJ%)8ak##C=cw%GgAiJ0r}BDQYi{m|U}7d3#3FampsR~^)h|?^&;Y>nKGMC4 z{WoV4;3RpD5n$B7N>A*iQ+^Wq)m18ZXnx$e=x*WtAWb9P6Q^)taDyYoUpqMVUCI*O zlG6tB`SNb{uX~Xt_c33M=F~O>5cqU~=@W$zvTw~=lw_v=clk3NW20}V~bzyYpCMUig1Z7 zb@A3JxUKBbng}=L+E01IIRf%#h{bdCeT|EG{T9nP4^F%($X8f;RX@%V=9O6y+!=AC z(|HWPof3S|$!vsE^Y^V8B$w-42@;qnDZn8i@9+jx37YQ^Mtpf!+JjT%%G|~yYebfT z9SW|aP6tzljdFG`MhQ15yG7&_{Vs2z&t)f3xKDyW4gG-hmNOqSf88n}QpiFG-=&Qg z=vV>Xnb{o701Ug!o9HYzBN58jiZpF6IIJYqmHB`}3TmnyYVwIZD+VW?pFnk1*5V+= zVGWV5vhn2Bbig;nE+C`z$pE#Lvcb}*Q*azPK~vwGudYQj3#AnfN(qra4z8jAqEDu7M&&BhF$OYg-9*#o1Rszb+1MLEu_Qd`MWUAwdaIPqBrlM zD|-hu5;Ej^XA-{6zVqjVjg}2kvBq zB*B|#=pci;rA4;t2gFpFNob&6suGv^L$#G60-JQY|42-J4!N`O0$r22?L=m_G4f@H zZ(lZlJ}%`lrMOQQmA@uh7T`AO$n_gfN*<6XaIlV3iVI3tBf6?LLwFbm3~=gy-8xJ> zWb%0twekS8D|ykyj;9YMz8rH3uW($WlW#GIcg(i|h=|xMempYsO407*@iQeeWw8mJ z;-OJi?MmDXjN^q@*6<-q<}gPGbUr<|KaF(1jo(Dh_;|n-Sz>H&8Kt>c6CbytKtd=kf z9S-@aj|^JOG7bS}&%E6Ur@G+^sBpwYOkL4Re0okvY`tu^zW#@L=p1q`=QNP??dzW1 zqp3;CrUwEGn&kw45RDh_?Hf_MDssGaq&O`xn3Z7xr7~~fnpI-TeMSUzGeQb3ivS~+ z{gHJH96REaTuYK@%H^I~j{^Dx@A9le-NNZsBNr;FAQYyX$Ex^Xe1NK8 z65hsqARJE2G%~yWoI1Vp@NjiHp!5 zCnGovgG#7+VSIH9F1}pOEzBI;yq>MC325~&T8f=3xiFz!R00}AS2l)V;ks7M6wK%E zY(_fpFc!X}!HhNtj%An6$bPVP1;`_5Z6QlMDEO_s?Zpdw1nihonw={@y-_zZBVjX0 zAtzPkNS7ZZ8vE1(jOf!}1OGLW?B)v*JLw?1fp0p`TMAra8^>@Ey(9;|~u1K`u zbY%BYHy^&6)iR*qux=FM{LA}MvN7~OEO?_>8|#l&p)xXwb$>5%+oPBtZ#`#y_)T9Xuc_8EFh;W%RsP@!Kj=-oczG0t z7+6xq8o;Wkri_n?&gA)52gY?U%}~~#(-cS(lUOcP`9a|F?R#4fb{eA3AReyD(l0&a z?FhKgY~JvW^{i<-p2PH@TC^*n0He&B=SE96_+YZY|8DA8%Taae`42z1*(vR`TmTpP zVg)z_?)AjSK$gdHyP%Q08tg(352R~4&t-nwK)s6HQ)+AhPWJtksWPZ>dO!HWr3m}t z*>+gVWeQ6oILeU>8%)0QDTiqe7MD~9&x#y`q>w_ok?eBz2}6IqdkzYg=FZ2a(o+&j zIlLB!qb;;LmcP;@c#APbAX`1}O7|}^ESZ@^y}2`ME0ppcf3Ph;zv0XsBv-3PPs_y& zo3=SIzf57yNALNp9u@at@^cwm(S*6_s59q8$hQ>P_~^+TdREws>4ttw$(^fkx>R3& zOwLv$GBUi~cJ2t{MNeHegNhK_10HRg--IyN4Od3_Vq_qmc+Qp<<_BMP-{YyIM88E0 z>E2)LE5X$5PkL@1_f0}Rdw<8ntTC3y_2rv_zEqvLz#ErwfM^BDNPfB)9A^0`!7L3|weh zOt)(N_dt#LS=!c?egLpok@T=Vd z%Z_L$-~ApodQly#!LxP!>(}eHjE$!YMln5`q|KRnns@HnQuT*>+mC1GzVt40{KU)Y zs`ML{hMNub=*JTo-szj43pjp110)F#D$Q+}kWb3wtZ!`vXoTnTn#DCji6Ug!-c2NO zl$r+cz_%dud?)8fakCsvF@Un$a)dsL!ongojw0@@z#*Or}?atQfOSGH4f=0|3g`l8pILStgsC}R<1aqItIQvT9Mi8uMn{+s|yJNxhMnfn@~;7h&)FYCfvVHUlU<(_=Uq-syEqLjO*b8_h*Q+^RAzg!b&spHDsq{b zo5oRs@HA=wgIBqc3F3r4jlatPjO3f0CHGJI7-9^wqAc%!8#tf_5`pk=7q&!fl4 zYz(7EG5FrGx*xzE3@Dob#`Fa~gq?TI9@CwdFCRO9{ko~A^ZieWTdm0eK(i%!MJ`{W z`od18R|?|ESUZAWj?G1lDo|t2W6sK&dcHwuy#b@zLBL85D0{(em;g3Eau91qNH!*P zx`ChN$H|y*dU|>Y2Csl{q1cF-+(*&H@;B=Ae=Oe?Oht=bb7b+pg?os?tFJzXV`1z46dn{HcF}RQv zw33U6mS_GAGE6`-d2UNy1$L2*GYQ&K;0Z*nedQWJjTD*Q~Rwo zl07jAm#BOXjYn~$DhEh3cCX$Mi%`c~N1_lwX9J!xuI4EQ5>H^;C6Wu9+@@@jB&c+O zdm`hE5@RW53TH*i=mWoo0;Z72SXO|hpDLHDf0euiV<&yPpd(;66|PXx_@I6Omx$_d z>Ey0DHJ@+l34y)z)@_|wSd21MhWT~SV=3k=F9ZVJrlZ1PYX`3rwLOn|T&|FKE(>IcP`+?{oq5K=zh_x)upemUKGO~q!nmCB3aJ1$lKd{vHy8$-k_}hV z^#Rv+jlyC&)wD_;0Syf;$)B86SfAEn#r<|eW9d!DFPM4PT6{haBW@Q(eGky0k>0a~ zNX|bXaS9}@ZdCWLwL?XChWq)~&i`ikNcTNDZIF%hec^h?ped%(Wh4z`SXP0)#dGvy znBTkdFFb4vAgw(~_H3q~;AWf6Cm!@GUr{)hVfqcme-Q-O{ruD{Z$RV|-V3I}z3VFC z_z-tgnWUiF4VOh>;eVe2Au3)TIKY8i%bom~Z+apWwVu6%D_}vqn8$rHW+q(^*17JW z7?|4WUkq_`9Huw^x@OQ?u5p-vQ7|#hc*`dag7DQWIpozs?`Q8JRemi24!BQu3X+mw zmtt{TC|lYcqbb$%yQR!(1cF?gDLj(;StjvYAPf+Zvu7flabc{pmP(^}s}zJ%iXtQ& z^%u#GY)kEEk(sE{k6Uj0RVRzD-q8)*tY33))tLD_%qTZMv*)X0ea-rt!3sb#S!S{i zPaHQnJs~M=4&1z2*4p0!*|;tMK34uimPP(xH$(y#KBsQEHeb&S5dQ>mq0&dVP{52* zSl;`jZ~bcx zWbt^h8wq;b8nEzH$ej87&XmZst{FV5FbigK#_d6Ko&wRMFmUsW?F9s*OmJ&IXQ;!AYlHJy=7++9?izzvd zfYu$-oiGXez3DUI5eQO=3Yy85?K~!RyN&HnyX3@-F#UwbyVHHW+a&>gs{eQ%;GGl} z7QP$$rDQk+?*t}@qdnnGT_8Ou=Ou3S(e;Q-z=d{v(`LeUYZSI|jT{Oeli}gs-V(D1 zyZBXO=hXYT##VT1%gK2o%;+g5M9T1BQ+%^su<0AfBY%^pA~U3tcE*#KTjR$K<7Q-u zF!@!;D0hrT0%%eA$5=g6;XNwAj8+#XujzmQguoYV)t&&73U&_|F8xNHTwvf28Sip_ z7MnF_5Wjsc$|E1O`lA>VzArMUHlg3jEyE}>S=q4!gkc0q-gbYw_QV`!m!T7M*c`{L z$2gC%9_U_vS4ZPg#EG+&CuH~I1qa_UP0Me2JL_q@ahXDsO|1!?NF)NN+Q(C(>8Kff z7aN70fD)jZ;2ZQkAqwq}EenDV$xJ@zC{c;vtLxNZ=}9_o1~c=j1#pZ+_+uYfxap@~=)%HMV=-wrkuK*m_6SBV_^RvGdQ5J&;AU>! z=Hv+W4|}HNXcN_92kou8%r&*qpPd9CfTQZ;UdEHC_&W?kauTWJ{s-mZ3r(V&3DM)T zkEvVp#XASW{m#Z#id5C;fVTy14nMvsOto2`Tl_bS@8wr+pR!HeGj%IW|-(Qu1Bsut^x z+td$BnYPGw+Aj#fe-s+h6vLwJ4&X-NyG3Bqblzr@O0c5KCTF$1LBuTqPA>_iVwQ~m zRsrOpBLV)zqGe&h0HZq?OPkM^ zK*QW-f*2yMY1zy=EhJ|5FA+% zBpWr>tv&)zjx5`_^EtBrqiH$0-g+%ldF2avwo}jlRi~zabWOlfld$)`6g(G@LGT5W z0zHK}DGTOmj%2-B_o_r~Cd56wIc7TLl5Et`79$fz2_4;-zkw zW)m@GnWMesHwTw|Ch20RC`Ch$&X2IJ>Yb1ZZszJqSD3C4{?6^ZjLWssAbbW8c z+*dj|;xdaFu?L*8z)8n4t`Jb>X_;&MZCDl`RUh2!q3ns;)3FEje9ER$Z$sh(utHQ& z^1!4zl_Cc4Z<7wdEl>-g0TFsJgWBe{GwoF}WK>Oge|uY2L4e39vr+pC6@mNUj&<>I z6I}F&VL#WLD7^X=xW+bm+Gr+4saXv`Cc(aVivV0$UYBsl4neX5@RQjcQj*9K*CBmZ zq0Z~gGglXj<#r1pIFbQBJky&0&ccF$`yTH6-^Vi}6QD|e`pkXMQr7oL8`L)Df(u0# zL_Ib&R6todn14nRJ{=L4B?ehRjwRytB;K^37(+8L}W`Dbp_#y;8x# z-BJ5D>JO3~2%lwh{vYabm_FF0Is|AKGR*WeldjsV52f0Ma@C_v|9L9aEE^5W#$0%i zoZ|Urm!vX6f*0g7=5k+RT_uRk^EysR)0zi8o!#QVR}PUP$fh8h0$#n8nVCsKKbA)Y zTA_YdokCd4yEsFQlBr>hY!@i?{%+IZxLqfZp?|IHK3#)^kh^~I@T^q$&TAJpF3DTZ zf9i1Z3&p_Ow%$F;ERq?X?LVw^HTscNnPgM3^|1GY2r25FJc9tYg}y{4(kt4}4@HDgeJ4XjRV=7Vg8uqBWYu1Dbt)P4F5fNbxPM6lD9k zzBtqj4FtxlP?5$u@pqIT70x%R+qeR`T5^kjjejlb1Sa9IaB05VZv`75b1WYDFEMT` zC!1^X@UT#GHw`d;wUdVPxPF%YLU0ry_2!icrca4Q&fgsVqpx+i*=Sm%s=aZFTCd#z zsBNQetFv0~M6!1|<@~=0e(?P|P*?_nc^Fng9`YNn(&Be02w#wnc&>4ivrlnD-o8R6 zpQ2wbB2+*g>TGyWwAR6O!)D%k!;e6djTSIUS@Ct|c7pt=Gf@Yg9XBL!~OCB9%CZ~LGa)v%2RMM=r!d3SK5x4QJAxJHYnlS<%nspZ_Lz6$*QE=8mjW~Gp=L|KI>TV(G&$_ybR8KLYgJ0V2&dd!Nlv-khHHQx98JHFrl z@%uf;@xHI#_dPuK{kcE)^|`L|I?wZBx6)?vr2kh`*TIt5_|J$=2h4c$PS%g}xG1$J z==qe#vUwzEw|W}q@>i4+ddVf2vt6g;qFp81-DZTE7B;X+K8)I+19$t3sn{>Bo9uod zm$;-P*v2_>9zy8B>tVPgu~sTOeP)oj$Ssf&p9-XjY<;8Jp!@!~SxUg_URWSUJY0Z) zf4qFeJA0%h7097ia9G4<7S>CqHmVloMgNAYa(szIp=(D@)2eHsT2hMF)%j_9zjQ2% ze9!!HK~C(M%&bc`F5jQV)1Q zAY)_B%5Q=_PGL>kz;E8dodjYR$Jh{3O2AX1C7=*tVY>J!$Czl1@pHR1kLcLwXZF$N z>j1%;8d7hJ>9sp;5;ZM+dUEp_dgJ7fg{edTbPhC6y zWLfOEJJE}**20lqTzSAv*dM0~W9cfOBnn?~$Klsw&GH76sI>LQjFd^wM=`aNVc3~D z;K3;*bNPorS7X-+Si(+g{jDK-) zalUwLyik|V{gh3=EdMGEfi49fZ2y2LmdBT#QZdwq_=egyEkuv+UYw^do7#AwgH;WA zQa9oD=8s^`?R#bc^v?a$Lbj?`EX*aNu~D{YDnGwXkt8V)+3QLyeyX#9 zefou39H+}6#O6k}doOfia<{5V9_WNFPV-U6^0*xKHW;yJ-HnU*cTBlaAH1>(O^4qZ z#1scBX{mkfGI*G5k&A>rOYv}Wf4r}UAbghA zc_%t{zM+YH9d9}{F|1w_K;KJbO8NBs3?JN|=+g^?vh!@u|>q59No{ z(BGVuJV+;B4UZKs-jM-x(9GnC>nAOWf4$SDxf8w5oHCd19m>kA1VisulnISuVq(T= z<7JqTJ#Unv&Fq;J_2qrz%*~0XPw@&Y^=WR+TWE~kCd>Qo+<_JntkNDLU~S`blCnI?c-so=Skcj>#>dv+Z_Y5 zpcE!<3=<8Lms(fuQwZ@UJ_~5LDJ(hUgl!?Ar$`eW%-3f$7k~3SBVUuBexhcOurOVN ze}?@t6X*PVE`s}9>>052NN>kMHk8Vb3;RD+wduoa3DTzGYL`t+)U~J7_jhcwf;@J; z5l+-YqO}-aGwd!jF^#$ev5ruQ)bvt&?VIBQ5@#GyJo^*wigylzrZy16u~*LCSS4MAc5uP2-1m`bq~;10sxpASj-;TyO%}w+)J67A`QmfD*Bgy z{`N$<`32+L%ejcCFAYLH1d5{eX@36>dfXx~0Z+~E?{TJf9n$?PSFot5sT+Rkm_p{- zrmnf_c=40O*$}b8D)vjqsihNE7iscw;?T?Ef_$nab#ZNH#!MXXEy#K(rJ>2Ai*|36 z%9$klbig-kLu8k_^=D%<8NR-aC2{@u)6e{WgKU!ViHP*qoRjotuhHic+U2N5El509 zuUL3jz5ZISOnt>h+l=jHL7GmV?Q70Hx-5_vW|$b)g6hlEXBCtriJ^wL7m5e|nOi1R*Sz73Gg}UB0yk#13@nqrbWK7=OFbfV_l_!&wG>rH$ zqjn=(thE(YdFvo$9miV`sDbzGB=5kvXwojt4v&$Esiap&>bYZe7PHZ}ThBGvlY&dvp42U98;6lehBfxr z9>0@c%Q7H6kjsMhF^Z*w-QN)=B*?%OXN0&0csMDl&?^!9!9iS-ZC;#wCK?q5t04g%o+gWQ#S7m+XZwwjQWP zM0-NQG%FdJq-Y-7h%4XNl#TsRj%qomP3n^K>ZPXr*beQ$-1jUf>EMx25b3|XxXknM zg0fLKFAGqJpL~C%eqQR+JU@}ps)$azd8mjn^oZdTaVk~e*oRIybX(3Md#DEz8f;W} zQj#SE0DMopk#yl}n6qFCqHRJs*%q~mxY}GZaaIkVf=&kIT*7d~H=8;(jIwu?qO&%@ z`8n^f;n#~>_F;bY06gx7$I*V|Qd_Z8H5Qx?%cmX6?x|=VPG{Sa3Ee-jxs;=0`T_`f zD6$JIws zp4gdmz*|v^OFR~Kg_cFx&Yxb+KH$VGb$NN>LF=xZsg=g)Qc+Lm)koKv*iNz-8n_pJ z`#Ca2XouT%g;k#HT6zV4)p;TywrXe`YuCY|s|){#d!0$6LE^=}e({Y}QMn0+sDE7} z?dNp*0qL-RvNZ&@Q-=blSsA7KE^LH!?|L`ecWo;z5X)WmK=Hh+J}D^au4z--IOL=y zydWcDXG9p{o!%}j92$=iV*SR8mn@6W?qcXs1d)+R^P9b+(pLBgc|Y%1BkyP9%qAY^ zypWv~tDCn#*JlGp=ryW&jt(8T7SL?fFj8kZ?b%^8j2zF_Rdp%IciBsv& zXZ#ffWn}E0oWs)X)4)Zxq&;mq3sakFf;hb^kzMkoxBRhJ?$@0g)Y}p4D$#p={lN}8 zD&M6#*ky0Cod6~8eZ!gP1vP#zC z-DWAE4Cg8&Yq#+AwqExrknS+?GfN@AjrTjM20me~j5+U8c;R8=pKQ?pNpS~ydazK| z6*?J`VbHpYE(49IME%1n*SxWA5Ztg{cygJgs_*f5D5IBAGDD?6*Vq1M_Jb^Yc9W;Y zt5Zqa>>2!ecqiXa-Ml%v=@H(kfVVSG>{>bT?#$-*4(ZHgH97exKJ3!S+4&8d%ie9llUERQ^BtN`s?Mg_fY%W z-0X~kpQ*YHecpNzx5VDlYa#@MN+UYZhfkHyUEtDGd}h;mvfz?SsoV!iCiGKVUOt*Kr?+0nc*5X19b z=r1h8)S#MWOSTBaT$_HxOevi?EmN?9Z8GadceF!qlR%4)lvFM4sQWXiK_$4(g*}`g z=Dc!HYK*0wmaL@yY3)|yneyQ^k;^1nS@Q}E^l z!$*o!rwlgcha8vd@d`}Bc0BKaFX#b`Q<==IT5RyfAy5UESYKak7B)76-q&hc<<@8D z9Val(pFjV6!x=OypvO4B?*N+Egns&9Uef_-JpULM{i-}3E}t1x`0Jvyf(JY+*mP9M zyqDtEci8o09C|J_EhHz~6FZ~nhb(p!%E309*VLc89T*>ju0f+lnOU7mKlrf{k8Ys& zM8{i`qqHy%NW`bUt~=W-Rc}tk*6y)7ySN0Ho0*%-7#cE59`4zSFV|sh!9Wf_8mo6| zD_UTdh?tFmeX3Q;t5;X-lfjV>u6hDA{K7C4>HyDS%!%FoXH;_CSA%{Azc3Jb>~2c9 zzg%AlW&U=)1trhxhQW%Al&<&ImFSQy*x&5rvXqL9ds-s+jl+@>=iusEj3@hgFOZ>J zRGIrMnm=3S&6ob5jj;+ll^R5W|2ySOz4V@S)M-Hl9`(1oD73e$Bm-~tn)*VTvY)*Z>!_jZZhZEK$z;_@Y;eQTvblGO-(I9xDc51lJ-l3>!_52)LD{}k&b=Ib4 zI$qxTZ}>gl^x9VVo1A{Ypf;afq}h&@%sQ_-Q1I~egBIyzjTc-r(s`hA1?wH#WF1DG zef_g1+-{zRMD^6)xETQE!vEZJ#PtwS$K{D|&vnFE5oQe$;wNEAg9h{f9FV57b8<0J zTl?;#PBV$i+t+Xt%rDUJ)@&Id!>(ZX9B=NspC3t~TQBnU*$qT7YycjeUb`?mWE^x~ zt*>KcDW0hShC^s(#D3AD{7})YsB`op*7a2NSvV6;dXH)|Y!kSmC4$3pYUdwGhg0PV zW1*+>Cz}aA`agRFq-=+8(cnI%4fn?ZOyVLuA*e1Jai(qkM`IJeykD>lIb$Qu3Rcs2 z&TMN4@JJf59+)faR3Zx-+4vrAWs~^f-s%G@E0WQJ{Ur~QGHp?qdL z2kX6<93AZk8+58pm}y#bUh-Dm z#-F{A<*~mo-T7)MXbrdPYTT%Ep)Fc~YW6XS+s#T&aJ zE5085o#*}{#k1=JhG50B+ATDAxX~QEJHr#V;!`!>g;$9|H6Ic&(H*xYr7|jLCfX z9Jyd|2e-1lFHu)^S+&@|VtIuPHx(T^-Mq28KM1@Oip^+Rd!*-vVr1uZrJ6O86dL;a zB$+&g2`P*rw}fw&u_GeQH8p{+rtlC^f5`9S^X={1x7qZ9;#XY3s=9J`8La7vS`Csx z0GT_@x!uI)?gbVkOcD}wmSr?xZ7lLVEy^0sHAI`8AwFH3P2)L!!$4NETcKR%-lLuU_@?$RT1P8Mm7Glz2wU16&B)VSpKq<;=Hl1_yiF zXBhaN!;?yZFb_{@7G9hhx83C-ljO;l0rU-DTBB@QSz{-_UNb{n_$qszfALQ*T`?CT z;uM+}UW;9EK?~;uvG%n__Vlc}=51ZP@lHCp@>q*$E8$+u^EUL)CR^OIMW7~FEE&*D zDwMApAVp34WS|{Zix!N#Xo4dZ12tG+h!?}7?GGs+*W&o-=o2_WORa2Al*z?_e_jh|g+q7z2MGtnz4^t6WqnS}S z0wC^9o!J~(upbP4D~KK#plmU(nN1DB+%+~adG+QEq4XiP9~Rh;i`awBIh*2h6iUQ; z!gET-A7(T*8W+8+uGTHMQwNua)psn0PoMrl&s{LrXlZN1>e7FlQeEx#Uh?+s+hDnj zhl1fAB%B?2>1e$?O0XD1d4`4(ztOLi{9;c@Ny#iFrC*BH4wXao-alsvgUl-g*-~>l z2T_%sBVects4ny{VP;2|Uh<=nJ%OcZ&mTX2 z)OC|{-+FUeeZ`<|qO&zaDZyyBq`h4cW?kT-@{df0g`N(YEbqF_cAYUFuhA`4x{;~u z*ElI{V#414R-4^?6C9x@*PUhO5pREQZ%p)peHHro`G=7|>>VCI=2WiChG%l;PP{=? z8U0C*C0MM`Cr=1(-n@xIA%bHVjpsMI_{+5Xhp8~?3AGScm$1dyJ13c|r%>@DZd=Ru z5J`Ey#e`EVk9I~jIyyR9PDMqy82!hB+)amEsj`!HBt$e2)`eL0%1GBerJ z>@zbmQY$N|QD9!=35aj#plmMMXSWuEoL$+sdHNE#ZJL^y!7ad&e;ysBRj*pG7lVg& zAr1Wq?ztmgXm)XtzCgv@-F>3+{cHQO;^Mn)F+69=s@}b$g^gG_k_b9|@Z-cpQPa>A zm~_&k7Z&H{8nZQWE?YY2>CwY<1r!Qw;iD3D-j<-jKD_B$N5cJ)^YYI+`j=LL7`@7V;dll5mnC@QqW#P-mv7Wg^Dr^J z_-XYj4D1iH5DfBdrayq!|D8M3S^_rvJL|Kvv&XW~K|w*M;X+Y&4-fWV=jFw^)ldl< zOGmP3EI`nQkWq1FVKHWVj5sp`4G!8MZx4U*;!PFW^us}K%{crWcbEt!S;}+_CPx^? zAja*RV#6QKdQC5t#TmxDEY(K-!@?MNO~DmhHZAMtZ@atDe{mzT*Yd5QNB!{I$Ma!^ zF%b+!H%Ba)Kb*x&swyiJHijQU)}E(#7>9h6w^3X#fK0NAkhpopiF6$1`5NIR;=1mR zjMLk6vu_%{`T+I{PZtJnL(L(`4G=)C;!U>8Y@ARDsOQg$uL0gv}SL(8N`V>8%(x z`mgN9xs znMuxEklcTkX2a@|qS-(yNWo5V!KoGSlBT40-@2#NSpg#|K$FBC{uJI?FBm_9V|*$g z3hd@PgvXyq9d36*lDk2I18A1fiNtoUkvC>?Bu5DF)5@s=Lw{*%6 zS8F?*Ch=gAa&ahU=Y_6qC7w31-2_cutBH^=6R-wq_4)6$xM}Vg(h)y?(te9vwCW`jPUP#XpVo zkP5zXkbuCU`_#@B6NnrCZ(hE2UO!1q7sje-Op=_886A_JKM#b-RI)6NVA|`t3uRUy zY&>yQ%c;%U!|GhrjwgTsP2B=%<|(w_q~o-T9EIBPe$tJU<)~;?skr&*T5O)j9@=07| zh@#i7Fw`6dy03F`E02dsY-ruBmPCOWZSMn9Qv}t(G<#Tqw%l7yK723Fo|v|Db@q$3 z$dL~zq=h(L<6eCO1F~mdGc0}S?>X9Ob`wFgO-XA|+f8n+<ncF5!3o~p~>$ve>xHtSm}(-AQ-xUp@1pI^yN z2Xp7vA>qd)*$qi0uk;_|<5bfW*n!*;al?Yc_Y`XX(j29pBL?D&!I>wY)1xeA(X!xW zANlwpK?;dc3JtAvY(;4lK{mI%-7q0h5(%4pr1`Szxv=T2RlK=dQK9tppPKbmN0W2} zas4QHZjSPPly(rnk}wVw>=K>0v@es4qjq?dYRatmX-2_M6rB7CUc@N(T85=}tHclk z=>U{M{LYEWqT-0KEE-yd z`BPJStDPj(1-NaUoeYn5CoX+e?=>Q#o|;ih@LCK^HP>Z$Hr@p-7fRPebnr;d5-`_v zD`;&k3mLI=E!i-yvVLwB3zqDrxR-ha8Y6G(gJXIsWPk|zY8j+;FKrq^O0m_d;_i*C zW~2gdJ*+0pcjKlf$W-a&rKu?c3JMBrbZvDt-OLMHWyWP*c{0Q;Z0ctlpKwXyoyT@| zgcXU;pPzmiqgw7;3jP9^v((Oac!qu$-}or4A~on6#4V}es`DY}M!1BBeV3sLd$2&) zs~NYH37OkX?b4YTsjV_Pm0rIB3H&|vQaf&!2ZYRfFc)N*fxufn5*vnP)YM2K7?a3q zyP(?b+d=vVKVxAmjjFFUO*KGJNgfB=bqn0Ne0IEA@<5K<0eO(-fFM-0Rx%JIg?!Q+XSR6QXtVy_Lg$QbAT!6SdY`#WoHhlfj zX-s?Cbsg%vQVW_I7|H&!y!`Z$i_!i~Q9}Ve37AcQWOAc5lm0Xmn+uTr!3KYVm>yb> zgCm>SsOxG+Mk)VIA9h?vaeBz?guLGdS!HEq$tfub?K_>npTZE5LZjE9%Z5s0%@L0m z=&Ba5GC4>}e0`_(`U=0(%nR?e@8rJC%J!VG4tVd=lQ^9Ny_3MJfIjzt@6?*((*>&_ zj>>{xeAQp%j$h0bHB{Y4VP1 zpJhMy_n(@KksbS#C}so2C7z`|9F1Vu`V2iVw?6feJMVphRSi}7l8MwVRn7i_RRX#_ z{H%TrEf}#oPHfyZNyG_jCa*u$RQBVCDa;;BI1s;MAUFnE$V$Adr)G2DQLRwnP}IQ? z#lJ>e%V0b1uC$GDfre|TM!v5AblJw{yx!RET|(vcp3pwc`Ij`1{d~y3Ve#X2i|H2 zj969?K}l8qHAY)iTbri-R)QheB{m36Xy)n!;SijffZP)0`Qinw_|F#R!rh&Hch?0o z{l+%FTH5j@S*aaT_hlc3)7^UiI3(&mYGvI*z!q|rXYZi26oEIYtEY!tlG85jkp0Abu0z^EMy=RJ{gMD#Vza)(_x`6GLj_lD4pX^dVq@QfzUD)9 zkP7aD*?+`@(K()5f!_k&yFepv#%Azb1>t1!Qd?KlC!=YfHMogL@1w+pfJY7Z{H8#^dT{_8S$zm7GPJk|8#ri02bbG>U-2Vq?SJ zeC!=nUiHRsIN2&{x$6qaJ*c57lantCgVV~rdoKZC>rrh$=ka5q@5gqb*~e6PKjk7X z1@OK>fCehHz4?8*WoNhNo1u?3DmtbwHzj^lkZuvR(jl%HbfZWhvBO?e00+0HqF2w9 z#WkoyehKMD zELP0WBddYL&@tyZo~``@X+}C!46kl*xx3te5u-GwrZvR64d3hOndFt>;Re)Vf>DL4i37+g<` z?=LzKxw&^+B1TW`hZqssMcPjK7Klp;k*8*Pvd%d**jTgp;5+xO&~9&W&-9I}Gk-Vr zCdZQm3bY}%vvK)}v0@FS&+|Fr54%Shz-S?MlQlzkSiH1Nz zirw^z2ORwj)e~DhCa*Rvgcegg^H|L}LpK8WF;KLSNd!6zeP({0@5tG%aW>J5Hxr^c601+~>ICNG)lgSCEYb6CErCbs!S2%Z z{^oe|bAH3++QZ%2azKcfdkq%;uk6r@vJ#|h7D@(ibrW>>N}?!mKi0u4qI-ZkfC)SU zRGop~bXJbGgy9x<0Y69PeChDwPEJK=Hu}bTX;p!)fFEwT1gypGl`byU?vp20QB#z~ z!tGjTfTrpyg_18Yszf+{;dV!-n4G*0P8Za|D@e8hb8{M@7?(9?pl?AAFBn4x!2NY` zI7_#hr4GE>+uN;$G=;;OeWFw(MY}uB={$NQ0L47zcVktGpMK$9x%NbMnLnU}+wH|W zL8o@geBR8gxl~^&s~oKx?$bTTM`RenF)ZgzYa6XkcNCYHQqRbo>_jf5os1G=Et*?% z>a#3E6PPK7ZES2vr?@U(oc;RsD-wpofh>uXR9dCxL*Z^nzHC_UjRV;+--O*o=8Zdn za&a+2U2e@&-x4Q5_m!{ZALG_|Z{}6!tC=oRAW%A>Q7+zMu0*M?8->7L>CdO-dg|Gm zhA#lN1;0{qn52Bl_|uCZ_9RD43kwTyZuc4r0Rb>XrTR!#1%Unn#1_l3gh#Eh0Olh= z4l|gv{P3<6Bq@NnOv5~>8!Y;#)D$0y&{~VMC+EF-NM!e*P1-@U7YF0(M~!Av{LMwI zfP!fi5Z0(O~BFp9*0uL6Xu(t>InGWd0M&6X=l_D zGjYdVd~6CVh0OazYlb$fxq5lo`{-=JuKSBUsxi84HO3x~Kbrh_hx zk~cNKnq{UVg(v_?8YqB|(uE^F@^8({S<-C;$^}pCKp1>Lk?giXg(Bqak+gP!bfSE{ zUwh>%p9hs?S!HA+Qdlq6>{{+E2S`CfVKBemS5sQ%TGunL#Z6$dywbjpc321N&35Uq z$One9`+D;SBT^s<>3r@vTBJ;jRHFsHVn-eBUu|xAMZ7L>3tonCPg4*!u0g}mb9(3- z*8Kr6Jm;<5do&7eweU_}lj{`pIM}PJ#VZ^RlB)(74Tb9N=}~f{S29c4^|FlqI)YJ` zC4i;NtMwX)kR13I`X$y(wp?~8$~4ioZQ&p3DQabseK_LC$@u^GN-}CSa#mFCKE6zI!m-p-a!(y2|Ay34;h)ye<%&VsAa!mE2Fs~kwS&GZPbgVz&nq*$3+kGI_-E7cZ z&&?S6StJ`Re4PwbFs!amU%qAs68v$=p1<)=M#i+s9OdRYz67_z28hVT(MN4OfJF=M zi53>g)Id!zL)4}2m)4|{jtx5X@qW6QlWX~To&yw52@UYgbsR{^f(d^8wsa*X z(LdqSfHIE_;jgP3*xy&j?F@P#l8nS3cRSM->815-Fh;CW*=J2=zKmg~Z^ck5zV&>{ zUiLcK2iK5jkq0cFWn)%se}%xK{EQWfMrD}-!>RW{(BQT(OSuB$jfYW{qt2ao3O|+@ z<-O;06@%LhU?XZf*$(WzWxiln&bj-eVsk`=a?Ti3uW0&RBI6N4n;)$M@Wo z%u(>&T8v4RGA*x~e8hcQvuPpsh2pcZt*-#?7z8;It!)wipFv4L z`Gvmn2io7?b^AtpjJ1B5C7rU=z8%uyelF!9xv?~!w|yEo3-AZ`2@x1E$^SB4rgvl{ zWNb{YCs}rcdRAI9PjmgiRyH%|j!PSFPtM2a$C|FL*tx`Whd-Gr6NtGi^U9~qtXWun zAv!9^U_9bU_TWCQ35WrO#UDN(l6w6XyHFHitTofS5F)4v%mZWwDhRk(n@U~-0Q!Zp z$%F_XlgUaCI7$2Z`+;B3zc$0qjkOQ<$}Ng^+40+FDNzIJ4G{XS&5DkC(|I`FvT-rE zO&XkghXS_f8&Wp|=906QijV#Oe*b`;3(xYBS#AZ}muW)r{-w?7K27~TG%qM8i125Z zx4o3XvjZpxlesspFPBi^pn9WIV+cIW@Po}bH!XbuOrmys`!W4H_fif11$NC{#`{xb zi<1xW{Q>7cK=8@RR zLyr2t2`fj3q=AB>aY`O^@}&<`++dNj$fP$# zWbMOJrOz zO^h3Uc=FlpU48RliCOI8G^v{7_P)FM@OUVi2c6BZsKl)a!RsdVk^)M zd`8X6r)+(*G%eBPL@xS!u~QpwZWuF}jXhaD?|=5`Z`R~d0HaVaDD-uKp3B5I^z$mi zV&mhfw>Ce&`iLRK6f7xO%YZw+Zuh>W{XeLi>gbQ{(&h@e+xsh+v<`ahD{`JXz zwu>c^f>_JWpZ?;}FD_tV!wotz9{1(8oV+}~=Yez=O#j558eTFCB(tPA$j&ETh1uSwa$+WXHS+Y!Q6cEYb(0IDd(Xu&|XQ3m@J& zt-_?ZNl4>E^!G5$2DnUaa@~f=M(^~6R4x)5=FggZqJ;soaa{(fTm3yfK1oSQa>7^0 zte>^MeuVwfy@mf9j}yiYPP0DI72ghjBN`NS2px-x2{Tb3xDfJL?O_ zsi187TD$M+I)EwwaU}puYgy!xfeT8OLZnT{E8f@$1$}vhVaZ}`K=>hq63oi%G%fIf`=YrFpBaVnD22eKBw!3o_^|S(kQA~RKE4( zR1EZ-4k+c}5sGQ;C#P93tYiVhL8M`8`Tj!uc z@GdRAfI5afw(l+lNWuzK3D>p&4>}*AfKB2=WJh!(+MEqY!KK9pyGu#8Mw3)^JR|e; z?ryCDI{Nq16c3pQuokA?mW>@v7=#&Ja?O~UfbBwYpjBYd6uyf~_{M2*b5{*K72p6M zf(a$0PDC;kiC+Y|ST)R2+D0?aQ;D3ZUSpKCzKEC3<^% z%LxOeImKa?YBqvYq$q1VIC9gQrr0SF7x~dKBWa6(7?ywe~3^r3hvfpBA_IsdSR*|K~oBFzhHM6 z=Zf!e5^hplwTF6^`eSuY!FsGp-N4Y>^6DP}!dD8Z_R?f1PK3ZI9YOkEPHm$g=-Fgv zbM5_%t;I$amz2DO#%lmE9VW`i#Dp2(6v+7^%$Z1=Pzfyh_IH$Mb(W}SufCOLJVH%fL-z1Jzr5`Z)MPgTbeqs8SZsRf4=oL2nM50(@5<5;vnSDr+vs;QAq z#=L%Y^AS3i&6Bqbvh9>|9bA{!Kim&Q_Vn_mHnLr;CU<&e*g{H>7{c)R901qJ%6eLSs6J`&^d2H`8!+q1$pOE}y_qIVTtv{bqL=IV(o(wYBA8~G9Y zKcZJRvvql^T)!Bu-%l~aFXa~9I+%HIU>-fSp{DsFYZZ0j&P;-ZC8OO9x0Nfp6>CI;E_hdyCDwIf#Ty`w< z0NSTA;NVR;Ixflkr6&|c;3<0Bnt(mK2v19(Lu321H+*fwa(X}n|O|rRliCk&5-;%*%Ik5{@2lR z1#=$v3w|{YD8w?9FIOU2py}P)dvkA!vbHXiP7I(4VU}}?tJ_`O-QG`Wgr@+*sDmR7 zbL5e&?F#hH>StE#=hmz9m4}~u-rkaV8N9hwaU1q8_yGP&6Mkjhzae$#+AzQ|iQ1?70xi2OD8!f1 zOYX?{c59JqZ2d5HJ_R@^FngH}$){d*Qc(@q=`m7QGOD%6@uiPH0P7?8zY+FY8OyMe$PW%Ud8fT&I* zV{cVd!d_aiGOao)aZl0@Q_qq;^O-k|5q1d3$K8oZmLm2@*0gb1mnb`j^_(d*^8(3s~z_j0o9&mjJ%;1aQ|$TgWu!9j_W z>Vq>FEzpD46Yn)vXe_v~zpC4`0GH1+?b{k3ipUfHd?-3;r*u<0C!YLFOG_gixuLG^ zKPqWGfr21?GE7rT>-5%Ul7tK4gEOQ=#+n5O_8>d6G8YfjaM6y4o_!CH^z+*g0qw-?DidFp{rWW0H=AKJ?YpClk+={NW>5afZvXvqLZ0q}^##su=2CWc zc3|7VOM!7j7Aq_iXqw)}!bG7_+i$k5dP?hymvjGQHv;mTLGRob0@0&2E8$bCmO&Z5Krg`E70@d95 z1LXaKn-yg|KRc;+^CrdCX1x!dta;gxIh?K}qk1*2PF>SLQxjdb$~~z_;m)umA^?;J zlsn2pZy3g1sy)h+C$+1(+{pnWJGwnM=xoo$#wVh-+$7Bp^uNyACXD#Od#n2REK|{n zX7oSX(?A~HhMb%nj5U)`tHJzB_Q~>5Y&Zw|(97kfH|xnzLPjYwS|`QEn%q?gI))0R z74-&)jKk8ywx=cN916T}n<%U9P%xO>0UI2FE)B&`DlhC{+t zpXL3~k}+<(Zg;H`pOh8B3*Y=H)Bg{g3f%wjP_&Y+r$OPuyderRUoh72hNKYn1He|y z8{gq=fu1=@?KlI+v^xZ}_yOxw5e>j#K{3#@Fc&|3vW%!xkzsz2i^%`R@n<0oBlS~r zpbW0M`OJEAedFcgOcMdS>Gtw~6CDcM&DYJu@lNte$BN;>g|h<0;&4y?8kq zbIW|Iv_TuD@4{ZX|3m(3^UVEMYyNG%omY&C!C6WihMIE~kuze**$=Ix$D6x4=*g!g zT>JATLy{f@lDA`hew2EF`iDCMaBM%YwEO_!NmX6IF6F>we3$;#8!a!SeVG5D!b7#r zf>DeP`=CS5RO(yn(A+C^P2=fr zEoxeM{3&)OflC_7Ob1Ke1rO#HuXy+5X8*wavosJGi-U$x&d$ykk$HmPL*3zzj47+# z>C0O#O5P_#m?5Q52|tU8nL9KmI#cl9R5; z=I@h$I!5Iz-?h&t^~oghB8DQ-{4S=K{<(LGDh#`ld3&+N$~j(yGQPTe^Ax zzibltFZgAX5vsbTh92zA>m!(DRdsZpzyMP@;h;e8*Kglmg-9+JMik?nNcwHNKHAT0XC#Ky{& z3&|K|B;92ljgIPhtj5*Ed)ynZO`r^1N*oB$Gs`A9))Q!zlbd|y56-Bw-y#T8_-9*y z4diTl0LF7))S0$>>Rn4O?bbZMlOreux4)5p@?d*=h2=&;|TtI(i& zs-{U(-}8O9+LX_~OIN_Tsic$P$c7F*KpHTHQNYg5PNq^`Ce24s&aPsB(unBj-Fpkk z&hY-$^x9jmMM+pmAZ~*1&vz~Ppwp`hW`51g|6~VDOctDbLVLc$6{8nS{4jes%EHfwJZj&jZ?TQr6Xe)cdI z%w6xJ&?7@nD`gK-%fq<2>F$^5oDn}odKFI%@>3&?|5CLDw}ScYGE9(K@6%L+Nr}+& zJF8QELTY!Yvuk*m`g_LJ=tMDxsWF$OCiwb@*jPO1umh93JxPLwL~@G}goWhYHUM~r zECH(%i0EX1yuq391n4U|$e{SSw`GLxCw~GJIRIQ)jun}7Ub}P&L!6!j>Hijex=5fR zu}%ScqQ-7wvbOei8RLvcABq(^Fee4PSu*ERbs8kLrp@c269GdX?#HSgzCXO;FpbgV z_Q7@LqDW+vZ!=TsEaU$^Q4_ol%4+wCP}WGp2Px(6XlvUbL(uB+7~Vh3O!P-2A;Q9x zkfFziih(g^zf-l|DAa6Q(3%Sx8yh<_0u=7gK+#3`yd>hwC`gO-CxNEg$dD!hom|NzD`+~u{EYB!X zw|)?KGyIdmz)zP?0n!f>;_T(lDZmKseRmKU8n#BVY84vE%Qcr=Mxkd`C%YB+nxHX% z@yh``8DQU~0?oi|AlGkT?y8H6m}TX6HmF;tfy`91JSdE|BS$E0xRzpx%D@dLZf$KH zEPhB%Om`6*1-}&^iNh+A+t~2${cCCvChGg~EbzbqhW=oME&GqT-GNZh6bLFytlxCq z`JM^H?{_aP7%kv1!a^Zxh53!UaU=Cxt}tIRB%bPxV%4lrCEW$&CTGpma#PiuHlOBK zyr`$SB%^k<7vkXU{|K{xVpOT`F6uCa@TNRCJofFo*JdC3GqCsnONR(5LQkOWPa^yS zAm8T$6JN*aYqXae!bF-_C>tks9tCcXtK70Hkav(q0r37;R+<@J6%>%x0(ouHdabh! zazG+vfv)I}0Q9>8;x-BED!ALWSiWX}_Ez8kH2_(U<4mGMIJ_Vz5$83IQ#^Nkb8~sG zj9ePFb8vW7Ri$lHH9I$>aqJo1ZF*hG8{lp&e&JOK&brE;RMP?{IhUGsy?078W9lsP z|K7}W(hRhFw~jwC6Ae8{EADs#WRa>98^6VeDH$2YE$%>!KVqaIn3(jTi#1$RC`X$l z2xPIO0M5cHgV*gQC=a<$3z^=Wkj(4}vT~iKL5OQun-Y+1YE?W+Ka)p<0>Vy`wCuCQ z#HWbt^tq(lPPiMwb3#xs>nb$Lb77Fh_{vtXRw#vZSy_iOreHH;uyozwoaz_)sV zE*}dl|LVe9J1U|C#G79<5oA9rV%kiVh9Dfs$i*_poUPoBV!y_YDWgdsS<9L{@ zkK7@Lm_jPIU(%NV1W5$e>SW-4lJgJF`H?abX^)IU1Q8!xupcti1MGDR*uGErYPK)| zC4#j%0sl8nVjkgO{yhYHcv`oxyHqO`{!nrhD6=aIRvu#K;*KPx$VQ;S3RjcA8C0Fq z8Gt?0(wU%c3^3fh%=wb_l=K{x8!pcj%JE3N@j@c-v>7C94<(;@92ETA5bX(f`++6#y@MPZbSA{qEt-bbG*Av=4Xs|ce76Eq9o)ui+_s>7jiB$k z7L2xm+0tuktyUzbq@+OkI4)6vEnHiuW{c7VBd+CUzj!an8T7yz94C_OrRv8mKPmow zJR1>bOy5yFYBhoU<>vbHqY9|ns5O%G{^-c?@N)9u9=r7}OwJ>tUxn|a|G7mXwWq3~ z?R^{K%fvVk*{?o&^r&mUt*uQ>SC_858fNLDk&6=Os@nYm%ho2%r)Z0D!sKZiz7UoK z&`b&JEo8s?_XUTw?RGzuOSs58`yUW<1V4#`MQ&$Vs@J$IeA)&`D(+=~4{6@R} zL^NF>4>}q#KFPnjy2|goHe0s<3ZvJiA!Lw60K?wYv~hWVt<>vsY;tlKOw(*yaK{cy zao~RAwMZ0MB5@+0nAK(^w@Z*Z3CIfIuRCfIhr~; zw0179A+FO4BNu_C`<*|P8Ap3Y$5MMJW}RcWLSu#hs%Bz98b7PI32W*Dw*MIl+F^lG zQ&WMpVPcLa=vwQQQZ{N4(C7usFpXv&PEqBj3v2{=&zPA5m*6xFG+l3p8YB zVY%Dji;waIZ6Js8MTkNdK|~EvqTpU5?vUGuP&%5|*YaJr9}NXz{i6rGYwdsN34K7I zWMa)Gd**u_9)u5r=r90OQ{beS3ZZarAdjK2x~e(!?lyYvf`wOJ!J!ZZB_-a+m-ABA zsw@0hRO1p7U`WX^R9ZqDy1(CvXbm9DK)RUXKBJ7X|2k7FAH3vHC2ZTW@Y_;wMT;sn z`Dsa&17?*2amD!b%3UZ>P@X<`B%xZ5?$u4$lX%qP0kDc!!weEY&rab-sSOjGE}*7* zU}gpaI%DvN8g7Ig)79I1-hiQGAqg0tw8VJ7wboaLs}XIMq?}n53Ef3s2){Jli@*(Q zm|G7W%zXWtQ>U=l@IB^nr#!BJpKmyPL`n`CcdWR#Mciiyg1*|dbn$@j%x zB~AcGIrD}?mF!b$B%edo!AT~2(+EEu9YDhHq10joa|9j@JPYX?J&PbhfH_Ju!;8?x zN+~F?c`wNuOAy7b5@YfIarPEaQLTT}@F)rx*a-p#SRfW9ZJ;6w0s?}Bigd@&sa^{a zMG-_&PpkUvt0MCg*bEOInVjU{_VY=k+YDJ znN-E)GpcKQ1_$l1!0hEc@9%DT_0=YV$a-s63v~WbsI z0-5PiT6JRo%A?QIveMG*-zkgVv2Z{Q4W;;wEJaz_xqJ5PxtNv(-_>0ko`V{MmS^oV zMF`9A#YiM{1F{ESy=$y^(Jf`u!U}oig*rjwa-Ix&PmFOoMx^kwf`|_!r`r!|5Uw#O z9UL6IT-gJN7&n561lzQy4!t_6-CXt4Y=NTI8&Q_Ra6#$J8PlU#=@#@Gt*x!MYt7T^ z2xjGm?)#CcbTDN0JB+-uEuEN{kTJNZ)NNsG`~sR;==z+T_9Z7L+og;1^3K&OxHXpq z1Bde^p_0@(V)H==1?6RSc6R>dPV>67Cg?G!b#8<0N}%#;q@7s4`MAu10~b5(leDu| z;pS26ax5FAx&ZvXmJ)u*RuQcz5=Gb7*GETLP48)Gxd3~GHRV0unhQ4V-n|rBS3Y&h z!c00wZCiKjm`j3oloLav`LT4Ir1$pbTGCij(iu(7D}x>pX)fT*0d!p$O9z6vM#Lhx z(>^^d?L5GlWOH_-bf6|TR`OjKSu5!*h`7Gc+(AWUIrtMRZL$h{IIco1NbfFw|9&37 zN`_v+qID9YHv9)p{FMH!;Ny)mb}%;H27rAQ36I$kypDD&96$aVId>Lme5Ch?n_EuT zKvCdsCO@87lXNhYAopN1PA^{*RBg|~aWFnMcE62Ha*uud+HsXS3n4uZrfz0WM4b0M zkp^8Q?{*hrn*ry?kS}m;%A8wyjgSjgK6mLmeNU;oT6{PSyfY~g$%*E$~yr|i?zwy)98XbW|jt^0`}1QJ;N zXPe9mBh$m_d6HkEEWi5}eFjnc2>HyiWy@Ch##Z$e#G4m<7GAjSh$2y4zt^#PcSroe zEp?qFb^CC0&lmyE1GAk=m-VE{%yW40LVv6O`PG~s4DNc~$>S)v>u zxcNyRHr0H%dlSS*H6J5S+Y)R#a8(!7OF>8R4cE`SXRYT{%~L{`ha<@!EcMM}P_p{^ zUM*&^Xta98hGF>@(qPGLWpSsb-0_}QsE`+jOK&>3O;65;&^hQ%cB(U_r<>QU3LIMX z5&h6r;4X6rIZ5Tt6LMGW@w}Xp`aFMeZL*8WIkgUrLi1gt6q=W9L3x8*i+!Va@yQ z+ut@#T{}19{IT4wv~*$amq}A~)1P9)a(ycrTs6LlR!NU;{$P=NK;_}}tzy^5q{}uK zd?%5fGRqy>e`@2#_HFoyuk=QzbK(T<8;|w3+C8$g_EkRzGuXyyuaCBJfg%DUr*Q_r+`INyl5C~y z&P-2hYlnz_dzHRoWZ>q9gYQ#UU+4I98gS@}N_t@GUq}4}Tcr7p9X*U!s8ZB_x#>+tjtmD~b8^LXAd)vz(V^F)=zwx3w1>d;fV^>m}c%H=2Ca>uxpa zR}Q6J`nWVTcuTi#^KFp*9V#}jtEe3z8SO5^(ko_Cbxe(s@^eO&lZ!xVE!a& zagO8n*ci@ujv(T>Lo-C2RK?ah#GvV+-64%#>Hx$g3Psm(qjMJ?M@4-G?wQZ&Q12BT z=FZOTHnQuOpP&qXey6tF zXZ5+`8y-3Scc}+%CQT0?2neo)^kA~Ij6IE9v9$Ojv==t`I-mKfj&mCERdB^SBOYV2=9T;cYd*a>43kG`@ z>}#8(3M3Uj7znnNimICvkWnUR#2 z+YpHAJ6=1>p3?laFhIny5zRqmjfZQ?yE{G!&wC_YVqkOb-H>p)>8o1NSkTFovKO-Ud; zODUTth|xBugkvdr0_gh3?hN!$nL2q;g_DPmJG7y{w9kQxKb>mVQU31OW5{~yhnyMJ ziDZL-EU>R#Lqx3)_+3cVWXq(vsaW@Yejzp;8WQU@ubqpdeG&J4tC6&wnOj1Gdf0X} z^>nztzhWLYasEL8Be%Cq{W{b5cTFzO%~25(Or*$-)1<(aqb&Ief3M!!yB!?uus2bG z=KialSgJu0d-tbjo633rI$>c!fuljIST1PjRf%Ur()FT`KltLTefo3^0eo=vW_e7z z7llgJb*K95w*GSH@slUiTX?9IeDz>CfsUt1EOghoi$I<)Dzi*De9oW6DQcD9>|`nb zOuoS&+$ERtWFFVMD2o!8a2DV+w+eLn9erM%FQYYY-X{EE(0bt-<%6Rvq{DyQV$#PO z6MHv{35(?%a`Iv05I*$O?=w6;Dpu>dHjzI9dJ(ekIt?HGqkhUNDoAsRPV1!Y+DpY! zO1WM8_Pb4zCntk_xuq$nKC=wmQS%xBQ`0ehcAB5!ku6k**gXV%tAQ*54pvd{zLW;h z=!#etE=QSowL}~G^qnJI-!z#v78V||kyHMQKFwQi8dURw&P1PP%nxvnjx1Dj$~Gv> zx3v?@@i`xPI+ye3j#yv*Xrp$1&3a+s>Y-ZJ#$_;t3V-Xv5shtV3RNJxm|aZmbK^+h zZr$`O^#!Z=OQAN?Pp{*ZgVK%$0OS#TCR}oQp`?!l%PHpR)00~iLn~!hYezwHcLHDk znV+BEb5KhNgr+vd&^M~0@JSv(oEyHri)%}S$(^T)Ld4b4R@~-6-p(sW&a!*OCbD(Y zrh}*moiUl~?7B0>(4E%2#LPBdlZ{ot@E{{yJ}$;y`YmHwkMv+ zaS&UlV;H7>MArCCAh+DIy`{5$e%0dHf~92VxAs0LwprDdX(0^SiyzEN1KFYz6R!Yt z!_}WBQ3eB0;_gT;6i`u8x&s4`L6FTl(e)*WR2!riqjlWh=peCq^I>G&2tsD~wWZ~# z9|Wq)-7sFXD9{C%L%wfQP!k>W7IP2>fh?zu z;;|&2>BGOn_TSI6if}1{2I1j1Ia=aTjT7ATpPg>86RUbGzj~;LE?)k1?g=fe;KOL| zlE-1rLahJ%nn|~%t5-*(#X0hvS@2^W*I=%z$D@}O3+*h~2D!(|ygtfE+wL4-XLH*Y z+4`U=`q7?=kM>~+3Z{tCDE;+^R zkBd9>oI-;Y@}Ojux2&&3Kfv@kpP6(G!qq>~eXSkOyv$MBTPleFTu09Im=4&!z+3Xx znSHIwss*outu1lj&(GJLYP_}leg1hy*L(IpY!&J~5hA7vnvZsACsUs^a0gUK@^+TIj>Y1K~akNwtnTP`TB$QPXXqk_5?+Qs&m+30>U6Be>;&;q}P zUC`(@@yu$wbf+FWete>F=*8OCT_J;db4&7coZ7b|7 zPxN1L{>HmAdz+zZYQaDqCA+r!#O7h6Zdv<8Gy#I#0su zX5&oZGq31%Im(N=Y1ij^ON4Rn)rzF7)99W2ZWONSOs9o;S&ZOD7;MhW+goa`BhXhVZJBNuE!O?%%Qvd9x^_Zq zPL`aXK(R%lcgmT<4m;<1(_dMIbccAOcSGHEwB~(ReY3*Vsb^l&XZuhe#`qSrD1GAeJkGlB>T^i1`tEy>&R%HYCZ+sQW$5*n zZx_o-JpJqd#)N8U3y4|*9@?*aUBF^FT~kxjS)ZALy5|vq*(>47Bpj0f@W#faxQ@TS zc5147*5p)$Hnla;M>9LVeK2)s%j2v{{x=o_E{pAU%4dW@!F)d5^!3Zp&|d$0;R1QV zUuXlf)_A9**x9t{U&W5fUGwlf(C8p0t3sbDWc67FWV=x}UjPO}y^XpEbHrZ}^3;pR zX2BFp2Q{jLOL3uatA*;Pkf3K5lI&O97shEwJ=0?!>bTksi)DIKhB;EVOLSSgMu#b? z9X}>NJ)d-TYeWBH(#@L_OlQ@8FNfjr6KP(#-~`hcFjL$8d7Kb4Q)mNiE}?Ss*9!*c zQkrzUUu|;>artOEkn?1z1rDj|VQ{r8`TMg^eVy&Ar>CsBok3wtI1B&UOB>_mgi8TL z#R1oqQ?|2v{??b9yDvu|vt^m=kt5hJouv^6Ycp*PpMF5B@-Pgi1*S|r?cx$hYxnT6 zlHL+t*!uNiZO)KaBfnDl^<}<#S@qK@vb>wWkJ|nEj6=$I&B85fl4boaJUd;P-uK)}|0XmZS>PX9UaBAF zvTk+bGoRW<(f3Jhvwyz#`u?B`OoZbUg~lmnXEZn|X5ZEBoC84iaN}an-gWbzUJ`iU zbdK4%dviuQZw&`^__$CyJGIO9jemgCx`4@Xaebfb!;H+I??<|py}3q4+NnQ^L55QZ zyIUU6sPqx$CC*;OINv4fs;Q|+(PXe^Pmq4kRIYOQv-4~d2G6Ob)Nv`zWmt6cctn=|GvW8Wn`g1kn(;w{TDVj*ZtZ;dc&SUc%i6G!O1@<0j_-!kO>ORy z3x0q709+*Zo(tDN_S7GZC>w&)s?cW_xDt#^Yb7;*`6B50y$`oNoPuh|1Q@kN$-Z@7 zC-x^L4A(m+WnIql7)fl7JFmpT}vx%+^rS%Yvn!H@ExSm(Z%rFOEBSILPO&=GTh&VkzR7z1i^H zsMvkKR+{avg|r$rPG%cC_v%VVkSXO(MaR82=gUyBkm+Pv$0Kinav*2XAPiP!JqZt& z>CKzY1;!K)J=|fU4p0zjBJ5Zg*#pH3Mto-l>Ud7tCYgx5nAF}d^-;1k#6HVjqSa~G zN!9LV?pn$H2kV4JdiVeOXi>%?S*qt-M^yLVWo`zMUlo-L8e`NR);ro7;#B!k&1#hK zGrX{pHri(@938|$IxC`m;SS9i5jJ~QIw@UdMDb+idUUKa*$@;FnbQQ ziJ~_FK{|sNLU%&xLUdHm&%c?!a@DHpwGhe0fzzmq(!a__q#>rYs3v6%>s3%(TqIV* z7MYBO-GO(gHT{$c4TXyO}t*nJZ)MoaeHd1!~jA?YwA*P(e-m7-l!Th=tY#V@c*%+ikDXUX@u-Q}fYIBz7MLLYc3t*Yu;-<)BQm!n<%DbTa?SL2gk z^Zq2;;NBWDVPrp9>cafN-03M7Ic1P^7$E}=zBam*Ixp#sYunYlWxrls;6MH$PvVwb zXN{~mg(~`aj1+iv#?W&&f}@>Oyy(rFH(Vuug?k9Zr&do+W>*`e8qsuh10oY%HV1aG z^!oj^atG;q{+X#+o_Fqe5Y_*$Bzg0FZQl|SYshV!-9FEC-blv5tIwyqN4ZMUCDQYh z3qn^L8UMQNqTXdPEK8IW^4hM6eAJBhYT%PBOENu^v-gNX7QK12>uS&a$JLX+%E+_p zkb9>fbN^tF^4=h2+wR>;7!`dR=fW&Y&DAyAO!y(DrOzF|eOYp9e*VMTA7zsK&FGp1 ze7qZKqZ#ERy{hFm5PuaP?o!@ybGy@e4}%$u^*n*L#Sga-ed#fI`GIk+j*bp0 z@JxUzU#&z1F%>!+FfV*o#3!bl;blE|(>6BG78~BKaP(KeWmJCbR^q(Bhx~Q`L z*IO4KJCW?wVO&pW|s-`nSyOD6|x-zLr%?o0{{nDH*EoTbOI z7QTP4Bqw*Bhv)<0kFe;w4u};INQ9?!bSRG=Z3NL;1Gbop)M80IL+xd+n)g}CXDsdw zOxS)^MYoH;pW!4d;&RVH@x-Z-%0sEwe9Pk-IVB=luhMGTsx#J*-98KFnUF~DU1r(@ zv2w*SjZ|`cR7J{LjDq>%h5EQbI*)}F)ld)HdWqov`u*vem3`$5i%;2F=gBm!5{>xh z2gfCKD!!$euAsf0HsAPb2}_>~zF*r8&I^TxnVR|Fq)B5lj9PUL&t`ocaS)_q0MtXp zHJqVIDW~~w%=i@9VeCMT$f)id(!2k-VBu2O8fzyl zU$zVtN9~9x;Ficfd4+eZ&eerayzaFZtG+B(-T(M_JsNxPhtzP3HJ zSXTWWBlu02^E!@)58`g6Yd4R8rT@>XR8Z(Wv-7cIHyA@0-2S-87&l8&L|b3EO#11l z_N~);ALvqTLT0JOY*Ws6mMMnxiKa1_(%-M*X8d1o1DJqU4p{`%axKJ1`6IOufdI*G z7V9a0EFZ~W`YawDu&rH9ZZ{h6k#d=&OznyH%h{7%?-W>Hr;EjPr!Jp#|6RfcQHV-o z*I7>>659$FpGbzKFNX@y0VQfFYuICe?EZ(uo+kG&S`+bMq2h_ntjD{k1BDW-OYG`K;s58l@ z`SFJeyKeoIngb_ypS2KvSk&CRqt_)|zDyV^Qn%3V;hRS-j}8o-Nv&@VY2}Z4(iC z>b6Cg@DG9?bS2#}{}2prdE~$j94dCgNd#as^63P3e+#ZSuQXT^{e4n`)c1PE6cPI# zg}j1D0Z_T=PKYoZiVh_i-=IyXsH#3j+bGss#pM9Bje&1|&SUoa%OImf0Q1O@Z0n=4 zIG@Ea#FEGNOH*Ba;?$i(-Evc>Ps%zlx<&>_`OE*KR;SAZKzGA4i4Uv>E}sA-lWGtk zZzJ@np)hUSvN4cCFA4&|XzK1oP$_*RRjBQ6*)6+cQgB&3grB{>{F`n9{F~<4}J!}Du}?9wmW#u>ob&KU>8;kzrGG-QiZi+NB9~3`9_Ne_wL-+*Ry3i z-M`IxqI0R9YG~l#t5m_?Ao0f!Cvkd=^~87U9Eh(8^!YhPLPrCb0`Jq-w$HbkH=?<> zwEOYbv8fIXu7c2GCQpRge62Z&6W0HEc{)9yc;#MrzYG>Z>p+G*rCRF95>>60X zdL7p2&Jt~IiwA*MO!o%Wt2e5=X*%Gmr+zCmrZez#I&HR$-po(%gGXNOeV_N|fXRf! zdLL13lN{x((}{}u4s&*X&%@Wfy$2kN>v|=<-#l7lO4?iM(e9c4OzNbtJlHPVLXFe#QR2WY?u zv2}dtMagF;szCkm0soOP7OsMp^p0@O9F}SqY0rXLo=0YeIj$ImheTr4tCx>qi$zT1KDM`Gk-kHSt6|N@zs9nu$9X#-uhqJ@nhk1Y{*i3IGYpGy3Vr5 zt2p2BaZQRL1N@+&`^LC4R9I#W^Z7rqN@i9=^x=tN6=(p+-wnGM6_59IawB&Usur~4<}j|o(`0dz86MG z*?q%9_k(hso)^W<&!R_D^pEp92!JwVFsNn2!+{ zNq4|Nxf0+!Z*0SHTL1tc0Zq1SkuF2(i?c0}6!GI_>bv`@Zds2I$`PsJ`3_>_7j4{5 zxw`jGaJoKK|cxnU?ehHK+}-)&}#O;3a$IsEhhDc6KfO)aq18IhT8^3ZcVtxo@9W%T+$NlJmosLJjs){?`DxQ&`SRD-mk&YwwI5xluazq4;(KB#3S*Cq@8Zh_yy9=e z)7U(kAfBXRrfI5L%c;}*3etz4uK}@mj`s5DpmvyaJ-{PLhHjzr1|Q|5nVDIXJk#e$ z;2_8RV7RB=8=THtzk|YCpHm`}uBvMMJz#-EsINuUfsme1S7$ROmtYY)F49EP%u|Ox z>bs?V1f}YgP?jNTvmK`<6k8oIYm%^ zPr8SKWtkTy336Px1V==ZIY56QCc3SPcv`}#HvY+v&7P^niZwp1=QNd4bGBh&4?QxuoH) z`GlA))-_J45%+1)I?-@2t5r{(+KPi60DF|d1$Q;F=?TIP0!Z`9WKF(1@lo7E-_*_p&bw}Syy1=c)AQ`q`F7_C2ny?v!q666P+wW;x_ z+^~F+FyofQBKtZT8nSR{ju*{jW@`4%rclR;K;}fPu5V)oIn?a~AG{~y3TpEgl7H@J(i)mZ zqfC-HxCHDHj!&mRWa|LOiwLdHp?i`e8$J%WcdwmrV*(x?hZ*AG^zk3OXPm{SWt?M<&puy17pgvtPkPON2XVkJ*ic z=7kDf=s_FH%f7D)_sKJ%b)4>(zA>C^b6}X;UBLTc4FgCPEpD=ak<++y(|gmzUl+YA zEyaGGgC+JIuyYY(7-SO72eFtqBqLouyBD*B;+vfqlD})}t4=l@Bm7Tj3`D{mI@uXI z16qDp7Os7?GjBo}MWJ2J2rT~u$3~$!vd>AYF{2{wbGRuAnxlC?rl<(yze9h%bCFr! znlqCzCK^_!-Kr^rj^>3;O#XY`PR?I(*ZFb#NB`O#ew&9BzBx*hSTFxak!}`FtHvZ# za_W0C3Y7{dN)k{?Y60#}@6?u7-yC5WTQs3c8rw!%`1lwj^yCm)UR(1I$5 zXXu-#@V?4s^nR>aHl$KgXuq&`*KhGSP zqVQgCO;S6d6RLt5l$bbx{c#3`KNSaaY?q@LP%Ao4?ceXEo9nx&~hh^rxu8YC;%&SHmACzKn?(`x`ezg?rYt-b&Jq{C{9}rt}T3O z*i{$VRm70gp-p^QPD}ds5zr%B&^4&169t9JVIHKJm@CiUM zsW^c_jd$~As`eK*5EF@DR+;DF0e;#}KYf-H%H`9;*2DV3PO`FpF;d^0R|1O$abqhAA9Tz9T1z|Mb;gIChqvIk4_%Q_n4$p+y+FdJV9o#v;f?~TTXjcRce*^(k! zW?Z-n@0gv<380gxg>Y{=ph&rTWihuvbcKfHbqC~WkUWlL)P7zgY!=8EO4cuAUq_e} z(HOIsn78iUy*s=u6x9?c2)3NMn5e>;XFb_ zg{(G&(*o$^iF~HTb0)y_Zv$~g1&1c7JelLVQ&(bgu!3FGDjXDq2#kfW4?BTaR{(Ur zclYk{a>GrI*^^T#nkEL}(@RtrT|Mmhz)gp9WuoQVlx`2p05fsgQOfkE>BK_vZrQ>oE`Ek!{h<0!g>#bnt9pPJmljKvf)jzpRyP(DNSqk&?w(7b zcB0<}imQ}hnH?a`vB8c_a=46>Aa>QU zGcV@i2MB@RG6s9aq5#en2N6^5@+9iy)OPdtqWRn^DXH!E9K33=c$P{dRAFKcJ^USm z(*;0I=f(8gxG^7tz@vVEI~isHC$-G{qkH?iKINWJWr;dCcU4Usr`WW&V*RbVQT^ZN zB(gg_;{h!t$D{@VD)Q=8t4u(Ax9Al&DqRok+L=siElhF%+~PRY|(iVGMzt zJ4Z5Xjv&K9P{pC`fYqr=Wpp$K;Nnzpo=-k`@tR#SWo2bPlq^7sKZ*^Gh6W@c|G{=WhPnCTWAsLk=^TVBrnowAx=O?MlRNDT8mS@{ z_3dM$riJg`Sxq{~J?#|Owyg|THJg%!;sMn@Ig()k+6tIP8|1`5&jL%Sv7HJJj#LXe z)svy1sHl#0@+78Ofe$K;PYwuC(_^HC~jdJRWVpJ0yil$G4_eY)mIUq zlxA?=MRf`pMtC)GY8HajTrGzrot%4tfuGu`aC^rV<&`7YdXSql#hvlHvWRng$Dr`F zGwBv=89i8%?K^gy@O$nwU_fhGqh|5JlsX~;Z#~2b2D@EEfQ7sT7Cbq zL`@0|yQZ6|Zyh%6RFieR7&TpV`d2I_O`Nl4H)pasDmKX$7B<;ssF`6E!N__3T#zXF z@yw$5iXYhV0P>z62#=`sd6^Q-#vhsP z0u)sxr3j>4u6&v@2CUewa4B*^g(k`v|>Ke3M*Q zVqLU~I{nGz^07vqdr`}a&a@BdN+xu+uSqrLiWhM&=W~3+B(uqJ1~6H-xuvBAPWQ*2 zJ$uH!`~0D(LTenkIqNI@SzljUO8Gj4-5ZP1sSYS=v3o6WQ=C70u{;O61OdMtz$gs> zlMs#z%L^TW9SlvQc<;KxbQir;%^`wmi6bVgcZd+Oa-ldcolVfPHJ9({`&h@lPQhtv zkz!FYXZ48G;3tWIsFka=<2u_b_!bTxlV^Q;jKnH6^=08t`tWb^b&GrRIYDEb#gh{6 zguUsIsFj(Fa$9Wj;aIb;bT!1Tn>q%k=s3AGzHU+@J2uC`6$A}Cq$}Y^W1p|xxKU0V z;X(TbEJ3n|@AA83TI2k;Z_eM@KL5srumMY7z4;Y;p6lm>!3|Q?3;xAF(=TcB0Veuc zHHua&oDe>cCtfdC+`4aHO|v7g3dmHdQ>DKH5fOq6HY`jX!z=9A60$3#3R^ccbp_6n zK$Hr>J>9XINSu)&I&>;3{e17cBgck)bZeW=AqyJTuD1 z-p;Jz()+Ew-3a}0?h8{0(*(^v?V^1{LFek;0F_1z{AFp@Q2~}oJ2q{KEVe#(?%d_= zFHmu$f=Hd-792X>mfR~I#`)>ANtuJ+*4tu+7NuGdV zDyF5t+T5K(M!4-1Puwmt`6l`sUh2ETOnveC?OUo&fWQB!t9G}6t!uXBUPmYlPZ_=) z2TsH9{k6+j#{xZWu{GZQ@^&u~g~ckR6^mLsT0B;{WLv0@NQvF9N-c)x==8c@x6MZe zw++pXc9OTZcPeD}VU#mj_K6HKcCs6_6_VoUuHlN5OBmu1hl@#XXUnN|$t-yDhR8}w z6PQCCp;`ViFv^u=t;rv47#0?>WjyQ`J{`W)D4gTtyE~g0>!i^yvFYq}=+XMoV@Q}( zZVd}nbr~H77)g{rQfh0R8AA|?6l+JHhGW2@3@O3TB7?g{ z2DUDghJ|(nlW*!yfs1P0qvz+3PkI~?Pra#PqjgH}!yM1>|JWLJ7j~(|tCmO%+=M~q z`Ybwnj##4RCzKJyaT@xDhJ0dTn$RX`K0WKz;4$q++tcMYh_;IA>{P=rNNn3t z5ifdQqEZK^J0!$-9f2w7p4(i4VxMVzs$1+ZSJ2Hmo!_X4Zd%KWr&93z= zLoZT(Ot>6cM>bH+b)s)FIiZl2c8F4VZl>Kk89)B4K+-eCcgD_nIh!35K?ow$6GZCR zzH?^)&kk+sDHJ6`jweo?xCFT)h>| zxetemwcEChoX%XgDEhpa8rf)V^wxOZb|EI2T{9(&u-#=cB2Qri*9p0G8PPr9bPs4b z4x%FSivj>b?kJZ<38#WObAsB70Ylkmsg|j}AsvF~&C`KC2}oE-|G;Gd%dRfedsFYpO`8n)eI6IUtZrrv_Znc)x{-{Ek+oJB@8~5|A;_GO!_HCw4 zj78r#c5|_!(yySgi`O)20qLxTLi7rU&ZsNysin<Ha+xvaY@*{z@vsj=%XKO+YutGP9Qqpn)LP?fRt z-~rWDq|3q4gy`nqJXCCJ(uURC+`Yq-oW6Pd-W46+sJAM57OKjTmaGaTsH3-jvtkIn zj^T0srbX*p06VK{Ydbs`eq>o4f3}Inl~hx0c`az9o2#>&v_7gHT=2kI|K@@lg)^~c zqW&>PWlhmT0O0h^ZMV**8&uHrcHZ?*ESV)}ZP zG#|e^A93l|h`_Ti0&A3@5WJl>Ha#FQp1o)D;YJ-%on^D;{#+!_zDLq?*PG2(Q0=r_ zoU_faN6J^PI#^omv0M?a+;N#->n$Tn5PF1n3N$2!E|3~@%oW@%7k@;nMJ%m+|L~`H>{nXmB@4`QOp7CNQyh3z>BoauuvI zt_bhvv-mtuvvw;d5xMyTP|}K-A#Pr^1$NW4b&VJQ{%) z7lmIp#Y#rWlRU4j{};b_xqJrJy8qzZ?XI?=1p`O+)ES>?d_iuAbojkuR>ZDq$#v=5 zwvTVSWT>u`h2Moljw8Zi?WBe4fo1I5x9^Ss6Y1rQJ0MD-=c8(ep{|QW7;W2`OuBQG zOW4#t(k8-T*lr$a$+^*d>+3WYJMXya`0eo^RRye+=4|7%1HlAbEZh?Y1}f=;HNli+>cEYV+|>(nz?+ zqI}l!3P}$o)){!y7#+`{M?lSE!w~Roqb=f2R4F>+n8O0y(VG3}1vk!kBTv8Nlqr4e z%l){=BRDRm#bBt||IHSYp}EcM*(}}vT7vzC-oC2Qu_8v5>Amq4k|H0LE$)UttXK!R7t@%Sj_qXE0NNE=9gZ5QLRg)1}{u3V#Zs&9hy_IT~ zIMjBtzeAJH7FQ|*r4vqt+o;VFO=zv?HC+Me#E8I{pYCT$0X4(UCG^?s+A&r9TBUm}$mdrr)}bro+TqaZ0;ueO>AA zuC1rP93N=~wgi48QLayt`Sfq%*rdn|9ihkr^^KVwe9!Jopmq1)XSHR%wm72{Qg-%f+PCq&us7rv5g;F`R99* z472`@!~`;PdDD1QbF^#jl^w)m8z$xU|FPYG;^c{cS@k0*N=ZqT^O9r^-ToI_^g1HT zWi2u}HEyDQ4*l@-I?q`!?TCk?E z|9sQ@8i5}hELR~!>^*fL{FL#?D0?oQDW6r0+__@LZ9~*I@1UoD7wamQD^mKv6TuU( z*39b}*fMWDf0x2ER0@A)(jV7hgKQHQ6F1CY=R;CtzJ2#@WN>is(STW`b4UKYx9?lw zc?5`+ENv|7e(gh>^f)^D2z4QeRs7!pN>-Lix?GHttO+=bYR=Qv*2eeGlo^l*g_x({ z*x^9f32izVI}J%|WL6JV9s_oALt~ah(l7uoObCuEN_@NA;5MSowoY`{0o6x`AEtHl ztQ;k?Aw?Yq59jL901|2G{(s*MzzssM9D++qWU&iogGzw3A(?!RP8#<}&acZpis?F~L5r%%gh)~I-`TsBsW)55W;c-n47=L9DyZ49{!=^^OH#-t8 z&RGp-0Milvc>wTF7x;41qU7!ps3$rX*+&l}iU;c@6S%`{ZL9MJ9H*8tr(knt%a&_e$8v~o=hLB7Pu=r#|Y zA|v>Fkb~O%1TE@CcW6F83dGGXik{`bz?5^oOXByi$TtNO|3s}HDSV>t^(>Ay3%r_gd+d7ZHLws4oF2HY4e@LZbN7ri9{3}~og>}}lI~XL92h4v z7wpugRt`Dmd(I+cpSUnUy#9CZHj8mdxn?NRs<_fY=m@9HZJe`*Da7g*msBRBEOJjc zPEoEKawY^fzz-yEY3I4;OihjCW!>T?__LwbV86s8eB+%@oj?BwgMo1L&W!h4!YYB} z%--2>2@{|YG4cm;Jtpm8lz2%CMECtk3v#dfDE5uBZzjqI5ILFEkIy1)`a_^dm`JQ8 zfQF#|f73-b=eIbK{xPIGI*?NUvaiC-VX($9tivI1JOqNa7{XT(%&-094`6!4Sm)4Q z`XZWP;#-Fx5L`@pav-uy>;k!eoShH1o4GW_P;scMX77wSY#TDgdcjb)VGRP%_82YH zJ$3SAI0)0GNU#&3zhd{k$~%lZRs}k(Ty&o2XAANy-OdJwWBno) zi?}`|srow&HCSSTNH~6JI^Yajf^wdA3)m7Ut+8MNJ`}OE7k?X|+gnSv#J7b*0%lbi z8KMx#ifkq08KV!mTtMAxBih-k)+)J(NW9EKrhG^X<`S|b>TVW9pPd?CcsZClBf zb!mw@SLP_=w5ubj7!zU02A`mG-908WN(dq*hJ$8i37Czy+0wDJq#k1A>4tMz7iaVk!+bF@Y8e@pNox3jJ3Qu%x!QEbbSDp>{i=oM1@VcLmz_)OVykai1L9CM-Oh z5G%fY`!W3e!eex8s+|(pNIY^J!e%ESmX{%mKogD_62JrZlarXuvS#$)`5-bcW@(yv z?zo~U%;{BOeRz^C{O|g5gxa)F2jZ>=@|Mk; zpI+KO8i${C7lNk!-wuQx>DnN z#|`hNG8VNOdi*mF{4o^lz)yj8-cPYQz>82xxa`b4`0F0hfeZjRV+GPY1^%U#E5(Fx z3j~p(Byo~ACGVyyj=~vxv(r5Shrq^`Nf$owAiaI_X4FpG)zvj;T<{4Yd8(gc!I`mB zd(72ThsQiLjNa9(4j_Hb3(7lQYnH~UKAY4;*uumU^mvQ(yB?(DZ7>=mh*Vd0kOF0Q zsq4M1dG+PO3DbiF-KxZWc<&CajM5<;P0b*Jkbxl$9@whU`^PaeAu7KU!J^NUN_Gec zRA*Q>Yc<|ZJ9Rm3$#)U~Zn>f<_$>qzJ#R_`v>)5t^ zwDx)6CJ>@?zqo>!04~j^*`ap-S#@|?r5vV`<}_l^(`6EhO{NVS!33H_fI_cVKWva0 zgs9cddAbKFu&R5Ce~Jj{#1W@7>u!xcueh3u=qp*0vGx0G*ADINz0}7V;KF1B$hEnbT&>LM$FJkLT6GF!@fk+ zkR%>dA&oW^PnH^=2YvQgsej{lH*VO?Vx@pnMKjeMnHSJ0oQ)jIp-s3-Gb&rm*E;F? ztlOuILwVA8j6tGiyOk6dR}R>z|?GKK(;GCm487*0)$f?9Jq zs-lrZ?Mf~rjGhb~#`5M-t3IswqjX)30m?qx`$Hh1(>@D<<&l`8{vB!{cGXuX*OS1U zrrt`*_;TYgJ?SmxO8!AXonr2oBuU;%t?Lfjt#^gt2$xq7jTRi^>}!0llACnpi3G*xM0)iZeO-Zl* z21=X}s6Lc&X`IHT1H&-Rk0m20<{lFLBcZ|n-nNCbX6e6sl~1@j)JCvgT#M(G$Sq)B z6A~ao#XvZxd?+qfgP}uze?KwR&%xjdH6(=*=00W&N@I1Vp{lAsp(_CK-P+BsNN9|BI@I&V{Gr8&;;_ir zk7P^uUx28nX6QRe98dx)my@L?p3_}ZNuLG&MA${pfD#Q8!K0uO29F3aa+*}T*!u$7 zn3#fqh1T?-NP}Y}%_T`Aw0 z4WgQFhjPnW9Lm|Gq?CK&8(%GzVG03Y^fO>Av4A-EB=Nr0I75}7mf}sg3N#YcpkR?h z&squ+bFV$&+(gWcG4y);qU}j^G$Z0Fm$HJwEy5DmYO)~;7D8B?3QP9^4sg{zi8ud!!^ZY?iYpH(iHXx1n~|vs{&X;=+lU<6Laj&nv`gMcS=sT-B_cxkGJ;^ zz1|Tnr$b<>D}knmpyD4IN+Gb<4@3R_V&%UA+$$*Y6||IPp&!)n&2z8 z`f}XGO(?LM3w(X;)*5+AdYXQpJ?G~N68H(wLU}p4yZydnWHtalhfBdooH;lUh-UHm z0cjI6I|9N!aNxj%E=#~uV!8~mzcT4+_-pK$UIba-m#=i+5OzrGl&^pC6M%3o*)um0vO(~`sn}mp#-Eudb>I-a4RPta8xMXc3njGB1@e^y2ko%{O8BpDwXZ_ zn=lQpBfhjJTn}bmMKw9*B{o&F5}N*RfXgAF<#Hpflt=?e{U6@Hzizjdw8Z}3iQqgy z?G5VY>4lBGjK5b6fnnwk!&S5H%bMoP_(Ly;c@lBcZQo5B;E0`{OXF!3d1UVTmUXj= zWEQ*s1};5Ch(*_eE!qDL89;O;k(yI#AMw;oW?jMXhv}%iy!VWACjtm=F;gn*PxrDQ z_AFC7_*FCRoF6l@eOVRLLiG>+tUG>;$v*JKP2|4a2pBjh7fpmIYMKAuC0hRUlCO2V zLf)x=Jy}CyjYM%sI8FTbKL~zRva&ww$?JG0ty4xfeuWs4L^yHvUG9RV%k|90-i&r1 zRA2aW$w;4PsYnnzvM_T%Y;!yuw5m3e6;D*g6z`}M*e76?`ulB!2mqN7#!E}2-GwOT z`~US3>l8-VY#z!AmdskC3H)~E^&$3YoAJDnt$g5^zeNBlnfbQ=7>%1LL{~H~>k-C- z@be|=U5fp$Y`=3ntOA&~9f(2bND&zRYnSPd2u^DG`Ap)f>d~t4$RRB(rOY9{^#0#k z)$lk_>?O)o4eafI!r2;^iJjIj#uPH=7s8XTad~*9=j~*1Ns-dXKg-J$R^sb@HD{*! zOa2b>R;#X~?jhYQ>gjX6g@bf&7QbBm7b$SXzjG+Dz_BJtF5v?#3rKn#doCQEc?pTJ z>^4i6@Vf5?t9~vEsdyu?%kQO2mTJ7@^eiJBHn%7QUz>4Vi0vGeEmWGwvxIbssJc-b zt(v*$7@se5)L(6%M5wpHAGPA&A9kuK_Ly&*ChwuE&zAkVj(l+XXXt=EYyWt z_nqseB_Idqy;(()`3_#K8v16R|6JJ%^A(&;!&6*;se4Jq0>r&J{(@L8=4wVDMjAX^GKW0%Uj-DdeBU*E}NS4SbLLEn1-VPPR z%v*-omd)hFgFHkI$oAf{YLC`Qh+#!0wlkwkTKqVa#zpAD^QB-5OpNCM}P?{Mt z3E)5>G)q5kJ5k$u&A5PF=+cYNoA>kZ%5Uq7f4I{pi|hRQ6>yyP!%z#!f-S!q-uv#B zy%eTfcIDi6D`@X7`q@)=at)9fp)FPclY$bQmQ=|_xfz-!WORLKE9YB zFw$yntY$LE91*G}E00C>cl+?qM*sjw-MEz7p1PBnG3H2?+<&?v>2Uk@Mcu85Ft*>0 zq{Q=Qi{>k0dvy7KMv=%ZN<-z)TGiLPHKQZfLJAhKNH{h&H8sIKTOFI(78*SstkH|m zi&*uk8SqTbuAA+x`H-)y)Ea%r8W#Kn^85^t{mjjId)R!3q;Xy`R2q4Ga)9_U^p!U?PwQdnHd1>fI}yy4iP7$v4+Pj0{F`N|geI zF0bV5y1Dns#l@ZVYOawOTC)vC-L`pX6KH@(oe0^{bXF(KBBBT)Zx!nJ<74#&wFZdt zM&zV@``{NxJB0}UCmK7BTohDL#moh~$}%|AbR6n4-8csc)>RdcLX0dZj@r7A<3vvi zlwjem8QLF_ zu5f^J%SDB(XY+KmM{?L~vRVd!ueo{i z6*!@Qoni{|E&&cyNfS9281yuUZ(cPFmlBg99$=Ph0m~^OH8GwjF-!dwos(bOM3PEg zYf_NEswlN#nsm5iR~MC@P>ElC&)bN(6~LEDQXQ-Vq3MI8tc~=Oz>Q&w?JxU7c%@_D z-0J;2(PE01aZPP44<5JJwV(i(ICiFpmz0!1EXof3uJ>Zg7K0$*hu+I!w3#YO0r>1d zS&Ww0TC`UzmtP0G1rWqfY##(GvHm8!@0u@90SPpCfFa1&c(If*^krFv!0BvZqN2jl)6fV7 zJeQOQiTD~eD*88DD)3;5Bzr`s4cvVANnCa`L?|ZVXd+~478UrITWoD@m2DIEK3$0) z2HFof*H$2vz`0?|vm<-zr6SCrh^vo6lo*vKdn*ToK{FpbiwHLJLLvO1ge>=0c!#&qHDNX-S! zQ!6j**|TTy*BgPk5QhM*E--z8=d;DkFt8W_N}!|y3l70tk8J~U6S83sOE#@F@c54! zF_BvmmqVfkUvW;p!FCmu6TFOdM>Or=3~qVJ1^Tf4Tmp>dl4vUs9&YkiR_4q`=)Uh}}VtkS^X;P(gb zocU=drWi*Gv~gIOGsVOnnkSk9F%aMcVtN#MU2EC@Giogs;XqJ73mvFHa${rWclWtGA7pOEN8fTV_(7v5$10!e%U^-B4{UC=AxtiP1vmCo$hc3<%vp zl9D6n5<;iYoBbR5AJ;bqMk2B$Kh1|Fbbbrqw-nEOoZWJda|W-{((<7p$Yg*Sn{l8N zBQ?PBND_6do5rbpkG)(1*C6t9$t%e;8*%dft4~TY<(6%}-)#99F=ifH?A1vY5%8MD}Th*0@YRX z)wMbms#0sP~l%m@2C;xSd9hkL-(psoizH}3K9$Y=jUa;S;kBi z`5Q=0-eHonjBuPntU~f$mRy?a0|5BE=UZN_2O^B2hB2heV1)_)39;&CP#@It$=e-P z==IMtB$h7Kn&R4hlaKlZhg!n6Q_t9-t-QS4?NTRfULX|Jb2{@a4H)vIOs;>0P<_8K zx@hFsNaxS2$079rLa&Xkk~L_!*uER>0NSw9@+}kblzY{$tj$J~zFV?FD;H^!0;dO+g3X*`oKuxrwGN`MW>`X~GIKzL^iR zBiuSOX8g&GpfUt<(eN6gc?3}SJ{$r+gM>cwrAbT${!c6iy=z5-ttn+9VCh@xIyfZJ z)HHYq`htRjrbxyW^%B7x z;P8MNBv0O=tsQ|Zb*+I*$2DFW`H&=I@KV3%rMFGqzY&F>{o($DRc;7!=rbTs>^8^Vt5+&=&XW_q5IT21VkbCfy`Z~_?(qJv2OM3JE3zr_FtbD7!!vkA+ zXp@6|L7U5IRa5G@4SO|Sc{90`K)+Zo=Ly6dTO|s|Ntec!440l3Wa3LZjk}<5 zY=P5WIC_KrGL}~cK@pAt^2j7m+_W#5J+1C&R_Txqy=P>M){HXUn8{Vw9`>&uJJS8PrS@)tTX6O|YYMy!r< zku^v`?_c5C*R#S|v77U6K=!|igB2B+L8=24Tx>?KBLqwKBE|_i(wJ8V_w?7%7E;9P zB5!?|m2xa`Z2B+Ra~hpEyVAb(M&}WTu*Uy=@u3|s(oEcA)_c$M?isgenEj6jTS+l(hC(V=KdjHnTH?){*DH;%Tmzm#~BC>`KpM;h9`PWI9x_f z-k(vT>q08X9`-W2nZkGi)hVIasS;$RswyTe=7xYn}TlL3>u8G_t-oEw-4Xb zwTzJkQ->U7Gx9CWh}iR|tQj~F7eZ$((;m(UJ+A98zPSyx?>J%MDDa5M2YuJg-;$%x z0aE_56qV0GbI$`fj2B|tBoEz*$vS2B7(aQMk58!NE8){X#f_qXa6uIA(4{9_x#C{2 zYw0Joulq>(B3>m5!&s1-6PAGb4Fb#&Wl+tc`_E#N8zAu%eJ6d)ueXWBDne8NK}-{k zAi%vNDt=qms5a>9C0&#a+(>@D^kN$~YVqm#KnVrNnDp#fy9KZGQKbOW#tY=$Fc@K| z>hyJA9YGDh7B?5y5aKY3S>%PbAPBL4v>FF)0{-;n$EL2~7nfK!1m?QEjOu8PsmWhH zgWp+zx^w&wD4-aU;)lC#ien}~;k9EM)~{dB$I2EN_JWxSj09lE5`1F>VP&v97W&}@ zY#c}1M3tC4bKY5T%G2{R8fo-I>CA)aAk&|`|4aSml_$Q*Lx%hsROJgA1ng=|pq-q_O8mtaWCD7GBKAho6-gcy>))<;vgPn>7f3MR@r% zPg(1ZTIwsquWVXuv?UV$%=FsK(MLMEx`DB>LjjD0l>Ywk2c++>kIpbGXxzU3af}U0 zDl%^nV>Q?2bHGQnf&PJzB}|w)Psu*GPLRhxvQ583+BOU`?}R-cNl;Oblc@`l_uuf5^u7A&c0d=|`r)V7vdO*M1WSt@ip*^#xg#z$FAv8=V075$!idFJ z@1UPcXHhUczHK0br9!BM=Z4bU^F@Up|#s?69?W%JqS>x zFb*IW7dSDjkxSD!1Y8Ldvtz9DWL1g$gc6aL+(>#&;7nWIyAUI>E8uxXev=a6-y%+~ z%-88=Urc7T=AEhN+y!*5vn=1G#w5~dGe{eRt06bEa!L;gAs!GNA!Nc-;mC_2SOUfG zQT=9|lD05csK0tvF|yeOkP#)S&S2HjF$a29s@w+o%=tjj=tFfirl|FSeGB_)UVsu{ zR!EDQiv`1z)oIo!HNopE1vjM?nBMljHrKu|&;kdv z8uvqp*jWIX^-p#NU)~YWO3#!~K;n~#MUWE+YG{!Li|#T%4mLI27NICDU&IT zRLNj;)vEz0le6v&{OA;*Y1lhGQT1V zx`tG2c~ydxkr==Q<}N0O_fVHF zguk%~csQL9A=s2?ZXFm?!!dBx!vi6YNoW8f-{J`K!mNS@-J|PE6d}DlYCw3^%;cdvMN)*nKXV=PnB(Fjy@0J2FkYF1d=#6E(lVL($N?0f$F zWze9shYlS|TL+xn7~*UoPQ^)@16#u$@Ud|$?EpEY(bDt;{!P7aM)x%sS5;2!(>O=B zfVk?cLvA?fzRQ)Ar$)Zps444zu>a(dMAremh$o$2(PX@^nXq-LEoopEh-857Rzd2r ze|>~)H>T7_apdFP;gMNM7XUzt0?_GWX?K5<=1gO7H4S8hM6I;K@rbd2s^x+RrmS%= zqXf7nKR6C2#{z?NT{vKb#|u3`2ShJ!@JONREfd<=b3OzUtK;j}#4>Orz0RNirKL+} z{)CZ2QV(rY@!3KuQoza=0>PiN7^}m(#4))9BRMXk{W$1dM`qbufDMESiLn6vCu1a? zaOx~@X({~i?5UNImreE(m@jj!vbSc)l=MM=^*_g~#Kc{5We(aTCgk*YW9Lz%@nIN3 zPu@ryYx}eoJcCmd&vwJAg%e?(^ZeySBvYmXm4&JKmbAw*${%q3Wn6t;F^09up7 zEPGUAdU4Aj$gkCXr|=lfkyxk3Bvs6-Ulb+0n)%jEa~p$f>7(f(WSK!=T#+A40YZjz zdLwFC7p)q?dDch&>wu&=LuhNO`-&xw|Qw zzuNYKdL`G_-E52fOJmudf_Kh)qM^DMJ z(Ea~`;Z^+ZsP=rHAL4PpU-p=GmTf9pGO|^z(91Q(4rJDfTmTC!J;<_ z9EaT^vC#YuqoUGC!*Q`9M(~e49-b3Yw7ar|G6k1SzkK`l?Wb)A60;ournV4QlnOU8 z!J~1T9lO@z)&d;j_q|BPf#5$HYdh{~LWl%E>w~$`c?kh#`u7ys0k5xa?^I155P-ma z`m^&PY}I?!5TN2XreIh7(r~L_4fmk)FZI8U*$p2xyR_bl_by>oJ&krNQWAkICUEql zh~S2El6-Aj!ED_Nk{G0tDW>IcpRvWBH^pjmu^21x{!rhev0tAFv(gBsJ~(*nP`Jd@ z1vxeD`{0iu-|D^tUydN-JgVErzR_&$n zlrP(1K1uq(p_yLa1pqf~RJvP>1UCq}Q2s8ut zl&*@vvhs)7DOHLbCs>HYE^B;ZHshXV@Fr@7TLI)K0^0CnhdB!R4{u*zDB4ybCLByN z4@ZBDPWq07!P8%&^JbGqwprB4xuNKa*dEKloodYk$Glip0+v?}8&t4(zTT9V^UnnZ zH9DpNc8QbhTDNvB8SovyI-fD7Ipi2nSuN*6CmY7os#FvOYriHZ`ZROg$h2l?!9Z}c zo(%cO(#WOpa1!|Xss|>}&|uxT(IPT0EiJe>h52h2QRJSckeg&TCh};2ARSsXvH>=l zsekkoL`6mtOH%Jp(}Py6v-V(^w-PTC?N0son~)+I2RUTf%41}aqamtim~Xt1gDr?J zv{pjheg|}j81VJWtr*8SD4BmGh_sAVlP4#yIwE%jK{tUd#olvVW_>;yFgOxz$Ekcn#eDzSRu{B_jsKf0<_Q;^H^Dh_l^%wIPmJ8BNx7U zvB1kVAO+UCyKcaTqkyC~(g6okDGe>H>o`-K+h3g|wx+Oc)t8Y^`q{t1^$?(8iJL(G z@}P`&cV4tmo1MB?V)Y;l1E)L?xES7_`!oVo9(>2tGd=|-C@A^rNT=+aDoqkhP=XM9 zG!KdJqOF5puD>vA1M!%nz$?ccW9erftSeZ7zeoXBRm1q~NB^#J_`y(O$8o~sL3;2y zsrEOCdVZFRgqI|7lmZa!NRk+meDogmyZE3!-?PPyMQ0w+&C{NqT2PnF(A#*yx}kUu zD>8omkbkw%I2Vd)03#AYjCNukYoK|<)VuWbFzJWHieDtBH+J5K-tW>H-$BZ)&2h=e zI%FtB!;WyeVoQ_c37O?qoING*Wesk0s($zj^{7z|LLYV!o@0RDuEQQ}q^SHh6amA^ z@~hA6=+XAY5<+_(PAp{l^@sQZ@y|8x9|C`?aaVKYZEz654S75YMEe6qy~zLS;qGPD z(lCZ5GD;e)zuI^>^X9STAOXsVSjmX|h=F<+)sH(<(QnZVl*;@(4cASIl^=gn6YiR* z{APT1GB93`V&&`ZVVE)B4pIE2*f#(Ie^UPSpT5Z+$EPqEXlZHvNXmiEY3vt(!H~}` z#E9P?rN>cqb#-6Pv`NG){B~JWai-kc@lQwsspY=lXZ(LVM7H+>^Zfw7!OCm^6C$Hj z0Zhz`?@49U??-pk0)R>ovJ1Ln>H1eXe=iy$78|)4dhn!KfgeDa`BpT$oxtX988PW`2M>2 zGnv*s2YnCR5uk4{T>P?l|C)sT&B_k^qi@TG`P=#h6QvS*Qz^g+Kp57bpx=!6j2(>W zH4z|c*THaVA&>O`Z8~Lx4$S;G?p$yJj zBY3#rA~FO~Ouj~K<}lefzRU(g?TG0_eK^id0F8h)dP8AD{_xcSdl9?(YrYNe3fzh% zqnxm8H{8srGXWjpYs>Xu-V$U&%|s8E$}fJ1pV8mMr)`p#-oD)rwHk1vEznbV+Q>3v zmi~>xOsp+wP(3_>xe_${%M6v@l0^i44)8fmq(jhzvp8-j9e;2ZUkjJ918EjtC{4hX zOzOJE(V&{^YQc>rL8_{%QD`(%CS8Js$+D_H&tX!?*n;{rxhIjBlnDg5mI{pjyRp@!@C+GSrI&lv88u2+iq+&ap6L z#Zg@@irXkmi*QPP4{pX4bQzL7XQNvL$Z2m+XDfA3X_O0U86X5zf z{a7K?n&oxxrxOFk4ZSuf9S!J)5}9AD9@Pfvk|AR|sx!EIOY{2y%*CHRbf{h2zBfDH z2GUdHGIJ!+d_T4)&s~s%lvl<>D2r<62Cp5tUNL5O(&5N)0>Yh)3v7Y(I;GMH{ImoV z(keaj2|ceyyQ-6&?Hs6mY0fn?k|09ClZ`|p5GJt-F}J=IIK;r1uTVC2PZnLyKbe=i~uTHO|N(O zVN_8Js5ic`T+Bu<A9=C95gxqVPqsEk8EWZYEqn52jiI*B zHaS^CL-z>p?Wc#&HMx6q&-^2grr$j?|6|wv$6eXy-!X$n7c^Vy=~e`Hr7E@6+NQ>? z&Fd-;PI)N1x(wW9%WgFO{nPThF_msTE=np3XTbv7@1CBw;K-J>538!GWb!K7B_0BX zb?0IUKSacM+X_5x4&dR5g9i*4=dfYn!iDHi{W&pM&NlL)>~ZpU0J-gq_p7GlLZfeC zR6Xgba@;ZGNJb(+8nvN-n{#97^yw?H?3ZR8K7820BrjOWV(F((pYDjOHYR7sZPG<< zm26$>xk2*VtAxX%X6s6fDt`)WWF~90sC)r3Pbo+q0~MWh$ZpZKFMaxq8MKRt?gG6c z=!kxjs@MyUtkVD#ai9J1#|i+(3F7p3AJbG=@`_4r2@7(^AR?hhwfW7rcT;!pv#Jx< z(t()W5j(;=AV7Do9@ZkImL##P;`Hy|pXQ=!vNfQwy>|V&&h1{9yQ}u}ym$2#vu!A5 zy?XV^=cMZsH0j7Y(C`pe0TTAuhYr)GP3y!@S-68H6=;0MaUD(ovi^eTs}!k!uD+z- z`Yg*v*T6`Ph%0k7BiFFszI|K$^5s+(j>bYzfIdd=T;f+)Mvxv+V8#ZaI0F_ZfG4mc<_{!Ql~Wx(JzFB86VGC zp!r0}Vx9GJ85tC9v4yn~byc$4Yb5IO+2uZOTw31iu6`JpQu*M)wR_chG1Ge-E?g?F zmQYHv<|yb~onDD3bN z-luxY+F2?UMT92>|7kpSfL|BVtRkG8b7f?<(U689(>J|ZkFHvr*f!nHY($fBj$@_F^NSi0#iV! zJZs+XJZ93Qh|El7LawnN(L@a=e}4c97fUo_bV_8<+)tEIZG6t&e@S2c#OrGN)Ywp2 zoE;s%=6*|<)h)f^4k||PLLXeEITf@V1kJ~7NdmZYod985VRpa9(cZTWqzl{Hyvgy& z<=azWYm@(41iLP`O=xCQ`=NE#)p9Xdq=!)#XoWK?ASO_`ajzA;i z!quyW5mw(GPk1U~#FC_7hekXG0Aqr(*^eKu>+S8$l97@se%p$6jlT!x7teoWRbM!h z`;5ck;3bj&p3m8RYv1=lP#8h5=4t6WwnoZ9vm~heq~g#e$F5AdbM0ildj5jx)2}?_ z(Xaz--huj8?}BwxjD%ptBu(|F zU~a-g9-O_(-});!w%m|ex5CQcK6?aqEDhYz{675gKN?oEG*M08Mqh=v4EV> zBYt?7vsHU0j~k~^9YCCyx7x3e%skm52|sDB3=#o^ZHW(#xM|>O>7`q*<08e?03pw# z$?1LC)*WW(Uf@0(xep#OaVq*3QPtn>gt{zFg5CZ4^?MT3nuapk8Iy(vmYzI*d>_V2 zW!;6^4wEEy1j#8WDaEH0;DX~2?P?-Y9Gb6VD%YO!j(2a~T*DC~=wG&b$t0!Y(l5X? zgr?MD5*KhEbub+oFvnxu#EIb_J{;h70!Z3;`MW2P30&raA#co$Sg;pOU{!;VyEG4u zD_g)zICu8!Swv589>TDDXnuf^E%9`a1zvb>3mRy3ZEcvB*ErVb;6z0bGr)b=ibzAO zk|RfsxSMg`y?s0GR}>tj^|LPI$cVyN>d4Wf!=rOC!ikj5fPf~|lA9_dn~$+9NdSw( z_({-tQCu%#l%W6DatL<}3wblq^3nT%4Agv6+R>v&aa*sWWid_%E;7>yE&%d)ytM4a z3;N`srKp@Y1%pU}g^f?ntsBAYuTB7L6oEDJIL|ZpoBoLz=NY?ernJ$Mi9~TgI~6x( z%VAqu5g7Z8<6dJo#^sPT2zqAq;A{CDJ-RAg8ocmfBS$8LJLvz4qpTDkgzvT`Dk|Dh z3PJET2z{S|ill}~#(#ayzc;xqLjYjAmc9L53EjIPpkTAuCr_Tl+I;i=eH$Svvcm$shMx{4$3>g z029asd9nT?*mUU03Z4dIuPGHgFfB9u+w-V>+(@oMQ z#ndOp5Tk`O*b4tmwAE$o!QI(K9!?c$P8=Duo2I8BProyKAhYKs7`L5p&LW2@LRlVp z&s*ZR9%{_Zur9#_hh+pik@-tNV4&G#L1yg&INXvJ8+o#A&67#U6B^KGiPTR^KIH6N z0z^5vMI<*Lu&THn50@2&|}N!D8N0 zc)zb+OiXMq9@(wL#6->AjJP)x9eZ(ujcVV%dq>oI+!j^HQ{-HGQvnjqWZ^(6fk*UZ zFo+wVF28(gRLJJ-87|I2;F@T_;6|2Dq>9!yJeaPZ<_JN{dCI!bfx+Vi{P9?2jzDHI z4&^YMf_{OBeL*yaR*)WEXQ{3SEz``Po5k@xOw-e5h1!PHMNDe9P~G12}`Hs z6kwqt-uhg+bP4IH$3lG=_HRIktP~3Y<(}3oZS^JcB0_E@^I=mG?VyMn7J%hEd3jx! z#3vu>xP?Z^-qdu%>`^^{dhe{(U~bGEJb3U(;ic=5Nv_?nL38)+Q0k4L-7b#!jK7RD z$VlImVU#OGji;sSM=*Ql;Ty!c<);epqzUpEE8y0OHuej=BO$d=BmnZoIbQ?{hz*u1 zD7))G_~)QV!Zd>2_y1(nix8gduA1*uHBR0*L{}guPnB_ygXK7Qa`1l6ie<2{9B9e$v5zfhm9WX zx=ULiL>zWU#n``ePT*B9rTI8zyT9K5%B8JQ&%wz_IJgf0w>6nPrKfywL7RexpSri= zUl@IQGvnC=yO91jpj6VDnA;2m7EJ*gSc-tDjwkKaa^R8|nNO%qpU!NnKnu7Po`w^M zZ3YK6YLI5p(R}&x}VD!tK z0^wcwTttO5JcJGhl1#6Cij4RuJ3G6PQxxUZnp354ih0x|>V8Xipi*J z^pue;?cBvXwgUp*_5kA_3`H`~|BM9QayS8C5793d!_&>$rK$6fHLFycOZxJG!U zfZHug+>T2GR($*-@ymM!RM>1FkX?9>N5j!{Xz%JU=+!UILWo>wm4|B4 zor?o~HK4{l?2*i)3)vaEHqA8~_!o5Zz^j#D3$9}m(pG|8GwT$S*=eQJb_gPnk1Z{? zcM37~R><<)4c9f!%C8tgasR^y@e8_)x+tX5FZL(qy#B;8uS$=>-u787nH#F$XN@7CfW$YRQ;7I0ibEfmJUn}yW z*>jYDI*TWOm>`^uXOY#MJG|LmuhEoI-qYGXW8VCZGg6Gk0N|{&2*FEQfJ>ujamRB2 zv*$Ik4kJ5_g9zbl8{`^vNFl-6>OEJJs@;TrMJh;-ilC%38!yO26N@UV2|*IG9D@3p z&X_)(Jl+gNCQjUTy^P5$6@71M@8q;yYN6d^XZFXVkce+~YI(biWl|7wc>SyktDA+S zO}ySqGa*Zov9T?gz6PK(=+R;URS?~2v$C?AJ{qSLctj_11VUP91|Te9*0OOBg`h5?gG|o3 z^ESBpwtcr46MKAvFK={-1BiAqh4dxCWGTh19|V6ny0hp1XCHP`~b#n z3%GY>@|RfI+2ywhG3t|O{7tfBYvf`VXfXC)9K=M|B1TbLcnPsRQ9!J&sDt}`X6JgRJY9Rt9ygbimJ z>H*T5f&}DxB!|g7Sa(5#)ZSh?5T97SeYv9}YeJH#q@-kw|4`=9nSug!{B*^{WoFNd z-^w1qOOc!$HMx%%QKhiY?qI8kZ%+z#?OlVojd^7g2#|W4itK=NB{03Jlo3Q4gP~xz zJclxSW}##Uk4h7W_V`JY=G5^jOAg@GrmoLJ2bf2r-3j^;gh#EiC0qFd?ZZ{x|Q~5h50W zRJQX)Rj(2EH%9%FXkSH1UfxDTEOuI&b9yUyvBby59tb^|KVsCVQ4+k1jQT7}KXFQs z4r;_WWP|N0gWZ;>28UXqn;ue3 zp^B^e!cONk9$<%le`fAc@J^|jF1nTz3GU--tPCsb=tFVvsV={fv zxh)}y*UXtLHjWzp>}bUFM9U@24Nu5KxJelT0s{W>4!5v*GB0exzKOTQNw>h?H>DB0 zw*-?}jQy|o?%ktWz%bROzHp`8R$ysF#sIu0#=<>(e%I2_uXX^lJ*Q%J62OHA`I2F3 zn-!5ftD6uU>KUh(V)V%);+}4@O^(c`*46|^3FgLeuzf)8T8E;SEoxqM+m@#V9$#4& zmarpw?jBrR9g@zR-Al%|j};a+EncXf`s{52jxyoY{*1U^wyPbw5GPhQTe(j3_wg|* zSQJc;J3_2nA>euT-b9jlc>Tkb|lbsC`6(0OR zda74w3K@t9K=IjP02z>Hg+uMRbR)qTrZl>*tQ~JLA@_05{&mo#L>cvSoBayVM&bPm znfW~y+Mq3YaLetq`zi0)!d7I#JSh+C#+TANmebDkNBV?f#-jY;UnC;$*UBBhykU{9Fl0r4!~Lw_YP3R( z`U0zG1$;cJHka}8M>36_wa1;P(jcL*qoPdxcK64J!`f`%#04WN&0wKW;800Q zoHabJko_Y>WYjrv28r!q$WyY)5st^V3*jhSnAXC!Ohqz_Olg7+x=YUSW@l1Bp)x9C zLZVUIabz~GTNmFx{5Q}+7kQ#Kw`j%LA2edpl0RiC5u*_VkcU*v268~S%j5aNr%!@d z9(8fi&Lfs|=sQDBGO(0*U7&CPIS~lCg3aMc3Kg9C>j>qg3G7I_%5kL(qdo!o?mPm< zMo)PakDkm*o>E8kSkz;=6ETD7_WEW4Wo`TJ*oW|6onCtg-A1GQPw0z=l~`i|u~Rtb z+3YK*X$7|l!v_}7(VOLhcTm~6Y0}^#?5t&3$X-!B><&ss3Qkge;2}O@kiD*eh~?wh z$3vM?8{7ygH3p9s^%C=2KZ}Ty;C0^ixB##sB$}#zngYAn1+j+pbR%$Seh+>Ph3uV4RLk zNjuFcn?~_rgVUA8hRO!5zurHsuI#-|a+2*Q8FkrXCr?HpmdHLPT#O1^RhZnqOj9w#&aS$oJA^b<+*o$4{_~GSYu^jkT z<6dbXE}2c5%&grH8WOSoEe+jUKE!@R*uQRI1OP}>KNg?f%HTAwbm=mq@yLHR!zDHD<;xws zf&JX9PUFCP1ntL0@OPe~);b;C`r$(X3J?pRUTs6g`n%nV$IwZT>yt9Go^p{C(cEZs zTf*Eg2q-rZgKEEU>ud4oG{^6tD*gNDN03b$T-euo3G6wEqH9|TsHve?|52#akyAV9 zFY{YZ=oQK$m1aJCtiBUC%^DoF!$ypN!-aykg$JH7MhL|KX+2dV>$Y|$mM(F}p^F5N z9M+GAtt5q3JG#ifzAQBfXSGNa1H1T?fg{438<+Qs6~W@bK6#G+>w9LpX?g`y&=kf zg+ud?1e^aizv+fVbCwG5)OJ6F(U{M+9hBhEb5WiNxA?K~*Uk31z?*J=&q4mf5|_le z#s3}um%mYxSfhwjLtjDB@cdW{)8aW#b&;3O3*-NzkZu@&(YG_vqww`b|9uy4BK?{1 zS`Ivd|2zIKf7cLUEz{p;jvWK;36ObloY9Dd7w{q|`NM#zZhO<|yU?H%RTBjbz@QHH z_TdQY2u)j1PQ~0hA%@t#0iGG9h)v!I-UxIGFm?I(>5~=`ub7YS?ZX8n>JT4@41<&z zX4ElYH>v=yPPq5kL22BHFN;Y$0jgDTNbcCh$a&B$TEoV)SSQFBH2@R9Yc5AJ|HX^# z|gKgl?q>MsQ6flC9C zF@w#u)d8h}nRwUZT`V1`QIBW8k(iZZ&eE z=YT?>oiN1^HsT8`(4PV3KiR#2voL%=MgicIid<}%wHI*y>KgtN^cn%gh5x&#E(j<{ z>#y1F_z zI?jc%9f7|H<*PgADp*sL#XnD2hqHF!M}__6cQ=ilwY~s_TyEa-<;!_~#zE(?Jdj?& z^)!+SR`e%V>q{z;gAP%mS?rwMo1yNZ;zV}&a?)a=tBfx2l7>F;V8a2*cHW=TtA3@G z|1k!B6*)%F1sFsUoY^dL;2^U~Md!|oC85`^6IMjWMC0{JSkPBG)J_JB<}^@$Iee$l z2aqxiN=Zs0NfjN>y1KegOi(U_!*g>L7^y0E!0*(=LE(Gp()PnV5m_rS07S^6sI-M; z@nv+YtNq3z+vw}ARU&VkVO`wC@n$cU&UiuOZ-`7I;Mr~@4XBY`AA}t90F;J7$k=9Y z-MaM*hwmCUF4yaRkOBWAX_zDht4XkkRSKo*=C?czVAerFK@(!8u>b{7NW~2vo@%77 zehyXJ9{0(Bi-BGy;5e%4gtf2s9=s)ZX!?{wx4xK zO|z1SE{W7(bqzlVY=d_j|MIxkz2l!pGL!y`rLGJnkz1fHx7CkFF+-b#JH(Ae)d| zy!(8sz$?`pqKvN!F$Vb_Kgpleh$pC--6{hrt z1-s0RT0pWH4Y}4C@A{_B43fp0IY%`VD53UkI%K510b_yQZ!?LoZZM<=+ z09wvyqS+BiKHm>y+n?`;cS?%W&02eV`->hJ{@h#~dhObH zxiInA*jTFr2gGeW(Ax3yIP>DAMC|MREBFI$#hto+K6j*}AMIY^og-~!5o7LQJKxX3 zqm92y!vErxM$OHMPnr^Zp(?P7)@=z!-<2l$WM~x|c=I2c`Sf2d1B2?5oFR zW&`$>4dfJOOa$j|+p$y>$bOmL%dY;~C`6c%LN}gi(hgAp(4<^2N@uGI$4y9d4ufh1c6nJU5 zU97gDyb|hPqI%}$AsyCkY;5c(Jv&KKrLwXzs~zziY2?KR8(MIbLo=hJ!Pgpy8+@Sz ze-Nft84hQ!y4iE)L_FlBBqu*Y=?rTO>LMaJ@D3xp6jyNiX_Ln{KeXtUFG$2kK zPYGV|^1*|Clhi*QXe&uOUD{Hr#&_rg`wN8>vS#0t6m)vNo|pjvYVnH`pxHGI1DLkt@eG(|1R!xYcJKH+DLne|AElp@L*+Nk8GT(Dgq~ug z>r@ux84GTos){pELamhauqH_iGnOg}qP2rz+Kh;*WAkO(+?&wIzkMO==RgkS+#lpNt0Ea{0gr%O%3w%fdpTj&1r}~=F+j&S z(0Iq0eqO~LnP1MjN7H`0?2OVK-{Xc$_wFKO;>SuBTKEDh9*E?C0znP^n|6T9=kC*lTzxf}T gD*R8}Ay%g=+p4I#ly^9l77ApIWlJdXX?_x-q@-jTmXNpXwD7ZFEUbw_0z6G!KJ_Qt5&_Z)34Z5%Dl3{Iep?H$Z) ztOa-kdCqg4Fm-gabr9v{wfg59cx>$N^PUr8k%f!wv%Rk2fI_kV{Qs^+OD77{E)+^m zM*6Nx>~ycQyUNm*)Lch{{Ph!iDnCCeG2Y7&;O+0PX?Nm#3HP>UIuVnh*_Qu3DL+pW z^Kmyt5(mfEXC*5XyDG2m)i9cUu(GyA>rfkazsF(5U4n(0nR=%7Xo8!=xAFMcmGQ0Z zi9OOZmt_9>q90@3>_xHu^_6s~93@Ko_ZP#ZGk<*#>+b*hJt(rKr~ZF^q4>Pz|N1zY zJ>I(<|Gp3_>Odmh-ygP19~Jl4b^Q0jUi^I_8PxxOOaGr-rQ~QUe79ct{)|BN-YVZZ34V|AWv${pM=$<&F%Ut=?O#_V+4$NYNy;x-NsHx|uQ~&BYHE z=e~)}o)8mbM9qbIZIVz+{GcH_z%Vc#iNt$q;L%?(?KyVNp=7H}2a8U%k5$w2XeaU~ zCABeXX{o6_dGu&cilO6V3n`hebcEr^=;(vZ`baK~q_1|Rt3&%kac9q+Q)>He*7`2B zMbfLY#7#KfWoX}z$yV~o$;pDj$Bc8;bP5B7Z+}VOlM{Q@b4|lmg2VK?vW-p6%=C68ZUc`}rNow@Ak zS^AlqZ9xi$noro-yzeDk`z?^S)KoZe5}xRayL&N$KStNm&7JJQuM z$6m-ns-U<3ogXM{>!NtCDJwr$+vqIy5VLo1P%#g?pWwNknv{@gM)>|wmmKviK`NAp z$E3F=o-ny^Y<}dqg2C4pXFIXZnL}IZA64DAmO26O*B)*H^5)N*^qmjEs+;;^w~Hir(wvT@!d@I6_TVu{hLk|B=fydk$$G zayPfIup15*E~1RZ;c&z2giPE-^PA?J`wEUTJx51JM>)=(t%#R!`{Xb#ug-NCYZV<6 z!*A0kZUmpv>)h`rpR!n^buuZTAwjA?!^UkYHRai}X9Mk$*Fu?z?aN_dVY*fdGNn!{ zz0SjLqja-XBD!+!Q-9CU31qY>Zf@j01!qEu{C5sM_e#hr+I&~Xw>Ysk@7{f0Ue9Ti zRA#zlV`^F+aENm{@@;Z*Vo_0dx=_*3%X=BElhcxP>Fohpbv@UN zWp`=9-^0V=xm%|M_TQzXq%2tOwy+!dLYtEC_T4)JI8OzH3@oe>Ic9@{mlyYh#nYd3 z|KZMvKr-)@elHgG=lfW^HnXOz&a9|MixkI+KR9Ud{XEF`>t&mq3tY3MTfHp;TD&t;hMX9RN?eR?E@97;vh`Y5lLSyUJX7BW`M zS-!cnbbX5Rg0L`NH9+L;7*A55R?%{(++*!_?WJU6DthgrgPHC0fCzMk3RhoX$EPJKgn zmLWM6i{v!!FmmsyPkz}=4nm|w;NXU=Y-w~6<_f0B|s!pndg1&#!a@S5XUk@ zLP9>ny=LCnU=oS6neEIvWnDOWxCibEee_1gca^~5`}qbn6m1>%d}SoL8{3rB`m> z4xYYc!cWJ3tNcsYDZ8QSeW*(}Z|+CJY;#JjEW9|Bw`}vEYf0a-YyC@p9)XlA?S#y- zkk6m5VvXnL=T{*+O}{&IC&{8C!(}|qIrbdsG#*0@iSIM7=luT6<^FdW8B`m~#4BjD z(A3lv&5W`lc$UBthh*<+jHK z1W+IsEG#TU{vFC@(?=~~ZO^sQ>^|S`^6}zNKYZY#KXT+vYU(~%HHHhOG#Ld$6sOtP z*02w(+rNJwDt}1A!Oacjg7kwbr;@UAbBUXC5Q~)VbI+E3$(>CHY)8)h#;cBwxe1zd z$Cx&vtE**_;k5S@*fEGYzBj=&)YeL?svbVa$*HKJu@6#2a`NdPGrf#ePpENl?L*XP z3K>#T(l1}WT!POyckUeWh)~av?}^g$6oK+AXyXfe{E&p)GQrK!@dDfgzssEdt=Nmr zgjw8j(A87+_V%{xKg?c4Ms}0!ewUnlf{l$7&UWRqlUMGF#S5D>#s|NA$-oeN6?MtM zL7;SNS*s!KIC99=f_@?Bw9X=@bX56F|M!nthpbkn(laT1PV6n)BH9om`{5LY;|+yk z{NTuTTJ2O(OYMb!R8Eo4(_%h)G<8A(^I$YWEw-;JXkD_TdQw!h+pJ_cVGE){f_WUr z;ziG{5YIK?C>pf^=bhGbtxk_(ZEY>PA3K~k?!sf)TclDjQ$%>=@4pu_dvA4auri$O z=AQKSa~rE>W@hLO*SQLErF$ zG@IUSLtn#%9H&DTb1?iS53NL$l9JM+LWgk*KmV?E_-gR-&+`|&Hs6D z?CrCAMKvSr%4SP9rnAqj5b;kSvgEp#tDn+cbewobbh>rxz)aydb32~ly>>)#Xi(6L zhzi~sItB5;T+6yhZVnEPJGoNQG;<4eyoN*7Pgeo`-aG%QCj;xTf!2n|TpgF%nf#Hn zzU~UCja<0jT>wq&CY7eqo~bguFa*iy^W0!nmRT#itQFdbk6~_gICMDLBBSDSFr$Qg z$FqnCzl|9zb&g5HWq@7ha8XlG!5Ji6FCfS`R>JK&(e>&Z+J4UsZXWFPc`o%&BTx%8DtgcsL|{}GS$wC*Upm)UvjbAlQcoyYA7=Sr>VPAxu**> zKB^Y~Xt~KCr31SI1k%1Z5x~^c5601RFvkUH#Fjz_#?fy}f;P zEXKwbGN-}j>U=;bkr&pH2Vl83a(I*a`&~8ATLu?$kaW=T!Yr{^?#7 zg69)6GQJUA^YZdsHi#I0qc1d&Efv1=%O^+%pS+eF(2dFsR?R3JJBIBLLr>eL86g;v-ttc&)Q9t%$H|h>LCCV~IxmOk(JpA3 zK??Tlg(HQ>gsi$BZEm`!7*0Bh;t8Fd>YEEuWw}~sPMspT7Q&=hBGFsqRCQap*9cS3 zUp^aRSi6ybetmEV4!ENxx{6XbQ7uz9jd}dLmW?a~8ZmO8&%pUFXOOsfh;$u>O;f-(Pb`iS_qTUL9m1C4S4NrBzzzWS$29O zDAABl{kGf6Oif;gZeVMQ!p*+VmO{fdNA#)z6KCG56W1!RJ!#Sq?I&>m+n2ul#6*GGZJ6{%aV&ezzKS>RAb&8Cjg-=9F$ z=jgPh`pH%#p;qRqsD~$067oy7r*j(TcDDO>77K2}-l}Hm5_4I&3%;KA8hA(^8!53m z;JXS3f*9$s+;yKp*gAH~%5`<{$vo^LUe{}TZQO;J*C9@Ig74KW^=zZ3t)7*&`BwPY zNHfK}6YT6{9oi0*rE6o1*ikKv^&tt&aRe}-AI|0GUg&XO{CPwmi`~)E3f$UQ8HOgr zj)G@%#<{Etj;dWPThzb|b~Zm<(zeSu>fZMc8WSCvEaBndcT`m$b8F=z81B>lHcW2r z0K_5=`Yd|tI}b*}u6=SMsNx9_zDU+7hvOO+9_~|AB+4Y=N)MrbNkijRZ$3n9dD+gE zjrd}{KtKq$inTQl?C0qDO9HMxOp%*IK1|ec!W&Z9bT9S@0>w!w`=O~UtLNN?NEisa z#%!kv9RZ(N%jq7M;oynZ6zZg;B-_DCQp=tKT6p5T{m&?TyvO6+s6^ww5yxX+zVwIW zj@M-oL)XuYLt=o2MM6B^X`uX}eP6T@LFJ8<>ZU7;_o^PBWM}_u zxB(k;y6i}*=Tf?!2&EB;HvsDTXu2S~^cT!Nw(2I~eNcUM()2s-S}PxpM4*?dUIsRpue%vDGs zExB(K#3)P!#R%OW3`9y5G#EpR`AAcr`dKe;_$QHfIry+c;(nhKa2X1Ietxu+6f_Aq zkJ6>@T4;jUHKGHy|nlk;Z5PylCaeqcz*VJc>E4p(hyn%H~< zXPvf6@uNEbmkEx%!=30Nv0`4l?TUO73rO4!e#{7n91!Ik@Yiw7KgzI?g< z`u+RsN>~R62S4bb#fWcUg(~4-a=g679*QR{xgrr#87$n#k(`p^rmZ%)G#b(((o_ch zK~%pqG==GRw6&+vSm=BeCwj4%Ry1%umjORa*y)t))(!IPWjH~PpjVUbEb}VU&r+AcWNCh^j25(rok>NxY*N`J!?yYixOOMoVAj6;D*qhMuc0WL4D@=WsIQA4S!6HJg#HjXQ$^&5*_c>_{LCoY`$M^4F&%NSS zxqFv>rfkO(YiyA4%J4g$gj(Di9=#oZ7$6A-Y3+b!NUNRKHZC6<8*`0S?mXmM;SFq; zWq0mA1@ZYu_ygpYs8ch3h;d`!vs_@fra0Qw|!-EH>g zb(YJQI!d!I$3RVAf6Z1=XL;T}4MDVfj8|;A)@;?*ra`{4zh>*}>Xofx`tDn((sjahfB76Nyrsoo;J5VtbT{$Uu zE3f%LJ><&BUiU5(7mFh}RnZNe+fnp5a`(^^BwUx5M`NLHbHw@%u^2{YK)-eM3#f9P%Ob0u)g;Z*SN72izjvPihL-ER#<5`fvm-#o&J z0ft-+s8RS!!vMeRHdpQN1n6fGk{~*_j(>s)`Yy5A;#T5%h{GFf_Y+MfsT_z(+K7k< zo({+YH40K&Mi{Q1ub3l;4vBCRfGjgGG!ztxH~d6`g0c(jmeDK$fY#?^x#uz+H{lu1 zRrI#B_&_TI5d7ZS!f5!IU%dE(^H67uF_sX#`T7Og$l8{=ivZM@>1dyHj5}2S@cdb*jYwTj*$9Nk zJ{NuSILdQpqhE}&+5xKFOa*KhG198PRHw!H^5x4uLz7aX&ND%cQae4?UC^k7MMS(c z_3E>oRt92Er%&xC`?~)(`|48;#h@57P=nJ)}yXB!9Nt!wVS=j|Lw~>_toXD;c zp_m5w#T<)!BVWSg`^f=Kv}_iHXfK`3SZ4;(GfBVVmlmc-;~x~{c+P8P>h&kxOkB2c z-E^dxihZX_t&+khzW3v)y*@(=9R@(1VTUjBP=7w(&}Xlri&yT_v?;`6dd~M#OKpBq z{{H$5z&7Wj#a_US86WS+vg8>kI#5a<@;3ghZ9UpC!uSJ%(=Ku=+k3!G@2h%Dsr*JR z{Gv$$uDbfm_HmMO9p_%Z7cc0s#!&Dm(^{%SG!pmi+jsrOjRj>3pQvLUW`>4uaOW78 zmX*KR~Fa;<$e)>HleLt1&ai|oo=&NhI%Jzc)iwcc9BpY_v-Lo znB7yzM7{}Jc;gwIRbx9Uw6gMY0>&4iz_@?wbfo)m;X^<^$s(XI8=5BsBjtB&tuIyO znzi1wxq0(upmJg_Xg}iL zD~hxYK>Ar_($Udf5ml$<=pij3m423&0GR)au4ywe3DstRG1?H9vc^~yZab;~oooEvU6N6IV|pngAjdoyZiZ9D;Y+_~o=P`Z$DGRlGU(2@5W zxcE^c$K*) zQkxa|A;a!NpcXy*Fs+@6w6;I=S0PD+T?oBzV8Ci!wuQ#pPx<-zbr#s2$|&1*Rl#>< z8D4`VfSXYVq9vEpd201lL!8)=r%#`z<)326Wif5KI$7m)wudxEN8-_n5y0o{P~uCE zn8-+WH!4lFqs2EQGa)s|T)S4+_f6%nhmKC%)Od!W#yW6l=OjM^H+t7J?4sJ}G_=E+ zE?!6nmLwZE9SI1jI@QuX(cIcP-;Fq>xf0ofGXC^5Fz`x(q=%8s_>8C%PGxKkfE(LJ zK}EIQ9mav)B~ge$tl2#vCv9hXL^S#j-FRnf7m>v?E>>ZlH`J;iRRf)+9s+Kc=kdzt zU)E`5tVg_i$Nnb}>wk&S6s#c{6U3XLM}TIJ(E2{<7=9y-^L4Jf8zavC$INmn8Ln{} zn1DwW`lzO3>YBi^;g+gop_0Z$nyu0F^_J@7RnZj^NNg$8)3c~i(2!-XygALO*)SZK znwFOBMm)Eudk$BB=Of@>QSQZe?wde+upK{jN5tg96MLZ?Rd=U2QPqfD-imLoo)txZ z+FMOfsht&rR>164o8%fuh6po(bOR5Li<9Rb-y91`mo_!Y=^7`VK=hRTzx5R95nvT^ zIm_G@M&y_-+M>K2j{X4J?l6#RX_!H%>7ZL-d$U2oqknTPG_p7p{_*?S7#o0z@)e?j z+71nZXz4P@(jPSQC{S}yPrD<8nJ?O&$S7SmZ^zRd&^A_6RaLDtyF3EJdcH~3$HnSiXoI+7Fg+C3$>$pN)K{AGKE-?d5?@3)oeHjmM0YzY0huEH}DJG z&Ft7n1-PTuk(xexiH*eFNA84fX6ba4LhQwdKp+o+B9%r|4y?FqpsA@D8(I62<0rjw z{SUptnlU!63oO7MY1?!BA5_?v?k9MR-OcDwxmtJza7O_`Xhj|kzKT^Mm^V*4x*#%b zWS;SiSfmYg$Fu{A;k=Q5>-p!kkLv4h-41b{XgZl<4A_?^XZ4F$cbZ`C{MZT|BO}4e z;k2FLY=-cnC$?MY<=C>5Wm)>ABcx=wwW)_q2|0c9nk|!#x}>_kldgiVZWTa(t*EFt z_#+2ldk`#zfKDbc^Z_WRrlzLeU6zke>_zY7rU{*XlJ3dY)~ExUM`86R8y>}-n1yQa z$+}k*DE451&0vzc6$k6#PKzLA#Qt0J53 zDWrp*`V)7czyC7{niDUQ-@Yy6(n`N7qM@cuT*h&=zUy(t7QggaL>`bREKO z`I1u`0PTa6K3h;J20`qWH8(#8eU6TN1d3#Q3D{Kp+Rdm_Pu-*vx6o&a>!9W46@F zGmlWN)r^yW5@TH?*FOAgWqp}wv9b=`bHIudJfBU>DLHfVwAS-DE(MY7?CjV`Ct|k> z9E^|9d&t)X1O#k09h}r|kp6g@VJ2Og(R{M`&6C#iAKx|ar5|)H5fTzInC&Y;*D<>c z?1H|ou20R{I^)JirEe-Iom#h(NJ!EDx#id7EbajCGHk}L1u;B)N_QsBvwmU0{)28w zx3vZofUAgTD}@s|AH}WpPEMo+Z&TKr%H$LSxS$8rsWcXW&K^75@$0v4)ZAg;RL(lEDWgV4M&36wCA_*|7T%f-RLsU}w$e9COVP2hLAyxEIQkM)0|EnK z&xnya9!u@nE6TdM%rv_kakGBFUl$gKAe@2^>7S(c9^^ShR?yzQm40gq0lH^N=7h`E zD9?jryDkjcHP+*Md;2|T^wKa=l9J4T6{G4BdL0@i{DXs4wq91S^Yb^4t}O!oLs*?O zreRoz8sLxPBBi!|w5Clbw2hui99KuH2LO|uvg@MeWM2tZ`TG*0*hGj39Sa6v&N3az z#?D@J;09*=qC!@UL70bS9>fzfuus;nGShZ(M8w8U=iZWgW($hix!ljrNKTcJmF?o* z0Ioq$!iy=Ce0ABqWGXE^HqrwK;echQ)wz2qvuU8(R8DSE?}27WzV5|~=p7J&+f75% zpznblosPWylCMJHBeL=T2wwXd%v>RuvjFMuy!7gU zCUc0c`@C#Q8Vb0Km%=vj%K5R{z{9K(ZM+D%?v;=BeL&G9ntY3$q_5uuwb1B32?Eli z??&2=!%bk^toRr{*$!Ur+E{}>#(njMo#;J#X$C9=wKGnDAEyn|-vUlY)VSVkfZc1U zf-MJ*p076R0yJPmd;_@v6cn{|IZ1?PLaLFq26#2z%~s88le)W=E`$FBkZX<>8d5Zq zq`UfZspRSaNs2L0zju3txJ5i0cW3xc#RK6{3`&8ypj;OCP{cgWAS&Z;aai6tWebUMY^#T<8Zv+pq=!WtqHlD+|)9q?{vT$P~9w0#v0|a!|oH3{I ze*>TpU!t1s3h02=Y)VFGUvL8>$Jk1C2i^KVS9xHmIb0hMx~G0mz%Y516c9#QS9V*7i!7^Vi5t zAi3v(ag}qtgjgAn?*o^FMVHJO*bQ5XV;$}7gZX&tD_5@gPArr8?t(VpiE`5dlpTa& zmBBbOY3CZ^s1i&D#O#aXW1^$AzY&=^fFIzu>b`(Ac3Ykf6EDFX(Q|)@>G#yydc0PS z2$~m;ppA{$Ahw?-C9!sG)Ya83t~#iZ40^6lp6SBPf4)L3F><%m9Wt8BLhTtgE5zL( zHd9cQDus9vbmYlt_7*u29zzd{=hiB6OdXk`0l-}CL%KiLG};n~P|)y!MZZWHbQ(#? zLcddT*tOfYZ_7JaUX_tS2zFH>!%Cl9W-HTMX!92c#TA2GtgO31TB`z}9P7CZk#TRL z>9soeE==#_CME68EL}f$HTc+QHq-2>P;no?J*po~o?itDV-Aj>7&k2KP6%ga@j)Ob zd~`E08(rYP;rH5hho$;__=kgFLQ&+;Bec-Au`-K$aaLKIYRuFD6zp4Ia$pp;&edW* zew_P(>r=Q$%Z$_Q+mwg`SY{juym$NAX9Z9u%W`GYaLjJ?X3*=2dn2AKq7ZaEE|6p9 z2Yji4!UE34tn)I_9YhNGU86v2>Vrat_zm=hVkE3>E*wLU5kmC8l=LXVIf11j_Qsgk z`ecd=M9gVQA;l}8G0#C#73JQ6EAlzdXupVvDC`CGFb|rX^A!8{6C+bnQie0Vw$i7p zR9fSl`^;9ljm{%Vh5W9`WiUC-1FRSZ+9i*YVWKnZO=JUoo^jn_Y)5RkAC!;F(l5#w ze+lppiGZij(bP-b7MZe{x+QnTuEMVK12KSo^7#mlcKP}eLC54WITmiJ@PK@s6WpWu zVQ%#!>e?`j?)IG5z{*a#lg~pN^dEFJl2xmeat%py|yu>eHuBCw};FKu}N+O@QPv z2#@%S+X-x7n+b+GIRHWs4t78vBM!nH(nvvbvg8*B~MSfUWZGL)^>@IH%=rvmf?>w%a*pn%dr zdxk4j%mYGw3s2i-F{30NKTdm zWwGa$t2=}yx~>e&7hoMCL$ng4`u><`CIO9hyfFa>oQii)(18>W*=yGfYs1+PdET7Z zS_zBhRtzT;t)c^|-L65fLm&Kn2q7E>4*)&}@O>CG#!IMUtmAqmx&X5_rzo%>aqsCu zUJl7Y@y;E6Ah{dakR)*RpCq6eWn)vOfcub+$fT!9CLk$<*X6nnsSl}JojrRN+J5qQ z&vmn?#TUZD!iJ!B{8UdpK7#=WF)-dC%d30^CP8TP6I&-g0VAK1z!-cr<;0B`Nso1X zkZeR=~wJV1i0`}Jea(SSBC;!mfF?g zJXKXx{L<3SrHpDuMSFr0IlX%V=oN5IRDfkhP$EMKdK~p)7k>8J(IYSRl{nApf<)Ib zybPy;8KL61W8SAi5Q3IP`BLCMRa$yF(Nk4X@gYQx(sJ?KjQHBfbL8hCpBQ7{mRO~v z`bULAtdyz{s~S-I*hP92w0)<&IvjyyNXxa)&m0w}RswJ1DnPX?(`Hr(&Kuoh zP?V|w$M9Kp@?p8^gi62AcpwTW^lvF^kKZEUh}eC^cQzNZFOE}`VRq+q>#(c1?p{Ho|i0gp5-Z$hqU+! z;jv>OZH_#E-Y{Fv^dyJTTzaIKVL8|)P%XB6VA!DBzTuiFB9pJ2EnR5Z5RDp+kePlb?at;D;?hyv>lVZuAGJA$&N#WE%=VuY3*- z2a-;JVJ3sK_5ruZ#?Ma+7LhAp3`1H=mi#+fpmml*PwEdCYY>#&hzl-np|31}b3YF_ zF2H08GYOlCBzr_E@4BCW01sQJ?uoD@(eil%UlFfJPmlKIq=Hu^h~5$zjG$-$m@$B+ z1Khv7NXdSqnl_H$7!wnA#G3-VBZdG5WBu-2Gxa?4L!keEe9%t84-y0>{Z11w*GN6_ zv_t|q%+(QWU)$DukUv0NCxCckWNiEzybn-#`HltqhlXB*qm3jbV0Z4?zdP?&3M}|A zL_~kkbQhK5(%iCSk-rcSucp5c6FK?@!Fu)>Y^bjRoq#9CKOo?; zlF~tFdIKQ^yoR2(Y0`1qI?a4xaS=|?LufyN1w#aJ@HQbL+E35l>C>y&r)m5Q2awzQ z7AxWl83_E+;Eysa_uhr5XL;S!O19ENc|6jm7*~p5GWBl59gTsL=pd z^GZsmv+Hc3Z;;C85HHzU#-m?Nbm+QqgZX6yY_5u*Y9T-eDtxUDaUoU%cmlcT^DrXw zFPRcn+RPk61zq8QDp;RN-)f7VTSg2UR{$SaWkP2e1YF2^mMj==5XU=qk_AcHWR1|D zawPNp@_E7qFDNT3``QhEKFQ15XuSs61W`G5E}X0PKoHM#7S1vgN~0=Psa{5A=EaK_ z2s_NjZ~)~EZ8*}0%sONvkUaJ2Z=1i2%;~9;l|Cdn7+F1!iwg#F`yy#$ibBG-fkGCE z&AF-qcy!B5=+)f1%CuN16c94X3Z4S#J3bGHz{UKSO#TeZguO@7HL&gs0wxC#N*EDS z7zEAfVOjJsy5JB1t3W7Htf4SMtf8e8AcqcCJ>hqpxT7bOz%&iO#O2lG8)<{wg-xdOLAUz2F`Nq%_Pju&{vuMf6Jp2Hs z0hvN5DJACP8N?y+Cq1h^@MlQqV0+}ljJuaF??#NH(1Km7QT_G#Fg|f*4+&xbMO+iV zp@R_EEcV68-`~JMwy)Wc^xV9-J-f3_9i{7f7R(vXpj$;eE^tqXG@0yD1}0Y*5Wnm| zs{-5ZAy6e4`1DZ-E<*AmxD*0bxK+Sg3$y|$&}ySs(>|a24LYO{CfiH`a!a$E%4q`L!{B^D9E9<0G!uA17qTL{P^);h^JGK znIVX;s;EQ|?;|UXp6v?;PjB-USenz3<+aL$n#>2M2jn_r8itLHEk9uiNCIeaF98fQ z&eN#}Ig$?mI8Xw3M6&`a^mTIbp8JjQdEBAk<_8Vl7GT`_ZnB>%{pUXv5?q7KClGrt z{49b)`@MEb)Hc=;kF?J?qO3zYMe-LIdywlPRzE0bC=_5L1YJ#dc4X>>s_8zcS#|}3 z^hKvB`VbbW5YWHgynnw}&toZqn?~>MUBoo%x}?hlaXT0yHuH(J(e1~?Lr7UeKsi#6*-j!me<@=Kx%;D}0K>9l9S840w;VE|MlC}3vx zfd5Y#RO8kn#E%a0{C&3)DA7G=yj6HN?^tR|d?h%~_oIL~s{u@oY(>fvloLMtk?WAw zyYt;3#O|7r{61R0e(_^BN!(C`j{qvs84^_q0-?0#v{PCKVRFFss5rT1T`@Q_Mp2q1 zBQOB*7{8UFh52?E{(fBA`H(odHyB4A2c$K*25ww3yP{xcZJ zx`@s=vIU9<3QXtB9Z?1i(SnfiP@3fAh@*a?VB2G*7uHS`g@VBim}((7F+zg>*B6H) zzc=$`7|=mL5}p8w^{KT3I2=2z%B=80QG|~gIiHtz;34`ls*5?n&y~mRLM$jzBCa6* zPnZL199{>h4H5E)OH=LXCD#ATQu2^BUAYd>75{_wyo~tgWxFuQC>!J!vjQkX~nUof3Jw2B1=JJ)0e1GZRb{WzDsWau+GcOIm0Tc@;6 zZuT5>JCOL~8Mv14J4>!5BgF1ZJX|Vt!%C~)?p65K*TFPOrHdIUxyPYH2WWsCKghH6 z#8a_(l%inSS+;;Zau5FZYyay56PzIxQ9ZAvw{Jeit= z%1hjVbq*ij;Nj-Z+bRRkB=gFC6r|;}X*DXr?!>GAUFbYMaMWO>C^7L;3mT;7{2k~b z+U{>eoML0E;qlK%rUYPkT~2O3?RauMCWg$`%Ar%m&I^+L!F)xhaD@ud^GZ-XM9p_GE${Hkc{&?EK+C(!+r@{S7Br7es#V z#=lnV*B1TE7%fm9p{>U)yMpGGga;D3(>i_*L0lifW8e$LR{OgrI2FR4KOeR$v(M|t zL5p-xC`K031^R#5@8bD8dnYy3pj`c50X0F~0Y4#S(A77%r6`#H+Sq|6kPl8_6ag6v z%HOd8_nNV>arjD1Z0v^{b44DEQv?Fijks#>fOve-VJxVQ_|seYPt-C&>M>w;oj8f# z;pF5*h9R*!7$`n4xr8qK_y+PeBlJfo&AQSuK+e`3R+g6401R311ek<60$!+tnzLQ2 z^TYfG)qC*-Fnqai1)#v`wqC&lFM<$X%j*b{1>=3O-vwUXaslN8C=wJ38W9EUDlLP!)%u_3}HhSDt|IQJ+CSyzjOJ)Y;{f)(4jVONJ4S z8#uRqU2+kbD1htQYFhI#{K{8GM#-(BFcdW^xwx=^*s7pz?M4AzJP$K;2HFiWsyIN3PW( z0K*3d>PbHC`T;(BR5@s;S&;uj3H=Yoh^F9+WFgmLX1PWQfPHAK@mt^DJmtSa^#v&itme{^a=7Gj~WP08S+#rel~JH2_cp zZJ~YPw@3TvK0#rug;s@SMU*$F!Ep?XbvV7a8Y?Jt2>5^^83Mg&p>_%s z0mK3c{r9xfTbgrP~tduZoydq>QBgjd@STM)PMvB)5!lem;asB{QnPM4}tnQc+c^p zrn-6+yH7^Ov*O;>!p@yjo~5h&(=xgT1+&E7q%tY!ND>5dVOr2+WyjsJN$vta(& zOg^*Y3YdJbM`dIrasO%I`60BUkyQnFGBayJL%YWG-=DIwrt1Iq-XroSP$-XG_|ktH z;K2U>3Ssvqzs)rW ziy{!yux-7YHcao+f5BeAzwNhk?Oy?aoW{Su{_nlluAFS4c*h!t>^RAhdgKwy1E$4>5e#ag!;a~tp^aB69 z!Nx~j_BpMW`txAAx3~GUNZTeGR!^oM-02RRoqb13n%w&!PyLf1HGBl>l49Jhojwik z+gBRc8)}=S0Y8hwCTj(MPWpXg@_%nFH|w5Olo9~pBg^w$GhxRF?dJO zw{BEp^!6u;-K>tW>)zLSKCYKZJjmnI(58H_>o5yXMTw!Csl7HUYbtW}m%rX*0pUuY zbYn`RFY-E7g;Q*Z|7LP_?Z_-U4Xq*rB1>FQ1HuG~`rj3U{vzwCmvV%g(>uEpP8>Xm z;q#GC_E+6v*?*ZvF>!bcYUqC~HuM+O1G=FXBb7|Q?yfyOE;AAhKUh}d&(So$&3ggK zN58)4lNhAVWZysd^qJOC=`$1@qMl(u!n6FV7SkuO9(6g9ZAiO6G3Sw(;-$e`r@<;l z{cp4;t(osb@)nE zpy4V047F>HlQhIx_FvEc3+Zsk*iktuX+3ZDk=k;kfa2Xl>7PT z`U8$hiIoRuWClmEbfc@b{iJxpqlvx6u3M;}sjvy0s^Ue8kk_we=-WVArlF%7{yW$1 zzP2Y}bM@}UA6^N}T>1OsNy@Xruey5{R4Z_YUlaG9dGnaYkKyCGl&aE63YM;jpLDpX zkjDIYa3Ku2Zqrk(cn$gkHJw}t19pEGhotffktPpLruDKdQYW6MSlJ)tqnQE;jL}Z%*4Wgp9Sjx~y#LY}@QkjxtUAgX^*QaR35_|?7=@=c62Q7yO zW!=3S`$!CFc>e$opBK&3BHc&6jPjga^*8n+ty=pm()83PP#wcM7tKbozrr?D`n8|K zKlp+4Y}NrsG7`DlgLf(=82YLPlU&`svUiWCY4KgiBbh1AWqgb#49uF)nq8ib&ZW3? z`pk_p*{znj19d@4(_hnN-5pQ!%;ITRf(cLG`wx_;`wVWpy1ZYY>54XZ^uSaQD)*fI zHCTdR{$Cor6v%ug%w;2VTKMvt*2&^^4D>-NeF`8mO&gZYRqjt?iuoPqO)t6P1)4Nw z!rM-(-VkBPuDZo4*iEv<&BXDc>L#OoR@o=!h}-ON6E%wjd)s$Owf(nGwLJRrVZU_q zEX`VY*SP`S82c>o9HyG3tFh_k6;VfxU7T7UcnLRfvSNy5(hSL5{j=4%UP^gMf$Z;}ha{KJ3U}lN#zhS{zh~nw&@+ZMa zBqgZJ`s(`|J|)HPmZ%~U3`gZj3^i}5eh^oDD5YD)<+#8CL7rvNVtI(>O>NjypVp@> zSDCo29W_faiBu_HWB9nPb4Ko2NNl=OwzFRiIG_{omI~mAhoD=}(UL?sL1Av0)eoZM*jP3hSXPeFWkS?xLfB0b>zOKjWXLBk)|uRpv^at@G!woPqAzC?u&i;p*u5fbUL+-STge%=(YL2JNZ zG_^Tq$>3nm33hFDFbD^O-!3S`-TBG9{aj{>9^&l&+DGz_$J(paz&Lrx%92{R7*goStG&ci*92`d`{w`xu$#D!8KN=883D; z_2pzC;LPel@Uq%L=E>OQV<+skcyx;Nf&a+wfHx|9?7;DIapjhLPjmnIIwMHLPwyu# z-aC~l$3=I6;T-czUl%GzGK#ZIPgP3?oTQDe(X8=Es`O32iTrZp=%A#}H;Xv;V2Ft4 z2?;hEJ1`k|+R6c5mDIgmX3}sh^J@Wyw?7_aJ}v7)+4<7nJ^dGfW|Sz4P49s01q-pIMC_~HplG}CE85T4=|OqdXNz%~({KM53a z?=tv#)EuW_^6!IoVaxJ5=mu;sYDZ55b3A-;yih0IHJ+~ZDKn8Om@KC(=E}+H)93fb z?{ZXn-Z`19I@hJ2KV)i0A|EM~wq3409ldvi%XNNwt=vj1Ole5@+Ixps*OH@di-c!- zt*p@%jC;W+FXy|3P90gVF4j5Jb~m-J10Z1^zengRl?mrk3EhyLnKJKu2}(kwcSi<` zcXem^frOV_s+$(qcIC&WXK`aaZ7Dp3*A9m6`l7GWWmLUr;c!R&KB`GnVOc=A)s|RJ zFNLXh^EshEKX}mnm7 zDXulgWJ+mUj7iyhji=46GvNBM`GYf(=6iST-P%@|c0X80e@MCAvT}22+!B(@do%vw z!aNbaG{^HXvdeT|4CSk{=Z|Wi@IvxJj8z+c(bLBBxTM(;MC&lASK#jJ;Cz{uj0_h+%g|?bpx3lnHnN4fmFxg#$t~+gMf;?3UXd^XQ%)4w53+L zHqD+7;0;7XMZitX7#ls65DiVu0C-_aCpY+%AXyRA>0ug_Gs_;-aQt_$adLvIl04DL z`?9R8Uu)^`@Gw7+%qXDp{O}JCMCqW90yb`HYkLImh>9W{0EIv`cmSL=Jawho_O)yi zeI;Vv-_uBl>EyYSFnhheGE1GfWYi683M zOmxh#@W_E6tL4H=FJQQz1CIl#SECy)U9~%n z8n;ZGr825&86PSM>OmuB@#(Id06g+m2e5?I7-R9^^Q>B4d4X*dJ9~B?n0QH1h{@*t z`!57^OoIu$ndGh=7VA74a+9ZU4+v?r`+Rlc!g0V*gOwmupl2JR+J8+{HpU0xOSE9wTZY2Bna&Q*q@9E#ujeUYHO@FeWOoxR_~eEraAS-0&0ml;>^M(lm%E zB#MCeEr75`c|Sj+kW|8Xqi>$Ydi?VCmzK0G8X=y~dL%Ie8Bt+>hkw&_^^aKIvP;wAZ z>CPcUKuWqhM2GGWhj`a`Uf1*9_w)FXAB=MxbIe-%zU}{QTOZa*AO4bB$y0H@7-pNH z2q&VPem>J48U2=^)h=Bw$0OLaS+?|E_NkLPt z_Ue8uUd8ai(xtb+yK)Y0zU1rgH6O-LF6baHrP3q&gi3YbQ$e=P2d2~|SveiG-}TYp zC))zek6%sH%B9SmH80s7+&r>Z|BetI9QC)QCLuw~;X5p`6Tpz^UIZhY=$MvSPMNbw z9X>|M`pcz*5QNtRVtY{eJ8-?bAkhIB`~?s_{DF+xz@ha60LrvafwK_=A)#EEsNn`! zmq3Q>8xZY;nm06@ot&JwgNaPw6~RW8arx)6vN|MiTK)s%a@3;=AgG4LsiB8|H}uyT zWs>xmV#ML+aKC#hEEz^DBmIidZ>CVL)VT<7P)+1j)U0TYhq5jtDOe^JAqY>p=8Hc}0{ye@s4!N{kHx zsTB<~sPWKa#$f9~Yl!jVE?MMmEx?QUvl~KD76CB+8j$=2laG8!tqL$FRGtDw!*U>? zi$Gil=D(=yI$m~bS_e83}X8d3B(NBHS{-0m2f>$O!Cu?hLILffrWKt9??rKedE zHsr>Cg2{AVSnKG}q<)xIe;8V^BmClrb;8+rG8vMl{Rof*0sQDLTao7ZlHX@DKyI&Jow<^Ane!P8V-ZzM1a!`&KB- zET2W{97b_E)LiiPdOFo6Y3<4yO&s~!RpU3U)ejmiY?r#F$o*2jqvFFAC2~nb8HzfzlAj<2Y2{;?uhfp1Qd9y=m<*in!gKwbQ{)_`Zr|iw z7>A4~VOlb^m>-ymHp|rNLA|V3>rIL^X$Y7yI(hU%J4HBWUX^ZXPg0U`R?erV`fy)A zsiXWWu$-+cXaai`xT1eh*&!~Mz=K!~EFNG%pQM!TK+(H^6`UV(oe)h3*9BAXhHE*n z0RR&a{PQk(lGbG4OJlpwy=tmRVOs*w`3BJRi};9UCf#Y30!B= zJ1p34hj}WT)girQKb2_1suuzx5zw63U^FbE>h)0#<&j9%#iV01CQ*nEp$EpMcEwL9 zAxsCTkur)vVORr=`ZquZ9D%e18sKY!0`3M#agl&fTLerID*F_qF{6^Q;1XZ?n>R@N zd&hRpKsrhD-Wk~VlM)kQ+ksl!fN!Y|3_jmAlB)+Pis0W@ib(205zsb`$ZIFfo}9z_ zpj3n~oPCiOl=K2*P0sAvYCH^d1lRGIieOehO^msI0OhqZT0IM}F&YX_3FkY=VCM`Q zPRieS1SYoYpb?A)ZD)Wf0@PYQmB6FV?|%zWIGOEjzTr=62giGRXJ9wo_qMSq$}?8@ zd(+lpRH5KAPh(x|_f-@g6_H+=9Dq^Tda$A_XI98mj_%o{lAP087Mf3U!o-xpn0@fPfmz@3!=RX&KNhtxO#2QaE_!l%c z&+U7|tiS!8u4w%pt;rUAo$;gS?QE*q+hgSi%BL#b&JVQ5?z3q>jEqM0bDMOVG`X%7 zRvc*>%4HH}ughwb3%%oe!B{&CGSC7>ry(K4XD7TttpkMKuIoE`IVppy(ei|f=D=YKPpYYxXjSKmG0AE z76}#o*t~1$;xcsH>X?p+s#J6}KJ@^-VD6TBbEI;pvyXxPF!s6Gn1rk`c$R**BRKp3 z=f5tM64$Fg1s|f2)e8J;46q%b+~8&8*zvu9stP(|CfYi*1gJF z{2Xyb7sMj4l<5*8?KW4qJ!jC-nMC#|Gy!z|g5H zn2H5!1nsEUY;vQ5@#fUBI*WI4;hmW?cvYRHGM+n9_ck?hLk$Rx0d#2zdp+q?3)4?v ze5$850KHIJwRrPirLh`#2wH&v+b{#nPXgG4G%Wr|@P$K3cfe&`JTL1?C+UR?Or&r2 z&VXwQMB^g{5e~9btl=HEs zZSdX}ml0CZWR7Pi;84l3?k(Kux1v$Xu9KgUaxsktJ{Ru?>P>u%O*A2#mTX5{DGw(W ztkIsD^EZ>-kN{jRkg*2@MCl4oz>T5oBoq|o79If3_}wdabN}*Q6ft81chU`T6>>T8 z7}w4$+@RwAU1s1v;-ye799-tmIOpY7YCupw0C<-3ZDs3m%=&rK1u&n)0y^f;|D0)e z#NKOVam^|B8vf?!nZL}G>A+WSw zCY)RPX4-q05cDwHq~>tWLwm3lo^daK59gERP?~F>$#G|7u}J$Vxw$(GhDSy_v3ezk zX_C~P7NtzE$@?iXbkR02uz;q!Wu%5zT>CR4q>8JCnaWRt!hjxjeZz11dLNVYc^ROE zW`LUx^u`HbcYgsmEtKElyR9&=VpIbm1Q-Q~8;*BC5!wwMbOLfpqw2bM;YKWYXI>^IafgLpjG1%0ENOqBWb@Z>rn}U zP5++-$DiBS`bK3qoWT&axa>^S1u-xdE6`}ZddeO!6wT`LJH`I;lIhQIKbO<-?-R(4 zNFpt2ow$w>!+6}?pckOgpS8AF+dZpdw1X7FSR(6n5R>lDFq)Rt-5kor*f_%$#*`0x z`pphc1el zmcTKchmM=Xsx$rMVRTUc#c&Hy&emX19fX z4)uqqDWK*TGAXKuylWM1E6guetdp{|_(bbtjk`;{`!09CiiGir;z&Xsa&Y|ME24?( zWVSbVSK6=Vv#Su z!D4M-+-(UH#qT2cd@CF+Y+$i=2kNd-v#CV+YCIV9knJ;DFZEQaoy0$8mNod%Z*)Ds zq6Jz-wr5XgkU}py7xxsM0b2Xq-QE42kWEZSR(=aGE|`M!3KZ^v`j^Dv%CJp}woYu& zldFNP4t*ODxq12V`DpERMH;rj1C}&5VsOV9ohuy#I~}oFyrT7;^T4oG-XOkx%u=~v zEP_F`T2{uzzko!GM6!_O^Tj0&EoT~kSwz@+07i>(U-#aP&bln%l>$l#C)tmdN-+eD)tw^KyK4&Z#slgC_;t zYE_CAfVITI%(s^$Yyab(ctEY5j{pq>h{&57`d-hp#T=f!Ok^3AByKU)?ugZ(L=!wN z=^C_3HzJfDXx`z%ShAvU%U=#Nr+-0GWP6E&55Q(HPW{U${13WlMahFPfK(#+*lmg| zc9iDjWbx(0yhZ%8n`b^^r4>6zAMPKn(;1D{K0rJ6t3aCMbp=VKD1`M`I-KgllN`8E3i>7j5|=w^S8>@iJ5<7>LzR?8uT=-0=Kwhpe*y=o#~4 zUQ!0O7`%-z%g=b=u6wmx@(+suMimD$6?^mnjBH5!%=T{B^d!&wU3WQsw2`v@22gb{ zH5w<#mGvvvjv-}L2ZDOTkDdG+9`O-b*jLqmYFZ9M%>072j(wgJd~3^{Yn0<`@Jsen z2^Oeg@ivk8s7WZ3Px*43WUy0u#TfIdqC<+#A)Q+=QLIg0%$Yw9{?1{-9#(^Y$y-V^ zIcvQSPkK%s?OQ%6-f%Bx@bKkil;m64Xnh0Cq+0TXj>~d&YccL z(!q@2&=a|Gxv03jNCZSv*X~QLlgG;`yv1rmENM7fZ$&V|>D13fLzITX`ZfH6SnS28 z7@^T3>`@VhP3}hggNYY-jq`@zWEDMXMUC{xR(`adW=Pd@kI7CwBii&?-qe zNQ9X6HJ_{SC|bHZ`&o33+H$s&a+0UnTZp6==`U&h2D?0gSj=Zr_&0eR&Wi4Bo{*}R zxwr>ZG_A{_$SGX@Zguoogckj3 zUiBjiG)Y?jBs}H#aPUEO`&g2y)!Z(jompeBzwP@aJM#&vubp25jGQ5bp^Sb~x6Pkc zotKU>SMgd}o1A zb|5W_oi5t@{tKbDy=pXO6`t+N2Pcm7f4?q&uQv@yZH3)PxvKxc`|^tf*J(!AV1~k#`Y=T;an9 zrHe?k`?>8>%--g^GhNMNf_!S1@e4`G?q-!4249!BRA>t^`|=o|d~;}C1z@?l3bMju zUh!4KnJ205{V&Ryq}+|J@ST87Q2SRedDltYBy)Pso(9C=X=t%{7{e*`rj^b9lmk4S zF?ptx@FnFCVpQ)SF62iL)K4X7x>v z9(_I7OU0+4kkS&5doAcC=!x+%+aYqC{;&qiix|z@B#PXFK9+$_|3@~lTR-4|9Xp750PxM z^7*lzFdZfmskBy!nQo!ANscu>Rt|1`%IUmrq5a90X_>vAg;!6D=gPtpr8W~PYL_iZ z+9)S+C9%npszqw%Y+!*}oS)4P3cweGzza`atGZnQ;`Rq|@}!gioSH$cIj}X8-2+{DkyQ4#OPa6Kv6lPd5!D{g*|oDwEIjzl7urhmWyx! zk}M@qU3P~{A8F+>x0m0p^y#=eQ#rsQ|Lr&sdGQd@k z%ss#LP1;<{1R-8rxU&|T2`^X)Ro*0gE3A9EnMH?)WeXU3Nm0e#LHVBbt-U~3&qqw)=(xhGe(mdW^cH6*L1=6-m@6F-l8lyE|O@$j3(bPf_=e?NjSU zqqkTh0lS=^d*0)Z6v6efFqXPPn7t%H(NOgxi1*m(^xix#nn4k(`u?LLed6Et79fe3}4d1VSgY{u~K_@!gjMQx?Y?$GeFSX#qnCH2~D9vmgz$PDZJ>%6Y=!}!O^cL3{ ziwid+8&#!x{fgskq0omF5;^CH%yJydw@TPC#$x(ZLyg4W8MCTet&vr|x4?}DCP!!3 z&gxBe=?_;ewJ?D4(Kr88O;dNk#;>FmFXLL*N8?)>KoM#4~ zh3|Ijqako}L?KZbg=MKL>svnd9#HOgelXS-pgBPhG8?A^tLJ zu4*hc#;qJnQRzI~wHzV&DUVk|JLYocybC->A@=VBf4)_2t>WwD+u1^# zuVCI?)W+aPp472(XA?jPo1DCSrKQ{1y@VndN~~cxZpzMoOQl^SB(YH%V0g#R1NxIl zTgBTLEA}&ZfVWV)=G+s;4d*MA9=zz8qygNAbcZO8zevDBO-_c4^y({d6-c(GytYHSrNeJf+ZJ|D>1MWC^y0tG!EH>)!EVnu& zZue>jYO0&RWq8&o6(utVgwmhyZ5l*_JX`5}6ZYeyzFkb#y+UR@R}5QD(-ekd6gc^>tAfSP&LE%HZ}}IH@bq)a4s~KV=&ldGV3`0t z?0t;w0^_72xnDPfm2ue@@CgH4VpLKN5y9(^CinQyKebcfXf)^!#*kPef;;4}Bn>Rur<}XPD@)S(KAAwL)PZBWuryO*O9# z9arv5Z4D&@phI)+rAJFeIz4yS+<rMMrF%3y1nhf5xx>pyyTTiX+a zjj&qlYri<~`PL6VPhef7u!Y5%MNw$5ft#f9RPRo@+Aa>-PYjk@U)a6Z^#P4?87K4~ zLAfM<*E%#$RJ{-C>iN0P(+0c#fDDM?9X^!eSeL#(r=Bk~)958Ag-8A+%mEGJ==fVn zL9w$Gtgd)s1qGp!IzN4+&O-~?3g%*#E-NB+A6uuNJs77!cIZbiA;Kb;I z`8{--+LezU`_jv3*PTYnqNfJx7L+9IH)fZI8t5(u{xL99v z49vz@@&y8$PUdL+d7Yn|pr+7hu;6NU^#{#B-o2Uy(H1=ImV#xv&ErPS!$gv~-0_th zIj+$DOX;0cTfJfWV(Lu|E?xGce?A4$)mP?2;__aA4yaOSRK^VFR%+GX+{g8NNqM_@ z$x@(ndZohWH-o+Q7DMj@-6n~e@F;EC61?S3Rm-}D-rLtviv}EtVmK{6R2j*Tmdqh7 zWSayL#KG0T+_~@nFIW}(-hWC};dV?tWMy7SK3-KW8~8ZhOdG7Ew$+;s+3x5@Co|$o zBh&lcI;|S3#u|%J9w&>%Uo3Tmo_J+yt2IUC8bH&|@vhy?Q&w9G8?=j4_7iZK|`diZi=tZf^ zOU}6WYGbkFHF>{mZ3XGjTqR2;_RtzHG2(b)w`3MRv4OJu^KYUpNjQBA%x%o-{QA)& z=HqzP0gNX}QD4=B?ShmB0#AEe>-Tk|G1(?F6NK5+a(a0k33JD57DZlD@s6-o-*hvZ z5-d7og;&f~uC=tc*7H`dXc7HB z{B<)sk%x1PzDZ*Xb82$stZRJ+JN!3^J}LSOk(p+bCAOs2VbZat+V1_Vzc+s1(G(Qi zcOhiWz$6~5x0nKIzzHS&+=+uPYn-d5{U@bC?_myx*$*^!tApBL@ZM)CXigflcp}zU zYEy5_9o*W-VlO|YB`@f@*6M@sb-Jb##OlLpPs3{hFFoH+G~i(pA=p>tTH`x9br3Sv zMFxvD?l4Y%4?6dfjXBHT4>8~BspmQK-5I)eFO0%%$xhH8B=F)b;^T^5tKBdq1UGZ`kb4Gt`<>Hq zMAo#>A*=E(oxX4wAFjd|>F(igTtOAW=S=##r|LM}=6Gafr!-DWCr^5K$WiXI{Z*>o1kJmc z{YZP{lQw+V?cz!nkN(4Z-|Yq7D^v z--Q#k4M2U5a^}ya^a@_V;U|xV$r*3jeKhoEX2P|Hm?xs|MIuVyTK~tb`G08pnDIji zPzCDLcFR@moY`L4`Q8UA6IAyV5h!1yS4`({j>eLn?%1Y3T>o*c)K~5(KN4Tv^|(J9YMd z3u*~+Z0L&qhzwQ|*IAC^qyON3y~+oE%XgF9G_-yD)@Nhda;{n^yV6A_YM*9;UgwXu zvR(?_?VL_@+&VUjdo8K6mKH1)vtnLK_$HyZ{0gOv=^H(0VeeW0cHd0kV%&vqrDGhi zrY)<=Ibq&Mc*Bvegx#Wdw`xO$Q`FX=;7K8)qXnh$e%R}VGjMBLktf$MrMqr=0YWz` z6m3c5J69aywS^?NQf_E=+*xD7oRlvDSO+9+0}-HNAG=|u<9DdDdFK=Tru&tw>LwlI zTY7|(R*^y)u|<-_*CqG`n_Zv*h9JJv*>6i%5+QZkBs!|sTNsi*@{ii2(*s>R8$M9q z%DADitI>|tKO(RtbYCHMB!P}py!`eU$+xQOPo^!U_@m_1TK6G!btTOFyged3-SgSZ z){vinmjoTRgJO^_CSOM(8MD`yEL!Dr;OshpSlke*Zvsj#IkC5a69YS`A?dkr# zSS^{Ni?w(#?(x1OJ8SYP#YO{M@OfZrDb^hWrNi+ zZX6}Tt8Fr1?7W&zLhvEQSE2cKAz9}wD0UajsX%cGIBqbYzj-%1BOA?E{0eS}9RR}_ zWo>;dA~f0o)Kk{S>duu38KUdW^>cn8mbB0}KBJY9v-6D(pU@~3Jy&PV3!8=+cC{?G z52xz^Kr;P}h)3V_`r;kg5^ZbP4*%45ew$rFdF4Fl-zrqlF##n2n@c53Il*q)dI7s6 zP4r&%Z#TR+N^S;*74`F*pt0LMNsHK-hK;!a8ia2B>Ve5ItYbdLhT5h{(-ktBx!3r| zimY^ z`XJKSxmd~$W9lb=ABIkN%46%EFG`lzVAyt8ho#Ei|vKh=S1c{y9nN1&A+M?9@KKJ zTD>r^Sa-JoMKtIeao)<^wrNez&J#Dhf38=h3pKVExdlTWK2bS)5Xa5xC8 zz89HmD8}Q;eDYhUfIvf;dz;YqrHsJ~lMCo`nOvikx4y2_5yM9nk>75Hp%!ENQjI;< zJz(m=Q7pF3NHn5UNE*oSLP1gGmXNLjz4aa)$!qk;PDrHuC8MRH;?2j?_PlGxV%0M1 zd!sa(j*QZc7Ry$RyHREM8KILQzCv}3`bn;@JZ>A;U+p+;3>Mft9V{G@-?~I_X%v;? zm39loFJp)E>Z6s`WMe!VV&eu~w)%1c6K*m?Om6whhQQyh4fwx7kzV-XDsieM*YJ() zV|}#WN2w=)FSUxV+Q$7$yE?yRJ7(yahkP&5edycD|EB|`|9hgFV6Em!;hSR1T~JLI z6n1)NiDs93T;3Qo``@a`l0l8JTT){ve>H3oN7w_wdoBhn%iRW7Mo0p$W*{6eSpvx& z;1wGB{$#_t4?&D`V2j$s6T^B3dM_`Q3+Yn()92VNU3S$E8mB3xU0q-J)Z4Gx={yCI zP0P#MI%#|zT|Kf?&Ed6gCDxq@L^?f|iY0I)-Ksgm5my#xOOJmm4t;{L)4nwNo)nKV_B+OGc-vlLnD z+Z#f=zZ10o;XUH~czT}(Y>p|Z5~HAtTtBxP6yA#rF)_U&A%Fn$+a#uzg9iSS{Q29h zA$@CumXOV4z2%M5LjyGd6`p$(ebk%UH6v&Tkzd#cGfibjF|v`O&$bCERf%7M!At#K z#NA$XS~F})Qwg0hf`XnB`}mbdN`y}b--TDSRVGLfhoFTi7htguW|xvgA1U4XmKAE9 ziiVr;2=Rl1Z;cO}+_&Y)?{sNtzBgzS`aGvhHb37CVzx~#>&$~* z^*b7g?Bt2UrlW)wx4V0XH21njdTLiDm7X zooOBpc!Y?^C2{(?E99CnoEOi!@}F$Wq;`nBFDq%NKSDSeP7!z!?}1shSzDtTKM;tS zA+y_V^Z~*e&$>sn+Ljp5XSM4>Z`Im~Wu-Q5kjjH_TGXi-}B|ua~}OpPGQaAhW+_9!r}0WIAcU^W~yx%qKW$I$D7iZ zhCd?(yQPFVgJY&}(7ft}M`LZ$6v&kACsWx0Idxre|KaeEQ>adcOj)7P%1Zk76Z8yWaL|xM>YK2&HODVYJCdLRvoU zDEHHCEN+<@#BB~$iC?D%Cu0KyNcU#3KCOS=oAf(eFWx__`b{pq&G7SfmsO$a#M z!mx+Y-@tE%vyjBR4~yxbt~)EHLoyYqpW2`7-tBPrCA2?Tn<2Z@T)k$60*sN|vfHIH@@S0=i?Ld6b_27mhhbOH=~Z7ne$o?b zUeG$cpZpThXf#QZZ2OFo9lUV|Y>Cl7QhGESFWm`XrRm`et%&z>J<8b2FNBMz&D7c# z%yN3w7^BsxabKhg;RKjq2i%o8%?P}%PdjQb#F``iQ>*xqKKgCT@7P315hbQ08|;>G zd77W*)|CToPv4SuJZSC5EO$@J83uQ?8JV-$mVK`5Jj7NyK)or4Ga3xWLDN14k(zY_ zP=ne50MX=hQaau+&|!f%n(^>9D?Gw~zO;C$vW8z|pn^8F!bk?8#G@T|IJ%?L2*?5} z#%_$NW*?!+o-%uAygckLKDLF2HKoS!S3@7W#fdx0&1MeI)}tOeXLB>x(nP8S-^(5^YQpO&mfIs<3kmwMyqf-mXZYPIY=B~yOP zQW$3I%|$-gE$~bD0;c2EFX;L{1J@`BYkWeJ=4Nm-*gXLeJdzmQ3*|$YYw`8&e9a;_ z#?5(}CZF!yfy3KQj4py-{mo18SK{$o+fNWeX>vyZ zP6&kwVdNB+%w)O$R=@z|6W?A^bT0ji9Y za{}dal~n12+Q~T4l=`!Loz(8j#n>G}ajp62K3saX(=84MTFwn?SR=7%tWCD~u`Q7o zc#s@rRD69ijj+%p^mzNYoD>2O;sgiFXoAc(gKsIhYX&j_bK869LN8F|)an>X7o@QZ z*XzG{j=ZTX0f#n?W8dRN{{~FvMAb>+=Ht=H*ci$_&wyP~d@lIiG3oxz5Hv$!m~Jx@ zdsJ_^G152VR}NK6z$FTbd@$@#QIGE`k|6^@ zfTLDKWjo{6B;*;bK1F*p`XU%hU@fMv^eq1+hm&1t&?}$fp}5()(5_+ftC?~Ir&BiZ zBY-9fdI(iw-Y6O)#K+EFkV#pM!gLwy;)34%C*R}Wv>A#b>P;XM@UkN@Ygk7EX=o89r*o8}f2=C9ZoKEEXu+VT8iYUoE0uvUvb~MWK*%+UA>z3a- z7M&rs!Q9x=)3Dnj&-uG6RXvEZHARShy|{*L@$kfsg;hs)cde1qprG?*kA>(@aFvl0 zBjd?G4u8GH7?Zef>?P+R^!$wN4(W>?M)@)+vp2pzRP%r8nm*%RSs5Di_Z}$@KN>ry z-tee}YUr1)do;%vnM?&F?sG8#uae&j69y18GM`SkOPVm_dM`TOy&}}$EI=4F>d7vN zoms29>GumUmSkonO2lQc>M&uIpKrK10Jr+4WvjK93%xO3rRNs@p|OmqobT8Yh*;J&hDYQ7 zn8LrCltO^M4^i?CAT}|#roe2ilbvy3=p;U;T+{VW*%fW;XzT;vFod?YwECBB(QYs& zD=TE-rcKq~&HAo?*k>O$76_Ojb=w@$L5@K`J~NE2icCt8VflIA!o3Y-&FI1d@X@ZB!IV$bOP}DwFtdd$W#N37w}DB8Dsw+eT|luvfaE#Y=k$W-`CgFEgCAI$ zxbW)d9$rb|>sn1=r4n&Ci5eeffKU*`^#wb3)lbv6Wx=s&PkkOgg_gc8buv9-lEUk> z90_EIz0dvG~>6see9TY-22WRI{=;+D{~KbL(ZpPEIvcDCD^dxB&dAz92h1I z8^yYusVA;o82sQ9_5we`vYgK;CIPUm9Z);vAP~k4;(ZpnEIH>yDukpLCe{T@X6=0H zn&ihH$wz%~?y2!nzReEyj_DsQk7H>yOp5-I(dDXMUiAVo!EvcZ?0 z7dW(_mx)cq`D`@;sJ@rg_@7y1Sz|sU)Tauf+6e@V49|%OH zrQsp}sy?xBDT%p3=b19Cuk|dH))UNzdgH4SFv}X;&q)GNrP(<9;NAv@6zU$|Y%~;T z+1kGC1P}KzhMMayeD6j5a-8oKvLC*WD`)J80t(XGJ)V4qb}@vpdBFfi1|)8I&38YZ7AXe?8~FO zgKj!fA$+(Ig*d0$Eok)^n`)~5kU5rz|CbedBkD~qZ0$$#%GHSD-<=iak)->}pcR1=c&)B~VU5)biV=Orte1&F zZ(oj{-;>H<{Iq_Zmlqs5IGgsGQiD_ptks$_m7x9n?A40-NM%H7>$64etnZj(BCQdySfqC|lE z{dC^Zn6^i*0^9s&N*3#m{mj_|eRs-Ym=(_EmkiL5cS@kfP5T)|*$2)Cj|Op099I^& zsd05G8(~I~+QWO1`o@@d>!vLQ9syx}h4WJ@K8#zAnEZl1@tYU}pHRDov0TB4Q%q2MU>xh15xzlNjdrg1^yNI7MdAr`h~)u>8Q8t`e(q>( zW2md5c~JnSP7AM?j?{vxLItY+K+2;DeQ>)2rHed6x&65- zDolzxMLEq9Qg4d)Os9{{mG-KudGUou>)&B4$zm*tp`AKhr|2zYDB16&^prfVldxF& z;0MVNLz6ASklrv~v6}c&cciOkG^9OGmB4NX5<*57Qarc4qTftb+@}$IS1yoQ-VP|I zt_B1>C-cO(T&jmcB6sO zlwZ<{ITTg!u5d}!n+zU;GPk=pIlMwaYF=0UU4n^|$1iB34NM&j_R3ztHwx4qoIOw9 zW?fW@7^pYbrA{PuOU$C!*T4>lHM;DYIY(2kXNW@|kH|RB4sCSQPs1e#TQZuVjfw+y z3uy)Vrm+p|P6X3dTfK-X_}ELp^Us2@1RJ8;^g;7_i=pHkz|!-i*lwV_*ZJbZ-b(Bhbk1+sKTvPgnX`WS@UtgOg0azlhvobN*r3np5q^K4w z5FYzyX^wYvO9kDOmLx{gf*Jj2zEu9w<)(izB{Nfx3&RNOt~MiA{0k`pGuNHJA$%Zk zlUzpQx0`@&s1C2**9VIMRKgUr;gB z?crE+p?n`Azvr*Yij7$aeh{k0k{-T4l$|mzH2PC!%n?aXGo(L93^8f-3z(MOF)ha_ z2)iQiGH{iEyy!RoyEZ~Jb^_%@YR|i|SDH&c!XD1DHRMbNCNx~z(?Sh=L)EaS9&Yj` z*OvXX-{HrSALR*K<+#s=KE|crkR&D7Ixe)ojM+pEP&{c{B$IV&luG)i&HzX3=J~!Y z_U`@2zBU*kY=^fbB*R}a3J5HXa8WLrdd8{+QMdku1A$nk&!VF>^{?PH2N=(QxlyOQ zTUqI|@qLY0FdQ8%cJkFYSHB_qd4PRaYjX!2caKVJl!tX%eoHPW5(mEDob?X^^`Ul) z59?y>@AgtDBGP?MdWn%8tL(Vw)49c8&lhPX>)#1}^d;SAT)=o!z1}#cFaO1tovTW! zk`g?(KLXg-+TCSH*zecQSW#3-*AfIC??51PY3uKW_2uo`%onpOonwon?;ZL=mR?dE z>M3&)kxxH@xcRTdH#t2aP6&miv~<@ffVP6gzljJ$GQ2H3(T4=|I9C~B1^L#Xn~dl^ zfY&G;g-kNDbN4WT(V5{J!}>0EZN^k}|6i<#wNHiuvsn`C;EUPDyUK5aPxyFQdbEyv zt-{J@8iGRm`;-q>|u%OA=>aCilA=>p0 zm=8;vUcv3D&5DaYV;SvmlK^4DIb64GZoAeI8*eNrTK{Oie8z;S@AF8q-bbD=KJO5B zgCM~1wwr~nZnaKjmEWDe(LX$Xr(L%{Pm5tO>owONF#qd-vqGaA=5wO z(vw;-Ki727^o~@<=u6ht7MbI}B>o$bx#2scdB<3@JF%Q!VZ{w08;;31TFTg%tH@w{LS)g zdX#f>ea$>qbp*VS2_}cJ8Nsybnl-Y(P={7tBsQW~zgk3neU}6h>G(C=P+};c4FQo{ z4Q@t&I@$_&-Nw!)gE$V}lo6cfF~+Fk2_OTAyo!l;6+gWWYb_J0hSj8Qu`V_|`ufPQ zIs9`24%|a{28|=vwb9$8bnv!xZRfj3HjnF9ITtz>nrNT1q>}3?P0fN{*HG~nfq7s~ zKnLax+`@leEWKCT<^J4Q9$3;!4Z7~%C*Ie3&XJUWSOYxAD#W!$sXQVK_}YJ;d^<^Q z-!aRHREq@temN`gz5~^}iI_|zC8qqC<-343eNWh(yO{DP{viwM(ebB#2iyj2ojf}s zhh9px3#--a%hr8dgz^1tIIgsZ9Jmp^oxJ+_^%{a&e1JkAD71(Fb5kwDXfixCo1Rx} z|7|OVtu>?zx^R%lx|pVJ4WSQ16bE%bJ&#p>7dLwUzNB`2iS@qFXj_gkG&bCI!{Tpvs#M@P4>0TPfS4{V$U=$*LI{4i@Z)C< zf_^GuHd4Vi^d1Pqbm3*Ylg`NPX`BmCySBXuc!jP=7D&@^29-T?K~v|C22ipqg?5`@ z$&Y7GXh($I5Wo=njk8!I3jhfv8%lj}7LDcIGjNq76G-XpT_2NRF>jejE{y}*x88B7 zd&g4~LC9u;-SYdG#rQbtiyv`fJ~tVn-K$tUO-YfA8X%zvAfIq+WP&GRkr-- zE9cak+bbC0fmTpcL(YqP0ty&SeSh%WhXpjj4VaZ zzagKL-imn&{MHL1FPI2a-;_TzF&*sU&(LIidGs$4Y75tyse6lr))QP9ZB_ax%W8_& zVl-LN+lHC%Py;@D;ZZ%lwS9-X(dm)psa0ui7g|_%IUS9k#B^Mw+QNDt4@&tKFng8c z9_-(w>uLL!wC$c?nL9rVkNVqXnVHdVZ%gCQM02zT2QEse;MK`4&SmagJ#MUgb3OKR ze-0lk#SK4#$`_()Eo@U;OqXpved-tTg8e7YE|+buso%&y!lCT+{8q_SXG=F#7cCce zhKT&<;F*5Y_1vG@0a@DQXD?;ds%v~v$74~a*^%d^YPn2NA)Ly;zl>^#iqJ-v{@@84 zl&ldiHgeaFu=Wtz1=jU8P&O#Q6!tNy8{))SsbR|~*~+jaCw%!AJcZ%|v6>l{RF9Ra zb_u2FVn$dwA3C>HNS_Bo_AkQfmCEF%rw;X=hZb?!&$%G8XZV8zJ8; zlR{*gveclZkU#m%7s1bw$YAWzv^&#~fP%5I0WTKk#hfn6((HbQpaSQ^>E`1?);piu-Ka0;xXea46Rd4>~?=Q_<>X8y2X~RaJ*jS0* zbNdiEBg6WvU(fYuE1U#XUrO$c5Tu`*EVI%0OUWGg?O$++>U~_!?a7_<& zo&v7B^D5gXwyiCbU}~q8ng0OtA?2w$z1H4{+@_2SZGt>?I-FNM$Z*DU0B@i7-H1x!J<(ORaHMI_<3FoJL3Cj|c=PhTAs)fcW! zcZeVzN+aD3qjaY<1JWVgUD7Gt4Ben~cStu#Hw+EZeUHEIyZ0~FVl8G^=j{FNC*J)& ze+EPYZ7>E>nc@+orQf6O&RIFd;JP`Uu6((E%rEwA@hUsal-1{M-@g>{teesQ;`0$0 zFx7E(>tmT|tud})EZ*7SNu%i2D~VX12cKp1H%t9-#`X-OG7LnONaQdPreHCkGYP$QMG69j!BPCgW(+4~ps>4z61WxCZQFM4oy|6FX5QlR@8RRF`n4`i~m|`7lVmGffOT3~{vI z$+)`M^uE__?io2i<;Zs-#+(Du z$wL;&3M9@zbgafEf0bAzj=p`gJMd6)%8XVFW7zMH!tIY5(fp8=5)qS%7^>O?zte?T zFPBXXBH|AQznN6y4^Lh19(76Ma#$)$>dB(LD~)$VZb@KRVW{1acKou2ef$w~OTvMT zQ8wm=HR=0vTP4GagbdG0afU~-j_jtbkv=C8B#~!2YPCL)|1Z|8(YPGP6m!{%alt;0 zSjJp>k1*ZR5eS(J!5O<_+DwAzplv7IgC)3BeEzD%b5P69+m?&0b(MP(_F7&^!y3Yg z?0M3S;EWWs$@ed;%)-LHl?VgLIB5&fjkgq42RE?dRd-bj_}*?$YYpmTQ|*Nd#-I+Q zp9J~Wu*p5`=_V+a0Ehn*5`y$S@Y77E9q_0eU{^P8Qmi4mIiz)u?9z-KDuwpEKm9x{ z$LN^kS74pTzvO>*HX`%Cb~hH#PiY4JC*VOu^;k?tsa@)a6^AHM``KMF@dw)`ZKLO!ng=Q@g;LT%H&cG( z16;$Bi@Bx@N%`qzsW|@X^#i4gVxqkfQ-B2sWM_;5`|g%;jQeYm-G#(9Oc6$$AkHFkzamwnHVsc=_3iBmg0QV_T2Z!ira0C(`T12Ac)cQ9_KA`^8cj@6FQOtqn&hFFcA) zr`|G!!9qz6#;ts8gRa~k5-|Q^;fpO#ljCIYh7#n1i;F^!1Bwomup zoiAE?-|)isn=dBMqdX8twX(g#D7NRls{j_7frl&MEm;P=?@di~^xb8~qk1*xHp2>y zbd9iO2&12NqRGEMz1v;1gbD6STVI=s5cO2y{W6K-gXV^Y+!8S4+b+9+flPcV(+dAY!BhWrRwQDHMc zZ2%5$)bNIECoO>g>A9L!`{V8g*PJti@vP3Z$exvN60^wO!1Jc?@~z0rxx_I=Icpa#!57?e z%0l8YxEAES_}NrBT}J&KZjrml%MF;eubP5uo<8OmKH_#1(JezhLgrorh?V~Kj9M-~ zIok#gk4=d%2Fi>qEKtP6#B6zky3eVRrSQ-1>5xW{k_QLg-nAMSI997*ou>^xMsD#d zr-B}P)WqCv?PHp%2>L966F0hA`?XPkk3YLhG!dm52H5uD#mK)Git&N}x2^d@3-w6L zRvObx=j0c~2cMVlPx=?6^e80;qV{Q4k7iSECnpqWFB&^L)LpSA6bjF$48Znv!eE+= zl=Bzl@pt`B5H^*|fSjCs$GSagN7$h0@Y{rKRPTphFE!?i2jSG@I&a;_44qjPpwzRm zu}X>I`!MI{%|uTr1Ki)#e+~m!6n8qQs^(R|zL`E7K6oRQf;^)OJ66dbNk@}3I@whG z{iG8_N#Gd7D@c_5jz)^sL#E(w@H$t5ZALQt=gB}TG`B7H5&^6$nXJUugm5O2r^)*~ zz^M~+BJzIv5y?1^$TcC(xji}LvHfUHEj=i^w9sD>j(5tBL*aFoM{_|6DGfM%N$ter zY#HhLMoi&%msi~HWLS#inS^i^*2z{?&l%j>ObiWveZ9nmmjIp(g6!+#3yzSlgIT`- zfGRw2kJ6iw@h%ntm^Q$y^f__I=mw2B(Ok6j+Z!=5nFiikF>V>Y_Z(%>t?g_n1q0qX zS1X(oA36N($jEyq6j_m*4zA^fYXk5Bj8W`EmwQ9XmEcj9m?mLuOcQcz2qzHKZJ#-k z!n*y})SPaXC~9ulj%B>e*VoWuEeTbZPI{k4NRY4kA#466Wh*#^yq0_N-|M~`>(@q~ z8=w2N1-ebkG)zQgSb=roo|GcsnC(W0)lUsLHZ15&9@@HytSw8URE(ixUeEwXlM?Co zRahzTq9TXPJ#MR7WP%ED9y^7M73mjRH82DxF~?mj!XG;YL@SqAdbuYh78_6xR2Qn5 zM%?91<0)XsJK5ywg>`acs*nVpMa=%j@A1$j%p+VeZE9s?m5lAsXnz0ctQbf?R5Wcf z!y#)ADKCVlJ!s&9YhfDUuaJMvKjp_gQ+BC)@{|zn7$KE;{6LQ2 zfE7e@AwWbZrTZ7V^(SnY`-k)NRKvPN6d0jZ(fu$&OI~f2kMlXM#QgzP8j{^i9x{^C zhM3MW$v<#ugchqsik_o~IcJBtE%yZ2F4r>NnM&8lb7M^pBW(9Qx`IC@QcZ~siS(*A zWr)R_B7DP;FQpylo74nLfm7vFjYSf8GgqzZ&+meFZ}HkiW&u=auG&=HhE)m9h_tjm z=Z|j57u&H=FHy2r%!ei2W6dZ@%Z_{y%5v2~=XwJSv_I-1JH#D0;bVCPpE z_}$jRCzXMpF<+_V#7M%=!ciB*St0O2hB8zoSK>ng@2O*5kTbZ)NTW`;sT|J;%`J(d zkt*0rF`gNj25QR0C(=-IufKblJz#2L_E*?)%aLc=KwTHa>XM)xa16RlPBoNtyAOaj zmZgK{$Y?V2m1x1QO6IaM4!3A4%)X%^GN(;Qr~GUDF<>>>3X;*JG=^k=H=J1U8QD|S z0pfMEX22}XA-4&RSh|}px13hvAF8#f9qyhUO=!V#Ha2SNatfL0NKhUbHRBF$4gV;D z5nC(ZrTrflse)%u{7d=igV?lyYZ+`Sn&=nFyRtTG5I> z=ixXRY#hQRg>r?>(DBVtt{&X-$3>|EKeWQ_oD7 zaZW+`)RRpM-|nt3>&5v=B~!s|0PTTv-uS z(^eo!czuZRr>4|HWfjFR1{wj_bm6lSd-OvB@J?wK+NN~sHC6-^XQk>nO`%o+jdxEF z;n2&pwn7+6ec*=67_sFbLhf3Fj-kIw_eVO}22^Mv!|n-66;+|2!HfQ14#``Uk!Z8I zN+nlFhSKJ#q)e7Gn1kjG(FZX;Gb>|?Y0JE3>=Q!HgVkRB3;)xW!UbY|G`HBg8(oj3*1b&$ymYd<}AU}8u#99Vs=wb`1 zHIX#)T&jo%>MMwh3d^(=F#BGk&=y|XmS|m5!oNCDf^@;`dn&rB3pA$`b_qnV$ec5r(&E`?F zhvd|^X)E9J&>>t^(Bs0_7sc~S*IYP1feTomz0PG1MD$kd%6wY{Y{pw!WoF|SU3&4v zL@ID+syF^hE6wD7*BgjZeqtUJQ-`|lSSa^V`mG`{VqJq&&~2L$o!sQ4L8xG_!V&Qs zbd<0=k5Tz3O6rOi2bg@){}$xn#pAOrZ$P(J(rmnaM=F;4=PjhfzjLkUd)qf07|P zTymmwarRO2A#zS{PsZ+Pn;Uj@lu_E}ccayGll8@(wcsS7wr{9q%-zL0vXp|IlFW>C zvA-=Xy=-E1^ewHU*~vQ zDET(iha%qgv^|JN5)G>53h&^Z)?qnIu(73gkp0wPRUIM9H#7^Z#?K<6t~lj5;m@4d zahbV@|2Y$2yHk_#UY@WN)gF+(K4UsRl0m62*jb1AWJq*=M2stZ`$kcJSgnJ}^S;uK zC-^Zc7z15HdiSb7?xqE@4cD@C&r71L6`>D{3II6ILow5wp&EI4AA<+Id=FaUlgQDc zHQp_d!Pr5}bzoK-KA|CPm|HzMl*}c7Fm=3l0>qDa_}y6131p!V&8}DHd&O)Z?cTk$ z|4K%T5%=9RI;-&8&H6QT8|QfA{7Cn^6)rPXkK=>zf8-0JctwCcxhtQ*jIANH|8$)2 zbZI*3XLpMxn5vN)LRU*k&c_{YoR8|<2jAo)hU*Z>!Z?g#O-;`x`1&b*FTpfTM|@b0 z13*|ouih^;o32_irOD$*jT56gaa~S)jvlbF2ATcN9HFcFE=|^QwRFMPZPeQY#l`16 z=R${KA}e)OunVq(urPyz_!obIwdI-2e${e@v^F+atc7a8|Foz@87;m{o|Zn!Qpzu0 z`n^+)gZ!ZOT9^fu|?gg^jyznU z7r&c{FvbdhU^6*lT|4nm)><>L6LHNuB1=IRiClrmpu}1G}y}g`K zyDO$cir804gL%jhobOe-pT6uX)P6dtW_f2InSGkmi<`1{9xk|0ZG|JuDyxM@<9$xB z@8C(P{qz)&kYIswgk5``X=X+Sjj!me!g$~s*e_DO>#Jr-vkIkw&DsHJrdhmKAbk0I zj0YwJ(}R1J^wN8sf-diVpBzOb+<@P+4&Cig5nPzO>Rr_4WTp4KdJPeCefPfGsb<0N zAEtZUKUaSx6}fS|_WErFhr8s|6o>O+Xpc_c#sxysWG7vPXi9nCY0wn)>e;Qgv{YeH z?BDTZH_c;7>tmtsP@s^u*g0eZL}~ACzdlXE`MTIHIj$-LxHL z$p}^oz@RP=_^w9mSU>|vxO;5nHByrkcjB)`9h1D9WF04Xea?uib${Ao61goKL%DaK zD6}soidCSlaesy1XA?3Yq1-VNUR<=$ela)8w9R4xb= z?`8&OJKlLVd+CWZ7sMG#<^D3ak&Z$rlt%T==P+J#w zBemgh%cp~8(j&D`o(%xKNi>@T%>Lm8c-rKx0FT4ePQK_b4%NsU%m-@O&PvpP&RnnT za8D-vHi3E3NFPA_`FRyf&?_~MCY%A1HLtIkJXXxk6PSc|T0ji7dJfPKkPY4s#n&KB z*+<$R`EJGf)1Xj+1C3>5;>FBRLe%N*FD3b06E?Hpq@`LDP<&LOi`ww3ziW*sKPhgC zB#dg8-KW1Z)wL3aPr`EU5&rxEG}RD!bzD1wC}1e@MKC|OX(qGVhn?fDJ4a4QT~=aqT!_}eqi+nF%*xogB+a*$6#jYh4O9o zb$Rrq8iSC1jWXw~^|&W7>~lx{HaAr^d{=|(JJ{7Nk8lBH_*INNYLbshhDn+9UulzO z+H>BGD;1v4BqS8Ad)4NNbKA=9QhVR0eN{>dC?P^_QQ)2&TcNG{bW$E%qK*9Uu`B@m zTYYz&Gj@N|9qm>Ry#DoU-(v>rswJ)+&eL*(O2N>SAt?Z*+~*}WSJCGB=YJ;4?3+wm z?(I2v4><6=kIGe#9QMK70C2Pf4ziA0DI!pGw1MiQ)o^7L0!}t-XNs212sHG#`DF%z zkY)rJp$d9avvFVau}zRYxvSL8$)Jp#bf{3Br>#05^9*kSqXhlopshe#>hItnow{ga zdUszKyifdl$)nse5N`wXlCM^xi9C*8KOmoz^NSkG6x7TFfIW2+z8h5wPG$wB_UO~O zmwYPEM)Jo=`TolpJgrcwYj?TxAzU8ZQ$0Qrr`9x+_~xfa&t2D~_r-eM>6siS;vkg* zrgMJad?w~6g2&K3?%)n9H2=A+4r9c|>J)Kde-_BaARTR%opcfk8tFW5u%`FgyGHz< zwZ|a0+f|MD-7>JThs;1i%3jIf8g^D12Q!3VrDA6npCfO77-LozMm7txN-G!W~XhsVC&TgTY=u8F$yC3|@-`ls^ks{tA1+n^4v{&ehp7*(b zzHGJn+W#dX#pG%tHRJnq1`MxYqm&~=6MgAn(JHRbp8JB$hD}v(a|1>HjdcB8GwP?; zo;uGS$s_K`gVV?g`mcd;HlMKdVOI@1Wm})*KT5SJ?QwcML7VEYD&yr1I0D)#Rgqg< zV6$3~1U6GWWsWJsYXDB16;Gm5x|&6smEgQOdlBcqs{iX_L&^Edtty&ZaP!+@5u0ZR ziJkcoqgSG4VKq-{nfyrhet2lY^fh~ zU=#8z^&Bq}IDVdwzJ5;7ozO4wCfQ_o){g443d2;{A;hb1X~ zBQ9Amqs2nEAI+>G<-*e^Ev(0`-^^F50#5CT+L>~bn_~C797uT@r;(%RokARz$)F>~ z*i?%T;Kth3c~`bJblge6CIXaAdhWa&HHEGt=C9^uO0|D})HrkJ(Tu}hQC2S;IqNt= zbW^|2xIhHe;a6D#MaXZz*~~w!4YMoY&`w-+aLenf7kXWiqo~c zRcyg-bq*<&>7s`~V@p4YBamitK2iQoVbTPda7AK0Jxw`I)ZVp2lJ>YFZK>*^Chl}D zkE4DC5^%W8P3Y#s>aEwR&PLvOJWWNmx-@z`hR`B-lgn&^O_4nnXIa&X>SORd;j%NX z6Dv8Sv^{%|{%l5IqLBJNmT7#H@=*H|DlF`<3^e^9__SHEVTZR36E0Rg_SjDGB&6th zWk0&_TSIWkpmGa$Ss4d|HT`&}u7Z1qSMHNZ=Z*|)5%}**$lNa z2qjtI>FVU_g4&>La#sKOzHn^Oo3lC_IS?UF{)r-1)7HA1VtrEWY1HPQiM&(hKJFNg z&}|6HUlaV5J;EpEo@2(8uNNYG{b{A+*HpvF(vKeD_vaP>X~PCS?X++j74XeYs|a1| zq$0N;6_~$z?0hM*zgo21b84J9Bv(ZwfrjO5PSagc z(&;yR@3Y&0-)3w_FvpXk*0g*KQX(l2@crV2m(yaNUuvEBOTeKz)byW`9F!ZmocBxr z4c!Kf<8X5(Jr&f+&R-U9(%Qb~^Mnr;j19X$clVKPSY2?q1tX<@Hpud3zB&Z{dBRpN z2tc8vBy);mcBY@x%vLMtKa8>}%@$aFgImU`5SX-_$o*1Wm@RF4HD7RIP0O(KP4m!& zjufD1qvOC?%`z?rCt#U#McYU0tlDHfMUK94Ex3Hns)R`dP6=st24CI{1b&{HyBoG) zZZfy#q{Vl#2!Hr+PTJu&t8)*_T$3lS0-x1JwgiKvBTEKFPgESZuS1cUS7OzX1?M@% z?}?*w%6OeVCQ6F#01wpF(UIxX$x|7A!ANhFd9bEMxD~Qg$TOVC-x?R`UGV~^x5RRA zv8QX(Q2^}zY9a#2l5i6a&{FIk)B-C*q`0BF0?<)fq z9Di_Y&yj1xb~0wP`%GiZk?qXBGTLo$4c_U}L|BTQRZr{9HJ|S>;oASl^R6dLy8!9N zQ2H$UsL6*V&uwfLi!Ht}lKx{>`0ZvHRq}eiIoi zWzup<^&2!QSXi8jHmntZpcC+&lZM8$Ky2VVy9U$HP#jc2)j|XsLpz0KNLTdddS5f4 z?wHP>wZmm^U9GwN8&WB@BbNfk`-!2h#r8@wh4yDv*l+tU=Y(DdCqsnwi7-O85#V4E z;FhLFF$R**ESU@drto}bX?0?D$x-8hs>U;yqz+h?`RGJjkx7f`Ipxi-g8WsikQs1} zB;9avJii!s9gX&Y38l64IW7%RikT{(Xi{G@gHLfgxdyEwrvU4y+4`jvK_&r`kN4*F zhXUNm_+N4OIc9&`97WZLEp4l*O|%E@j2ix=d?^P8!d%g6L@ByYu_$eW8qv)G?twcw zdRz<3_3ll!!N0Tw3C>kS>CthG@u* zcc%Oj=V_y$O%rvi8j?7_60rXEojI^dldk^Ez8;rQ+=T;9^x_b8Oqj@3(6T<$B76Ogvp!qS@a=a^ltFgZ06`9sBqbvy@tgC*6K3}#m#nh=H}rauuNNyQ zr=r|4yUw&<3p;*gqnPoy?-kS0jq!vM@0#*L5{i^r`TWJx^G^Rzyh6E_jA5Vd722DM zTB`sAC}du>?)TJ#(Q$RmMvKcY{v>p|xMai+GcwH26}aX!3H=3mH(6Pf#T!Tku$1Of zA*|X`Qjyz?PeQ_M$S{BYkPdhZcjf+boA-;0?G-f1MBI;--r?4PoqF~pwCnAr(Oo0% zJk;PGZW`#3%vNzGq!XH46^%4M4{v~+NS5?3Yp*Lh~i zU;LM9)d5@mAnk*YyV;Ucj7NE$YO*;;WEU){p>8r#zI08L6)om(peM{3n#P zW`?Muiu$9R!ylsATv`<3{tBwKF=8li)(+gI`v3R#l^-fZfYn}1elkdt0hg8eCUf<- zQ4ecYwRG2_e^C$>`rWY|5?7}tNx7|EXD_E`Y+T}+wI|bsavOZ( z=YE}c{j8+RjZ;%9-iK;A|1#Vr7Z<~o>A%-oFKkt{p7tzs+;A7D?va^dc=3DRv0+h& z9J>Mz$HZ4D;?X%6%j`t6zXx|(d3>J)gmSu({T#@jIrkp#r6wjea&k!fR#aPxOcZ+- zu=NJ8V-!kQlms+&hJ#jCP99piDl6|E04!h) zfe*eK@VlP$$jp(QA4OU>I}Wr};$-mg$TEDTm?mDtA*s?5kO;8#Ou%2Y7O zz=vT)4jZvli8)Is(Uge7YsW}M2-%SDD1;gwIfURGFx_<>R^7)?%W0SnTV&+T3=#@*{5lCew0+YpJJc!q zdv8$=zY4fTb$|48mQf-mZOqTXAhrcfdgF~Das0E_MgHZ!%W0eCp*(cB7Duft#myH$ z{%BdxaDXu0vQ9X(&@hkw6GGQtAKqp&c$k-crwuczAAe=P`U>Y6O&LKca@UP*1Y}s; z?a+yan`e6<0l}recO9F&?>YYEMteiWD0+ZY<%^_h@BWiL;=Sed7aky-I|AE#1Kxcv z&74g@AVQut=;g&%2nf7(UtV4dv94-HLdGU{ZY}+XwoonKfEmxa#F1N2**OzZ&hPrQ z6PV$AeRWn#y?~(zJP2iGnTnp*_=J%A^Em!PmKT~FW#k$$`%2W~7r z0UE2iD9~q%ZRKr_&$yMEeZI51K}7Rcw;Cw42!IrbLBY>!tPA?SoSMbOd0FvZ*sr2s zlQ(e9qTvund*h$9AM<0s=0}JBQb3hj>kPdP zk#-w?lj?|i_D!4mZ{HpK6PI!RC7=mRD##9RMShz_#_>yzE+TTvFPE#ej68wU!HVC2 z+oY`R#&5{s{smJoP;3b^N9GY@2xw};ZOI9T(T;AIx>s`8Qf0Jt_ zcW-)TAWdzpAj3EfG9eL5$48?(&Fr%FPi$MUV{IcGCyh@*;eCI_xKjcN7$^p zf5o%wXqcI80Xk>Ch*G3Y7>ZEkbr^vZD+0jAxcFS$fu(9qYVwJ%x7{jp6EsBbEq+*T zHkK@pLP@v|-tzi*#Ay?hY40@K@D!uHV-OJ<5M*0FIzKkEi_{~v6XQdl#A_c#4f+B zG`qjqWMA=GZrNG~&IBt3@uJJ6{SU|cI9z;R+kJ*UY$yAZQx)2~DI;Xep;)Ow0C&4f zA$3R&<-uLdauE|1nwYSX@C9(u-Q$#v)ni_PejR-WjE~1hl?$Y=I)&Va6_0w|F#=O& zIJ-c@af*p0arU z>m+QiaH>Bz$op?X4ioMKkS$~8eIRGh0|W?0Jd+r6=j3(?n0(WcXuqlld6zbT!48S77GQPI&~eSOKReXq+M zfcWX}pFi-Xj{<53 z`ThX#ox2`2#t}^3@7_=wt$CM~roC;JHFFHNuM8{JQ9}SM1CHL0FYRt;U?Cv4%XAC4 zK;i7X0lWj+wW}gtSo+yPul2_@Uf2~N2>rJS8jd88qU#O>lLGQEOcRjvb^eYg?bBV64$yR75PdwK z!=}vNE9BJaR3}aAQ)LP6^2HslWaM(3OWEahGLqLl-^y4Z(jEx+B4+E#4l2G1+6qp} z;2zIO_f{Z|`5cKGqzuW0X7P%#d*O%!pmcsCNZy`9iSkbkGpyBr8(&`uY1+-zB0f)?T7UxQs zaDV|DtI2tMbjyZcbDBx7acIP4SdnQ;I|$fhkq1??cRZiiQT@=$R)6_dH1pyr21K7{ zL_d(SILiZZ(!H^MPsW4G7Rk7DiW|kE&z2WwO5R(z7It=;`Zs0eRXtv7m)TqEIWJem z!W5)khHO^^?w+-lgab%_{+&? z>%fd(i%$v_2tWj5Witp&`Ya_-YtYh-p=4@Qv$HCn=uA^1Yt%30)5#J6n}-TgJ#O6} z1@B`q{!$mx91)tkR-0E|^?)0p)04MWPi-G8Bd$Z>DWwk+{UdO4M}xs&8lg3Vl0qNT z8PF;?9K1D$5@8$pY;10cNaXr0qGPquZVy%XUnX?CLyj$C)4`e>{sTX;7q0s*7By`e z+PxL(f!o7{qg4eg^czmqD^WM8H@;ytde@`o;T6BuXRLFw|0Lni9D;Hf(}uem{l_1p z$Qvu{y5t@XFRBRKwsBe4{m)hPsmoz0&Cam1x1Blh_`*5%0N%v*{=BH>3*S4#qRjOa zJKKTcv&AsYZ#DyR3)~yAx7QnIXKT>kcImmyds60Ez6M~Ofv&OiHJxr+Sc=$*b}P;o zdnE#JO9w0xp=;xD%N*ZFm8l^vw+?(Y0)Fu;MIX=gW0<BmF)O7)WUZV;UNjm1QlLhr3@?ti zo5Q@88>MKASzCEq!*~ZR3&@ot`0BmuI_XDZGV56Ge*#WbTVa-n zp*QQHX>BGYFZ?j_%b7hsAJaG!KWBeWc1oiC{o^Zk(l$HeMBG0SFQ>x<6MShPC0`h5 z7mgI+GhUR8!c#8}1G6q_rKGS{HV1N(2KkNDXIaENuqRD-RMV6`z(%45?F-~P`5mD_ zJ<{et#a%4O53P2`UxX<%s_huzyoGk03QUMlrAVP7YwDQJ#is$vLtbZ9RRYI{WsEN; z;&C0?Yt9OEbntuEOa#c??=RI$Hf2%PGrAx3Xo(j3}pJL zK0UrXp1D=nVE7P|kWBsg1O1Q8d`gc>_?8vogdLBf3K#(A@tnCFxw4)FGoISImCqCk zKETy~_4xc$XOWL|*^+y;sZ<4)UoyNn4(0Q^8DLjO_Bhs61%#i8p?jy6+Q|yn$OT7V zxs`3Cz7{4l;WbBKF|QIskupFtJ9CGilo3+s!y|-LO|=xAQ~gHQ)5sUJF-2M$^FANq zLUBOGA@L1MMPRZq1qEu0I#+<|hpVk*6GRJ4=STJga|ngoxM4aA9_7G~2Am>(RBBB! z4|{uOB#8%yc6up$j8~!KlDX_^M9a*H$>owNpUrX*?%Q`U_D#`jxn>2og<+EL{8{5+1lDxER4o4M z8bCqkJRfgPdI9tZ3nLXn>QG<`V7nu1l~UluLcH{M-jLJD1M^=3R@0T2l@w0PR?xPXOxrOh?C^ za*a+(+$$1QDx{Y6Sr=670GWxlY^YBWn8f57my~8OA479?jY~0UV-t!EqKZt__3Ut) zMLf@2_dUv&>Ep zf&E$J_gAgp2g@wzR%0krHe|nkq#D6T2to0=os+7D7|Nv{(Pq}K#C$OU;AK#5Q~(LR zF;-;tXHyg*b6G=|L-I-V8s{=4PIx7i_!4I<*3Z(9>v$L2Tk=cE4PT6Iv`gM#f4TKE zzn-Z6_Ghu0T~^{UI2f_aWp96f#P_wx?juE)t9}99DtmGV zD+xKGF1RfG*Use?a6OP!9m65h<3I{00{+4@5yoMnT_o$IAv?U&cU2dhUK`IuBHJqj z+-GUW&K`uSTD6@~AiBB?oL>m?Dhq1Ol{EN+54(mV-oCsnq?`kd)>+({{~Bye{rnio zyUfAAP?@LvH_hKiZ-CLUoTqm>>4&6EB=j5&d*pCL=y0{$ZeMC!K8gDVRC`7^RgR(o zDi6P-Hd-*G>#L7i(;cs!p<^S%u^7-dY|5hYUg55lKj|@=K$2UeGskkxFlZ|5RNV zZ-)3Q5+Awt!xN@eE3z>F0xaud5=w57TafG?Znd%vvVhIl^_&1891pg-!S&(^3k&nP zpTCDmFM_E#% z(B9szew4(ru)c0*#gXzgORuVBoDIpi{wJ{&a33qm&)eIu|N9xxHMISZEdVqgg*Rcw zqZny$!7I~d!y{fiUMgX1sNH^>)(hQHPM0>(6k;{$5wXY`0S@MaLN^Vq-(ie>$5X*f z9W8zcem;YqFo+*Qxzaer0IOMEW14Sr&UaewdPtU^t<4|k#_2md)vLPPP1+#hmZcLB zBL*5|-rNTwq?piX1X_;9r@_BpUtP664@ER;zwvf%aiYL9SQJEL( z<4nvErcG?gO<-(S+Zvej)gmYP+kSeoPXIP69>a=~5;ZAi-~BXaZ_D*N*rQUSF~jiy z@SSM1e@8R74$r-<2|;7Mgo7uCHqb?Z8rt|poak<$I25RM?No5~l8I!PiTMWxz?)y{ z#R0na@b;`ehw6WlRlw;y*-F9JAZyW~AN;}^?F=sKfL~R75`Ysh6w-f63L|@ma5cbd z3%FW{BCQN)P@ai;63m7R^XU>n{;=HUnI_Ly8fhWqwC(p!Pk&$KM7QNS8Si-w?mFwP z?CeR2?~q2x#{IYX?E_)#N%^t?51Vu%-`CU8L-6S@4^51eofuh>s*JRd!BqC{2{4S! zq0jo~mC!*_Fywv>4Ze0B&PQgeb9EA_q+GP=8=`2Z_S#xp>xC)_KGK2FQ4An4Jlwfu^1g7!5`g15UH`)BXL4Tf zd^@kD=ZAUb78cYhHPf@f@zm4_GUE9vS=?7d0Hm`vcwDNPK==gH$%Qtue<|@}m%G|S z!C^5u8NWie5exKz(9kGv#ReW`(;i3H#?fI z?Ei)^A^O@@c0RMb9C>roWAY3n(GQcpppA`p9Kk z=~HIi2E4N$@W@yoRh&_arPbM4_0bzPHa7oXzu0F^I`-17H!knvWDD(&|FG*W`5ewN z%=wO4v=$c?*>CnB>MlL^ptFMTB=mF;uE_hvda3@fViMW9u@UwGn5uL+OR<9Ho_-LS}aV6$?xk03I|=;$f4QF=2qaS%5P6H^LMy00uDo3IY1$@N8T#nDFf6 zes%C1_Tc|{-uZcR?*}IVj74W=w8Dfj@Zm6Ml+*o|f6uRfPvt`ae+Y1`OgM;0`5h5b ziV>QQMrQT`@_V5p7%=}n)3oWviJRa1Ja{)TH}8hs$LtkW{G;OBKr~4tcQ&rFs+jK4Wa_e6zP~g#H9Px^pqwHT;MPlik6ljW;;~pke>(jTp!*u=rjS>R=lc1oqqh;&|`8z0q5A_|qjyeh%#xek*?K318t&3E z?qB}87_5As5(={3XA6o`smne>KJ5W^7`H#u5sumO_opY{UF_a_vwlH2OET)991y#| zo!+OvZya@yewKo1=f|;&S8u4VYq#$TmFl2}6N!ruW_HrBm1`CA_*1BJ#b|3>iM6bw2uzo`%lp5H;xt7z++|f znDAN)GU3p^NlOO}IFJIoIMS_co6NnR5v+nIi^q|MaoTz&^3NLhh*p9va`*n_O6e8P z;AxA1`ApL^<8yA@K>Y6a-d)yxpiU(tILpMd@t5i!RVNN_4+9cnlJs{1Jyr{g2`tN2 zAA{7*izTolqYSb1{2tjmQ>^VFp{4Y>P9@dRtkFGX+Ls?Sh=lJv+hV>r4KyQSwGx|_ zIkl!PbYjbndGd#|a0V?M$a?-sWX~)s2{`=<2>V z?YrhM-)3i(Wlt8ne7mZ`><^z=AnZZ!eF)gmbQ>6c;W7I24gKIYP4d0vGq_6K-tyDu zar0MB7COdH|3lPUh6NSuU)yx2q)1D*bhjuWAl;#Kcej$#-JR0i4T5xccXx+8!#U^w zz90N3To-%K?3v$M>t607!UwtrZ}DsHuXP7~We=e7Z@#+1m2i*6J?0%e83F zkEQrcyL0k_SXz_b^~3hG#-EQOYY^=t|9I4TvyJ4Njb}a@YRQbPLc5LZ6@HBC9pENA z$<$Q)HSrj>d*sS(`I~;JV4!l10&#dVVO+3t#AYMN*PrbTNy&+0R z5Fs1xw4R=xE;sYW9Nt{`C>vqc9`C_qnQ6(kkLa}|9b#=z_aE!Zb(u3xj@FREJXJ=- z$waBvh#4KK2!;v_y2cz49YQpuX*=ZAp+Y3fcCIeb0%_H*oJ=~?MGTSto* z!P!l1N@amF&my8^-&ZP?l;q^GshT6WuMh1Lo4L*{(nS{a1bL%QjBajjW0R9P%`%3~ zrx~pfLrHS`sS&Tgml!zWeX$PEaQuZ^-X{zpv zz>NjN(&gpbrYgBN`F+D ze)Z#3S>8;17ykZ^BkJ9FCF1bZ?eaNk*WwFn-qeL}^Y{#G zqC)(rHq8y+i*OFjj^$P$3_@y`y@8&bG%IGY$gi(Qcdui3Yl@pv`4 zeR1ni_4pplzwIKjFbYbh`FXfpWf zG7?C$yLFuWs99}#6F|@_1p{&h!7COo>yNj zmYZ4PWwt#Gqwe8HG zd5vE8J|xdGM4a5vn|^;oQi;j9*AoqU0>Uh>+Xz_maw3-;bzFMub5y8Jh0<)G_r45_ zDjrSte7lz>_=~9puxZ8Dl5%p`R8A&l8l$;a@cn;}F75~9>xwTtwkg%Cbuv{GWwt8v zMKH%&T?LeRnf!P;$=Pll2g1PoEu5p&$11>Vc1y`@Z=fplzUEdTnW`#V-!`rcuIYJJ zjh&P<%F(H->57$dS_t4-2-!37CZ%E!5C~nuyH{6gF>eK3h~Hnrig0c0p06*?t`Cl) zZBB&NJ_N>@2sB^)A(L8O1<9PdUkNws_U&)gzKXTb6Zd>NRjbdIsEB&#?ov3`;3J(8 zzO@NkUB5@UKnqQ(%2wjksd%T5A{YJ+OWd?S*k1uRZZ-{zW9#jKQo5r##~AYN_@|06 zYpdY337OyAOmjgD~ZCYI8$Y$cd2UiLlNHB6v7i3;>WrtH`XoeD?y_b4l%IX~o%mUUF?j#ujlL@QpI3U zHtwZQeCN&c7F6ItjAr<;%WXhY9yhSV>>^KE0w{%ego`?1eTAtGNCz?(iI_i^6X)3N zN@L2D=?#h*f@q**SgF;S=GS11(goN@hiby_9(^?*O>QTb>yIm%J+nxJdn0MG+8!qr-`ys>r0!%K>B{#@{hZ|FUbZc13!AH z+SCL~v)9wGjU9vUz0A7TX$X8}8*K^i2MYsPnYHU5;i1BBGFzA`!Won8qwig1FA0q= z-n`-2JrPsz89{^x{)IEGP?g;6YdatD(yy*7rJ;(kf?wr4pnZVy(Uq2xV*8EXH$I32 zIB196GM$D7A7Rnnr4;XKUGv3uYa_~xA=6dxwv{0x)xjjBh^!%%{fm?(jaOYI8M;WQ zztT5h`e996W8ISJG-^W_Sbuu_=g_%!Gb0_p2ZT%<>$4KNJVC(A%a?6gPP0)+3vUb& zQXtC!>bM)aSLujI>^X=ranz+xuLKEU)Z@>A4>&za0peZTW!mZ5tH#_0G?dNCKH~1N zF${$w?53us3hPzD7NDB-9oMghM@3;8R1Y#&<~nq+FS#9-euR7m6Q6#g>SV_`(?S_# z`+HVxjl}WsZC@4eQ^7TGpOa-sOp0hoPpc@BYLfze$a`T^c=ko`xZ`I*{14T5Lk5F> z@;UKr54%|l)GIK$*=Cd-F%o}u5GsidGKj>+e#IEifrNZJ;G_&^Ii#3sUr*b*({dnO z?(k*5k#<;ym2Vs`lEto6ZaNy;bD#M9pj9M>Huntya0SKx0Q4C!jvf$fW{K;nM~m3E zVmrXA(E2j=R?0byB0MDe$b>|ckLfHy=Jy3*AnNe;+g@_WN9x!bsuEMeJtQ)c2=k^x z_IRc~AVVAHK&Mgk#P~6&&|i~f7zs;LF~3i8v|5vK$c*5j$lOizIiZRxSeD8s)PQfA zP}Q3JcoI0oEl58x2;-3;%xBkN>>5ehnUzb{|DsN1buuC%-*>=V&R ze!|Dc&(yHCv1xQ-{z7B`as-7`xqlnXf=#Lz%+Zc4Y%^nejNzRWr9WpmYRW2cj|Fp# z5v7)>qQ4KI##mD%{gr~@+)+_IfswBn?u*RDIOlfJe`x&#Vr6Edh zyHUVuZc)sS8&6myp9qen=)qNpV%I>Hz^}g!05iYDKv## zmI{Wh2OYbdf&N&#YcKa+El*s5V;}f^^3Mm?v=I<8%q>6Nt`NCcNWf7Kt{Ir#zf4RR zPh1$cFhCEqC$#lV?DjfRzCC>RqYxb-k`l9uLJaq#a5S0p8&XOCQ3^y1%6_|b>mYx_ zYFEtaUr8Z1v31|KcdZEd0-kM#JayOr0m-+I*uCWLl*4>xF50S&)zQrm)jp@^+lQ;G zD{R<3}hkVPnCyukWOkB;0gu&BT=}DX8Hi3 zMt#%+v8{DYI_iyIa_F0lojg9!H#bw8+K)|`H^?q~L)cy(-=Lt`Of5{qHqgsXd!~uD zDP@mrxY7va^i&H3@)V=hF@w5I74l+;ycCH2zz*>))pEMT8;u);zHBr3wr)VI<ObJ{;0RQf2C{e~$iX?ftme+rE1Dhijo~8O%=cUWicOzUt~)yQXlh zda$+K4_iY)q`Pb&Zd^2Kp^XYYTFgJ7I47p1IW{Ar1W=RZ+c?{J9rdU|ow~1CoO3bB z6r7<)pbE$PCRpp>j$`qX!&zdtz1uIW4QDJ>V^8XjN8DiF6^$M=FM^tRXm5ADgGwjS zpaBC+e|2CwU8gT!&gV-am0}gV`gO^z6D@lMLYyotDSyBx{H&2WzPkFA{S)Zrg$9Bt zib>GDW+25(nrUrXyGzMg85yxchg4ky}=;F+BJPO%`e8U zNFPsSnDn?L9~Q8_SEW=rp>0RqgjtL<>@m(qx*iC892aEwxru^=sY<%&{XG_IKoL-x zzT&60vK&~ME=ckHobJgElD@tzDKjWC1D+eLic}a*_;Cx-!I?aAVz9DNx9UgcR}^lwCI5%F7IR9uzV1ax_+6CGHfrNxa zi1*7n$-k^^OK{UT^}22DZNEKUG1UDh zpYcbiwjLZ=|@6X zci6t!R>d2Uh^q%cxa+tv%j6C8*!yQSqP+Skz^QaX>-I{#N(Kl}AJXN&P$ys-^4pkI z$q3hrdAvsHsko^U%)U>`5~!wovF&HRr7udon!>^x{gVIsV~{6l2?71Btu3xI4%oQ7 zz04Fi1kOP4bnVuu_V6Z9W%oxhV-U@4gX#}yTp8}o(tI0L$4tf4xdX&KhsVSOgHJ^L z)v=jdd(t~ZIf#Xe2&PV$xIh}q9!eS7BM7lK* zu9!x(#HOqu-=p-M7OCS|6E0}fHHjyK^;K&uSSqn4QBM@>JA>d2co-L4inv*a6px-p zKf}$&>~XddaoJVzaAooXo8=G}ySiefcF)k9+;Q4Zxb)4S&7KKc>z`+6Sam#?0h5rz z?Ay?BkF)(=y|e?4wuGvMu5H+nj6Z)&EgHL!fL*Ec)iXG5jj5`>wvmYddO!UBzeO)An^8zl<&EqpO zM$-SW*)n~;)Ri6f-W8Wro`drF#b!!TMIJ{gOi$48VYDErYuSf}Eo~?cVGp~V_OH(u z-hrsE#|hJcqhEj{XH|&T>h9Ld)rr9Se4=e*)hU=6&+<27vQ~(jta$@6y?RvFa*pY5 z)pv0*ZEnnaLi~bR_sh((az#jc3A_8*9mly!kx#&MpFAkwq%Yyjr(&IChD<&naH0$} z-3moocG@LH-i<&F;hKUCnw|y{Ho%Tb+L>R ze}&fpz{?YrO!_dTvxt3iz;=@xjoAD*-0>72|st-vX|WUZ!VBGrJl$si*7n-#lx0`w#kFNu;8cA){8cUo+L5>IBgx}jpTi<>8{%6D z+ePziF9~wRO+4#hj!AO3n)ao-jW8FCy-^4a`j|I3k&4Xcd^zvSGkgjd6#FvFFFFF; zT?nozRK~}@-=?W03+I<&X}dBF1=)tiDan3I@zVDMD?b&nGKK1x?98>7j%r!LI#|w69 zYI%x~)~NFQZ38$%1)VFQIfQVw-Y>{LEtfNovlpWjqg~Z&%?6kA^J(2AF(-UH+|K&8 zd~vhx#r}l=y`es&$2QUIkYS4Pls5NUhQ+Dh)}{UzPmEL7<(mtqOF};=)oWJOxT`7n zaU8BwDo(Z=;;KYa z!=)>YYe?=z4dZbAsKngRHK3KQ58s3e#XHRDR;ltFC<`iEb>UX+qg7bJW!8fM9 z4nsDoEA1=wbadIs`hZ|Of~#0rAF2y?D!Mi;V{b0PaC*{h;>`S~d4`lk9xq#rfOZh% zHk0TQOlbWJ2qzEpsfv9@4TNZIe1vH(@kDE`LQ{|dfp+y z*<7!>q9vU_RdoW+6I4V{#w==xYC4Vtl!D7I;Nq9H@aisceT| zKx8i=RWzwaNCbg_ApbKnvsBf7upqcoyQ%Y(odl6lOZ7{${=uydN08TGFbZ3(&NU9x zk&-SA<|8Ob&|SkgJO3@3kk-$dcFE4na|q~UHZP0KoEym}yctVS}rp2MseVNFcX`>)d#ILCFCG$WepIX7!pxy>3;t;PvB5=3jsj>KL{S}h@w zzEggU=725{g;Hmrw56O9whnuEg*cckx3{}Pzru2M3l!!i2s*>e-!i<_29hFs%^7hIyFRs~QBo#l&dHj7I|R5cXfJmI!*}J- z3AS5yS?r6J@7~!04ov#V>j%S3QT1M!rskN6eyI<|wkKtjPO9n_O8eJ~K;hYxQ zP3Sz~-SAf0zpjVB-;DyVV%j)Hg+8H7Hq)LMYk?;^&24$q7A_as7!3p@1caoxh?0at z1KaZ}Jj4xkVtm~9)mSJeaE(1-dcBa7mX_vnsJR*fLK1l6h5y7#fw#iibx`wcD@JbP z>He~5u&%y-ljzh1e&zYZIVUf#_eyXNh>Ib+>F#JG_x+#FK*|l)-ku(w1ZbFdXMsYY z_3h8c;WfVcp~ER$&C4)w-7y%;c4)&9Q9rW{RBWjZ+DpceHmwl$G%nu(*p?y;+m`ap zq{RzY)R^;K+7#y4aP)}uNBv1A_$F-{5uz!ytB_t?H6&+EwRK@Gp5nY6e#iHod=*RR zFb;|KzOpI-BxEsftL5-}QmK?Tprp)ljT9DG$CQtV0-hvpXl5 zu_q{b88d&q?t-y~pB`;mExor44+}vwGKpZ%2!Qu&>)%SQTO~lJaXuS%^le%Ko-+7{ zBUGL2w_qv5H%2rt7n5)`S>Na9HFzS)F+TGJa}*Iwu_mD&YL{)b7KxbueHn<@k@WS9d`E{yuP|N4XC0Z>DY{>oHw?9;CyweFQ%;*#S(@L;6aE-SE+wR~ zB>cXOV$>hJx7aU`r@g(U0^duQT?n%4Hlv>2{m{fXFnL{*{I{8HMw$NkAR1}$G4Dtl zt515CE8f#cnMD;45uqG(mzUBtp|Nm}P0qvRpqW}Hpf=QQ?#$6U*Ndz+Y)}^b1lhe1& zKVdH8zjR>IS(jd|HM%bkvyc$qzklbp+d`nCqGI9U2?nNEFkq{xsaZ=lFY5$>EEK*~ z1FV>^EO~_29LRZPgeOXb-~$blcGJ(Kq_;Ko_1}SE3}kjQOyP;a^-l@e4$1kEx&v52 zv$-`LGO=JCnpPdeeoX_6Wrv9RL0#@Ve6vD>bd^jAQ5hbL{>^^E2o8+H*J$n1^MZgk zQ&Cwm_Mp{mM1DV+^;B55FCidaM{f2eOpD zckl;E4(!>6jNLDJ#_UpAaNvI|r^)hLWXjp(!!CSOfR&JI6 z-8#h~(-iocsB1p_dAP_R+pt1^I~u$iG-o5EDT2sv(-cslNQ3r$qPiVqJM1Mh^mZF_ zrPgK7-BnJg7qDmM|0b~---FGoUv?z%pLX@u6J)4kX{U*t?gyerEk)!C2L|iqu^{*q=zOXz#~%Yv0t0i9}*78wb5$e zzPHq?vd{ko_=QtdMw7SL0j=p9RfO-`!}gbsB3cXcUwY=|v5DUlV+~T1WHu%okTf-N zl$`_Upkj3zgC&zRje)WQ8!ZQ4s0EL-Gq<duFAv9ix#eEs*(bp9hi8XF5zsJ3&F_$&~k-!noEc3tLn*XrD zfrydYUA=E{a8_7Pwf2++~|brq*mR*L%X>TyB&6|rV2z> z%(KF?cA4*r){7hBO{wXoy(VSA$APq==Co@r$TRjr-@_Lcy+i)pBr`dV8V#Dl;=l2gh+l%kz7cw4E4Ai!o!CvJ##ei`jJ&XfipelPk zxy^^yxed6Gh5yhb=nhX>srq0L-mPTrKCUb{GZ`2hZWYuf z>g{nDAR)64lTH_VqpEU(UV5H`H6J2XG{b0FbLBU0{B|@3nz58;j1g&1S#n+0E)zrv z(j?bMt|AtG{;zjuPKK9xedWzLAx%T}znj?vV5SzRHOZ!g(p=wiiEaobFN|DTs5!Q$ z^lt|FT|IE6F|( zgypLide{nyj5G6m1W(hCyrLfgV7q~98}2+Rp;Yzx-|B5d108_$KWZ^&7P3C4B}}xN zfu8~gX1-V7p95xVcZ7GptRhQ98Z;)l>7uIw_OT6;zemfll}Tv_Wb1hdPL}^Bw++Mx zh)+ofj*Gr%5Q4s+{$&1Gr1MJW+9qWFX#0|g83FA6A3Y%jDCXYpjpPB|q!=CsDncS# zq@-yrM%B3f-ZZOM-Yui#5a$MN0gh8*sGD#Yt_6ra<6>%#AMv0St-HPi4{>prV>9(pNmK1tl)A%G`rWvSu08Y~RK)}Dlw zSCt9(MuKS1iRYLa_b+INlV^LVFE`UZZ=A>Lj145(lfX1w0}u-;>g46z3&WM5#hTaw zy_iev=V(P5N{*wQBwtqsql+NrmLBP<&{eI}+UMKQ=oo`#pX`AvXPsn^S#svTE>+$$ zQ%xGPtYM2>9Wm6!M?N#Y=`j?u54P_;q51&t7M9^4w}Uf81tL*LD^dAVR)>AhrX`hj zF0RTCj-}7rM_AmTHYkfhIF2SJK?LhogJDffzGBriBgTNj0i3ri-;6=(h1yv(5PYzg zRehH?`euSdKUXeW02udEEI(0&OVMdR%5slE3$AEG0{N(X;_)Nq$mh+UsKe_x8HoJw z;{pFtc2=@^TFgXPsup9`WY!{H&suzXKC!%;u)sG?ZjK87 zgJSuElk{~|9No3-Pp~)Lk`ac~XH<1(@ae#LHB?-b1U@n*bYZh zu4CrnQL=J)L>xhcj!3kjmQH^po&kQgU046nPYXjIWLmX8$qN{=`2nYhP^OK5wt%Y9 zT?JP;7^f}q#zaH0uz}By(_jb?Yw)ytnee5wc-v#0JDjHF-m@iZ!Nn+w#yqnC6((dJ z^{={$Bt^#}UFK-P$In$QqM754nVKzirYfplAOYNCM`vFQcy_sgb;u;6WLsDeV`0`) z@)O3%w#*-)`27SQ({9PL;M{`hRmj(*$o4kRvpH-*Erhj6tMkdRUE#+YMHT2Y8*~Ch zyDXd>u*=nF@r3$xkeP2j{uux%%+u3fGgF&=$XIpO3GvgZT>^WXzjkx!iKm7Ht8?D} zrjx~k={!K#W1kI=fS!22Y547aXk9Cp8qPEG6&Xpw<=mFeS0-b5>fYa!mg?fb^V0e^ZwPZ$u*t&N zv8cey2phk`(7KI|-h4m8O*e&A?foKVhcrIo-k=EWxos>#ZHCM0`nk%Y2(Ia^iCHEz zEZ2k*Yk|7)Jk7qxx<_-|!>p{hq{JV+4wxUIif9g8gK*qQCmM|SR9P`6^~qb}AV9CI zemE@E+GnP}&3>Rg2|$93F2X(7^AU~aOsWl{iJ$W>}C-^yHO7O~OgAXTf|Y^wd8BiR_)_suL3Ey5q; zHR1x<^^>eamc2~?A|{kWpSv9@LBXhaY+IaqBjK*y@s49mRbNSVAD^E1LjRLH$|ngt zRfgN&mh^1JkT-eH1&DCUe0^D49LEhkaBMR1IV-?Y+og|4eV57WS>)d54O4c9_}3!P4i!JUWvPZD`Bj(X60{^=4S~E?V|Jll+8vNU?@HxAB2K4UtA0qiX|O24K&qc zh4LRx18o#18ic)(r++eLh9tjtAIhlIzy9$Hk5qWudP;eljJ3yO=_mL+H3{jf`L%iy z@Bs3WVC?B(=xA&LsAp0OEqRjqOR>isiS}l^B8>i(Iz*q0S{?Ml1Ctt_~*?j7md*Y70$3%i(H)RQ{r!K zGg2A6+VTa1+^sc#Mct#Ec%F%VU{P4}xm{TbylL{${K6@d1Qy&E{6-^_Q~L5R|Jrx+ zIq;v=;qas%MCkA6V8rXq6y;T0_PdjCvg1Hco~o+dEv&{ zeGfBbxhTKG5MikfzhZ2WPD^~TUVf?;2t?s;=Plz12Q_F{GjAZ50jN6ckoO?-ayD22 zT?3!7Rj+O||81aVQc5*lCf^6#VhUpNTpQgc*|4KuQKano-cwZnS)Sq5?zdL;DII!B zI0_4-8b?g}ZqW9eu+{qaD;r|K9NdZN7(ZF^Tq z&ZB`$L*B*<9Vc?_mbXZNe~Nw5Ii1k8jO2#JOHmJoX_cjnNbYY!&E6~WjxCGQqqY%$ zg-`vs8O*?0FEJoE37XezStEbvoBd_|f+_TGyS{GiZjKx@!@Xu|XG|d4A6GvWd5!*d z?+bIE@4JjA`YEM?!uCjVaUR}~4hqF`W&Z?zIdm&3i%=7;sEzf-4bvxiD7H?fc!TYN zz#sVHEQWqEKM{(xiRjS#V{RN%tiLaZlAwcY)dnY>Bsq{~u%YRF0ASoL4s(jTqB=aA zj|Yv2x~sc0B9wh7x%vT=+&tS?D&*5NCCYFTeY;Ylx60uaU5mXn9>9$$ICQ#o`RW)# zKEJw;I~dJvZ44j@;k71}1Ka;?!=|QxR0F4gDz|ZA@=hu)Sf?9Ny^7=B*Y2RfN^v$7hbk5I@(a z-@_PPH&^!Vvs0Vz+MRLG!We|3eP0bD#zF#$xE=D6i5I-)VNCF>>Tl&tc~;U8YLw2Z zpqDLXFp@p1HiYYWW091^gsDNUplz!Ep39Cm@!!{!|LZ(UsiaSymW6+~`-U4s_br^@ zuSHe>jVWtHou}D#f11Q`FX?wtm&DPnB6H&T^_m2Ow=uDxy=X00N(Hj|)K6-8N#pZ6 z)8B{eqx|@w9OfU(=RU8Z}_a{@RO)hWTD zxmsQ(=qhV=+cX^J2%R7vR<#u$Y&*aI;9b(KX6UvhS~fpL3m-gNj>8k+m_EtK(^fE~w- zuqwixi`JxeAoxQ=s2%>I@1<&9>D8^O%VO}aNeQe}x;j7CnubaT2Ctn$66VDkkC$4B zXKu?(!WNB}cNi{5hs6aNx~CO`c3EKnu4nQKmL1kXHX4J7xNEFl7Q6StKW3NA_?Z5^ zm~>&YClBf)$0EjRBhEjUq48CVkh{SLc?J2TB z%ov3Ryai$RQ1BPtYaA;4(!%2h%+VaZM@I}0nORw#(@re-(_LkVR(z|!rhlq1M)M&4 zdK-23sN$J~XTup4i-qL!?LWVRT|E%74$;RJO^f%06N+cIIX zU!ac6v=bU?H^^p_o$$zhIx*|wW6UNujHk!>LRK#*xefHv1tmbk94^DrScZUZ5J$VD zDuU_&nAg~Fh<<70G8Wdqco{O?`8t9*myKywT-&fjSF3S_;Q?H-A3{c)d%+TGb>FNid5!8c0)he%vf63k z-hbu%Sc*RNW1plJ@fD~Xu$d~L`I)2Hc$E0nEmz1EGqBDV*k`kKK@I?iEf$JcI#qR@ zW1P5bt{#tP_+W`|3{iMWu?b8Ou6$x*Uh`E{1XWJo-QBT4ze32#1BR_;&Go3SDC!k# z2zz&NIb2gCz`x15*FLi^yu7u|fQJ3B{iKAXX<67_%sqBVjB8>-+YnNF`+jXxH4j>Q zjc1Vxb~y89!aUID#7N`d(Lq5#!;rUjVme#Zxn-dc@d=4up}~Eu)rdNta8Eks+u~x* z-TgkT=Av>4#o&tUx>Xft?XnDmz^BXT&{Lwf-T$&&mzAnjsO3$muuRduOvzCzMN1)J zEN*nQf=i1TR|>Aw7wH^Rd7Rti>CJpl@ftZ~ioBPWddKXq1Wma# zJw6U@%V*ETk#o2?>Jz9dC?7ncy*M@7JLQuM?V=>l)IgZ4XmgsaO~=7ca}UjQop@nC z4_l)nM>Sr`K|N|DaZ1lqRt)~KH(|M}jSx6^VaNg-=A1vquS~Dm8AIp$6HA0^2bYOf zAjKg+DYUv1Rn}4-FfVe^Z~U%e;yJ%X zdR&k?v@YrYo-5oB+mCE11MAP|sbVh{og7Y9bpEex3n%Yp*Kjm73+tl#!CKD9=$`)@ zTWVR1ZI$shvAd6?P0b^!ktMAQbb8$Nsai-lw|Z$9FFfo*L=H$MPGhRXFMg^Q7@ZR4 zO6p3xA?ik>?&!%rXSbv7!>U8r0}0AE+`FR7T+Orqp6;C4tll@qz^}TT@GLc@Ln?Wq z#X)z9!v#n&tT96((c4w_J8=Yi5G;9$Gh&#<*k)~@4@A>f3%b?D;_AS8!IuJB9o-n= z1HgJv`8QJx{;x-Z(AKqBUBG0A+ccdk%E!kvq%uMIHvHXfRmLs=@V>+80_!ulsS|Yf zMokl&|Ac9>*DbaG#;)hT`&-ev5rBwL0V0a+@iSk1X~5wqor;E<`nUeFN;|`jsAi6_ zgct2$cZpJOGlWOw_$dkN(2ruKSbjxYRn;CY5MWKZT&>J++?q2!NBeTZLKilhDJH2A z1Ji{Sj)6NwzX(TL-VnE&FF`3z5< zy6b`YciKigd<@*8y9J@O)=HGHW|UJS77VA&IfN1BKAD%i5F zM!QJ1%N%@gEKN)9cOXc&pY<)fVYS{-i`V&AQhz_BcKGj_OI} zsnm$(L3?sE%$8u(tqH6CK?J6hDOgwrZijFHeK=jAHzG6w&3E>oZ7KK7DC8m5cO{N7 z+W0I1T(4iF%*DX$LaipfKB9krhoAP7vzZu`M{>q76W+DyuvjBI6;#m`hxq7(t=bR( z7(H8O0Q(rP;Bv!h*f(=jhZLv!i+_%)!n!L(W-DxFo{6^bO^r7pf7y2;(mItRUXUE| zm@_>aNWv6H48tcxH(X_E9lzByqvtHQy38(G^*$Wd`Jv+@Q=GlYHUA7IF?>4a;4@eX zp2(&RwRxuMr5753M+9p|S6WMGTq6&C;83uPu#x;9%bHO+KtzZ5FBN?gX&01pC<|qL z*|oj8Aa`<{#;iYYegEBw3t704lrLt;G(X^F+}0D)(?IZhL)kTVoR4fhqej-U>=Zj3 z8^_o#8@UPUyi@M)0^5J8to#YIkBcSvNxzE-_8!W1rWrGvZ{HNegWP$p+WxQRq(?gr z0Nsy6-XoS;7c8EPkK-6KcfSxGCHi={w8?{}shKk;#BQxxJwOBCC@0U~{^;-Y^z0ds z{{j+QfzFB>VC@qAsj>0^w@hGc0K3CGWTf6;tDKlI*?gM>1HG@*dQ_kHh4Ea_78l65 zd936RX*jqc1h6SHq%gVloQ+YQ+32Cejzw)q^UOW_0~_gt%>RM~QQofB(PpZ)fI?7v zB3zE0Vgc-Igt}b*u@h~JBmWqPu^oQ!P5*2u<9!}-jvEU_&($JErXKx%GA21h!W#_4 zuu7K)a)YnpwOC}M?DhIJ&3HKip7@6+-7dQXThN16hYx9*Dzz?Xk&iIGyFuhu<|RwM zR@*lSrrg76ExY{3!n-`cmhwUA!)OltC}ROL9{2S<3xwLF-qAnCUa2u(Rln^ScI-c* zHM<#L{t2=jfY8&~&^2x!qMa!F6>;we99*3Q4bi3SLGA+OhoVi^DLaojgmL$@gnu~7j_19C6T zX8YIr%5)}YJ*vb%!BeT(DEw~v@ouigXcWoQre5!Ha}T9U^G_VXQ1&Cdo2di}D9!}1 zzO;Gk(keni0~nVkf@uJmzo{$CfokfopIgQeV<6T0Ae}(@V;4-tH0gl>eWKEd=R?-N z5j@9r@J_I_Wi$Lppg4<0kc}n{@_)IEZn$cMDcf3Yp}}p(3OA_SdGg;rrLf(9>{=b) z=S4{m5gGXvc}Z?1!1B}Iz{&J+u)Q)%&`0q{yKn3$UOZ0k2Jb-ouT{q9M@KRH?M3wm z?WA2Y#%HdFZeE!O&ovJy?hJ^P`YUS@8m~Wyf@gw|siUeFNmU;ERg{aE@w3{M#}kfH zUdG$jj~$3mUDa$s3`X$_48j}td7c=g_7Bi&II^~ZFb-U_p5b$@t5bm62wmY&x_YL%jSt8H}qV_LIu&OEa(8HEjy3VvP+?3zq|NcZidfQnb>7thb!JXI7NgGMJQ|7OH1iGx@xK-qe7f zK`O4xe%f=sT>Kceit>%TxKqkwtQ5e0my?fv;szFAPlQ8|XI}2h;;s zvY4Q%dT3c0o-xG3pU)nZDp`tZY1MiAF{V_j8zN1Al?Txr@TiJB`3pdRUYi zI*E(WApIL~w%fPsU1dT?qj}Ncv&pPEtz#oC6g-;bfG!Ms0jWoG=bClhjQoZQgSSyd zlA-^$rmFP3wy=9X?m`9BU>trkY5(^-Ta9?N6*cQ7{=$%E<%g=6B+MIec-}tDgjZi_ z7vJx9wUx!{WrA;5ZoYf@_BjgJiZNYHXkJr#Uf*Si<NtUxIXu(kxu*f+y9Eg&1154j+9 zd#EEhpCb7=u_V!;>rL3vyCHJ;O06N!>Y(<_7H02;bFdcF=W!sRjlir)Mjs{pQ%7y( zz0im>W99nv6fmKh-1!?i&4@T{hie0r{uOhK74v*=`6;)?$TKEgjs^CtgrDy8?bfk+ zbit0uSbO{C-96Qf;4;U)P>+7NlnUlH7dMWrUIqR6MS){Zcmr(Nsx9L2e>D)^#|&I0sh}rhHcdpd;W`l z+z%E>#h1%uB3+w74ZB-)ZweV4;~NXBP5Hm$J?Jj@v148W+_4*V^71>v^<#;_KY`aU zum8Oy>$&A$P-U=roG7?u4BmPr*g&@DmF)e) zI3KlC4*36g;epfe>|WJcLMM8ClP8qf2o-tHy15O@exLt@k5feJChzc_&8g+#Sr{Hu z%9}BsaC@1|_gPdeHR4~m$I3yiF4BHW4ILC56u}4;$!KZFO^S%MLSIl06#+&?-G`sQ z(56u0*Tep)BLfpoy?8NcCTKe49j4GG%6s2`(9=5VAN&F_n$#qSEk&Ik28V%7w1>t6 z_oIjcT$aFN@u`b~tU*W5*3XZ;csiS4EvK+}54$!s(Qa**8wVSU83@tQs0BKLx@BP` z>BQA`?fV%&BErP~tN!Jbc4|ZnXH>HQw+8oaQ6G2YRP5>ZmqM`ib(13WN}ACpONsnt zpePZrMIw#=Tk)#R*6ML^mvNXS=aFB&_NIOZD8v%wQ7HZ9(ll6Vwi>x2U^ z=8})rl&#ia%nlF3n!ZVTMtI;SSko6O#780d;!*sCfQI>#QFac)R`;uc0GcmgW(> zn$ZRZXSl;MbYn_XBKl6*30vK6E%Q<(BpJ*g45pn8jbkir^66E@%VD|P(&Bf% zDx*d`voGlTQE#}UE(gBU`CuP|(P8#+pr{rXfvhYoD{BFh4w5|`<{;`0HI>|hP5wbL z$(m~74UQe1Ly8FKIFZ0NO?q2oR<@h!=~>r3Wn)U)kQGT(saY*1wCz|}f-nRlte@T> zDMW~EdkN0J^bJb=BM%eK#zTlgq1H6}{ui{JNh~`vaFe-4-9eOd_K0CLO);(^hHm9I zt2z|{FJS$kivuYJqOoY#_G{9%oXnM%I^gWH@t>J=f1E<6EpDY8eADJ4s*o+hXV$b< z+XNcK$FB^L(AAVgx$@}n#n(6x{TJ!|ToF0hUpvj!3Tv-^Py%VyA(V60;{W>h7|5W= z3De5vp(_eh4`Lhu0mJmKmnyF*(pzh=!U-q(mqA#lr?Zsy9AXJCXs&sD1A_GL!Lk=@ z(H@#{hHi(ghHlp<#GToUH;$GjADFaq&v6k1mZNW&vak(S{YV?KS-iewE{w=!+qKLj zv%`W;ifIps6tx|uyjcW+E8^uCX&bC^Bnf{$s9|}l zC9<;zkD;}jn=6RTpQev!I~X(oP3etz1R>tTFPsB$6N%XN)OGqDGnl$r3E6d-_A1VY zs0=8zVsu_BulW zlQ5!a`Kx2uF&Y1WFP?<65#|2B>T%8x-6iiNPAw(;*XkFtU%&jNbjllx$FHDYbFs-N zBz|g!%pbKFnt*$DI+^J!k3Tx}%ZjCN;2g_u9Z!CtM;r?69HB9RrAH~$YWtEF=M@2; z$Y9Qyaq!K%7D@6QH4@T6#P~@B(QO%*y^_IsN1!44^%(b6@k0oO3Ddv!nFl>(ru3SH z_1SV*pJ&UzW6EF0f1mtrY{{0dZ{uphFf#RP(}OmZS#f(lZXt>DwOnYgt(2eDyucUy z(i|@pPk<=W;qiSxbYnN8D|)kkW@+k6L{*W(iO=&CIXHUM)q6kBbDz@tM9bTi#ueqq zy7FQ-75z4Tvi7i5QJ}lk$_5X zBm{nPxyG2e!IW!MSs#?^Df!;R|9dA9WB4N<=SclrI_HxTwJMIq0MhQ+F~g_j<+#@t z^Rs$t;$NS%a1xOM`66oEo-X>Ym>mw zE7YjM+->IGBk@vA7-8AUexQ6bePm;B2O+JAy+LSln-KM&V4|iO$0Wd9C!^&|rJE zlsJOfUVz3`AFE>8gzI7fT}WZzfROz!jvR!7c$4MzRCx%>{B})>H~39rPjA1MK9Li} z)-NR5nVpFLfnDrHAKM~VuqjTLi>z`}Uj>rn*g)XK-BkR>{Jep2jK_j{?qlA4QeVk zz8bxC-bmRDcY{*-8n-u?t{anx$Wn18>~kJj;(QU(Mkwq2L&m1&ZRhcLD!l_qLT8!_ z>SNfL-sflu{gOAQdAn>;HLu0d8B)i2>o>Ug;_`1iHZAQq{7>_gEj4lD-B;Za9{)U6 z)UwAjJnM@sG{aaMC|UY?H8&zBv)+LshI{nQbytxyk$;WO|H4N}Yt1{E z2n+zY!*pj#POE-L{^=nu%5OF030gHbC={fs2 z?3*cUUpD|wL85o0U>Zd^>w@AS#~#xk@nVy7=cuvQ1PM(g?}tUzL8~bg%|MOg&0>`) z%yp1khsbrN)4pY8k@Vx2&Vb!N{pY!_np?n_sM*Gpkn3!y7(N{-DmW}>0%E{>mME6Wjti(QlCXRkh7OOYVM{iIY9a|@DsWFF? z0z6k`v4Rrx*c>&ZVz_Rca>lMpv806T?;eFpcVas%&!@Q*nXY z*$HFiGmd)6QJ^aBi1#Ljh8FB=XQh{DX`xTVcBzq!2H-fOlUr22tLT!N*$=1zzZU${ z*&o=U{$4)%&QDuX`?p6PNsdpZjX5AQTsAo>?<=I2q+5kQ>kaacGSj(Q>#PMC9aiZz zhqq=lV6o=&x50nPN)~#}gju}w+q3wx!6h$~tX<$@B;T_pA=@_lcPfPUPOyn*0_1{z z_&18fW|z_)&ipU~ywzU6X%Fx~-4y>%GQnHDO;L+!DOFZ(>HcucJMSoazo3l1~c6XA?qN=Yv!CtnJlmoKlWx2Y4 z2)M&9`S*#<>#*=DgxiW6kwbJo!6X@9tUeu@wok^e=sfnm8Ke;KyQRrJ9Y??79W##P z!kREoC06P@E7p>>yLdsRLLyR~lSM){L!i;~OXBcz*~ktD33@bOt?td_ML95)=vR1A z+I_%e?TLC%r9wgUcB2IddDiQ^x%uVp9#Y^(Mqe>^r2J-R}zjcVyyG0+@vzu;KM@HhCsFrK1DM6OqbD-P!G{lIQ?TgvC z021PsJwfqoq?YJ2h>h>mc(nI{oKm$j=yVgq#QdG$qm%aYO9zkr{ICDTst=5uf!qpD z8_2_l%9A+A(jnn2X1 z?4_ZaSk;Q+{?nk=dz=<1{^&X3{zkU#GJtJ^0MsqgS_f3@SYM1uD2sbt7?S%vmFrC z1Q8VE&nCOb27xsO-*<8!ce<9Grm6|w8a;sT!OfG0D>@*lbSSa~ET!5zDOhSamhS=I zzrL6&K8in485f7X2o}&>@zk&ZQhD^Yu&@1uNl@TZ{jZtvj|8yM^3xXcoT|`#%6K-Za zv+m8q58~p_yiy9CXJy4c@&eOEOmPKc^D4^ZkmzC0-J7jFDesS|qA)DQN zj)kL(t|=?=bMjpExBD16rA1U-DSBGcQh_9QJ)&zz9g<4%uCca+5)2Ul)-9rkd2kgB z2}YMb6hR)kt1g{-mM!eM2TG`UQ&T=tX**HXxkAz!*#o}dp@G1O4bbs44jo151qKO$ zt20ceZ#q~#qC{iBHHT@oFJqXO55&dE6dTAa(0s9?P)pCJB&>sjz%^jX_I=<3bSHhO zg1R#v&Wovyr=$J0i3eMi!Qk5J1}uQASBU-EU?%k*R41p4qkQAsI32c$unHEG_0gPIQOcVAkAJ?=Pylu1&lWFrB;hHB!m86Bq7 zBuYs$4XHJYNpH&Wv==HcJJ`gY*S8W9e(TJH_N8)&rXBw|g1mqU+1Y8%eop>J8YoDM zI5#LncKPJ$#&@*1C`}JL@BeV%{t@f1lfkEl{l#3{MbJTum)(i|15MXv!mzr zSc_H4ND~`4O?#DC@#|e>^&5hS6roq#p7If9wDCbw)FU;k=d_92@4bkh5^d6B2U>D`PHQ z4e>=h!Z$$a&NTJ~$6|8FULL9(I_eVsoL+&K$wf#rOBl