{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":70203,"databundleVersionId":8068726,"sourceType":"competition"},{"sourceId":5819812,"sourceType":"datasetVersion","datasetId":3344234},{"sourceId":8084829,"sourceType":"datasetVersion","datasetId":4772325},{"sourceId":8103662,"sourceType":"datasetVersion","datasetId":3014066},{"sourceId":8108072,"sourceType":"datasetVersion","datasetId":4789213},{"sourceId":8138141,"sourceType":"datasetVersion","datasetId":4811146},{"sourceId":4834225,"sourceType":"datasetVersion","datasetId":2801306},{"sourceId":33105,"sourceType":"modelInstanceVersion","modelInstanceId":27718},{"sourceId":33109,"sourceType":"modelInstanceVersion","modelInstanceId":27720},{"sourceId":33112,"sourceType":"modelInstanceVersion","modelInstanceId":27722},{"sourceId":33528,"sourceType":"modelInstanceVersion","modelInstanceId":28065}],"dockerImageVersionId":30684,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip uninstall timm -y\n!pip install /kaggle/input/timm-0613/timm-0.6.13-py3-none-any.whl -qq","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-04-19T16:07:48.530342Z","iopub.execute_input":"2024-04-19T16:07:48.530710Z","iopub.status.idle":"2024-04-19T16:08:08.747924Z","shell.execute_reply.started":"2024-04-19T16:07:48.530681Z","shell.execute_reply":"2024-04-19T16:08:08.746444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/fastxtend-0-1-7/fastxtend-0.1.7-py3-none-any.whl -qq\n!pip install /kaggle/input/fastxtend-0-1-7/colorednoise-2.2.0-py3-none-any.whl -qq\n!pip install /kaggle/input/fastxtend-0-1-7/primePy-1.3-py3-none-any.whl -qq","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-04-19T16:08:08.750956Z","iopub.execute_input":"2024-04-19T16:08:08.751393Z","iopub.status.idle":"2024-04-19T16:08:53.949074Z","shell.execute_reply.started":"2024-04-19T16:08:08.751357Z","shell.execute_reply":"2024-04-19T16:08:53.947283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/onnxruntime/humanfriendly-10.0-py2.py3-none-any.whl --no-index --find-links /kaggle/input/onnxruntime -qq\n!pip install /kaggle/input/onnxruntime/coloredlogs-15.0.1-py2.py3-none-any.whl --no-index --find-links /kaggle/input/onnxruntime -qq\n!pip install /kaggle/input/onnxruntime/onnxruntime-1.17.3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl --no-index --find-links /kaggle/input/onnxruntime -qq","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-04-19T16:08:53.951741Z","iopub.execute_input":"2024-04-19T16:08:53.952311Z","iopub.status.idle":"2024-04-19T16:09:39.649967Z","shell.execute_reply.started":"2024-04-19T16:08:53.952259Z","shell.execute_reply":"2024-04-19T16:09:39.648421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/pakeges/networkx-3.0-py3-none-any.whl -qq\n!pip install /kaggle/input/d/ludovick/onnxruntime/openvino_telemetry-2023.2.1-py3-none-any.whl -qq\n!pip install /kaggle/input/d/ludovick/onnxruntime/openvino-2024.0.0-14509-cp310-cp310-manylinux2014_x86_64.whl -qq\n!pip install /kaggle/input/d/ludovick/onnxruntime/openvino_dev-2024.0.0-14509-py3-none-any.whl -qq","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-04-19T16:09:39.653791Z","iopub.execute_input":"2024-04-19T16:09:39.654222Z","iopub.status.idle":"2024-04-19T16:10:32.019995Z","shell.execute_reply.started":"2024-04-19T16:09:39.654186Z","shell.execute_reply":"2024-04-19T16:10:32.018387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from fastai.vision.all import *\nfrom fastxtend.audio.all import *\nfrom fastcore.parallel import *\nimport librosa\nimport ast\nimport shutil\nimport warnings\n\nimport onnx\nimport onnxruntime as ort\nimport scipy\nfrom openvino.runtime import Core\nimport time","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-04-19T16:10:32.021944Z","iopub.execute_input":"2024-04-19T16:10:32.022303Z","iopub.status.idle":"2024-04-19T16:11:08.750252Z","shell.execute_reply.started":"2024-04-19T16:10:32.022272Z","shell.execute_reply":"2024-04-19T16:11:08.748926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = Path('/kaggle/input/birdclef-2024')\n\nfor el in path.ls():\n    print(el)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-04-19T16:11:08.751940Z","iopub.execute_input":"2024-04-19T16:11:08.752889Z","iopub.status.idle":"2024-04-19T16:11:08.762150Z","shell.execute_reply.started":"2024-04-19T16:11:08.752848Z","shell.execute_reply":"2024-04-19T16:11:08.760661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Background","metadata":{}},{"cell_type":"markdown","source":"In this notebook I'll work on implementing faster code to avoid a notebook timeout error I received on two of my last three submissions. All three notebooks ran the same code (except for model path).","metadata":{}},{"cell_type":"markdown","source":"![image.png](attachment:90e953c8-91ea-45a4-aa49-7a321ccd2f4a.png)","metadata":{},"attachments":{"90e953c8-91ea-45a4-aa49-7a321ccd2f4a.png":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAigAAADxCAYAAADho0xLAAAK12lDQ1BJQ0MgUHJvZmlsZQAASImVlwdUU9kWhs+96SGhBSIgJfSOdAJICT106SAqIQlJKDEkBBWxIYMjOBZURFAZ0ZGm4OgIyFgQCxYGwd4nyKCgjoMFGypzA48wM2+999bba52cb+3ss8/eJ+fe9QcAcghLJMqGVQHIEeaJY4L9aEnJKTTcMEADDCABT2DIYktEjOjocIDY9Px3e3cLQPL5uq08179//19NncOVsAGAUhFO50jYOQh3IuMZWyTOAwB1EPEbL8kTybkPYQ0xUiDCv8mZN8Uf5Jw+yWjSZExcjD/CNADwJBZLzAOAZIP4aflsHpKHJO/BXsgRCBEuRNibzWdxED6BsE1OzmI5DyNsgcSLACAjpwPo6X/Jyftb/nRFfhaLp+CpviYNHyCQiLJZy/7Po/nflpMtnd7DDBkkvjgkRr4fcn53shaHKViYHhk1zQLOVE1y5ktD4qeZLfFPmWYOKyBMsTY7MnyaMwRBTEWePGbcNHMlgbHTLF4co9grQ+zPmGaWeHJfIsIyaVa8ws/nMhX5C/hxidOcL0iInGZJVmzYTIy/wi+Wxijq5wqD/Wb2DVL0niP5S78CpmJtHj8uRNE7a6Z+rpAxk1OSpKiNww0InImJV8SL8vwUe4myoxXx3OxghV+SH6tYm4dczpm10YozzGSFRk8zEIAIwAJsmso0AZDHXZonb8R/sWiZWMDj59EYyNPGpTGFbDsbmqO9ozMA8md36jq8oU4+kxD18owvtxMA91LEyZvxsYwBOP4EAMq7GZ/xa+QqbQbgZB9bKs6f8qHlHxjk11MBGkAb6ANjYAFsgSNwRd4RviAQhIIoEAeSwUKkVj7IAWKwBBSCNaAElIHNYDuoAjVgH6gHh8AR0AZOgDPgArgC+sBNcB/IwBB4DkbBOzAOQRAOIkMUSBsygEwha8gRokPeUCAUDsVAyVAaxIOEkBQqhNZCZVA5VAXthRqgH6Hj0BnoEtQP3YUGoBHoNfQJRsEkWAPWg83gOTAdZsBhcBy8AObBuXABXAxvhCvhWvgg3Aqfga/AN2EZ/BweQwGUEoqKMkTZougof1QUKgWVgRKjVqJKURWoWlQzqgPVjbqOkqFeoD6isWgKmoa2RXuiQ9DxaDY6F70SvQFdha5Ht6LPoa+jB9Cj6K8YMkYXY43xwDAxSRgeZgmmBFOBOYA5hjmPuYkZwrzDYrFUrDnWDRuCTcZmYpdjN2B3Y1uwndh+7CB2DIfDaeOscV64KBwLl4crwe3EHcSdxl3DDeE+4JXwBnhHfBA+BS/EF+Er8I34U/hr+Kf4cYIqwZTgQYgicAjLCJsI+wkdhKuEIcI4UY1oTvQixhEziWuIlcRm4nniA+IbJSUlIyV3pXlKAqXVSpVKh5UuKg0ofSSpk6xI/qRUkpS0kVRH6iTdJb0hk8lmZF9yCjmPvJHcQD5LfkT+oExRtlNmKnOUVylXK7cqX1N+qUJQMVVhqCxUKVCpUDmqclXlhSpB1UzVX5WlulK1WvW46m3VMTWKmoNalFqO2ga1RrVLasPqOHUz9UB1jnqx+j71s+qDFBTFmOJPYVPWUvZTzlOGNLAa5hpMjUyNMo1DGr0ao5rqms6aCZpLNas1T2rKqCiqGZVJzaZuoh6h3qJ+mqU3izGLO2v9rOZZ12a915qt5avF1SrVatG6qfVJm6YdqJ2lvUW7TfuhDlrHSmeezhKdPTrndV7M1pjtOZs9u3T2kdn3dGFdK90Y3eW6+3R7dMf09PWC9UR6O/XO6r3Qp+r76mfqb9M/pT9iQDHwNhAYbDM4bfCMpklj0LJplbRztFFDXcMQQ6nhXsNew3Ejc6N4oyKjFqOHxkRjunGG8TbjLuNREwOTCJNCkyaTe6YEU7op33SHabfpezNzs0SzdWZtZsPmWuZM8wLzJvMHFmQLH4tci1qLG5ZYS7plluVuyz4r2MrFim9VbXXVGrZ2tRZY77but8HYuNsIbWptbtuSbBm2+bZNtgN2VLtwuyK7NruXc0zmpMzZMqd7zld7F/ts+/329x3UHUIdihw6HF47WjmyHasdbziRnYKcVjm1O71ytnbmOu9xvuNCcYlwWefS5fLF1c1V7NrsOuJm4pbmtsvtNl2DHk3fQL/ojnH3c1/lfsL9o4erR57HEY8/PG09szwbPYfnms/lzt0/d9DLyIvltddL5k3zTvP+3lvmY+jD8qn1eexr7MvxPeD7lGHJyGQcZLz0s/cT+x3ze+/v4b/CvzMAFRAcUBrQG6geGB9YFfgoyCiIF9QUNBrsErw8uDMEExIWsiXkNlOPyWY2MEdD3UJXhJ4LI4XFhlWFPQ63CheHd0TAEaERWyMeRJpGCiPbokAUM2pr1MNo8+jc6J/nYedFz6ue9yTGIaYwpjuWErsotjH2XZxf3Ka4+/EW8dL4rgSVhNSEhoT3iQGJ5YmypDlJK5KuJOskC5LbU3ApCSkHUsbmB87fPn8o1SW1JPXWAvMFSxdcWqizMHvhyUUqi1iLjqZh0hLTGtM+s6JYtayxdGb6rvRRtj97B/s5x5ezjTPC9eKWc59meGWUZwzzvHhbeSN8H34F/4XAX1AleJUZklmT+T4rKqsuayI7MbslB5+TlnNcqC7MEp5brL946eJ+kbWoRCTL9cjdnjsqDhMfkECSBZL2PA1EJPVILaTfSAfyvfOr8z8sSVhydKnaUuHSnmVWy9Yve1oQVPDDcvRy9vKuQsPCNYUDKxgr9q6EVqav7FplvKp41dDq4NX1a4hrstb8UmRfVF70dm3i2o5iveLVxYPfBH/TVKJcIi65vc5zXc236G8F3/aud1q/c/3XUk7p5TL7soqyzxvYGy5/5/Bd5XcTGzM29m5y3bRnM3azcPOtLT5b6svVygvKB7dGbG3dRttWuu3t9kXbL1U4V9TsIO6Q7pBVhle27zTZuXnn5yp+1c1qv+qWXbq71u96v5uz+9oe3z3NNXo1ZTWfvhd8f2dv8N7WWrPain3Yffn7nuxP2N/9A/2HhgM6B8oOfKkT1snqY+rPNbg1NDTqNm5qgpukTSMHUw/2HQo41N5s27y3hdpSdhgclh5+9mPaj7eOhB3pOko/2vyT6U+7jlGOlbZCrctaR9v4bbL25Pb+46HHuzo8O479bPdz3QnDE9UnNU9uOkU8VXxq4nTB6bFOUeeLM7wzg12Luu6fTTp749y8c73nw85fvBB04Ww3o/v0Ra+LJy55XDp+mX657YrrldYel55jv7j8cqzXtbf1qtvV9j73vo7+uf2nrvlcO3M94PqFG8wbV25G3uy/FX/rzu3U27I7nDvDd7PvvrqXf2/8/uoHmAelD1UfVjzSfVT7q+WvLTJX2cmBgIGex7GP7w+yB5//Jvnt81DxE/KTiqcGTxuGHYdPjASN9D2b/2zouej5+IuS39V+3/XS4uVPf/j+0TOaNDr0Svxq4vWGN9pv6t46v+0aix579C7n3fj70g/aH+o/0j92f0r89HR8yWfc58ovll86voZ9fTCRMzEhYolZk1IAhQw4IwOA13WINk5GtAOiy4nzp7T1pEFT/wcmCfwnntLfk+YKQJ0vAPGrAQhHNMoeZJgiTEJmuSSK8wWwk5Ni/MskGU6OU7lIiLLEfJiYeKMHAK4DgC/iiYnx3RMTX/Yjxd4FoDN3StPLDYto+cMYOfXorwT/tCm9/5ce/zkDeQXO4J/zn/AaF/I9Vn1sAAAAemVYSWZNTQAqAAAACAAEAQYAAwAAAAEAAgAAARIAAwAAAAEAAQAAASgAAwAAAAEAAgAAh2kABAAAAAEAAAA+AAAAAAADkoYABwAAABIAAABooAIABAAAAAEAAAIooAMABAAAAAEAAADxAAAAAEFTQ0lJAAAAU2NyZWVuc2hvdKGOucQAAALvaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgICAgICAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjE8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlBob3RvbWV0cmljSW50ZXJwcmV0YXRpb24+MjwvdGlmZjpQaG90b21ldHJpY0ludGVycHJldGF0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MjQxPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6VXNlckNvbW1lbnQ+U2NyZWVuc2hvdDwvZXhpZjpVc2VyQ29tbWVudD4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjU1MjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgrgto1fAABAAElEQVR4AexdBZgUxxIu9OHurgnBnRDc3d3d3V2CQ3CHw12DO8ESJLi7ux8OwfL6r72em93b3dvj9o4jVH3f7sy0VPf83dNdXVU9E+xfRSQkCAgCgoAgIAgIAoJAEEIgeBCqi1RFEBAEBAFBQBAQBAQBRkAEFOkIgoAgIAgIAoKAIBDkEBABJcg1iVRIEBAEBAFBQBAQBERAkT4gCAgCgoAgIAgIAkEOARFQglyTSIUEAUFAEBAEBAFBQAQU6QOCgCAgCAgCgoAgEOQQEAElyDWJVEgQEAQEAUFAEBAERECRPiAICAKCgCAgCAgCQQ4BEVCCXJNIhQQBQUAQEAQEAUFABBTpA4KAICAICAKCgCAQ5BAQASXINYlUSBAQBAQBQUAQEAREQJE+IAgIAoKAICAICAJBDgERUIJck0iFBAFBQBAQBAQBQUAEFOkDgoAgIAgIAoKAIBDkEBABJcg1iVRIEBAEBAFBQBAQBERAkT4gCAgCgoAgIAgIAkEOgZBBrkZSIUFAEBAEgigCHz9+omPHj1nVLkP69BQ6dGirMLkQBAQB/yMQ7F9F/mcjHJwh8Pr1G9q1axf9/HMOih49urOkEheACDx8+JCOHDlKHz9+pBw5slOsWLECsDRh/V9E4OnTp5Qlaw6rW1u5YhllzpzJKuxbuDh9+gw9f/6ccuX6xWF1Ef/48RMjPmTIkJQ4cSLj+r9ycv/+Azp27BgVLFiA/ve///1Xbuubvw/RoPijCQsXKUYQPsyEhzd79mzUonkzChs2LEf17deffv99Ff3444+0edN6c3KXzhctWkITJk6i1Kl/opkzpht5Pn/+TMtXrKSdO3bRn3/9RZ8+faJkyZJSo4YNqGLFChQsWDBOe/HSJapXryGfb1i/hqJFi2bw0CfmNDrMfKxTpxa1bNGcli5bTmPHjjdHWZ3PnTuLfkiZksOmTfOgNWvX0sWLlyhmzJj0sxIK+vTpZbd8ZHjw4CH9nDMX540XLx7t/Ws3n7vjb+vWbdSseUuD1ZDBA6lGjerG9fd40qlzV9q3bz/VrVub+6stBvbaOnr0aJQ1a1YqV7YMZcqU0TaLv6+7detBe/78i4oULkQDBvS34nf27Dlq1Lgph+34Y6vxfFklCsSLKpUrcR3ixInNpeL5mzhxMm3bvp3On79AkSJFpLRp01Kb1q0oW7asfqqZxj5Vqh9p9qwZfsrrSmJMyGXKluek8+bOpjx5ctvNtmLl7zRo0BAjLmLEiHTyxFHj+ktPho/4jVavXkuRI0emTRvXGWOV5rdt23bq2+9Xvly4YK4a15LpqAA5VqhYme7fv09NGjeinj27B0gZZqZz586jqWp8tEetW7WkWrVq2Iv67sKCtIDy9vA2bpCwWYsEyYa5fv0GCwXmyqGT//33QVq7dj0/eBBSsmbJzAJKdj8OUprv48eP+eGxlezbd+hE69ZZCzznzp2nzl260foNG2nWTA9+8N+9e8f5we/Dh4+ardXRnMYqwuvi1q3bfPbkyRODl7104APC5AehTBNwWb1mLe3es0cJaRvsai+6dO2mk9Pdu3eNc3ecDBk6nNlAg5U3bx7KXyC/O9gyjxMnTlL5CpX4/ML5M35S9/snr39v4Pr169yWmKzskb22RjueOXOWMMBOnzaFihQpbC/rF4fduHmT6zR/wUKeNM38X79+bfQ9COd+oaTJLELzDI9pVKhQQb9kdZi2e/euhrAN009FNcmdOn3aSO/p+Yz+VMIWfmPGjKLy5coacb6daOxDhQqYITpatKgUJ04cevHiBSVMlJCrY68vplKLqlKlShKe/5MnT/pWbZfjM2XMSFOnTuf2PHjwEGs0zZkXLV7CcRCIkiZNao4KkPMcalGJMTNturQBwt+W6SmlvcKzZI/cPfbZK+NbCQuY3u+Gu//34wd66tGf1AxL8TLmp2AhQ7mBa8Cw6N27J5UqWZKg/l2wcBEtVg/XjRs3aP+Bv6mgmgixUq9evZqPVYKuDaxsWH1BfWomhGstiDkc51jVaOGkTJnSVK1qFYqoVmyzZ81hQWDXrt00b958pTmpa5vV1+sVy5dSjBgxrNJFihTJ6hoDx7q1q63CcBEvXlzGQQsn/fv1UauBWnT23FmqWrUGYdBes3Ydr1TMmTdv2coDuTnMnedoD9CAX/tRyZIlfLDGhBc8uHOfcWftoRmiHb+UnOV1pWyU69t9+BZvr+5o640b1tJHdW+XlDasd5++9PDhIxZC7a2mXSnDlTRt2rZXGp4/KVrUqPaq5SPMFZ4+MnkFuIqvo/z79+83hBNofsqULkXXrl2n7t17ErSTv/3mNwHFXjmu3p+9dLb3B5+Z/QpbR6T7Isw/+P3xxw5q3KSZo+R+DocpJUSIEDzurVq12kpA+eeff4yxwKwJ1oXYuz8dZz5++PCBQoWynjdscdDpx44dzUKko/HW1TId8dfl6OP9exbhBBqbOnVq62A+Ro5sPdZaRX5nF85H5K8Ixot1HvRRraI/3rlDOA/KFEWpKaHmhQlmoBqc8OCBrl69ykcMTj+lTkfNm7fia6yoUv2UlvLmK8BCRNp0GSlzluwch1UiBuY0aTNQyh9+YpX2y5cvOU7/4WGZo1awoNJqIBw/bgwPIunTpeOHLNcvFpvy4iXLdBY/HRMkSMB2Zpir9C9q1ChWPDDA6TjzEQPChQsX2dcmefJkLCCFDBmCUDcMSiCsmMwEM1mnTl04qETxYuYof5/v33+AsdaMWrVuy9evXr3ioKVLl1Gu3PkoeYofCavs4iVKE/KYafXqNUrjUpiSJf+B86IdDyjhEwQhUGtPcJ0ufSaqXbsea4DQhmhnCF+aypatwGE9evZ2mFenPXnqFLc/eKBsmBT37t2no3kQRxzCUQbqiPtAv8KEYqbz589TzVp16IcfU3P5I0eONkc7PUdbo08kSZyYNSYjfxvB6dEv7927x+fok6PHjOW6oA64d9wj+rMmaBmGDhtOOX7+heuJIybw27dv6yRWR0xU7dt3tAqzd7FWaRGrVKnO95YiZSrG/8aNm5z0woULfL86HyZZYIaJBOSsbXUeV4579lgmewhzdWrXoihRorAJbOLE8bx4gNYOvk/62c+cJZsV2/oNGnG9JipTri3NmDmL8QSulSpXpcNHjhhJND/0ASwKNLZVq9WgZ8+e0bz5CyjnL3l4LGnZqg1dvnyF8wJb4IAfMHLUj42C3HyCxRiEONC69RuM9sA1+q4WkLDwAj319KSuXbsb95c12880Sy3G0O9A5vuBphb3jL6uNb++tTNMPBijoRnUZFtmsWIlafz4iVZ1RT5guFKZwmBCBg9ct2zZmuukedke73o9N2nSpqGECRNY/WwXg7Z5v6dr6yV7ELnzT88e0YulE43a4DxCgSoUIkpMIyyonmzatNl4uLSg8EoN0niAoLYFvX//nq/x8PTrP4DDMLDhoaxdpx4dP36CwyDo7Nixk3bQTr7Wf5cuXzbK6Nqlsw42jsOHDyHY68OFC2eEBeZJzpw/0+FD1pM8BhKokEEpUiS3qs6AAQPpzZs3SuBJTM2aNaVNm7dYxfvnAlqRcOHCWg0WuEZ9MMANHDSY2QN/1AGDNSZy+DgkVapltGeHjhaMYR4KESI4bdm6lXbt3s2r+xAhrB8hDLyhQodSmqR4VE6p9KFN69evP/tUYCDWJoA2rVvSzp27rW5N50XglStXWeOEfoN+gLZEGPrHgvlzWSDV/QimxhYtLMIv8qJfYSL+Y/sWtt3Dt6dS5Wp8f4gHTZo8xXLyBf96UkDWYMGCM4cePXrRsuUr+BzCLDRlS5YsVW1+Qmlf1nF4n779OAwXaGuouOFrcfrMGVq/bg2n0X8YtHEfmIDBt2qVyjrK6gjhpF27DhwGjIDX3n37qFjxkrRv7x6vcJ/tjwjf2tZVzQ14JUmSBAeC0AYTK3zQIKCnTJmChg0bwnH4022GepoJeCHs2bPn5mDGYPDgoUbY0aPHlDa2Fm3buon7p+aHvgGzqqZDhw5TqdLlrEyluF+YdNB/0Ia6Du/eoY/Z78eaX0AcqyrhA8IEnjsIXdmUbxNopZdpGCaon35KxfGVVf+9du0ax6N/YSzFs/vg4QPq0b2b1f10UKZvTUoB71I7a/z1YhCLpooVq7AmHLxgXocm7OLYcXT/wQOCDxtI5+vVu6+BJ8IxhgVXz+3ECeNw6YMeKB6gY8eO05w5c1kjiXGzbt3avJjzkeE7DbCMLkHs5j3nD6HPr98atcI5woIqdVOrwPQZMhNWb9B+oDNPUisnPFy+Eey7Rw7/zRM6HBa1cALTyKWL5wjmFls6fMiygsLEhYHcluLHj88rXahmv4Ty5S/IKzasgvUPA6CZMEDoOH00DwzmtDgfNmwED5aoc8MG9Y1oDLh6Yps8aQIFC65GFBcIK0Wsosw/TIi2hN06R494a2zgEIhrrFLg7wCH3q5dO7Pj35nTJwzt146du5jVho2b+Ii2hNB1YP9egnNkxowZuK3gzLZ61Uqj2GNHDxlOjT17dOO+AHPIrFmzldOnZVBr364tCzDO8nbu0pUHvDx5ctP5c2cIdatbtw6X06NnL6M8nECwbdyoIfcXs0MlJnfQzJmzDOEEdb144Sz16tWD41z5Q1tDm4PBFCvFDh0tEwAmCmgOMbnoNly2bDHju2f3Tr53+ERpDdKWLRbBs0mTxrRr53bu99j9AqdtWy1K5kyZCOlAPZUmxp5dHhoZLZx079aVMQJOcEbH5Dtq9Bg+N7c/fFBwDVW+b23rCjY6TbVqVbhP4BoYQaOB56Kj0gxC6PUPNW3amC5fOk/bt23h/on2xkrelrp17cJtq7UOwAzP2tkzJwk8QNDA2Tr2I9xZX0S8KwTtg/l5xDm0eY4Iuxr1ImrVKouACoFr926LYFmlSiXOOm26BwsnWCAcOrif2w/+T6Dp02ewSZkvvP4wJkI4hz8YNH9f0s7Tpk9n4QTj1dYtm9QzeNoQSrDo0IstXS7SYVFz5MhBw1y1ffsfOtrqCO0dhDIQMMOYj7ZCv4FQZMvbKvN3dhHkBJR/rpyg19ssndXcFgj754r7nLTMvP17DoEkbNgw7LUPXhgcByofEWxr9Y0GDxrAAzTU6FhtgmLFismmEQyiWZSDLYQYM719ZxHesOIOCEL98QCZf+ZVsy7THI/zBw7uF6t1jxkzOduY0SN5Rw8uMMFAoAPBVwYmMlcJkz4mTvNPr35c5fFr/760ceM6yp8vH/vFTJjgrV6/e+cus9E7VTDRoq7QgnTu3JGWLF7I/kXOyooQIQKhDBCcdLHawiDbqlULZ9lYhawF1UQJE9KKFStY8xDda/cVNAswF5ipffu27MOUP38+w6kQKz4QBAtQpUoVKUOG9OxrA4HG1mzHiRz8lStXkSpWqsLaAdwHBuRxY8dwarPJ7ooyIUBQ3Lt3LwthSIDtmyDsaAHBnAAfqoOHDtG8uXPUbzZPJBxp+oN2EJoWTMgwq9n2Qfg1acKOGZQLfwaYokD6vnUa26N/2taWF57FVb+voEUL5xuCCp4J1AdmQ5gSv4SAMwQPHKGRady4IbM55qVlNfNs2LA++1yYfRqaNWvCO43qeQm3SH/r1k1zNredP3r02Op5xLN5967FBGivEIxvlVWfBK1RmhRM3FgYoL1BVSpbtGbYdACC5hOTPtoZvIEJ6JwyX5qpZ88erDnEmAr6knbWJlxoeaAFA8GXEGMzCH3XTJXUrkloXKF1a9q0CUdhHDWbOHX6T58+U6eO7XlcHzxoIAvW0CBibMC99+rdRyf97o8BM8P5A1bP6apxvOzDYbLm5PN3R5S5QIV5Tu9NcYav9Qf3gMkKx0sM/qB7Sm1dpkx5Vl/DBm/eFmyvdGyz03Re+W6AMCibKWnSJOZLQxWKBwBCkO37PDDxIy640kborc5WDHy52LZ1M6+Mzckw2ZoJkxtWyWbSA4Y5DCu9MUotCsLDCIdeTZMmTeaVAwS8pk0asZ356ZOnOpqvI4QPb3dXDFZHtmTrEGcbb3sNlTfU8ZhIbEk7y0FbghUdtBHrlXCCH6hEieI0dMgg3iZpm9d8jQEOZjy0B6ht29Y+nKHN6XF+R/ldaVq4aLE+tTre8RKgdGB4hZMmaDWgDv/8+V8OunL1Ch+TJk3CR/2XMGEiFpr0tbNjmjSpefeOTtOlcydja+rpU6d1MPudGBdeJzeuWyZEaDlu3rzFK9OZSqOEH/oMzCGdOnWwzaZwCkEe06dS0WIl2DQ2Zeo0qzRn1W4iTT17+RzUb9/2xlGnMx/927ZmXvocanoIKm/fviU4qg9S5hmsjrsrE5i57+v0vh2xPR9mSk16u62txgnxekKGiVGTfm7DeL3yQIcHxLFDh3bcv828zXU3h+vzKsp0Bz8ZPIPQpkKgA0EY09phmKtBEMwxptrS9Ws3CBo3TXGVachMX9LO589fYBaoh5kghGBxdOa09fijBRekjR0rlpFFC1tGgDpBv26ttp6bCc8XzEbwY8EuOSxAIPR+7xSkEHj95yr65+wpbpNgqhGjNbaoxO+dKEb/YtJVcUgTPk+FINtueDjKlCml7IrzCHZgv1DSpEk4ue3kc1s9mGZCZ9a0ePFSpeZuoy/52FOZAPB+FDw0fx/YZxXnygX8MfTA5ih98OAhfE0zatQYmqiEEBBMCjVrVrdit9HLfILJG46qtpRFOQ7DHGJ7f0inB2PbPK5eQ5UMp0EQTGF1lSc9NDgtW7Yx/EQQB1MQVviXlWYAfifwCYITLYQbpMc7C5wRfCS0cIJ0eDdMrZo1jNWfvbywvWvCoAVHOluKGzeOqtNl22C711oQsZ2wzYKQ3YxegVjZaR+RgoWKsvCDSaWJEioxAelJE/1mwYK5PlhFjRKVw4AXTDtYEe9Tu17WrFnHwgr6SOHChVi7Y5sZq1eYyqCB0qp/nQaThSaYrmzNg6F82fnn37bVZeMI599bSviCthM/LAwgxOK9RNCggOA8rgVfXGN1rQVLR9rWR48eIalBWjCJHTu2ERZUTiBs2lukOKtfWtW3MU5h0l+m/JG0czd2PWqCRgy+W8WKFlXPbHMdbBwTKJO2M/qSdtZlarw1f21qTJ48uQ7y8xFtrc2v5cqVY4EFTMyLVexAEgGFyFs09zPM7s3w73vlZzJzsME0QplaFCp+cv7hXJPnrMGEtEGRoLmAuhvqSlAir/cLuFrXjBkycFI8BHixGAirBpgVzISOW7CgxbY7dtx4XoliizM6NValEE5AVatUMWcL1HMM2Fo4gYoaJgVbSqBsxZj8zD9zGoRHUy8GCwjCSl7TsKGDqWjRIjypnD1nWa3pOJgisEMEEyruASp87VukTRvmiRHtoAkTEPwnQPXr12WfDLSth8dMncRqUtV50b565Xbo8BF2msMuKAg6qM+C+Qv9NBHAXwa0XDmb6gF2g3rnA9TkfqVBg37lLOADfqCsWbPwEavg8OHCc33TKXPOvHkLaNy4CXRJmZqwawpmmnLlK1GYMGGoQ/t2tGWzd78270xhZqa/xmorJvjZUvr06Yyga9evGzgdOXyURowYSXpnDRLpifOx6Z5daVujAF9OPJ96smMkHIH17j2sniHIafrhh5SUJIm3dnTqtOls5oSw6+idGOChd5bAtDZz5mxml8F075q/f4+O+rF/+fqWX5ty4MekNQ4VypczsumX3J1XvjwplGCAZwGmzyFDhvG7VF7Y7HI0MnqdfEk7w3cNhAWgfi4hVGA8Buk68YUf//B8Q3OLn8eMGZwbc4fWNMOH6ks0336sxjeRPMhoUJ6tGE+fvAaPEGofeJTqnQ0Acf5mx2r69PwFfXr8hJA2as1uRvzXPkFHg6Osfrh0fczOoDrM2TF37lxs3sE7O6Dq0ysLe3ngUIotbvCNwAOIn5kwwcGcYEt4U6serHXcsqWLKWQo765gL03FCuXVoD9MZ3F6xIMM5zVNI0eNJvw0YfWHt8TaM3/hVfSVq1hWT7Y7gXR+dxyxsgUOaLMq6v0s8PXBhGbbhsARQh8mUJh3MAkDcxDepgpKmSIFH/FXqHAxDh8+fKha9Q/j9DCH9ezRnR1yYYoAFuXVAAxTjKO8fXr3Imw9hcobGhts5da2+BhKcLNtQ6MCdk7qqZ0BCxcu4nuDpspZv7KT3Srol5w5+bXuUMcPVhME7gP9VjsNY/cMXsJ1W5mp9KSLtwdrjRxe9lWtek1+2/KlS94aoOLFilqVY76A1mHatMmUJ28Bq/bBII63G0+eMpXgoD1dOVNCowMVOai0yXcLwgHaDduaPTxmsMOpK21rroezc/gnYGEAIQJ9ANoks09UwQL5WVsCrY+Ow1tn8QPpvmivjP6/DqRx4ydYmeOw283d5KgvurscW36VlTOseVcZHKexONEEvxtgi3ExW/acrGlD/4PAjmcrQfwEanH2Xif3cfySdoZQjB1maMPsOX5hHymUD8LuTP8IKHAKR3+Avw0E6SlTphm7u8Af/ilCFgSChAbl06Pb9HKl96oySr2uFDxcRKONcI4wTUiLPEGJ9MQGr3Q8YNOmTubXzfuljvDFWLpkkbFahNoTD1ejhg2YDQZfTUi7fNkSNhdgS6smhOPlP2vXrPLxkiKdBnU1//Q7IXQ8juZ4nEM74yrpd4zo9La8zCYPnUYfzSpwHRYQR2Dp4TGVtRqYSKFRgMbL9psqmHig/YDZBSY7TH5oY+yy0n5HmCixlRSTDO7tD2UGgoMqPlEAGjJkMLcF1NaYoICHdoSzlxd58uXLqwauSSywon4QTsAf221HjhyBJA7J3E+QCCYYfIJA9xP0K5gf4C8B8ivmAwdYtCgYvCG8YUW4cME8VsHjHMIc6gzMFi9aYDitDhkykNPgPiDEmtNg55kzihs3Lg03bdfVabt06URt2rTiCQ0CCNoHzwDax2wmQPtop2DsSMPWa1faVpdj77hKvR8Hq368LwOOmHhlu/7MgxZOIIzgeZyufGlAwHq52umkzXioa9OmjVnIs1cG+MEkCMEHBOESixM4O7tCfmlbR33RlXL8kwbmFDwXmqpVq6pP+Yi2X71qBaVXH2XE8wWBHUc8q3hZJHw6nNGXtHPs2LHU28BXseCN5xXCCdoK752aNcvD6QIhhHoVgW+E/oBdeRhL0FdwP/A9nKne/m1+e7JvfP7r8UHiY4GPhjehN39tZ6xDp0hJcUdvVk+yTSP/+5nudShG769YVl3hchemmN08/rPtg62A8JPQg6pvN4pBEo7EkM6F/IYAzBUYfMyrNnsc8MkBTP6OMIagh4kPbQZ+fiFnedEXPD2fEiZxv0w49spHPwmj6oaBMaAIanBgFD684zJg248a1Xkav9YP7QOyfQuymQ/U9RCi4JdgJt/aVqdFft8+FojdRsAA/cC2HM0Hx+fPn3O8K22KCQzpbR3izfzcdW7ui8Dl/PkL7MAKTRUELntvD3ZX2b7xgSnk9p3bSmsS/4t8NFxtZ3M94LAKvxEt4Jvj3HEOUyuEw4B8Jt1Rz6/B46sLKO/O7KcH3Wta7j2Y8oAevpTC/JSdPBcNpxeLLauOSDWas0nn3bmD9KCrRf2PDLGHLaIwaXJ+DdykTEFAEPgOEYAmEe/BMBOcYn0Tbs3pv6VzaMjM5uOvLaB8S9hJXf2PgLfjgf95+Z2D0opg67CmcHmLsXCir22PEFzC5StGb3Zv4SjkjTtWOZPaaltsM8q1ICAICAJuQABb2fUL89zALsizgM+R2ZctcqTIQb7OUsH/DgJfVUB5uXUBvb9qeUNpsDChKVoDy0utnMGLNG//3kn/vnvPecEjYrG6zrJInCAgCAgCgsAXIIAda3rX2hdklyyCgL8Q+GoCyufXL+jZvJFG5SNVbkYhons7exoRNidIg7TPF0zgmGfzRlH43OUpeHhrm7JNNrdfesy1/wIttxckDAUBQUAQEAS+OwSa1Kvx3d2z7Q1/NQHl2eLf6POLl1yfkOrNe5ErOH/hlbniSPt661L6qByXPquPX4GXfqmbOV1AnkvnCUh0hbcgIAgIAoLA946AzVaZwIHjw+3L9GqDtwYiaqM+FCx0GJcLR1rk0QRe4CkkCAgCgoAgIAgIAv8NBL6KgPJ0Rh9+dT0g/F/6zBTul9J+RhN5kBeE1+CDp5AgIAgIAoKAICAI/DcQCHQTz9vD24g//gf81MfsojUdZBfJsOlyqXC171hR2HS/8NH2L1qTgXSvnRJu1EfRwBO8w2YtYptMrgUBQUAQEAQEAUHgG0MgUN+D8u/HD3S3dQH66PW11gilqlH05q69Pt0Rrk+mdlfmoqUcHVK9vCfexJ0UzJePhDniJeGCgCAgCAgCgoAgEDQQCFQTz4t1HoZwEjxieIpay/H3dD49uUv32hfh36en9xyiBR7gBYLggzKEBAFBQBAQBAQBQeDbRiDQBJRPzx7Ri6UTDbSi1GyvBAvLZ9iNQNPJm0Pb+LX2eLX9m4NbTTHWp+ABXppQxufnllde6zA5CgKCgCAgCAgCgsC3hUCgCSie84fS59dvGZ1QiZNQxJINnCIVLlsRCp08Bf/CZXf8pVMwAS/wBKGMp/Osv+zLEfInCAgCgoAgIAgIAt8MAoHig/LPlZN0v0N5/pgdkIk1aC6FzZDXrSC9PbGHHvauZ+GpvhgaZ8xq+l9y17746daKCDNBQBAQBAQBQUAQ8DcCgbKLh7+3o770CgquviKKDwTi524Cb7y4DV/1RZlxhq91dxHCTxAQBAQBQUAQEAQCAYEA16C8/nMVPR7RMRBuxWcRMbqOpvB5KviMkBC3I/BCvRU4UqSIbucrDL8uAv+ldn379i2FVDv8QoUKlHXZ1204KV0Q+A8gEKA+KP++f0ueswZ/NZhQNuoQEPT582cqVa4i/b56jRX7Bw8ecvi7d/9Yhdu7ePjwEV3x+liivXhz2PyFi2n02PHmILec16xTn86dP++U15mz5/iecL+2v9Vr19HfBw+p8Ap05+5dp3wCI9IvmNrW5+q169SgcTNq17GzEYV2njBpChUvXY4KFStJvfv9Srptcb/A479Krrbr8N9G0dLlKwINhrXrN1C/Xwe6VN7AwUNp5e+rOW2zlm2o/0D7711CAv/0HZcqE0CJbOv9/v17H8/poKHDjdKvXr3GfTx/4WJ8xLWQIBAUEQjQpcSHu9cofJEqX/W+UYfQSVIHSB1eKHPSmHETKFvWLJQwQQIu4+Onj4Twf//97GuZm7ZspcNHjtCEsaN9Tfv8+XN68vSpr+n8muCB+p7R27fvnGZLljQJjRhqETSXrVhJ19RE3q1LJ84TN05sihAhAg0bPJDixY3rlE9gRPoFU3N9NmzaTL+NGkNx4sSht++88Zi3YBFt3rpN3d8ACh8+AvXq248mTp5CnTu2p48fLW1t5vNfOs+UMYNL7Yp+GTly5EC79VevXtHDR49cKg91e/nK8s2v3j27Ubhw4Rzm+9K+45BhIEXY1vvevfs8Bk2ZOI6CBbOsQSNGjMC1+fDhI3Xu3pOyZs5EHlMn04KFi/h66cL5olkKpPaSYlxHIEAFFAgGASUcuH6LAZsyvno5XLcevWnB3FkUPLhPhRRU5IuWLKVjx0/QT6l+pCqVK1L8ePFo959/0YxZs7lyWLEPHtCfJ/r9B/6m9Rs3kaenJxUvVpTKlCqpBhnLG3U/fPhAk6dNp+OKV7p0aalOzRoUJUoU5uGoHEQ6i+PMXn/Q5kBb0Lplc0qRPLkRFTZsWEqT+ie+jqsm8CdPnhjXCHz0+DEtX/k75folJx08fJjrBywOHT6qwn6mEuo+pk6fwQJW5YoVKHcuy5uB/1W+Qit+X0V7FBb/+9//qE6tGpQhvcWx2RwXLVo0Kl+2DGHCBPUbMIjq1a5FyZIl5WvUOefPOej1mzd2MeVEvvy9U0Kax5RJdPLUaVqu6qQpcaKENGTgr6pe6TiodMkStGvPnzqaj/v2HyAIbqFChaJ6dWpR2jRprOJxgYkB/QBpg6s3KAOHQgULcLpPnz7RgkVLOC5u3Dj0S86f6fr1G9S0cUOORx4IUKhjgQL5CHXwK0FLtnT5SrqrtD7VqlSmPX/tpUYN6hHadrBaXY8d9RuzhMaoY5du1K93L4KwrdsVkdAwLVf3iWPGDOmpccP6fM/murx+/YaGDB/BbYx2N5MzDNCmBfLlpW1/7CAI4xUrlKeC+fNxduCzcPES2rvvAAGfWLFimtlanT9+/IQWLF7M7ZgzRw5CXk2HDh+hmDFjUgL1zKK8n3Nkp81qkZA3d26KETOGVd/p07M7QevQpVMHfl7BA4LqpUuXqU2rFpolH9Hnjx49Tp8/f6IDfx+iOTOn06tXr7m9jx47xouXJqot48SOzelPnzlLC1V7Q3DCs4D2wDPuDAPz82B+VuyNI3fv3+N2tdcP9x04QI+UcNe1c0dl7gpJPbp1Ze0nwvPlyW11X3IhCHxtBHzOqF+7Rt9Y+d3Ug/5UCRMzZs3xUXOssNt06MiTdqmSxdkE0rRFax6AUyRPRkmTJOE8GIwxUWAi6tG7L6VMkYLyq8EaJp3fV3mbkCC8XLl8VQktpXhAbNepixoUP/NK3lE5zupgrvC169cJdcuaJYuVcGJO4+j8jRIMjhw9xtG3bt4mmKMgtOTLm5s8Zs6mOg0aUzwllCVJkpjvD74AoIlTptJ8paEooCaiJIkTU+t2HenylSscN27iJJozbwHlVYNmjBjRqW2HTnTq9BmO+2vvPnqmJjFNfx88SPfu31f19ompTuPbsVLF8pQyZQofyVA3CCcQ8iC8wKSXx0vA0olnzJ7DwgZU67gHTMS2BK3L4qXLqGjhQpQ9W1ZlahhsmPeGjRipzBCrqGiRQhQpYkSCWeLY8ePMAvfas08/1VcSU5YsmVhjB2HGL3Tr9m1q0bqdEgJDU8kSxWnKNA/asXMX35O57cDz06fP3Jb/vP+HzHEwXTZp3pK1SyWKF6U/duykvv2tzSxI36xlK86H+7QlZxjgPn8bPZa1kfHjx2MTzvUbN5jFiFGjacVKb3wWL1lmy5qvIcC3bNuOzp27QBXKllXtdYqOnzhppD1x8hRpcwbKg/YTwmB61b62fSdq1Kj0WPXhTZu3GPlnzZmr/KwiGdf6BH0eAtStW3eoWtXKSnv6L5tOsCgpW6Y0PVca1UZNWyjT4DsluLxSbdGWYseJRRXKl6NFi5caZmJnGDh6VmzrjXHk7p17LJjBpAUTLhY1WlCD4ItFFYQTUJgw/+OFE8KFBIGghkCAalCC2s0GRH1g3hgysL8akLpQnty/WA1g585foBs3btLGtatYtYyVb9UatXkFXk4NXFhBw8SjVy5z5y+k5k0bU/WqFrMYVuRY9WLyBGFw/G34ENbUFMifl0qXr0RXrlyld//847CcZEmTOoxDHUAw2XTpPp1X/7VrVucw//xFVVqdHl27MIsjR45RyFAhebWOgI2btvAEiIlhmbo3rDaTJ0vGae/cuUvrN2yitq1bst/AxHGjDY3Ka7UiXbJsOaVL61M7wZnVHzRTtpjqOBwhQEAwqKu0L6l+/MEc5et5wybNCOYwrMAhUJpp8K/9eWWfP28eKlm2Al27fo1+SJnSnITbtU6tmixsQUBbofwiIHAlTpSIV+bTp0xUE0UqzgMc3rx9w+cQ9mrVqK60FQ34OrZahcMUZdtOzu5t0+atPAnpNgGG9Rs1taqfbxfQ6iVXGqv+fXpx0hzZstEh1Xc14Z4aN2vJ2o2Rw4dSiBAhdJRxRN+2h4Fu/2ZNGlHZ0qVYW/bX3v106tQZ1j6gz0ydNMHQ2kHgwmRvS2fOnlXavac0b9YMNfGGURrIIk59hDq0a8PaPc3Htu+UU1q7xUuXM/Y3b90imE5KKQHPHqHPD1VmQBDaFf5JG9asYrNJyeLFuF9AiIeQDoK2CNrCrFkyU4Tw4TkMf/YwSJQwocNnpX3b1j76fOzYsSh71qyUVy0Q0C8mTZlGT596Uu8e3ejuvbv0o40gHl1pKBEuJAgENQREQHFDi2TOlIkqlCvLph6tKgfb8xcuqJVvEsPuDbMHVuPnzp0nLRyYiz977hzhB3MICKse80CfMkVyw4wEwQiq7ouX1Zt21crVUTkYoBzF6TqMnWB5w6+tSt5cN7+cQ12uKUKE8BTRtOqEhgCTCwZ8EFaWmnC/GLB1XLq0aXUUZc6UkaZ6zDSuv+QEviVYRd9Rn0Twq4CyYukidqIEVi1ataVF8+cYVYDZARRR3Vvo0KEJZg5bun37Do2fNFm173meNBD//p/36l5vc9Iff/AWmFKnTqUE16McDo2SNvUgIJMyrbx+/Zq1H+ZdU87u7eKlS5Q+ncVEBR4QWv1K6Msw62jCPUOY0KSdxVs0a2LVZ3U8jo4w0GkSKM2Jpvjx4rKQpvsCzKOa0qZJbeCjw3C8qMwvmMwhnIAg4CdJnIjP7f3FjhXLXrARVqxIERo/cTJruqAxQrnQ5tkjc58HVhDYipTwxgd9G4IVzKBYgEDThgUHFi0wC2rfGGcY2HtW7NUFZiNtRkV8LCVUQzPbs1sXihkjBsHEZKbrN28qMxc+ziokCAQtBERAcVN7wC791779NHLMWINjLDUAwl/DTI/VdaaMGc1BxjlW57WqV6MiJvW4WUCBytlMz549Jwyy8L1wVI4rdYBwhYkQWqC5avUZGNswY0S3DPRzZ3oQ1OmaQocOxWYGXHt6PqPo0aNxFExGsb18D4DJS6Uq1+SpcHCFIqsJYcOa311JaqSB2h3aEAiD+DVr3Ihq129IL19aHC+NhL6cdOnRk1fM82bPYGfieg2bcA44GYNgooIGCAQNiibcP+5dEzQEuH8IfmZydm/oI/A70PTCVHet6ofpAULvUweO2ODxQO060wTT4j9KcweTAghO4kUKF6Q+/QfQwnmzjXvR6XF0hIF3mmDep+oMphJMqCBoALRw8OiRNx4c6fUH7ZLP5+CpOYmfziEAQmDeqMw8EFBaNmvqUn48c8BlxZJFVunDhbNg1apFM6pftw4dPnpUmZnGs8AObY6FfGLg7FmxKsDrAv5GcI7VQjjyQ0DCD6ZUaO/Qflgw4Qgtb2LlzyYkCAQ1BMQHxU0tgtXa8CGDDD8JsM2QLi1hMoBpAn4JmOyOHjvOznmIh2oXqyo4BYJg6oGfAuz/4cOHo8lTpymn1ckch78bN2/RduVECF5z5s3nlTjMAs7KcRanGcPfBXWHrXyocnAMDMJkCAdU2PW1QATnTPhG4N6h9RmpfBKgjcAqGuYv+KOAsCpeuGgxhwMv7Jqify21tsXUEvrl/2i73v3688SNuixQ5WLlC22JXwhtBhMJdjpB1Q+fHxAmMqzM4WcCZ8uVq1azoyhHqr88amU7dboHa2/QT0arCQ2aDHsO2TqP7REOxHA+hekBW6THT5hkJIHTMwi+QjBhwPcHBOHATFiRo23gV4E4aIPq1G9kJEHbNKhXl7IobWK7Dp25HCPS68QRBrbpzNfoJ/CZGDN+AmsloA2Cs6o9Sqdw9Hz2jM0hKGvd+o1Wgpm9POYwe32nvBLesU0ZiwE8J65QeqX5g+Zy2/Y/uC9jUVK3YSN+1qHBq1i1BgslOZQvEhx2sU3YGTl7VpDPtt7wlWrVtr3S4F5U9X7GbQUNFMYoOAZDKJk8dToL2XPnL2CtH8KFBIGghoAIKG5sEZhgsDNCE3bYwB4PP4KCRYuzlz52BeiVjR7w4EuCyQG7Z35UvhEVq1QnvKMATrOVTP4OqX/6SQ3UE5nXIuUoCKECk7mzcpzF6XriiAl33OjfeCJbs269OcrqHDtQbEnvMrINd3St049RO0ewc6hoyTK8kwCaAUzIoFG/DVMD+i31/pGyVFc52WJHR41qVTmubetWKt81qlW3Ab+DBeaGYF71ssWUM/jjr0/PHmo3yycqV6kq1+WEcrzU28L1fbjCHho2CAF5CxbhfgCfBfKCcuTwYSyQDRo8jLZu+4PKlC5psMSqHe1eqVoN9jnCxDuwf18j3pUTCBc1qlWhNu07stkBky2wBkHQgc8P2rxGnXrGVvHgagVuvj9MYPCD6dytB9/D5i3baOCvPusxaEA/3v0zcMhQH1VzhoFtYr09FuGjRgxV7+q5wP0Ejtw5smezqpvOi91egwb0Jzgt43mbOWeOl+Ozzz6r85iP9vpOLuUrBawQB/OdKxQ1quW5nzV3Hj/H9Ro25p1CELph4sXzX75yVdUWpZXvx332T7LH14yBs2fFtt4VlfNtbmVKglNzmQqVeUfRMDVWgCDsDB00gHbs2s1+MeuUzxeuES4kCAQ1BAL8TbJB7Ya/Vn2wktFbgm3roNXrOhyTEMIw0NkSVq9YkWnVt228s3KcxdnyCcxr+NCAtB3eXDZwgE+BNkWY47BrA6tCe2SLqb00fgnDihgqcm3S8EtenRY7qmCqiKl8dMyTP7auIkz3jy7qPRW4Z7Mg4q7y4RsBYRQC8MRxY1h7g/rh3lAn3zQzWH0/f/7Cbt/U9+ns6AgDZ3l0HDRIqLtvdUR67KyLZjIdah6uHM19B+dYQEB411vgXeGh0+CZw/tztJZQh6PvwhfLr5o4354Vs6CBceTjxw8O+yw0gljgCAkCQRUBEVCCastIvb4bBKDZuHrtOu8ouaEcFg/8fZBGDBtMeI9HQJGtgBJQ5XzLfOH4i23AECJmz5j2Ld+K1F0Q+CYREAHlm2w2qfR/CQFoL+BXgd1deCMrzFzaDBhQ9wnfGryrBGYRIfsI/KleZgefliKFCjrUQtjPKaGCgCDgDgREQHEHisJDEBAEBAFBQBAQBNyKgDjJuhVOYSYICAKCgCAgCAgC7kBABBR3oCg8BAFBQBAQBAQBQcCtCIiA4lY4hZkgIAgIAoKAICAIuAMBEVDcgaLwEAQEAUFAEBAEBAG3IiACilvhFGaCgCAgCAgCgoAg4A4EREBxB4rCQxAQBAQBQUAQEATcioAIKG6FU5gJAoKAICAICAKCgDsQEAHFHSgKD0FAEBAEBAFBQBBwKwIioLgVTmEmCAgCgoAgIAgIAu5AQAQUd6AoPAQBQUAQEAQEAUHArQiIgOJWOIWZICAICAKCgCAgCLgDARFQ3IGi8BAEBAFBQBAQBAQBtyIgAopb4RRmgoAgIAgIAoKAIOAOBERAcQeKwkMQEAQEAUFAEBAE3IqACChuhVOYCQKCgCAgCAgCgoA7EBABxR0oCg9BQBAQBAQBQUAQcCsCIqC4FU5hJggIAoKAICAICALuQEAEFHegKDwEAUFAEBAEBAFBwK0IiIDiVjiFmSAgCAgCgoAgIAi4AwERUNyBovAQBAQBQUAQEAQEAbciIAKKW+EUZoKAICAICAKCgCDgDgREQHEHisJDEBAEBAFBQBAQBNyKgAgoboVTmAkCgoAgIAgIAoKAOxAQAcUdKAoPQUAQEAQEAUFAEHArAiKguBVOYSYICAKCgCAgCAgC7kBABBR3oCg8BAFBQBAQBAQBQcCtCIiA4lY4hZkgIAgIAoKAICAIuAMBEVDcgaLwEAQEAUFAEBAEBAG3IiACilvhFGaCgCAgCAgCgoAg4A4EREBxB4rCQxAQBAQBQUAQEATcioAIKG6FU5gJAoKAICAICAKCgDsQEAHFHSgKD0FAEBAEBAFBQBBwKwIioLgVTmEmCAgCgoAgIAgIAu5AQAQUd6AoPAQBQUAQEAQEAUHArQiIgOJWOIWZICAICAKCgCAgCLgDARFQ3IGi8BAEBAFBQBAQBAQBtyIgAopb4RRmgoAgIAgIAoKAIOAOBEK6g4nwEAQEAUHge0Dg48dPdOz4MatbzZA+PYUOHdoqTC4EAUHA/wgE+1eR/9kIB2cIvH79hnbt2kU//5yDokeP7iypxAUgAg8fPqQjR47Sx48fKUeO7BQrVqwALE1Y/xcRePr0KWXJmsPq1lauWEaZM2eyCvsWLk6fPkPPnz+nXLl+cVhdxD9+/MSIDxkyJCVOnMi4/q+c3L//gI4dO0YFCxag//3vf/+V2/rm70M0KP5owsJFihGEDzPh4c2ePRu1aN6MwoYNy1F9+/Wn339fRT/++CNt3rTenNyl80WLltCEiZModeqfaOaM6Uaez58/0/IVK2nnjl30519/0adPnyhZsqTUqGEDqlixAgULFozTXrx0ierVa8jnG9avoWjRohk89Ik5jQ4zH+vUqUUtWzSnpcuW09ix481RVudz586iH1Km5LBp0zxozdq1dPHiJYoZMyb9rISCPn162S0fGR48eEg/58zFeePFi0d7/9rN5+7427p1GzVr3tJgNWTwQKpRo7px/T2edOrclfbt209169bm/mqLgb22jh49GmXNmpXKlS1DmTJltM3i7+tu3XrQnj//oiKFC9GAAf2t+J09e44aNW7KYTv+2Go8X1aJAvGiSuVKXIc4cWJzqXj+Jk6cTNu2b6fz5y9QpEgRKW3atNSmdSvKli2rn2qmsU+V6keaPWuGn/K6khgTcpmy5TnpvLmzKU+e3HazrVj5Ow0aNMSIixgxIp08cdS4/tKT4SN+o9Wr11LkyJFp08Z1xlil+W3btp369vuVLxcumKvGtWQ6KkCOFSpWpvv371OTxo2oZ8/uAVKGI6YYx2vXqUf79x+gOHHikMf0qarfpHGU/LsKDzICyud/P9Ph6ydo8+lddPL2OXr48jE9fmGR3GNEik6xIsagdAlSUYm0BShL4gwUIvjXd5+5fv0GCwXmHoNO/vffB2nt2vX84EFIyZolMwso2f04SGm+jx8/5ofHVrJv36ETrVtnLfCcO3eeOnfpRus3bKRZMz34wX/37h3nB78PHz5qtlZHcxqrCK+LW7du89mTJ08MXvbSgQ8Ikx+EMk3AZfWatbR7zx4lpG2wq73o0rWbTk537941zt1xMmTocGYDDVbevHkof4H87mDLPE6cOEnlK1Ti8wvnz/hJ3e+fvP69gevXr3NbYrKyR/baGu145sxZmjt3Hk2fNoWKFClsL+sXh924eZPrNH/BQp40zfxfv35t9D0M6n6hpMksQvMMj2lUqFBBv2R1mLZ7966GsA3TT0U1yZ06fdpI7+n5jP5UwhZ+Y8aMovLlyhpxvp1o7EOFCpghOlq0qDwZvnjxghImSsjVsdcXU6lFValSJQnP/8mTJ32rtsvxmTJmpKlTp3N7Hjx4iDWa5syLFi/hOAhESZMmNUcFyHkOtajEmJk2XdoA4e+M6azZc1g4QRo8X2/fvnWW/LuKC5je7wcI//n4D838cwnN+HMRPX311G7Om4/f0M3Ht+jwtWM0+8/FFC1CNGqcpyY1ylOd/hfy66vjevfuSaVKliSofxcsXESL1cN148YN2n/gbyqoJkKs1KtXr+ZjlaBvFlY2rL6gPjUTwrUWxByOc6xqtHBSpkxpqla1CkVUK7bZs+awILBr126aN2++0pzUtc3q6/WK5UspRowYVukiRYpkdY2BY93a1VZhuIgXLy7joIWT/v36UK1atejsubNUtWoNwqC9Zu06XqmYM2/espUHcnOYO8/RHqABv/ajkiVL+GCNCS+4L0Kvs/bQDNGOX0rO8rpSNsr17T58i7dXd7T1xg1r6aO6t0tKG9a7T196+PARC6H2VtOulOFKmjZt2ysNz58ULWpUe9XyEeYKTx+ZvAJcxddR/v379xvCCTQ/ZUqXomvXrlP37j0J2snffvObgGKvHFfvz1462/uDz8x+ha0j0n0R5h/8/vhjBzVu0sxRcj+Hw5QSIkQIHvdWrVptJaD8888/xlhg1gTrQuzdn44zHz98+EChQoUyB5EtDjpy7NjRLEQ6Gm9dLdMRf12O7fGeEkiGDRthGyzXXgh8VTXEhpN/UN7hFWnEpokOhRN7LQVBBnmQFzy+NkVRakqoeWGCGagGJzx4oKtXr/IRg9NPqdNR8+at+BorqlQ/paW8+QqwEJE2XUbKnCU7x2GViIE5TdoMlPKHn1il/fLlS47Tf3hY5qgVLKi0GgjHjxvDg0j6dOn4Icv1i8WmvHjJMp3FT8cECRKwnRnmKv2LGjWKFQ8McDrOfMSAcOHCRfa1SZ48GQtIIUOGINQNgxIIKyYzwUzWqVMXDipRvJg5yt/nUJsCa02tWrfl61evXnHQ0qXLKFfufJQ8xY+EVXbxEqWN1YzOs3r1GqVxKUzJkv/AedGOB5TwCYIQqLUnuE6XPhPVrl2PNUBoQ5QN4UtT2bIVOKxHz94O8+q0J0+d4vYHD5QNk+Levft0NA/iiEM4ykAdcR/oV5hQzHT+/HmqWasO/fBjai5/5MjR5min52hr9IkkiROzxmTkb5YBFf3y3r17nBd9cvSYsVwX1AH3jntEf9YELcPQYcMpx8+/cD1xxAR++/ZtncTqiImqffuOVmH2LtYqLWKVKtX53lKkTMX437hxk5NeuHCB71fnwyQLzDCRgJy1rc7jynHPHstkD2GuTu1aFCVKFDaBTZw4nhcP0NrB90k/+5mzZLNiW79BI67XRGXKtaUZM2cxnsC1UuWqdPjIESOJ5oc+gEWBxrZqtRr07Nkzmjd/AeX8JQ+PJS1btaHLl69wXmALHPADRo76sVGQm0+wGIMQB1q3foPRHrhG39UCEhZeoKeentS1a3fj/rJm+5lmqcUY+h3IfD/Q1OKe0de15te3doaJB2M0NIOabMssVqwkjR8/0aquyAcMVypTGEzI4IHrli1bc500L0dHjHu4V4zZet5wlPZ7DLdesgcSAjDnDN80mabtmmtVYtKYialw6ryUP1VOShA1LsWMYHEoffTqCd32vEe7zu+n7Wf30LVHltXwg+cPqdWC7nQyfz3qVqIlBQ/2VeUtvpdNmzYbD5cWFF6pQRoPENS2oPfv3/M1Hp5+/QdwGAY2dFTYIo8fP8Fh6LA7duykHbSTr/XfpcuXjTK6dumsg43j8OFDCPb6cOHCGWGBeZIz5890+NABqyIxkECFDEqRIrlV3IABA+nNmzdK4ElMzZo1pU2bt1jF++cCWpFw4cJaDRa4Rn0wwA0cNJjZA3/UAYM1JnL4OEC1jPbs0NGCMcxDIUIEpy1bt9Ku3bt5dR8ihPUjhIE3VOhQSpMUj8oplT60af369WefCgzE2gTQpnVL2rlzt9Wt6bwIvHLlKmuc0G/QD9CWCEP/WDB/Lgukuh/B1NiihUX4RV70K0zEf2zfwrZ7+PZUqlyN7w/xoEmTp1hOvuBfTwrIGszrmevRoxctW76CuUGYhaZsyZKlqs1PKO3LOg7v07cfh+ECbQ11NnwtTp85Q+vXreE0+i9hwgR8H5iAwbdqlco6yuoI4aRduw4cBoyA1959+6hY8ZK0b+8er3Cf7Y8I39rWVc0NeCVJkgQHgtAGEyt80CCgp0yZQq2Qh3Ac/nSboZ5mAl4Ie/bsuTmYMRg8eKgRdvToMaWNrUXbtm7i/qn5oW/ArKrp0KHDVKp0OStTKe4XJh30H7ShrsO7d+hj9vux5hcQx6pK+IAwgecOQlc25dsEWullGoY/xk8/peL4yqr/Xrt2jePRvzCW4tl98PAB9ejezep+OijTtya44bnSzhp/vRjEoqlixSqsCQcvmNehCbs4dhzdf/CA4MMG0vl69e5r4IlwjGHB1XM7ccI4XNqlDcqkhAUUnu+RI0dQ7jz57Kb7ngMDfUaHcNJqYU8r4SRRjIQ0sdZQ2tF5OfUq1ZZyJc9GiaMloHChw/IP5whD3M4uKzgt8miCoAOe4P01qJtaBabPkJmweoP2A515klo54eHyjWDfPXL4b57Q4bCohROYRi5dPEcwt9jS4UOWFRQ6NgZyW4ofPz6vdKGa/RLKl78gr9iwCtY/DIBmwgCh4/TRPDCY0+Icakz4laDODRvUN6Ix4OqJbfKkCRQsuBpRXCCsFLGKMv8wIdoSduscPeKtsYFDIK5hsoK/Axx6u3btzI5/Z06fcA6HawAAQABJREFU4PqBx46du5jVho2b+Ii2hNB1YP9egnNkxowZuK1q1apBq1et5DT4O3b0kOHU2LNHN+4LMIfMmjVbOX1aBrX27dqyAOMsb+cuXXnAg/Pi+XNnCHWrW7cOl9OjZy+jPJxAsG3cqCH3F7NDJSZ30MyZswzhBHW9eOEs9erVg+Nc+UNbQ5tz7NhxXil26GiZADBRQHOIyUW34bJlixnfPbt38r3DJ0prkLZssQieTZo0pl07t3O/x+4XOG3balEyZ8pESAfqqTQx9nySoJHRwkn3bl0ZI+AEZ3RMvqNGj+Fzc/vDBwXXUOX71rauYKPTVKtWhfsErrGahkYDz0VHtUKG0Osfatq0MV2+dJ62b9vC/RPtjZW8LXXr2oXbVmsdgBmetbNnThJ4gKCBs3XsR7izvoh4VwjaB/PziHNo8xwRdjXqRdSqVRYBFQLX7t0WwbJKlUqcddp0DxZOsEA4dHA/tx/8n0DTp89gkzJfeP1hTIRwDn8waP6+pJ2nTZ/OwgnGq61bNqln8LQhlGDRoRdbulykw6LmyJGDhrlq+3bH2n1ocLsqh3BQDzVOaEdrzU+OFgQCXUCB5mSTySxTJmMx2tZxMZXOUNihv4VtYyEt8iCvJvAE769BEEjChg3DXvsoH4PjQOUjgm2tvtHgQQN4gIYaHatNUKxYMdk0gkE0i3KwhRBjprfvLE5UWHEHBKH+WNWYf+ZVsy7THI/zBw7uF6t1jxkzOduY0SN5Rw8uMMFAoAPBVwYmMlcJkz4mTvNPr35c5fFr/760ceM6yp8vH/vFTJjgrV6/e+cus9E7VTDRoq7QgnTu3JGWLF7I/kXOyooQIQKhDBCcdLHawiDbqlULZ9lYhawF1UQJE9KKFStY8xDda/cVNCQwF5ipffu27MOUP38+w6kQKz4QBAtQpUoVKUOG9OxrA4HG1mzHiRz8lStXkSpWqsLaAdwHBuRxY8dwarPJ7srlK1zXvXv3shCGBNi+CcKOFhDMCfChOnjoEM2bO0f9ZvNEwpGmP2gHoWnBhAyzmm0fhF+TJuyYgYAKfwaYokD6vnUa26N/2taWF57FVb+voEUL5xuCCp4J1AdmQ5gSv4SAMwQPHKGRady4IbM55qVlNfNs2LA++1zUqVPbCG7WrAnvNKrnJdwi4tatm0a8O08ePXps9Tzi2bx712ICtFcOxrfKqk+C1ihNCsxuWBigvUFVKlu0Zth0AILmE5M+2hm8gQnonDJfmqlnzx6sOcSYCvqSdtYmXGh5oAUDwZcQYzMIfddMldSuSWhcoXVr2rQJR2EcNZs4zemhOUf/QJuaF2zmNHJOFDAznANk4S9iNuu0LNiAuhZv6SC182A4x06oOYgSRItHU3bM5sTgnT7BT1QqfSHnmd0cC8dLDP4gOD2VKVOe1dewwZu3BdsrFtvsNJ1XvhsgDMpmSpo0ifnSUIXiAYAQZPs+D0z8iAuutBF6q7MVA18utm3d7EOix2RrJkxuWCWbSQ8Y5jCs9MYotSho8KCBCpvSRvSkSZN5ZQwBr2mTRmxnfvrE21EaNuAI4cPb3RWD1ZEt2TrE2cbbXkP1C3U8Bgpb0s5y0JZgRQdtxHolnOAHKlGiOA0dMoi3SdrmNV9jgMNghPYAtW3b2ocztDk9zu/cuWMELVy02Dg3n9zxEqB0WHiFkyasxqAO//z5Xw66cvUKH5MmTcJH/ZcwYSIWmvS1s2OaNKl5945O06VzJ2Nr6ulTp3Uw+50YF14nN65bJkRoOW7evMUr05lKo4Qf+gzMIZ06dbDNpnAKwVsuixYrwaaxKVOnWaU5q3YTaerZq48+NY63b3vjaASaTvzbtiZWxinMmxBUsBMDjuqDlHkGmozuygRm7vtGBl9OsD0fZkpNerutrcYJ8XpCholRk35uw3i98kCHB8SxQ4d23L/NvM11N4fr8yrKdAc/GTyD0KZCoANh4tbaYZirQRDMMaba0vVrNwgaN01xlWnITF/SzufPX2AWqIeZIIRgcXTmtPX4owUXpI0dK5aRRQtbRoA6OXT4sLHD8Vc1d3gqXyGQTvtEbbaAlit8+HAc/j3/BZqAgt06A9Z5O+ZB+/Glwom5wbopAef207u07vgWDkYZhVPn/mq7e/BwlClTiubMmUewA/uFkiZNwsltJ5/b6sE0EyYLTYsXL1Vq7jb6ko89lQkA70fBQ/P3AW+nSqtETi7gj6EHNkfJggcP4WuaUaPG0EQlhIBgUqhZs7oVu41e5hNM3nBUtaUsynEY5hDb+0M6PRjb5nH1GqpkOA2CYAqrq1ad0OC0bNnG8BNBHExBWOFfVpoB+J3AJwh2Ywg3SN+6lXMBGz4SWjgBP7wbplbNGsbqD2G2BNu7Jti606RNoy+NY9y4cVSdLhvXzk60IGI7YZsFIWf5ofXRPiIFCxVl4QeTShMlVGIC0pMm+s2CBXN9sIoaJSqHAS+YdrAi3qd2vaxZs46FFfSRwoULsXbHNjNWrzCVQQOlVf86DSYLTTBd2ZoHQ4X0nqh1OvPRv21r5gXn31tK+IK2Ez8sDCDE4r1E0KCA4DyuBV9cY3WtBUtH2tZHjx4hqUFaMIkdO7YRFlROIGzaW6Q4q19a1bcxTmHSX6b8kbRzN3Y9aoJGDL5bxYoWVc9scx1sHBMok7Yz+pJ21mVqvDV/bWpMnjy5DvLzcctmb6d5ONTbEvzJYEKGoPu9k7doHsBIYCsxnFpB8B8ZWdXniudLqwBe2icFZaCsr0HQXEDdDXUlKJHX+wVcrUvGDBk4KR4CvFgMhFUDzApmChkypLEjZuy48bwSxRZnbKvDqhTCCahqlSrmbIF6jgFbCydQUcOkYEsJlK0Yk5/5Z06D8GjqxWABQVjJaxo2dDAVLVqEJ5Wz5yyrNR0HUwR2iGBCxT1Aha99i7Rpwzwxoh00YQKC/wSofv267JOBtvXwmKmTWE2qOi/aV6/cDh0+wjugsAsKgg7qs2D+Qj9NBBjsQMuVs6keYOGgBzW5X2nQoF85C/iAHyhr1ix8xCo4fLjwXN90ypwzb94CGjduAl1SpibY3GGmKVe+EoUJE4Y6tG9HWzZ792vzzhRmZvprrF6eBX62lD59OiPo2vXrBk5HDh+lESNGkt5Zg0R64nxsumdX2tYowJcTz6ee7BgJR2C9ew8rYghymn74ISUlSZJYX9LUadPZzAlhFw7D9gg89M4SmNZmzpzNyTKY7t1evi8Jc9SPv4SXX/JoUw78mLQWoUL5cgYL/ZK788qXJ4USDPAswPQ5ZMgwfpfKC5tdjkZGr5MvaWf4roGwANTPJbSoGI9Buk584cc/vMLBPObpczObxIkSmS+/2/NA0aDAedVjz0ID5K7FWvpLw/H09TOa9dcS6li0Ke/cgbkHPFsv7MFloKxm+eoE2svcYCaAo6x+uPSN+tW2mDt3Ljbv4J0d2LKmVxaan/kIh1JscYNvBB5A/MyECQ7mBFvCm1r1YK3jli1dTCFDeXcFe2kqViivBv1hOovTIx5kOK9pGjlqNOGnCas/vCXWnvkLr6KvXMWyerLdCaTzu+OIlS1wQJtVUe9nga8PJjTbNgSOEPowgcK8g0kYmIPwNlVQyhQp+Ii/QoWLcfjw4UPVqn8Yp4c5rGeP7uyQC1MEsCivBmCYYhzl7dO7F2HrKVTe0NhgK7e2xcdQgpttGxoVsHNSr25tWrhwEd8bNFXO+pWd7FZBv+TMya91hzp+sJogcB/ot9ppGLtn8BKu28pMpSddvD1Ya+Twsq9q1Wvy25YvXfLWABUvVtSqHPMFtA7Tpk2mPHkLWLUPtBR4u/HkKVMJDtrTlTMlNDp4kRyotMl3C8IB2g3bmj08ZrDDqStta66Hs3P4J2BhACECfQDaJLNPVMEC+VlbAq2PjsNbZ/ED6b5or4z+vw6kceMnWJnjsNvN3eSoL7q7HFt+lZUzrHlXGRynMWlrgt8NsMW4mC17Tta0of9BYMezlSB+ArU4e6+T+zh+STtDKMYOM7Rh9hy/sI8Uygdhd6Z/BJTmzZsqYd1n++mXCWI89g9/HwB8wwGBokHBG2I9X3syTNhK7B8fEQgn1ae3oIl/zKQOS/oZO3fAE7xBKOvIjRN8Hlh/emKDVzoesGlTJ/Pr5v1SPnwxli5ZZKwWofbEw9WoYQNmg8FXE9IuX7aEzQXY0qoJ4Xhd89o1q3y8pEinQV3NP/1OCB2Pozke59DOuEr6HSM6vS0vs8lDp9FHswpchwXEEVh6eExlrQYmUmgUoPGy/aYKJh5oP2B2gckOkx/aGLustN8RJkpsJcUkg3v7Q5mB4KCKTxSAhgwZzG0BtTUmKODRq7dFg2gvL/Lky5eXpkyZxAIr6gfhBPyx3RZbEp2RuZ8gHUww+ASB7ifoVzA/wF8C5FfMBw6waFEweEN4g8Zn4YJ5rILHOYQ51BmYLV60wHBaHTJkIKfBfUCINafBzjNnFDduXBpu2q6r03bp0onatGnFExoEELQPngG0j9lMgPbRTsHYkYat1660rS7H3nGVej8OVv3wlYIjJl7Zrj/zoIUTCCN4Hqer15eDgPVytdNJm/FQ16ZNG7OQZ68M8INJEIIPCMIlFidwdnaF/NK2jvqiK+X4Jw3MKXguNFWrVlWf8hFtv3rVCkqvPsqI5wsCO454VvGySPgqOaMvaefYsWOpt4GvYsEbzyuEE7QV3js1a5aH0wVCCPUqAv+QWZPlHz7/hbyB8rHAAevG0Kw/FzFeTZRmA9uFv4S0cHLxnmXlFULt3V/Z0oMyJrSofwdvGE8eu+cz64Z5alLfMj4d776k3K+RB05S8JPQg6pvdcAgqdzgjVdv+5Ze4r0RgLkCg4951eYd632GTw5g8rf3LSOkgqCHiQ9tBn5+IWd50Rc8PZ8SJnG/TDj2ykc/CaPqBiEroAhqcGDkzMkPtv2oUZ2n8Wv90D4gqNAdEdT1EKLgl2Am39pWp0V+3z4WiN1GwAD9wLYczQdHfIgP8a60KSZkpLd1iDfzc9e5uS8Cl/PnL7ADKzRVELjsvT3YXWX7xgdm9Nt3biutSXxuR9/S28a72s7mfNgxBx8hLeCb4+Q8YBEIFAGl8pSm/Jp63MrCZpP5nSZ+vS17wsmkmkOpeLr8Bqu9Vw5RrWkWp8WsSTPRihbTjTg5EQQEAUHAvwhAk4j3YJgJTrG+Cbfm9N/SOTRkZvPx1xZQviXspK7+R8Db8cD/vBxywIf/NOENsba09cxuKpAqF4WyeZuhTueKcIK0Zt7mMjUfOQoCgoAg4B8EsJVdvzDPP3y+lbzwOTL7skWOFPlbqbrU8z+AQKAIKPqrxMBLv75eYzdt9wIaumEcFUmTjybXHuZDSHFVOLHlbS5TlyVHQUAQEAQEAdcRwI41vWvN9VySUhBwDwKBIqA4qurRGydZOEH8NqVFaam+q2MWUvwinDgqI6DC8xQoHFCsha8gIAgIAoKAIEB/qvcGfc8UKAJKjEjR6ebjN4wzPvyHb+uAMidOT20LN6Hx2z342iykvHz3infrmB1ibX1OOJPpD7w1ocyApO+94wQktsJbEBAEBAFBQBAIFAElVsQYSkCxvBgLXyXWAgrgx7tMQGYhpfn8bnTL8y75RTgBD/DWhDKFBAFBQBAQBAQBQeDbRMB/G7ZdvGd8H0fTrvP79alxhJACTYqmP87u8bNwgrxm3uYyNV85CgKCgCAgCAgCgsC3gUCgCCjF0+Y30NiuhA97LwazFVKQAe858c2soxmDJ3hrMpepw+QoCAgCgoAgIAgIAt8GAoEioGRNkoGihrd8MOzaoxuErxrbI7OQ4hfhBLzAE7xBKCtL4gx8Ln+CgCAgCAgCgoAg8O0hECg+KMGDBacmeWvRiE0TGaERWyarbcV57H6PB0IK3taZKnYKq5ewOYMWX0oGT00oK4TptfA6XI6CgCAgCAgCgoAg8G0gEChvkgUUECLyDq9ofNG4TMZiNKHmILeg1GZRb1p3fAvzih05Fu3p9rtd4ccthQkTQUAQEAQEAUFAEAhwBALFxIO7wBeH+5bpaNwQBIoRm721HkaEH0+GKx5aOEFWlIGyhAQBQUAQEAQEAUHg20Ug0AQUQIQvDjfLX89Aa/KO2QTtB7QrfiXkQd4piocm8PbPl5I1HzkKAoKAICAICAKCwNdFINBMPPo2P//7mVot7EmbTI6yiWIkpK7FWrJw4cqXPdef2M4+J/rdKuBdQgk/k2oNIfi7CAkCgoAgIAgIAoLAt41AoAsogAtCyvBNk2narrlW6CWNmZgKp85L+VPl5A//6e/24A2xeAkb3nOCrcR6t47ODM1JtxItRTjRgMgxyCPw4sVLihQpYpCvpysV/Pz5M719+47Chw/nSnJJIwgIAoKASwh8FXUDtBw9SramSerjgHBq1QTBw2P3fKo1rSXlG1aBUvfOyz+cIwxxZuEEecEDvL6G5uTBg4fUrmNnKlSsJBUvXY4GDBqiBuq3+naC7HHg4KG08vfVfq7f9Rs3qHzlqn7O9/zFC+rVtz+VKleR3r3zNudt2rKVKlerSfkLF6PGzVrSnbt3Dd4169Snc+fPG9f/pZN3794pLCrQmnXrnd7W5q3bqEevvk7TuDPSL+27dv0G6vfrQC5+0tRpVKlaDYdVwTNx/MQJh/FBNcJevS9eukQNGjfjPlu1Zm36a+8+u9X/++Ahwve6/tix0268BAoCgoDvCHwVAUVXC/4i2HHTtURrihYhmg729Yi0yIO8X9PnpFmr1hQhQgSaNnkC9evdk46fPEWDhg73tf5fO8GTp0/p5auXfq7Ghw8f6cmTp37Kd/nKFapYpTrdUMLNCyWoEP3L+U+fOUtDho2gRg3r07zZMyhu3DjUoXNXg/eDhw95VW4E/IdOwoQJQyOHD6VCBfI7vavXr17Tg0cPnaZxZ6Rf2vfVq1f08NEjLr5G1ao0fIjjHXkQfNp38m5bd9Y5IHnZ1vvDhw/UtEVrypw5I82fM5MqVShPPXr3pefPn1tVA0L4ALUIAL16/doqTi4EAUHAdQQC5T0ozqqDHTctC9Sj5vnr0OHrJ2jz6V108vY5evjyMT1+Yfn4Hz78h2/rpEuQikqkLcAvYfva7znx9HzGk3W71q0oVqyYlCJ5cvpt2GC1UjzJt3vw8GE6dOgItWrRjK8xUS9esoz69OrB1/sP/E3rN27iSbtI4UJUtnQpDscbcVf8vor2/PkXhQsXjmpUq0IZM1heOgezwKIlS+nosWOUMEECatK4IcWJHZvzOYt7/PgJLVi8mE6eOk05c+SgT58+cR79p+vi6elJxYsVpTKlSpL2BcIKcOOmLfTp8ycqXKigzuLyEfXq3rUz/ZAiBdWu39DIFzJkSOrTszsVLVKYw2pWr8qDP8wFeA8O6Nr167RqzVqF8xMqXbIElSxRnMPNf5hUgcm+/QdUvmBUuWIFKlSwACfBfS5YtITjIAD9kvNnun79BjVVuIGuXrtOy1esJExEWbNkoVo1qlOYMH7bAWaLLYSPBPHjUYH8+ajfgEFUr3YtSpYsKZc3YdIUyvlzDlVWZtq4eQvFjBGDBVzddseOn6CECRNQ00YNuU9xJtPfZKWp+KTwadOyhSnUcvrHzl20VmlkXirBIZe6zwb16jKOCxcvUaakSKyNunz5Cpdfv24dP7cvsASvvfsOsDCJPq/p6vVr3NczpE/HaYDBSSWso40bNqintIxduM9B29iwfl3asm0798M8uXMxCzwbU6Z60DAl5IQK5T0kPXr8mEaMHE0FlSAHjV+nDm0p1Y8/Gs/H//73P6pTqwZlSJ+e+UB4nuYxg9szY4b0VKtmDYqs7t03DOz1/7v37vmod6KEiahRg/qqn1RjbKtVqUxTpnlwP8qU0fvFkFM9PChWzJgUPZrriy6NpRwFAUHAGwHLTOB9/dXOYKLJnjST2ibcgVa0mE57uv5OZwft5h/OEdZPbSFGmq8tnACkqFGjUNIkSahP/wF0+swZwsSaPFkyXlUh/tbN23RECRKaMNjuVZMoCJNp1x69KFnSpPRzjuw0eux4nogRN3HyVJo5ey7lz5uX4saJQ23ad+IBFxMEBnhMYmXLlCaYTRo1baFMJu+Mwd9eHFZ9Ldu2o3PnLlCFsmWVkHLKEKJ0XbAKTKkEiPz58nJdfl+1BlG0/Y8dNHDIMEqXLi1ly5qFxoybwOF++cucKSMVsSPYpPrxBxZOoEaHIDJ9xixK/dNPhnCCMqZ5zCQM/D+kTElDR4xknG3Lnjh5Ci1euoyKKiEve7as1H/gYLpy9SonG6byrFTCXtEihShSxIgE09ax48c57v6DB9SkeUt6q/ArVrQIbVP32q1nL1v2Tq/tYTt9xky6cfMm54P6/5lpdf33wYN07/59qzjdrjAJQAh7pLQSdRs25v5kLhz3snnLNqpZrZo52ODVXwlDadOkYR5Ll6+kFStXcdwJJSiMGjNOTZbRWUCbO3+h0df80r4jRo1mnhpLCNuazH0d5Y0dP5Fix47F7QsBQQvfFZXGIUH8BPS/0P+j+QsX6ey0eu161Q5vrYQTRL5584YO/H2QBfsypUtS7FixaOKUqTR/wSIWAJMkTkyt23UkCDigdh07Mb41qlVVAtkF1tAh3BkGeBbt9X979cYzD4Ho06fPXI7HTMsOwjSpvb81dkkJgavXrKP+ff3Wl1BPIUFAELBGwHu5Yh0uVy4gMHbUCMIg1aJ1OwodOjRPxC2bN/PV+RGTRL06tdRqrB6Xgonlzds3PCktUyv6iePGqFVhOo5LkyY1fVYD4tlz59lHY8OaVTyQlyxejEqWrUBHjh7jFTL8N+zFwXERK8t5s2Yo7UAYpSEpwr4g+vZQl+ZNG1P1qlU4KFSoUIQJrlLF8rRk2QrCart+3docFyJECJo0ZZrOanWcPG06JUqYkCdIqwhfLsZNmEQbNm1W310KQVMnWQtArVs2Nya3A2oCP37iFE/CZpaoe51aNSlGjOjs/7NCrbRPnT5DiRMlIvhwTJ8ykX5KlYqz3Llzl3HGxYaNm1nA7N/HMpHkyZWL/WuAY/x48cxFkKN7O3P2rFNsrZg4uEC7QkDbtG41hQ0blttn9dp19EqZd0D/fv6Xhv82iv5Uws7cmR4UPbrPVTk0Q0sWzuN6f/z4kSDsHD95kqpWqcQ8cv2S0+hr15TW6Oix41SxfDmX2xdCFLRoaB89Gd+6fZuFYy7A5g8CKZ4DTYUK5metR748uTmoXNnSfP1UmRqjRo1KW5VGpUunDjq5j+Po34Zz+2IRsEz1zTkzp/NiAAnRpus3bKL2bVvTY9XPC+TPT/ny5lGaop/VN78+G7wcYeCs/9vWWzP7c+9ew/8G5eLZB6F+WLDUrF6N+59OL0dBQBD4MgREQPky3DhXNKXC7dalE3Vs35YnhfGTJlPnbt3VpDjJKVes+Jo0amCk0cIITA2gtEoo0aS1D8tX/s4TcJESFlMQ4jFxYKLA5A5NhL04mEsgOEA4AUEASZI4EZ/j7+y5c/ybOn0Gh4En+IEwcbZs7v2VaWg4HNEpZT568/qNnwUUmH9gBlu3YSNrNDauXUURlbYDBFOJpoQJ4qsVtWXS1mE43r59h4A7Jvr3799z1Pt/3tPNW7f5/McffuAj/lKnTkWHjxzlazjgwpdAEyb+qFGi0IWLl3wIKI7u7eKly06x1bydHc9fuECJVXtAOAGhfapUqmhkQV/BD9otCGH2CGYdCMqHDh9hkyHaL0umTEbSBPHjG+eJEiWks2ctzseutu/NW7c4/0+pfjT4oI9qLI1Ar5NYStPhjKD5iK/qtHX7H4T2QbvlV0KFI9L3resBzaEm9FeYzECdO7RjTRtMfrmVUNa0SSOK74WrIwyc9X9dhu2xoDLfgT/uv2effqzphJC4dPkKJbS9ZTOWbR65FgQEAb8jIAKK3zHjHFhpn1D+JvCLwKSSO9cvamKNwCpnrKRChAxBL56/MLibnUsxGT5UTqCasOr9+PETxYhumYCwsoypbNggDN4QMjDoYxJbscRbNY74cOHCsunIWRx8OMyElaYmlFNLrfjgB6NJCyiYsB88tDhCIg5mKkc0ZeJ4R1F2w+EkGzp0KDbfQCDBqhOmLWiEMBlbKJjdvObALj16sg8CHG3jxY1L9RpaBKq4cSy+OTCpaI0IVtua4LvzRPnmaILvz4uXL9mMoMP00dG9xQYPJ9gCRwgPmjyfWTtTIhztCj8WM0HYhH+FpmGDB1L3Xn1o1+49Jmx0LNEkZRY8f+EijRk5nM2GEDahKdGk/Yn0Nbb5g1xtX/jKgJ4+9TSEpEePHPcFTuzLX3mlRYFW5vKVq+wsjGfIN9LPBzRJ0LxoQj8CwUcqnzKNQujwmDmLOnXtQUsWzOU4Rxg46/+c0fSHZ/6WEnxhloXWBEIJTJ9/7dvH5/B3eq2cYstVsux0g1P4yNFj6e7de9Simbegb2Ipp4KAIOAEgSDjg+KkjkEyCj4z8ItYuWq1Ei4+Epxm581fxCtDCBTwL8FOFPg2XFWTxZy58437gDkBk8hDNfljMmrasjVNUFoA7AhKrFa4v6lBDfb3e/fuU4ky5VkASZ82LQsr29SqE2abx2pirNuwEWtQnMWlUytdz2fPWDUOh9J16zeyn4OuDNTu8OH45/0/zBeOmKgLCAMwVuYQTHB/cEB0F8EXBP4Dl5QWAr4c0KBAGHOmpbFXNu4puXJChXAC4QZaARAENqzyscKFwzLaCW2hCQIlVvAnlCkE5U6ZNp01R/B3cZV8wxaaqoWLFittzi3GmHcxWTYxGUVkSJeWJzU4ckIbAL+VoiXLqJ0hFuE2ZcoUBPMEtEzwr7lxw+LfYjBQJ/+o+sdRPh/oc+gX2L7tCrnavuiX0HiMGT+B+yu22sJ85iqFCxuO7w044B5BJZQzNtoKfjDlypZxiZV+PmbNmctmTmTq2KUb7VAOwq+V9q5shcrKvHeK0qVNoxzL0yuBylsQd1SAs/5vW++XL19Rl+49aeeu3fzMw+kc5rJ06tkEjR31G00aP5ZGDB3MP4TBNwrmNCFBQBDwOwKiQfE7ZpwDu0J6KPPEKOXgCqdAEHbWjBoxlM8xOUITgHejYLWFgWrPX3s5rmXzpnT7zh3j3RGYhBo3tJh8xowcwdtti5Uqy2mLKwfOPGoyhdCDranYGTJ2gqW8CuXKUtIkSTids7hBA/rTYLX9eYJyKIX2BuURBeN88PPAdlFsBQZhVT1qxDA+b9OqBU8iOg73AKHpi8hSnMpqOcEOCKzyGzZtzuwgUPTv29vu7hVn5aGOuDcIUtitgvp7FaHwGqaEvTE0aPAwtfMkLsHRUmsWsArGbh69wwS4YHIx7yJxVi7iYOKzxRZ9QFNbtcMLjs216jagLJkz8e6XYGqnkZmiqPqOULu/fh04hIVWaF3gjwGHTDPBRwgTYrtOnZVWYJ5hskOaurVrsh9UgSLFWciCSc+2HM0L/UiTX9oX/RoO2xCeUMcc2bPRS6VxcoVgwsL9AwfcG5xmI0eOzEIEBK70SkizR7ZaD6QZo4SADp26cD1wDYEWu4EgtNdQO8G6dO/FAieeub5q6789MmPgrP/bqzfS41UCEGqBQ6WK5QnPKChliuRWxeHZTK98yeAwLCQICAJ+R+CrvEnW79UM2jmgoscAiUnWlqAdcKS+xiCHH1aGtoT3TEDNby/vM6URCR8+gt3J1FncU09PimZSjZvLhCYCZdpOjEgDbQ4Gde3HYs7n33OYw2AGwa6JLyVosGB+iBkzhrF9FrygnUEYhAAQVr+4h4H9+/I1/rh8NdFiwvQPAXeU015Nnli9w7lYk7M+oNPgCC1V5MiRrHYymeOdncNE9ejRYzZ9+EXIAk+/tC/e+QGTnHmSd1Yvc5w2Xem8eOEZtDhmfyxzemfnqDMIW/HNBByeKVOavX5sTmd77qz/29YbeYEDBGJ7QpQtb7kWBASBL0NABJQvw01yfQMItGnfkc1rMCdg6y+2rEJbgXfBBBTZE1ACqqxvlS80QdgNduHiRVqzcpm/hcNvFQeptyAgCDhHQAQU5/hI7DeMAPwd4CtxTu3wgYYEpgC8fyUgCY6sUOnrrc0BWda3yhs+LHihYd48uY0XDX6r9yL1FgQEgYBDQASUgMNWOAsCgoAgIAgIAv9v7yrApDiWcKHBNViA4MEtWHCHBHcN7u4aCAR3D3a4u7uEBH04BA/uwSW45fVfez3MDrt7e7d7d0Cqvm93e1qqe/7u6a6uqp4VBAKIwHuPuQAykGKCgCAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4GwERULyNqPATBAQBQUAQEAQEAY8REAHFYwiFgSAgCAgCgoAgIAh4G4HQ3mYo/AQBQUAQ+FwRePPmLR0+ctju9jJmyEBhw4a1i5MLQUAQ8ByBEP8q8pyNcHCFwNOnz+j333+n777LQTFjxnSVVdICEYHbt2/TwYOH6M2bN5QjR3aKHTt2INYmrD9HBO7fv09Zsuawu7WlSxbRt99mtov7FC6OHz9Bjx49oty5czltLtLv3r1npIcOHZoSJfrauP5cAn//fYsOHz5MhQoVpC+++OJzua1P/j5Eg+JBFxYpWpwgfJgJD2/27NmoWdMmFD58eE76uVdvWrZsOaVMmZI2rF9jzu5WeN68BTR23K+UJk1qmjplslHm3bt3tHjJUtr22++0Y+dOevv2LSVNmoQa1K9HFSqUpxAhQnDev86epTp16nN47ZqVFCNGDIOHDpjz6Djzb61aNal5s6a0cNFiGjVqjDnJLjxz5jT6JkUKjps0yYdWrlpFf/11lmLFikXfKaGgZ8+fHNaPArdu3abvcubmsl999RXt2vkHh73xtWnTZmrStLnBakD/vlS9ejXj+r8Y6NCxM+3evYdq1/6Rx6sVA0d9HTNmDMqaNSuVLVOaMmfOZC3i8XWXLt1o+46dVLRIYerTp7cdv5MnT1GDho057retm4znyy5TEF5UrlSR2xA3bhyuFc/fuHHjafOWLXT69BmKEiUypUuXjlq1bEHZsmX1V8s09qlSpaTp06b4q6w7mbEgly5TjrPOmjmd8ubN47DYkqXLqF+/AUZa5MiR6c+jh4zrgAYGDxlKK1asoqhRo9L6dauNuUrz27x5C/3c6xe+nDtnpprXkuqkQPktX6ES/f3339SoYQPq3r1roNRhZfrbtt9p8mQfOnbsOCdlzpSJWrduyeuHNe9/9fqjFlCeH9jM/RI+a9GPsn8uXbrMQoG5cRjke/fuo1Wr1vCDByEla5ZvWUDJ7s9JSvO9e/cuPzxWyb5tuw60erW9wHPq1Gnq2KkLrVm7jqZN9eEH/8WLF1we/F6/fqPZ2v2a89gl+F5cvXqNQ/fu3TN4OcoHPiAsfhDKNAGXFStX0R/btyshba1D7UWnzl10drpx44YR9kZgwMDBzAYarHz58lKBggW8wZZ5HD36J5UrX5HDZ06f8Je635Oynt7ApUuXuC+xWDkiR32Nfjxx4iTNnDmLJk+aQEWLFnFUNMBxl69c4TbNnjOXF00z/6dPnxpjD8K5fyhJUpvQPMVnEhUuXMg/RZ3m7dq1syFsw/RTQS1yx47bFhsUevDgIe1QwhY+I0cOp3JlyzjlZU3Q2IcJEzhTdIwY0Slu3Lj0+PFjSvh1Qq7e0VhMpTZVJUuWIDz/f/75p7WZAb7GYjxx4mTuz3379rNG08xs3vwFnAaBKEmSJOakQAnnUJtKzJnp0qcLFP5Wpnh+ev/S1y561+7dhM+0aT5UsEABu7T/6kXIj/XG/33zmu779Kb7U34hhD9m6tGjO+3ZvZPWrlll7MovX75Me/63l5uNnfqF8399sCPU9wQrG8wOVnJlfcOuRgsnpUuXojmzZ9LKlcuMSfD33/+gWbNmW1m6db1k8UL6fdtWu0/nTh3tymLisObBdepUqQhqcC2c9O7Vk87+dZrbBgELk/bKVavteOFiw8ZNPJF/kOClCPQHqM8vvWjE8KEUT03OZnJnwXPVH5oXdtEBJVdl3akb9fp1H36lO2o7+nrH9m20bdsWFkpix47F2SCEOiJ36nAnT6vWben+gweOqnAY5w5PhwVVpLv4Oiu/Z88eQziB5ufwof20bOliQ5s4dOhwZ0Xdjnf3/hzls94ffGb27N5BJ44fpcSJEn3QBj0WYf4ZN3Y0tW7V4oM8nkTAlBIqVChmsXz5CjtWL1++NOYCsyZYZ3J0fzrN/Pv69YfrhhUHnX/UqBFqnjpFZdRc6ojcrdMZfzNP5BniOx4wd6MPjhw+QGnTpuFsEyZMMmf/T4c/WgHl8WofeqN20W+uXyeEP2aKptSUUPPCBNNXTU76wbtw4QI3G5NT6jTpqWlT20OOHVWq1OkoX/6CLESkS5+Jvs2SnfNil4iJOW26jJTim9Ss0v7nn3/sbh8PywwlgYNKlSpJY0aPZDtyhvTpeaeWO5fNpjx/wSK7cu5eJEiQgO3MMFfpT/To0eyKY4LTaebfMGHC0Jkzf7GvTbJkSZVpqTaFDh2K0DZMSiDsmMwEM1mHDp046ofvi5uTPA7v2fM/xlozatGyNV8/efKEoxYuXES58+SnZMlTEnbZ3/9QilDGTCtWrFQalyKUNNk3XBb9+D9f4RNCoNaeoEz6DJnpxx/rsAYIfYh+hvClqUyZ8hzXrXsP7ntHZXXeP48d4/4HD9QNk+KuXbt1Mk/iSEM86kAbcR8YV1u3/mbkQ+D06dNUo2Yt+iZlGq5/2LARdumuLtDXGBNYyKDRGDZ0CGfHuLx58yaHMSZHjBzFbUEbcO+4R4xnTdAyDBw0mHJ8l4vbid+uXbvTtWs27ZzOp3+xULVt215fOv1dpbSIlStX43tLniIV43/58hXOf+bMGb5fXbhhoyZ8rRcSV32ry7jzu337Ds4GYa7WjzUpWrRobAIbN24MVa1SmbV22IToZ//bLNns2Nat14DbNU6Zcq00Zeo0xhO4VqxUhQ4cPGhk0fwwBrAp0NhWqVqdHj58SLNmz6GcufLyXNK8RSs6d+48lwW2GDv4ACNn49ioyMsB+LKUVnMXaPWatXYCIsauFpCAHQiCaufOXY37y5rtO6VpmGEI5Ob7gaYW94yxrjW/fvUzTDyYo6HZ0GSts3jxEjRmzDi7tqIcMFyqTGEwIYMHrps3b0lokyN69uyZGqM1qHHjhvRL714UIUIENnXBZAi6cOGio2L/ybjA0R96COXbh3fo8cJxBheEIxWsTKGixTLiPtbA+vUbjIdLCwpP1CSNwQq1LejVq1d8jYenV+8+HIeJDQ/lj7Xq0JEjRzkOgs5vv22j32gbX+uvs+fOGXVYNRvIM3jwAIK9HgM/OChnzu/owH77RR4LGFTIoOTJk9k1q0+fvoSHNpFaAJs0aUzrN2y0S/fkImTIkAqH8HaTBa7RHkxwffv1Z/bAH23AZI2FHD4OUC2jP9u1t2mPYB4KFSokbdy0iX7/4w/lv7FDXds/Qph4w4QNQ/ChKatU+vOVqrpXr97sU4GJWJsAWrVsrjQSf9jdmi6LyPPnL1CVKtW53RgH6EvEYXxAW4adrR5HMDU2a/Z+h4txhYV465aNbLuHb0/FSlX5/nSFv46foIP+/gV2mkKECMnBbt1+okWLl3AYwiw0ZQsWLFR9fpTWrbVpzHr+3IvjkAl9DXMRfC2OnzhBa1av5LL6K2HCBLy4YAEG3yqVK+kku18IJ23atOM4YITnDGry4t+XoN27tvvGf9j/SPCrb2NEj87l3flKnDgxZ4PQBhMrfNAgoKdIkZwGDRpgsNB9Zl28gBfiHj58ZORFAH3Zv/9AI+7QocNUrVpN2rxpPY9PzQ9jw6zR2r//AJUsVdbOVIr7hUkH4wd9qNvw4sVLp+PYqDgQAlWU8AFhAs8dhK5syrcJtNTXNAwTVOrUqTi9khq/Fy/aFm6ML8yleHZv3b5F3bp2sbufdsr0rQlueO70s8ZfbwaxaapQoTJpzSu0v/DT+2vUaPr71i2CDxtIl/upx88GnojHHBZSPbfQPlkpYsSI3GZzPATqqdOmc1TJEj+Yk/7TYdvs8pFB8GD2AHr39LnRKoQR97FSF7ULzJDxW8LuDdoPDOZf1c4JD5dfBPvuwQN7eUGHw6IWTmymkVMEc4uVDuy37aCwcGEit1L8+PF5p4tFLCCUv0Ah3rFhF6w/mADNhAlCp+lf88RgzovwoEFDeLJEm+vXq2skY8LVC9v4X8dSiJBqRnGDsFPELsr8wYJoJZzWOXTwvcYGDoG4jhIlCsHfAQ69nTt3ZMc/qFrRPhAc2EBr163nX/QlhK7/7dlF2OlkypSR+6pmzeq0YvlSzoMvqPa1U2P3bl14LNy+fUcJQ9OVic82qbVt05oFGFdlO3bqzBMenBdPnzrBauDatWtxPd26/2TUhwAE24YN6rOKWteNeCzuoKlTpxnCCdr615mT9NNP3TjNnS/0NbQ5hw8f4Z1iu/a2BQALBTSHWFx0Hy5aNJ/x3f7HNr53+ERpDdLGjTbBs1Gjhso8uIXHPU6/wGnbqkX5NnNmQj5Qd6WJceSTBI2MFk66dunMGKEP4YyOxXf4iJEcNvc/fFBwDQdyv/rWHWx0nqpVK/OYwDV209Bo4LlorzSDEHo9Iey0z509TVs2b+Txif7GTt5KXTp34r7VWgdghmft5Ik/ebeO/NDAWR37Ee9qLCLdHYL2wfw8IgxtnjPCqUa9iVq+fCVng8D1xx82wbJyZZtGYZJyJIVwgg3C/n17uP/g/wSaPHkKm5T5wvcLcyKEc/iDQfMXkH6eNHkyCyeYDzZtXK+eweOGUIJNh95s6XqRD5uagwf3Gf40W7Zs1clOfzFWoLktULAwC6P58+ejNm1bO83/X0v46ASUl+eP0tPNtsFq7gzEvTzvPSctM29PwxBIwocPx1774IXJsa/yEcGxVr+of78+PEFDjY7dJgg2fphGMIlmUQ62EGLM9PyFTXjDjjswCO3Hrsb8Me+adZ3mdIRvOblf7NZ9pkzlYiNHDOMTPbjAAgOBDoT7hYnMXcKij4XT/NG7H3d5/NL7Z1q3bjUVyJ+f/WLGjn2vXr9x/Qaz0SdVsNCirdCCdOzYnhbMn0uFChZwWVWkSJGUCvdnzgMnXey2MMm2aNHMZTmYH7Sg+nXChLRkyRLWPMT0PX2FXbXVZ6mtmtQwHgoUyG84FWLHB4JgAapYsQJlzJiBoFWCQGM123EmJ19ly1agChUrs3YA94EJefSokZzbbLI7r0wIEBR37drFQhgy4PgmCCdaQDAnwIdq3/79NGvmDPWZzgsJJ5q+oB2EpgULMsxq1jF48tRJIzdOzKBe+DPAFAXS921ksgQ86VsLK8Z++bIlNG/ubENQwTOB9sBsCFNiQAg4Q/DALzQyDRvWZzaHfbWsZp7169clmFhr1frRiG7SpBGfNKrjK9wi4erVK0a6NwN37ty1ex7xbN64YTMBOqoH81slNSZBK5UmBeMeGwP0N6hyJZvWDIcOQNB8YtFHP4M3MAGdUuZLM3Xv3o01h5hTQQHpZ23ChZYnRYrkzAe+hNr/CmPXTBXVqUloXKF1a9y4ESdhHjWbOM35dRhthPZWE8zjB5T2S8iGQOCscB6g+2ByT3isMYdwWXNy+MVBZS5QcQ8m96C4g1d5wD1wisLxEpM/6KZSW5cuXY7V17DBm48FO6odx+w0nVaDE4RJ2UxJkiQ2XxqqUDwAEIKs7/PAwo+0kEoboY862zHw42Lzpg28MzZnw2JrJixu2CWbSU8Y5jjs9EYqtSiof7++CptSRvKvv47nnTEEvMaNGrCd+f69+0Y6bMCRIkZ0eCoGuyMrYXL2D0H1C3U8FhIr6SPa0JZgRwdtxBolnOAD+uGH72nggH5sO7aWNV9jgoMZD/0BwjFCvwTL68rvStPcefN10O73uq8ApSOhNtYErQZ2nO/e2Z6j8xfOc1KSJIn5V38lTPg1C0362tVv2rRp+PSOztOpYwfjaOpx32OSSMOYt9LlS7YFEVqOK1eu8s4U6mx8MGZgDunQoZ21GPsu+UyeSMWK/8CmsQkTJ9nlOalOE2nq/pOaNyx07dp7HC1JfOlp3zriCfMmBJXnz58THNX7KfMMNBldlQnMPPYdlXUUh+P5ECg16eO2Vo0T0vWCDBOjJv3chvN95YGOD4zfdu3a8Pg28za33Ryvw5WV6Q5+MngGoU3VDrMQxrR2GOZqEARzR+Pr0sXLBI2bJqsDfED6+fTpM8wO7TAThBBsjk4ct59/tOCCvHFixzaKaGHLiLAEMCbwwXiBmQj3D18haL10f1qK/KcuPyoB5emO5fTy5DHugBDKsTJGQ5tK/ObR4uokj1p0VRryRMxb/qPtJDwcpUuXpBkzZhHswP6hJEkSc3br4nNNPZhmwmKhaf78hUrN3Upf8m93ZQLA+1Hw0Oz93267NHcuINHric1Z/pAhQ/mZZ/jwkTROCSEgmBRq1Khmx26dr/kEizccVa2URTkOwxxivT/k8/ThhSoZEwEIprDaatcJDU7z5q0MPxGkwRSEHf45pRmA3wl8guBEC+EG+Vu2aI5sTgk+Elo4QSa8G6ZmjerG7s9RQdjeNcHWnTZdWn1p/MaLF1e16Zxx7SqgBRHrgm0WhFyVh9ZH+4gUKlyMhR8sKo2UUIkFSC+aGDdz5sz8gFX0aNE5DnjBtIMd8W516mXlytUsrGCMFClSmLU71sLYvcJUBg2UVv3rPFgsNMF0ZTUPhgn9fqHW+cy/nvatmRecf68q4QvaTnywMYAQi/cSQYMCwu5YC764xu5aC5bOtK137txBVoO0YBInThwj7mMJQNh0tElx1b50amxjnsKiv0j5I2nn7mrVqhrFoBGD71bxYsXUM9vUiNeBBMqk7YoC0s+6To235q9NjcmSJdNR/v6Fv8mBAwcYK/ipYUxgvHRSmlkIKBBqdipTnF8aWn9X/AkWeC+aB3Pj/32l/Eym9jdaEal0TQoTPxl/ENb0YFp/Qt6PkaC5gLob6krQ177vF3C3rZkyZuSseAjwYjEQdg0wK5gJO/BChWy23VGjx/BOFEd7cawOu1IIJ6AqlSubiwVpGBO2Fk6gooZJwUoJlK0Yi5/5Y86D+BjqxWCBQdjJaxo0sD8VK1aUJ4mTp2y7NZ0GUwROiGBBxT1Aha99i7Rpw7wwoh80YQGC/wSobt3a7JOBvvXxmaqz2C2quiz6V+/c9h84yCegcAoKgg7aM2f2XH8tBPCXAS1WzqZ6gl2r3vkANbl/qV+/X7gI+IAfKGvWLPyLXXDECBG5vemVOWfWrDk0evRYOqtMTTg1BTNN2XIVKVy4cNSubRvauOH9uDafTGFmpq+G6uVZ4GelDBnSG1EXL10ycDp44BANGTKM9MkaZNIL513TPbvTt0YFfgQe3H/AjpFwBNan97DQQJDT9M03KShx4vfa0YmTJrOZE8IuHIYdEXjokyUwrU2dOp2zZTTdu6NyAYlzNo4Dwss/ZbQpB35MuF9Q+XJlDRb6JXenlS9PciUY4FmA6XPAgEH8LpXHllOORkHfQED6Gb5rIGwA9XMJLSrmY5BuE1/48+v582esuYXz/Zy584zS5rGSUo0VIaKPRoPycMkYeus7eYSKGoWiVeto9A/Cz35TkuWjx/T27j1C3ug1uhjpwR2AmQCOsvrh0u0xO4PqOFe/efLkZvMOPMdxZE3vLByVgUMpjrjBNwIPID5mwgIHc4KV8KZWPVnrtEUL51PoMO+HgqM8FcqXU5P+IF3E5S8eZDivaRo2fAThowm7P7wl1pH5C6+ir1TZtnuyngTS5b3xi50tcECfVVanZeDrgwXN2ofAEUIfFlCYd7AIA3MQ3qYKSpE8Of/iq3CR4hw/ePBAtesfxPlhDuverSs75MIUASzKqQkYphhnZXv2+Ilw9BQ7KmhscJRb2+K/VIKbtQ+NBjgI1Kn9I81VEyHuDZoqV+PKQXG7qFw5c/Jr3aGO768WCNwHxq12GsbpGbyE65oyU+lFF28P1ho5vOyrarUa/LbMs2ffa4C+L17Mrh7zBXaYkyaNp7z5Ctr1D3adeLvx+AkTCQ7aeCsnNDp4kRyolMl3C8IB+g3Hmn18prDDqTt9a26HqzD8E7AxgBCBMQBtktknCrthaEug9dFpeOssPiA9Fh3VgRd6jR4z1s4ch9Nu3iZnY9Hb9Vj5VVLOsOZTZXCcxuZEE/xugC3mxWzZc7KmDeMPAjuerQTxE6jN2Sud/YPfgPQzhGKcMEMfZs+Ri32kUD8IpzM9EVBSqXdFYZOD8fjzz735AAGeTa1phXCEgw5CRB+FBuXtnWv0z9L3u8podTpTyAiRjf5BGHGakBdlPibSCxu80vGATZo4nl837582whdj4YJ5xm4Rak88XA3q12M2mHw1Ie/iRQvYXIAjrZoQj9c1r1q5nB3mdLz5F201f/Q7IVzlcfTSI3N+c1i/Y0THmetCWD+IOt38a1aBm+O9HQaWPj4TWauBhRQaBWi8rP+pgoUH2g+YXWCyw+KHPsYpK+13hIUSR0mxyODetiozEBxU8RcFoAED+nNfQG2NBQoY/NTD5jPhqCzKwJt/woRfWWBF+yCcgD+O2w4bNgRZnJJ5nCATTDD4CwI9TjCuYH6AvwTIv5j37WPTomDyhvAGjc/cObNYBY8whDm0GZjNnzfHcFodMKAv58F9QIg15/FrQo4XLx4NNh3X5Yarr06dOlAr9RIxLGiY8NE/eAbQP2YzAfpHOwXjRBqOXrvTt7oeR7/L1ftxsOuHrxQcMfHKdv03D1o4gTCC53Gy8qUBAevF6qSTNuOhrY0bN2Qhz1Ed4AeTIAQfEIRLbE7g7OwO+advnY1Fd+rxJA/MKXguNFWtWkUH+Rd9v2L5Esqg/pQRzxcEdvziWV29agX7KtkVsFwEpJ/jxImt3ga+nAVvPK8QTtBXeO8U3vSKMeyMQqlXEfhFK1cs4/fjYC7Bpgf3g7GCuR7PkpANgY/izwLvDG5Ez3Zu4RaFTZ6C4o3YoJ5kSyf/+45utitOr87bdl0R8hShWF18Ptt+xFFA+EnoSbBRaPgAABf4SURBVNWvG8UkCUdiR/+z41fZ/3o6zBWYfMy7NkeY4C8HsPg7wxiCHhY+9Bn4+YdclcVYePDgPu+q/LPgOKof4yScahsmxsAiqMGBUcSIzuuAbT96dNd5/Ns+9A/oyy+/dFoU6noIUfBLMJNffavzorxffxaI00bAAOPAWo/mg1/8ER/S3elTLGDIb3WIN/PzVtg8FoHL6dNn2IEVmiosot74L56AthVm9GvXrymtSXzuR//ycbefzXxxYg4+QlrAN6d5I4wxhfcJuTvXe6POT4VHsAsoL07soVtda9jwCqE8oAcvpHCps9ODeYPp8XzbriNK9aZs0nlxah/d6mxT/6NAnEHzKFxaddJHSBAQBASBIEAAmkS8B8NMcIr1S7g15/+UwtCQmc3HwS2gfErYSVs9R+C944HnvPzPQWlFcHRYU4R8xVk40dfWXwguEfIXp2d/bOQklI03SjmTWrUt1oJyLQgIAoKAFxDAUXb9wjwvsPvoWcDnyOzLFjVK1I++zdLAzweBYBVQ/tk0h15dsL2hNES4sBSjnu2lVq7gRZ7ne7fRvy9ecVnwiFy8tqsikiYICAKCgCAQAATgzKlPrQWguBQRBDxCINgElHdPH9PDWcOMxkep1IRCxXzv7GkkWALIg7yP5ozllIezhlPEPOUoZER7m7KlmNcv8xYs4nWewlAQEAQEAUFAEAACO9Q7g/7rFGwCysP5Q+nd438Y/9DqzXtRy7t+4ZW5o5D36aaF9EY5Lr1Tf34FXvqlbuZ8gRmWwROY6ApvQUAQEAQEgf86ApajMkEDx+tr5+jJ2vev8I7eoCeFCBvO7cqRF2U0gRd4CgkCgoAgIAgIAoLA54FAsAgo96f05FfXA8IvMnxLEXKV8jeaKIOyILwGHzyFBAFBQBAQBAQBQeDzQCDITTzPD2wm/vM/4Kf+zC5G434OkQyfPreKV+eOFYVPn4t/rV8xGvWlm22UcKP+FA08wTt81qLWbHItCAgCgoAgIAgIAp8YAkH6HpR/37ymGy0L0hvff2uNVLIqxWzq3uvTneF6b2JXZS5ayMmh1ct7vhq3jUL48SdhznhJvCAgCAgCgoAgIAh8HAgEqYnn8WofQzgJGTkiRa/p/P903t67QTfbFuXP2/s3naIFHuAFguCDOoQEAUFAEBAEBAFB4NNGIMgElLcP79DjheMMtKLVaKsEC9vfsBuRpsCz/Zv5tfZ4tf2zfZtMKfZB8AAvTajj3SPbK691nPwKAoKAICAICAKCwKeFQJAJKA9mD6R3T58zOmESJabIJeq5RCpCtqIUNlly/kTI7vyfTsEEvMAThDruz7L/Z19OkC9BQBAQBAQBQUAQ+GQQCBIflJfn/6S/25XjP7MDMrH7zaTwGfN5FaTnR7fT7R51bDzVP4bGHbmCvkjm3j9+erUhwkwQEAQEAUFAEBAEPEYgSE7x8P/tqH96BYVU/96JPwjEx9sE3nhxG/7VF3XGHbzK21UIP0FAEBAEBAFBQBAIAgQCXYPydMdyujukfRDcyodVfNl5BEXMW/7DBInxOgKP1VuBo0SJ7HW+wjB4Efic+vX58+cUWp3wCxMmSPZlwdtxUrsg8BkgEKg+KP++ek4PpvUPNphQN9oQGPTu3TsqWbYCLVux0o79rVu3Of7Fi5d28Y4ubt++Q+d9/yzRUbo5bvbc+TRi1BhzlFfCNWrVpVOnT7vkdeLkKb4n3K/1s2LVatq7b7+KL0/Xb9xwyScoEv2DqbU9Fy5eonoNm1Cb9h2NJPTz2F8n0PelylLh4iWoR69fSPct7hd4fK7kbr8OHjqcFi5eEmQwrFqzlnr90tet+vr2H0hLl63gvE2at6LefR2/dwkZPBk7bjUmkDI5avesOXN5bGLM9urTj169emXU/vDhQx7jBYoUpwpVqtPWbb8badaAf7C2lpVrQcBTBAJ1K/H6xkWKWLSyp230qDzaEDZxGo94OCv8WJmTRo4eS9myZqGECRJwtjdv3xDi//33nbNiRvz6jZvowMGDNHbUCCPOWeDRo0d07/59Z8kBjr+l/s/o+fMXLssnTZKYhgy0CZqLliyli2oh79KpA5eJFzcORYoUiQb170tfxYvnkk9QJPoHU3N71q7fQEOHj6S4cePS8xfv8Zg1Zx5t2LRZ3V8fihgxEv30cy8aN34CdWzflt68sfW1mc/nFM6cKaNb/YpxGTVq1CC79SdPntDtO3fcqg9t++eJ7T+/enTvQhEiRHBaLqBjxynDIEqwthsCx8zZc2mgGrPRo0ajnkqYG6OE7I7t2nCLWrZpR/HVO6N8JvxKe/bupd5KgEmeLCkl+vrrD1rsH6w/KCwRgoCHCASqgALBILCEAw/v22vF8aB36daD5sycRiFDfqiQgop83oKFdPjIUUqdKiVVrlSB4n/1Ff2xYydNmTad24Ede/8+vXmh3/O/vbRm3Xp68OABfV+8GJUuWYJCKKdf0OvXr2n8pMl0RPFKnz4d1apRnaJFi8ZpzupBoqs0Luz7BW0OtAUtmzdVE1YyIyl8+PCUNk1qvo6nFvB79+4Z14i8c/cuLV66jHLnykn7Dhzg9gGL/QcOqbjv6Ad1HxMnT2EBq1KF8pQnt+3NwP8qX6Ely5bTdoXFF198QbVqVqeMGWyOzea0GDFiULkypQkLJgg7wjo/1qSkSZPwNdqc87sc9PTZM4eYciY/vl4oIQ0T9p/HjtNi1SZNib5OSAP6/qLalZ6jSpX4gX7fvkMn8+/uPf8jCG5hwoShOrVqUrq0ae3ScfH69RseB8gbUr1BGTgULlSQ8719+5bmzFtASIsXLy7lyvkdXbp0mRo3rM/piIcAhTYWLJif0Ab/ErRkCxcvpRtK61O1ciXavnMXNahXh9C3/QcOplHDhzJLaIzad+pCvXr8RBC2db8iERqmxeo+8ZspYwZqWL8u37O5LU+fPqMBg4dwH6PfzeQKA/Rpwfz5aPPW3wjCeIXy5ahQgfxcHPjMnb+Adu224RM7diwzW7vw3bv3aM78+dyPOXPkIJTVtP/AQYoVKxYlUM8s6vsuR3baoDYJ+fLkoS9jfWk3dnp270r9FC6dOqjFXD2vIAiqZ8+eo1YtmmmW/Isxf+jQEXr37i39b+9+mjF1Mj158pT7+9Dhw7x5aaT6Mm6cOJz/+ImTNFf1NwQnPAvoDzzjrjAwPw/mZ8XRPHJPYVC/bm3KnjUr11e9amVauMim4YI29PKVq+QzcTz3fYoUyZVpNoqxSfEP1nYgyIUgEAgIfLiiBkIlnzPLLh3b030lTEyZNuOD28QOu1W79rxolyzxPZtAGjdryRMwdixJEifmMpiMsVBgIerW42dKkTw5FVCTNUw6y5a/NyFBeDl/7oISWkryhNimQyc1Kb7jnbyzely1wdzgi5cuEdqWNUsWO+HEnMdZ+JkSDA4eOszJV69cI5ijILTkz5eHfKZOp1r1GtJXapJPnDgR3x98AUDjJkyk2UpDUVAtRIkTJaKWbdrTufPnOW30uF9pxqw5lC+vWjy+jEmt23WgY8dPcNrOXbvpoVrENO3dt49u/v037wKtmOo8fv1WrFCOMFlbCW2DcAIhD8ILTHp5fQUsnXfK9BksbECNjnvAQmwlaF3mL1xExYoUpuzZsipTQ3/DvDdoyDBlhlhOxYoWpiiRIxPMEoePHGEWuNfuPXupsZKIsmTJzBo7CDP+oavXrlGzlm2UEBiWSvzwPU2Y5EO/qV027sncd+D59u077suXr17apcF02ahpc9Yu/fB9Mdr62zb6ube9mQW8mjRvweVwn1ZyhQHuc+iIUayNjB//KzbhXLp8mVkMGT6Clix9j8/8BYusrPkaAnzz1m3o1KkzVL5MGdVfx+jI0T+NvEf/PEYXLlzka9QH7SeEwQyqf63PY/To0emuGsPrN2w0yk+bMZMXcyPCN4AxDwHq6tXrVLVKJaU9/ZdNKNiUlCldih4pjWqDxs2UafCFElyeqL5oTXHixqby5crSvPkLDTOxKwycPSvWdmMeqVK5ItWsXs1o5g4ljOqxfeLkSRbSJk2ZSpWq1qBOXbtTqpQp1ecbzu8u1gZzCQgCgYhAoGpQArHdHw1rmDcG9O2tJqROlDdPLrsJ7NTpM3T58hVat2o5q5ax861S/UfegZdVExd20DDx5FeLMAhq2aaNG1K1KjazGHbk2PVi8QRhpzN08ADW1BQskI9KlatI589foBcvXzqtJ2mSJE7T0AYQTDaduk7m3f+PNd5PbJwYgK/oSqvTrXMnLnnw4GEKHSY079YRsW79Rl4AsTAsUveG3WaypEk57/XrN2jN2vXUumVz9hsYN3qEoVF5qnakCxYtpvTpPtROcGH1hZ2uFVOdhl8IEBAMaivti56QzemuwvUbNSGYw7ADh0Bppv6/9GbNR4F8ealEmfJ08dJF+iZFCnMW7tdaNWuwsAUBbYnyi4DABbU6duaTJ4xTGrZUXAY4PHv+jMMQ9rDYNKxfj6/jqF04TFHWfnJ1b+s3bGLtne4TYFi3QWO79vl1Aa1eMqWx6t3zJ86aI1s22q/GribcU8MmzQnajWGDB1KoUKF0kvGLse0IA93/TRo1oDKlSrK2bOeuPXTs2AnWPmDMTPx1rKG1g8CFxd5KWHzv3btPs6ZNoXDhwikNZFGXPkLt2rRi7Z7mYx07ZZXWbv7CxYz9latX6ebNv6mkEvAcEcY8TCog9Cv8k9auXM4OuSW+L87jAkI8hHQQtEXQFmbN8i1FihiR4/DlCIOvEyZ0+qy0bd3S5ZiH/82Bg4do4dzZXAfG8B1lHsMz30o9ZxBUm7ZoRYvmzaGYMWPw8+kO1kaDJSAIBCICIqB4AdxvM2em8mXLsKlHq8rB9vSZM2rnm9iwe8Psgd34qVOnSQsH5upPnjpF+MAcAoK61TzRp0iezDAjQTDCYvDXOfWmXbVzdVYPFi5naboNo8ba3vBrVcmb2+afMNTlmiJFikiRlWClCRoCLC6Y8EHYWWrC/WLC1mnp06XTSfRt5kw00WeqcR2QAHxLsIu+rv4Swb8CypKF89iJElg1a9Ga5s2eYTQBZhlQZHVvYcOGJZg5rHTt2nXlBzBe9e9pw2Hx1ctX6l6vcdaU39h2sLhIkyYVLyoIQ6OkTT24zqxMK0+fPmXth/nUlKt7++vsWcqQ3maiAg8Irf4ljGWYdTThniFMaNLO4s2aNLIbszodv84w0HkSKM2JpvhfxWMhTY8FmEc1pUubxsBHx+H3L2V+wWIO4QQEAT9xog/9KjhRfcWJHVsHHf4WL1qUxowbz5ouaIxQL7R5jsg85oEVBLaiP7zHB2MbghXMoNiAQNOGDQc2LTALat8YVxg4elYctUXH/f7HdsJ4HT1iKMWJY7vXcF+EY23tsMGDWHjC5gialB27dvEzhrLuYK3rkF9BIDAREAHFS+jCLr1z9x4aNnKUwTG2mgDhr2Gmu+o6c6ZM5igjjN15zWpVqahJPW4WUKByNtPDh494koXvhbN63GkDhCsshNACzVS7z6A4hvllTNtEP3OqD0Gdrils2DBsZsD1gwcPeVeHMExGcXx9D4DJP0pVrumBwsEdiqoWhLUrl7mT1cgDtTu0IRAG8WnSsAH9WLc+/fOPzfHSyOhHoFO37rxjnjV9CjsT16nfiEvAyRgEE5X2dYAGRRN2tbh3TdAQ4P4h+JnJ1b1hIcauWdNjU9tDh7ZNATA9QOi978QRGzxuqVNnmmBafKk0dzApgOAkXrRIIerZuw/NnTXduBedH7/OMHifJ8T7oArBVBLrS5uwe//+A0M4uHPnPR7mAtAuffgc3Ddn8VcYAiAE5nXKzAMBpXkT97ROeOaAy5IF8+zqixDBhlWLZk2obu1adODQIWVmGsMCO7Q5NvoQA1fPil0FpotDh49wX/Tq0V0JHpmNlAQJ4lM45e9lfsajRI3CPjP+wdpgKAFBIBAREB8UL4GL3drgAf0MPwmwzZg+HWExgGkCfglY7DBxwDkPBNUudlVwCgRhNwM/Bdj/I0aMQOMnTlJOq+M5DV9wbtuinAjBa8as2bwTh1nAVT2u0jRj+Lug7bCVD1QOjkFBWAzhgAq7vp4s4ZwJlTPuHVqfYconAdoI7KJh/oI/Cgi74rnz5nM88MKpKfrX1morprbYgH+j73r06s0LN9oyR9WLnS+0Jf4h9BlMJDjpBFU/fH5AWMiwM4efCZwtly5fwY6inKi+8ubJrTRqPqy9wTgZoRY0aDIcOWTrMtZfOBDD+RSmBxyRHjP2VyMLnJ5B8BWCCQO+PyAIB2aCMyf6Bn4VSIM2qFbdBkYW9E29OrUpi1oM27TryPUYib4BZxhY85mvMU7giD5yzFjWSkAbBJOYI0qvcHygjtDCdIi6Vq9ZZyeYOSpjjnM0dsop4R1mEmwG8Jy4QxmU5g+ay81btvJYxqakdv0G/KxDg4ejvdAi5lC+SHDYxTFhV+TqWUE5a7vhyItnCU7QOGGIcaPnmNw5c/KcBNMhtDxwvkb+XGqM+AdrV+2VNEHAWwiIgOItJBUfmGAwKWjCCRvY4zEZFCr2PXvp41SANi/oCQ++JFgccHompXJWq1C5GuEdBXCarWjyd0iTOrWaqMcxr3nKURBCBRZzV/W4StPtxC8WXKiCsZCtXL3GnGQXxgkUK+lTRtZ4Z9c6/0h1cgQnh4qVKM3vUYFmAAsyaPjQQWpCv6reP1KGaisnW5zoqF61Cqe1btlClbtINWvX43ewwNwQwrddVky5gAdfPbt3U6dZ3lLZilW4LUeV46U+Fq7vwx320LBBCMhXqCiPA/gskC+UULdDIOvXfxBt2ryVSpcqYbDErh39XrFqdfY5wsLbt/fPRro7AQgXOMnRqm17NjtgsQXWIAg68PlBn1evVcc4Kh4yREjj9BjyQaiGH0zHLt34HjZs3Ex9f/mwHf369OLTP30HDEQxO3KFgV1GdRFC1a9p+JCB6l09Z3icwJE7R/Zsdm3T+XDaq1+f3gSnZTxvU2fM8HUO/XDM6jLmX0djJ7fylQJWSIP5zh2KHt323E+bOYuf4zr1G/JJIfQxTLx4/stVqqL6ohTdUM89fHMckRkDV8+Ktd2Tp05j8/DU6TN5zGB+wQcErRBeCTB77jzGE474mJO0E627WDtqr8QJAt5GINDfJOvtBn+q/PByJH0k2HoPWr2u47EIIQ4TnZWwe8WOTKtjremu6nGVZuUTlNfwoQFpO7y5buAAnwJtijCn4dQGNFeOyIqpozz+icOOGH4E2qThn7I6L05UwVQRS/nomIUb7GARp8cHTlbgns2CiLfqx64ZwigE4HGjR7L2Bu3DvaFNfmlmYNp59Oixw7Gp79PVrzMMXJXRadACoO1+tRH5cbIuhsl0qHm482seOwhjcYfwro/Au8ND58Ezh/fnaC2hjsfYhRbFv5o4v54VaEHcJZhQHc0xKO8frN2tT/IJAv5FQAQU/yIm+QUBLyMAzcYFdaoCTsqXr1xR79LYR0MG9Se8xyOwyCqgBFY9nzJfOP7iGDCEiOlTJn3KtyJtFwQ+SQREQPkku00a/TkhAO0F/CpwugtvZIWZS5sBA+s+4VuDd5XALCLkGAG8PwQ+LUULF/JIc+aYu8QKAoKAXwiIgOIXQpIuCAgCgoAgIAgIAkGOwHtPtCCvWioUBAQBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQIioDjGRWIFAUFAEBAEBAFBIBgREAElGMGXqgUBQUAQEAQEAUHAMQL/B3PgCSBGwXi/AAAAAElFTkSuQmCC"}}},{"cell_type":"markdown","source":"I referenced the following notebooks:\n\n- https://www.kaggle.com/code/honglihang/openvino-is-all-you-need/notebook#openvino(fp16)\n- https://www.kaggle.com/code/lmhongkhnh/birdclef2024-multithread-with-openvino-inference/notebook\n- https://www.kaggle.com/code/niyanthapandiyan/openvino-for-competition-with-internet-disabled\n- https://www.kaggle.com/code/zijiangyang1116/birdclef-24-inference-with-onnx\n- https://www.kaggle.com/competitions/birdclef-2023/discussion/412707\n- https://www.kaggle.com/competitions/birdclef-2023/discussion/412808\n\nAnd major thanks to the authors of [this](https://www.kaggle.com/datasets/ludovick/onnxruntime/data), [this](https://www.kaggle.com/datasets/ludovick/onnxruntime/data) and [this](https://www.kaggle.com/datasets/nohamagdy/pakeges) public Kaggle dataset which contain the onnxruntime and openvino wheel files for installation in an internet-disabled notebook.","metadata":{}},{"cell_type":"markdown","source":"Here are the results of my experiments, showing inference seconds (and correlation coefficient and percentage of `argmax` similarity vs baseline probabilities in parentheses) for each type of model:\n\n|arch|Baseline|ONNX|fp32 XML|fp16 XML|\n|:-:|:-:|:-:|:-:|:-:|\n|resnet26d|51.57|28.73 (1.00/100%)|19.83 (1.00/100%)|19.39 (1.00/99.17%)|\n|resnet34|37.52|22.58 (1.00/100%)|23.08 (1.00/100%)|23.69(1.00/99.17%)|\n|resnet50|64.85|29.24 (1.00/100%)|28.88 (1.00/100%)|28.97 (0.99/91.7%)|\n\n\"baseline\" means using `learn.get_preds(dl=tst_dl)` to calculate predictions with the fastai `Learner` after loading the exported .pth to `learn.model(<mode_path>)`.\n\n---\n\nHere are the Kaggle Public scores for each submission (TO = notebook timeout):\n\n|arch|Method|Public Score|\n|:-:|:-:|:-:|\n|resnet26d|Baseline|TO|\n|resnet26d|ONNX|0.54|\n|resnet26d|fp32 XML|0.54|\n|resnet26d|fp16XML|0.54|\n|resnet34|Baseline|0.56|\n|resnet34|ONNX|0.56|\n|resnet34|fp32 XML|0.56|\n|resnet34|fp16XML|0.56|\n|resnet50|Baseline|TO|\n|resnet50|ONNX|0.57|\n|resnet50|fp32 XML|0.57|\n|resnet50|fp16XML|0.56|\n\nAll of my ONNX and XML model inference notebooks ran well under 2 hours, with the resnet26d fp16 running in a little more than an hour. I consider this round of experiments a success.","metadata":{}},{"cell_type":"markdown","source":"I'll start by running the code that I need---`DataLoaders` and `Learner`.","metadata":{}},{"cell_type":"markdown","source":"## Create `DataLoaders`","metadata":{}},{"cell_type":"code","source":"trn_path = Path('/kaggle/input/birdclef-2024-training-data-subset/notebooks/train_chunks')","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:08.768134Z","iopub.execute_input":"2024-04-19T16:11:08.768752Z","iopub.status.idle":"2024-04-19T16:11:08.831363Z","shell.execute_reply.started":"2024-04-19T16:11:08.768702Z","shell.execute_reply":"2024-04-19T16:11:08.830214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PowerToDB(Transform):\n    order = 75\n    def __init__(self, sr=32000, n_fft=512): \n        self.sr = sr\n        self.n_fft=n_fft\n        self.mel = MelSpectrogram(sample_rate=self.sr, n_fft=self.n_fft)\n    def encodes(self, x:TensorAudio):\n        return TensorMelSpec.create(librosa.power_to_db(self.mel(x).cpu()), settings={})","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:08.833309Z","iopub.execute_input":"2024-04-19T16:11:08.834803Z","iopub.status.idle":"2024-04-19T16:11:08.846597Z","shell.execute_reply.started":"2024-04-19T16:11:08.834765Z","shell.execute_reply":"2024-04-19T16:11:08.845557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LoadTensorAudio(Transform):\n    def __init__(self, sr=32000):\n        self.sr = sr\n    def encodes(self, x:Path):\n        x = torch.load(x)\n        return TensorAudio(x, sr=self.sr)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:08.848968Z","iopub.execute_input":"2024-04-19T16:11:08.850983Z","iopub.status.idle":"2024-04-19T16:11:08.865598Z","shell.execute_reply.started":"2024-04-19T16:11:08.850935Z","shell.execute_reply":"2024-04-19T16:11:08.863069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"auds = DataBlock(blocks = (TransformBlock, CategoryBlock),  \n                 get_items=get_files,\n                 item_tfms = [LoadTensorAudio, PowerToDB(sr=32000)], \n                 splitter=RandomSplitter(valid_pct=0.2, seed=42),\n                 get_y = lambda o: o.parent.name)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:08.873255Z","iopub.execute_input":"2024-04-19T16:11:08.873874Z","iopub.status.idle":"2024-04-19T16:11:09.016365Z","shell.execute_reply.started":"2024-04-19T16:11:08.873830Z","shell.execute_reply":"2024-04-19T16:11:09.014645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dls = auds.dataloaders(Path(trn_path), bs=64)\ndls.show_batch(figsize=(10, 5))","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:09.017912Z","iopub.execute_input":"2024-04-19T16:11:09.018294Z","iopub.status.idle":"2024-04-19T16:11:21.494034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(dls.vocab)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:21.495609Z","iopub.execute_input":"2024-04-19T16:11:21.496143Z","iopub.status.idle":"2024-04-19T16:11:21.506972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dls.vocab","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:21.509332Z","iopub.execute_input":"2024-04-19T16:11:21.510166Z","iopub.status.idle":"2024-04-19T16:11:21.540834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create `learner`s","metadata":{}},{"cell_type":"code","source":"models = {\n    'resnet26d': '/kaggle/input/birdclef-2024-resnet18/pytorch/26d_v1/1/birdclef24_resnet26d',\n    'resnet34': '/kaggle/input/birdclef-2024-resnet18/pytorch/34_v1/1/birdclef24_resnet34',\n    'resnet50': '/kaggle/input/birdclef-2024-resnet18/pytorch/50_v1/1/birdclef24_resnet50'\n}","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:21.543507Z","iopub.execute_input":"2024-04-19T16:11:21.544530Z","iopub.status.idle":"2024-04-19T16:11:21.551524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learners = {}\n\nfor arch, model_path in models.items():\n    learn = vision_learner(\n        dls, \n        arch,\n        n_in=1,\n        loss_func=CrossEntropyLossFlat(),\n        metrics=[accuracy],\n        pretrained=False)\n    \n    learn.model_dir = '/kaggle/working/'\n    learn.load(model_path)\n    \n    learners[arch] = learn","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:21.554274Z","iopub.execute_input":"2024-04-19T16:11:21.555228Z","iopub.status.idle":"2024-04-19T16:11:27.774880Z","shell.execute_reply.started":"2024-04-19T16:11:21.555181Z","shell.execute_reply":"2024-04-19T16:11:27.773732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learners","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:27.776919Z","iopub.execute_input":"2024-04-19T16:11:27.777616Z","iopub.status.idle":"2024-04-19T16:11:27.786400Z","shell.execute_reply.started":"2024-04-19T16:11:27.777576Z","shell.execute_reply":"2024-04-19T16:11:27.784008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learners['resnet26d'].arch, \\\nlearners['resnet34'].arch, \\\nlearners['resnet50'].arch","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:27.788549Z","iopub.execute_input":"2024-04-19T16:11:27.788988Z","iopub.status.idle":"2024-04-19T16:11:27.806307Z","shell.execute_reply.started":"2024-04-19T16:11:27.788954Z","shell.execute_reply":"2024-04-19T16:11:27.804713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Submission File Creation","metadata":{}},{"cell_type":"markdown","source":"Later I'll also try to optimize my `create_test_chunks` function to trim off a few more minutes during inference, but will use it as is for now.","metadata":{}},{"cell_type":"code","source":"def create_test_chunks(full_tst_files, test_chunks):\n    for fname in full_tst_files:\n        # prepare 48 five-second chunks\n        ta = TensorAudio.create(fname)\n        chunks = [ta[...,(i * 160000):(i + 1) * 160000] for i in range(48)]\n        \n        for i in range(48):\n            # create chunk tensor file name stem\n            end_time = (i + 1) * 5\n            fn_stem = f\"{fname.stem}_{end_time}\" \n\n            # create full file path for chunk tensor\n            fn = Path(test_chunks)/(fn_stem + '.pt')\n\n            # load a chunk of the TensorAudio\n            ta = chunks[i]\n\n            # convert it to regular tensor\n            ta = ta.clone().detach()\n\n            # save it\n            torch.save(ta, fn)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:27.808686Z","iopub.execute_input":"2024-04-19T16:11:27.809579Z","iopub.status.idle":"2024-04-19T16:11:27.819115Z","shell.execute_reply.started":"2024-04-19T16:11:27.809538Z","shell.execute_reply":"2024-04-19T16:11:27.817899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create Test `DataLoaders`","metadata":{}},{"cell_type":"markdown","source":"I'll use the same test `DataLoaders` for all my experiments. It will contain 240 five-second chunks, which is about four batches with a batch size of 64.","metadata":{}},{"cell_type":"code","source":"tst_files = get_files(path/'unlabeled_soundscapes')\n\ntest_chunks = '/kaggle/temp/test_chunks'\nos.makedirs(test_chunks, exist_ok=True)\n\ncreate_test_chunks(tst_files[:5], test_chunks)\n\ntst_files = get_files(Path(test_chunks))","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:27.821070Z","iopub.execute_input":"2024-04-19T16:11:27.821797Z","iopub.status.idle":"2024-04-19T16:11:34.132960Z","shell.execute_reply.started":"2024-04-19T16:11:27.821762Z","shell.execute_reply":"2024-04-19T16:11:34.131496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(tst_files)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:34.134695Z","iopub.execute_input":"2024-04-19T16:11:34.135132Z","iopub.status.idle":"2024-04-19T16:11:34.145096Z","shell.execute_reply.started":"2024-04-19T16:11:34.135077Z","shell.execute_reply":"2024-04-19T16:11:34.143534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create test DataLoaders\ntst_dl = dls.test_dl(tst_files)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:34.147277Z","iopub.execute_input":"2024-04-19T16:11:34.147780Z","iopub.status.idle":"2024-04-19T16:11:34.158125Z","shell.execute_reply.started":"2024-04-19T16:11:34.147737Z","shell.execute_reply":"2024-04-19T16:11:34.157254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"markdown","source":"With the setup out of the way, I'll now create three versions of each model and time how long it takes to calculate predictions for those 240 chunks:\n\n- .onnx format\n- .xml format\n- .xml format (fp16)","metadata":{}},{"cell_type":"markdown","source":"## ResNet26d: Baseline Inference","metadata":{}},{"cell_type":"markdown","source":"I'll start by calculating predictions with `learn.get_preds` as I did in my previous submission that timed out.","metadata":{}},{"cell_type":"code","source":"learn = learners['resnet26d']","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:34.159376Z","iopub.execute_input":"2024-04-19T16:11:34.160714Z","iopub.status.idle":"2024-04-19T16:11:34.172804Z","shell.execute_reply.started":"2024-04-19T16:11:34.160674Z","shell.execute_reply":"2024-04-19T16:11:34.171536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# time how long it takes to calculate predictions on 240 chunks\nstart_time = time.time()\n\nwith learn.no_bar(), learn.no_logging(): probs,_= learn.get_preds(dl=tst_dl)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} baseline inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:11:34.174455Z","iopub.execute_input":"2024-04-19T16:11:34.174875Z","iopub.status.idle":"2024-04-19T16:12:25.760225Z","shell.execute_reply.started":"2024-04-19T16:11:34.174835Z","shell.execute_reply":"2024-04-19T16:12:25.758387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"probs.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:12:25.762775Z","iopub.execute_input":"2024-04-19T16:12:25.763199Z","iopub.status.idle":"2024-04-19T16:12:25.773758Z","shell.execute_reply.started":"2024-04-19T16:12:25.763163Z","shell.execute_reply":"2024-04-19T16:12:25.772023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ResNet26d: ONNX Inference","metadata":{}},{"cell_type":"markdown","source":"I'll create a function I can use for each model to create an .onnx model file.","metadata":{}},{"cell_type":"code","source":"# constants for all onnx session creations\ninput_names = ['x']\noutput_names = ['output']\ninput_tensor = learn.dls.one_batch()[0]","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:12:25.775621Z","iopub.execute_input":"2024-04-19T16:12:25.775970Z","iopub.status.idle":"2024-04-19T16:12:27.634178Z","shell.execute_reply.started":"2024-04-19T16:12:25.775943Z","shell.execute_reply":"2024-04-19T16:12:27.633198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_onnx(learn, input_tensor, input_names, output_names):\n    # create the .onnx model file\n    fname = f\"birdclef24_{learn.arch}.onnx\"\n    torch.onnx.export(learn.model, input_tensor, fname, verbose=False, input_names=input_names, output_names=output_names)\n\n    # read in the .onnx model and prepare for inference\n    onnx_model = onnx.load(fname)\n    onnx_model_graph = onnx_model.graph\n    onnx_session = ort.InferenceSession(onnx_model.SerializeToString())\n    \n    return onnx_session","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:12:27.635433Z","iopub.execute_input":"2024-04-19T16:12:27.636305Z","iopub.status.idle":"2024-04-19T16:12:27.644053Z","shell.execute_reply.started":"2024-04-19T16:12:27.636273Z","shell.execute_reply":"2024-04-19T16:12:27.642776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I'll create a function to calculate predictions using the .onnx file.","metadata":{}},{"cell_type":"code","source":"def infer_onnx(onnx_session, input_names, output_names):\n    all_batch_outputs = []\n\n    for batch in tst_dl:\n        x = batch[0]\n        n_pad = 0\n\n        if x.shape[0] < 64:\n            n_pad = 64 - x.shape[0]\n            zero_tensor = torch.zeros((n_pad, 1, 128, 626))\n            x = torch.cat([x, zero_tensor], dim=0)\n\n        outputs = onnx_session.run(output_names, {input_names[0]: x.numpy()})[0]\n        outputs = scipy.special.softmax(outputs[:64-n_pad, ...], axis=1)\n        all_batch_outputs.append(torch.tensor(outputs))\n        \n    return all_batch_outputs","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:12:27.645988Z","iopub.execute_input":"2024-04-19T16:12:27.646382Z","iopub.status.idle":"2024-04-19T16:12:27.662837Z","shell.execute_reply.started":"2024-04-19T16:12:27.646352Z","shell.execute_reply":"2024-04-19T16:12:27.661316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"onnx_session = create_onnx(learn, input_tensor, input_names, output_names)\n\n# time how long it takes to calculate predictions on 240 chunks\nstart_time = time.time()\n\nall_batch_outputs = infer_onnx(onnx_session, input_names, output_names)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} .onnx inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:12:27.671510Z","iopub.execute_input":"2024-04-19T16:12:27.672018Z","iopub.status.idle":"2024-04-19T16:13:15.097329Z","shell.execute_reply.started":"2024-04-19T16:12:27.671981Z","shell.execute_reply":"2024-04-19T16:13:15.089017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:15.106725Z","iopub.execute_input":"2024-04-19T16:13:15.107817Z","iopub.status.idle":"2024-04-19T16:13:15.134490Z","shell.execute_reply.started":"2024-04-19T16:13:15.107725Z","shell.execute_reply":"2024-04-19T16:13:15.130306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I'll use Jeremy Howard's helper functions from [this](https://www.kaggle.com/code/jhoward/getting-started-with-nlp-for-absolute-beginners#Metrics-and-correlation) notebook to display the correlation between these predictions and the baseline as well as what percentage of the argmax indices match between the two (i.e. what percentage of their predicted class are the same).","metadata":{}},{"cell_type":"code","source":"def corr(x,y): return np.corrcoef(x,y)[0][1]\n\ndef show_corr(a, b, title):\n    x,y = a.reshape(240 * 182), b.reshape(240 * 182)\n    plt.scatter(x,y, alpha=0.5, s=4)\n    plt.title(f'{title} vs Baseline; r: {corr(x, y):.2f}; % argmax: {(torch.argmax(a, dim=1) == torch.argmax(b, dim=1)).sum()/240.}')","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:15.139614Z","iopub.execute_input":"2024-04-19T16:13:15.141336Z","iopub.status.idle":"2024-04-19T16:13:15.164985Z","shell.execute_reply.started":"2024-04-19T16:13:15.141228Z","shell.execute_reply":"2024-04-19T16:13:15.160288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} .onnx');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:15.169044Z","iopub.execute_input":"2024-04-19T16:13:15.169939Z","iopub.status.idle":"2024-04-19T16:13:18.285872Z","shell.execute_reply.started":"2024-04-19T16:13:15.169844Z","shell.execute_reply":"2024-04-19T16:13:18.284645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"These predictions are essentially the same, with onnx taking about 60% less time for inference.","metadata":{}},{"cell_type":"markdown","source":"## ResNet26d: fp32 XML Inference","metadata":{"execution":{"iopub.status.busy":"2024-04-18T21:10:41.876364Z","iopub.execute_input":"2024-04-18T21:10:41.876892Z","iopub.status.idle":"2024-04-18T21:10:42.559761Z","shell.execute_reply.started":"2024-04-18T21:10:41.876853Z","shell.execute_reply":"2024-04-18T21:10:42.558761Z"}}},{"cell_type":"markdown","source":"I'll use `openvino` to create XML models and run inference on that.","metadata":{}},{"cell_type":"code","source":"fname = f\"birdclef24_{learn.arch}.onnx\"","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:18.287298Z","iopub.execute_input":"2024-04-19T16:13:18.287622Z","iopub.status.idle":"2024-04-19T16:13:18.293580Z","shell.execute_reply.started":"2024-04-19T16:13:18.287594Z","shell.execute_reply":"2024-04-19T16:13:18.292009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mo --input_model {fname} --compress_to_fp16=False","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:18.295581Z","iopub.execute_input":"2024-04-19T16:13:18.297115Z","iopub.status.idle":"2024-04-19T16:13:24.661250Z","shell.execute_reply.started":"2024-04-19T16:13:18.297032Z","shell.execute_reply":"2024-04-19T16:13:24.659831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_infer_request(learn):\n    core = Core()\n    openvino_model = core.read_model(model=f'birdclef24_{learn.arch}.xml')\n    compiled_model = core.compile_model(openvino_model, device_name=\"CPU\")\n    infer_request = compiled_model.create_infer_request()\n    return infer_request","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:24.663208Z","iopub.execute_input":"2024-04-19T16:13:24.663765Z","iopub.status.idle":"2024-04-19T16:13:24.672728Z","shell.execute_reply.started":"2024-04-19T16:13:24.663725Z","shell.execute_reply":"2024-04-19T16:13:24.671182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def infer_xml(infer_request):\n    infer_outputs = []\n\n    for batch in tst_dl:\n        x = batch[0]\n        n_pad = 0\n\n        if x.shape[0] < 64:\n            n_pad = 64 - x.shape[0]\n            zero_tensor = torch.zeros((n_pad, 1, 128, 626))\n            x = torch.cat([x, zero_tensor], dim=0)\n\n        outputs = infer_request.infer(inputs=x.numpy())[0]\n        outputs = scipy.special.softmax(outputs[:64-n_pad, ...], axis=1)\n        infer_outputs.append(torch.tensor(outputs))\n        \n    return infer_outputs","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:24.674869Z","iopub.execute_input":"2024-04-19T16:13:24.675350Z","iopub.status.idle":"2024-04-19T16:13:24.694815Z","shell.execute_reply.started":"2024-04-19T16:13:24.675314Z","shell.execute_reply":"2024-04-19T16:13:24.693000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"infer_request = create_infer_request(learn)\n\nstart_time = time.time()\n\nall_batch_outputs = infer_xml(infer_request)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} fp32 .xml inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:24.696427Z","iopub.execute_input":"2024-04-19T16:13:24.696907Z","iopub.status.idle":"2024-04-19T16:13:44.741549Z","shell.execute_reply.started":"2024-04-19T16:13:24.696866Z","shell.execute_reply":"2024-04-19T16:13:44.740253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:44.743769Z","iopub.execute_input":"2024-04-19T16:13:44.744445Z","iopub.status.idle":"2024-04-19T16:13:44.752532Z","shell.execute_reply.started":"2024-04-19T16:13:44.744410Z","shell.execute_reply":"2024-04-19T16:13:44.751347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} fp32 .xml');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:13:44.754061Z","iopub.execute_input":"2024-04-19T16:13:44.754444Z","iopub.status.idle":"2024-04-19T16:13:47.143313Z","shell.execute_reply.started":"2024-04-19T16:13:44.754408Z","shell.execute_reply":"2024-04-19T16:13:47.142050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There is no loss of information in the fp32 .xml.","metadata":{}},{"cell_type":"markdown","source":"## ResNet26d: f16 XML Inference","metadata":{}},{"cell_type":"code","source":"!rm birdclef24_resnet26d.xml\n!rm birdclef24_resnet26d.bin","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:15:23.361321Z","iopub.execute_input":"2024-04-19T16:15:23.361831Z","iopub.status.idle":"2024-04-19T16:15:25.800476Z","shell.execute_reply.started":"2024-04-19T16:15:23.361799Z","shell.execute_reply":"2024-04-19T16:15:25.798545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mo --input_model {fname} --compress_to_fp16=True","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:15:25.804747Z","iopub.execute_input":"2024-04-19T16:15:25.805293Z","iopub.status.idle":"2024-04-19T16:15:31.169987Z","shell.execute_reply.started":"2024-04-19T16:15:25.805249Z","shell.execute_reply":"2024-04-19T16:15:31.168548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"infer_request = create_infer_request(learn)\n\nstart_time = time.time()\n\nall_batch_outputs = infer_xml(infer_request)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} fp16 .xml inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:15:31.172292Z","iopub.execute_input":"2024-04-19T16:15:31.173059Z","iopub.status.idle":"2024-04-19T16:15:50.857076Z","shell.execute_reply.started":"2024-04-19T16:15:31.172888Z","shell.execute_reply":"2024-04-19T16:15:50.855044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:15:50.862424Z","iopub.execute_input":"2024-04-19T16:15:50.863870Z","iopub.status.idle":"2024-04-19T16:15:50.873443Z","shell.execute_reply.started":"2024-04-19T16:15:50.863821Z","shell.execute_reply":"2024-04-19T16:15:50.872309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} fp16 .xml');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:15:50.875002Z","iopub.execute_input":"2024-04-19T16:15:50.876340Z","iopub.status.idle":"2024-04-19T16:15:53.687770Z","shell.execute_reply.started":"2024-04-19T16:15:50.876291Z","shell.execute_reply":"2024-04-19T16:15:53.686408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There's a slight loss of information in fp16 .xml format.","metadata":{}},{"cell_type":"markdown","source":"## ResNet34: Baseline Inference","metadata":{}},{"cell_type":"code","source":"learn = learners['resnet34']","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:15:53.689394Z","iopub.execute_input":"2024-04-19T16:15:53.689798Z","iopub.status.idle":"2024-04-19T16:15:53.695338Z","shell.execute_reply.started":"2024-04-19T16:15:53.689764Z","shell.execute_reply":"2024-04-19T16:15:53.694187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# time how long it takes to calculate predictions on 240 chunks\nstart_time = time.time()\n\nwith learn.no_bar(), learn.no_logging(): probs,_= learn.get_preds(dl=tst_dl)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} baseline inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:15:53.697136Z","iopub.execute_input":"2024-04-19T16:15:53.697835Z","iopub.status.idle":"2024-04-19T16:16:31.237877Z","shell.execute_reply.started":"2024-04-19T16:15:53.697799Z","shell.execute_reply":"2024-04-19T16:16:31.236749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"probs.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:16:31.239805Z","iopub.execute_input":"2024-04-19T16:16:31.240219Z","iopub.status.idle":"2024-04-19T16:16:31.249350Z","shell.execute_reply.started":"2024-04-19T16:16:31.240183Z","shell.execute_reply":"2024-04-19T16:16:31.248007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ResNet34: ONNX Inference","metadata":{}},{"cell_type":"code","source":"onnx_session = create_onnx(learn, input_tensor, input_names, output_names)\n\n# time how long it takes to calculate predictions on 240 chunks\nstart_time = time.time()\n\nall_batch_outputs = infer_onnx(onnx_session, input_names, output_names)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} .onnx inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:16:31.251537Z","iopub.execute_input":"2024-04-19T16:16:31.252411Z","iopub.status.idle":"2024-04-19T16:17:07.800901Z","shell.execute_reply.started":"2024-04-19T16:16:31.252355Z","shell.execute_reply":"2024-04-19T16:17:07.799198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:17:07.805906Z","iopub.execute_input":"2024-04-19T16:17:07.806668Z","iopub.status.idle":"2024-04-19T16:17:07.815658Z","shell.execute_reply.started":"2024-04-19T16:17:07.806625Z","shell.execute_reply":"2024-04-19T16:17:07.814575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} .onnx');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:17:07.817116Z","iopub.execute_input":"2024-04-19T16:17:07.818483Z","iopub.status.idle":"2024-04-19T16:17:10.298738Z","shell.execute_reply.started":"2024-04-19T16:17:07.818446Z","shell.execute_reply":"2024-04-19T16:17:10.296998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"No loss information with .onnx.","metadata":{}},{"cell_type":"markdown","source":"## ResNet34: fp32 XML Inference","metadata":{}},{"cell_type":"code","source":"fname = f\"birdclef24_{learn.arch}.onnx\"\n!mo --input_model {fname} --compress_to_fp16=False","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:17:10.300322Z","iopub.execute_input":"2024-04-19T16:17:10.300683Z","iopub.status.idle":"2024-04-19T16:17:15.660680Z","shell.execute_reply.started":"2024-04-19T16:17:10.300653Z","shell.execute_reply":"2024-04-19T16:17:15.659366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"infer_request = create_infer_request(learn)\n\nstart_time = time.time()\n\nall_batch_outputs = infer_xml(infer_request)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} fp32 .xml inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:17:15.663031Z","iopub.execute_input":"2024-04-19T16:17:15.663666Z","iopub.status.idle":"2024-04-19T16:17:39.029844Z","shell.execute_reply.started":"2024-04-19T16:17:15.663607Z","shell.execute_reply":"2024-04-19T16:17:39.028351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:17:39.032010Z","iopub.execute_input":"2024-04-19T16:17:39.032470Z","iopub.status.idle":"2024-04-19T16:17:39.042325Z","shell.execute_reply.started":"2024-04-19T16:17:39.032434Z","shell.execute_reply":"2024-04-19T16:17:39.040693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} fp32 .xml');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:17:39.044225Z","iopub.execute_input":"2024-04-19T16:17:39.044693Z","iopub.status.idle":"2024-04-19T16:17:41.437648Z","shell.execute_reply.started":"2024-04-19T16:17:39.044656Z","shell.execute_reply":"2024-04-19T16:17:41.436375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"No loss information with fp32 .xml.","metadata":{}},{"cell_type":"markdown","source":"## ResNet34: fp16 XML Inference","metadata":{}},{"cell_type":"code","source":"!rm birdclef24_resnet34.xml\n!rm birdclef24_resnet34.bin\n!mo --input_model {fname} --compress_to_fp16=True","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:19:28.814368Z","iopub.execute_input":"2024-04-19T16:19:28.814862Z","iopub.status.idle":"2024-04-19T16:19:36.429795Z","shell.execute_reply.started":"2024-04-19T16:19:28.814830Z","shell.execute_reply":"2024-04-19T16:19:36.427890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"infer_request = create_infer_request(learn)\n\nstart_time = time.time()\n\nall_batch_outputs = infer_xml(infer_request)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} fp16 .xml inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:19:36.432670Z","iopub.execute_input":"2024-04-19T16:19:36.433146Z","iopub.status.idle":"2024-04-19T16:20:00.481533Z","shell.execute_reply.started":"2024-04-19T16:19:36.433105Z","shell.execute_reply":"2024-04-19T16:20:00.479627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:20:00.484528Z","iopub.execute_input":"2024-04-19T16:20:00.485020Z","iopub.status.idle":"2024-04-19T16:20:00.493877Z","shell.execute_reply.started":"2024-04-19T16:20:00.484976Z","shell.execute_reply":"2024-04-19T16:20:00.492348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} fp16 .xml');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:20:00.497468Z","iopub.execute_input":"2024-04-19T16:20:00.497891Z","iopub.status.idle":"2024-04-19T16:20:03.011126Z","shell.execute_reply.started":"2024-04-19T16:20:00.497846Z","shell.execute_reply":"2024-04-19T16:20:03.009805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"markdown","source":"## ResNet50: Baseline Inference","metadata":{}},{"cell_type":"code","source":"learn = learners['resnet50']\n\n# time how long it takes to calculate predictions on 240 chunks\nstart_time = time.time()\n\nwith learn.no_bar(), learn.no_logging(): probs,_= learn.get_preds(dl=tst_dl)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} baseline inference: {total_time:.2f} seconds\")\nprint(probs.shape)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:20:03.012716Z","iopub.execute_input":"2024-04-19T16:20:03.013173Z","iopub.status.idle":"2024-04-19T16:21:07.871148Z","shell.execute_reply.started":"2024-04-19T16:20:03.013132Z","shell.execute_reply":"2024-04-19T16:21:07.869562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ResNet50: ONNX Inference","metadata":{}},{"cell_type":"code","source":"onnx_session = create_onnx(learn, input_tensor, input_names, output_names)\n\n# time how long it takes to calculate predictions on 240 chunks\nstart_time = time.time()\n\nall_batch_outputs = infer_onnx(onnx_session, input_names, output_names)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} .onnx inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:21:07.876951Z","iopub.execute_input":"2024-04-19T16:21:07.879260Z","iopub.status.idle":"2024-04-19T16:22:02.270511Z","shell.execute_reply.started":"2024-04-19T16:21:07.878982Z","shell.execute_reply":"2024-04-19T16:22:02.268924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:22:02.272876Z","iopub.execute_input":"2024-04-19T16:22:02.274664Z","iopub.status.idle":"2024-04-19T16:22:02.284021Z","shell.execute_reply.started":"2024-04-19T16:22:02.274620Z","shell.execute_reply":"2024-04-19T16:22:02.282774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} .onnx');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:22:02.285639Z","iopub.execute_input":"2024-04-19T16:22:02.287182Z","iopub.status.idle":"2024-04-19T16:22:04.861894Z","shell.execute_reply.started":"2024-04-19T16:22:02.287140Z","shell.execute_reply":"2024-04-19T16:22:04.860280Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ResNet50: fp32 XML Inference","metadata":{}},{"cell_type":"code","source":"fname = f\"birdclef24_{learn.arch}.onnx\"\n!mo --input_model {fname} --compress_to_fp16=False","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:22:04.864382Z","iopub.execute_input":"2024-04-19T16:22:04.864861Z","iopub.status.idle":"2024-04-19T16:22:10.373222Z","shell.execute_reply.started":"2024-04-19T16:22:04.864824Z","shell.execute_reply":"2024-04-19T16:22:10.371823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"infer_request = create_infer_request(learn)\n\nstart_time = time.time()\n\nall_batch_outputs = infer_xml(infer_request)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} fp32 .xml inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:22:10.380034Z","iopub.execute_input":"2024-04-19T16:22:10.380512Z","iopub.status.idle":"2024-04-19T16:22:39.589437Z","shell.execute_reply.started":"2024-04-19T16:22:10.380474Z","shell.execute_reply":"2024-04-19T16:22:39.587488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:22:39.592131Z","iopub.execute_input":"2024-04-19T16:22:39.592582Z","iopub.status.idle":"2024-04-19T16:22:39.602256Z","shell.execute_reply.started":"2024-04-19T16:22:39.592544Z","shell.execute_reply":"2024-04-19T16:22:39.600688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} fp32 .xml');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:22:39.604280Z","iopub.execute_input":"2024-04-19T16:22:39.604748Z","iopub.status.idle":"2024-04-19T16:22:41.972325Z","shell.execute_reply.started":"2024-04-19T16:22:39.604706Z","shell.execute_reply":"2024-04-19T16:22:41.970608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ResNet50: fp16 XML Inference","metadata":{}},{"cell_type":"code","source":"!rm birdclef24_resnet50.xml\n!rm birdclef24_resnet50.bin\n!mo --input_model {fname} --compress_to_fp16=True","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:24:14.273161Z","iopub.execute_input":"2024-04-19T16:24:14.273926Z","iopub.status.idle":"2024-04-19T16:24:22.462135Z","shell.execute_reply.started":"2024-04-19T16:24:14.273881Z","shell.execute_reply":"2024-04-19T16:24:22.460751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"infer_request = create_infer_request(learn)\n\nstart_time = time.time()\n\nall_batch_outputs = infer_xml(infer_request)\n\nend_time = time.time()\ntotal_time = end_time - start_time\n\nprint(f\"{learn.arch} fp16 .xml inference: {total_time:.2f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:24:22.465554Z","iopub.execute_input":"2024-04-19T16:24:22.466439Z","iopub.status.idle":"2024-04-19T16:24:51.885514Z","shell.execute_reply.started":"2024-04-19T16:24:22.466399Z","shell.execute_reply":"2024-04-19T16:24:51.884170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t = torch.cat(all_batch_outputs)\nt.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:24:51.887718Z","iopub.execute_input":"2024-04-19T16:24:51.888606Z","iopub.status.idle":"2024-04-19T16:24:51.897615Z","shell.execute_reply.started":"2024-04-19T16:24:51.888552Z","shell.execute_reply":"2024-04-19T16:24:51.896494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_corr(t, probs, f'{learn.arch} fp16 .xml');","metadata":{"execution":{"iopub.status.busy":"2024-04-19T16:24:51.900135Z","iopub.execute_input":"2024-04-19T16:24:51.900785Z","iopub.status.idle":"2024-04-19T16:24:54.642761Z","shell.execute_reply.started":"2024-04-19T16:24:51.900751Z","shell.execute_reply":"2024-04-19T16:24:54.641073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There is significantly more loss in the fp16 .xml model for ResNet50 than the smaller models.","metadata":{}}]}