From fe2279a550a18b2850d592e9f34b2412dd40e9e3 Mon Sep 17 00:00:00 2001 From: Siddharth Mishra-Sharma Date: Wed, 29 May 2024 23:07:39 -0400 Subject: [PATCH] remove old debugging notebooks --- CITATION.cff | 2 +- benchmarks/galaxies/datasets_debugging.ipynb | 507 -------- benchmarks/galaxies/galaxy_benchmark.ipynb | 544 -------- benchmarks/galaxies/nequip_debugging.ipynb | 754 ----------- benchmarks/galaxies/node_prediction.ipynb | 390 ------ .../galaxies/node_prediction_vperp.ipynb | 362 ------ benchmarks/galaxies/pooling_debugging.ipynb | 957 -------------- benchmarks/galaxies/segnn_debugging.ipynb | 1158 ----------------- 8 files changed, 1 insertion(+), 4673 deletions(-) delete mode 100644 benchmarks/galaxies/datasets_debugging.ipynb delete mode 100644 benchmarks/galaxies/galaxy_benchmark.ipynb delete mode 100644 benchmarks/galaxies/nequip_debugging.ipynb delete mode 100644 benchmarks/galaxies/node_prediction.ipynb delete mode 100644 benchmarks/galaxies/node_prediction_vperp.ipynb delete mode 100644 benchmarks/galaxies/pooling_debugging.ipynb delete mode 100644 benchmarks/galaxies/segnn_debugging.ipynb diff --git a/CITATION.cff b/CITATION.cff index 3f6a7c5..2aaa818 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,7 +5,7 @@ authors: given-names: "Julia" - family-names: "Mishra-Sharma" given-names: "Siddharth" -- family-names: "Cuesta-Lzaro" +- family-names: "Cuesta-Lazaro" given-names: "Carolina" title: "eqnn-jax" version: 0.1.0 diff --git a/benchmarks/galaxies/datasets_debugging.ipynb b/benchmarks/galaxies/datasets_debugging.ipynb deleted file mode 100644 index 1df6210..0000000 --- a/benchmarks/galaxies/datasets_debugging.ipynb +++ /dev/null @@ -1,507 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2024-05-15 15:20:24.112989: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:9261] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n", - "2024-05-15 15:20:24.113024: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:607] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n", - "2024-05-15 15:20:24.114266: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1515] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n" - ] - } - ], - "source": [ - "import sys\n", - "sys.path.append(\"../\")\n", - "\n", - "from benchmarks.galaxies.dataset_large import get_halo_dataset\n", - "from tqdm import tqdm\n", - "import numpy as np\n", - "\n", - "# Make sure tf does not hog all the GPU memory\n", - "import tensorflow as tf\n", - "\n", - "# Ensure TF does not see GPU and grab all GPU memory\n", - "tf.config.experimental.set_visible_devices([], \"GPU\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of samples: 2000\n" - ] - } - ], - "source": [ - "features = ['x', 'y', 'z'] # ['x', 'y', 'z', 'Jx', 'Jy', 'Jz', 'vx', 'vy', 'vz', 'M200c']\n", - "params = ['Omega_m', 'sigma_8'] # ['Omega_m', 'Omega_b', 'h', 'n_s', 'sigma_8']\n", - "batch_size = 64\n", - "\n", - "dataset, num_total = get_halo_dataset(batch_size=batch_size, # Batch size\n", - " num_samples=2000, # If not None, will only take a subset of the dataset\n", - " split='train', # 'train', 'val'\n", - " standardize=False, # If True, will standardize the features\n", - " return_mean_std=False, # If True, will return (dataset, num_total, mean, std, mean_params, std_params), else (dataset, num_total)\n", - " seed=42, # Random seed\n", - " features=features, # Features to include\n", - " params=params # Parameters to include\n", - " )\n", - "\n", - "# Print number of samples\n", - "print(f\"Number of samples: {num_total}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/31 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Plot for the two parameters side by side\n", - "\n", - "import matplotlib.pyplot as plt\n", - "\n", - "fig, axs = plt.subplots(1, 2, figsize=(15, 5))\n", - "\n", - "out = model.apply(unreplicate(pstate).params, tpcf_val)\n", - "\n", - "\n", - "axs[0].scatter(params_val[:, 0], out[:, 0])\n", - "axs[0].plot(params_val[:, 0], params_val[:, 0], color='black')\n", - "axs[0].set_title(\"Omega_m\")\n", - "\n", - "axs[1].scatter(params_val[:, 1], out[:, 1])\n", - "axs[1].plot(params_val[:, 1], params_val[:, 1], color='black')\n", - "axs[1].set_title(\"sigma_8\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "equivariant", - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/benchmarks/galaxies/galaxy_benchmark.ipynb b/benchmarks/galaxies/galaxy_benchmark.ipynb deleted file mode 100644 index 10e5889..0000000 --- a/benchmarks/galaxies/galaxy_benchmark.ipynb +++ /dev/null @@ -1,544 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "d4bb58c1-7527-4f64-ab7e-c98f90e6b4b3", - "metadata": {}, - "source": [ - "# GNN" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1b190a07-a112-4322-be03-d723e71cc754", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-04-01 11:34:00.648304: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - " 47%|▍| 2365/5000 [05:40<05:31, 7.94it/s, loss: 0.00299, val_loss: 0.00358, ckp_test_loss: 0.00303]" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos" - ] - }, - { - "cell_type": "markdown", - "id": "5df2e90e-b956-4709-9885-79997e5a646d", - "metadata": {}, - "source": [ - "## With 2PCF" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "447f74a8-d41f-41d2-9cde-3b82059a91a4", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-04-01 12:29:06.557448: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - " 55%|▌| 2748/5000 [06:39<04:49, 7.77it/s, loss: 0.00296, val_loss: 0.00230, ckp_test_loss: 0.00230]" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --use_tpcf 'all'" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b391319d-a083-4115-994d-d6a63bafd275", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-14 09:37:53.987366: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - "100%|█| 5000/5000 [11:31<00:00, 7.23it/s, loss: 0.00310, val_loss: 0.00234, ckp_test_loss: 0.00230]\n", - "Training done.\n", - "Final test loss 0.002384 - Checkpoint test loss 0.002301.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --use_tpcf 'small'" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "fa611684-489b-4889-a394-bae5415a75b9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-14 09:51:59.265201: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - "100%|█| 5000/5000 [11:33<00:00, 7.21it/s, loss: 0.00381, val_loss: 0.00279, ckp_test_loss: 0.00272]\n", - "Training done.\n", - "Final test loss 0.002675 - Checkpoint test loss 0.002717.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --use_tpcf 'large' " - ] - }, - { - "cell_type": "markdown", - "id": "0603287b-742c-4fcd-84e7-473f32806716", - "metadata": {}, - "source": [ - "## With RBF" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "72070bab-58dc-4156-85bb-2c6574a06612", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-14 09:10:48.224943: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "1.554175e-08\n", - "Training...\n", - " 0%| | 0/5000 [00:00with\n", - "Tracedwith\n", - "100%|█| 5000/5000 [11:04<00:00, 7.52it/s, loss: 0.00408, val_loss: 0.00284, ckp_test_loss: 0.00278]\n", - "Training done.\n", - "Final test loss 0.002756 - Checkpoint test loss 0.002784.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --use_rbf True" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "e7375296-15ac-4d33-976f-d3d37aa5aecb", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-19 14:20:23.737045: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - "100%|█| 5000/5000 [11:03<00:00, 7.54it/s, loss: 0.00408, val_loss: 0.00284, ckp_test_loss: 0.00278]\n", - "Training done.\n", - "Final test loss 0.002756 - Checkpoint test loss 0.002784.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --use_rbf True" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "39d08ba0-1a82-4e17-bd82-f515ebe6b50f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-14 10:14:39.974390: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - "100%|█| 5000/5000 [11:38<00:00, 7.16it/s, loss: 0.00310, val_loss: 0.00234, ckp_test_loss: 0.00230]\n", - "Training done.\n", - "Final test loss 0.002384 - Checkpoint test loss 0.002300.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --use_tpcf 'small' --use_rbf True" - ] - }, - { - "cell_type": "markdown", - "id": "65279497-f0f4-4114-a6f4-22b5cc0092ee", - "metadata": {}, - "source": [ - "## Does this problem exist with different k?" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "17eb45c1-8413-4819-8bc4-6e2f6053bc72", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-21 11:16:36.219405: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - " 94%|▉| 4725/5000 [10:24<00:34, 7.98it/s, loss: 0.00255, val_loss: 0.00299, ckp_test_loss: 0.00274]^C\n", - " 94%|▉| 4725/5000 [10:24<00:36, 7.56it/s, loss: 0.00255, val_loss: 0.00299, ckp_test_loss: 0.00274]\n", - "Traceback (most recent call last):\n", - " File \"/n/holystore01/LABS/iaifi_lab/Users/jballa/eqnn-jax/benchmarks/galaxies/train.py\", line 406, in \n", - " main(**vars(args))\n", - " File \"/n/holystore01/LABS/iaifi_lab/Users/jballa/eqnn-jax/benchmarks/galaxies/train.py\", line 380, in main\n", - " run_expt(model, \n", - " ^^^^^^^^^^^^^^^\n", - " File \"/n/holystore01/LABS/iaifi_lab/Users/jballa/eqnn-jax/benchmarks/galaxies/train.py\", line 335, in run_expt\n", - " steps.set_postfix_str('loss: {:.5f}, val_loss: {:.5f}, ckp_test_loss: {:.5F}'.format(train_loss,\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/array.py\", line 297, in __format__\n", - " return format(self._value[()], format_spec)\n", - " ^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/profiler.py\", line 340, in wrapper\n", - " return func(*args, **kwargs)\n", - " ^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/array.py\", line 566, in _value\n", - " self._npy_value = self._single_device_array_to_np_array() # type: ignore\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - "KeyboardInterrupt\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --k 10" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ad02e46f-5462-423a-bba4-57f912c025a1", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-21 11:28:41.413891: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - "100%|█| 5000/5000 [11:08<00:00, 7.48it/s, loss: 0.00313, val_loss: 0.00236, ckp_test_loss: 0.00230]\n", - "Training done.\n", - "Final test loss 0.002413 - Checkpoint test loss 0.002302.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --k 10 --use_tpcf 'small'" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "0fea88be-6e32-4758-bff5-4a7585856682", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-21 11:46:16.172455: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - "100%|█| 5000/5000 [12:34<00:00, 6.63it/s, loss: 0.00411, val_loss: 0.00308, ckp_test_loss: 0.00304]\n", - "Training done.\n", - "Final test loss 0.003074 - Checkpoint test loss 0.003036.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --k 40" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "ce74a396-945d-4b9f-a9da-5f2d1b3eb54a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-21 12:06:05.360684: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "Training...\n", - "100%|█| 5000/5000 [12:44<00:00, 6.54it/s, loss: 0.00309, val_loss: 0.00234, ckp_test_loss: 0.00230]\n", - "Training done.\n", - "Final test loss 0.002383 - Checkpoint test loss 0.002303.\n", - "\n" - ] - } - ], - "source": [ - "! python3 train.py --model GNN --feats pos --k 40 --use_tpcf 'small'" - ] - }, - { - "cell_type": "markdown", - "id": "a52a752f-1ff4-4c69-8c10-7879badda386", - "metadata": {}, - "source": [ - "# DiffPool" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "771215f3-3b41-40b2-9d11-a1ebfa26e5d9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-19 15:37:01.883540: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/numpy/lax_numpy.py:3835: UserWarning: 'kind' argument to argsort is ignored; only 'stable' sorts are supported.\n", - " warnings.warn(\"'kind' argument to argsort is ignored; only 'stable' sorts \"\n", - "Training...\n", - " 0%| | 0/5000 [00:00\n", - " main(**vars(args))\n", - " File \"/n/holystore01/LABS/iaifi_lab/Users/jballa/eqnn-jax/benchmarks/galaxies/train.py\", line 380, in main\n", - " run_expt(model, \n", - " ^^^^^^^^^^^^^^^\n", - " File \"/n/holystore01/LABS/iaifi_lab/Users/jballa/eqnn-jax/benchmarks/galaxies/train.py\", line 335, in run_expt\n", - " steps.set_postfix_str('loss: {:.5f}, val_loss: {:.5f}, ckp_test_loss: {:.5F}'.format(train_loss,\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/array.py\", line 297, in __format__\n", - " return format(self._value[()], format_spec)\n", - " ^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/profiler.py\", line 340, in wrapper\n", - " return func(*args, **kwargs)\n", - " ^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/array.py\", line 566, in _value\n", - " self._npy_value = self._single_device_array_to_np_array() # type: ignore\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - "KeyboardInterrupt\n" - ] - } - ], - "source": [ - "! python3 train.py --model DiffPool --feats pos # \"d_downsampling_factor\": 2" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ccb8d563-a79c-4656-8efd-7ad95947285e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2024-03-19 15:28:54.731756: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n", - "Loading dataset...\n", - "/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/numpy/lax_numpy.py:3835: UserWarning: 'kind' argument to argsort is ignored; only 'stable' sorts are supported.\n", - " warnings.warn(\"'kind' argument to argsort is ignored; only 'stable' sorts \"\n", - "Training...\n", - " 0%| | 0/5000 [00:00\n", - " \n", - " ^\n", - " File \"/n/holystore01/LABS/iaifi_lab/Users/jballa/eqnn-jax/benchmarks/galaxies/train.py\", line 380, in main\n", - " \n", - "\n", - " File \"/n/holystore01/LABS/iaifi_lab/Users/jballa/eqnn-jax/benchmarks/galaxies/train.py\", line 335, in run_expt\n", - " \n", - "\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/array.py\", line 297, in __format__\n", - " return format(self._value[()], format_spec)\n", - " ^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/profiler.py\", line 340, in wrapper\n", - " return func(*args, **kwargs)\n", - " ^^^^^^^^^^^^^^^^^^^^^\n", - " File \"/n/home07/jballa/.conda/envs/jupyter_py3.11/lib/python3.11/site-packages/jax/_src/array.py\", line 566, in _value\n", - " self._npy_value = self._single_device_array_to_np_array() # type: ignore\n", - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - "KeyboardInterrupt\n" - ] - } - ], - "source": [ - "! python3 train.py --model DiffPool --feats pos # \"d_downsampling_factor\": 10, num_downsamples: 2" - ] - }, - { - "cell_type": "markdown", - "id": "9e12e2b8-869a-4685-b90d-ea8c67c384c4", - "metadata": { - "tags": [] - }, - "source": [ - "# SEGNN" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "5d049e98-de43-429b-bd71-298cd487a527", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "^C\n" - ] - } - ], - "source": [ - "! python3 train.py --model SEGNN --feats pos --steps 1000 " - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "93a563c8-42c9-4bc3-98d4-ef4c6d28597d", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "losses = np.load('experiments/GNN_pos_32_10000_64_20_all/train_losses.npy')\n", - "val_losses = np.load('experiments/GNN_pos_32_10000_64_20_all/val_losses.npy')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "ca7f0cda-c564-42c3-8697-834dd27a1d40", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGwCAYAAABB4NqyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAABAXElEQVR4nO3deXxU1cH/8e9MlklCVghkgUBYIsi+SQxqsQ/RYN1QVKBUhPLTatXCQ9VKFVCpskgtVSlUWwWfuiCtonWBYhRFQJBVNhGUPRtb9j1zfn9QBgYSCDEzd2A+79drXszce+bMuSch+ebcc+61GWOMAAAA/Ijd6gYAAAB4GwEIAAD4HQIQAADwOwQgAADgdwhAAADA7xCAAACA3yEAAQAAvxNodQN8kdPpVFZWliIiImSz2axuDgAAqAdjjIqKipSYmCi7/exjPASgWmRlZSkpKcnqZgAAgAbYv3+/WrVqddYyBKBaRERESDregZGRkRa3BgAA1EdhYaGSkpJcv8fPhgBUixOnvSIjIwlAAABcYOozfYVJ0AAAwO8QgAAAgN8hAAEAAL/DHCAAALzE6XSqsrLS6mZcsIKCghQQENAodRGAAADwgsrKSu3evVtOp9PqplzQoqOjFR8f/6Ov00cAAgDAw4wxys7OVkBAgJKSks55kT6cyRij0tJS5eXlSZISEhJ+VH0EIAAAPKy6ulqlpaVKTExUWFiY1c25YIWGhkqS8vLy1KJFix91OowICgCAh9XU1EiSgoODLW7Jhe9EgKyqqvpR9RCAAADwEu4v+eM1Vh8SgAAAgN8hAAEAAL9DAAIAAF6TnJysWbNmWd0MApA3FZZX6cCxUh0t4SJYAADfZrPZzvp44oknGlTv119/rXvuuadxG9sALIP3on98tVczFu/QHX1bacZtPaxuDgAAdcrOznY9X7BggSZNmqQdO3a4toWHh7ueG2NUU1OjwMBzx4rmzZs3bkMbiBEgAAC8zBij0spqSx7GmHq1MT4+3vWIioqSzWZzvf72228VERGhjz/+WH369JHD4dCXX36p77//XjfffLPi4uIUHh6uyy67TJ988olbvaefArPZbPrb3/6mW265RWFhYUpJSdH777/fmN1dK0aAAADwsrKqGnWetMSSz972VIbCghvn1/+jjz6qmTNnql27doqJidH+/fv1s5/9TE8//bQcDodee+013XjjjdqxY4dat25dZz1PPvmkZsyYoWeffVYvvPCCRowYob1796pp06aN0s7aMAIEAAAa5KmnntI111yj9u3bq2nTpurRo4d+9atfqWvXrkpJSdGUKVPUvn37c47ojBo1SsOHD1eHDh30zDPPqLi4WGvWrPFo2xkBAgDAy0KDArTtqQzLPrux9O3b1+11cXGxnnjiCX344YfKzs5WdXW1ysrKtG/fvrPW0717d9fzJk2aKDIy0nXPL08hAAEA4GU2m63RTkNZqUmTJm6vH3roIS1dulQzZ85Uhw4dFBoaqttuu02VlWdf/RwUFOT22mazyel0Nnp7T3Xh9/4FqJ7zzwAAuKCsWLFCo0aN0i233CLp+IjQnj17rG1UHXxiDtDs2bOVnJyskJAQpaamnvW838svv6yrrrpKMTExiomJUXp6+hnljTGaNGmSEhISFBoaqvT0dO3cudPTh3FONnEPGADAxSslJUXvvPOONm7cqE2bNunnP/+5x0dyGsryALRgwQKNHz9ekydP1vr169WjRw9lZGTUee5v2bJlGj58uD777DOtWrVKSUlJuvbaa3Xw4EFXmRkzZuj555/X3LlztXr1ajVp0kQZGRkqLy/31mEBAOB3nnvuOcXExKh///668cYblZGRod69e1vdrFrZTH0vCOAhqampuuyyy/Tiiy9KkpxOp5KSkvTggw/q0UcfPef7a2pqFBMToxdffFEjR46UMUaJiYn67W9/q4ceekiSVFBQoLi4OM2bN0/Dhg07Z52FhYWKiopSQUGBIiMjf9wBnmLOsu81ffG3ur1PKz17OxdCBAB/UV5ert27d6tt27YKCQmxujkXtLP15fn8/rZ0BKiyslLr1q1Tenq6a5vdbld6erpWrVpVrzpKS0tVVVXlulbA7t27lZOT41ZnVFSUUlNT66yzoqJChYWFbg8AAHDxsjQAHT58WDU1NYqLi3PbHhcXp5ycnHrV8bvf/U6JiYmuwHPifedT59SpUxUVFeV6JCUlne+hAACAC4jlc4B+jGnTpumtt97Su++++6OGFCdMmKCCggLXY//+/Y3YSgAA4GssXQYfGxurgIAA5ebmum3Pzc1VfHz8Wd87c+ZMTZs2TZ988onbBZROvC83N1cJCQludfbs2bPWuhwOhxwORwOP4vyxCh4AAGtZOgIUHBysPn36KDMz07XN6XQq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AAD4nQYFoP379+vAgQOu12vWrNG4ceP00ksvNVrDAAAAPKVBAejnP/+5PvvsM0lSTk6OrrnmGq1Zs0aPPfaYnnrqqUZt4EWFs1sAAPiEBgWgLVu2qF+/fpKkt99+W127dtXKlSv1+uuva968eY3ZPgAAgEbXoABUVVUlh8MhSfrkk0900003SZI6deqk7OzsxmvdRcrU526o3DEVAACPaVAA6tKli+bOnavly5dr6dKlGjRokCQpKytLzZo1a9QGAgAANLYGBaDp06frr3/9q66++moNHz5cPXr0kCS9//77rlNjaCDuBg8AgMcFNuRNV199tQ4fPqzCwkLFxMS4tt9zzz0KCwtrtMYBAAB4QoNGgMrKylRRUeEKP3v37tWsWbO0Y8cOtWjRolEbCAAA0NgaFIBuvvlmvfbaa5Kk/Px8paam6o9//KMGDx6sOXPmNGoDLyac3AIAwDc0KACtX79eV111lSTpn//8p+Li4rR371699tprev755xu1gQAAAI2tQQGotLRUERERkqT//Oc/uvXWW2W323X55Zdr7969jdrAixF3gwcAwFoNCkAdOnTQokWLtH//fi1ZskTXXnutJCkvL0+RkZGN2kAAAIDG1qAANGnSJD300ENKTk5Wv379lJaWJun4aFCvXr0atYH+h5lCAAB4WoMC0G233aZ9+/Zp7dq1WrJkiWv7wIED9ac//em86po9e7aSk5MVEhKi1NRUrVmzps6yW7du1ZAhQ5ScnCybzaZZs2b96DoBAID/aVAAkqT4+Hj16tVLWVlZrjvD9+vXT506dap3HQsWLND48eM1efJkrV+/Xj169FBGRoby8vJqLV9aWqp27dpp2rRpio+Pb5Q6AQCA/2lQAHI6nXrqqacUFRWlNm3aqE2bNoqOjtaUKVPkdDrrXc9zzz2nu+++W6NHj1bnzp01d+5chYWF6ZVXXqm1/GWXXaZnn31Ww4YNc92L7MfWKUkVFRUqLCx0e3iCjas8AwDgExoUgB577DG9+OKLmjZtmjZs2KANGzbomWee0QsvvKCJEyfWq47KykqtW7dO6enpJxtjtys9PV2rVq1qSLMaXOfUqVMVFRXleiQlJTXo8wEAwIWhQbfCmD9/vv72t7+57gIvSd27d1fLli3161//Wk8//fQ56zh8+LBqamoUFxfntj0uLk7ffvttQ5rV4DonTJig8ePHu14XFhZ6NATV60bv3A0eAACPaVAAOnr0aK1zfTp16qSjR4/+6EZ5m8PhqPOUGgAAuPg06BRYjx499OKLL56x/cUXX1T37t3rVUdsbKwCAgKUm5vrtj03N7fOCc5W1Ol1zBMCAMDjGhSAZsyYoVdeeUWdO3fWmDFjNGbMGHXu3Fnz5s3TzJkz61VHcHCw+vTpo8zMTNc2p9OpzMxM13WFzpcn6gQAABefBgWgAQMG6LvvvtMtt9yi/Px85efn69Zbb9XWrVv1f//3f/WuZ/z48Xr55Zc1f/58bd++Xffdd59KSko0evRoSdLIkSM1YcIEV/nKykpt3LhRGzduVGVlpQ4ePKiNGzdq165d9a7TSoztAADgGxo0B0iSEhMTz5jsvGnTJv3973/XSy+9VK86hg4dqkOHDmnSpEnKyclRz549tXjxYtck5n379sluP5nRsrKy3K40PXPmTM2cOVMDBgzQsmXL6lUnAABAgwNQY3nggQf0wAMP1LrvRKg5ITk5WaYeq6POVqcvYH0XAADWavCVoOFpxCQAADyFAAQAAPzOeZ0Cu/XWW8+6Pz8//8e0BZKYKg0AgOedVwCKioo65/6RI0f+qAYBAAB42nkFoFdffdVT7fALXOMQAADfwBwgAADgdwhAFqjPUn5uhgoAgOcQgAAAgN8hAPkaJgoBAOBxBCAAAOB3CEAAAMDvEIC8iLNbAAD4BgIQAADwOwQgn8UyeAAAPIUABAAA/A4ByOcwUQgAAE8jAAEAAL9DAAIAAH6HAORFNk5vAQDgEwhAAADA7xCALFCvG71zN3gAADyGAAQAAPwOAcjXcL8MAAA8jgAEAAD8DgEIAAD4HQKQF3F2CwAA30AAsoDhRqcAAFiKAOSzCEkAAHgKAQgAAPgdApDPYaIQAACeRgACAAB+hwAEAAD8DgEIAAD4HQKQBbjPKQAA1iIA+SpSEgAAHkMAAgAAfocA5Gu4XwYAAB5HAAIAAH6HAAQAAPwOAciLbJzeAgDAJxCALMACLwAArEUA8lmkJAAAPIUABAAA/A4ByOcwTwgAAE8jAAEAAL9DAAIAAH6HAORFJ05uGSY4AwBgKQIQAADwOwQgX8XFggAA8BgCEAAA8DsEIF/D7TIAAPA4AhAAAPA7BCAvYnAHAADfQACyAPObAQCwFgEIAAD4HQKQz2KYCAAATyEAAQAAv0MAAgAAfocABAAA/A4ByItsYh08AAC+gABkAaY3AwBgLQKQr+JiQQAAeAwBCAAA+B0CEAAA8DsEIF/DDcMAAPA4AhAAAPA7BCAvYnAHAADfQACyAgu8AACwFAHIZ5GSAADwFAIQAADwOz4RgGbPnq3k5GSFhIQoNTVVa9asOWv5hQsXqlOnTgoJCVG3bt300Ucfue0fNWqUbDab22PQoEGePIRGxEQhAAA8zfIAtGDBAo0fP16TJ0/W+vXr1aNHD2VkZCgvL6/W8itXrtTw4cM1ZswYbdiwQYMHD9bgwYO1ZcsWt3KDBg1Sdna26/Hmm29643AAAMAFwPIA9Nxzz+nuu+/W6NGj1blzZ82dO1dhYWF65ZVXai3/5z//WYMGDdLDDz+sSy+9VFOmTFHv3r314osvupVzOByKj493PWJiYrxxOAAA4AJgaQCqrKzUunXrlJ6e7tpmt9uVnp6uVatW1fqeVatWuZWXpIyMjDPKL1u2TC1atFDHjh1133336ciRI3W2o6KiQoWFhW4PTzhxcsswwRkAAEtZGoAOHz6smpoaxcXFuW2Pi4tTTk5Ore/Jyck5Z/lBgwbptddeU2ZmpqZPn67PP/9c1113nWpqamqtc+rUqYqKinI9kpKSfuSRAQAAXxZodQM8YdiwYa7n3bp1U/fu3dW+fXstW7ZMAwcOPKP8hAkTNH78eNfrwsJC60MQd4MHAMBjLB0Bio2NVUBAgHJzc9225+bmKj4+vtb3xMfHn1d5SWrXrp1iY2O1a9euWvc7HA5FRka6PQAAwMXL0gAUHBysPn36KDMz07XN6XQqMzNTaWlptb4nLS3NrbwkLV26tM7yknTgwAEdOXJECQkJjdNwT+J+GQAAeJzlq8DGjx+vl19+WfPnz9f27dt13333qaSkRKNHj5YkjRw5UhMmTHCVHzt2rBYvXqw//vGP+vbbb/XEE09o7dq1euCBByRJxcXFevjhh/XVV19pz549yszM1M0336wOHTooIyPDkmMEAAC+xfI5QEOHDtWhQ4c0adIk5eTkqGfPnlq8eLFrovO+fftkt5/Maf3799cbb7yhxx9/XL///e+VkpKiRYsWqWvXrpKkgIAAffPNN5o/f77y8/OVmJioa6+9VlOmTJHD4bDkGAEAgG+xPABJ0gMPPOAawTndsmXLzth2++236/bbb6+1fGhoqJYsWdKYzWs0J85uMb8ZAABrWX4KDAAAwNsIQAAAwO8QgAAAgN8hAPkclsEDAOBpBCAAAOB3CEAAAMDvEIC86vjpLVbBAwBgLQIQAADwOwQgX8XVEgEA8BgCEAAA8DsEIF/D3eABAPA4AhAAAPA7BCAAAOB3CEBedPJu8ExwBgDASgQgC2w6UGB1EwAA8GsEIC/KKSiXJNU46zMCxCgRAACeQgDyoqyCMqubAAAARADyQSyDBwDA0whAXmQj3AAA4BMIQF7ENQ4BAPANBCAvIv8AAOAbCEAW4VpAAABYhwDkRaeeAjtn/iEgAQDgMQQgixBvAACwDgHIInWeAmOmNAAAHkcAski9LgYNAAA8ggDkRfZTRncMJ8EAALAMAciLTj25xRxnAACsQwACAAB+hwDkTaecAnOeex28Z9sCAIAfIwBZhFNgAABYhwBkkbrzD8vgAQDwNAKQF50abc59CgwAAHgKAciLzutWGAAAwGMIQF5kO3UMiAAEAIBlCEBedOoI0DlPgTFEBACAxxCALEK8AQDAOgQgi9R5M1QAAOBxBCAvOjXz1HkzVO4GDwCAxxGALMLNUAEAsA4ByItODT2cAQMAwDoEIIsQgAAAsA4ByItODT3nPgVGQgIAwFMIQF50aqSpcxI0AADwOAKQN5lT5wDVuQzMO20BAMCPEYC86NTIwxwgAACsQwCyCAEIAADrEIC86PwmQQMAAE8hAHkR1wECAMA3EIAswt3gAQCwDgHIi9xPgQEAAKsQgLyoXqvAuBkqAAAeRwDyIrcRIE5xAQBgGQKQF506uEP8AQDAOgQgL2oVE+p6zgAQAADWIQB50dC+Sa7n51wFBgAAPIYA5EWBAXY1j3BIqs8IEAEJAABPIQB5mf2/84C4EjQAANYhAHlZbmGFJGn93mN1lGAZPAAAnkYAssjE97Za3QQAAPwWAQgAAPgdAhAAAPA7BCAAAOB3CEC+iusEAQDgMQQgAADgdwhAFtp/tPTMjdwNHgAAjyMAWejDzdk/6v01TqPHF23WexsP1qt8aWW1apycWgMAgABkoWkff6tPtuVqW1ahsgvKJEkV1TX1fv+/N2XpH1/t09i3NtZZJq+wXE6n0bGSSnWetES3/mXFj222m4cWblL6c5+rstrZqPWeL2OOH+Ppvt5zVBPe2ayC0qpa31deVaP80jPfV19VNdYed32VVdbonfUHdLSWPrrQGQ/Ml3PyhwJw0Qu0ugH+5jcDU/R85k7X6//32lrX84czOmrX0s36U7D0+XeHdNejH2r6kG6KCAnSsdJKvbpij3blFUuSZv+8tya9t8X13hW7DqtrYpQ+2JwlR2CAOsZFaNHGg/r7l7vVNraJhvc7fiPWTQcK9MOhYrVrHu7Wrvkr9+i9jQe18N7+6vbEEpVW1uidX/dXsybB2pVXrCf/vU2tYkKVEBWqIyUVenXUZcovrdI/1x2QJP058zs9nNFJu/KKtOdwqS5v30zhjuPfXsdKKhUREqjAALuMMTqYX6YWESHqPWWpiiuq9e2UQQoJCnBrT2F5lb76/ogGdGyu4AC78ooqlF9apeTYMEnS/a9v0NUdm+uWXi21cX++/rT0O63979W1tz81SJ9sz9WDb25w1Xe4uEJ3pSWrV+toNXGc/La/7OlPVFRerZ92bK4H/idFfdrEuLXD6TSy22s/Lfnx5mzd9/p6dYqP0Gtj+qlFRIgkae2eo5qxZIdCggL0xXeH9MGDV6pryyh9veeobp+7SolRIXp4UEdd0zle4Y5AlVfVKCjArgC7TYeLK9SsSbBsNpuMMTpUVKEWkcfrrapx6nBxhcKCAhUVFuTWluoap5xGCg60q6K6Ro5A9/6c+vF2vbZqry5NiNTHY6/Sy1/8oKc/2q51j6erWbjDrWx5VY3b16O8qkbr9x5T3+SmCg6063BxhRyBdkWEnGxDjdNoW1ahLk2IUGDA+f1dtWRrjorLqzWkT6vzep8kFZVXqdsT/1FQgE07n/6Z27780kqt3XNMP7mkuYIDT7apstqpz3bk6ScpzRUa7N5P27IK9XzmTi3feUgzbuuh67snaGtWgSSpS2JUrW0wxsh2yqlrY4yMkdv3zY6cIn36bZ66tYzSpPe2aPJNXTTgkubnfbzeVlZZo8AAm4LO82t6KmOM3t1wUB3jI+rsQ8AKNuOJP58ucIWFhYqKilJBQYEiIyMbte6Fa/fr4X9+U+f+W+zL9afgOfq8prvuqnq0UT/b237WLV4fbc6xuhm1uiolVnuPlGrfafOwNk2+Vh98k6Vnl+xQ/mmjRrHhDh0uPn4rk2+euFbdn/iP2/5hlyXpra/31/p5zSMcOlRUccb2ub/orXv/sf6M7cEBdtlsUkUdI2s7n75Ov39ns3YdKtaGffln7L+ua7weva6T2jRroi0HC3TDC1+69m15MkNdJy9xvQ6w27TsoavVLDxYP5mxTIeLK9QzKVr3/7SD7j4loJ/u0es6acAlzRXuCNRVMz47Y39oUIASo0P0k0uaKyQoQMZIPxwq1n+25erqjs11Xdd4bdyfrzfXHO+zNs3CNKhLvA7kl+nDb7J1/0/ba9P+Ah0qqlBqu6bKL61SjdPof69J0fq9+Xpp+Q+uPwgk6YXhvdS1ZZQefHO9+rZpqnkr97j2dYyL0Bt3p+qtr/fr2SU7XNunD+mmDzfn6JGMjuqSGKm2Ez5yO4a7r2qrl5fvliR98OCVuuuVNUpr30zPD+slu92m3MJyXf/8l7q9byv9blAnVyiWpO+f+Zl25RXrcHGFRvxt9Rn9M2NId20+WKBBXePlNEZNHIGqrjH65kC+ruuWoMSoENlsNjmdRk99sE1tmoVp88ECVVQ5NWVwV0WFBumHQ8Xac6RUO/OK9JOU5npu6XcqLKvS2PQUtYoJU9vYJm6feXq4lY4HlPc3ZSkrv1zpl7ZQSlyEpJPhsm1sEz1xUxd1jItQfFSI1uw+qi++O6QHB3Y4I2jX5vXVe/XYu8f/WFvz2EAF2u2KCg3SpgP56pwQqfKqGkWHBZ+znrOpcRoF2G3auD9fJRXVuqJDrNvx2c4yt9IYo/Iq5xlh+FQlFdUKCw6Q0xz//1IvlSVSzTlGXANDpaCQ+tUnqaC0SpGhga7jKa2s1g+HSpQUEyZHkP2Mr61HFGYfP7Y6GBnZgsKkqJZn7jNGNU5z3n8knVfzzuP3NwGoFp4MQKf/MjrdiQCUY2K0vKZbrWXCbOXqYturmnqcwVzt7KTlzu4ysv339qvH/z3++sznqmP7iec68dycul1yyq4yOWppwUk1sivXxLh9ik2S3e1TTu47sf34//WT27rZdivUdmaYON1BE6tDJrrO/c1shYpWsdtn2U85Ktc2mzmtvU63dkrSV85Ltd+0qPOzrrGvU3tblpz/fdeJGpz/fZy+zZzy7/Hnx1tWI7u2ONtq31k+q7UtT4m2I2ftmyiVKMpW9w+xE/JNE+0x8Wcts8/EqVIBbn3j+tqd/rWUkc1mzujzNPs2tbHlnrM9e02cvnB2c+t/9+envz7ZphNf12sC1qudLeuULad+9+mUr+p/9/33J+SZ/x+Of99vcKa4tbG2H6gn6q7rdW3vO71MqUJUorp/WQ62r1B3+w91tOCkINVohbOLKlR76LDbpBLj0GETKSObqzcknfZc+nm/JH3wTbaqnUZlldV1lqtt++ntPFGuQ4smyi+tVPqlccdHjm02ZeWX6d/fZKl5RLAOF1WqVUyo8grLXaegg1StaFuJAlTj+pzQ4ACVVda46u4UH6GqGqfyy6p0tLjilM892Y6gALtSWoRr16Ei/bRjC+07UiJHoF3fHChwa3OPVtGKDgtSsybB2n+0VIXlVUqIcuiL7w6rR6toNc/5XLGq636P7o4GxSu7JlJhQXYVllWqeXiwEiODVWOMbOb4d1l1jVP7DhfLGCO7nAoLDlB5ZZXrez3IVq0Nzg76n8sv04Fjpdq4L19xkQ7tyC2W0xilJ1YpunS3IkIcKq+u0bHSSoU7AhUZEqSSymrX93i4I1BllTUKcwQo8L9Br7zKqbyiCjVtEqwmhT/IVlNer+OSJBPVWhXVTgUH2mW3SfuPHp/qERvhkCPQLnu//yddMbbe9dXHBReAZs+erWeffVY5OTnq0aOHXnjhBfXr16/O8gsXLtTEiRO1Z88epaSkaPr06frZz04OfxtjNHnyZL388svKz8/XFVdcoTlz5iglJaXOOk/lyQAkSe0mfKi6phj81L5BrwY/2+ifCQBAYyk0YbVuj7TVsrq5DuWXj1XIoKcaq0mSzu/3t+VzgBYsWKDx48dr7ty5Sk1N1axZs5SRkaEdO3aoRYsz/8pduXKlhg8frqlTp+qGG27QG2+8ocGDB2v9+vXq2rWrJGnGjBl6/vnnNX/+fLVt21YTJ05URkaGtm3bppCQ+g83esoPU6/X4i3ZtZ76+MLZXeMr71VzW0Et7zzJJqPdJkFHTUSt+yNspbo38N+uvyLr+uu4tpGXk8/Ptf/k38lBqlGwrfaJxsfLSDEqUpCt9kneTrcRJdspYyzu2048L1SYvnUm1VpXoJzqYf/e9Xd/XZyy65CJVpFCXaNazlP+sj9Rxpzy76ljRE7ZFKpKXR2w6ayfc6rXqwe6js59hOnENvd/T4z92HT8r9yBARvOWv+p1js7nHX/UROhYoXWub+bbbcCdfZJ+bG2AjWpYzTuxNfU6XY0Z34tT/SnXUZv1PyPVMfX7c6A/8gmuX1PnPgOdJ5W18nn9lq2HR/VeLn6+v+++8zvc8n9/0BtZS6171WYKs5orfsoR93b6lJb2WBbtaJUcs56nLJrWvVwVan2UyHtbVlKtB056/+MUJWrma3wvz13nPu4jfuYjtz21V7O/XldddVdTnXUJZ28Zmy5gnVM4afsr7ttx993ljrr2caztbNATfTPmp+ouo6vRZCqdbl9m4JUU8v/iZP/d9x+HpkTr0+Wi7YVK82+7ZxnBAJVo3XOS846iljb8Z2uxIRog+kgU+fnGXWwHVS4zj1SVLa6uZYMOmcxj7F8BCg1NVWXXXaZXnzxRUmS0+lUUlKSHnzwQT366JlzYIYOHaqSkhJ98MEHrm2XX365evbsqblz58oYo8TERP32t7/VQw89JEkqKChQXFyc5s2bp2HDhp1RZ0VFhSoqTv4QLywsVFJSksdGgE4wxmhrVqGGv/yVbuieoNv6JKlzQqR+Oe9rrfqh9lMYIUF2lVe5zwu5umNzLdtxyGPtbCw2ORUg5xm/jOr6hXehsMupUJ39lJyRTaXn+MFTP0bBqj5nqUoFnbNM4zjenlN/gDsvgq8pAO/YM+36Rq3vghkBqqys1Lp16zRhwgTXNrvdrvT0dK1atarW96xatUrjx49325aRkaFFixZJknbv3q2cnBylp6e79kdFRSk1NVWrVq2qNQBNnTpVTz75ZCMc0fmx2Wzq2jJKm5/IcNv+xt2pqqoxbitXTlVd49T6ffnqkRRVr0mITqdRaVWNa1VWQWmVHEF2OQLtrsl0Z5soaIzRgWNlSowOVYDd5ppImV9aqajQILeJgbXVY4xRcUW1iiuqFRYcqMiQQOUUlissOPD4Mn0jdYw/OZJVXFGt0KAABdhtKiqv0pHiSjULD3ZbdZRdUKYAm00tIkM09aPtatOsiX6e2trtc6tqnAoKsOtIcYWaOAJls0l5hRVqFRPq1r/ZBWVa/t1h3dwrUQVlVbLJpuYR7vOZpi/+VvGRIbrz8jbKL6vSrrxiRYYGqmV0qKutNptNJRXV2plXrE+/zdOvr25f56TET7/N1Yuf7tIN3RPVKT5CcVEh2n+0VK1iwtQqJlTZBeUKtNsUGRqkqNAg1TjN8cma1U59n1esbi2jZLfblFdYrqZNglVe7VRwgF17jpSoXWwT7cgt0ne5RRrUJcFtcqfTeXwV3o6cInVtGaUlW3N0SVyE/v7lD5p8YxclNT0+rF1SUa3cwnIdKqpQXGSISiqr1SIiRGHBATpaUqm4yBAFBRyfH2OzSYeKKhQeEii7zabiimrFhjvkdBrtP1aqkKAArdh1WEXl1erfvplimgSrrLJGB46VqW1sEx0rrVSA3SZHoF0V1U5VVjsVHRakV1fsUUaXePVr29T1fbRw3QG1i22i8JBArdx1RDf3TFSzcIe2HCxQfmmVLm/XVIXl1dqZW6TgQLuiw4LlNEYJUSFa9f0RlVc5FR8Vou9yizS0b5I+25GnN9fsU1WN0UPXdpTTGG3LLlROQbm2ZhVo/DUdldQ0VEu25ircEaj0S1to/7EyxYQF6eMtOZrywTaN6p+sgZfGKTE6RFXVRmVVNWoe4dC3OYXqGBeh2+eu0k8uaa5fXN7GdYxLt+Uq3BGgNs2a6P1NWRrVP1mffpunT7bn6unB3dQmNky5BeWa9clOXd6+mbYeLFBRRbVu7dVSsz7Zqb7JMUq/NE6rvj+iPm1i1KZZmI6VVuqf6w6ob5umWvH9YX1zoEC78oqVEBWi7ILjf40/cWNn/eSS5vr7l7tVWlmjhzI6qqi8SpXVTj3z0XYdzC/T/qNlGnZZkm7qkajtOUVq37yJ1u89ptv7JunXr69XSUW1/veaS/Tgmxtkt0lDerfSwnUHFBMWpOlDumv17qO6vnuC3ttwUFFhwXr76/3q17apbDbpvY1Z6tEqStd3T1CA3a5nl3zr9gfd+Gsu0XNLv5MkjUxroxW7Duv7Q8fnqv20Y3O1iAjRgrX7FRxoV2W1U1d2iNWXuw67/d+aeENnzVj8rWsBwYzbuqtldKjmrdyjpduOzzMLtNtks0lVNQ3/+z+jS5yWbD33vDXU7evH0s9dyIMsHQHKyspSy5YttXLlSqWlpbm2P/LII/r888+1evWZKyeCg4M1f/58DR8+3LXtL3/5i5588knl5uZq5cqVuuKKK5SVlaWEhARXmTvuuEM2m00LFiw4o06rRoAAAEDjuWBGgHyFw+GQw3H2FUwAAODiYemVoGNjYxUQEKDcXPdhxNzcXMXH1770Nj4+/qzlT/x7PnUCAAD/YmkACg4OVp8+fZSZmena5nQ6lZmZ6XZK7FRpaWlu5SVp6dKlrvJt27ZVfHy8W5nCwkKtXr26zjoBAIB/sfwU2Pjx43XXXXepb9++6tevn2bNmqWSkhKNHj1akjRy5Ei1bNlSU6dOlSSNHTtWAwYM0B//+Eddf/31euutt7R27Vq99NJLko5PLB43bpz+8Ic/KCUlxbUMPjExUYMHD7bqMAEAgA+xPAANHTpUhw4d0qRJk5STk6OePXtq8eLFiouLkyTt27dPdvvJgar+/fvrjTfe0OOPP67f//73SklJ0aJFi1zXAJKOT6IuKSnRPffco/z8fF155ZVavHixT1wDCAAAWM/y6wD5Ik9fCRoAADS+8/n9bekcIAAAACsQgAAAgN8hAAEAAL9DAAIAAH6HAAQAAPwOAQgAAPgdAhAAAPA7BCAAAOB3LL8StC86cW3IwsJCi1sCAADq68Tv7fpc45kAVIuioiJJUlJSksUtAQAA56uoqEhRUVFnLcOtMGrhdDqVlZWliIgI2Wy2Rq27sLBQSUlJ2r9/P7fZ8CD62TvoZ++gn72DfvYeT/W1MUZFRUVKTEx0u49obRgBqoXdblerVq08+hmRkZH8B/MC+tk76GfvoJ+9g372Hk/09blGfk5gEjQAAPA7BCAAAOB3CEBe5nA4NHnyZDkcDqubclGjn72DfvYO+tk76Gfv8YW+ZhI0AADwO4wAAQAAv0MAAgAAfocABAAA/A4BCAAA+B0CkBfNnj1bycnJCgkJUWpqqtasWWN1k3zW1KlTddlllykiIkItWrTQ4MGDtWPHDrcy5eXluv/++9WsWTOFh4dryJAhys3NdSuzb98+XX/99QoLC1OLFi308MMPq7q62q3MsmXL1Lt3bzkcDnXo0EHz5s3z9OH5rGnTpslms2ncuHGubfRz4zl48KB+8YtfqFmzZgoNDVW3bt20du1a135jjCZNmqSEhASFhoYqPT1dO3fudKvj6NGjGjFihCIjIxUdHa0xY8aouLjYrcw333yjq666SiEhIUpKStKMGTO8cny+oKamRhMnTlTbtm0VGhqq9u3ba8qUKW73hqKfz98XX3yhG2+8UYmJibLZbFq0aJHbfm/26cKFC9WpUyeFhISoW7du+uijjxp2UAZe8dZbb5ng4GDzyiuvmK1bt5q7777bREdHm9zcXKub5pMyMjLMq6++arZs2WI2btxofvazn5nWrVub4uJiV5l7773XJCUlmczMTLN27Vpz+eWXm/79+7v2V1dXm65du5r09HSzYcMG89FHH5nY2FgzYcIEV5kffvjBhIWFmfHjx5tt27aZF154wQQEBJjFixd79Xh9wZo1a0xycrLp3r27GTt2rGs7/dw4jh49atq0aWNGjRplVq9ebX744QezZMkSs2vXLleZadOmmaioKLNo0SKzadMmc9NNN5m2bduasrIyV5lBgwaZHj16mK+++sosX77cdOjQwQwfPty1v6CgwMTFxZkRI0aYLVu2mDfffNOEhoaav/71r149Xqs8/fTTplmzZuaDDz4wu3fvNgsXLjTh4eHmz3/+s6sM/Xz+PvroI/PYY4+Zd955x0gy7777rtt+b/XpihUrTEBAgJkxY4bZtm2befzxx01QUJDZvHnzeR8TAchL+vXrZ+6//37X65qaGpOYmGimTp1qYasuHHl5eUaS+fzzz40xxuTn55ugoCCzcOFCV5nt27cbSWbVqlXGmOP/Ye12u8nJyXGVmTNnjomMjDQVFRXGGGMeeeQR06VLF7fPGjp0qMnIyPD0IfmUoqIik5KSYpYuXWoGDBjgCkD0c+P53e9+Z6688so69zudThMfH2+effZZ17b8/HzjcDjMm2++aYwxZtu2bUaS+frrr11lPv74Y2Oz2czBgweNMcb85S9/MTExMa6+P/HZHTt2bOxD8knXX3+9+eUvf+m27dZbbzUjRowwxtDPjeH0AOTNPr3jjjvM9ddf79ae1NRU86tf/eq8j4NTYF5QWVmpdevWKT093bXNbrcrPT1dq1atsrBlF46CggJJUtOmTSVJ69atU1VVlVufdurUSa1bt3b16apVq9StWzfFxcW5ymRkZKiwsFBbt251lTm1jhNl/O3rcv/99+v6668/oy/o58bz/vvvq2/fvrr99tvVokUL9erVSy+//LJr/+7du5WTk+PWT1FRUUpNTXXr6+joaPXt29dVJj09XXa7XatXr3aV+clPfqLg4GBXmYyMDO3YsUPHjh3z9GFarn///srMzNR3330nSdq0aZO+/PJLXXfddZLoZ0/wZp825s8SApAXHD58WDU1NW6/ICQpLi5OOTk5FrXqwuF0OjVu3DhdccUV6tq1qyQpJydHwcHBio6Odit7ap/m5OTU2ucn9p2tTGFhocrKyjxxOD7nrbfe0vr16zV16tQz9tHPjeeHH37QnDlzlJKSoiVLlui+++7Tb37zG82fP1/Syb4628+JnJwctWjRwm1/YGCgmjZtel5fj4vZo48+qmHDhqlTp04KCgpSr169NG7cOI0YMUIS/ewJ3uzTuso0pM+5Gzx83v33368tW7boyy+/tLopF539+/dr7NixWrp0qUJCQqxuzkXN6XSqb9++euaZZyRJvXr10pYtWzR37lzdddddFrfu4vH222/r9ddf1xtvvKEuXbpo48aNGjdunBITE+lnuGEEyAtiY2MVEBBwxsqZ3NxcxcfHW9SqC8MDDzygDz74QJ999platWrl2h4fH6/Kykrl5+e7lT+1T+Pj42vt8xP7zlYmMjJSoaGhjX04PmfdunXKy8tT7969FRgYqMDAQH3++ed6/vnnFRgYqLi4OPq5kSQkJKhz585u2y699FLt27dP0sm+OtvPifj4eOXl5bntr66u1tGjR8/r63Exe/jhh12jQN26ddOdd96p//3f/3WNcNLPjc+bfVpXmYb0OQHIC4KDg9WnTx9lZma6tjmdTmVmZiotLc3ClvkuY4weeOABvfvuu/r000/Vtm1bt/19+vRRUFCQW5/u2LFD+/btc/VpWlqaNm/e7PafbunSpYqMjHT9IkpLS3Or40QZf/m6DBw4UJs3b9bGjRtdj759+2rEiBGu5/Rz47jiiivOuJTDd999pzZt2kiS2rZtq/j4eLd+Kiws1OrVq936Oj8/X+vWrXOV+fTTT+V0OpWamuoq88UXX6iqqspVZunSperYsaNiYmI8dny+orS0VHa7+6+2gIAAOZ1OSfSzJ3izTxv1Z8l5T5tGg7z11lvG4XCYefPmmW3btpl77rnHREdHu62cwUn33XefiYqKMsuWLTPZ2dmuR2lpqavMvffea1q3bm0+/fRTs3btWpOWlmbS0tJc+08sz7722mvNxo0bzeLFi03z5s1rXZ798MMPm+3bt5vZs2f73fLs0526CswY+rmxrFmzxgQGBpqnn37a7Ny507z++usmLCzM/OMf/3CVmTZtmomOjjbvvfee+eabb8zNN99c61LiXr16mdWrV5svv/zSpKSkuC0lzs/PN3FxcebOO+80W7ZsMW+99ZYJCwu7aJdnn+6uu+4yLVu2dC2Df+edd0xsbKx55JFHXGXo5/NXVFRkNmzYYDZs2GAkmeeee85s2LDB7N271xjjvT5dsWKFCQwMNDNnzjTbt283kydPZhn8heCFF14wrVu3NsHBwaZfv37mq6++srpJPktSrY9XX33VVaasrMz8+te/NjExMSYsLMzccsstJjs7262ePXv2mOuuu86Ehoaa2NhY89vf/tZUVVW5lfnss89Mz549TXBwsGnXrp3bZ/ij0wMQ/dx4/v3vf5uuXbsah8NhOnXqZF566SW3/U6n00ycONHExcUZh8NhBg4caHbs2OFW5siRI2b48OEmPDzcREZGmtGjR5uioiK3Mps2bTJXXnmlcTgcpmXLlmbatGkePzZfUVhYaMaOHWtat25tQkJCTLt27cxjjz3mtrSafj5/n332Wa0/k++66y5jjHf79O233zaXXHKJCQ4ONl26dDEffvhhg47JZswpl8cEAADwA8wBAgAAfocABAAA/A4BCAAA+B0CEAAA8DsEIAAA4HcIQAAAwO8QgAAAgN8hAAEAAL9DAAIAAH6HAATggnLo0CHdd999at26tRwOh+Lj45WRkaEVK1ZIkmw2mxYtWmRtIwH4vECrGwAA52PIkCGqrKzU/Pnz1a5dO+Xm5iozM1NHjhyxumkALiCMAAG4YOTn52v58uWaPn26fvrTn6pNmzbq16+fJkyYoJtuuknJycmSpFtuuUU2m831WpLee+899e7dWyEhIWrXrp2efPJJVVdXu/bbbDbNmTNH1113nUJDQ9WuXTv985//dO2vrKzUAw88oISEBIWEhKhNmzaaOnWqtw4dQCMjAAG4YISHhys8PFyLFi1SRUXFGfu//vprSdKrr76q7Oxs1+vly5dr5MiRGjt2rLZt26a//vWvmjdvnp5++mm390+cOFFDhgzRpk2bNGLECA0bNkzbt2+XJD3//PN6//339fbbb2vHjh16/fXX3QIWgAsLd4MHcEH517/+pbvvvltlZWXq3bu3BgwYoGHDhql79+6Sjo/kvPvuuxo8eLDrPenp6Ro4cKAmTJjg2vaPf/xDjzzyiLKyslzvu/feezVnzhxXmcsvv1y9e/fWX/7yF/3mN7/R1q1b9cknn8hms3nnYAF4DCNAAC4oQ4YMUVZWlt5//30NGjRIy5YtU+/evTVv3rw637Np0yY99dRTrhGk8PBw3X333crOzlZpaamrXFpamtv70tLSXCNAo0aN0saNG9WxY0f95je/0X/+8x+PHB8A7yAAAbjghISE6JprrtHEiRO1cuVKjRo1SpMnT66zfHFxsZ588klt3LjR9di8ebN27typkJCQen1m7969tXv3bk2ZMkVlZWW64447dNtttzXWIQHwMgIQgAte586dVVJSIkkKCgpSTU2N2/7evXtrx44d6tChwxkPu/3kj8GvvvrK7X1fffWVLr30UtfryMhIDR06VC+//LIWLFigf/3rXzp69KgHjwyAp7AMHsAF48iRI7r99tv1y1/+Ut27d1dERITWrl2rGTNm6Oabb5YkJScnKzMzU1dccYUcDodiYmI0adIk3XDDDWrdurVuu+022e12bdq0SVu2bNEf/vAHV/0LFy5U3759deWVV+r111/XmjVr9Pe//12S9NxzzykhIUG9evWS3W7XwoULFR8fr+joaCu6AsCPZQDgAlFeXm4effRR07t3bxMVFWXCwsJMx44dzeOPP25KS0uNMca8//77pkOHDiYwMNC0adPG9d7Fixeb/v37m9DQUBMZGWn69etnXnrpJdd+SWb27NnmmmuuMQ6HwyQnJ5sFCxa49r/00kumZ8+epkmTJiYyMtIMHDjQrF+/3mvHDqBxsQoMAFT76jEAFy/mAAEAAL9DAAIAAH6HSdAAIInZAIB/YQQIAAD4HQIQAADwOwQgAADgdwhAAADA7xCAAACA3yEAAQAAv0MAAgAAfocABAAA/M7/B/ebii/lMjb6AAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(losses, label='Train')\n", - "plt.plot(val_losses, label='Val')\n", - "plt.xlabel(\"Steps\")\n", - "plt.ylabel(\"Loss\")\n", - "plt.legend()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "698324f0-353f-4b04-b2b0-c80d8cc8cc56", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python [conda env:.conda-jupyter_py3.11]", - "language": "python", - "name": "conda-env-.conda-jupyter_py3.11-py" - }, - "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.11.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/benchmarks/galaxies/nequip_debugging.ipynb b/benchmarks/galaxies/nequip_debugging.ipynb deleted file mode 100644 index c0f839f..0000000 --- a/benchmarks/galaxies/nequip_debugging.ipynb +++ /dev/null @@ -1,754 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], - "source": [ - "import sys\n", - "sys.path.append(\"../../\")\n", - "\n", - "from tqdm import tqdm\n", - "import numpy as np\n", - "\n", - "# Make sure tf does not hog all the GPU memory\n", - "import tensorflow as tf\n", - "\n", - "# Ensure TF does not see GPU and grab all GPU memory\n", - "tf.config.experimental.set_visible_devices([], \"GPU\")\n", - "\n", - "%load_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "x_train = np.load(\"/Users/smsharma/Downloads/halos_small.npy\")[..., :3]\n", - "mean = np.mean(x_train, axis=(0,1))\n", - "std = np.std(x_train, axis=(0,1)) \n", - "\n", - "x_train = (x_train - mean) / std" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "import flax\n", - "from flax.training.train_state import TrainState\n", - "from functools import partial\n", - "import flax.linen as nn\n", - "import optax\n", - "from tqdm import trange\n", - "\n", - "replicate = flax.jax_utils.replicate\n", - "unreplicate = flax.jax_utils.unreplicate" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "from models.utils.equivariant_graph_utils import get_equivariant_graph\n", - "from models.utils.graph_utils import build_graph, compute_distances, nearest_neighbors\n", - "from models.segnn import SEGNN\n", - "from models.gnn import GNN\n", - "from models.utils.graph_utils import get_apply_pbc" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "import e3nn_jax as e3nn\n", - "from typing import Dict\n", - "import jax\n", - "from models.gnn import GNN\n", - "from models.segnn import SEGNN\n", - "from models.egnn import EGNN\n", - "from models.nequip import NequIP\n", - "import jraph\n", - "import jax.numpy as jnp\n", - "\n", - "use_pbcs = True\n", - "apply_pbc = get_apply_pbc(std=std / 1000.,) if use_pbcs else None\n", - "k = 10\n", - "n_radial = 64\n", - "position_features = True\n", - "r_max = 0.6\n", - "use_3d_distances = False\n", - "l_max = 1\n", - "\n", - "SEGNN_PARAMS = {\n", - " \"d_hidden\": 128,\n", - " \"l_max_hidden\": l_max,\n", - " \"n_layers\": 3,\n", - " \"message_passing_steps\": 3,\n", - " \"task\": \"graph\",\n", - " \"output_irreps\": e3nn.Irreps(\"1x0e\"),\n", - " \"hidden_irreps\": None,\n", - " \"message_passing_agg\": \"mean\",\n", - " \"readout_agg\": \"mean\",\n", - " \"n_outputs\": 2,\n", - " \"scalar_activation\": \"gelu\",\n", - " \"gate_activation\": \"sigmoid\",\n", - " \"mlp_readout_widths\": (4, 2, 2),\n", - " \"residual\": False,\n", - "}\n", - "\n", - "GNN_PARAMS = {\n", - " \"d_hidden\": 128,\n", - " \"message_passing_steps\": 3,\n", - " \"n_layers\": 3,\n", - " \"activation\": \"gelu\",\n", - " \"message_passing_agg\": \"mean\",\n", - " \"readout_agg\": \"mean\",\n", - " \"mlp_readout_widths\": (4, 2, 2),\n", - " \"task\": \"graph\",\n", - " \"n_outputs\": 2,\n", - " \"norm\": \"none\",\n", - " \"position_features\": position_features,\n", - " \"residual\": False,\n", - "}\n", - "\n", - "NEQUIP_PARAMS = {\n", - " \"n_outputs\": 2,\n", - " \"n_radial_basis\": n_radial,\n", - " \"r_cutoff\": r_max,\n", - " \"sphharm_norm\": 'component',\n", - "}\n", - "\n", - "\n", - "class GraphWrapper(nn.Module):\n", - " param_dict: Dict\n", - "\n", - " @nn.compact\n", - " def __call__(self, x):\n", - "\n", - " positions = e3nn.IrrepsArray(\"1o\", x.nodes[..., :3])\n", - " \n", - " if x.nodes.shape[-1] == 3:\n", - " nodes = e3nn.IrrepsArray(\"1o\", x.nodes[..., :])\n", - " velocities = None\n", - " else:\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o\", x.nodes[..., :])\n", - " velocities = e3nn.IrrepsArray(\"1o\", x.nodes[..., 3:6])\n", - "\n", - " \n", - " st_graph = get_equivariant_graph(\n", - " node_features=nodes,\n", - " positions=positions,\n", - " velocities=None,\n", - " steerable_velocities=False,\n", - " senders=x.senders,\n", - " receivers=x.receivers,\n", - " n_node=x.n_node,\n", - " n_edge=x.n_edge,\n", - " globals=x.globals,\n", - " edges=None,\n", - " lmax_attributes=l_max,\n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " )\n", - " \n", - " return jax.vmap(SEGNN(**self.param_dict))(st_graph)\n", - " \n", - "class GraphWrapperGNN(nn.Module):\n", - " param_dict: Dict\n", - " @nn.compact\n", - " def __call__(self, x):\n", - " return jax.vmap(GNN(**self.param_dict))(x) \n", - "\n", - "class GraphWrapperNequIP(nn.Module):\n", - " param_dict: Dict\n", - "\n", - " @nn.compact\n", - " def __call__(self, x):\n", - " if x.nodes.shape[-1] == 3:\n", - " ones = jnp.ones(x.nodes[..., :].shape[:2] + (1,))\n", - " nodes = jnp.concatenate([x.nodes[..., :], x.nodes[..., :], ones], axis=-1)\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o + 1x0e\", nodes)\n", - " else:\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o + 1x0e\", x.nodes[..., :])\n", - " \n", - " graph = jraph.GraphsTuple(\n", - " n_node=x.n_node,\n", - " n_edge=x.n_edge,\n", - " edges=None,\n", - " globals=x.globals,\n", - " nodes=nodes, \n", - " senders=x.senders,\n", - " receivers=x.receivers)\n", - " \n", - " return jax.vmap(NequIP(**self.param_dict))(graph)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of parameters: 573253\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/nx/bx2847k56j3dddp761x637pc0000gn/T/ipykernel_9853/1825512499.py:16: DeprecationWarning: jax.tree_leaves is deprecated: use jax.tree.leaves (jax v0.4.25 or newer) or jax.tree_util.tree_leaves (any JAX version).\n", - " print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n" - ] - }, - { - "data": { - "text/plain": [ - "Array([[-0.00502239, -0.00011915],\n", - " [-0.00469782, -0.00013022]], dtype=float32)" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph = build_graph(x_train[:2], \n", - " None, \n", - " k=k, \n", - " apply_pbc=apply_pbc,\n", - " use_edges=True, \n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " use_3d_distances=use_3d_distances,\n", - ")\n", - "\n", - "model = GraphWrapper(SEGNN_PARAMS, )\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "\n", - "# Number of parameters\n", - "print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n", - "\n", - "out" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of parameters: 700674\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/nx/bx2847k56j3dddp761x637pc0000gn/T/ipykernel_9853/1152665868.py:6: DeprecationWarning: jax.tree_leaves is deprecated: use jax.tree.leaves (jax v0.4.25 or newer) or jax.tree_util.tree_leaves (any JAX version).\n", - " print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n" - ] - }, - { - "data": { - "text/plain": [ - "Array([[ 0.16024624, -0.09174243],\n", - " [ 0.1541301 , -0.07500153]], dtype=float32)" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model = GraphWrapperGNN(GNN_PARAMS)\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "\n", - "# Number of parameters\n", - "print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n", - "\n", - "out" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of parameters: 393216\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/nx/bx2847k56j3dddp761x637pc0000gn/T/ipykernel_9853/2023141262.py:6: DeprecationWarning: jax.tree_leaves is deprecated: use jax.tree.leaves (jax v0.4.25 or newer) or jax.tree_util.tree_leaves (any JAX version).\n", - " print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n" - ] - }, - { - "data": { - "text/plain": [ - "Array([[-0.9241759 , -0.74314517],\n", - " [-0.5319379 , -0.60047907]], dtype=float32)" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model = GraphWrapperNequIP(NEQUIP_PARAMS)\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "\n", - "# Number of parameters\n", - "print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n", - "\n", - "out" - ] - }, - { - "cell_type": "code", - "execution_count": 457, - "metadata": {}, - "outputs": [], - "source": [ - "# from models.transformer import Transformer\n", - "\n", - "# model = Transformer(task=\"graph\", n_outputs=2, induced_attention=True, n_inducing_points=256, readout_agg=\"attn\")\n", - "\n", - "# rng = jax.random.PRNGKey(0)\n", - "# out, params = model.init_with_output(rng, x_train[:2])\n", - "\n", - "# out" - ] - }, - { - "cell_type": "code", - "execution_count": 458, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4 GPUs available\n" - ] - } - ], - "source": [ - "# Devices\n", - "num_local_devices = jax.local_device_count()\n", - "print(f\"{num_local_devices} GPUs available\")" - ] - }, - { - "cell_type": "code", - "execution_count": 459, - "metadata": {}, - "outputs": [], - "source": [ - "# Define train state and replicate across devices\n", - "\n", - "# Cosine learning rate schedule\n", - "lr = optax.cosine_decay_schedule(3e-4, 2000)\n", - "# lr = optax.warmup_cosine_decay_schedule(\n", - "# init_value=0.0,\n", - "# peak_value=3e-4,\n", - "# warmup_steps=500,\n", - "# decay_steps=5000,\n", - "# )\n", - "\n", - "# lr = optax.linear_onecycle\"_schedule(5000, 3e-4)\n", - "tx = optax.adamw(learning_rate=lr, weight_decay=1e-5)\n", - "state = TrainState.create(apply_fn=model.apply, params=params, tx=tx)\n", - "pstate = replicate(state)" - ] - }, - { - "cell_type": "code", - "execution_count": 460, - "metadata": {}, - "outputs": [], - "source": [ - "def loss_mse(pred_batch, cosmo_batch,):\n", - " return np.mean((pred_batch - cosmo_batch) ** 2)\n", - "\n", - "@partial(jax.pmap, axis_name=\"batch\",)\n", - "def train_step(state, halo_batch, cosmo_batch,):\n", - "\n", - " halo_graph = build_graph(halo_batch, \n", - " None, \n", - " k=k, \n", - " use_edges=True, \n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " use_3d_distances=use_3d_distances,\n", - " )\n", - " \n", - " def loss_fn(params):\n", - " outputs = state.apply_fn(params, halo_graph)\n", - " loss = loss_mse(outputs, cosmo_batch)\n", - " return loss\n", - "\n", - " # Get loss, grads, and update state\n", - " loss, grads = jax.value_and_grad(loss_fn)(state.params)\n", - " grads = jax.lax.pmean(grads, \"batch\")\n", - " new_state = state.apply_gradients(grads=grads)\n", - " metrics = {\"loss\": jax.lax.pmean(loss, \"batch\")}\n", - " \n", - " return new_state, metrics" - ] - }, - { - "cell_type": "code", - "execution_count": 461, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/2000 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+EAAAINCAYAAABRSH6rAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAACprElEQVR4nOzde1gU9f4H8PdyETQUIUXU8JIWZRZ48p6lHVBYTIQQUzMtS8yTZip5SY+WVPwwI06lUWihFUK2QglIomFleei66cky9GhrJWvpCqJyn98fxh6Q2y7M7Mzsvl/P4/PIMjv72QXmO5/v5fPVCIIggIiIiIiIiIgk5yR3AERERERERESOgkk4ERERERERkY0wCSciIiIiIiKyESbhRERERERERDbCJJyIiIiIiIjIRpiEExEREREREdkIk3AiIiIiIiIiG2ESTkRERERERGQjLnIHILba2lr8/vvv6Ny5MzQajdzhEBERQRAEXLhwAb169YKTE/u/xcD2noiIlMSatt7ukvDff/8dfn5+codBRETUyKlTp3DdddfJHYZdYHtPRERKZElbb3dJeOfOnQFcefNdunSRORoiIiKgtLQUfn5+5jaK2o/tPRERKYk1bb3dJeF1U9K6dOnCRpmIiBSF06bFw/aeiIiUyJK2ngvTiIiIiIiIiGyESTgRERERERGRjTAJJyIiIiIiIrIRJuFERERERERENsIknIiIiIiIiMhGmIQTERERERER2QiTcCIiIiIiIiIbYRJOREREREREZCNMwomIiIiIiIhshEk4ERERERERkY0wCSciIiIiIiKyESbhRERERERERDbCJJyIiIiIiIjIRpiEExEREREREdmIpEn4p59+ikmTJqFXr17QaDTIyspq8fj9+/dDo9E0+ldcXCxlmEREREREREQ2IWkSfvHiRQQEBGDjxo1WPe/o0aM4ffq0+Z+Pj49EERIREREREZHYTHo9TmVmwqTXyx2K4rhIeXKtVgutVmv183x8fNC1a1fxAyIiIruVk5MDFxcXhISEiHI+k16PshMn4NG/P7wCA0U5JxERkSM4kpCA42+8Yf56QEwMBi1fLmNEyqLINeGBgYHo2bMnxo8fj88//7zFYysqKlBaWtrgHxEROZaCggJERUVh0qRJ+Pe//93u8x1JSMCBqCjoY2NxICoKRxISRIiSiIjI/pn0+gYJ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qqursX//fhw/fhwzZsxA586d8fvvv6NLly7w8PCQ9LVtie29YxDrXkKtCZTJZMKdd96JH374ATfffDMOHDgAb29vucOSlFp/VtQ8RyluZ027xOnoJAkpE9r2nLu557Zlj862qqmpwaxZs5CdnQ13d3dkZ2fjmo8/xgE77x0kIun98ssvCA0NhcFgQEVFBcaPH4/OnTsjISEBFRUVSE5OljtEIouJdS+h1hG48vJyRERE4IcffkCvXr2Ql5dn9wk4oMz6CVIM/jgSpa73lxOro5PopKxu2Z5zt/RcW1W+FAQB8+fPR3p6OlxcXKDT6XCbp6ciq4ESkfosWrQIQ4cOhclkajBdNTIyEvv27ZMxMiLriHUvodSK262pqanBAw88gE8//RRdunTB7t270adPH7nDckhHEhJwICoK+thYHIiKwpGEBJs8154odb2/nJiEk+ikTGjbc+6WnmuLi4MgCIiNjUVKSgqcnJyQlpaGsLAwbn1BRKL57LPPsHr1anTo0KHB4/369cNvv/0mU1RE1hOrbVRjGysIAhYvXoz3338fHTp0QFZWFm677Ta5w3JIUg3+OBprtuFzFEzCSXTNJa5/HDgg2bktSZZbeq4tLg5xcXFITEwEAKSkpCA6OrrVuIiIrFFbW4uamppGj//666/o3LmzDBERtY1YbaMa29gXXngBr7zyCgBg27ZtuPvuu2WOyHFJNfjjiAYtX44xOh0CN2zAGJ1OMQX35MIknETnFRiI3hERjR7/LSur3b1/7UmWW3uulBeHpKQkrF271vz/OXPmWBwXEZGlJkyYgKSkJPPXGo0GZWVlWLt2LcLCwuQLjMhKYrWNamtj33nnHSz/a716YmIi7rvvPpkjcmxSDf44Kq/AQPhFRir278+WWB2dJHEqMxP62NhGjwdu2AC/yMh2n19NBTK2bNmCRx55BMCV0fDVq1crIi4ish1btU2nTp1CaGgoBEFAUVERhg4diqKiInTr1g2ffvopfHx8JHttW2N77xgcqTp6fn4+wsLCUF1djSVLluDFF1+UOyRC+7ZNU/KWayQ+blHGRll2jrIVQWsyMjIwffp083rw9evXQ6PRqOJmgIjEY+styjIyMvD999+jrKwMf/vb33D//ferdl/h5rC9J3vy3Xff4a677kJZWRmmTZuGd999F05OnLCqFGoa/CH5MAlno6wIjt77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xYMPPtjiMddffz18fX1x5syZBo9XV1fj3LlzVq33HjFiBADg2LFjzSbhK1euxJIlS8xfl5aWclcLG3KUTllBELBw4UJkZWXBzc0NH374IW655Ra5wyIiO8MknBTFkilvzR1z9ZT03hER2Lp/P9auXQsASEpKwpw5cwBIV3SMxcyIyB50794d3bt3b/W4UaNG4fz58/jmm29w++23A7iylVNtba05sbaE/q/aHj179mz2GDc3N7i5uVl8ThKfI3TKPv/883jttdeg0Wjw7rvv4s4775Q7JCKyQyzMRopSN+WtvqunvDV3zN9efBG9IyLMj721bRsWL14MAFi3bh0WLVpk/p5U69sccd0cETmum2++GaGhoZg7dy6+/PJLfP7551iwYAGmTZtmroz+22+/4aabbsKXX34JADh+/Dji4uLwzTff4OTJk/jwww8xa9Ys3HXXXbjtttvkfDvk4FJTU7F69WoAwMsvv4yoqCiZIyIie8WRcFIcS6a8NXWMSa83j4R/VlaGjX/+CQBYMGuWuVGtI9X6NkdbN0dE9O6772LBggUICgqCk5MToqKi8PLLL5u/X1VVhaNHj5qrn3fo0AF79+5FUlISLl68CD8/P0RFRTW6ThPZ0u7du/HII48AAJYvX44FCxbIHBER2TONIAiC3EGIqbS0FJ6enigpKUGXLl3kDods6FRmJvSxsfjq0iU8X1yMGgAhnTvjjdRU9Ln33iafw+roRGQLbJvEZw+fKdsKZfjqq68wbtw4XLp0CQ888AC2bt0KjUYjd1hEpDLWtEscCSe74dG/Pw5fvowEoxE1AMZ6eODRbt3Q+frrm32OVOvbHGHdHBERtZ097aShZsePH8fEiRNx6dIlTJgwAZs3b2YCTkSS45pwshtFlZV47uxZVAoChnfqhEXdu+PGRx9VZTJs0utxKjMTpr+KFRERkf1obicNXvNt68yZMwgJCcEff/yBIUOG4P3330eHDh3kDouIHABHwskuHD58GKGhobhUWYmxw4cjZckSdPP3V2UCztERIiL7JtdOGpz+/j9lZWWYOHEijh8/jv79+yM3NxedO3eWO6wG+PMisl9MwlvBC6DyFRUVYfz48TCZTBg5ciSy8/Ph4eHR7PFK/pna0z7jSv6ciYjkJMdOGuzg/Z+qqipMnToVX3/9Na699lrk5eVZta+9LfDnRWTfmIS3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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "features = ['x', 'y', 'z'] # ['x', 'y', 'z', 'Jx', 'Jy', 'Jz', 'vx', 'vy', 'vz', 'M200c']\n", - "params = ['Omega_m', 'sigma_8'] # ['Omega_m', 'Omega_b', 'h', 'n_s', 'sigma_8']\n", - "\n", - "dataset, num_total = get_halo_dataset(batch_size=50, # Batch size\n", - " num_samples=250, # If not None, will only take a subset of the dataset\n", - " split='val', # 'train', 'val'\n", - " standardize=True, # If True, will standardize the features\n", - " return_mean_std=False, # If True, will return (dataset, num_total, mean, std, mean_params, std_params), else (dataset, num_total)\n", - " seed=42, # Random seed\n", - " features=features, # Features to include\n", - " params=params # Parameters to include\n", - " )\n", - "\n", - "iterator = iter(dataset)\n", - "\n", - "plt.figure(figsize=(12, 6))\n", - "\n", - "fig, ax = plt.subplots(1, 2, figsize=(12, 6))\n", - "\n", - "mse_list = []\n", - "\n", - "x_val, params_val = [], []\n", - "for _ in tqdm(range(num_total // batch_size)):\n", - " x, params = next(iterator)\n", - "\n", - " # Convert to numpy\n", - " x, params = np.array(x), np.array(params)\n", - " \n", - " # x_val.append(np.array(x))\n", - " # params_val.append(np.array(params))\n", - "\n", - " graph = build_graph(x, \n", - " None, \n", - " k=k, \n", - " use_edges=True, \n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " use_3d_distances=use_3d_distances,\n", - " )\n", - "\n", - " pred = jax.jit(model.apply)(unreplicate(pstate).params, graph)\n", - "\n", - " ax[0].scatter(params[:, 0], pred[:, 0], s=10, color='firebrick')\n", - " ax[1].scatter(params[:, 1], pred[:, 1], s=10, color='firebrick')\n", - "\n", - " mse = np.mean((pred - params) ** 2)\n", - " mse_list.append(mse)\n", - "\n", - "# Diagonal\n", - "ax[0].plot([-1.5, 1.5], [-1.5, 1.5], color='black')\n", - "ax[1].plot([-1.5, 1.5], [-1.5, 1.5], color='black')\n", - "\n", - "print(f\"Mean MSE: {np.mean(mse_list)}\")\n", - "\n", - "# # # Diagonal line\n", - "# plt.plot([0, 0.5], [0, 0.5])\n", - "\n", - "plt.xlabel(\"True\")\n", - "plt.ylabel(\"Predicted\")" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [], - "source": [ - "# x_test = np.load(\"../../../BNN_SBI/data/set_diffuser_data/test_halos.npy\")[..., :3] / 1000.\n", - "# params_test = pd.read_csv(\"../../../BNN_SBI/data/set_diffuser_data/test_cosmology.csv\",)\n", - "\n", - "# params_test = params_test[[\"Omega_m\", \"sigma_8\"]].values\n", - "\n", - "# x_test = (x_test - mean) / std\n", - "# params_test = (params_test - mean_params) / std_params" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 4/4 [00:04<00:00, 1.04s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mean MSE: 0.1213223785161972\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "text/plain": [ - "Text(0, 0.5, 'Predicted')" - ] - }, - "execution_count": 77, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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WblypQYNGqSCggL17t1bixcvdryfmUj3u61cubLJn10oFNKOHTvc6TCQAPHejHjvjVyO9VLuxnti/f/kWqwnCffI3r17dfbZZ+vKK69M63WjR4/W9u3boz+PPPKIQz3MXCbf7Ze//KXuvPNOLVy4UC+//LIOOeQQjRo1SvX19Q72NDMXXHCB3nzzTT333HN66qmn9OKLL+ryyy9P+rpJkyaZ/ux++ctfutDbxB599FFNnTpVc+fO1WuvvaYBAwZo1KhR+uijj2Je/69//Uvnn3++Lr30Uq1Zs0Zjx47V2LFj9cYbb7jc8+TS/W6SVFhYaPozev/9913scXr27NmjAQMGpHycY3V1tb7//e/rpJNOUjgc1rXXXqvLLrtMzz77rMM9TV+63y1i48aNpj+/jh07OtRDIHXEezPivftyOdZLuR3vifVN5UysN+Cp+++/3ygqKkrp2okTJxpjxoxxtD92SvW7HThwwOjcubNx6623Rtt27dplFBQUGI888oiDPUzf+vXrDUnGf/7zn2jb3/72NyMUChnbtm2L+7oTTzzRuOaaa1zoYXqOP/5446qrroo+3r9/v9G1a1ejvLw85vXnnHOO8f3vf9/UNmTIEGPy5MmO9jMT6X63dP6/6DeSjKVLlya8ZsaMGcY3v/lNU9u5555rjBo1ysGeZS+V77ZixQpDklFTU+NKn4BMEO+J917J5VhvGPkT74n1uRXrmQkPmJUrV6pjx47q06ePrrzySn366adedylr1dXV2rFjh0aOHBltKyoq0pAhQ7Rq1SoPe9bUqlWr1LZtWx177LHRtpEjR6pZs2Z6+eWXE7724YcfVvv27fWtb31Ls2fP1hdffOF0dxPau3evVq9ebfq9N2vWTCNHjoz7e1+1apXpekkaNWqU7/6cMvlukrR7924deeSRKi4u1pgxY/Tmm2+60V1XBOXPLhulpaXq0qWLvve97+mll17yujtAVoj33sqVeJ/LsV4i3lsF6c8uU7kS6w/yugNI3ejRo3XWWWeppKREmzdv1nXXXafTTjtNq1atUvPmzb3uXsYiezk6depkau/UqZPv9nns2LGjybKXgw46SIcddljCvv7oRz/SkUceqa5du2rdunWaOXOmNm7cqCeeeMLpLsf1ySefaP/+/TF/7xs2bIj5mh07dgTizymT79anTx/dd9996t+/v2prazV//nwNGzZMb775po444gg3uu2oeH92dXV1+vLLL9W6dWuPepa9Ll26aOHChTr22GPV0NCgRYsWacSIEXr55Zc1aNAgr7sHpI14771cife5HOsl4r0VsT44SMJtNGvWLFVUVCS85q233tLRRx+d0fufd9550f/u16+f+vfvr169emnlypU65ZRTMnrPVDn93byW6vfLVOM9ZP369VOXLl10yimnaPPmzerVq1fG7wv7DB06VEOHDo0+HjZsmI455hjdfffduvHGGz3sGZLp06eP+vTpE308bNgwbd68WbfffrsefPBBD3uGXEW8J97HQ7z3P+J9MOVarCcJt9G0adN00UUXJbymZ8+etn1ez5491b59e23atMnxoOzkd+vcubMkaefOnerSpUu0fefOnSotLc3oPdOV6vfr3Llzk0IfX331lT777LPo90jFkCFDJEmbNm3yLCi3b99ezZs3186dO03tO3fujPtdOnfunNb1Xsnku1m1aNFCAwcO1KZNm5zoouvi/dkVFhYGemQ8nuOPP15VVVVedwM5inhPvE+V1/E+l2O9RLy3ItYHB0m4jTp06KAOHTq49nkffPCBPv30U1Mgc4qT362kpESdO3fW8uXLo0G4rq5OL7/8ctrVZDOV6vcbOnSodu3apdWrV2vw4MGSpBdeeEEHDhyIBtpUhMNhSXLlzy6eli1bavDgwVq+fLnGjh0rSTpw4ICWL1+uKVOmxHzN0KFDtXz5cl177bXRtueee840ouwHmXw3q/379+v111/X6aef7mBP3TN06NAmR8z48c/OLuFw2NP/fyG3Ee8zQ7x3Xy7Heol4b0WsDxCvK8Plq/fff99Ys2aNccMNNxht2rQx1qxZY6xZs8b4/PPPo9f06dPHeOKJJwzDMIzPP//cmD59urFq1SqjurraeP75541BgwYZRx11lFFfX+/V14gp3e9mGIbxf//3f0bbtm2NJ5980li3bp0xZswYo6SkxPjyyy+9+AoJjR492hg4cKDx8ssvG1VVVcZRRx1lnH/++dHnP/jgA6NPnz7Gyy+/bBiGYWzatMmYN2+e8eqrrxrV1dXGk08+afTs2dM44YQTvPoKUX/84x+NgoICY/Hixcb69euNyy+/3Gjbtq2xY8cOwzAMY/z48casWbOi17/00kvGQQcdZMyfP9946623jLlz5xotWrQwXn/9da++QlzpfrcbbrjBePbZZ43Nmzcbq1evNs477zyjVatWxptvvunVV0jo888/j/5/S5Lxq1/9ylizZo3x/vvvG4ZhGLNmzTLGjx8fvf7dd981Dj74YOOnP/2p8dZbbxl33XWX0bx5c+OZZ57x6ivEle53u/32241ly5YZ77zzjvH6668b11xzjdGsWTPj+eef9+orAFHEe+K91/E+l2O9YeR2vCfW526sJwn3yMSJEw1JTX5WrFgRvUaScf/99xuGYRhffPGFceqppxodOnQwWrRoYRx55JHGpEmTov/A+Em6380wvj625Prrrzc6depkFBQUGKeccoqxceNG9zufgk8//dQ4//zzjTZt2hiFhYXGxRdfbLrhqK6uNn3fLVu2GCeccIJx2GGHGQUFBUbv3r2Nn/70p0Ztba1H38BswYIFRvfu3Y2WLVsaxx9/vPHvf/87+tyJJ55oTJw40XT9Y489ZnzjG98wWrZsaXzzm980nn76aZd7nLp0vtu1114bvbZTp07G6aefbrz22mse9Do1kaM6rD+R7zRx4kTjxBNPbPKa0tJSo2XLlkbPnj1N/x/0k3S/W0VFhdGrVy+jVatWxmGHHWaMGDHCeOGFF7zpPGBBvCfe+yHe53KsN4zcjffE+hOj1+darA8ZhmHYPbsOAAAAAACa4pxwAAAAAABcQhIOAAAAAIBLSMIBAAAAAHAJSTgAAAAAAC4hCQcAAAAAwCUk4QAAAAAAuIQkHAAAAAAAl5CEAwAAAADgEpJwAAAAIOBCoVDCn1/84hdedxHAfx3kdQcAAAAAZGf79u3R/3700Uc1Z84cbdy4MdrWpk2b6H8bhqH9+/froINIBQAvMBMOAAAABFznzp2jP0VFRQqFQtHHGzZs0KGHHqq//e1vGjx4sAoKClRVVaWLLrpIY8eONb3PtddeqxEjRkQfHzhwQOXl5SopKVHr1q01YMAA/elPf3L3ywE5huEvAAAAIA/MmjVL8+fPV8+ePdWuXbuUXlNeXq6HHnpICxcu1FFHHaUXX3xRF154oTp06KATTzzR4R4DuYkkHAAAAMgD8+bN0/e+972Ur29oaNAtt9yi559/XkOHDpUk9ezZU1VVVbr77rtJwoEMkYQDAAAAeeDYY49N6/pNmzbpiy++aJK47927VwMHDrSza0BeIQkHAAAA8sAhhxxietysWTMZhmFq27dvX/S/d+/eLUl6+umn1a1bN9N1BQUFDvUSyH0k4QAAAEAe6tChg9544w1TWzgcVosWLSRJffv2VUFBgbZs2cLSc8BGJOEAAABAHjr55JN16623asmSJRo6dKgeeughvfHGG9Gl5oceeqimT5+un/zkJzpw4ICGDx+u2tpavfTSSyosLNTEiRM9/gZAMJGEAwAAAHlo1KhRuv766zVjxgzV19frkksu0YQJE/T6669Hr7nxxhvVoUMHlZeX691331Xbtm01aNAgXXfddR72HAi2kGHdCAIAAAAAABzRzOsOAAAAAACQL0jCAQAAAABwCUk4AAAAAAAuIQkHAAAAAMAlJOEAAAAAALiEJBwAAAAAAJeQhAMAAAAA4BKScAAAAAAAXEISDgAAAACAS0jCAQAAAABwCUk4AAAAAAAuIQkHAAAAAMAl/x9xUBDANtuARQAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from tqdm import tqdm\n", - "\n", - "n_test_batch = 50\n", - "n_test_batches = len(x_test) // n_test_batch\n", - "\n", - "# Make two plots side by side for 0 and 1 idx parameters\n", - "\n", - "plt.figure(figsize=(12, 6))\n", - "\n", - "fig, ax = plt.subplots(1, 2, figsize=(12, 6))\n", - "\n", - "mse_list = []\n", - "\n", - "for i in tqdm(range(n_test_batches)):\n", - "\n", - " # TODO: jit/pmap\n", - " graph = build_graph(x_test[i * n_test_batch:(i + 1) * n_test_batch], \n", - " None, \n", - " k=k, \n", - " use_edges=True, \n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " )\n", - "\n", - " \n", - " omega_m_pred = jax.jit(model.apply)(unreplicate(pstate).params, graph)\n", - "\n", - " ax[0].scatter(params_test[i * n_test_batch:(i + 1) * n_test_batch, 0], omega_m_pred[:, 0], s=10, color='firebrick')\n", - " ax[1].scatter(params_test[i * n_test_batch:(i + 1) * n_test_batch, 1], omega_m_pred[:, 1], s=10, color='firebrick')\n", - "\n", - " mse_list.append(loss_mse(omega_m_pred, params_test[i * n_test_batch:(i + 1) * n_test_batch]))\n", - "\n", - "print(f\"Mean MSE: {np.mean(mse_list)}\")\n", - " \n", - "ax[0].plot(params_test[:n_test_batch, 0], params_test[:n_test_batch, 0], color='gray')\n", - "ax[1].plot(params_test[:n_test_batch, 1], params_test[:n_test_batch, 1], color='gray')\n", - "\n", - "plt.xlabel(\"True\")\n", - "plt.ylabel(\"Predicted\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "equivariant", - "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.9" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/benchmarks/galaxies/node_prediction.ipynb b/benchmarks/galaxies/node_prediction.ipynb deleted file mode 100644 index 3d29167..0000000 --- a/benchmarks/galaxies/node_prediction.ipynb +++ /dev/null @@ -1,390 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "sys.path.append('../../')" - ] - }, - { - "cell_type": "code", - "execution_count": 224, - "metadata": {}, - "outputs": [], - "source": [ - "from functools import partial\n", - "\n", - "import numpy as np\n", - "import jax\n", - "import jax.numpy as jnp\n", - "import flax\n", - "import flax.linen as nn\n", - "from flax.training.train_state import TrainState\n", - "import jraph\n", - "\n", - "from models.gnn import GNN\n", - "from models.segnn import SEGNN\n", - "from models.utils.graph_utils import build_graph\n", - "\n", - "import optax\n", - "from tqdm import trange\n", - "\n", - "replicate = flax.jax_utils.replicate\n", - "unreplicate = flax.jax_utils.unreplicate" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1800, 5000, 6)" - ] - }, - "execution_count": 91, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "n_nodes = 5000\n", - "n_features = 6\n", - "\n", - "x_train = np.load(\"../../../hierarchical-encdec/data/set_diffuser_data/train_halos.npy\")[:, :n_nodes, :n_features]\n", - "x_train = x_train / 1000.\n", - "\n", - "# Conver to jnp\n", - "x_train = jnp.array(x_train)\n", - "\n", - "x_train.shape" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Node prediction task -- randomly knock out 10% of the velocities, and try to predict them." - ] - }, - { - "cell_type": "code", - "execution_count": 326, - "metadata": {}, - "outputs": [], - "source": [ - "import e3nn_jax as e3nn\n", - "from models.utils.equivariant_graph_utils import get_equivariant_graph\n", - "from models.utils.graph_utils import build_graph\n", - "from models.utils.irreps_utils import weight_balanced_irreps\n", - "from models.segnn import SEGNN\n", - "from models.utils.graph_utils import get_apply_pbc\n", - "\n", - "class GraphWrapper(nn.Module):\n", - " @nn.compact\n", - " def __call__(self, x): \n", - " return jax.vmap(GNN(task=\"node\", d_output=3))(x)\n", - " \n", - "class GraphWrapper(nn.Module):\n", - "\n", - " @nn.compact\n", - " def __call__(self, x):\n", - "\n", - " positions = e3nn.IrrepsArray(\"1o\", x.nodes[..., :3])\n", - " \n", - " if x.nodes.shape[-1] == 3:\n", - " nodes = e3nn.IrrepsArray(\"1o\", x.nodes[..., :])\n", - " velocities = None\n", - " else:\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o\", x.nodes[..., :])\n", - " velocities = e3nn.IrrepsArray(\"1o\", x.nodes[..., 3:6])\n", - "\n", - " # print(nodes)\n", - " \n", - " st_graph = get_equivariant_graph(\n", - " node_features=nodes,\n", - " positions=positions,\n", - " velocities=velocities,\n", - " steerable_velocities=True,\n", - " senders=x.senders,\n", - " receivers=x.receivers,\n", - " n_node=x.n_node,\n", - " n_edge=x.n_edge,\n", - " globals=x.globals,\n", - " edges=None,\n", - " lmax_attributes=2,\n", - " apply_pbc=None\n", - " )\n", - " \n", - " return jax.vmap(SEGNN(task=\"node\", output_irreps=\"1x1o\", num_blocks=2, l_max_hidden=2))(st_graph)" - ] - }, - { - "cell_type": "code", - "execution_count": 327, - "metadata": {}, - "outputs": [], - "source": [ - "graph = build_graph(\n", - " halos=x_train[:2, :, :],\n", - " tpcfs=None,\n", - " k=20,\n", - " use_edges=True,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 328, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "78252" - ] - }, - "execution_count": 328, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model = GraphWrapper()\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "sum(x.size for x in jax.tree_util.tree_leaves(params))" - ] - }, - { - "cell_type": "code", - "execution_count": 329, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(2, 5000, 3)\n" - ] - } - ], - "source": [ - "print(out.nodes.shape)" - ] - }, - { - "cell_type": "code", - "execution_count": 330, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4 GPUs available\n" - ] - } - ], - "source": [ - "# Devices\n", - "num_local_devices = jax.local_device_count()\n", - "print(f\"{num_local_devices} GPUs available\")" - ] - }, - { - "cell_type": "code", - "execution_count": 331, - "metadata": {}, - "outputs": [], - "source": [ - "# Define train state and replicate across devices\n", - "tx = optax.adamw(learning_rate=6e-4, weight_decay=1e-5)\n", - "state = TrainState.create(apply_fn=model.apply, params=params, tx=tx)\n", - "pstate = replicate(state)" - ] - }, - { - "cell_type": "code", - "execution_count": 332, - "metadata": {}, - "outputs": [], - "source": [ - "def loss_mse(pred_batch, halo_batch, mask):\n", - " # Only compute MSE based on mask (values which are 1)\n", - " if isinstance(pred_batch, e3nn.IrrepsArray):\n", - " pred_batch = pred_batch.array # Euclidean distance is preserved by MSE, so we are safe doing this\n", - "\n", - " return jnp.sum(jnp.where(mask, (pred_batch - halo_batch[..., 3:6]) ** 2, 0.))\n", - "\n", - "@partial(jax.pmap, axis_name=\"batch\",)\n", - "def train_step(state, halo_batch_masked, halo_batch, mask):\n", - "\n", - " # Set those velocities in x_batch (only indices 3:6 of last dimension of x_batch) to 0\n", - " halo_graph = build_graph(halo_batch_masked, \n", - " None, \n", - " k=20, \n", - " )\n", - "\n", - " def loss_fn(params):\n", - " outputs = state.apply_fn(params, halo_graph)\n", - " loss = loss_mse(outputs.nodes, halo_batch, mask)\n", - " return loss\n", - "\n", - " # Get loss, grads, and update state\n", - " loss, grads = jax.value_and_grad(loss_fn)(state.params)\n", - " grads = jax.lax.pmean(grads, \"batch\")\n", - " new_state = state.apply_gradients(grads=grads)\n", - " metrics = {\"loss\": jax.lax.pmean(loss, \"batch\")}\n", - " \n", - " return new_state, metrics" - ] - }, - { - "cell_type": "code", - "execution_count": 333, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/2000 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "# plt.plot(train_loss_gnn, label=\"GNN\")\n", - "# plt.plot(train_loss_segnn, label=\"SEGNN, lmax=1\")\n", - "# plt.plot(train_loss_segnn_l2, label=\"SEGNN, lmax=2\")\n", - "# plt.plot(train_loss_gnn_shuffled, label=\"GNN, shuffled\")\n", - "\n", - "# Smoothed versions\n", - "ds = 10\n", - "plt.plot(np.convolve(train_loss_gnn, np.ones(ds)/ds, mode='valid'), label=\"GNN\")\n", - "plt.plot(np.convolve(train_loss_segnn, np.ones(ds)/ds, mode='valid'), label=\"SEGNN, lmax=1\")\n", - "plt.plot(np.convolve(train_loss_segnn_l2, np.ones(ds)/ds, mode='valid'), label=\"SEGNN, lmax=2\")\n", - "plt.plot(np.convolve(train_loss_gnn_shuffled, np.ones(ds)/ds, mode='valid'), label=\"GNN, shuffled\")\n", - "\n", - "plt.legend()\n", - "plt.ylim(300, 1500)\n", - "plt.xlabel(\"Steps\")\n", - "plt.ylabel(\"SE of predicted velocities\")\n", - "\n", - "plt.title(\"Predict 10% missing velocities\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "equivariant", - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/benchmarks/galaxies/node_prediction_vperp.ipynb b/benchmarks/galaxies/node_prediction_vperp.ipynb deleted file mode 100644 index b62ad33..0000000 --- a/benchmarks/galaxies/node_prediction_vperp.ipynb +++ /dev/null @@ -1,362 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "sys.path.append('../../')" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from functools import partial\n", - "\n", - "import numpy as np\n", - "import jax\n", - "import jax.numpy as jnp\n", - "import flax\n", - "import flax.linen as nn\n", - "from flax.training.train_state import TrainState\n", - "import jraph\n", - "\n", - "from models.gnn import GNN\n", - "from models.segnn import SEGNN\n", - "from models.utils.graph_utils import build_graph\n", - "\n", - "import optax\n", - "from tqdm import trange\n", - "\n", - "replicate = flax.jax_utils.replicate\n", - "unreplicate = flax.jax_utils.unreplicate" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1800, 5000, 6)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "n_nodes = 5000\n", - "n_features = 6\n", - "\n", - "x_train = np.load(\"../../../hierarchical-encdec/data/set_diffuser_data/train_halos.npy\")[:, :n_nodes, :n_features]\n", - "x_train = x_train / 1000.\n", - "\n", - "# Conver to jnp\n", - "x_train = jnp.array(x_train)\n", - "\n", - "x_train.shape" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Node prediction task -- randomly knock out 10% of the velocities, and try to predict them." - ] - }, - { - "cell_type": "code", - "execution_count": 172, - "metadata": {}, - "outputs": [], - "source": [ - "import e3nn_jax as e3nn\n", - "from models.utils.equivariant_graph_utils import get_equivariant_graph\n", - "from models.utils.graph_utils import build_graph\n", - "from models.utils.irreps_utils import weight_balanced_irreps\n", - "from models.segnn import SEGNN\n", - "from models.utils.graph_utils import get_apply_pbc\n", - "\n", - "# class GraphWrapper(nn.Module):\n", - "# @nn.compact\n", - "# def __call__(self, x): \n", - "# return jax.vmap(GNN(task=\"node\", d_output=2))(x)\n", - " \n", - "class GraphWrapper(nn.Module):\n", - "\n", - " @nn.compact\n", - " def __call__(self, x):\n", - "\n", - " positions = e3nn.IrrepsArray(\"1o\", x.nodes[..., :3])\n", - " nodes = e3nn.IrrepsArray(\"1o + 1x0e\", x.nodes[..., :4])\n", - " velocities = e3nn.IrrepsArray(\"1x0e\", x.nodes[..., 3:])\n", - " \n", - " st_graph = get_equivariant_graph(\n", - " node_features=nodes,\n", - " positions=positions,\n", - " velocities=velocities,\n", - " steerable_velocities=False,\n", - " senders=x.senders,\n", - " receivers=x.receivers,\n", - " n_node=x.n_node,\n", - " n_edge=x.n_edge,\n", - " globals=x.globals,\n", - " edges=None,\n", - " lmax_attributes=1,\n", - " apply_pbc=None\n", - " )\n", - " \n", - " return jax.vmap(SEGNN(task=\"node\", output_irreps=\"1x1o\", num_blocks=3, l_max_hidden=1, message_passing_agg=\"sum\", scalar_activation=\"silu\"))(st_graph)" - ] - }, - { - "cell_type": "code", - "execution_count": 173, - "metadata": {}, - "outputs": [], - "source": [ - "graph = build_graph(\n", - " halos=x_train[:2, :, :4],\n", - " tpcfs=None,\n", - " k=20,\n", - " use_edges=True,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 174, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "73300" - ] - }, - "execution_count": 174, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model = GraphWrapper()\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "sum(x.size for x in jax.tree_util.tree_leaves(params))" - ] - }, - { - "cell_type": "code", - "execution_count": 175, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(2, 5000, 3)\n" - ] - } - ], - "source": [ - "print(out.nodes.shape)" - ] - }, - { - "cell_type": "code", - "execution_count": 176, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4 GPUs available\n" - ] - } - ], - "source": [ - "# Devices\n", - "num_local_devices = jax.local_device_count()\n", - "print(f\"{num_local_devices} GPUs available\")" - ] - }, - { - "cell_type": "code", - "execution_count": 177, - "metadata": {}, - "outputs": [], - "source": [ - "# Define train state and replicate across devices\n", - "tx = optax.adamw(learning_rate=6e-4, weight_decay=1e-5)\n", - "state = TrainState.create(apply_fn=model.apply, params=params, tx=tx)\n", - "pstate = replicate(state)" - ] - }, - { - "cell_type": "code", - "execution_count": 178, - "metadata": {}, - "outputs": [], - "source": [ - "def loss_mse(pred_batch, halo_batch):\n", - " # Only compute MSE based on mask (values which are 1)\n", - " if isinstance(pred_batch, e3nn.IrrepsArray):\n", - " pred_batch = pred_batch.array[..., :2] # Euclidean distance is preserved by MSE, so we are safe doing this\n", - "\n", - " return jnp.sum((pred_batch - halo_batch[..., 4:6]) ** 2)\n", - "\n", - "@partial(jax.pmap, axis_name=\"batch\",)\n", - "def train_step(state, halo_batch):\n", - "\n", - " # Set those velocities in x_batch (only indices 3:6 of last dimension of x_batch) to 0\n", - " halo_graph = build_graph(halo_batch[..., :4], \n", - " None, \n", - " k=20, \n", - " )\n", - "\n", - " def loss_fn(params):\n", - " outputs = state.apply_fn(params, halo_graph)\n", - " loss = loss_mse(outputs.nodes, halo_batch)\n", - " return loss\n", - "\n", - " # Get loss, grads, and update state\n", - " loss, grads = jax.value_and_grad(loss_fn)(state.params)\n", - " grads = jax.lax.pmean(grads, \"batch\")\n", - " new_state = state.apply_gradients(grads=grads)\n", - " metrics = {\"loss\": jax.lax.pmean(loss, \"batch\")}\n", - " \n", - " return new_state, metrics" - ] - }, - { - "cell_type": "code", - "execution_count": 179, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/2500 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "# Smoothed versions\n", - "ds = 1\n", - "plt.plot(np.convolve(train_loss_gnn, np.ones(ds)/ds, mode='valid'), label=\"GNN\")\n", - "plt.plot(np.convolve(train_loss_segnn, np.ones(ds)/ds, mode='valid'), label=\"SEGNN, lmax=1\")\n", - "plt.plot(np.convolve(train_loss_segnn_2, np.ones(ds)/ds, mode='valid'), label=\"SEGNN, config2\")\n", - "\n", - "plt.legend()\n", - "plt.xlabel(\"Steps\")\n", - "plt.ylabel(\"SE of predicted velocities\")\n", - "\n", - "plt.ylim(5000, 10000)\n", - "# plt.xlim(0, 2500)\n", - "plt.title(\"Predict $v_{\\perp}$\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "equivariant", - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/benchmarks/galaxies/pooling_debugging.ipynb b/benchmarks/galaxies/pooling_debugging.ipynb deleted file mode 100644 index 47fd3a7..0000000 --- a/benchmarks/galaxies/pooling_debugging.ipynb +++ /dev/null @@ -1,957 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], - "source": [ - "import sys\n", - "sys.path.append(\"../../\")\n", - "\n", - "from dataset_large import get_halo_dataset\n", - "from tqdm import tqdm\n", - "import numpy as np\n", - "\n", - "# Make sure tf does not hog all the GPU memory\n", - "import tensorflow as tf\n", - "\n", - "# Ensure TF does not see GPU and grab all GPU memory\n", - "tf.config.experimental.set_visible_devices([], \"GPU\")\n", - "\n", - "%load_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of samples: 500\n" - ] - } - ], - "source": [ - "features = ['x', 'y', 'z'] # ['x', 'y', 'z', 'Jx', 'Jy', 'Jz', 'vx', 'vy', 'vz', 'M200c']\n", - "params = ['Omega_m', 'sigma_8'] # ['Omega_m', 'Omega_b', 'h', 'n_s', 'sigma_8']\n", - "batch_size = 64\n", - "\n", - "dataset, num_total, mean, std, mean_params, std_params = get_halo_dataset(batch_size=batch_size, # Batch size\n", - " num_samples=500, # If not None, will only take a subset of the dataset\n", - " split='train', # 'train', 'val'\n", - " standardize=True, # If True, will standardize the features\n", - " return_mean_std=True, # If True, will return (dataset, num_total, mean, std, mean_params, std_params), else (dataset, num_total)\n", - " seed=42, # Random seed\n", - " features=features, # Features to include\n", - " params=params # Parameters to include\n", - " )\n", - "\n", - "std = np.array(std)\n", - "\n", - "# Print number of samples\n", - "print(f\"Number of samples: {num_total}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 7/7 [00:00<00:00, 33.80it/s]\n" - ] - } - ], - "source": [ - "iterator = iter(dataset)\n", - "\n", - "x_train, params_train = [], []\n", - "for _ in tqdm(range(num_total // batch_size)):\n", - " x, params = next(iterator)\n", - " x_train.append(np.array(x))\n", - " params_train.append(np.array(params))\n", - "\n", - "x_train = np.concatenate(x_train, axis=0)\n", - "params_train = np.concatenate(params_train, axis=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "# x_train = np.load(\"../../../BNN_SBI/data/set_diffuser_data/train_halos.npy\")[..., :3] / 1000.\n", - "\n", - "# import pandas as pd\n", - "# params_train = pd.read_csv(\"../../../BNN_SBI/data/set_diffuser_data/train_cosmology.csv\",)\n", - "# params_train = params_train[[\"Omega_m\", \"sigma_8\"]].values\n", - "\n", - "# # Normalize and get std\n", - "\n", - "# mean = np.mean(x_train, axis=(0, 1))\n", - "# std = np.std(x_train, axis=(0, 1))\n", - "\n", - "# x_train = (x_train - mean) / std\n", - "\n", - "# # Normalize params\n", - "# mean_params = np.mean(params_train, axis=0)\n", - "# std_params = np.std(params_train, axis=0)\n", - "\n", - "# params_train = (params_train - mean_params) / std_params" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "import flax\n", - "from flax.training.train_state import TrainState\n", - "from functools import partial\n", - "import flax.linen as nn\n", - "import optax\n", - "from tqdm import trange\n", - "\n", - "replicate = flax.jax_utils.replicate\n", - "unreplicate = flax.jax_utils.unreplicate" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [], - "source": [ - "from models.utils.equivariant_graph_utils import get_equivariant_graph\n", - "from models.utils.graph_utils import build_graph, compute_distances, nearest_neighbors\n", - "from models.segnn import SEGNN\n", - "from models.gnn import GNN\n", - "from models.utils.graph_utils import get_apply_pbc" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.68722886" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "_, _, distances = nearest_neighbors(x_train[0], 20)\n", - "np.sqrt(np.sum(distances ** 2, axis=-1)).max()" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.43053427" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "_, _, distances = nearest_neighbors(x_train[0], 20, apply_pbc=get_apply_pbc(std=std / 1000.,))\n", - "np.sqrt(np.sum(distances ** 2, axis=-1)).max()" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(array([ 67., 41., 40., 56., 105., 154., 186., 213., 112., 26.]),\n", - " array([1.73205081e-07, 4.02442031e-02, 8.04882273e-02, 1.20732255e-01,\n", - " 1.60976291e-01, 2.01220319e-01, 2.41464347e-01, 2.81708360e-01,\n", - " 3.21952403e-01, 3.62196416e-01, 4.02440459e-01]),\n", - " [])" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "plt.hist(build_graph(x_train[:1], None, 20, n_radial_basis=0, apply_pbc=None).edges.flatten()[:1000], histtype='step')\n", - "plt.hist(build_graph(x_train[:1], None, 20, n_radial_basis=0, apply_pbc=get_apply_pbc(std=std / 1000.,)).edges.flatten()[:1000], histtype='step')" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Array(0.43053427, dtype=float32)" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "build_graph(x_train[:1], None, 20, n_radial_basis=0, apply_pbc=get_apply_pbc(std=std / 1000.,)).edges.max()" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Array(5.8868947, dtype=float32)" - ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "compute_distances(x_train[0],).max()" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "65x0e+21x1o" - ] - }, - "execution_count": 97, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from models.utils.irreps_utils import balanced_irreps\n", - "balanced_irreps(1, 128, True)" - ] - }, - { - "cell_type": "code", - "execution_count": 463, - "metadata": {}, - "outputs": [], - "source": [ - "import e3nn_jax as e3nn\n", - "from typing import Dict\n", - "import jax\n", - "from models.gnn import GNN\n", - "from models.segnn import SEGNN\n", - "from models.egnn import EGNN\n", - "from models.nequip import NequIP\n", - "\n", - "use_pbcs = True\n", - "apply_pbc = get_apply_pbc(std=std / 1000.,) if use_pbcs else None\n", - "k = 10\n", - "n_radial = 64\n", - "position_features = True\n", - "r_max = 0.6\n", - "use_3d_distances = False\n", - "l_max = 1\n", - "# TODO: sphharm norm parity between SEGNN and NequIP\n", - "\n", - "SEGNN_PARAMS = {\n", - " \"d_hidden\": 128,\n", - " \"l_max_hidden\": l_max,\n", - " \"n_layers\": 3,\n", - " \"message_passing_steps\": 3,\n", - " \"task\": \"graph\",\n", - " \"output_irreps\": e3nn.Irreps(\"1x0e\"),\n", - " \"hidden_irreps\": None,\n", - " \"message_passing_agg\": \"mean\",\n", - " \"readout_agg\": \"mean\",\n", - " \"n_outputs\": 2,\n", - " \"scalar_activation\": \"gelu\",\n", - " \"gate_activation\": \"sigmoid\",\n", - " \"mlp_readout_widths\": (4, 2, 2),\n", - " \"residual\": False,\n", - "}\n", - "\n", - "GNN_PARAMS = {\n", - " \"d_hidden\": 128,\n", - " \"message_passing_steps\": 3,\n", - " \"n_layers\": 3,\n", - " \"activation\": \"gelu\",\n", - " \"message_passing_agg\": \"mean\",\n", - " \"readout_agg\": \"mean\",\n", - " \"mlp_readout_widths\": (4, 2, 2),\n", - " \"task\": \"graph\",\n", - " \"n_outputs\": 2,\n", - " \"norm\": \"none\",\n", - " \"position_features\": position_features,\n", - " \"residual\": False,\n", - "}\n", - "\n", - "\n", - "class GraphWrapper(nn.Module):\n", - " param_dict: Dict\n", - "\n", - " @nn.compact\n", - " def __call__(self, x):\n", - "\n", - " positions = e3nn.IrrepsArray(\"1o\", x.nodes[..., :3])\n", - " \n", - " if x.nodes.shape[-1] == 3:\n", - " nodes = e3nn.IrrepsArray(\"1o\", x.nodes[..., :])\n", - " velocities = None\n", - " else:\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o\", x.nodes[..., :])\n", - " velocities = e3nn.IrrepsArray(\"1o\", x.nodes[..., 3:6])\n", - "\n", - " \n", - " st_graph = get_equivariant_graph(\n", - " node_features=nodes,\n", - " positions=positions,\n", - " velocities=None,\n", - " steerable_velocities=False,\n", - " senders=x.senders,\n", - " receivers=x.receivers,\n", - " n_node=x.n_node,\n", - " n_edge=x.n_edge,\n", - " globals=x.globals,\n", - " edges=None,\n", - " lmax_attributes=l_max,\n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " )\n", - " \n", - " return jax.vmap(SEGNN(**self.param_dict))(st_graph)\n", - " \n", - "class GraphWrapperGNN(nn.Module):\n", - " param_dict: Dict\n", - " @nn.compact\n", - " def __call__(self, x):\n", - " return jax.vmap(GNN(**self.param_dict))(x)\n", - " \n", - "class GraphWrapperEGNN(nn.Module):\n", - " param_dict: Dict\n", - " @nn.compact\n", - " def __call__(self, x):\n", - " return jax.vmap(EGNN(positions_only=True, n_outputs=2, n_layers=4, apply_pbc=apply_pbc, n_radial_basis=n_radial, r_max=r_max, tanh_out=True))(x)\n", - " \n", - "import jraph\n", - "import jax.numpy as jnp\n", - "\n", - "class GraphWrapperNequIP(nn.Module):\n", - " param_dict: Dict\n", - " @nn.compact\n", - " def __call__(self, x):\n", - " if x.nodes.shape[-1] == 3:\n", - " ones = jnp.ones(x.nodes[..., :].shape[:2] + (1,))\n", - " nodes = jnp.concatenate([x.nodes[..., :], x.nodes[..., :], ones], axis=-1)\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o + 1x0e\", nodes)\n", - " else:\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o + 1x0e\", x.nodes[..., :])\n", - " \n", - " graph = jraph.GraphsTuple(\n", - " n_node=x.n_node,\n", - " n_edge=x.n_edge,\n", - " edges=None,\n", - " globals=x.globals,\n", - " nodes=nodes, \n", - " senders=x.senders,\n", - " receivers=x.receivers)\n", - " \n", - " return jax.vmap(NequIP(n_outputs=2, n_radial_basis=n_radial, r_cutoff=r_max, sphharm_norm='component'))(graph)" - ] - }, - { - "cell_type": "code", - "execution_count": 464, - "metadata": {}, - "outputs": [], - "source": [ - "graph = build_graph(x_train[:2], \n", - " None, \n", - " k=k, \n", - " apply_pbc=apply_pbc,\n", - " use_edges=True, \n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " use_3d_distances=use_3d_distances,\n", - ")\n", - "\n", - "model = GraphWrapper(SEGNN_PARAMS, )\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "\n", - "# Number of parameters\n", - "print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n", - "\n", - "out" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# model = GraphWrapperGNN(GNN_PARAMS)\n", - "\n", - "# out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "\n", - "# # Number of parameters\n", - "# print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n", - "\n", - "# out" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of parameters: 437554\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/tmp/ipykernel_3792805/4071777609.py:6: DeprecationWarning: jax.tree_leaves is deprecated: use jax.tree.leaves (jax v0.4.25 or newer) or jax.tree_util.tree_leaves (any JAX version).\n", - " print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n" - ] - }, - { - "data": { - "text/plain": [ - "Array([[ 0.00021333, 0.00200208],\n", - " [ 0.00073536, -0.00076745]], dtype=float32)" - ] - }, - "execution_count": 455, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model = GraphWrapperEGNN({})\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "\n", - "# Number of parameters\n", - "print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n", - "\n", - "out" - ] - }, - { - "cell_type": "code", - "execution_count": 456, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of parameters: 388992\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/tmp/ipykernel_3792805/1302920410.py:6: DeprecationWarning: jax.tree_leaves is deprecated: use jax.tree.leaves (jax v0.4.25 or newer) or jax.tree_util.tree_leaves (any JAX version).\n", - " print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n" - ] - }, - { - "data": { - "text/plain": [ - "Array([[-11.465982 , 2.9736307 ],\n", - " [ -8.782197 , -0.79811597]], dtype=float32)" - ] - }, - "execution_count": 456, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model = GraphWrapperNequIP(SEGNN_PARAMS)\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "\n", - "# Number of parameters\n", - "print(f\"Number of parameters: {sum([p.size for p in jax.tree_leaves(params)])}\")\n", - "\n", - "out" - ] - }, - { - "cell_type": "code", - "execution_count": 457, - "metadata": {}, - "outputs": [], - "source": [ - "# from models.transformer import Transformer\n", - "\n", - "# model = Transformer(task=\"graph\", n_outputs=2, induced_attention=True, n_inducing_points=256, readout_agg=\"attn\")\n", - "\n", - "# rng = jax.random.PRNGKey(0)\n", - "# out, params = model.init_with_output(rng, x_train[:2])\n", - "\n", - "# out" - ] - }, - { - "cell_type": "code", - "execution_count": 458, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4 GPUs available\n" - ] - } - ], - "source": [ - "# Devices\n", - "num_local_devices = jax.local_device_count()\n", - "print(f\"{num_local_devices} GPUs available\")" - ] - }, - { - "cell_type": "code", - "execution_count": 459, - "metadata": {}, - "outputs": [], - "source": [ - "# Define train state and replicate across devices\n", - "\n", - "# Cosine learning rate schedule\n", - "lr = optax.cosine_decay_schedule(3e-4, 2000)\n", - "# lr = optax.warmup_cosine_decay_schedule(\n", - "# init_value=0.0,\n", - "# peak_value=3e-4,\n", - "# warmup_steps=500,\n", - "# decay_steps=5000,\n", - "# )\n", - "\n", - "# lr = optax.linear_onecycle\"_schedule(5000, 3e-4)\n", - "tx = optax.adamw(learning_rate=lr, weight_decay=1e-5)\n", - "state = TrainState.create(apply_fn=model.apply, params=params, tx=tx)\n", - "pstate = replicate(state)" - ] - }, - { - "cell_type": "code", - "execution_count": 460, - "metadata": {}, - "outputs": [], - "source": [ - "def loss_mse(pred_batch, cosmo_batch,):\n", - " return np.mean((pred_batch - cosmo_batch) ** 2)\n", - "\n", - "@partial(jax.pmap, axis_name=\"batch\",)\n", - "def train_step(state, halo_batch, cosmo_batch,):\n", - "\n", - " halo_graph = build_graph(halo_batch, \n", - " None, \n", - " k=k, \n", - " use_edges=True, \n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " use_3d_distances=use_3d_distances,\n", - " )\n", - " \n", - " def loss_fn(params):\n", - " outputs = state.apply_fn(params, halo_graph)\n", - " loss = loss_mse(outputs, cosmo_batch)\n", - " return loss\n", - "\n", - " # Get loss, grads, and update state\n", - " loss, grads = jax.value_and_grad(loss_fn)(state.params)\n", - " grads = jax.lax.pmean(grads, \"batch\")\n", - " new_state = state.apply_gradients(grads=grads)\n", - " metrics = {\"loss\": jax.lax.pmean(loss, \"batch\")}\n", - " \n", - " return new_state, metrics" - ] - }, - { - "cell_type": "code", - "execution_count": 461, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/2000 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+EAAAINCAYAAABRSH6rAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAACprElEQVR4nOzde1gU9f4H8PdyETQUIUXU8JIWZRZ48p6lHVBYTIQQUzMtS8yTZip5SY+WVPwwI06lUWihFUK2QglIomFleei66cky9GhrJWvpCqJyn98fxh6Q2y7M7Mzsvl/P4/PIMjv72QXmO5/v5fPVCIIggIiIiIiIiIgk5yR3AERERERERESOgkk4ERERERERkY0wCSciIiIiIiKyESbhRERERERERDbCJJyIiIiIiIjIRpiEExEREREREdkIk3AiIiIiIiIiG2ESTkRERERERGQjLnIHILba2lr8/vvv6Ny5MzQajdzhEBERQRAEXLhwAb169YKTE/u/xcD2noiIlMSatt7ukvDff/8dfn5+codBRETUyKlTp3DdddfJHYZdYHtPRERKZElbb3dJeOfOnQFcefNdunSRORoiIiKgtLQUfn5+5jaK2o/tPRERKYk1bb3dJeF1U9K6dOnCRpmIiBSF06bFw/aeiIiUyJK2ngvTiIiIiIiIiGyESTgRERERERGRjTAJJyIiIiIiIrIRJuFERERERERENsIknIiIiIiIiMhGmIQTERERERER2QiTcCIiIiIiIiIbYRJOREREREREZCNMwomIiIiIiIhshEk4ERERERERkY0wCSciIiIiIiKyESbhRERERERERDbCJJyIiIiIiIjIRpiEExEREREREdmIpEn4p59+ikmTJqFXr17QaDTIyspq8fj9+/dDo9E0+ldcXCxlmEREREREREQ2IWkSfvHiRQQEBGDjxo1WPe/o0aM4ffq0+Z+Pj49EERIREREREZHYTHo9TmVmwqTXyx2K4rhIeXKtVgutVmv183x8fNC1a1fxAyIiIruVk5MDFxcXhISEiHI+k16PshMn4NG/P7wCA0U5JxERkSM4kpCA42+8Yf56QEwMBi1fLmNEyqLINeGBgYHo2bMnxo8fj88//7zFYysqKlBaWtrgHxEROZaCggJERUVh0qRJ+Pe//93u8x1JSMCBqCjoY2NxICoKRxISRIiSiIjI/pn0+gYJ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qqursX//fhw/fhwzZsxA586d8fvvv6NLly7w8PCQ9LVtie29YxDrXkKtCZTJZMKdd96JH374ATfffDMOHDgAb29vucOSlFp/VtQ8RyluZ027xOnoJAkpE9r2nLu557Zlj862qqmpwaxZs5CdnQ13d3dkZ2fjmo8/xgE77x0kIun98ssvCA0NhcFgQEVFBcaPH4/OnTsjISEBFRUVSE5OljtEIouJdS+h1hG48vJyRERE4IcffkCvXr2Ql5dn9wk4oMz6CVIM/jgSpa73lxOro5PopKxu2Z5zt/RcW1W+FAQB8+fPR3p6OlxcXKDT6XCbp6ciq4ESkfosWrQIQ4cOhclkajBdNTIyEvv27ZMxMiLriHUvodSK262pqanBAw88gE8//RRdunTB7t270adPH7nDckhHEhJwICoK+thYHIiKwpGEBJs8154odb2/nJiEk+ikTGjbc+6WnmuLi4MgCIiNjUVKSgqcnJyQlpaGsLAwbn1BRKL57LPPsHr1anTo0KHB4/369cNvv/0mU1RE1hOrbVRjGysIAhYvXoz3338fHTp0QFZWFm677Ta5w3JIUg3+OBprtuFzFEzCSXTNJa5/HDgg2bktSZZbeq4tLg5xcXFITEwEAKSkpCA6OrrVuIiIrFFbW4uamppGj//666/o3LmzDBERtY1YbaMa29gXXngBr7zyCgBg27ZtuPvuu2WOyHFJNfjjiAYtX44xOh0CN2zAGJ1OMQX35MIknETnFRiI3hERjR7/LSur3b1/7UmWW3uulBeHpKQkrF271vz/OXPmWBwXEZGlJkyYgKSkJPPXGo0GZWVlWLt2LcLCwuQLjMhKYrWNamtj33nnHSz/a716YmIi7rvvPpkjcmxSDf44Kq/AQPhFRir278+WWB2dJHEqMxP62NhGjwdu2AC/yMh2n19NBTK2bNmCRx55BMCV0fDVq1crIi4ish1btU2nTp1CaGgoBEFAUVERhg4diqKiInTr1g2ffvopfHx8JHttW2N77xgcqTp6fn4+wsLCUF1djSVLluDFF1+UOyRC+7ZNU/KWayQ+blHGRll2jrIVQWsyMjIwffp083rw9evXQ6PRqOJmgIjEY+styjIyMvD999+jrKwMf/vb33D//ferdl/h5rC9J3vy3Xff4a677kJZWRmmTZuGd999F05OnLCqFGoa/CH5MAlno6wIjt77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xYMPPtjiMddffz18fX1x5syZBo9XV1fj3LlzVq33HjFiBADg2LFjzSbhK1euxJIlS8xfl5aWclcLG3KUTllBELBw4UJkZWXBzc0NH374IW655Ra5wyIiO8MknBTFkilvzR1z9ZT03hER2Lp/P9auXQsASEpKwpw5cwBIV3SMxcyIyB50794d3bt3b/W4UaNG4fz58/jmm29w++23A7iylVNtba05sbaE/q/aHj179mz2GDc3N7i5uVl8ThKfI3TKPv/883jttdeg0Wjw7rvv4s4775Q7JCKyQyzMRopSN+WtvqunvDV3zN9efBG9IyLMj721bRsWL14MAFi3bh0WLVpk/p5U69sccd0cETmum2++GaGhoZg7dy6+/PJLfP7551iwYAGmTZtmroz+22+/4aabbsKXX34JADh+/Dji4uLwzTff4OTJk/jwww8xa9Ys3HXXXbjtttvkfDvk4FJTU7F69WoAwMsvv4yoqCiZIyIie8WRcFIcS6a8NXWMSa83j4R/VlaGjX/+CQBYMGuWuVGtI9X6NkdbN0dE9O6772LBggUICgqCk5MToqKi8PLLL5u/X1VVhaNHj5qrn3fo0AF79+5FUlISLl68CD8/P0RFRTW6ThPZ0u7du/HII48AAJYvX44FCxbIHBER2TONIAiC3EGIqbS0FJ6enigpKUGXLl3kDods6FRmJvSxsfjq0iU8X1yMGgAhnTvjjdRU9Ln33iafw+roRGQLbJvEZw+fKdsKZfjqq68wbtw4XLp0CQ888AC2bt0KjUYjd1hEpDLWtEscCSe74dG/Pw5fvowEoxE1AMZ6eODRbt3Q+frrm32OVOvbHGHdHBERtZ097aShZsePH8fEiRNx6dIlTJgwAZs3b2YCTkSS45pwshtFlZV47uxZVAoChnfqhEXdu+PGRx9VZTJs0utxKjMTpr+KFRERkf1obicNXvNt68yZMwgJCcEff/yBIUOG4P3330eHDh3kDouIHABHwskuHD58GKGhobhUWYmxw4cjZckSdPP3V2UCztERIiL7JtdOGpz+/j9lZWWYOHEijh8/jv79+yM3NxedO3eWO6wG+PMisl9MwlvBC6DyFRUVYfz48TCZTBg5ciSy8/Ph4eHR7PFK/pna0z7jSv6ciYjkJMdOGuzg/Z+qqipMnToVX3/9Na699lrk5eVZta+9LfDnRWTfmIS3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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "features = ['x', 'y', 'z'] # ['x', 'y', 'z', 'Jx', 'Jy', 'Jz', 'vx', 'vy', 'vz', 'M200c']\n", - "params = ['Omega_m', 'sigma_8'] # ['Omega_m', 'Omega_b', 'h', 'n_s', 'sigma_8']\n", - "\n", - "dataset, num_total = get_halo_dataset(batch_size=50, # Batch size\n", - " num_samples=250, # If not None, will only take a subset of the dataset\n", - " split='val', # 'train', 'val'\n", - " standardize=True, # If True, will standardize the features\n", - " return_mean_std=False, # If True, will return (dataset, num_total, mean, std, mean_params, std_params), else (dataset, num_total)\n", - " seed=42, # Random seed\n", - " features=features, # Features to include\n", - " params=params # Parameters to include\n", - " )\n", - "\n", - "iterator = iter(dataset)\n", - "\n", - "plt.figure(figsize=(12, 6))\n", - "\n", - "fig, ax = plt.subplots(1, 2, figsize=(12, 6))\n", - "\n", - "mse_list = []\n", - "\n", - "x_val, params_val = [], []\n", - "for _ in tqdm(range(num_total // batch_size)):\n", - " x, params = next(iterator)\n", - "\n", - " # Convert to numpy\n", - " x, params = np.array(x), np.array(params)\n", - " \n", - " # x_val.append(np.array(x))\n", - " # params_val.append(np.array(params))\n", - "\n", - " graph = build_graph(x, \n", - " None, \n", - " k=k, \n", - " use_edges=True, \n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " r_max=r_max,\n", - " use_3d_distances=use_3d_distances,\n", - " )\n", - "\n", - " pred = jax.jit(model.apply)(unreplicate(pstate).params, graph)\n", - "\n", - " ax[0].scatter(params[:, 0], pred[:, 0], s=10, color='firebrick')\n", - " ax[1].scatter(params[:, 1], pred[:, 1], s=10, color='firebrick')\n", - "\n", - " mse = np.mean((pred - params) ** 2)\n", - " mse_list.append(mse)\n", - "\n", - "# Diagonal\n", - "ax[0].plot([-1.5, 1.5], [-1.5, 1.5], color='black')\n", - "ax[1].plot([-1.5, 1.5], [-1.5, 1.5], color='black')\n", - "\n", - "print(f\"Mean MSE: {np.mean(mse_list)}\")\n", - "\n", - "# # # Diagonal line\n", - "# plt.plot([0, 0.5], [0, 0.5])\n", - "\n", - "plt.xlabel(\"True\")\n", - "plt.ylabel(\"Predicted\")" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [], - "source": [ - "# x_test = np.load(\"../../../BNN_SBI/data/set_diffuser_data/test_halos.npy\")[..., :3] / 1000.\n", - "# params_test = pd.read_csv(\"../../../BNN_SBI/data/set_diffuser_data/test_cosmology.csv\",)\n", - "\n", - "# params_test = params_test[[\"Omega_m\", \"sigma_8\"]].values\n", - "\n", - "# x_test = (x_test - mean) / std\n", - "# params_test = (params_test - mean_params) / std_params" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 4/4 [00:04<00:00, 1.04s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mean MSE: 0.1213223785161972\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "text/plain": [ - "Text(0, 0.5, 'Predicted')" - ] - }, - "execution_count": 77, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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WblypQYNGqSCggL17t1bixcvdryfmUj3u61cubLJn10oFNKOHTvc6TCQAPHejHjvjVyO9VLuxnti/f/kWqwnCffI3r17dfbZZ+vKK69M63WjR4/W9u3boz+PPPKIQz3MXCbf7Ze//KXuvPNOLVy4UC+//LIOOeQQjRo1SvX19Q72NDMXXHCB3nzzTT333HN66qmn9OKLL+ryyy9P+rpJkyaZ/ux++ctfutDbxB599FFNnTpVc+fO1WuvvaYBAwZo1KhR+uijj2Je/69//Uvnn3++Lr30Uq1Zs0Zjx47V2LFj9cYbb7jc8+TS/W6SVFhYaPozev/9913scXr27NmjAQMGpHycY3V1tb7//e/rpJNOUjgc1rXXXqvLLrtMzz77rMM9TV+63y1i48aNpj+/jh07OtRDIHXEezPivftyOdZLuR3vifVN5UysN+Cp+++/3ygqKkrp2okTJxpjxoxxtD92SvW7HThwwOjcubNx6623Rtt27dplFBQUGI888oiDPUzf+vXrDUnGf/7zn2jb3/72NyMUChnbtm2L+7oTTzzRuOaaa1zoYXqOP/5446qrroo+3r9/v9G1a1ejvLw85vXnnHOO8f3vf9/UNmTIEGPy5MmO9jMT6X63dP6/6DeSjKVLlya8ZsaMGcY3v/lNU9u5555rjBo1ysGeZS+V77ZixQpDklFTU+NKn4BMEO+J917J5VhvGPkT74n1uRXrmQkPmJUrV6pjx47q06ePrrzySn366adedylr1dXV2rFjh0aOHBltKyoq0pAhQ7Rq1SoPe9bUqlWr1LZtWx177LHRtpEjR6pZs2Z6+eWXE7724YcfVvv27fWtb31Ls2fP1hdffOF0dxPau3evVq9ebfq9N2vWTCNHjoz7e1+1apXpekkaNWqU7/6cMvlukrR7924deeSRKi4u1pgxY/Tmm2+60V1XBOXPLhulpaXq0qWLvve97+mll17yujtAVoj33sqVeJ/LsV4i3lsF6c8uU7kS6w/yugNI3ejRo3XWWWeppKREmzdv1nXXXafTTjtNq1atUvPmzb3uXsYiezk6depkau/UqZPv9nns2LGjybKXgw46SIcddljCvv7oRz/SkUceqa5du2rdunWaOXOmNm7cqCeeeMLpLsf1ySefaP/+/TF/7xs2bIj5mh07dgTizymT79anTx/dd9996t+/v2prazV//nwNGzZMb775po444gg3uu2oeH92dXV1+vLLL9W6dWuPepa9Ll26aOHChTr22GPV0NCgRYsWacSIEXr55Zc1aNAgr7sHpI14771cife5HOsl4r0VsT44SMJtNGvWLFVUVCS85q233tLRRx+d0fufd9550f/u16+f+vfvr169emnlypU65ZRTMnrPVDn93byW6vfLVOM9ZP369VOXLl10yimnaPPmzerVq1fG7wv7DB06VEOHDo0+HjZsmI455hjdfffduvHGGz3sGZLp06eP+vTpE308bNgwbd68WbfffrsefPBBD3uGXEW8J97HQ7z3P+J9MOVarCcJt9G0adN00UUXJbymZ8+etn1ez5491b59e23atMnxoOzkd+vcubMkaefOnerSpUu0fefOnSotLc3oPdOV6vfr3Llzk0IfX331lT777LPo90jFkCFDJEmbNm3yLCi3b99ezZs3186dO03tO3fujPtdOnfunNb1Xsnku1m1aNFCAwcO1KZNm5zoouvi/dkVFhYGemQ8nuOPP15VVVVedwM5inhPvE+V1/E+l2O9RLy3ItYHB0m4jTp06KAOHTq49nkffPCBPv30U1Mgc4qT362kpESdO3fW8uXLo0G4rq5OL7/8ctrVZDOV6vcbOnSodu3apdWrV2vw4MGSpBdeeEEHDhyIBtpUhMNhSXLlzy6eli1bavDgwVq+fLnGjh0rSTpw4ICWL1+uKVOmxHzN0KFDtXz5cl177bXRtueee840ouwHmXw3q/379+v111/X6aef7mBP3TN06NAmR8z48c/OLuFw2NP/fyG3Ee8zQ7x3Xy7Heol4b0WsDxCvK8Plq/fff99Ys2aNccMNNxht2rQx1qxZY6xZs8b4/PPPo9f06dPHeOKJJwzDMIzPP//cmD59urFq1SqjurraeP75541BgwYZRx11lFFfX+/V14gp3e9mGIbxf//3f0bbtm2NJ5980li3bp0xZswYo6SkxPjyyy+9+AoJjR492hg4cKDx8ssvG1VVVcZRRx1lnH/++dHnP/jgA6NPnz7Gyy+/bBiGYWzatMmYN2+e8eqrrxrV1dXGk08+afTs2dM44YQTvPoKUX/84x+NgoICY/Hixcb69euNyy+/3Gjbtq2xY8cOwzAMY/z48casWbOi17/00kvGQQcdZMyfP9946623jLlz5xotWrQwXn/9da++QlzpfrcbbrjBePbZZ43Nmzcbq1evNs477zyjVatWxptvvunVV0jo888/j/5/S5Lxq1/9ylizZo3x/vvvG4ZhGLNmzTLGjx8fvf7dd981Dj74YOOnP/2p8dZbbxl33XWX0bx5c+OZZ57x6ivEle53u/32241ly5YZ77zzjvH6668b11xzjdGsWTPj+eef9+orAFHEe+K91/E+l2O9YeR2vCfW526sJwn3yMSJEw1JTX5WrFgRvUaScf/99xuGYRhffPGFceqppxodOnQwWrRoYRx55JHGpEmTov/A+Em6380wvj625Prrrzc6depkFBQUGKeccoqxceNG9zufgk8//dQ4//zzjTZt2hiFhYXGxRdfbLrhqK6uNn3fLVu2GCeccIJx2GGHGQUFBUbv3r2Nn/70p0Ztba1H38BswYIFRvfu3Y2WLVsaxx9/vPHvf/87+tyJJ55oTJw40XT9Y489ZnzjG98wWrZsaXzzm980nn76aZd7nLp0vtu1114bvbZTp07G6aefbrz22mse9Do1kaM6rD+R7zRx4kTjxBNPbPKa0tJSo2XLlkbPnj1N/x/0k3S/W0VFhdGrVy+jVatWxmGHHWaMGDHCeOGFF7zpPGBBvCfe+yHe53KsN4zcjffE+hOj1+darA8ZhmHYPbsOAAAAAACa4pxwAAAAAABcQhIOAAAAAIBLSMIBAAAAAHAJSTgAAAAAAC4hCQcAAAAAwCUk4QAAAAAAuIQkHAAAAAAAl5CEAwAAAADgEpJwAAAAIOBCoVDCn1/84hdedxHAfx3kdQcAAAAAZGf79u3R/3700Uc1Z84cbdy4MdrWpk2b6H8bhqH9+/froINIBQAvMBMOAAAABFznzp2jP0VFRQqFQtHHGzZs0KGHHqq//e1vGjx4sAoKClRVVaWLLrpIY8eONb3PtddeqxEjRkQfHzhwQOXl5SopKVHr1q01YMAA/elPf3L3ywE5huEvAAAAIA/MmjVL8+fPV8+ePdWuXbuUXlNeXq6HHnpICxcu1FFHHaUXX3xRF154oTp06KATTzzR4R4DuYkkHAAAAMgD8+bN0/e+972Ur29oaNAtt9yi559/XkOHDpUk9ezZU1VVVbr77rtJwoEMkYQDAAAAeeDYY49N6/pNmzbpiy++aJK47927VwMHDrSza0BeIQkHAAAA8sAhhxxietysWTMZhmFq27dvX/S/d+/eLUl6+umn1a1bN9N1BQUFDvUSyH0k4QAAAEAe6tChg9544w1TWzgcVosWLSRJffv2VUFBgbZs2cLSc8BGJOEAAABAHjr55JN16623asmSJRo6dKgeeughvfHGG9Gl5oceeqimT5+un/zkJzpw4ICGDx+u2tpavfTSSyosLNTEiRM9/gZAMJGEAwAAAHlo1KhRuv766zVjxgzV19frkksu0YQJE/T6669Hr7nxxhvVoUMHlZeX691331Xbtm01aNAgXXfddR72HAi2kGHdCAIAAAAAABzRzOsOAAAAAACQL0jCAQAAAABwCUk4AAAAAAAuIQkHAAAAAMAlJOEAAAAAALiEJBwAAAAAAJeQhAMAAAAA4BKScAAAAAAAXEISDgAAAACAS0jCAQAAAABwCUk4AAAAAAAuIQkHAAAAAMAl/x9xUBDANtuARQAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from tqdm import tqdm\n", - "\n", - "n_test_batch = 50\n", - "n_test_batches = len(x_test) // n_test_batch\n", - "\n", - "# Make two plots side by side for 0 and 1 idx parameters\n", - "\n", - "plt.figure(figsize=(12, 6))\n", - "\n", - "fig, ax = plt.subplots(1, 2, figsize=(12, 6))\n", - "\n", - "mse_list = []\n", - "\n", - "for i in tqdm(range(n_test_batches)):\n", - "\n", - " # TODO: jit/pmap\n", - " graph = build_graph(x_test[i * n_test_batch:(i + 1) * n_test_batch], \n", - " None, \n", - " k=k, \n", - " use_edges=True, \n", - " apply_pbc=apply_pbc,\n", - " n_radial_basis=n_radial,\n", - " )\n", - "\n", - " \n", - " omega_m_pred = jax.jit(model.apply)(unreplicate(pstate).params, graph)\n", - "\n", - " ax[0].scatter(params_test[i * n_test_batch:(i + 1) * n_test_batch, 0], omega_m_pred[:, 0], s=10, color='firebrick')\n", - " ax[1].scatter(params_test[i * n_test_batch:(i + 1) * n_test_batch, 1], omega_m_pred[:, 1], s=10, color='firebrick')\n", - "\n", - " mse_list.append(loss_mse(omega_m_pred, params_test[i * n_test_batch:(i + 1) * n_test_batch]))\n", - "\n", - "print(f\"Mean MSE: {np.mean(mse_list)}\")\n", - " \n", - "ax[0].plot(params_test[:n_test_batch, 0], params_test[:n_test_batch, 0], color='gray')\n", - "ax[1].plot(params_test[:n_test_batch, 1], params_test[:n_test_batch, 1], color='gray')\n", - "\n", - "plt.xlabel(\"True\")\n", - "plt.ylabel(\"Predicted\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "equivariant", - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/benchmarks/galaxies/segnn_debugging.ipynb b/benchmarks/galaxies/segnn_debugging.ipynb deleted file mode 100644 index 55fbe9f..0000000 --- a/benchmarks/galaxies/segnn_debugging.ipynb +++ /dev/null @@ -1,1158 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "sys.path.append(\"../\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from pathlib import Path\n", - "# import numpy as np\n", - "import jax.numpy as np\n", - "import pandas as pd\n", - "import jax\n", - "import jraph\n", - "import matplotlib.pyplot as plt\n", - "\n", - "%load_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2024-04-09 10:37:11.533482: W external/xla/xla/service/gpu/nvptx_compiler.cc:679] The NVIDIA driver's CUDA version is 12.2 which is older than the ptxas CUDA version (12.3.52). Because the driver is older than the ptxas version, XLA is disabling parallel compilation, which may slow down compilation. You should update your NVIDIA driver or use the NVIDIA-provided CUDA forward compatibility packages.\n" - ] - } - ], - "source": [ - "data_dir = Path('/n/holystore01/LABS/iaifi_lab/Lab/set-diffuser-data/val_split/')\n", - "halos = np.load(data_dir / 'train_halos.npy')\n", - "\n", - "n_nodes = 5000\n", - "halos = halos[:, :n_nodes, :] / 1000.\n", - "\n", - "halos_test = np.load(data_dir / 'test_halos.npy')\n", - "halos_test = halos_test[:, :n_nodes, :]/ 1000." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Prepare data" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1600\n" - ] - } - ], - "source": [ - "cosmology = pd.read_csv(data_dir / f'train_cosmology.csv')\n", - "cosmology_test = pd.read_csv(data_dir / f'test_cosmology.csv')\n", - "print(len(cosmology))" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Omega_mOmega_bhn_ssigma_8
00.17550.066810.77370.88490.6641
10.21390.055570.85990.97850.8619
20.18670.045030.61890.83070.7187
\n", - "
" - ], - "text/plain": [ - " Omega_m Omega_b h n_s sigma_8\n", - "0 0.1755 0.06681 0.7737 0.8849 0.6641\n", - "1 0.2139 0.05557 0.8599 0.9785 0.8619\n", - "2 0.1867 0.04503 0.6189 0.8307 0.7187" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cosmology.head(3)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "omega_m = np.array(cosmology['Omega_m'].values)[:,None]\n", - "omega_m_test = np.array(cosmology_test['Omega_m'].values)[:,None]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Train EGNN" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "import flax\n", - "from flax.training.train_state import TrainState\n", - "from functools import partial\n", - "import flax.linen as nn\n", - "import optax\n", - "from tqdm import trange\n", - "\n", - "replicate = flax.jax_utils.replicate\n", - "unreplicate = flax.jax_utils.unreplicate" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "sys.path.append(\"../../\")\n", - "from models.utils.equivariant_graph_utils import get_equivariant_graph\n", - "from models.utils.graph_utils import build_graph\n", - "from models.utils.irreps_utils import weight_balanced_irreps\n", - "from models.segnn import SEGNN\n", - "from models.utils.graph_utils import get_apply_pbc" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cell:\n", - "[[ 1.7311106 -1.7321664 -1.7304591]\n", - " [-1.7311106 1.7321664 -1.7304591]\n", - " [-1.7311106 -1.7321664 1.7304591]]\n", - "\n" - ] - } - ], - "source": [ - "n_feat = 3\n", - "\n", - "halo_pos_mean = halos[..., :n_feat].mean((0,1))\n", - "halo_pos_std = halos[..., :n_feat].std((0,1))\n", - "\n", - "use_pbcs = True\n", - "apply_pbc = get_apply_pbc(std=halo_pos_std,) if use_pbcs else None" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "halo_pos = (halos[..., :n_feat] - halo_pos_mean) / halo_pos_std\n", - "halo_pos_test = (halos_test[..., :n_feat] - halo_pos_mean) / halo_pos_std" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "import e3nn_jax as e3nn\n", - "from typing import Dict\n", - "\n", - "SEGNN_PARAMS = {\n", - " \"d_hidden\": 64,\n", - " \"l_max_hidden\": 1,\n", - " \"num_blocks\": 2,\n", - " \"num_message_passing_steps\": 3,\n", - " \"intermediate_hidden_irreps\": True,\n", - " \"task\": \"graph\",\n", - " \"output_irreps\": e3nn.Irreps(\"1x0e\"),\n", - " \"hidden_irreps\": weight_balanced_irreps(lmax=1,\n", - " scalar_units=64,\n", - " irreps_right=e3nn.Irreps.spherical_harmonics(1),\n", - " ),\n", - " \"normalize_messages\": True,\n", - " \"message_passing_agg\": \"mean\",\n", - " \"readout_agg\": \"mean\",\n", - "}\n", - "\n", - "class GraphWrapper(nn.Module):\n", - " param_dict: Dict\n", - "\n", - " @nn.compact\n", - " def __call__(self, x):\n", - "\n", - " positions = e3nn.IrrepsArray(\"1o\", x.nodes[..., :3])\n", - " \n", - " if x.nodes.shape[-1] == 3:\n", - " nodes = e3nn.IrrepsArray(\"1o\", x.nodes[..., :])\n", - " velocities = None\n", - " else:\n", - " nodes = e3nn.IrrepsArray(\"1o + 1o\", x.nodes[..., :])\n", - " velocities = e3nn.IrrepsArray(\"1o\", x.nodes[..., 3:6])\n", - "\n", - " # print(nodes)\n", - " \n", - " st_graph = get_equivariant_graph(\n", - " node_features=nodes,\n", - " positions=positions,\n", - " velocities=None,\n", - " steerable_velocities=False,\n", - " senders=x.senders,\n", - " receivers=x.receivers,\n", - " n_node=x.n_node,\n", - " n_edge=x.n_edge,\n", - " globals=x.globals,\n", - " edges=None,\n", - " lmax_attributes=1,\n", - " apply_pbc=apply_pbc\n", - " )\n", - "\n", - " print(st_graph.additional_messages.shape)\n", - " \n", - " return jax.vmap(SEGNN(**self.param_dict))(st_graph)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[[-1.491283 -1.4030712 1.3533763 ]\n", - " [-0.4481547 1.0214067 -1.0602913 ]\n", - " [ 0.0900492 -0.26586807 -1.3759227 ]\n", - " ...\n", - " [ 0.18467267 1.2348855 -0.68346786]\n", - " [-0.94678676 0.6115723 0.8889472 ]\n", - " [ 0.6138253 -1.5027117 -0.8169943 ]]\n", - "\n", - " [[-1.1788335 -0.09380226 0.25299197]\n", - " [ 1.6684078 -1.5874363 0.07615469]\n", - " [ 0.38549396 -1.6113889 -1.1038722 ]\n", - " ...\n", - " [ 0.18306427 1.2357682 -0.67559546]\n", - " [-0.95020354 0.61490405 0.8900071 ]\n", - " [ 0.60879433 -1.5037086 -0.8157273 ]]\n", - "\n", - " [[ 0.50716215 0.20108296 0.26518437]\n", - " [ 0.32212007 -1.638577 -0.12335889]\n", - " [-0.23541386 -1.3727064 0.5165399 ]\n", - " ...\n", - " [-1.4194124 1.586744 -0.32679686]\n", - " [ 0.61250997 -1.0988469 0.63125104]\n", - " [-0.88482964 -1.315285 -1.081695 ]]\n", - "\n", - " ...\n", - "\n", - " [[ 1.2146022 -1.2387208 0.30438587]\n", - " [-0.41744828 0.3113455 -1.267016 ]\n", - " [-1.6358345 0.08852612 0.2902094 ]\n", - " ...\n", - " [-0.30442855 -0.38709894 1.2921233 ]\n", - " [ 0.17331147 1.3117721 1.0808634 ]\n", - " [-1.092509 0.9687155 0.95120513]]\n", - "\n", - " [[-0.91180766 1.4149159 -0.23372903]\n", - " [ 0.480485 -1.575171 0.28082153]\n", - " [ 1.5289196 0.36354047 -0.72274685]\n", - " ...\n", - " [ 0.6598446 1.4245194 -1.6624392 ]\n", - " [ 0.12993449 -1.6229584 -1.1366367 ]\n", - " [ 0.79187244 1.668308 0.3557063 ]]\n", - "\n", - " [[-0.7750756 -1.3372743 0.8478109 ]\n", - " [ 1.7203519 -0.9894736 -1.5330925 ]\n", - " [ 0.04694255 -1.6164299 1.5560129 ]\n", - " ...\n", - " [ 0.9296657 1.0610524 1.2063062 ]\n", - " [ 1.6384339 0.4342099 -1.6647142 ]\n", - " [ 0.13067617 1.3472925 0.5056137 ]]]\n", - "[[[1.7320508e-07]\n", - " [1.4203507e-01]\n", - " [1.4897923e-01]\n", - " ...\n", - " [1.7524348e-01]\n", - " [1.8539707e-01]\n", - " [1.9600260e-01]]\n", - "\n", - " [[1.7320508e-07]\n", - " [5.3134322e-02]\n", - " [1.1144747e-01]\n", - " ...\n", - " [2.1488699e-01]\n", - " [2.1735543e-01]\n", - " [2.2154722e-01]]\n", - "\n", - " [[1.7320508e-07]\n", - " [2.2541145e-02]\n", - " [6.2401991e-02]\n", - " ...\n", - " [2.0289990e-01]\n", - " [2.0997070e-01]\n", - " [2.1113555e-01]]\n", - "\n", - " ...\n", - "\n", - " [[1.7320508e-07]\n", - " [6.4707600e-02]\n", - " [1.5919115e-01]\n", - " ...\n", - " [2.1866263e-01]\n", - " [2.2252156e-01]\n", - " [2.3287639e-01]]\n", - "\n", - " [[1.7320508e-07]\n", - " [6.5385081e-02]\n", - " [9.8009765e-02]\n", - " ...\n", - " [2.5408545e-01]\n", - " [2.7262819e-01]\n", - " [2.7846825e-01]]\n", - "\n", - " [[1.7320508e-07]\n", - " [1.4624454e-01]\n", - " [1.6203266e-01]\n", - " ...\n", - " [1.7586449e-01]\n", - " [1.7885725e-01]\n", - " [1.9269361e-01]]]\n", - "(8, 100000, 1)\n" - ] - }, - { - "data": { - "text/plain": [ - "169537" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph = build_graph(halo_pos[:8], \n", - " None, \n", - " k=20, \n", - " apply_pbc=apply_pbc,\n", - " use_edges=True, \n", - " use_rbf=False, \n", - ")\n", - "\n", - "model = GraphWrapper(SEGNN_PARAMS, )\n", - "\n", - "out, params = model.init_with_output(jax.random.PRNGKey(0), graph)\n", - "sum(x.size for x in jax.tree_util.tree_leaves(params))" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Array([[ 4.5409113e-05],\n", - " [ 8.0596612e-05],\n", - " [-7.8846278e-06],\n", - " [ 2.2992001e-05],\n", - " [ 1.4310288e-04],\n", - " [-2.1337757e-05],\n", - " [-6.6804620e-05],\n", - " [-2.0324760e-04]], dtype=float32)" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "out" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4 GPUs available\n" - ] - } - ], - "source": [ - "# Devices\n", - "num_local_devices = jax.local_device_count()\n", - "print(f\"{num_local_devices} GPUs available\")" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Define train state and replicate across devices\n", - "tx = optax.adamw(learning_rate=2e-4, weight_decay=1e-5)\n", - "state = TrainState.create(apply_fn=model.apply, params=params, tx=tx)\n", - "pstate = replicate(state)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4 GPUs available\n" - ] - } - ], - "source": [ - "# Devices\n", - "num_local_devices = jax.local_device_count()\n", - "print(f\"{num_local_devices} GPUs available\")" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "def loss_mse(pred_batch, cosmo_batch,):\n", - " return np.mean((pred_batch - cosmo_batch) ** 2)\n", - "\n", - "@partial(jax.pmap, axis_name=\"batch\",)\n", - "def train_step(state, halo_batch, cosmo_batch,):\n", - "\n", - " halo_graph = build_graph(halo_batch, \n", - " None, \n", - " k=20, \n", - " use_edges=True, \n", - " use_rbf=False, \n", - " apply_pbc=apply_pbc,\n", - " )\n", - "\n", - " \n", - " def loss_fn(params):\n", - " outputs = state.apply_fn(params, halo_graph)\n", - " loss = loss_mse(outputs, cosmo_batch)\n", - " return loss\n", - "\n", - " # Get loss, grads, and update state\n", - " loss, grads = jax.value_and_grad(loss_fn)(state.params)\n", - " grads = jax.lax.pmean(grads, \"batch\")\n", - " new_state = state.apply_gradients(grads=grads)\n", - " metrics = {\"loss\": jax.lax.pmean(loss, \"batch\")}\n", - " \n", - " return new_state, metrics" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/2000 [00:00with\n", - "Tracedwith\n", - "(8, 100000, 1)\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 58%|█████▊ | 1157/2000 [08:09<05:56, 2.36it/s, loss=0.0038630525]\n", - "\n", - "KeyboardInterrupt\n", - "\n" - ] - } - ], - "source": [ - "n_steps = 2000\n", - "n_batch = 32\n", - "n_train = 1800 \n", - "\n", - "key = jax.random.PRNGKey(0)\n", - "\n", - "with trange(n_steps) as steps:\n", - " for step in steps:\n", - " key, subkey = jax.random.split(key)\n", - " idx = jax.random.choice(key, halo_pos.shape[0], shape=(n_batch,))\n", - " \n", - " halo_batch, cosmo_batch = halo_pos[:n_train][idx], omega_m[:n_train][idx]\n", - " # halo_batch, cosmo_batch = halo_pos[:n_batch], omega_m[:n_batch] # Overfit on a small sample\n", - "\n", - " # Split batches across devices\n", - " halo_batch = jax.tree_map(lambda x: np.split(x, num_local_devices, axis=0), halo_batch)\n", - " cosmo_batch = jax.tree_map(lambda x: np.split(x, num_local_devices, axis=0), cosmo_batch)\n", - " halo_batch, cosmo_batch = np.array(halo_batch), np.array(cosmo_batch)\n", - "\n", - " pstate, metrics = train_step(pstate, halo_batch, cosmo_batch)\n", - " \n", - " steps.set_postfix(loss=unreplicate(metrics[\"loss\"]))" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/1 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from tqdm import tqdm\n", - "\n", - "n_test_batch = 8\n", - "\n", - "for i in tqdm(range(1)):\n", - "\n", - " # TODO: jit/pmap\n", - " graph = build_graph(halo_pos[i * n_test_batch:(i + 1) * n_test_batch], \n", - " None, \n", - " k=20, \n", - " use_edges=True, \n", - " use_rbf=False, \n", - " apply_pbc=apply_pbc,\n", - " )\n", - " \n", - " omega_m_pred = jax.jit(model.apply)(unreplicate(pstate).params, graph)\n", - "\n", - " plt.scatter(omega_m[i * n_test_batch:(i + 1) * n_test_batch], omega_m_pred[:, 0], s=10, color='firebrick')\n", - " \n", - "# Plot a diagonal (y=x) line\n", - "plt.plot([0, 1], [0, 1], color = 'black', linewidth = 1)\n", - "\n", - "plt.xlabel(\"True\")\n", - "plt.ylabel(\"Predicted\")" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/20 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from tqdm import tqdm\n", - "\n", - "n_test_batch = 10\n", - "n_test_batches = len(halo_pos_test) // n_test_batch\n", - "\n", - "for i in tqdm(range(n_test_batches)):\n", - "\n", - " # TODO: jit/pmap\n", - " graph = build_graph(halo_pos_test[i * n_test_batch:(i + 1) * n_test_batch], \n", - " None, \n", - " k=20, \n", - " use_edges=True, \n", - " use_rbf=False, \n", - " apply_pbc=apply_pbc,\n", - " )\n", - " \n", - " omega_m_pred = jax.jit(model.apply)(unreplicate(pstate).params, graph)\n", - "\n", - " plt.scatter(omega_m_test[i * n_test_batch:(i + 1) * n_test_batch], omega_m_pred[:, 0], s=10, color='firebrick')\n", - " \n", - "plt.plot(omega_m_test[:n_test_batch], omega_m_test[:n_test_batch], color='gray')\n", - "\n", - "plt.xlabel(\"True\")\n", - "plt.ylabel(\"Predicted\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "equivariant", - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -}