From b13a838a0a4311a9ede22729dcd2e126e7501f05 Mon Sep 17 00:00:00 2001 From: ASEM000 Date: Wed, 10 Apr 2024 23:12:50 +0900 Subject: [PATCH] Update [guides][other]optimlib.ipynb --- docs/notebooks/[guides][other]optimlib.ipynb | 179 +++++++++++++------ 1 file changed, 122 insertions(+), 57 deletions(-) diff --git a/docs/notebooks/[guides][other]optimlib.ipynb b/docs/notebooks/[guides][other]optimlib.ipynb index 0b7d37f..1aab273 100644 --- a/docs/notebooks/[guides][other]optimlib.ipynb +++ b/docs/notebooks/[guides][other]optimlib.ipynb @@ -13,7 +13,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In the following example a mini optimizer library is built using `serket`. The strategy will be to write the optimizer methods with the inplace modification as done in similar libraries like `PyTorch`, then use `value_and_tree` to execute the inplace modification on a new instance and comply with `jax` functional updates." + "In the following example a mini optimizer library is built using `sepes`. The strategy will be to write the optimizer methods with the inplace modification as done in similar libraries like `PyTorch`, then use `value_and_tree` to execute the inplace modification on a new instance and comply with `jax` functional updates." ] }, { @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -35,27 +35,24 @@ "import jax.numpy as jnp\n", "import jax.random as jr\n", "import serket as sk\n", - "from typing import Any, TypeVar\n", - "import matplotlib.pyplot as plt\n", - "\n", - "PyTree = Any\n", - "T = TypeVar(\"T\")" + "import functools as ft\n", + "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Utils" + "## MLP" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ - "class FNN(sk.TreeClass):\n", + "class MLP(sk.TreeClass):\n", " def __init__(self, *, key: jax.Array):\n", " k1, k2 = jr.split(key)\n", " self.w1 = jax.random.normal(k1, [10, 1])\n", @@ -70,7 +67,7 @@ " return output\n", "\n", "\n", - "def loss_func(net: FNN, input: jax.Array, target: jax.Array) -> jax.Array:\n", + "def loss_func(net: MLP, input: jax.Array, target: jax.Array) -> jax.Array:\n", " return jnp.mean((net(input) - target) ** 2)\n", "\n", "\n", @@ -82,12 +79,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## First order-optimizer" + "## First-order optimization" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Optimizer (Adam)" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -133,7 +137,7 @@ " self.nu = jax.tree_map(jnp.zeros_like, tree)\n", " self.count = 0\n", "\n", - " def __call__(self, updates: T) -> T:\n", + " def __call__(self, updates):\n", " \"\"\"Apply the Adam update rule to the incoming updates\"\"\"\n", " # this method will transform the incoming updates(gradients) into\n", " # the updates that will be applied to the parameters\n", @@ -150,9 +154,22 @@ " def update(mu, nu):\n", " return mu / (jnp.sqrt(nu) + self.eps)\n", "\n", - " return jax.tree_map(update, mu_hat, nu_hat)\n", - "\n", - "\n", + " return jax.tree_map(update, mu_hat, nu_hat)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Learning rate scheduler (Exponential decay)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ "class ExponentialDecay(sk.TreeClass):\n", " \"\"\"Scale the incoming updates by an exponentially decaying learning rate\n", "\n", @@ -178,7 +195,7 @@ " self.transition_begins = transition_begins\n", " self.transition_steps = transition_steps\n", "\n", - " def __call__(self, updates: T) -> T:\n", + " def __call__(self, updates):\n", " \"\"\"Scale the updates by the current learning rate\"\"\"\n", " # NOTE: calling this method will raise `AttributeError` because\n", " # its mutating the state (e.g. self.something=something)\n", @@ -197,43 +214,85 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Test" + "### Composing" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "class Optim(sk.TreeClass):\n", + " def __init__(self, net):\n", + " self.adam = Adam(net)\n", + " self.lr = ExponentialDecay(-1e-3, decay_rate=0.99, transition_steps=1000)\n", + "\n", + " def __call__(self, updates):\n", + " updates = self.adam(updates)\n", + " updates = self.lr(updates)\n", + " return updates" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Training loop" + ] + }, + { + "cell_type": "code", + "execution_count": 7, "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/mv/cckpw89s2jjd622p9pywk0nm0000gn/T/ipykernel_91930/3733352812.py:39: DeprecationWarning: jax.tree_map is deprecated: use jax.tree.map (jax v0.4.25 or newer) or jax.tree_util.tree_map (any JAX version).\n", + " self.mu = jax.tree_map(jnp.zeros_like, tree)\n", + "/var/folders/mv/cckpw89s2jjd622p9pywk0nm0000gn/T/ipykernel_91930/3733352812.py:40: DeprecationWarning: jax.tree_map is deprecated: use jax.tree.map (jax v0.4.25 or newer) or jax.tree_util.tree_map (any JAX version).\n", + " self.nu = jax.tree_map(jnp.zeros_like, tree)\n", + "/var/folders/mv/cckpw89s2jjd622p9pywk0nm0000gn/T/ipykernel_91930/3733352812.py:5: DeprecationWarning: jax.tree_map is deprecated: use jax.tree.map (jax v0.4.25 or newer) or jax.tree_util.tree_map (any JAX version).\n", + " return jax.tree_map(moment_step, grads, moments)\n", + "/var/folders/mv/cckpw89s2jjd622p9pywk0nm0000gn/T/ipykernel_91930/3733352812.py:12: DeprecationWarning: jax.tree_map is deprecated: use jax.tree.map (jax v0.4.25 or newer) or jax.tree_util.tree_map (any JAX version).\n", + " return jax.tree_map(debias_step, moments)\n", + "/var/folders/mv/cckpw89s2jjd622p9pywk0nm0000gn/T/ipykernel_91930/3733352812.py:60: DeprecationWarning: jax.tree_map is deprecated: use jax.tree.map (jax v0.4.25 or newer) or jax.tree_util.tree_map (any JAX version).\n", + " return jax.tree_map(update, mu_hat, nu_hat)\n", + "/var/folders/mv/cckpw89s2jjd622p9pywk0nm0000gn/T/ipykernel_91930/624809840.py:38: DeprecationWarning: jax.tree_map is deprecated: use jax.tree.map (jax v0.4.25 or newer) or jax.tree_util.tree_map (any JAX version).\n", + " return jax.tree_map(lambda x: x * self.rate, updates)\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ - "Epoch=1000\tLoss: 2.632e-02\n", - "Epoch=2000\tLoss: 5.233e-03\n", - "Epoch=3000\tLoss: 3.013e-03\n", - "Epoch=4000\tLoss: 1.561e-03\n", - "Epoch=5000\tLoss: 8.358e-04\n", - "Epoch=6000\tLoss: 5.747e-04\n", - "Epoch=7000\tLoss: 4.370e-04\n", - "Epoch=8000\tLoss: 3.416e-04\n", - "Epoch=9000\tLoss: 2.878e-04\n", - "Epoch=10000\tLoss: 2.520e-04\n" + "Epoch=1000\tLoss: 2.438e-02\n", + "Epoch=2000\tLoss: 4.649e-03\n", + "Epoch=3000\tLoss: 2.498e-03\n", + "Epoch=4000\tLoss: 1.100e-03\n", + "Epoch=5000\tLoss: 6.216e-04\n", + "Epoch=6000\tLoss: 4.409e-04\n", + "Epoch=7000\tLoss: 3.273e-04\n", + "Epoch=8000\tLoss: 2.752e-04\n", + "Epoch=9000\tLoss: 2.299e-04\n", + "Epoch=10000\tLoss: 1.949e-04\n" ] }, { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 4, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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", + "image/png": "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SHOLlHpWGwx8zz2baONM9wJwF3T/m3tTQRXtIqWGNlsw0dGjR5kwYQJ79uxh9uzZ/Pe//+WRRx655PH/+Mc/WL16NQ888ABbtmxh3759fPvttzz00EMANGzYkP79+3PXXXexdu1aNm7cyPjx4/H19S2pUxIpPaw5q6i2v+d/bQP+7R7Eq0JEpFTxvJ6RMmTkyJGcP3+e9u3bY7PZeOihh7j77rsveXyLFi349ddfeeqpp+jWrRuGYVC3bl2GDRuWe8yMGTMYP348PXr0IDQ0lJdffplnnnmmJE5HpPSxWGDAaxDRHiqEQu1uZicSkXx43myaMqJnz560atWKt99+2+woQNn9OoqISOl1pbNpdJtGRERETKViREREREylMSMmWb58udkRRERESgX1jIiIiIipVIyIiIiIqTymGHG5imb/i/JKXz8RETFLmR8z4nA4sFqtnDhxgqpVq+JwOLQcegEYhkFmZianTp3CarXicDjMjiQiIuVMmS9GrFYrtWvXJjY2lhMnTNqTxgP4+flRs2ZNrFaP6SwTEZEyoswXI+DuHalZsybZ2dm5O97KlbPZbNjtdvUoiYiIKTyiGAH37qBeXl54ef3FNuMiIiJSqqhPXkREREylYkRERERMpWJERERETFUmxoxc2Fg4OTnZ5CQiIiJypS783r7we/xSykQxkpKSAkBERITJSURERKSgUlJSCAoKuuTzFuOvypVSwOVyceLECQICAop0+mlycjIREREcPXqUwMDAIvu4pYmnn6POr+zz9HP09PMDzz9HnV/hGYZBSkoK4eHhl13Hqkz0jFitVmrUqFFsHz8wMNAjv8H+yNPPUedX9nn6OXr6+YHnn6POr3Au1yNygQawioiIiKlUjIiIiIipynUx4u3tzXPPPYe3t7fZUYqNp5+jzq/s8/Rz9PTzA88/R51f8SsTA1hFRETEc5XrnhERERExn4oRERERMZWKERERETGVihERERExlccXI//617/o3Lkzfn5+VKxY8YpeYxgGzz//POHh4fj6+tKzZ0927tyZ55iMjAweeughqlSpgr+/PwMHDuTYsWPFcAaXd/bsWe68806CgoIICgrizjvvJDEx8bKvsVgs+T7+85//5B7Ts2fPi56/7bbbivlsLlaY8xs9evRF2Tt27JjnmNJy/aDg55iVlcU//vEPmjdvjr+/P+Hh4Ywc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", "text/plain": [ "
" ] @@ -243,18 +302,21 @@ } ], "source": [ - "net = FNN(key=jr.PRNGKey(0))\n", - "optim = sk.Sequential(\n", - " Adam(net),\n", - " ExponentialDecay(-1e-3, decay_rate=0.9, transition_steps=1000),\n", - ")\n", + "net = MLP(key=jr.PRNGKey(0))\n", + "optim = Optim(net)\n", "\n", "\n", "@jax.jit\n", "def train_step(net, optim, input, target):\n", " grads = jax.grad(loss_func)(net, input, target)\n", - " grads, optim = sk.value_and_tree(lambda optim: optim(grads))(optim)\n", - " net = jax.tree_map(lambda p, g: p + g, net, grads)\n", + "\n", + " # argnums=1 -> return the updated optim state\n", + " @ft.partial(sk.value_and_tree, argnums=1)\n", + " def apply_optim(grads, optim):\n", + " return optim(grads)\n", + "\n", + " grads, optim = apply_optim(grads, optim)\n", + " net = jax.tree_util.tree_map(lambda p, g: p + g, net, grads)\n", " return net, optim\n", "\n", "\n", @@ -273,19 +335,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Line search\n", + "### Line search\n", "\n", "In this section [backtracking line search](https://en.wikipedia.org/wiki/Backtracking_line_search) is implemented. The line search is used to find the step size that satisfies the strong [Wolfe conditions](https://en.wikipedia.org/wiki/Wolfe_conditions). for more check [N&W Ch3](https://www.math.uci.edu/~qnie/Publications/NumericalOptimization.pdf). The method is written in a stateful manner, i.e. it modifies the state of the optimizer inplace, However it is executed in a functional manner using `at` method to comply with `jax` transformations." ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import jax\n", - "import serket as sk\n", + "import sepes as sk\n", "import jax.numpy as jnp\n", "from typing import Callable\n", "import jax.tree_util as jtu\n", @@ -300,11 +362,21 @@ "tree_vdot = sk.bcmap(ft.partial(jnp.vdot, precision=jax.lax.Precision.HIGHEST))\n", "\n", "\n", + "def mask_field(**kwargs):\n", + " return sk.field(\n", + " # un mask when the value is accessed\n", + " on_getattr=[lambda x: sk.tree_unmask(x, cond=lambda node: True)],\n", + " # mask when the value is set\n", + " on_setattr=[lambda x: sk.tree_mask(x, cond=lambda node: True)],\n", + " **kwargs,\n", + " )\n", + "\n", + "\n", "class BackTrackLS(sk.TreeClass):\n", " \"\"\"Backtracking line search with strong Wolfe conditions.\n", "\n", " Args:\n", - " func: the function to be optimized with respect to the loss function.\n", + " func: the function to be optimized with reskect to the loss function.\n", " accepts single pytree argument. for multiple arguments use\n", " `functools.partial` to fix the other arguments.\n", " maxiter: the maximum number of iterations.\n", @@ -324,7 +396,7 @@ " # make func pass through jax transformations\n", " # without jax complaining about the function not being jax-type\n", " # see common-recipes->fields for more details\n", - " func: Callable = sk.field(on_getattr=[sk.unfreeze], on_setattr=[sk.freeze])\n", + " func: Callable = mask_field()\n", "\n", " def __init__(\n", " self,\n", @@ -357,7 +429,7 @@ " self.fail = False\n", " self.iter_count = 0\n", "\n", - " def step(self, xk0: T, fk0: jax.Array, dfk0: T) -> tuple[T, jax.Array, T]:\n", + " def step(self, xk0, fk0: jax.Array, dfk0):\n", " \"\"\"Compute the next iterate of the line search.\n", "\n", " Args:\n", @@ -409,12 +481,12 @@ " return xk1, fk1, dfk1\n", "\n", " @staticmethod\n", - " def cond_func(state: T) -> bool:\n", + " def cond_func(state) -> bool:\n", " *_, ls = state\n", " return ~(ls.fail | ls.tol_reached | ls.max_iter_reached)\n", "\n", " @staticmethod\n", - " def body_func(state: T) -> T:\n", + " def body_func(state):\n", " (xk0, fk0, dfk0), _, ls = state\n", " # NOTE: calling this method will raise `AttributeError` because\n", " # its mutating the state (e.g. self.something=something)\n", @@ -423,16 +495,9 @@ " return (xk0, fk0, dfk0), (xk1, fk1, dfk1), ls" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Test" - ] - }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -472,7 +537,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.0" + "version": "3.12.2" }, "orig_nbformat": 4 },