Skip to content

Instantly share code, notes, and snippets.

@mariogeiger
Created September 29, 2022 19:54
Show Gist options
  • Select an option

  • Save mariogeiger/75a454ba82502f5dc999a1ec969eaba9 to your computer and use it in GitHub Desktop.

Select an option

Save mariogeiger/75a454ba82502f5dc999a1ec969eaba9 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import jax\n",
"import jax.numpy as jnp\n",
"import haiku as hk\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import diffrax"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"@hk.without_apply_rng\n",
"@hk.transform\n",
"def model(x):\n",
" # Multi-layer perceptron with 3 hidden layers of 64 units each.\n",
" mlp = hk.Sequential(\n",
" [\n",
" hk.Linear(64),\n",
" jax.nn.relu,\n",
" hk.Linear(64),\n",
" jax.nn.relu,\n",
" hk.Linear(64),\n",
" jax.nn.relu,\n",
" hk.Linear(1),\n",
" ]\n",
" )\n",
" assert x.ndim == 2\n",
" y = mlp(x)[:, 0]\n",
" assert y.shape == (x.shape[0],)\n",
" return y\n",
"\n",
"\n",
"def loss_fn(y_true, y_pred):\n",
" # Hinge loss.\n",
" return jnp.mean(jnp.maximum(0.0, 1.0 - y_true * y_pred))\n",
"\n",
"\n",
"def accuracy_fn(y_true, y_pred):\n",
" # Accuracy.\n",
" return jnp.mean(jnp.equal(y_true, jnp.sign(y_pred)))\n",
"\n",
"\n",
"def generate_data(rng, n, d):\n",
" # Generate random data.\n",
" x = jax.random.normal(rng, (n, d))\n",
" y = jnp.sign(x[:, 0])\n",
" return x, y\n",
"\n",
"\n",
"x_train, y_train = generate_data(jax.random.PRNGKey(0), 1024, 32)\n",
"w0 = model.init(jax.random.PRNGKey(1), x_train)\n",
"learning_rate = 0.05\n",
"n_epochs = 1024\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Training with GD.\n",
"@jax.jit\n",
"def update_fn(w, x, y):\n",
" def f(w, _):\n",
" loss, g = jax.value_and_grad(lambda w: loss_fn(y, model.apply(w, x)))(w)\n",
" w = jax.tree_util.tree_map(lambda w, g: w - learning_rate * g, w, g)\n",
" return w, loss\n",
"\n",
" return jax.lax.scan(f, w, None, length=n_epochs)\n",
"\n",
"\n",
"w_gd, loss_gd = update_fn(w0, x_train, y_train)\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# ODE Following the Lagrangian\n",
"# L = exp(2t / learning_rate) (learning_rate/4 ||dw/dt||^2 - Loss(w))\n",
"\n",
"\n",
"def f(t, Y, args):\n",
" w, dw = Y\n",
" g = jax.grad(lambda w: loss_fn(y_train, model.apply(w, x_train)))(w)\n",
" ddw = jax.tree_util.tree_map(lambda g, dw: -learning_rate / 2.0 * (g + dw), g, dw)\n",
" return (dw, ddw)\n",
"\n",
"\n",
"ts = learning_rate * np.arange(n_epochs)\n",
"solution = diffrax.diffeqsolve(\n",
" diffrax.ODETerm(f),\n",
" diffrax.Dopri5(),\n",
" t0=0,\n",
" t1=ts[-1],\n",
" dt0=learning_rate / 2.0,\n",
" y0=(w0, jax.tree_util.tree_map(jnp.zeros_like, w0)),\n",
" saveat=diffrax.SaveAt(ts=ts),\n",
")\n",
"loss_lagrangian = jax.vmap(lambda w: loss_fn(y_train, model.apply(w, x_train)))(\n",
" solution.ys[0]\n",
")\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0, 0.5, 'loss')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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v9K5c2c2bNhAhw4dTvj958yZUx2qfs/lchEZGck777zD0KFDAaPl5v777+eRRx4BjCDWqFEjvvrqKy666KKjvkZd7QqulpsGdn4H4y/kD1v2+deCfnUlMAhSboXb18K594K9kbFWzpuXwbvXGRt4ioh4mG+//ZYLLriAZs2aERYWxogRI9i/fz9FRUUAbNq0iT59+tR4ze8/B2jZsuVRwWbLli1cd911tGrVivDwcJKSkgBIT0+vcV23bt2qjxMSjGES2dnZJ/X+R8rKymLs2LG0bduWiIgIwsPDKSgoqPV9Q0NDCQ8Pr37f+qJdwRtY3+TGBNos/HawmF37i0iKOfHfCuQIQeFw/kToPcZoxVn5Cmz60tihvN9tcPYEY88rEfFugSFGC4pZ710Hdu7cydChQxk3bhz/+c9/iI6OZvHixdx0002UlZUREnLi7xMaevTPjGHDhtGyZUtmzJhB06ZNcblcdOnS5agBx4GBgdXHFosF4Kiuq5MxatQo9u/fzzPPPEPLli1xOBykpKTU+r5V730673siFG4aWKgjgJ4to1i2/QA/bNmncHO6GsXCxY9Bz9Ew917Y/h388BSsfQcu/D9jJeTKf8Qi4oUslpPqGvJEaWlpuFwunnrqKaxWo8Nk9uzZNa5p3749K1eurHHu958fy/79+9m0aRMzZsxgwIABACxevPikazyV91+yZAkvvPACgwcPBiAjI6O6m81sCjcmGNA2tjLc5DAiJcnscnxDkw7GOjmbvoS5E+HQLmONnJ9mwdCpxvYPIiL1LDc396gxKTExMZSXl/Pcc88xbNgwlixZwvTp02tcc9ttt3HOOecwdepUhg0bxoIFC/jqq6+qW1iOJyoqisaNG/Pyyy+TkJBAeno6995770nXfSrv37ZtW95880169epFXl4e//jHPwgODj7p964PGnNjggFtYwBYun0/LpfG3dQZiwU6DIHxK+D8+4y9q7bOg2lnwbLpWulYROrdwoULOeOMM2o83nzzTaZOncpjjz1Gly5dePvtt5kyZUqN1/Xv35/p06czdepUunfvzty5c7nrrruOGlT7e1arlVmzZpGWlkaXLl246667eOKJJ0667lN5/1dffZWDBw9y5plnMmLECG6//XaaNGly0u9dHzRbygQVThdd//0NxeVOvrnrHNrFhZlSh8/bt9mYMp5euZZD895w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PPNMAgICCAgIYNGiRTz77LMEBAQQFxen+1vHIiMjadeuHVu3bvWqv78KN6fJbrfTs2dP5s+fX33O5XIxf/58UlJSTKzMNyUnJxMfH1/jfufl5bF8+XLd7xPgdrv529/+xscff8yCBQtITk6u8XzPnj0JDAyscX83bdpEenq67u9pcLlclJaW6v6epgsuuID169ezdu3a6kevXr244YYbqo91f+tWQUEB27ZtIyEhwbv+/po9otkXzJo1y+1wONxvvPGG+9dff3XffPPN7sjISHdmZqbZpXml/Px895o1a9xr1qxxA+6pU6e616xZ4961a5fb7Xa7H330UXdkZKT7k08+ca9bt8596aWXupOTk93FxcUmV+75xo0b546IiHAvXLjQvXfv3upHUVFR9TW33HKLu0WLFu4FCxa4V61a5U5JSXGnpKSYWLV3uffee92LFi1y79ixw71u3Tr3vffe67ZYLO5vvvnG7Xbr/ta1I2dLud26v6fr73//u3vhwoXuHTt2uJcsWeJOTU11x8TEuLOzs91ut/fcX4WbOvLcc8+5W7Ro4bbb7e4+ffq4ly1bZnZJXuu7775zA0c9Ro0a5Xa7jengDzzwgDsuLs7tcDjcF1xwgXvTpk3mFu0ljnVfAffrr79efU1xcbH71ltvdUdFRblDQkLcl19+uXvv3r3mFe1l/vKXv7hbtmzpttvt7tjYWPcFF1xQHWzcbt3fuvb7cKP7e3qGDx/uTkhIcNvtdnezZs3cw4cPd2/durX6eW+5vxa32+02p81IREREpO5pzI2IiIj4FIUbERER8SkKNyIiIuJTFG5ERETEpyjciIiIiE9RuBERERGfonAjIiIiPkXhRkRERHyKwo2IiIj4FIUbEfEZ5513HnfeeafZZYiIyRRuRERExKdobykR8Qk33ngjM2fOrHFux44dJCUlmVOQiJhG4UZEfEJubi4XX3wxXbp04eGHHwYgNjYWm81mcmUi0tACzC5ARKQuREREYLfbCQkJIT4+3uxyRMREGnMjIiIiPkXhRkRERHyKwo2I+Ay73Y7T6TS7DBExmcKNiPiMpKQkli9fzs6dO8nJycHlcpldkoiYQOFGRHzG3Xffjc1mo1OnTsTGxpKenm52SSJiAk0FFxEREZ+ilhsRERHxKQo3IiIi4lMUbkRERMSnKNyIiIiIT1G4EREREZ+icCMiIiI+ReFGREREfIrCjYiIiPgUhRsRERHxKQo3IiIi4lMUbkRERMSn/D+v29dfHow+BwAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.plot(ts, loss_gd, label=\"GD\")\n",
"plt.plot(ts, loss_lagrangian, label=\"Lagrangian\")\n",
"\n",
"plt.legend()\n",
"plt.xlabel(\"t\")\n",
"plt.ylabel(\"loss\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.6 64-bit",
"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.10.6"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "f26faf9d33dc8b83cd077f62f5d9010e5bc51611e479f12b96223e2da63ba699"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment