├── .gitignore ├── 1-setup.ipynb ├── 2-intro_FNO.ipynb ├── 3-darcy_flow.ipynb ├── 4-training-on-Darcy-Flow.ipynb ├── README.md ├── assets ├── 2023-Nik.pdf └── Bootcamp_DLI_Modulus_v2207_CalTech_share.pdf ├── config ├── darcy_config.yaml └── tfno_darcy_config.yaml └── images └── fourier_layer.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | data 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /1-setup.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "2c160c9c-a445-493e-9948-7ba507c606fb", 6 | "metadata": {}, 7 | "source": [ 8 | "# Running bash commands from your notebook\n", 9 | "\n", 10 | "First, let's install all the dependencies. \n", 11 | "\n", 12 | "You can directly run bash commands in your notebook, by either prefixing your commands with an exclamation mark `!`:\n", 13 | "```ipython\n", 14 | "[1] !echo \"this is a bash command\"\n", 15 | "this is a bash command\n", 16 | "\n", 17 | "[2] !ls\n", 18 | "/home/user/git_repos/FNO_workshop\n", 19 | "```\n", 20 | "\n", 21 | "or by starting your cell with the `%%bash` ipython magic. \n", 22 | "\n", 23 | "Let's see a simple example:" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 3, 29 | "id": "24e20734-97e5-4295-9952-d67ac36b63a0", 30 | "metadata": {}, 31 | "outputs": [ 32 | { 33 | "name": "stdout", 34 | "output_type": "stream", 35 | "text": [ 36 | "Couldn't find program: 'bash'\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "%%bash\n", 42 | "\n", 43 | "for var in hello world\n", 44 | "do\n", 45 | " echo ${var} \n", 46 | "done" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "id": "5b47acb6-a558-40bf-bd76-872941fdf879", 52 | "metadata": {}, 53 | "source": [ 54 | "# Installing the dependencies\n", 55 | "\n", 56 | "Now, let's install the dependencies." 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 4, 62 | "id": "bcce1c3e-b4d7-44ea-8b98-bce1f04182cf", 63 | "metadata": {}, 64 | "outputs": [ 65 | { 66 | "name": "stdout", 67 | "output_type": "stream", 68 | "text": [ 69 | "Couldn't find program: 'bash'\n" 70 | ] 71 | } 72 | ], 73 | "source": [ 74 | "%%bash \n", 75 | "\n", 76 | "target_folder='./temp'\n", 77 | "[ -d ${target_folder} ] || mkdir -p ${target_folder}\n", 78 | "cd temp\n", 79 | "\n", 80 | "git clone https://github.com/tensorly/tensorly \n", 81 | "cd tensorly\n", 82 | "python -m pip install -e .\n", 83 | "cd ..\n", 84 | "\n", 85 | "git clone https://github.com/tensorly/torch\n", 86 | "cd torch\n", 87 | "python -m pip install -e .\n", 88 | "cd ..\n", 89 | "\n", 90 | "git clone https://github.com/NeuralOperator/neuraloperator\n", 91 | "cd neuraloperator\n", 92 | "python -m pip install -e ." 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 5, 98 | "id": "e0bb548e-6e98-4fac-935e-52a8115c4aac", 99 | "metadata": {}, 100 | "outputs": [ 101 | { 102 | "name": "stdout", 103 | "output_type": "stream", 104 | "text": [ 105 | "Collecting gpustat\n", 106 | " Downloading gpustat-1.0.0.tar.gz (90 kB)\n", 107 | "Requirement already satisfied: six>=1.7 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gpustat) (1.16.0)\n", 108 | "Collecting nvidia-ml-py<=11.495.46,>=11.450.129\n", 109 | " Downloading nvidia_ml_py-11.495.46-py3-none-any.whl (25 kB)\n", 110 | "Requirement already satisfied: psutil>=5.6.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gpustat) (5.8.0)\n", 111 | "Collecting blessed>=1.17.1\n", 112 | " Downloading blessed-1.20.0-py2.py3-none-any.whl (58 kB)\n", 113 | "Collecting jinxed>=1.1.0\n", 114 | " Downloading jinxed-1.2.0-py2.py3-none-any.whl (33 kB)\n", 115 | "Requirement already satisfied: wcwidth>=0.1.4 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from blessed>=1.17.1->gpustat) (0.2.5)\n", 116 | "Collecting ansicon\n", 117 | " Downloading ansicon-1.89.0-py2.py3-none-any.whl (63 kB)\n", 118 | "Building wheels for collected packages: gpustat\n", 119 | " Building wheel for gpustat (setup.py): started\n", 120 | " Building wheel for gpustat (setup.py): finished with status 'done'\n", 121 | " Created wheel for gpustat: filename=gpustat-1.0.0-py3-none-any.whl size=19886 sha256=647135e0be6c489fa67d18d54e79c7dca544dfd5496efe4d20129d52a8c8803f\n", 122 | " Stored in directory: c:\\users\\devzh\\appdata\\local\\pip\\cache\\wheels\\1b\\ed\\14\\0d513c962b25da841c42022cb5847c2ef835902c8563b8fb01\n", 123 | "Successfully built gpustat\n", 124 | "Installing collected packages: ansicon, jinxed, nvidia-ml-py, blessed, gpustat\n", 125 | "Successfully installed ansicon-1.89.0 blessed-1.20.0 gpustat-1.0.0 jinxed-1.2.0 nvidia-ml-py-11.495.46\n", 126 | "Collecting gdown\n", 127 | " Downloading gdown-4.6.4-py3-none-any.whl (14 kB)\n", 128 | "Requirement already satisfied: requests[socks] in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gdown) (2.26.0)\n", 129 | "Requirement already satisfied: beautifulsoup4 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gdown) (4.10.0)\n", 130 | "Requirement already satisfied: filelock in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gdown) (3.3.1)\n", 131 | "Requirement already satisfied: six in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gdown) (1.16.0)\n", 132 | "Requirement already satisfied: tqdm in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gdown) (4.62.3)\n", 133 | "Requirement already satisfied: soupsieve>1.2 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from beautifulsoup4->gdown) (2.2.1)\n", 134 | "Requirement already satisfied: charset-normalizer~=2.0.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests[socks]->gdown) (2.0.4)\n", 135 | "Requirement already satisfied: urllib3<1.27,>=1.21.1 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests[socks]->gdown) (1.26.7)\n", 136 | "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests[socks]->gdown) (2021.10.8)\n", 137 | "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests[socks]->gdown) (3.2)\n", 138 | "Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests[socks]->gdown) (1.7.1)\n", 139 | "Requirement already satisfied: colorama in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from tqdm->gdown) (0.4.4)\n", 140 | "Installing collected packages: gdown\n", 141 | "Successfully installed gdown-4.6.4\n", 142 | "Requirement already satisfied: opt-einsum in c:\\users\\devzh\\anaconda3\\lib\\site-packages (3.3.0)\n", 143 | "Requirement already satisfied: numpy>=1.7 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from opt-einsum) (1.21.2)\n", 144 | "Requirement already satisfied: h5py in c:\\users\\devzh\\anaconda3\\lib\\site-packages (3.6.0)\n", 145 | "Requirement already satisfied: wandb in c:\\users\\devzh\\anaconda3\\lib\\site-packages (0.12.1)\n", 146 | "Requirement already satisfied: ruamel.yaml in c:\\users\\devzh\\anaconda3\\lib\\site-packages (0.17.21)\n", 147 | "Requirement already satisfied: zarr in c:\\users\\devzh\\anaconda3\\lib\\site-packages (2.14.1)\n", 148 | "Requirement already satisfied: numpy>=1.14.5 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from h5py) (1.21.2)\n", 149 | "Requirement already satisfied: Click!=8.0.0,>=7.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (8.0.3)\n", 150 | "Requirement already satisfied: promise<3,>=2.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (2.3)\n", 151 | "Requirement already satisfied: sentry-sdk>=1.0.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (1.3.1)\n", 152 | "Requirement already satisfied: GitPython>=1.0.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (3.1.18)\n", 153 | "Requirement already satisfied: docker-pycreds>=0.4.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (0.4.0)\n", 154 | "Requirement already satisfied: protobuf>=3.12.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (3.17.3)\n", 155 | "Requirement already satisfied: psutil>=5.0.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (5.8.0)\n", 156 | "Requirement already satisfied: subprocess32>=3.5.3 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (3.5.4)\n", 157 | "Requirement already satisfied: python-dateutil>=2.6.1 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (2.8.2)\n", 158 | "Requirement already satisfied: shortuuid>=0.5.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (1.0.1)\n", 159 | "Requirement already satisfied: requests<3,>=2.0.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (2.26.0)\n", 160 | "Requirement already satisfied: configparser>=3.8.1 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (5.0.2)\n", 161 | "Requirement already satisfied: PyYAML in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (6.0)\n", 162 | "Requirement already satisfied: six>=1.13.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (1.16.0)\n", 163 | "Requirement already satisfied: pathtools in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from wandb) (0.1.2)\n", 164 | "Requirement already satisfied: ruamel.yaml.clib>=0.2.6 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from ruamel.yaml) (0.2.7)\n", 165 | "Requirement already satisfied: asciitree in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from zarr) (0.3.3)\n", 166 | "Requirement already satisfied: numcodecs>=0.10.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from zarr) (0.11.0)\n", 167 | "Requirement already satisfied: fasteners in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from zarr) (0.18)\n", 168 | "Requirement already satisfied: colorama in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from Click!=8.0.0,>=7.0->wandb) (0.4.4)\n", 169 | "Requirement already satisfied: gitdb<5,>=4.0.1 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from GitPython>=1.0.0->wandb) (4.0.7)\n", 170 | "Requirement already satisfied: smmap<5,>=3.0.1 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from gitdb<5,>=4.0.1->GitPython>=1.0.0->wandb) (4.0.0)\n", 171 | "Requirement already satisfied: entrypoints in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from numcodecs>=0.10.0->zarr) (0.3)\n", 172 | "Requirement already satisfied: urllib3<1.27,>=1.21.1 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests<3,>=2.0.0->wandb) (1.26.7)\n", 173 | "Requirement already satisfied: charset-normalizer~=2.0.0 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests<3,>=2.0.0->wandb) (2.0.4)\n", 174 | "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests<3,>=2.0.0->wandb) (2021.10.8)\n", 175 | "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\devzh\\anaconda3\\lib\\site-packages (from requests<3,>=2.0.0->wandb) (3.2)\n" 176 | ] 177 | } 178 | ], 179 | "source": [ 180 | "!pip install gpustat\n", 181 | "!pip install gdown\n", 182 | "!pip install opt-einsum\n", 183 | "!pip install h5py wandb ruamel.yaml zarr" 184 | ] 185 | }, 186 | { 187 | "attachments": {}, 188 | "cell_type": "markdown", 189 | "id": "f4ed3b9d-fffd-4d5d-852c-7dc95dad086f", 190 | "metadata": {}, 191 | "source": [ 192 | "# Prepare data " 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 10, 198 | "id": "3a2484ab-0f02-45c9-acce-cb0bbe803dbb", 199 | "metadata": {}, 200 | "outputs": [], 201 | "source": [ 202 | "import os\n", 203 | "import requests\n", 204 | "import hashlib\n", 205 | "url_dict = {\n", 206 | " 'darcyflow-1':'https://caltech-pde-data.s3.us-west-2.amazonaws.com/piececonst_r241_N1024_smooth1.mat', \n", 207 | " 'darcyflow-2': 'https://caltech-pde-data.s3.us-west-2.amazonaws.com/piececonst_r241_N1024_smooth2.mat', \n", 208 | " 'Navier-Stokes': 'https://caltech-pde-data.s3.us-west-2.amazonaws.com/ns_V1e-3_N5000_T50.mat', \n", 209 | " 'darcy-test-32': 'https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_test_32.pt', \n", 210 | " 'darcy-test-64': 'https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_test_64.pt', \n", 211 | " 'darcy-train-32': 'https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_train_32.pt', \n", 212 | " 'darcy-train-64': 'https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_train_64.pt', \n", 213 | " 'KF-Re100': 'https://caltech-pde-data.s3.us-west-2.amazonaws.com/KFvorticity_Re100_N50_T500.npy'\n", 214 | "}\n", 215 | "\n", 216 | "chksum_dict = {\n", 217 | " 'piececonst_r241_N1024_smooth1.mat': '5ab3edf67bb5fd6d49ebf308cd79ed70340106d1a18af8a8439d3e7fc8e82d21', \n", 218 | " 'piececonst_r241_N1024_smooth2.mat': '51a818ed2e4f08752eea5d3f137f0e00271589c48297a46c641382a51eb80acf', \n", 219 | " 'ns_V1e-3_N5000_T50.mat': '78b8d9e83d767dc7050fb8145ee7e7f11e2d18d325bff9abc7f108ec3292ee78', \n", 220 | " 'darcy_train_64.pt': 'c05770239c91ebf093ea971e4d724008a49c9f21b5363fcf182e80499fae7fb4', \n", 221 | " 'darcy_train_32.pt': 'b8d8095d3832ed67f55b4a8fcb1970618b4ca2c6fc91aee2fe49b9c9b2c071ae', \n", 222 | " 'darcy_test_64.pt': '2220bb25c920109e9565a7fc07b675de16d124d563996f6e7256e2faa1fde24f', \n", 223 | " 'darcy_test_32.pt': '65137910193a553295c26e3d8273761daa44766597f4b34cfb12299fc6e3f311', \n", 224 | " 'KFvorticity_Re100_N50_T500.npy': '55f5af44a732a7843d631ace6384ac75c787d4fb36765b2e83ce1febb52d5463'\n", 225 | "}\n", 226 | "\n", 227 | "def download_file(url, file_path):\n", 228 | " with requests.get(url, stream=True) as r:\n", 229 | " r.raise_for_status()\n", 230 | " with open(file_path, 'wb') as f:\n", 231 | " for chunk in r.iter_content(chunk_size=1024 * 1024 * 1024):\n", 232 | " f.write(chunk)\n", 233 | " print('Complete')\n" 234 | ] 235 | }, 236 | { 237 | "attachments": {}, 238 | "cell_type": "markdown", 239 | "id": "d36ba93d", 240 | "metadata": {}, 241 | "source": [ 242 | "## Download Darcy datasets" 243 | ] 244 | }, 245 | { 246 | "cell_type": "code", 247 | "execution_count": 7, 248 | "id": "70b2c9d0-990d-43fd-9a80-7af9dbc8dd64", 249 | "metadata": {}, 250 | "outputs": [ 251 | { 252 | "name": "stdout", 253 | "output_type": "stream", 254 | "text": [ 255 | "Downloading https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_train_64.pt...\n", 256 | "Complete\n", 257 | "Downloading https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_train_32.pt...\n", 258 | "Complete\n", 259 | "Downloading https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_test_64.pt...\n", 260 | "Complete\n", 261 | "Downloading https://caltech-pde-data.s3.us-west-2.amazonaws.com/darcy_test_32.pt...\n", 262 | "Complete\n" 263 | ] 264 | } 265 | ], 266 | "source": [ 267 | "data_root = 'data'\n", 268 | "darcy_dir = os.path.join(data_root, 'darcy_flow')\n", 269 | "os.makedirs(darcy_dir, exist_ok=True)\n", 270 | "\n", 271 | "day1_data = ['darcy-train-64', 'darcy-train-32', 'darcy-test-64', 'darcy-test-32']\n", 272 | "\n", 273 | "for key in day1_data:\n", 274 | " value = url_dict[key]\n", 275 | " print(f'Downloading {value}...')\n", 276 | " filename = os.path.basename(value)\n", 277 | " save_path = os.path.join(darcy_dir, filename)\n", 278 | " download_file(url=value, file_path=save_path)\n" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": null, 284 | "id": "db98503a", 285 | "metadata": {}, 286 | "outputs": [], 287 | "source": [ 288 | "# verify data integrity\n", 289 | "for data_file in os.listdir(darcy_dir):\n", 290 | " data_path = os.path.join(darcy_dir, data_file)\n", 291 | " with open(data_path, 'rb') as f:\n", 292 | " data = f.read()\n", 293 | " sha256 = hashlib.sha256(data).hexdigest()\n", 294 | " if sha256 == chksum_dict[data_file]:\n", 295 | " print(f'{data_file} verified!')\n", 296 | " else:\n", 297 | " print(f'{data_file} verfication failed!')" 298 | ] 299 | }, 300 | { 301 | "attachments": {}, 302 | "cell_type": "markdown", 303 | "id": "6a5cc551", 304 | "metadata": {}, 305 | "source": [ 306 | "### Download KF datasets (2d NS)" 307 | ] 308 | }, 309 | { 310 | "cell_type": "code", 311 | "execution_count": 2, 312 | "id": "817f3d48", 313 | "metadata": {}, 314 | "outputs": [ 315 | { 316 | "name": "stdout", 317 | "output_type": "stream", 318 | "text": [ 319 | "Downloading https://caltech-pde-data.s3.us-west-2.amazonaws.com/KFvorticity_Re100_N50_T500.npy to data\\kf\n", 320 | "Complete\n" 321 | ] 322 | } 323 | ], 324 | "source": [ 325 | "data_root = 'data'\n", 326 | "kf_dir = os.path.join(data_root, 'kf')\n", 327 | "os.makedirs(kf_dir, exist_ok=True)\n", 328 | "\n", 329 | "kf_data = ['KF-Re100']\n", 330 | "for key in kf_data:\n", 331 | " value = url_dict[key]\n", 332 | " print(f'Downloading {value} to {kf_dir}')\n", 333 | " filename = os.path.basename(value)\n", 334 | " save_path = os.path.join(kf_dir, filename)\n", 335 | " download_file(url=value, file_path=save_path)" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": 11, 341 | "id": "73acfd3d-23d4-4f02-9bc7-167438ac2de4", 342 | "metadata": {}, 343 | "outputs": [ 344 | { 345 | "name": "stdout", 346 | "output_type": "stream", 347 | "text": [ 348 | "KFvorticity_Re100_N50_T500.npy verified!\n" 349 | ] 350 | } 351 | ], 352 | "source": [ 353 | "for data_file in os.listdir(kf_dir):\n", 354 | " data_path = os.path.join(kf_dir, data_file)\n", 355 | " with open(data_path, 'rb') as f:\n", 356 | " data = f.read()\n", 357 | " sha256 = hashlib.sha256(data).hexdigest()\n", 358 | " if sha256 == chksum_dict[data_file]:\n", 359 | " print(f'{data_file} verified!')\n", 360 | " else:\n", 361 | " print(f'{data_file} verfication failed!')\n" 362 | ] 363 | } 364 | ], 365 | "metadata": { 366 | "kernelspec": { 367 | "display_name": "base", 368 | "language": "python", 369 | "name": "python3" 370 | }, 371 | "language_info": { 372 | "codemirror_mode": { 373 | "name": "ipython", 374 | "version": 3 375 | }, 376 | "file_extension": ".py", 377 | "mimetype": "text/x-python", 378 | "name": "python", 379 | "nbconvert_exporter": "python", 380 | "pygments_lexer": "ipython3", 381 | "version": "3.8.8" 382 | }, 383 | "vscode": { 384 | "interpreter": { 385 | "hash": "95d4b27ba6bfea4a66eebe0e0159b214d32a94d313a7f4c98bd9b87f5ee37cbe" 386 | } 387 | } 388 | }, 389 | "nbformat": 4, 390 | "nbformat_minor": 5 391 | } 392 | -------------------------------------------------------------------------------- /2-intro_FNO.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "59194c45-83c9-4a77-a1b0-185eca26afd5", 6 | "metadata": {}, 7 | "source": [ 8 | "# Check the dependencies " 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "af7a5c4c-b3a5-4f32-aee9-55290566ff56", 15 | "metadata": {}, 16 | "outputs": [ 17 | { 18 | "name": "stdout", 19 | "output_type": "stream", 20 | "text": [ 21 | "tl.__version__='0.8.0'\n", 22 | "tltorch.__version__='0.3.0'\n", 23 | "no.__version__='0.1.0'\n" 24 | ] 25 | } 26 | ], 27 | "source": [ 28 | "import tensorly as tl\n", 29 | "import tltorch\n", 30 | "import neuralop as no\n", 31 | "\n", 32 | "print(f'{tl.__version__=}')\n", 33 | "print(f'{tltorch.__version__=}')\n", 34 | "print(f'{no.__version__=}')" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "id": "a36bb3e2-c158-497c-babe-5eead700cbf1", 40 | "metadata": { 41 | "tags": [] 42 | }, 43 | "source": [ 44 | "# FFT and Spectral Convolution\n" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 2, 50 | "id": "4efa0d7f-e39c-496e-891d-6b34c62fbd9d", 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "from neuralop.models.fno_block import FactorizedSpectralConv\n", 55 | "from neuralop.models import TFNO2d\n", 56 | "import torch" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 3, 62 | "id": "2c8c3eb7-82e1-4df7-b6e6-3f34331637c4", 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "fourier_conv = FactorizedSpectralConv(in_channels=3, out_channels=10, n_modes=(4, 4),\n", 67 | " factorization=None, implementation='reconstructed')" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 4, 73 | "id": "4eaf645a-b7f5-4dcc-b8de-fb388ccc9b26", 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "in_data = torch.randn((2, 3, 16, 16))" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 5, 83 | "id": "016b33e0-88a6-4215-99e0-19da4f8fd5f5", 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "out = fourier_conv(in_data)" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 6, 93 | "id": "36d0f546-9fa9-4936-a6b6-19d7bde03639", 94 | "metadata": {}, 95 | "outputs": [ 96 | { 97 | "data": { 98 | "text/plain": [ 99 | "torch.Size([2, 10, 16, 16])" 100 | ] 101 | }, 102 | "execution_count": 6, 103 | "metadata": {}, 104 | "output_type": "execute_result" 105 | } 106 | ], 107 | "source": [ 108 | "out.shape" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 7, 114 | "id": "4936746b-5abb-4a8b-9e74-238502c65930", 115 | "metadata": {}, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "FactorizedSpectralConv(\n", 121 | " (weight): ModuleList(\n", 122 | " (0): ComplexDenseTensor(shape=torch.Size([3, 10, 2, 2]), rank=None)\n", 123 | " (1): ComplexDenseTensor(shape=torch.Size([3, 10, 2, 2]), rank=None)\n", 124 | " )\n", 125 | ")" 126 | ] 127 | }, 128 | "execution_count": 7, 129 | "metadata": {}, 130 | "output_type": "execute_result" 131 | } 132 | ], 133 | "source": [ 134 | "fourier_conv" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "id": "a616d68d-677a-4e6f-abd5-9e631ebf7fb6", 140 | "metadata": {}, 141 | "source": [ 142 | "The way the spectral convolution works is that it multiplies (complex) coefficients with (complex) weights, learned end-to-end." 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "id": "0c8d9860-d43d-47f3-a6aa-c7ed4522684e", 148 | "metadata": { 149 | "tags": [] 150 | }, 151 | "source": [ 152 | "# Tensorized Spectral Convolutions\n", 153 | "\n", 154 | "It is possible to express the weights of one or more layers as in factorized form, as a low-rank decomposition of the full weights.\n", 155 | "\n", 156 | "`neuralop` comes with support for tensorization out of the box, you can simply specify, e.g., to use a Tucker factorization, `factorization='tucker'`." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 8, 162 | "id": "b3f919de-97c2-4f0b-bb40-8e47cd2c1e0e", 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "fourier_conv = FactorizedSpectralConv(in_channels=3, out_channels=10, n_modes=(4, 4),\n", 167 | " factorization='tucker', implementation='reconstructed')" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 9, 173 | "id": "91a7aa04-9cc3-4f8c-b34f-54fbc625b718", 174 | "metadata": {}, 175 | "outputs": [ 176 | { 177 | "data": { 178 | "text/plain": [ 179 | "FactorizedSpectralConv(\n", 180 | " (weight): ModuleList(\n", 181 | " (0): ComplexTuckerTensor(shape=(3, 10, 2, 2), rank=(1, 5, 1, 1))\n", 182 | " (1): ComplexTuckerTensor(shape=(3, 10, 2, 2), rank=(1, 5, 1, 1))\n", 183 | " )\n", 184 | ")" 185 | ] 186 | }, 187 | "execution_count": 9, 188 | "metadata": {}, 189 | "output_type": "execute_result" 190 | } 191 | ], 192 | "source": [ 193 | "fourier_conv" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "id": "f8df876d-72e1-40cd-9a86-330a57dc0e8d", 199 | "metadata": {}, 200 | "source": [ 201 | "## Efficient forward pass\n", 202 | "\n", 203 | "When factorizing the weights, have two main options during the forward pass:\n", 204 | "1. reconstruct the full weights and use that for the forward pass \n", 205 | "2. contract the input directly with the factorized weights to predict the output\n", 206 | "\n", 207 | "When the factorized weights are small, the second option can lead to large speedups or memory reduction, particularly when coupled with checkpointing. \n", 208 | "\n", 209 | "In `neuralop`, you can use those simply by specifying `implementation='reconstructed'` or `implementation='factorized'`:" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 10, 215 | "id": "a0667a6b-1efe-47e0-8908-29c5fb0cf45a", 216 | "metadata": {}, 217 | "outputs": [], 218 | "source": [ 219 | "fourier_conv = FactorizedSpectralConv(in_channels=3, out_channels=10, n_modes=(4, 4),\n", 220 | " factorization='tucker', implementation='factorized')" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "id": "ec3ab24a-09fe-4864-b2ed-e96b54792e9f", 226 | "metadata": {}, 227 | "source": [ 228 | "# Full Tensorized Fourier Neural Operator \n", 229 | "\n", 230 | "The full architecture is composed of \n", 231 | "\n", 232 | "i) a lifting layer taking the number of input channels and lifting that to the desired number of hidden channels\n", 233 | "ii) a number of spectral convolutions, as shown above\n", 234 | "iii) a projection layer projecting back from the number of hidden channels to the desired number of output channels\n" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 11, 240 | "id": "d51aec17-2cf4-40c4-9452-84a4b5259db6", 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "tfno = TFNO2d(n_modes_height=16, n_modes_width=16, hidden_channels=16, \n", 245 | " factorization=None, skip='linear')" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": 12, 251 | "id": "c87127e5-d24c-4096-be3a-8872a853a132", 252 | "metadata": {}, 253 | "outputs": [ 254 | { 255 | "data": { 256 | "text/plain": [ 257 | "TFNO2d(\n", 258 | " (convs): FactorizedSpectralConv2d(\n", 259 | " (weight): ModuleList(\n", 260 | " (0): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 261 | " (1): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 262 | " (2): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 263 | " (3): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 264 | " (4): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 265 | " (5): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 266 | " (6): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 267 | " (7): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 268 | " )\n", 269 | " )\n", 270 | " (fno_skips): ModuleList(\n", 271 | " (0): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 272 | " (1): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 273 | " (2): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 274 | " (3): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 275 | " )\n", 276 | " (lifting): Lifting(\n", 277 | " (fc): Conv2d(3, 16, kernel_size=(1, 1), stride=(1, 1))\n", 278 | " )\n", 279 | " (projection): Projection(\n", 280 | " (fc1): Conv2d(16, 256, kernel_size=(1, 1), stride=(1, 1))\n", 281 | " (fc2): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))\n", 282 | " )\n", 283 | ")" 284 | ] 285 | }, 286 | "execution_count": 12, 287 | "metadata": {}, 288 | "output_type": "execute_result" 289 | } 290 | ], 291 | "source": [ 292 | "tfno" 293 | ] 294 | }, 295 | { 296 | "cell_type": "markdown", 297 | "id": "0e70efec-bf3c-48ac-b53a-59800055f1b9", 298 | "metadata": {}, 299 | "source": [ 300 | "## Lifting layer\n", 301 | "\n", 302 | "Increasing the number of channels" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 13, 308 | "id": "1deead74-bd3d-4aa9-8d2c-cfd9ab0763d7", 309 | "metadata": {}, 310 | "outputs": [ 311 | { 312 | "data": { 313 | "text/plain": [ 314 | "Lifting(\n", 315 | " (fc): Conv2d(3, 16, kernel_size=(1, 1), stride=(1, 1))\n", 316 | ")" 317 | ] 318 | }, 319 | "execution_count": 13, 320 | "metadata": {}, 321 | "output_type": "execute_result" 322 | } 323 | ], 324 | "source": [ 325 | "tfno.lifting" 326 | ] 327 | }, 328 | { 329 | "cell_type": "markdown", 330 | "id": "08844bac-9335-4ac4-afc8-f1d67c3e31bb", 331 | "metadata": {}, 332 | "source": [ 333 | "## Spectral convolutions" 334 | ] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "execution_count": 14, 339 | "id": "f2bc28dc-1226-4ed3-b757-3c42357d276a", 340 | "metadata": {}, 341 | "outputs": [ 342 | { 343 | "data": { 344 | "text/plain": [ 345 | "FactorizedSpectralConv2d(\n", 346 | " (weight): ModuleList(\n", 347 | " (0): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 348 | " (1): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 349 | " (2): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 350 | " (3): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 351 | " (4): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 352 | " (5): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 353 | " (6): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 354 | " (7): ComplexDenseTensor(shape=torch.Size([16, 16, 8, 8]), rank=None)\n", 355 | " )\n", 356 | ")" 357 | ] 358 | }, 359 | "execution_count": 14, 360 | "metadata": {}, 361 | "output_type": "execute_result" 362 | } 363 | ], 364 | "source": [ 365 | "tfno.convs" 366 | ] 367 | }, 368 | { 369 | "cell_type": "markdown", 370 | "id": "1c7d9882-13db-447d-affd-07ef17256e1c", 371 | "metadata": {}, 372 | "source": [ 373 | "## Skip connections: recovering non-periodicity\n", 374 | "\n", 375 | "Recall the FNO architecture has skip connections: the FFT transformation will loose non-periodic information that has to be reinjected through skip connections. These skip connections also help with learning.\n", 376 | "\n", 377 | "![FNO_layer](./images/fourier_layer.png)\n", 378 | "\n", 379 | "Here, linear layer (represented by weight W in the image). We can also use Identity skip (`skip='identity'`) or soft-gated connections (`skip='soft-gating'`)" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": 15, 385 | "id": "f063e3bf-34e5-4d7f-83f9-b3522aa6430b", 386 | "metadata": {}, 387 | "outputs": [ 388 | { 389 | "data": { 390 | "text/plain": [ 391 | "ModuleList(\n", 392 | " (0): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 393 | " (1): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 394 | " (2): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 395 | " (3): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 396 | ")" 397 | ] 398 | }, 399 | "execution_count": 15, 400 | "metadata": {}, 401 | "output_type": "execute_result" 402 | } 403 | ], 404 | "source": [ 405 | "tfno.fno_skips" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "id": "070e930e-38b6-4d3c-b62a-3ca700294c99", 411 | "metadata": {}, 412 | "source": [ 413 | "## Projection: going back to the target number of channels \n", 414 | "\n", 415 | "Finally, the projection layer takes the hidden dimension to projection_channels and to the actual number of output channels (here, 1)" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": 16, 421 | "id": "88344f47-a7e8-458e-9fbb-775804fbbaad", 422 | "metadata": {}, 423 | "outputs": [ 424 | { 425 | "data": { 426 | "text/plain": [ 427 | "Projection(\n", 428 | " (fc1): Conv2d(16, 256, kernel_size=(1, 1), stride=(1, 1))\n", 429 | " (fc2): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))\n", 430 | ")" 431 | ] 432 | }, 433 | "execution_count": 16, 434 | "metadata": {}, 435 | "output_type": "execute_result" 436 | } 437 | ], 438 | "source": [ 439 | "tfno.projection" 440 | ] 441 | }, 442 | { 443 | "cell_type": "code", 444 | "execution_count": null, 445 | "id": "7aae1ab6-852c-4720-9b3b-5791c2b42872", 446 | "metadata": {}, 447 | "outputs": [], 448 | "source": [] 449 | } 450 | ], 451 | "metadata": { 452 | "kernelspec": { 453 | "display_name": "Python 3 (ipykernel)", 454 | "language": "python", 455 | "name": "python3" 456 | }, 457 | "language_info": { 458 | "codemirror_mode": { 459 | "name": "ipython", 460 | "version": 3 461 | }, 462 | "file_extension": ".py", 463 | "mimetype": "text/x-python", 464 | "name": "python", 465 | "nbconvert_exporter": "python", 466 | "pygments_lexer": "ipython3", 467 | "version": "3.9.15" 468 | } 469 | }, 470 | "nbformat": 4, 471 | "nbformat_minor": 5 472 | } 473 | -------------------------------------------------------------------------------- /3-darcy_flow.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "4df7dcda-a364-4255-9339-a9a09c2a5e34", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "from pathlib import Path\n", 11 | "from neuralop.datasets import load_darcy_pt" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "id": "ff12d431-bde9-4eba-906b-d0faea8c49fb", 17 | "metadata": {}, 18 | "source": [ 19 | "# Load the data " 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 3, 25 | "id": "aa9c49f5-878b-4cac-9a35-b9dc53085d11", 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "data_path=\"/dli/task/bootcamp/data/darcy_flow/\"" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": null, 35 | "id": "f40e8c0a-c031-457b-863c-c728de7d1b80", 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "train_loader, test_loaders, output_encoder = load_darcy_pt(data_path, n_train=100, n_tests=[10], \n", 40 | " batch_size=3, test_batch_sizes=[3],\n", 41 | " test_resolutions=[32], train_resolution=32)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 8, 47 | "id": "2f29d90a-4fc7-4b83-8ed4-f1bb4dce2574", 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "train_dataset = train_loader.dataset" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "id": "21000189-ecac-42e2-b008-06eefa7b1710", 57 | "metadata": {}, 58 | "source": [ 59 | "# Visualizing the data " 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "id": "1cf47f09-1fb3-4667-9b04-a98b3ee8d08d", 65 | "metadata": {}, 66 | "source": [ 67 | "The data is stored in a dictionary" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 9, 73 | "id": "b6a9aed5-6532-42ba-8131-0307460c960d", 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "data = train_dataset[0]\n", 78 | "x = data['x']\n", 79 | "y = data['y']" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": 10, 85 | "id": "9f475172-62b0-4ce3-8dce-a7d0d9dca9fb", 86 | "metadata": {}, 87 | "outputs": [ 88 | { 89 | "data": { 90 | "text/plain": [ 91 | "torch.Size([3, 128, 128])" 92 | ] 93 | }, 94 | "execution_count": 6, 95 | "metadata": {}, 96 | "output_type": "execute_result" 97 | } 98 | ], 99 | "source": [ 100 | "x.shape" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "id": "7d7947ad-f98c-414b-8a12-64270988ad1f", 106 | "metadata": {}, 107 | "source": [ 108 | "`x` is of shape (3, height, width). \n", 109 | "\n", 110 | "This is because, in addition to the binary input, we appended a positional encoding, so the model knows the location of each pixel.\n", 111 | "\n", 112 | "Let's check the actual data:" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 8, 118 | "id": "077ebd7d-883b-4300-b13d-ed88813a3be1", 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "%matplotlib inline\n", 123 | "import matplotlib.pyplot as plt" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 10, 129 | "id": "814a044d-a52f-4cf2-aa1b-859370012af5", 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "data": { 134 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAqIAAAKzCAYAAADFi2/NAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOy9e7wcRZ02/lT1zDlJIAQSQi5ySQJBBARFLnKToICLgCiL7IpcRFbxRVRkd5GIaPDVRNGF+C6iL6ABiSCioKioyarg+oISEBcFfoACAYQQgZCEXE7OdNXvj7p0VXV1T8+cmTPnJN8nn86crq6uru7pmX7m+d6YlFKCQCAQCAQCgUAYZvBeT4BAIBAIBAKBsGWCiCiBQCAQCAQCoScgIkogEAgEAoFA6AmIiBIIBAKBQCAQegIiogQCgUAgEAiEnoCIKIFAIBAIBAKhJyAiSiAQCAQCgUDoCYiIEggEAoFAIBB6AiKiBAKBQCAQCISegIgogdAFvPvd78bYsWPxyiuvFPZ53/veh3q9jhdeeAHXXXcdGGN46qmnhm2OMTz11FNgjOG6666zbe3Obc6cOZgzZ05H5zda8f73vx8zZszo9TQsHn74YcybN6/n91u3MW/ePDDGej0NAoFQAiKiBEIXcPbZZ2Pjxo248cYbo9tXr16N2267DccffzymTJmC4447Dvfccw+mTZs2zDNtjnbndtVVV+Gqq67q0qxGFy655BLcdtttvZ6GxcMPP4xLL710syeiBAJh5KPW6wkQCJsjjj32WEyfPh3f+ta3cO655+a233TTTdiwYQPOPvtsAMDkyZMxefLk4Z5mJbQ7tz333LMLsxmd2HXXXXs9BQKBQBiRIEWUQOgCkiTBmWeeifvvvx9/+tOfctsXLVqEadOm4dhjjwUQN38/8MADOP7447HDDjugv78f06dPx3HHHYdnn30WQNyMbsAYw7x58+z6X/7yF5x11lmYPXs2xo0bh9e85jU44YQTonMLEc7tzjvvBGMsurjm59A0b+b7la98BZdffjlmzpyJrbfeGgcffDB+97vf5Y57zTXXYPfdd0d/fz/23HNP3HjjjZVN3EIIXHbZZdhjjz3Q39+PHXbYAWeccYa9du4c9957byxbtgyHH344xo0bh1mzZuGLX/wihBBe3zVr1uDf/u3fMHPmTPT19eE1r3kNzj//fKxbt67pfGLzZozhvPPOww033IDXve51GDduHPbdd1/85Cc/8foZ8/IDDzyAk046Cdtssw0mTJiA0047DX//+99zY7rvu8GMGTPw/ve/H4B6P9/znvcAAI488kj73sXuI4O///3v+NCHPoSddtoJ/f39mDx5Mg499FD813/9l+2zdOlSnHjiidhxxx0xZswY7LbbbjjnnHPw4osvRs/nwQcfxHve8x5MmDABEydOxAUXXIBGo4FHH30U//AP/4Dx48djxowZuOyyy7z9zf23ePFiXHDBBZg6dSrGjh2LI444Ag888EDhObi4+eabcfDBB2OrrbbC1ltvjbe//e2V9yUQCJ0FEVECoUv4wAc+AMYYvvWtb3ntDz/8MO69916ceeaZSJIkuu+6detw9NFH44UXXsDXvvY1LF26FAsXLsTOO++MtWvXtjyX5557DpMmTcIXv/hF/PznP8fXvvY11Go1HHTQQXj00UdbGmu//fbDPffc4y3f/va3Ua/XsddeezXd3z2f73znO1i3bh3e8Y53YPXq1bbP1VdfjQ996EPYZ599cOutt+LTn/40Lr30Utx5552V5vi//tf/wic/+UkcffTRuP322/G///f/xs9//nMccsghOWK0YsUKvO9978Npp52G22+/Hcceeyzmzp2LxYsX2z7r16/HEUccgeuvvx4f+9jH8LOf/Qyf/OQncd111+Gd73wnpJTVLl6An/70p7jyyivxuc99Dj/4wQ8wceJEvPvd78YTTzyR6/vud78bu+22G77//e9j3rx5+OEPf4i3v/3tGBwcbOmYxx13HObPnw9AvRfmPTzuuOMK9zn99NPxwx/+EJ/5zGewZMkSXHvttTjqqKPw0ksv2T5//etfcfDBB+PrX/86lixZgs985jP4/e9/j8MOOyw6x1NOOQX77rsvfvCDH+CDH/wgrrjiCnziE5/Au971Lhx33HG47bbb8Na3vhWf/OQnceutt+b2/9SnPoUnnngC1157La699lo899xzmDNnTvTauZg/fz7e+973Ys8998T3vvc93HDDDVi7di0OP/xwPPzww1UvI4FA6BQkgUDoGo444gi5/fbby02bNtm2f/3Xf5UA5GOPPWbbFi1aJAHIJ598Ukop5X333ScByB/+8IeFYz/55JMSgFy0aFFuGwD52c9+tnDfRqMhN23aJGfPni0/8YlPlI4Zzi3ECy+8IGfNmiX32msvuWrVKu/cjzjiiNzYr3/962Wj0bDt9957rwQgb7rpJimllGmayqlTp8qDDjrIO87y5ctlvV6Xu+yyS+F5SSnlI488IgHIc88912v//e9/LwHIT33qU94cAcjf//73Xt8999xTvv3tb7frCxYskJxzuWzZMq/f97//fQlA3nHHHaVzOvPMM3PzBiCnTJki16xZY9tWrFghOedywYIFtu2zn/2sBOC9T1JK+Z3vfEcCkIsXL/bGjL3vu+yyizzzzDPt+i233CIByF//+tel8zbYeuut5fnnn1+pr5RSCiHk4OCgXL58uQQgf/SjH+XO5z/+4z+8fd7whjdIAPLWW2+1bYODg3Ly5MnypJNOsm2//vWvJQC53377SSGEbX/qqadkvV6X//Iv/5I7lsHTTz8ta7Wa/OhHP+ode+3atXLq1KnylFNOqXyOBAKhMyBFlEDoIs4++2y8+OKLuP322wEAjUYDixcvxuGHH47Zs2cX7rfbbrthu+22wyc/+Ul84xvfGLJS02g0MH/+fOy5557o6+tDrVZDX18fHn/8cTzyyCNtj7tu3Tocd9xx2LhxI372s59h2223bbrPcccd5ynB++yzDwBg+fLlAIBHH30UK1aswCmnnOLtt/POO+PQQw9tOv6vf/1rALCmaIMDDzwQr3vd6/DLX/7Sa586dSoOPPBAr22fffax8wGAn/zkJ9h7773xhje8AY1Gwy5vf/vbwRirrNSGOPLIIzF+/Hi7PmXKFOywww7esQ3e9773eeunnHIKarWaPd9u4sADD8R1112Hz3/+8/jd734XVThXrlyJD3/4w9hpp51Qq9VQr9exyy67AED0Hjv++OO99de97nVgjFl3FQCo1WrYbbfdotfj1FNP9SLid9llFxxyyCGl1+MXv/gFGo0GzjjjDO99HDNmDI444oi230cCgdA+iIgSCF3EySefjAkTJmDRokUAgDvuuAMvvPCCDVIqwoQJE3DXXXfhDW94Az71qU9hr732wvTp0/HZz362ZVMsAFxwwQW45JJL8K53vQs//vGP8fvf/x7Lli3Dvvvuiw0bNrR1bo1GAyeffDIee+wx3HHHHdhpp50q7Tdp0iRvvb+/HwDsPIy5d8qUKbl9Y20hzP6xKP/p06d75uTYfMyc3Ovywgsv4MEHH0S9XveW8ePHQ0qZM/dXRZVjG0ydOtVbr9VqmDRpUu58uoGbb74ZZ555Jq699locfPDBmDhxIs444wysWLECgPLJPeaYY3DrrbfiwgsvxC9/+Uvce++91vc3dj4TJ0701vv6+jBu3DiMGTMm175x48bc/uH1MG1l1+OFF14AABxwwAG59/Lmm29u+30kEAjtg6LmCYQuYuzYsXjve9+La665Bs8//zy+9a1vYfz48TZYpAyvf/3r8d3vfhdSSjz44IO47rrr8LnPfQ5jx47FRRddZB/YAwMD3n6xB/HixYtxxhlnWN9AgxdffLGSihnDhz70Ifzyl7/EHXfcgX333betMWIw5MyQBheG+FTZ//nnn8eOO+7obXvuueew/fbbtzyn7bffHmPHjs35+7rbu40VK1bgNa95jV1vNBp46aWXPDLb39+fux+A+D3RCrbffnssXLgQCxcuxNNPP43bb78dF110EVauXImf//zn+POf/4z/+Z//wXXXXYczzzzT7veXv/xlSMctQ+xeWLFiRZTcG5j36fvf/75VawkEQm9BiiiB0GWcffbZSNMUX/7yl3HHHXfgn//5nzFu3LjK+zPGsO++++KKK67Atttuiz/84Q8AlDo4ZswYPPjgg17/H/3oR9ExjPJo8NOf/hR/+9vf2jgj4NOf/jQWLVpkg1Y6ide+9rWYOnUqvve973ntTz/9NO6+++6m+7/1rW8FAC/YCACWLVuGRx55BG9729tantPxxx+Pv/71r5g0aRL233//3DIcyeq/853veOvf+9730Gg0vMwEM2bMyN0Pv/rVr/Dqq696baEK3Qp23nlnnHfeeTj66KPtvWhM5OE99n//7/9tefyquOmmm7wgseXLl+Puu+8uLaLw9re/HbVaDX/961+j7+P+++/ftfkSCIQ4SBElELqM/fffH/vssw8WLlwIKWVTszygfBKvuuoqvOtd78KsWbMgpcStt96KV155BUcffTQA9fA/7bTT8K1vfQu77ror9t13X9x7773RJPrHH388rrvuOuyxxx7YZ599cP/99+PLX/5yTjGsgltuuQVf+MIXcPLJJ2P33Xf3Ui/19/fjjW98Y8tjuuCc49JLL8U555yDk08+GR/4wAfwyiuv4NJLL8W0adPAefnv59e+9rX40Ic+hP/8z/8E5xzHHnssnnrqKVxyySXYaaed8IlPfKLlOZ1//vn4wQ9+gLe85S34xCc+gX322QdCCDz99NNYsmQJ/vVf/xUHHXRQu6dcCbfeeitqtRqOPvpoPPTQQ7jkkkuw7777er60p59+Oi655BJ85jOfwRFHHIGHH34YV155JSZMmOCNtffeewNQ2QnGjx+PMWPGYObMmVE1cfXq1TjyyCNx6qmnYo899sD48eOxbNky/PznP8dJJ50EANhjjz2w66674qKLLoKUEhMnTsSPf/xjLF26tGvXY+XKlXj3u9+ND37wg1i9ejU++9nPYsyYMZg7d27hPjNmzMDnPvc5XHzxxXjiiSfwD//wD9huu+3wwgsv4N5778VWW22FSy+9tGtzJhAIeRARJRCGAWeffTY+/vGPY88996xEWGbPno1tt90Wl112GZ577jn09fXhta99bc70+R//8R8AgMsuuwyvvvoq3vrWt+InP/lJTqH76le/inq9jgULFuDVV1/FfvvtZ9MitYqHHnoIgDJvfv/73/e27bLLLh2p1vOhD30IjDFcdtllePe7340ZM2bgoosuwo9+9CM8/fTTTff/+te/jl133RXf/OY38bWvfQ0TJkzAP/zDP2DBggWlptsibLXVVvjv//5vfPGLX8TVV1+NJ598EmPHjsXOO++Mo446algU0VtvvRXz5s3D17/+dTDGcMIJJ2DhwoXo6+uzff793/8da9aswXXXXYevfOUrOPDAA/G9730PJ554ojfWzJkzsXDhQnz1q1/FnDlzkKYpFi1alAvwAoAxY8bgoIMOwg033ICnnnoKg4OD2HnnnfHJT34SF154IQCgXq/jxz/+MT7+8Y/jnHPOQa1Ww1FHHYX/+q//ws4779yV6zF//nwsW7YMZ511FtasWYMDDzwQ3/3ud5sWD5g7dy723HNPfPWrX8VNN92EgYEBTJ06FQcccAA+/OEPd2WuBAKhGEzKNhPgEQgEwjDilVdewe677453vetduPrqq3s9nWHDvHnzcOmll+Lvf//7sPiijnTceeedOPLII3HLLbfg5JNP7vV0CATCEEGKKIFAGHFYsWIFvvCFL+DII4/EpEmTsHz5clxxxRVYu3YtPv7xj/d6egQCgUDoEIiIEgiEEYf+/n489dRTOPfcc/Hyyy9j3LhxePOb34xvfOMblao3EQgEAmF0gEzzBAKBQCAQCISegNI3EQgEAoFAIBB6AiKiBAKBQCAQCISegIgogUAgEAgEAqEnICJKIBAIBAKBQOgJiIgSCAQCgUAgEHoCIqIEAoFAIBAIhJ6AiCiBQCAQCAQCoScgIkogEAgEAoFA6AmIiBIIBAKBQCAQegIiogQCgUAgEAiEnoCIKIFAIBAIBAKhJyAiSiAQCAQCgUDoCYiIEggEAoFAIBB6AiKiBAKBQCAQCISegIgogUAgEAgEAqEnICJK6Dquu+46MMbw1FNP9XoqAID169dj3rx5uPPOO3s9FQKBQGgL9L1K2FxARJTQdRx33HG45557MG3atF5PBYD6wrz00kvpC5NAIIxa0PcqYXNBrdcTIGz+mDx5MiZPntzraRAIBMJmA/peJWwuIEWU0HXETEhz5szB3nvvjWXLluHwww/HuHHjMGvWLHzxi1+EEML2u/POO8EYw+LFi3HBBRdg6tSpGDt2LI444gg88MAD3nHmzJmDOXPm5I7//ve/HzNmzAAAPPXUU/bL+9JLLwVjDIwxvP/97y+c/4c//GGMGTMG999/v20TQuBtb3sbpkyZgueff771i0IgEAhDwGj+Xn311Vex7bbb4pxzzslte+qpp5AkCb785S+3dkEIoxZERAk9w4oVK/C+970Pp512Gm6//XYce+yxmDt3LhYvXpzr+6lPfQpPPPEErr32Wlx77bV47rnnMGfOHDzxxBMtHXPatGn4+c9/DgA4++yzcc899+Cee+7BJZdcUrjPwoUL8brXvQ6nnHIKXnnlFQCwJqjFixePGNMYgUAgjIbv1a233hof+MAH8J3vfAerV6/2tl111VXo6+vDBz7wgZbmQBi9INM8oWd46aWXcMcdd+DAAw8EABx11FG48847ceONN+KMM87w+k6ePBm33XYbGGMAgMMOOwyzZ8/GggULcM0111Q+Zn9/P970pjcBAHbccUe8+c1vbrrPmDFjcMstt+BNb3oTzjrrLJx33nn4/Oc/j0996lM4+uijKx+bQCAQuo3R8r163nnn4atf/SoWLVqE888/HwCwceNGfOtb38J73/teTJo0qfLxCaMbpIgSeoapU6faL0uDffbZB8uXL8/1PfXUU+2XJQDssssuOOSQQ/DrX/+66/MEgN122w3XXHMNfvjDH+L444/H4Ycfjnnz5g3LsQkEAqEqRsv36qxZs3D88cfjqquugpQSAHDjjTfipZdewnnnndf14xNGDoiIEnqG2C/e/v5+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4mL86Ec/wj/+8Q/XPF988QUuu+wylJeXIzc3FyUlJTj77LOTqtJ+8MEHGDt2LIqLi5GXl4eBAwfixRdfjNrmFStW4LrrrkPHjh3Rvn17TJw4Efv27UNtbS3Gjx+Po48+GmVlZbjjjjvQ1NQUsS5d13H//feje/fuyMvLw5AhQ/DXv/41Yr7NmzdjwoQJ6Ny5M3Jzc3H88cfjd7/7XcR8//znP3HeeeehXbt26NSpE2644Qbs2bMnYj4Rwfz581FRUYG8vDwMGjQIf/nLXyLmi3coaePGjbj88stRVFSEkpISTJ482fVvEgC+//57XHPNNSguLsZRRx2FCy64AF988UXCfxNEba2tYml4EgoA5eXl6Nq1K7Zt2+aarpTCLbfcgqeffhrHH3882rVrhwEDBuC1116LWMbrr7+Ok046Cbm5uejZs2eLTuupqqpC//798e677+LUU09Ffn4+unTpgnvuuSdiG7/77jvcdNNN6NKlC3JycnDMMcdgxowZaGhocM0X73sgHhHBI488gpNOOgn5+fno0KEDfvKTn0TEeqvN7733HoYPH26f5rBo0SL78xg0aBDatWuHyspKvPnmm1HXt23bNowbNw7t27dHUVERfvrTn9pFF6cXXngBw4YNQ0FBAY466iice+652LBhQ8R8ixcvxnHHHWfH4aeeeirqerdv347x48ejsLAQRUVFuPTSS1FbWxsxX7RD8z169MCYMWPw5ptvYtCgQcjPz0ffvn3xxBNPRLx/9erVGDZsGPLy8ux9+vjjj0MphS+//DJq2zKWUMp89tlnUlhYKOPGjRMRkWAwKGeddZZ07txZtm/fbs9XU1MjAGTSpEktWv7atWsFgCxatCjitTVr1ohSSi677DJ54403ZMWKFbJo0SK58sorRUSkrq5OFi1aJADkF7/4hbz33nvy3nvvybZt22Kuz5q/W7duMnnyZPnLX/4if/jDH6Rz587SrVs32b17tz3vnDlzBIBcfvnl8vrrr8tTTz0lxxxzjBQVFclnn31mz3fcccfJscceK08//bSsWrVK/ud//kemTZsmK1eujLvtK1askJycHDn99NPlhRdekDfffFOuuuqqiM/DanPPnj1l2rRpsnz5cpk3b54EAgG5/PLLZdCgQTJ79myprq6Wu+66SwDI//2//9d+v7VvunXrJqeddpr8z//8j/zpT3+Sk08+WbKzs2XNmjX2vBs3bpSioiKprKyUp556SpYvXy7Tpk0TTdNk5syZ9ny1tbXSuXNn6dKliyxatEjeeOMNueKKK6R79+4CwLXt9913nwCQa665xv68u3TpIqWlpTJixIiIdjq33XrvcccdJ/fee69UV1fLggULJDc3V66++mp7vmAwKKeddprk5eXJAw88IMuXL5dZs2ZJ7969BYDcd999cfcFUVtr61hq+de//iWapsl//Md/uKYDkB49esgpp5wiL774orzxxhtSVVUlWVlZ8q9//cue76233pJAICCnnXaaLF261I4V1t92IiNGjJCOHTtKeXm5/OY3v5Fly5bJbbfdJgDk5ptvtuc7cOCAnHjiiVJQUCC/+tWvZPny5XLPPfdIVlaWnH/++fZ8ib4H4rnuuuskOztbpk2bJm+++aY899xz0rdvXykpKZHa2tqINh933HGycOFCWbZsmYwZM0YAyKxZs6SyslKef/55eeONN+TUU0+V3Nxc+frrr+33W3GqoqJCfvazn8myZctkwYIFUlBQIAMHDpTGxkZ73vvvv1+UUjJ58mR57bXXZOnSpTJs2DApKCiQjRs32vNZcf+iiy6SV199VZ555hk59thjpVu3blJRUWHPt3//fjn++OOlqKhIfvvb39qft7W/osVTp4qKCunatauccMIJ8tRTT8myZcvkkksuEQCyatUqe76PPvpI8vLy5MQTT5QlS5bIK6+8Iueff7706NFDAEhNTU3C/ZFJmIim2AsvvCAA5KGHHpJ7771XNE2T5cuXu+b58ssvJRAIyOTJk1u07HiJ6K9+9SsBIN9///0hvT8a64/7Rz/6kWv6//7v/woAmT17toiI7N69W/Lz810BUURk69atkpubKxMmTBARkW+//db+bFqqb9++MnDgQGlqanJNHzNmjJSVlUkwGHS1+dZbb3XNd/HFFwsAWbBggWv6SSedJIMGDbLHrS+28vJyOXDggD29vr5eiouL5ZxzzrGnnXvuudK1a1epq6tzLfOWW26RvLw8+e6770RE5K677hKllHz44Yeu+UaOHOlKRHfv3i15eXkxP+9kE9H58+e73n/TTTdJXl6e6LouIiKvv/66AJBHH33UNd/cuXOZiJJntGUsFRFpamqSqqoqad++vWzdutX1GgApKSmR+vp6e1ptba1omiZz5861pw0dOjRmrEg2EQUgf/7zn13Tr7vuOtE0TbZs2SIiIo899pgAkBdffNE137x58wSA/bkk8z0QzXvvvRfxo1xEZNu2bZKfny933nlnRJs/+OADe9quXbskEAhIfn6+K+n88MMPBYD85je/sadZcSo8+X/22WcFgDzzzDMiYnx/ZGVlRcTyPXv2SGlpqYwfP15EjB8p5eXlMmjQIDvGiRj/NrKzs12J6KOPPhrz8042Ec3Ly7P3i4jxI6G4uFiuv/56e9oll1wiBQUF8u9//9ueFgwG5YQTTjgiE1Eemk+x8ePH48Ybb8TPfvYzzJ49Gz//+c8xcuRI1zwVFRVobm7GwoULW2291mH38ePH48UXX8TXX3/dasu+4oorXOPDhw9HRUUFVq5cCQB47733cODAAVx11VWu+bp164azzjrLPqRdXFyMXr164b/+67+wYMECbNiwAbquJ1z/559/jn/+8592O5qbm+3h/PPPx44dO7Bp0ybXe8aMGeMaP/744wEg4uKe448/Hlu2bIlY57hx45CXl2ePFxYW4sILL8Q777yDYDCIgwcP4q9//St+9KMfoV27dhFtOnjwIN5//30AwMqVK9GvXz8MGDDAtY4JEya4xt977z0cPHgw5uedrLFjx7rGTzzxRBw8eBA7d+4EAKxatQqA8W/F6fLLL096HURtrS1jqYjgmmuuwbvvvounnnoK3bp1i5jnzDPPRGFhoT1eUlKCzp072/Fi3759WLt2bcxYkazCwsKIv9kJEyZA13W88847AIAVK1agoKAAP/nJT1zzWTHXirGH+j3w2muvQSmFn/70p65YVlpaigEDBkT07FFWVobBgwfb48XFxejcuTNOOukklJeX29OtuBstxobHufHjxyMrK8v+Xlm2bBmam5sxceJEV5vy8vIwYsQIu02bNm3C9u3bMWHCBNeh9IqKCgwfPty1jpUrV8b8vJN10kknoXv37vZ4Xl4e+vTp49rGVatW4ayzzkKnTp3saZqmRcTcIwUT0TSYPHkympqakJWVhdtuuy0l6zzjjDPw8ssv23+4Xbt2Rf/+/Vvl4qbS0tKo03bt2gUA9mNZWVnEfOXl5fbrSin89a9/xbnnnov58+dj0KBB+MEPfoDbbrst6vmSlm+++QYAcMcddyA7O9s13HTTTQAQ0RVIcXGxazwnJyfm9IMHDya9zY2Njdi7dy927dqF5uZm/Pa3v41ok9W7gdWmXbt2xVyek/U5JTNvPB07dnSN5+bmAgAOHDhgrycrKyvisygpKUl6HUSp0BaxVERw7bXX4plnnsHixYtx0UUXRZ0v/O8IMP6WrL+j3bt3Q9f1w/57jfZ3Z73fGWNLS0sjzlns3LkzsrKy7PkO9Xvgm2++gYigpKQkIp69//77CeMrYMTSWHE3mRiblZWFjh072ttixf2TTz45ok0vvPCCK75GW160abt27Yr7eScj0b+LeOs5UmMsr5pPsX379uHKK69Enz598M033+Daa6/Fn//855Ss+6KLLsJFF12EhoYGvP/++5g7dy4mTJiAHj16YNiwYYe83GgnctfW1uLYY48FEPrD3LFjR8R827dvd/0qrKiosKsXn332GV588UXMnDkTjY2NeOyxx6Ku33r/9OnTMW7cuKjzHHfccS3YosRibXNOTg6OOuooZGdnIxAI4Morr8TNN98cdRk9e/YEYHw+sZbnZH2OseZNpj+8ZHTs2BHNzc347rvvXF8c0dZLlC5tEUutJHTRokVYuHAhfvrTnx7ysjp06AClVFJ/2/FYCVe091sxoWPHjvh//+//QURcyejOnTvR3NzsirGH8j3QqVMnKKXw7rvv2j9cnaJNO1y1tbXo0qWLPd7c3Ixdu3bZ22xt03//93/HPSKUKG6Gz/u3v/0t4XyHq2PHjnH365GGFdEUu+GGG7B161YsXboUCxcuxCuvvIIHH3wwpW3Izc3FiBEjMG/ePACwrzAMr4wl69lnn3WNr1mzBlu2bLE7WB82bBjy8/PxzDPPuOb76quvsGLFCpx99tlRl9unTx/84he/QGVlJdavXx9z/ccddxx69+6Njz76CEOGDIk6OA+htYalS5e6fsXv2bMHr776Kk4//XQEAgG0a9cOZ555JjZs2IATTzwxapusAHnmmWdi48aN+Oijj1zreO6551zjp556KvLy8mJ+3q1lxIgRAIyrUZ2WLFnSausgOlytHUtFBNdddx0WLVqE3//+97j66qsPq30FBQU45ZRTYsaKZO3ZswevvPKKa9pzzz0HTdNwxhlnAADOPvts7N27Fy+//LJrPuvK8GgxNtb3QDRjxoyBiODrr7+OGssqKyuT3p5khce5F198Ec3Nzfb3yrnnnousrCz861//ihn3AeP7oaysDM8//zxExF7eli1bsGbNGtc6zjzzzJifd2saMWIEVqxY4aok67qOP/3pT626Hr9gRTSFHn/8cTzzzDNYtGgR+vXrh379+uGWW27BXXfdhR/+8Ic45ZRTABh/IL169cKkSZOSOrfpv//7vwHA7kbjgw8+wFFHHQUA9jlD9957L7766iucffbZ6Nq1K77//nv8+te/RnZ2tp149OrVC/n5+Xj22Wdx/PHH46ijjkJ5ebnrnJ5oPvjgA1x77bW45JJLsG3bNsyYMQNdunSxD4sfffTRuOeee/Dzn/8cEydOxOWXX45du3Zh1qxZyMvLw3333QcA+Pjjj3HLLbfgkksuQe/evZGTk4MVK1bg448/xt133x23Db///e8xevRonHvuubjqqqvQpUsXfPfdd/jHP/6B9evXt/ofeCAQwMiRIzF16lTouo558+ahvr4es2bNsuf59a9/jdNOOw2nn346brzxRvTo0QN79uzB559/jldffRUrVqwAAEyZMgVPPPEELrjgAsyePRslJSV49tln8c9//tO1zg4dOuCOO+7A7NmzXZ/3zJkzW3ToKJHzzjsPP/zhDzFt2jTU19dj8ODBeO+99+wvtZZ0GUbUFtoilt52221YuHAhJk+ejMrKSvscbsBI2gYOHNjidv7nf/4nzjvvPIwcORLTpk1DMBjEvHnzUFBQgO+++y6pZXTs2BE33ngjtm7dij59+uCNN97AH//4R9x44432uYgTJ07E7373O0yaNAlffvklKisrsXr1asyZMwfnn38+zjnnHADJfQ9E88Mf/hD/5//8H1x99dX44IMPcMYZZ6CgoAA7duzA6tWrUVlZiRtvvLHFn088S5cuRVZWFkaOHImNGzfinnvuwYABA+zzKHv06IFf/vKXmDFjBr744gucd9556NChA7755hv87W9/Q0FBAWbNmgVN0/Cf//mfuPbaa/GjH/0I1113Hb7//vuocXPixIl48MEHMXHiRNx///3o3bs33njjDSxbtqxVt23GjBl49dVXcfbZZ2PGjBnIz8/HY489hn379gE4AmNs+q6TOrJ8/PHHkp+fH9GNyMGDB2Xw4MHSo0cPu7ujlnY5AiDmYHnttddk9OjR0qVLF8nJyZHOnTvL+eefL++++65rWc8//7z07dtXsrOzE14hbV2Bvnz5crnyyivl6KOPtq+O37x5c8T8jz/+uJx44omSk5MjRUVFctFFF7m62Pjmm2/kqquukr59+0pBQYEcddRRcuKJJ8qDDz4ozc3NCT+Hjz76SMaPHy+dO3eW7OxsKS0tlbPOOksee+yxiDavXbvW9V7rCkjnVYwiIpMmTZKCggJ73No38+bNk1mzZknXrl0lJydHBg4cKMuWLYtoU01NjUyePFm6dOki2dnZ8oMf/ECGDx9u9yhg+fvf/y4jR46UvLw8KS4ulmuuuUb+/Oc/R3TfpOu6zJ07V7p16yY5OTly4oknyquvviojRoxI+qr58G20PhPnlZrfffedXH311XL00UdLu3btZOTIkfL+++8LAPn1r38dcx8QtbW2iqUVFRUx46jzymoRieg+ybmM8HW98sordtzr3r27PPDAA1GvuI5mxIgR0q9fP3n77bdlyJAhkpubK2VlZfLzn/88ooeQXbt2yQ033CBlZWWSlZUlFRUVMn36dDl48KA9T7LfA7E88cQTMnToUCkoKJD8/Hzp1auXTJw40XWFvNXmaJ/NBRdcEDE9/LO0Ppt169bJhRdeKEcddZQUFhbK5ZdfLt98803E+19++WU588wzpX379pKbmysVFRXyk5/8RN566y3XfI8//rj07t1bcnJypE+fPvLEE0/IpEmTIvbtV199JT/+8Y/t9f74xz+WNWvWJH3VfLRtDI/PIiLvvvuuDB06VHJzc6W0tFR+9rOf2b0ctLRXA79TIo5aNVELLF68GFdffTXWrl1rHwahzPXcc8/hiiuuwP/+7/9GXG1KRK2vqqoK3377LT799NN0N4VSYNSoUfjyyy/x2WefpbspKcVD80QU4fnnn8fXX3+NyspKaJqG999/H//1X/+FM844g0koEdFhmjp1KgYOHIhu3brhu+++w7PPPovq6upW7bbRL5iIElGEwsJCLFmyBLNnz8a+fftQVlaGq666CrNnz05304iIfC8YDOLee+9FbW0tlFI44YQT8PTTTx9WTw1+xUPzRERERJQWab0065FHHkHPnj2Rl5eHwYMH4913301nc4iIfI9xlYj8JG2J6AsvvIApU6ZgxowZ2LBhA04//XSMHj0aW7duTVeTiIh8jXGViPwmbYfmhw4dikGDBuHRRx+1px1//PG4+OKLMXfu3HQ0iYjI1xhXichv0nKxUmNjI9atWxfRSfmoUaMi7nQQja7r2L59OwoLCyPurUtEFE5EsGfPHpSXl2ds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4+k80TCu+kOmbQ+QeduUadsDtG1c9WVFVNM0dOnSBQDQvn37jNnRlkzbpkzbHiDztinTtgeI3CZWQuNjXPWXTNseIPO2KdO2B2ibuMrSABERERGlBRNRIiIiIkoL3yaiubm5uO+++5Cbm5vuprSaTNumTNseIPO2KdO2B8jMbUqVTPzsMm2bMm17gMzbpkzbHqBtt8mXFysRERERkf/5tiJKRERERP7GRJSIiIiI0oKJKBERERGlBRNRIiIiIkoL3yaijzzyCHr27Im8vDwMHjwY7777brqblJS5c+fi5JNPRmFhITp37oyLL74YmzZtcs1z1VVXQSnlGk499dQ0tTi+mTNnRrS1tLTUfl1EMHPmTJSXlyM/Px9VVVXYuHFjGlucWI8ePSK2SSmFm2++GYD3988777yDCy+8EOXl5VBK4eWXX3a9nsw+aWhowK233opOnTqhoKAAY8eOxVdffZXCrXCLt01NTU246667UFlZiYKCApSXl2PixInYvn27axlVVVUR++2yyy5L8ZZ4G+Oqd2RabGVcZVyNxZeJ6AsvvIApU6ZgxowZ2LBhA04//XSMHj0aW7duTXfTElq1ahVuvvlmvP/++6iurkZzczNGjRqFffv2ueY777zzsGPHDnt444030tTixPr16+dq6yeffGK/Nn/+fCxYsAAPP/ww1q5di9LSUowcOdK+r7UXrV271rU91dXVAIBLLrnEnsfL+2ffvn0YMGAAHn744aivJ7NPpkyZgpdeeglLlizB6tWrsXfvXowZMwbBYDBVm+ESb5v279+P9evX45577sH69euxdOlSfPbZZxg7dmzEvNddd51rv/3+979PRfN9gXHVezIptjKuMq7GJD50yimnyA033OCa1rdvX7n77rvT1KJDt3PnTgEgq1atsqdNmjRJLrroovQ1qgXuu+8+GTBgQNTXdF2X0tJSeeCBB+xpBw8elKKiInnsscdS1MLDd/vtt0uvXr1E13UR8df+ASAvvfSSPZ7MPvn+++8lOztblixZYs/z9ddfi6Zp8uabb6as7bGEb1M0f/vb3wSAbNmyxZ42YsQIuf3229u2cT7GuOotmR5bGVcZVy2+q4g2NjZi3bp1GDVqlGv6qFGjsGbNmjS16tDV1dUBAIqLi13T3377bXTu3Bl9+vTBddddh507d6ajeUnZvHkzysvL0bNnT1x22WX44osvAAA1NTWora117avc3FyMGDHCN/uqsbERzzzzDCZPngyllD3dT/vHKZl9sm7dOjQ1NbnmKS8vR//+/X2z3+rq6qCUwtFHH+2a/uyzz6JTp07o168f7rjjDs9Wj1KNcdWbMjW2Mq4aGFcNWa3YxpT49ttvEQwGUVJS4ppeUlKC2traNLXq0IgIpk6ditNOOw39+/e3p48ePRqXXHIJKioqUFNTg3vuuQdnnXUW1q1b57k7NQwdOhRPPfUU+vTpg2+++QazZ8/G8OHDsXHjRnt/RNtXW7ZsSUdzW+zll1/G999/j6uuusqe5qf9Ey6ZfVJbW4ucnBx06NAhYh4//I0dPHgQd999NyZMmID27dvb06+44gr07NkTpaWl+PTTTzF9+nR89NFH9iHCIxnjqvf+bjM5tjKuuufxw99YW8ZV3yWiFuevKMAIPuHTvO6WW27Bxx9/jNWrV7umX3rppfbz/v37Y8iQIaioqMDrr7+OcePGpbqZcY0ePdp+XllZiWHDhqFXr1548skn7RPN/byvFi5ciNGjR6O8vNye5qf9E8uh7BM/7LempiZcdtll0HUdjzzyiOu16667zn7ev39/9O7dG0OGDMH69esxaNCgVDfVk/z8t2rJhLgKZHZsZVxt2Tzp1tZx1XeH5jt16oRAIBDxC2Lnzp0Rv0a87NZbb8Urr7yClStXomvXrnHnLSsrQ0VFBTZv3pyi1h26goICVFZWYvPmzfYVnn7dV1u2bMFbb72Fa6+9Nu58fto/yeyT0tJSNDY2Yvfu3THn8aKmpiaMHz8eNTU1qK6udv1qj2bQoEHIzs72xX5ra4yr3pcpsZVxlXE1nO8S0ZycHAwePDii7FtdXY3hw4enqVXJExHccsstWLp0KVasWIGePXsmfM+uXbuwbds2lJWVpaCFh6ehoQH/+Mc/UFZWZpfrnfuqsbERq1at8sW+WrRoETp37owLLrgg7nx+2j/J7JPBgwcjOzvbNc+OHTvw6aefena/WcFy8+bNeOutt9CxY8eE79m4cSOampp8sd/aGuOq92VKbGVcZVyNcFiXOqXJkiVLJDs7WxYuXCh///vfZcqUKVJQUCBffvllupuW0I033ihFRUXy9ttvy44dO+xh//79IiKyZ88emTZtmqxZs0Zqampk5cqVMmzYMOnSpYvU19enufWRpk2bJm+//bZ88cUX8v7778uYMWOksLDQ3hcPPPCAFBUVydKlS+WTTz6Ryy+/XMrKyjy5LU7BYFC6d+8ud911l2u6H/bPnj17ZMOGDbJhwwYBIAsWLJANGzbYVzoms09uuOEG6dq1q7z11luyfv16Oeuss2TAgAHS3NzsuW1qamqSsWPHSteuXeXDDz90/V01NDSIiMjnn38us2bNkrVr10pNTY28/vrr0rdvXxk4cGDatslrGFe9JRNjK+Mq42o0vkxERUR+97vfSUVFheTk5MigQYNc3XR4GYCow6JFi0REZP/+/TJq1Cj5wQ9+INnZ2dK9e3eZNGmSbN26Nb0Nj+HSSy+VsrIyyc7OlvLychk3bpxs3LjRfl3XdbnvvvuktLRUcnNz5YwzzpBPPvkkjS1OzrJlywSAbNq0yTXdD/tn5cqVUf+NTZo0SUSS2ycHDhyQW265RYqLiyU/P1/GjBmT1m2Mt001NTUx/65WrlwpIiJbt26VM844Q4qLiyUnJ0d69eolt912m+zatStt2+RFjKvekYmxlXGVcTUaJSKSfP2UiIiIiKh1+O4cUSIiIiLKDExEiYiIiCgtmIgSERERUVowESUiIiKitGAiSkRERERpwUSUiIiIiNKCiSgRERERpQUTUSIiIiJKCyaiRERERJQWTESJiIiIKC2YiBIRERFRWjARJSIiIqK0+P+/3HhFahDzfwAAAABJRU5ErkJggg==", 135 | "text/plain": [ 136 | "
" 137 | ] 138 | }, 139 | "metadata": {}, 140 | "output_type": "display_data" 141 | } 142 | ], 143 | "source": [ 144 | "# Which sample to view\n", 145 | "index = 10\n", 146 | "\n", 147 | "data = train_dataset[index]\n", 148 | "x = data['x']\n", 149 | "y = data['y']\n", 150 | "fig = plt.figure(figsize=(7, 7))\n", 151 | "ax = fig.add_subplot(2, 2, 1)\n", 152 | "ax.imshow(x[0], cmap='gray')\n", 153 | "ax.set_title('input x')\n", 154 | "ax = fig.add_subplot(2, 2, 2)\n", 155 | "ax.imshow(y.squeeze())\n", 156 | "ax.set_title('input y')\n", 157 | "ax = fig.add_subplot(2, 2, 3)\n", 158 | "ax.imshow(x[1])\n", 159 | "ax.set_title('x: 1st pos embedding')\n", 160 | "ax = fig.add_subplot(2, 2, 4)\n", 161 | "ax.imshow(x[2])\n", 162 | "ax.set_title('x: 2nd pos embedding')\n", 163 | "fig.suptitle('Visualizing one input sample', y=0.98)\n", 164 | "plt.tight_layout()\n", 165 | "fig.show()" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "id": "ba9e2a5c-98e7-47c0-9e24-7a8e41c657dc", 172 | "metadata": {}, 173 | "outputs": [], 174 | "source": [] 175 | } 176 | ], 177 | "metadata": { 178 | "kernelspec": { 179 | "display_name": "Python 3 (ipykernel)", 180 | "language": "python", 181 | "name": "python3" 182 | }, 183 | "language_info": { 184 | "codemirror_mode": { 185 | "name": "ipython", 186 | "version": 3 187 | }, 188 | "file_extension": ".py", 189 | "mimetype": "text/x-python", 190 | "name": "python", 191 | "nbconvert_exporter": "python", 192 | "pygments_lexer": "ipython3", 193 | "version": "3.9.15" 194 | } 195 | }, 196 | "nbformat": 4, 197 | "nbformat_minor": 5 198 | } 199 | -------------------------------------------------------------------------------- /4-training-on-Darcy-Flow.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "012a357f-8533-482c-823d-a4587c49e726", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import torch\n", 11 | "import wandb\n", 12 | "import sys\n", 13 | "from configmypy import ConfigPipeline, YamlConfig, ArgparseConfig\n", 14 | "from neuralop import get_model\n", 15 | "from neuralop import Trainer\n", 16 | "from neuralop.training import setup\n", 17 | "from neuralop.datasets import load_darcy_pt\n", 18 | "from neuralop.utils import get_wandb_api_key, count_params\n", 19 | "from neuralop import LpLoss, H1Loss" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "id": "9b6358b5-78d1-4baf-8928-6bb49b150680", 25 | "metadata": {}, 26 | "source": [ 27 | "# Loading the configuration\n", 28 | "\n", 29 | "You can open the yaml file in config/darcy_config in the same folder as this notebook to inspect the parameters and change them." 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "id": "4503f065-4063-4a4f-b00f-06a7c3a88e27", 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "# Read the configuration\n", 40 | "config_name = 'default'\n", 41 | "pipe = ConfigPipeline([YamlConfig('./darcy_config.yaml', config_name='default', config_folder='./config'),\n", 42 | " ])\n", 43 | "config = pipe.read_conf()\n", 44 | "config_name = pipe.steps[-1].config_name" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "id": "e95d820d-9578-4ad7-80b4-05a5771f1642", 50 | "metadata": {}, 51 | "source": [ 52 | "## Setup\n", 53 | "\n", 54 | "Here we just setup pytorch and print the configuration" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 3, 60 | "id": "46066d9f-21a3-4aab-b6e1-f7f38e05f88b", 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "# Set-up distributed communication, if using\n", 65 | "device, is_logger = setup(config)" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 4, 71 | "id": "26d599f9-6463-4056-9a4d-72c01d05298e", 72 | "metadata": {}, 73 | "outputs": [ 74 | { 75 | "name": "stdout", 76 | "output_type": "stream", 77 | "text": [ 78 | "###############################\n", 79 | "##### CONFIGURATION #####\n", 80 | "###############################\n", 81 | "\n", 82 | "Steps:\n", 83 | "------\n", 84 | " (1) YamlConfig with config_file=./darcy_config.yaml, config_name=default, config_folder=./config\n", 85 | "\n", 86 | "-------------------------------\n", 87 | "\n", 88 | "Configuration:\n", 89 | "--------------\n", 90 | "\n", 91 | "n_params_baseline=None\n", 92 | "verbose=True\n", 93 | "arch=tfno2d\n", 94 | "distributed.use_distributed=False\n", 95 | "tfno2d.data_channels=3\n", 96 | "tfno2d.n_modes_height=32\n", 97 | "tfno2d.n_modes_width=32\n", 98 | "tfno2d.hidden_channels=64\n", 99 | "tfno2d.projection_channels=256\n", 100 | "tfno2d.n_layers=4\n", 101 | "tfno2d.domain_padding=None\n", 102 | "tfno2d.domain_padding_mode=one-sided\n", 103 | "tfno2d.fft_norm=forward\n", 104 | "tfno2d.norm=group_norm\n", 105 | "tfno2d.skip=linear\n", 106 | "tfno2d.implementation=factorized\n", 107 | "tfno2d.separable=0\n", 108 | "tfno2d.preactivation=0\n", 109 | "tfno2d.use_mlp=1\n", 110 | "tfno2d.mlp.expansion=0.5\n", 111 | "tfno2d.mlp.dropout=0\n", 112 | "tfno2d.factorization=None\n", 113 | "tfno2d.rank=1.0\n", 114 | "tfno2d.fixed_rank_modes=None\n", 115 | "tfno2d.dropout=0.0\n", 116 | "tfno2d.tensor_lasso_penalty=0.0\n", 117 | "tfno2d.joint_factorization=False\n", 118 | "opt.n_epochs=150\n", 119 | "opt.learning_rate=0.005\n", 120 | "opt.training_loss=h1\n", 121 | "opt.weight_decay=0.0001\n", 122 | "opt.amp_autocast=False\n", 123 | "opt.scheduler_T_max=300\n", 124 | "opt.scheduler_patience=5\n", 125 | "opt.scheduler=CosineAnnealingLR\n", 126 | "opt.step_size=50\n", 127 | "opt.gamma=0.5\n", 128 | "data.folder=/data/darcy_flow/\n", 129 | "data.batch_size=32\n", 130 | "data.n_train=3000\n", 131 | "data.train_resolution=32\n", 132 | "data.n_tests=[500, 500]\n", 133 | "data.test_resolutions=[32, 64]\n", 134 | "data.test_batch_sizes=[32, 32]\n", 135 | "data.positional_encoding=True\n", 136 | "data.encode_input=True\n", 137 | "data.encode_output=False\n", 138 | "patching.levels=0\n", 139 | "patching.padding=0\n", 140 | "patching.stitching=False\n", 141 | "wandb.log=False\n", 142 | "wandb.log_test_interval=1\n", 143 | "\n", 144 | "###############################\n" 145 | ] 146 | } 147 | ], 148 | "source": [ 149 | "# Make sure we only print information when needed\n", 150 | "config.verbose = config.verbose and is_logger\n", 151 | "\n", 152 | "#Print config to screen\n", 153 | "if config.verbose and is_logger:\n", 154 | " pipe.log()\n", 155 | " sys.stdout.flush()" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "id": "1339c794-3e1c-469b-b0a0-cf968fc1dfa1", 161 | "metadata": {}, 162 | "source": [ 163 | "# Loading the data \n", 164 | "\n", 165 | "We train in one resolution and test in several resolutions to show the zero-shot super-resolution capabilities of neural-operators. " 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "id": "3515a85a-40fc-4223-9cdb-8768de37d6e2", 172 | "metadata": {}, 173 | "outputs": [ 174 | { 175 | "name": "stdout", 176 | "output_type": "stream", 177 | "text": [ 178 | "UnitGaussianNormalizer init on 3000, reducing over [0, 1, 2, 3], samples of shape [1, 32, 32].\n", 179 | " Mean and std of shape torch.Size([1, 1, 1]), eps=1e-05\n", 180 | "Loading test db at resolution 64 with 500 samples and batch-size=32\n" 181 | ] 182 | } 183 | ], 184 | "source": [ 185 | "# Loading the Darcy flow training set in 32x32 resolution, test set in 32x32 and 64x64 resolutions\n", 186 | "train_loader, test_loaders, output_encoder = load_darcy_pt(\n", 187 | " config.data.folder, train_resolution=config.data.train_resolution, n_train=config.data.n_train, batch_size=config.data.batch_size, \n", 188 | " positional_encoding=config.data.positional_encoding,\n", 189 | " test_resolutions=config.data.test_resolutions, n_tests=config.data.n_tests, test_batch_sizes=config.data.test_batch_sizes,\n", 190 | " encode_input=config.data.encode_input, encode_output=config.data.encode_output,\n", 191 | " )" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "id": "8109298a-aca3-45b7-a8de-c5cf4e1c210b", 197 | "metadata": {}, 198 | "source": [ 199 | "# Creating the model and putting it on the GPU " 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": 6, 205 | "id": "db295d23-ab86-4f37-83cc-7af0a8e485ea", 206 | "metadata": {}, 207 | "outputs": [ 208 | { 209 | "name": "stdout", 210 | "output_type": "stream", 211 | "text": [ 212 | "Given argument key='dropout' that is not in TFNO2d's signature.\n", 213 | "Given argument key='tensor_lasso_penalty' that is not in TFNO2d's signature.\n", 214 | "Keyword argument out_channels not specified for model TFNO2d, using default=1.\n", 215 | "Keyword argument lifting_channels not specified for model TFNO2d, using default=256.\n", 216 | "Keyword argument non_linearity not specified for model TFNO2d, using default=.\n", 217 | "Keyword argument decomposition_kwargs not specified for model TFNO2d, using default={}.\n", 218 | "\n", 219 | "n_params: 16844673\n" 220 | ] 221 | } 222 | ], 223 | "source": [ 224 | "model = get_model(config)\n", 225 | "model = model.to(device)\n", 226 | "\n", 227 | "#Log parameter count\n", 228 | "if is_logger:\n", 229 | " n_params = count_params(model)\n", 230 | "\n", 231 | " if config.verbose:\n", 232 | " print(f'\\nn_params: {n_params}')\n", 233 | " sys.stdout.flush()" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "id": "fec85d0a-4db4-4b1f-b599-8c2afc98520a", 239 | "metadata": {}, 240 | "source": [ 241 | "# Create the optimizer and learning rate scheduler\n", 242 | "\n", 243 | "Here, we use an Adam optimizer and a learning rate schedule depending on the configuration" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 7, 249 | "id": "5164537a-267b-4fda-9bcd-257dc3ac4826", 250 | "metadata": {}, 251 | "outputs": [], 252 | "source": [ 253 | "#Create the optimizer\n", 254 | "optimizer = torch.optim.Adam(model.parameters(), \n", 255 | " lr=config.opt.learning_rate, \n", 256 | " weight_decay=config.opt.weight_decay)\n", 257 | "\n", 258 | "if config.opt.scheduler == 'ReduceLROnPlateau':\n", 259 | " scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, factor=config.opt.gamma, patience=config.opt.scheduler_patience, mode='min')\n", 260 | "elif config.opt.scheduler == 'CosineAnnealingLR':\n", 261 | " scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=config.opt.scheduler_T_max)\n", 262 | "elif config.opt.scheduler == 'StepLR':\n", 263 | " scheduler = torch.optim.lr_scheduler.StepLR(optimizer, \n", 264 | " step_size=config.opt.step_size,\n", 265 | " gamma=config.opt.gamma)\n", 266 | "else:\n", 267 | " raise ValueError(f'Got {config.opt.scheduler=}')" 268 | ] 269 | }, 270 | { 271 | "cell_type": "markdown", 272 | "id": "e52a72eb-965a-4997-89a4-0cdfcbcb0a1a", 273 | "metadata": {}, 274 | "source": [ 275 | "# Creating the loss\n", 276 | "\n", 277 | "We will optimize the Sobolev norm but also evaluate our goal: the l2 relative error" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 8, 283 | "id": "07a53d9d-2d06-4d36-9b46-2c7f15f29c40", 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "# Creating the losses\n", 288 | "l2loss = LpLoss(d=2, p=2)\n", 289 | "h1loss = H1Loss(d=2)\n", 290 | "if config.opt.training_loss == 'l2':\n", 291 | " train_loss = l2loss\n", 292 | "elif config.opt.training_loss == 'h1':\n", 293 | " train_loss = h1loss\n", 294 | "else:\n", 295 | " raise ValueError(f'Got training_loss={config.opt.training_loss} but expected one of [\"l2\", \"h1\"]')\n", 296 | "eval_losses={'h1': h1loss, 'l2': l2loss}" 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": 9, 302 | "id": "5dad660e-43e9-4f38-91f6-8427b14b8ae0", 303 | "metadata": {}, 304 | "outputs": [ 305 | { 306 | "name": "stdout", 307 | "output_type": "stream", 308 | "text": [ 309 | "\n", 310 | "### MODEL ###\n", 311 | " TFNO2d(\n", 312 | " (convs): FactorizedSpectralConv2d(\n", 313 | " (weight): ModuleList(\n", 314 | " (0): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 315 | " (1): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 316 | " (2): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 317 | " (3): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 318 | " (4): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 319 | " (5): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 320 | " (6): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 321 | " (7): ComplexDenseTensor(shape=torch.Size([64, 64, 16, 16]), rank=None)\n", 322 | " )\n", 323 | " )\n", 324 | " (fno_skips): ModuleList(\n", 325 | " (0): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 326 | " (1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 327 | " (2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 328 | " (3): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 329 | " )\n", 330 | " (mlp): ModuleList(\n", 331 | " (0): MLP(\n", 332 | " (fcs): ModuleList(\n", 333 | " (0): Conv2d(64, 32, kernel_size=(1, 1), stride=(1, 1))\n", 334 | " (1): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1))\n", 335 | " )\n", 336 | " )\n", 337 | " (1): MLP(\n", 338 | " (fcs): ModuleList(\n", 339 | " (0): Conv2d(64, 32, kernel_size=(1, 1), stride=(1, 1))\n", 340 | " (1): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1))\n", 341 | " )\n", 342 | " )\n", 343 | " (2): MLP(\n", 344 | " (fcs): ModuleList(\n", 345 | " (0): Conv2d(64, 32, kernel_size=(1, 1), stride=(1, 1))\n", 346 | " (1): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1))\n", 347 | " )\n", 348 | " )\n", 349 | " (3): MLP(\n", 350 | " (fcs): ModuleList(\n", 351 | " (0): Conv2d(64, 32, kernel_size=(1, 1), stride=(1, 1))\n", 352 | " (1): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1))\n", 353 | " )\n", 354 | " )\n", 355 | " )\n", 356 | " (mlp_skips): ModuleList(\n", 357 | " (0): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 358 | " (1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 359 | " (2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 360 | " (3): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", 361 | " )\n", 362 | " (norm): ModuleList(\n", 363 | " (0): GroupNorm(1, 64, eps=1e-05, affine=True)\n", 364 | " (1): GroupNorm(1, 64, eps=1e-05, affine=True)\n", 365 | " (2): GroupNorm(1, 64, eps=1e-05, affine=True)\n", 366 | " (3): GroupNorm(1, 64, eps=1e-05, affine=True)\n", 367 | " )\n", 368 | " (lifting): Lifting(\n", 369 | " (fc): Conv2d(3, 64, kernel_size=(1, 1), stride=(1, 1))\n", 370 | " )\n", 371 | " (projection): Projection(\n", 372 | " (fc1): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))\n", 373 | " (fc2): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))\n", 374 | " )\n", 375 | ")\n", 376 | "\n", 377 | "### OPTIMIZER ###\n", 378 | " Adam (\n", 379 | "Parameter Group 0\n", 380 | " amsgrad: False\n", 381 | " betas: (0.9, 0.999)\n", 382 | " capturable: False\n", 383 | " differentiable: False\n", 384 | " eps: 1e-08\n", 385 | " foreach: None\n", 386 | " fused: False\n", 387 | " initial_lr: 0.005\n", 388 | " lr: 0.005\n", 389 | " maximize: False\n", 390 | " weight_decay: 0.0001\n", 391 | ")\n", 392 | "\n", 393 | "### SCHEDULER ###\n", 394 | " \n", 395 | "\n", 396 | "### LOSSES ###\n", 397 | "\n", 398 | " * Train: \n", 399 | "\n", 400 | " * Test: {'h1': , 'l2': }\n", 401 | "\n", 402 | "### Beginning Training...\n", 403 | "\n" 404 | ] 405 | } 406 | ], 407 | "source": [ 408 | "if config.verbose and is_logger:\n", 409 | " print('\\n### MODEL ###\\n', model)\n", 410 | " print('\\n### OPTIMIZER ###\\n', optimizer)\n", 411 | " print('\\n### SCHEDULER ###\\n', scheduler)\n", 412 | " print('\\n### LOSSES ###')\n", 413 | " print(f'\\n * Train: {train_loss}')\n", 414 | " print(f'\\n * Test: {eval_losses}')\n", 415 | " print(f'\\n### Beginning Training...\\n')\n", 416 | " sys.stdout.flush()" 417 | ] 418 | }, 419 | { 420 | "cell_type": "markdown", 421 | "id": "b5967441-b8bc-4ea8-a4d9-7a5bea384cbf", 422 | "metadata": {}, 423 | "source": [ 424 | "# Creating the trainer" 425 | ] 426 | }, 427 | { 428 | "cell_type": "code", 429 | "execution_count": 10, 430 | "id": "a19ebfd3-8a2b-42c0-af98-7a1db2dda0f6", 431 | "metadata": {}, 432 | "outputs": [ 433 | { 434 | "name": "stdout", 435 | "output_type": "stream", 436 | "text": [ 437 | "Training on regular inputs (no multi-grid patching).\n", 438 | "MGPatching(self.n_patches=[1, 1], self.padding_fraction=[0, 0], self.levels=0, use_distributed=False, stitching=False)\n" 439 | ] 440 | } 441 | ], 442 | "source": [ 443 | "trainer = Trainer(model, n_epochs=config.opt.n_epochs,\n", 444 | " device=device,\n", 445 | " mg_patching_levels=config.patching.levels,\n", 446 | " mg_patching_padding=config.patching.padding,\n", 447 | " mg_patching_stitching=config.patching.stitching,\n", 448 | " wandb_log=config.wandb.log,\n", 449 | " log_test_interval=config.wandb.log_test_interval,\n", 450 | " log_output=False,\n", 451 | " use_distributed=config.distributed.use_distributed,\n", 452 | " verbose=config.verbose and is_logger)" 453 | ] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "id": "b16a3727-313d-4219-8f8f-0cec58d74b00", 458 | "metadata": {}, 459 | "source": [ 460 | "# Training the model " 461 | ] 462 | }, 463 | { 464 | "cell_type": "code", 465 | "execution_count": 11, 466 | "id": "0d6e3298-99ee-4371-8bad-60e6aac03d56", 467 | "metadata": {}, 468 | "outputs": [ 469 | { 470 | "name": "stdout", 471 | "output_type": "stream", 472 | "text": [ 473 | "Training on 3000 samples, testing on [32, 64].\n", 474 | "[0] time=3.03, avg_loss=7.8899, train_err=0.3945, 32_h1=0.2295, 32_l2=0.1710, 64_h1=0.2847, 64_l2=0.1733\n", 475 | "[1] time=1.38, avg_loss=3.7664, train_err=0.1883, 32_h1=0.1646, 32_l2=0.1177, 64_h1=0.2326, 64_l2=0.1221\n", 476 | "[2] time=1.37, avg_loss=3.1005, train_err=0.1550, 32_h1=0.1411, 32_l2=0.1027, 64_h1=0.2156, 64_l2=0.1106\n", 477 | "[3] time=1.36, avg_loss=2.5222, train_err=0.1261, 32_h1=0.1238, 32_l2=0.0800, 64_h1=0.2026, 64_l2=0.0936\n", 478 | "[4] time=1.36, avg_loss=2.3043, train_err=0.1152, 32_h1=0.1235, 32_l2=0.0808, 64_h1=0.1874, 64_l2=0.0858\n", 479 | "[5] time=1.36, avg_loss=2.2108, train_err=0.1105, 32_h1=0.1332, 32_l2=0.1041, 64_h1=0.2055, 64_l2=0.1122\n", 480 | "[6] time=1.37, avg_loss=1.9753, train_err=0.0988, 32_h1=0.1077, 32_l2=0.0720, 64_h1=0.1885, 64_l2=0.0838\n", 481 | "[7] time=1.37, avg_loss=1.9352, train_err=0.0968, 32_h1=0.1032, 32_l2=0.0642, 64_h1=0.1847, 64_l2=0.0753\n", 482 | "[8] time=1.36, avg_loss=1.8174, train_err=0.0909, 32_h1=0.1013, 32_l2=0.0632, 64_h1=0.1798, 64_l2=0.0763\n", 483 | "[9] time=1.37, avg_loss=1.7847, train_err=0.0892, 32_h1=0.1053, 32_l2=0.0672, 64_h1=0.1909, 64_l2=0.0788\n", 484 | "[10] time=1.37, avg_loss=1.6375, train_err=0.0819, 32_h1=0.0926, 32_l2=0.0513, 64_h1=0.1808, 64_l2=0.0666\n", 485 | "[11] time=1.37, avg_loss=1.5826, train_err=0.0791, 32_h1=0.0958, 32_l2=0.0574, 64_h1=0.1810, 64_l2=0.0700\n", 486 | "[12] time=1.36, avg_loss=1.6231, train_err=0.0812, 32_h1=0.0940, 32_l2=0.0534, 64_h1=0.1740, 64_l2=0.0636\n", 487 | "[13] time=1.42, avg_loss=1.5427, train_err=0.0771, 32_h1=0.0937, 32_l2=0.0532, 64_h1=0.1834, 64_l2=0.0692\n", 488 | "[14] time=1.37, avg_loss=1.4741, train_err=0.0737, 32_h1=0.0989, 32_l2=0.0623, 64_h1=0.1844, 64_l2=0.0798\n", 489 | "[15] time=1.36, avg_loss=1.5156, train_err=0.0758, 32_h1=0.1020, 32_l2=0.0649, 64_h1=0.1844, 64_l2=0.0730\n", 490 | "[16] time=1.37, avg_loss=1.5620, train_err=0.0781, 32_h1=0.0940, 32_l2=0.0608, 64_h1=0.1803, 64_l2=0.0747\n", 491 | "[17] time=1.36, avg_loss=1.3939, train_err=0.0697, 32_h1=0.1018, 32_l2=0.0620, 64_h1=0.1842, 64_l2=0.0772\n", 492 | "[18] time=1.89, avg_loss=1.4904, train_err=0.0745, 32_h1=0.1010, 32_l2=0.0704, 64_h1=0.1868, 64_l2=0.0794\n", 493 | "[19] time=1.83, avg_loss=1.4300, train_err=0.0715, 32_h1=0.0929, 32_l2=0.0525, 64_h1=0.1784, 64_l2=0.0679\n", 494 | "[20] time=1.84, avg_loss=1.3752, train_err=0.0688, 32_h1=0.0964, 32_l2=0.0635, 64_h1=0.1825, 64_l2=0.0694\n", 495 | "[21] time=1.84, avg_loss=1.4671, train_err=0.0734, 32_h1=0.0911, 32_l2=0.0513, 64_h1=0.1832, 64_l2=0.0696\n", 496 | "[22] time=1.88, avg_loss=1.3043, train_err=0.0652, 32_h1=0.0938, 32_l2=0.0538, 64_h1=0.1804, 64_l2=0.0687\n", 497 | "[23] time=1.37, avg_loss=1.2880, train_err=0.0644, 32_h1=0.0897, 32_l2=0.0492, 64_h1=0.1824, 64_l2=0.0629\n", 498 | "[24] time=1.37, avg_loss=1.3901, train_err=0.0695, 32_h1=0.1080, 32_l2=0.0701, 64_h1=0.1828, 64_l2=0.0785\n", 499 | "[25] time=1.37, avg_loss=1.3788, train_err=0.0689, 32_h1=0.0878, 32_l2=0.0514, 64_h1=0.1744, 64_l2=0.0613\n", 500 | "[26] time=1.37, avg_loss=1.3071, train_err=0.0654, 32_h1=0.0880, 32_l2=0.0489, 64_h1=0.1847, 64_l2=0.0698\n", 501 | "[27] time=1.36, avg_loss=1.3056, train_err=0.0653, 32_h1=0.0980, 32_l2=0.0679, 64_h1=0.1828, 64_l2=0.0830\n", 502 | "[28] time=1.37, avg_loss=1.2677, train_err=0.0634, 32_h1=0.0956, 32_l2=0.0621, 64_h1=0.1827, 64_l2=0.0692\n", 503 | "[29] time=1.37, avg_loss=1.2611, train_err=0.0631, 32_h1=0.0913, 32_l2=0.0500, 64_h1=0.1855, 64_l2=0.0652\n", 504 | "[30] time=1.37, avg_loss=1.1833, train_err=0.0592, 32_h1=0.0888, 32_l2=0.0512, 64_h1=0.1818, 64_l2=0.0655\n", 505 | "[31] time=1.36, avg_loss=1.2170, train_err=0.0608, 32_h1=0.0879, 32_l2=0.0481, 64_h1=0.1758, 64_l2=0.0625\n", 506 | "[32] time=1.36, avg_loss=1.1431, train_err=0.0572, 32_h1=0.0886, 32_l2=0.0479, 64_h1=0.1756, 64_l2=0.0594\n", 507 | "[33] time=1.37, avg_loss=1.2162, train_err=0.0608, 32_h1=0.0923, 32_l2=0.0522, 64_h1=0.1749, 64_l2=0.0629\n", 508 | "[34] time=1.37, avg_loss=1.1588, train_err=0.0579, 32_h1=0.0892, 32_l2=0.0526, 64_h1=0.1797, 64_l2=0.0656\n", 509 | "[35] time=1.37, avg_loss=1.1747, train_err=0.0587, 32_h1=0.0884, 32_l2=0.0481, 64_h1=0.1829, 64_l2=0.0650\n", 510 | "[36] time=1.36, avg_loss=1.1491, train_err=0.0575, 32_h1=0.0936, 32_l2=0.0542, 64_h1=0.1787, 64_l2=0.0672\n", 511 | "[37] time=1.37, avg_loss=1.1532, train_err=0.0577, 32_h1=0.0950, 32_l2=0.0569, 64_h1=0.1737, 64_l2=0.0679\n", 512 | "[38] time=1.37, avg_loss=1.2426, train_err=0.0621, 32_h1=0.0875, 32_l2=0.0488, 64_h1=0.1750, 64_l2=0.0638\n", 513 | "[39] time=1.37, avg_loss=1.1345, train_err=0.0567, 32_h1=0.0874, 32_l2=0.0493, 64_h1=0.1780, 64_l2=0.0658\n", 514 | "[40] time=1.36, avg_loss=1.1238, train_err=0.0562, 32_h1=0.0914, 32_l2=0.0516, 64_h1=0.1796, 64_l2=0.0662\n", 515 | "[41] time=1.36, avg_loss=1.1093, train_err=0.0555, 32_h1=0.0855, 32_l2=0.0457, 64_h1=0.1741, 64_l2=0.0621\n", 516 | "[42] time=1.36, avg_loss=1.0772, train_err=0.0539, 32_h1=0.0899, 32_l2=0.0523, 64_h1=0.1807, 64_l2=0.0688\n", 517 | "[43] time=1.36, avg_loss=1.0772, train_err=0.0539, 32_h1=0.0894, 32_l2=0.0556, 64_h1=0.1769, 64_l2=0.0705\n", 518 | "[44] time=1.36, avg_loss=1.0901, train_err=0.0545, 32_h1=0.0843, 32_l2=0.0443, 64_h1=0.1750, 64_l2=0.0589\n", 519 | "[45] time=1.36, avg_loss=1.0783, train_err=0.0539, 32_h1=0.0874, 32_l2=0.0486, 64_h1=0.1778, 64_l2=0.0593\n", 520 | "[46] time=1.46, avg_loss=1.0837, train_err=0.0542, 32_h1=0.0874, 32_l2=0.0482, 64_h1=0.1722, 64_l2=0.0575\n", 521 | "[47] time=1.37, avg_loss=1.1760, train_err=0.0588, 32_h1=0.0873, 32_l2=0.0507, 64_h1=0.1706, 64_l2=0.0639\n", 522 | "[48] time=1.37, avg_loss=1.0357, train_err=0.0518, 32_h1=0.0889, 32_l2=0.0503, 64_h1=0.1799, 64_l2=0.0663\n", 523 | "[49] time=1.36, avg_loss=1.0873, train_err=0.0544, 32_h1=0.0846, 32_l2=0.0464, 64_h1=0.1725, 64_l2=0.0592\n", 524 | "[50] time=1.36, avg_loss=1.0996, train_err=0.0550, 32_h1=0.0861, 32_l2=0.0461, 64_h1=0.1696, 64_l2=0.0598\n", 525 | "[51] time=1.37, avg_loss=1.0487, train_err=0.0524, 32_h1=0.0839, 32_l2=0.0433, 64_h1=0.1752, 64_l2=0.0602\n", 526 | "[52] time=1.37, avg_loss=1.0527, train_err=0.0526, 32_h1=0.0858, 32_l2=0.0469, 64_h1=0.1736, 64_l2=0.0588\n", 527 | "[53] time=1.36, avg_loss=1.0138, train_err=0.0507, 32_h1=0.0854, 32_l2=0.0475, 64_h1=0.1777, 64_l2=0.0619\n", 528 | "[54] time=1.36, avg_loss=1.0210, train_err=0.0511, 32_h1=0.0832, 32_l2=0.0431, 64_h1=0.1728, 64_l2=0.0580\n", 529 | "[55] time=1.36, avg_loss=0.9939, train_err=0.0497, 32_h1=0.0870, 32_l2=0.0474, 64_h1=0.1755, 64_l2=0.0609\n", 530 | "[56] time=1.37, avg_loss=1.0085, train_err=0.0504, 32_h1=0.0833, 32_l2=0.0438, 64_h1=0.1731, 64_l2=0.0603\n", 531 | "[57] time=1.37, avg_loss=1.0132, train_err=0.0507, 32_h1=0.0842, 32_l2=0.0462, 64_h1=0.1757, 64_l2=0.0613\n", 532 | "[58] time=1.36, avg_loss=0.9938, train_err=0.0497, 32_h1=0.0839, 32_l2=0.0439, 64_h1=0.1811, 64_l2=0.0651\n", 533 | "[59] time=1.36, avg_loss=0.9814, train_err=0.0491, 32_h1=0.0820, 32_l2=0.0425, 64_h1=0.1728, 64_l2=0.0565\n", 534 | "[60] time=1.36, avg_loss=0.9849, train_err=0.0492, 32_h1=0.0861, 32_l2=0.0477, 64_h1=0.1715, 64_l2=0.0616\n", 535 | "[61] time=1.37, avg_loss=0.9787, train_err=0.0489, 32_h1=0.0844, 32_l2=0.0450, 64_h1=0.1742, 64_l2=0.0623\n", 536 | "[62] time=1.36, avg_loss=1.0104, train_err=0.0505, 32_h1=0.0830, 32_l2=0.0437, 64_h1=0.1769, 64_l2=0.0605\n", 537 | "[63] time=1.36, avg_loss=0.9910, train_err=0.0495, 32_h1=0.0821, 32_l2=0.0415, 64_h1=0.1742, 64_l2=0.0579\n", 538 | "[64] time=1.36, avg_loss=0.9622, train_err=0.0481, 32_h1=0.0849, 32_l2=0.0462, 64_h1=0.1763, 64_l2=0.0608\n", 539 | "[65] time=1.36, avg_loss=1.0191, train_err=0.0510, 32_h1=0.0823, 32_l2=0.0419, 64_h1=0.1736, 64_l2=0.0570\n", 540 | "[66] time=1.37, avg_loss=0.9814, train_err=0.0491, 32_h1=0.0873, 32_l2=0.0492, 64_h1=0.1752, 64_l2=0.0643\n", 541 | "[67] time=1.36, avg_loss=0.9867, train_err=0.0493, 32_h1=0.0833, 32_l2=0.0446, 64_h1=0.1698, 64_l2=0.0588\n", 542 | "[68] time=1.36, avg_loss=0.9983, train_err=0.0499, 32_h1=0.0815, 32_l2=0.0417, 64_h1=0.1712, 64_l2=0.0590\n", 543 | "[69] time=1.37, avg_loss=0.9956, train_err=0.0498, 32_h1=0.0836, 32_l2=0.0453, 64_h1=0.1756, 64_l2=0.0604\n", 544 | "[70] time=1.37, avg_loss=0.9433, train_err=0.0472, 32_h1=0.0830, 32_l2=0.0432, 64_h1=0.1739, 64_l2=0.0583\n", 545 | "[71] time=1.36, avg_loss=0.9813, train_err=0.0491, 32_h1=0.0830, 32_l2=0.0433, 64_h1=0.1691, 64_l2=0.0588\n", 546 | "[72] time=1.36, avg_loss=0.9456, train_err=0.0473, 32_h1=0.0828, 32_l2=0.0429, 64_h1=0.1695, 64_l2=0.0599\n", 547 | "[73] time=1.37, avg_loss=0.9099, train_err=0.0455, 32_h1=0.0835, 32_l2=0.0438, 64_h1=0.1716, 64_l2=0.0599\n", 548 | "[74] time=1.37, avg_loss=0.9241, train_err=0.0462, 32_h1=0.0816, 32_l2=0.0419, 64_h1=0.1699, 64_l2=0.0572\n", 549 | "[75] time=1.37, avg_loss=0.8907, train_err=0.0445, 32_h1=0.0825, 32_l2=0.0410, 64_h1=0.1772, 64_l2=0.0604\n", 550 | "[76] time=1.36, avg_loss=0.8940, train_err=0.0447, 32_h1=0.0821, 32_l2=0.0428, 64_h1=0.1733, 64_l2=0.0588\n", 551 | "[77] time=1.37, avg_loss=0.8958, train_err=0.0448, 32_h1=0.0828, 32_l2=0.0447, 64_h1=0.1756, 64_l2=0.0593\n", 552 | "[78] time=1.37, avg_loss=0.9276, train_err=0.0464, 32_h1=0.0816, 32_l2=0.0424, 64_h1=0.1740, 64_l2=0.0599\n", 553 | "[79] time=1.37, avg_loss=0.8763, train_err=0.0438, 32_h1=0.0818, 32_l2=0.0414, 64_h1=0.1715, 64_l2=0.0570\n", 554 | "[80] time=1.36, avg_loss=0.8634, train_err=0.0432, 32_h1=0.0812, 32_l2=0.0416, 64_h1=0.1753, 64_l2=0.0614\n", 555 | "[81] time=1.36, avg_loss=0.8450, train_err=0.0423, 32_h1=0.0832, 32_l2=0.0448, 64_h1=0.1701, 64_l2=0.0626\n", 556 | "[82] time=1.37, avg_loss=0.8997, train_err=0.0450, 32_h1=0.0818, 32_l2=0.0419, 64_h1=0.1718, 64_l2=0.0590\n", 557 | "[83] time=1.37, avg_loss=0.8658, train_err=0.0433, 32_h1=0.0816, 32_l2=0.0415, 64_h1=0.1703, 64_l2=0.0552\n", 558 | "[84] time=1.37, avg_loss=0.9292, train_err=0.0465, 32_h1=0.0815, 32_l2=0.0424, 64_h1=0.1674, 64_l2=0.0580\n", 559 | "[85] time=1.36, avg_loss=0.9417, train_err=0.0471, 32_h1=0.0825, 32_l2=0.0439, 64_h1=0.1755, 64_l2=0.0608\n", 560 | "[86] time=1.37, avg_loss=0.8608, train_err=0.0430, 32_h1=0.0792, 32_l2=0.0392, 64_h1=0.1720, 64_l2=0.0573\n", 561 | "[87] time=1.38, avg_loss=0.9083, train_err=0.0454, 32_h1=0.0822, 32_l2=0.0440, 64_h1=0.1693, 64_l2=0.0602\n", 562 | "[88] time=1.57, avg_loss=0.8522, train_err=0.0426, 32_h1=0.0823, 32_l2=0.0427, 64_h1=0.1695, 64_l2=0.0571\n", 563 | "[89] time=1.36, avg_loss=0.8273, train_err=0.0414, 32_h1=0.0813, 32_l2=0.0414, 64_h1=0.1702, 64_l2=0.0568\n", 564 | "[90] time=1.36, avg_loss=0.8612, train_err=0.0431, 32_h1=0.0834, 32_l2=0.0468, 64_h1=0.1718, 64_l2=0.0641\n", 565 | "[91] time=1.36, avg_loss=0.8358, train_err=0.0418, 32_h1=0.0811, 32_l2=0.0410, 64_h1=0.1678, 64_l2=0.0558\n", 566 | "[92] time=1.37, avg_loss=0.8725, train_err=0.0436, 32_h1=0.0807, 32_l2=0.0408, 64_h1=0.1688, 64_l2=0.0557\n", 567 | "[93] time=1.36, avg_loss=0.8163, train_err=0.0408, 32_h1=0.0804, 32_l2=0.0417, 64_h1=0.1714, 64_l2=0.0593\n", 568 | "[94] time=1.36, avg_loss=0.8119, train_err=0.0406, 32_h1=0.0791, 32_l2=0.0393, 64_h1=0.1706, 64_l2=0.0581\n", 569 | "[95] time=1.36, avg_loss=0.8022, train_err=0.0401, 32_h1=0.0819, 32_l2=0.0416, 64_h1=0.1697, 64_l2=0.0555\n", 570 | "[96] time=1.37, avg_loss=0.8371, train_err=0.0419, 32_h1=0.0793, 32_l2=0.0393, 64_h1=0.1684, 64_l2=0.0570\n", 571 | "[97] time=1.37, avg_loss=0.8227, train_err=0.0411, 32_h1=0.0800, 32_l2=0.0407, 64_h1=0.1685, 64_l2=0.0583\n", 572 | "[98] time=1.43, avg_loss=0.8176, train_err=0.0409, 32_h1=0.0841, 32_l2=0.0471, 64_h1=0.1681, 64_l2=0.0578\n", 573 | "[99] time=1.85, avg_loss=0.8517, train_err=0.0426, 32_h1=0.0809, 32_l2=0.0401, 64_h1=0.1726, 64_l2=0.0607\n", 574 | "[100] time=1.85, avg_loss=0.8445, train_err=0.0422, 32_h1=0.0810, 32_l2=0.0408, 64_h1=0.1688, 64_l2=0.0558\n", 575 | "[101] time=1.42, avg_loss=0.7962, train_err=0.0398, 32_h1=0.0796, 32_l2=0.0393, 64_h1=0.1680, 64_l2=0.0577\n", 576 | "[102] time=1.84, avg_loss=0.7758, train_err=0.0388, 32_h1=0.0799, 32_l2=0.0398, 64_h1=0.1664, 64_l2=0.0556\n", 577 | "[103] time=1.87, avg_loss=0.8005, train_err=0.0400, 32_h1=0.0792, 32_l2=0.0395, 64_h1=0.1688, 64_l2=0.0552\n", 578 | "[104] time=1.43, avg_loss=0.8099, train_err=0.0405, 32_h1=0.0791, 32_l2=0.0394, 64_h1=0.1664, 64_l2=0.0535\n", 579 | "[105] time=1.37, avg_loss=0.7828, train_err=0.0391, 32_h1=0.0815, 32_l2=0.0430, 64_h1=0.1691, 64_l2=0.0574\n", 580 | "[106] time=1.37, avg_loss=0.7799, train_err=0.0390, 32_h1=0.0795, 32_l2=0.0393, 64_h1=0.1679, 64_l2=0.0556\n", 581 | "[107] time=1.36, avg_loss=0.7685, train_err=0.0384, 32_h1=0.0810, 32_l2=0.0434, 64_h1=0.1725, 64_l2=0.0633\n", 582 | "[108] time=1.36, avg_loss=0.7581, train_err=0.0379, 32_h1=0.0801, 32_l2=0.0407, 64_h1=0.1744, 64_l2=0.0574\n", 583 | "[109] time=1.37, avg_loss=0.7415, train_err=0.0371, 32_h1=0.0782, 32_l2=0.0383, 64_h1=0.1670, 64_l2=0.0540\n", 584 | "[110] time=1.37, avg_loss=0.7387, train_err=0.0369, 32_h1=0.0790, 32_l2=0.0392, 64_h1=0.1664, 64_l2=0.0539\n", 585 | "[111] time=1.37, avg_loss=0.7338, train_err=0.0367, 32_h1=0.0788, 32_l2=0.0385, 64_h1=0.1694, 64_l2=0.0574\n", 586 | "[112] time=1.36, avg_loss=0.7426, train_err=0.0371, 32_h1=0.0811, 32_l2=0.0434, 64_h1=0.1745, 64_l2=0.0593\n", 587 | "[113] time=1.36, avg_loss=0.7849, train_err=0.0392, 32_h1=0.0817, 32_l2=0.0452, 64_h1=0.1653, 64_l2=0.0627\n", 588 | "[114] time=1.37, avg_loss=0.7933, train_err=0.0397, 32_h1=0.0803, 32_l2=0.0409, 64_h1=0.1715, 64_l2=0.0568\n", 589 | "[115] time=1.37, avg_loss=0.7377, train_err=0.0369, 32_h1=0.0789, 32_l2=0.0389, 64_h1=0.1688, 64_l2=0.0556\n", 590 | "[116] time=1.37, avg_loss=0.7639, train_err=0.0382, 32_h1=0.0794, 32_l2=0.0394, 64_h1=0.1683, 64_l2=0.0574\n", 591 | "[117] time=1.36, avg_loss=0.7515, train_err=0.0376, 32_h1=0.0785, 32_l2=0.0382, 64_h1=0.1665, 64_l2=0.0549\n", 592 | "[118] time=1.37, avg_loss=0.7180, train_err=0.0359, 32_h1=0.0792, 32_l2=0.0394, 64_h1=0.1671, 64_l2=0.0576\n", 593 | "[119] time=1.37, avg_loss=0.7191, train_err=0.0360, 32_h1=0.0795, 32_l2=0.0396, 64_h1=0.1672, 64_l2=0.0541\n", 594 | "[120] time=1.37, avg_loss=0.7148, train_err=0.0357, 32_h1=0.0792, 32_l2=0.0389, 64_h1=0.1671, 64_l2=0.0575\n", 595 | "[121] time=1.36, avg_loss=0.7012, train_err=0.0351, 32_h1=0.0795, 32_l2=0.0399, 64_h1=0.1639, 64_l2=0.0555\n", 596 | "[122] time=1.37, avg_loss=0.6962, train_err=0.0348, 32_h1=0.0787, 32_l2=0.0388, 64_h1=0.1697, 64_l2=0.0570\n", 597 | "[123] time=1.37, avg_loss=0.6970, train_err=0.0349, 32_h1=0.0793, 32_l2=0.0388, 64_h1=0.1693, 64_l2=0.0567\n", 598 | "[124] time=1.37, avg_loss=0.6888, train_err=0.0344, 32_h1=0.0788, 32_l2=0.0382, 64_h1=0.1687, 64_l2=0.0570\n", 599 | "[125] time=1.37, avg_loss=0.7060, train_err=0.0353, 32_h1=0.0799, 32_l2=0.0412, 64_h1=0.1649, 64_l2=0.0576\n", 600 | "[126] time=1.36, avg_loss=0.6991, train_err=0.0350, 32_h1=0.0792, 32_l2=0.0393, 64_h1=0.1681, 64_l2=0.0583\n", 601 | "[127] time=1.37, avg_loss=0.7098, train_err=0.0355, 32_h1=0.0796, 32_l2=0.0406, 64_h1=0.1641, 64_l2=0.0574\n", 602 | "[128] time=1.37, avg_loss=0.6971, train_err=0.0349, 32_h1=0.0792, 32_l2=0.0399, 64_h1=0.1690, 64_l2=0.0588\n", 603 | "[129] time=1.37, avg_loss=0.6810, train_err=0.0340, 32_h1=0.0793, 32_l2=0.0393, 64_h1=0.1648, 64_l2=0.0559\n", 604 | "[130] time=1.36, avg_loss=0.6848, train_err=0.0342, 32_h1=0.0780, 32_l2=0.0378, 64_h1=0.1670, 64_l2=0.0536\n", 605 | "[131] time=1.94, avg_loss=0.6600, train_err=0.0330, 32_h1=0.0779, 32_l2=0.0379, 64_h1=0.1661, 64_l2=0.0545\n", 606 | "[132] time=1.87, avg_loss=0.6428, train_err=0.0321, 32_h1=0.0794, 32_l2=0.0394, 64_h1=0.1695, 64_l2=0.0588\n", 607 | "[133] time=1.85, avg_loss=0.6532, train_err=0.0327, 32_h1=0.0789, 32_l2=0.0392, 64_h1=0.1690, 64_l2=0.0568\n", 608 | "[134] time=1.88, avg_loss=0.6573, train_err=0.0329, 32_h1=0.0780, 32_l2=0.0376, 64_h1=0.1664, 64_l2=0.0559\n", 609 | "[135] time=1.78, avg_loss=0.6445, train_err=0.0322, 32_h1=0.0784, 32_l2=0.0386, 64_h1=0.1644, 64_l2=0.0560\n", 610 | "[136] time=1.82, avg_loss=0.6378, train_err=0.0319, 32_h1=0.0780, 32_l2=0.0383, 64_h1=0.1651, 64_l2=0.0527\n", 611 | "[137] time=1.85, avg_loss=0.6550, train_err=0.0327, 32_h1=0.0792, 32_l2=0.0400, 64_h1=0.1652, 64_l2=0.0551\n", 612 | "[138] time=1.75, avg_loss=0.6341, train_err=0.0317, 32_h1=0.0775, 32_l2=0.0376, 64_h1=0.1661, 64_l2=0.0556\n", 613 | "[139] time=2.00, avg_loss=0.8234, train_err=0.0412, 32_h1=0.0783, 32_l2=0.0386, 64_h1=0.1654, 64_l2=0.0566\n", 614 | "[140] time=1.97, avg_loss=0.6822, train_err=0.0341, 32_h1=0.0784, 32_l2=0.0380, 64_h1=0.1675, 64_l2=0.0558\n", 615 | "[141] time=1.98, avg_loss=0.6332, train_err=0.0317, 32_h1=0.0778, 32_l2=0.0379, 64_h1=0.1670, 64_l2=0.0546\n", 616 | "[142] time=1.99, avg_loss=0.6205, train_err=0.0310, 32_h1=0.0786, 32_l2=0.0394, 64_h1=0.1678, 64_l2=0.0592\n", 617 | "[143] time=1.82, avg_loss=0.6098, train_err=0.0305, 32_h1=0.0785, 32_l2=0.0386, 64_h1=0.1676, 64_l2=0.0584\n", 618 | "[144] time=1.38, avg_loss=0.6116, train_err=0.0306, 32_h1=0.0794, 32_l2=0.0422, 64_h1=0.1702, 64_l2=0.0591\n", 619 | "[145] time=1.37, avg_loss=0.6018, train_err=0.0301, 32_h1=0.0776, 32_l2=0.0373, 64_h1=0.1674, 64_l2=0.0564\n", 620 | "[146] time=1.38, avg_loss=0.6001, train_err=0.0300, 32_h1=0.0781, 32_l2=0.0386, 64_h1=0.1662, 64_l2=0.0583\n", 621 | "[147] time=1.38, avg_loss=0.5990, train_err=0.0300, 32_h1=0.0796, 32_l2=0.0416, 64_h1=0.1679, 64_l2=0.0572\n", 622 | "[148] time=1.38, avg_loss=0.6462, train_err=0.0323, 32_h1=0.0802, 32_l2=0.0411, 64_h1=0.1721, 64_l2=0.0580\n", 623 | "[149] time=1.37, avg_loss=0.6152, train_err=0.0308, 32_h1=0.0777, 32_l2=0.0373, 64_h1=0.1688, 64_l2=0.0562\n" 624 | ] 625 | } 626 | ], 627 | "source": [ 628 | "trainer.train(train_loader, test_loaders,\n", 629 | " output_encoder,\n", 630 | " model, \n", 631 | " optimizer,\n", 632 | " scheduler, \n", 633 | " regularizer=False, \n", 634 | " training_loss=train_loss,\n", 635 | " eval_losses=eval_losses)" 636 | ] 637 | }, 638 | { 639 | "cell_type": "markdown", 640 | "id": "1b20be56-d200-44dc-b97b-fca021e353c8", 641 | "metadata": {}, 642 | "source": [ 643 | "# Follow-up questions" 644 | ] 645 | }, 646 | { 647 | "cell_type": "markdown", 648 | "id": "9a67e1d5-4b9a-4be3-bff4-fb2a6b152f9c", 649 | "metadata": {}, 650 | "source": [ 651 | "You can now play with the configuration and see how the performance is impacted.\n", 652 | "\n", 653 | "Which parameters do you think will most influence performance? \n", 654 | "Learning rate? Learning schedule? hidden_channels? Number of training samples? \n", 655 | "\n", 656 | "Does your intuition match the results you are getting?" 657 | ] 658 | } 659 | ], 660 | "metadata": { 661 | "kernelspec": { 662 | "display_name": "Python 3 (ipykernel)", 663 | "language": "python", 664 | "name": "python3" 665 | }, 666 | "language_info": { 667 | "codemirror_mode": { 668 | "name": "ipython", 669 | "version": 3 670 | }, 671 | "file_extension": ".py", 672 | "mimetype": "text/x-python", 673 | "name": "python", 674 | "nbconvert_exporter": "python", 675 | "pygments_lexer": "ipython3", 676 | "version": "3.9.15" 677 | } 678 | }, 679 | "nbformat": 4, 680 | "nbformat_minor": 5 681 | } 682 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Caltech AI4Science Bootcamp 2 | 3 | - [Slides](assets/Bootcamp_DLI_Modulus_v2207_CalTech_share.pdf) 4 | - [Reference](assets/2023-Nik.pdf) 5 | 6 | ## Agenda 7 | Day 1: Feb 13th, 2023 8 | 9 | - 12:30 PM - 01:30 PM: Welcome and Introduction to PDEs and Neural Operators 10 | - 01:30 PM - 02:00 PM: Getting started with NVIDIA compute 11 | - 02:00 PM - 02:15 PM: Break 12 | - 02:15 PM - 03:45 PM: Fourier Neural Operator (FNO), NeuralOp library, and learning the Navier-Stokes equations 13 | - [Recording](https://caltech.zoom.us/rec/share/QoUOu2fRVjZohOBTBeeqkvivJWLbCEi15UBqatJwxgCy546A1Dv7VunQEjNKO_97.7Acc_2LX7J17mMem)- passcode: RG$?n2?v 14 | 15 | 16 | Day 2: Feb 14th, 2023 17 | - 12:30 PM - 02:00 PM: Introduction to Modulus, Physics Informed Neural Network (PINN), and Physics Informed Neural Operator (PINO) 18 | - 02:00 PM - 02:15 PM: Break 19 | - 02:15 PM - 04: 00 PM: Re-visiting the Navier-Stokes equations and Mini project 20 | - [Recording]( 21 | https://caltech.zoom.us/rec/share/1UeB1MZiqhGzkzPKoHAWAX33IpMYniTOs0YkxDAo9lgFHXux4mBBoki5QOrZ6pOy.65onc8Bg6I41Cvga)- passcode: 2he6K@su 22 | 23 | ## Others 24 | - [Bootcamp material](https://github.com/NeuralOperator/bootcamp.git) 25 | - [NeuralOperator repo](https://github.com/NeuralOperator/neuraloperator.git) 26 | 27 | -------------------------------------------------------------------------------- /assets/2023-Nik.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuraloperator/bootcamp/380749a4d670639806abc82de6eae11fda249ed9/assets/2023-Nik.pdf -------------------------------------------------------------------------------- /assets/Bootcamp_DLI_Modulus_v2207_CalTech_share.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuraloperator/bootcamp/380749a4d670639806abc82de6eae11fda249ed9/assets/Bootcamp_DLI_Modulus_v2207_CalTech_share.pdf -------------------------------------------------------------------------------- /config/darcy_config.yaml: -------------------------------------------------------------------------------- 1 | default: &DEFAULT 2 | 3 | #General 4 | verbose: True 5 | arch: 'tfno2d' 6 | 7 | #Distributed computing 8 | distributed: 9 | use_distributed: False 10 | 11 | # FNO related 12 | tfno2d: 13 | data_channels: 3 14 | n_modes_height: 32 15 | n_modes_width: 32 16 | hidden_channels: 64 17 | projection_channels: 256 18 | n_layers: 4 19 | domain_padding: None #0.078125 20 | domain_padding_mode: 'one-sided' #symmetric 21 | fft_norm: 'forward' 22 | norm: 'group_norm' 23 | skip: 'linear' 24 | implementation: 'factorized' 25 | separable: 0 26 | preactivation: 0 27 | 28 | use_mlp: 1 29 | mlp: 30 | expansion: 0.5 31 | dropout: 0 32 | 33 | factorization: None 34 | rank: 1.0 35 | fixed_rank_modes: None 36 | dropout: 0.0 37 | tensor_lasso_penalty: 0.0 38 | joint_factorization: False 39 | 40 | # Optimizer 41 | opt: 42 | n_epochs: 150 43 | learning_rate: 5e-3 44 | training_loss: 'h1' 45 | weight_decay: 1e-4 46 | amp_autocast: False 47 | 48 | scheduler_T_max: 300 # For cosine only, typically take n_epochs 49 | scheduler_patience: 5 # For ReduceLROnPlateau only 50 | scheduler: 'CosineAnnealingLR' # Or 'CosineAnnealingLR' OR 'ReduceLROnPlateau' OR 'StepLR' 51 | step_size: 50 52 | gamma: 0.5 53 | 54 | # Dataset related 55 | data: 56 | folder: "/dli/task/bootcamp/data/darcy_flow/" 57 | batch_size: 32 58 | n_train: 3000 59 | train_resolution: 32 60 | n_tests: [500, 500] 61 | test_resolutions: [32, 64] 62 | test_batch_sizes: [32, 32] 63 | positional_encoding: True 64 | 65 | encode_input: True 66 | encode_output: False 67 | 68 | # Patching 69 | patching: 70 | levels: 0 71 | padding: 0 72 | stitching: False 73 | 74 | # Weights and biases 75 | wandb: 76 | log: False 77 | log_test_interval: 1 78 | -------------------------------------------------------------------------------- /config/tfno_darcy_config.yaml: -------------------------------------------------------------------------------- 1 | default: &DEFAULT 2 | 3 | #General 4 | verbose: True 5 | arch: 'tfno2d' 6 | 7 | #Distributed computing 8 | distributed: 9 | use_distributed: False 10 | 11 | # FNO related 12 | tfno2d: 13 | lifting_channels: 32 14 | data_channels: 3 15 | n_modes_height: 12 16 | n_modes_width: 12 17 | hidden_channels: 32 18 | projection_channels: 32 19 | n_layers: 4 20 | domain_padding: None #0.078125 21 | domain_padding_mode: 'one-sided' #symmetric 22 | fft_norm: 'forward' 23 | norm: None 24 | skip: 'linear' 25 | implementation: 'factorized' 26 | separable: 0 27 | preactivation: 0 28 | 29 | use_mlp: 1 30 | mlp: 31 | expansion: 0.5 32 | dropout: 0 33 | 34 | factorization: 'tucker' 35 | rank: 0.2 36 | fixed_rank_modes: None 37 | dropout: 0.0 38 | tensor_lasso_penalty: 0.0 39 | joint_factorization: False 40 | 41 | # Optimizer 42 | opt: 43 | n_epochs: 150 44 | learning_rate: 5e-3 45 | training_loss: 'h1' 46 | weight_decay: 1e-4 47 | amp_autocast: False 48 | 49 | scheduler_T_max: 300 # For cosine only, typically take n_epochs 50 | scheduler_patience: 5 # For ReduceLROnPlateau only 51 | scheduler: 'CosineAnnealingLR' # Or 'CosineAnnealingLR' OR 'ReduceLROnPlateau' OR 'StepLR' 52 | step_size: 50 53 | gamma: 0.5 54 | 55 | # Dataset related 56 | data: 57 | folder: "/dli/task/bootcamp/data/darcy_flow/" 58 | batch_size: 32 59 | n_train: 3000 60 | train_resolution: 32 61 | n_tests: [500, 500] 62 | test_resolutions: [32, 64] 63 | test_batch_sizes: [32, 32] 64 | positional_encoding: True 65 | 66 | encode_input: True 67 | encode_output: False 68 | 69 | # Patching 70 | patching: 71 | levels: 0 72 | padding: 0 73 | stitching: False 74 | 75 | # Weights and biases 76 | wandb: 77 | log: False 78 | log_test_interval: 1 79 | -------------------------------------------------------------------------------- /images/fourier_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neuraloperator/bootcamp/380749a4d670639806abc82de6eae11fda249ed9/images/fourier_layer.png --------------------------------------------------------------------------------