From bcd575e9bb32924cdd017d1cc67a466a84b9f407 Mon Sep 17 00:00:00 2001 From: jh-206 Date: Fri, 2 Aug 2024 10:33:06 -0600 Subject: [PATCH] Update rnn_train_versions.ipynb Remove old reproducibility case, not needed anymore --- fmda/version_control/rnn_train_versions.ipynb | 798 +++++++++----------------- 1 file changed, 259 insertions(+), 539 deletions(-) rewrite fmda/version_control/rnn_train_versions.ipynb (65%) diff --git a/fmda/version_control/rnn_train_versions.ipynb b/fmda/version_control/rnn_train_versions.ipynb dissimilarity index 65% index 5d3bb29..5e7bf33 100644 --- a/fmda/version_control/rnn_train_versions.ipynb +++ b/fmda/version_control/rnn_train_versions.ipynb @@ -1,539 +1,259 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e20166f4-1a8b-4471-a9a9-e944cc4b1087", - "metadata": {}, - "source": [ - "# Getting same hash with v1 (Boise) and v2 (classes)\n", - "See the comments in the commit before PR#11 for details" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8530bc7e-61ae-4463-a14f-d5eb42f0b83e", - "metadata": {}, - "outputs": [], - "source": [ - "# Environment\n", - "import numpy as np\n", - "import pandas as pd\n", - "import tensorflow as tf\n", - "import matplotlib.pyplot as plt\n", - "import sys\n", - "# Local modules\n", - "sys.path.append('..')\n", - "from moisture_rnn import RNN\n", - "import reproducibility\n", - "from utils import print_dict_summary\n", - "from data_funcs import load_and_fix_data, rmse\n", - "from moisture_rnn0 import run_case\n", - "from moisture_rnn_pkl import pkl2train\n", - "from utils import hash2" - ] - }, - { - "cell_type": "markdown", - "id": "63d275da-b13a-405e-9e1a-aa3f972119b5", - "metadata": {}, - "source": [ - "### Reproducibility Datasets" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2dfa08fa-01c9-4fd7-927b-541b0a532e4f", - "metadata": {}, - "outputs": [], - "source": [ - "# Original File\n", - "reproducibility_file='reproducibility_dict0.pickle'\n", - "\n", - "repro={}\n", - "repro.update(load_and_fix_data(reproducibility_file))\n", - "print_dict_summary(repro)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f5f4c46a-6e9f-46a0-86e7-3503b83d1816", - "metadata": {}, - "outputs": [], - "source": [ - "# Restructured original file\n", - "reproducibility_file='../data/reproducibility_dict2.pickle'\n", - "repro2 = pkl2train([reproducibility_file])\n", - "print_dict_summary(repro2)" - ] - }, - { - "cell_type": "markdown", - "id": "87f59db1-fa7b-44f4-bbe4-7e49221226e9", - "metadata": {}, - "source": [ - "## RNN with Stateful Batch Training\n" - ] - }, - { - "cell_type": "markdown", - "id": "d135d6e5-505c-474b-8ed6-b70a37691b2c", - "metadata": {}, - "source": [ - "### Custom Class" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4ede9568-cbfa-41b1-ab93-69155344383a", - "metadata": {}, - "outputs": [], - "source": [ - "from moisture_rnn import create_rnn_data2, RNN\n", - "import logging\n", - "from utils import logging_setup\n", - "logging_setup()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e84f8219-3f71-43d2-b159-4f200a7cf1c0", - "metadata": {}, - "outputs": [], - "source": [ - "import yaml\n", - "\n", - "with open(\"../params.yaml\") as file:\n", - " params = yaml.safe_load(file)[\"rnn_repro\"]\n", - "# params.update({'scale': 1})\n", - "params" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "749a4a1c-e3b7-4a6c-9305-ed2349ca7647", - "metadata": {}, - "outputs": [], - "source": [ - "rnn_dat = create_rnn_data2(repro2[\"reproducibility\"], params)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "458ea3bb-2b19-42b3-8ac8-fdec96c6d315", - "metadata": {}, - "outputs": [], - "source": [ - "reproducibility.set_seed()\n", - "rnn = RNN(params)\n", - "m, errs = rnn.run_model(rnn_dat)" - ] - }, - { - "cell_type": "markdown", - "id": "d4103c38-e067-4e72-a694-27080fa5265e", - "metadata": {}, - "source": [ - "### Physics Initialized" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "383e2870-a581-4ac2-8669-f16ac41a64a4", - "metadata": {}, - "outputs": [], - "source": [ - "params.update({'phys_initialize': True})\n", - "reproducibility.set_seed()\n", - "rnn = RNN(params)\n", - "m, errs = rnn.run_model(rnn_dat)" - ] - }, - { - "cell_type": "markdown", - "id": "a5ee76d9-2a0f-4bca-9fef-5d0f9361a02d", - "metadata": {}, - "source": [ - "### Using Old Code with `run_case`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6875a379-bf28-438a-b7fc-d5f81879b26f", - "metadata": {}, - "outputs": [], - "source": [ - "from module_param_sets0 import param_sets\n", - "params = param_sets['0']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "29596ede-689a-4629-8f07-412289e51122", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "reproducibility.set_seed()\n", - "params['initialize']=False \n", - "case = 'case11'\n", - "case_data=repro[case]\n", - "case_data['h2']=427\n", - "run_case(case_data,params)" - ] - }, - { - "cell_type": "markdown", - "id": "f67940bd-3540-455c-862d-60d7818973eb", - "metadata": {}, - "source": [ - "### Physics Initialized" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "56452fc3-3043-4882-b6bf-29cef45ed88b", - "metadata": {}, - "outputs": [], - "source": [ - "from module_param_sets0 import param_sets\n", - "params = param_sets['0']\n", - "params['verbose_weights']=True\n", - "reproducibility.set_seed()\n", - "params['initialize']=True \n", - "case = 'case11'\n", - "case_data=repro[case]\n", - "case_data['h2']=427\n", - "run_case(case_data,params)" - ] - }, - { - "cell_type": "markdown", - "id": "1cad6dcd-7a0a-4afb-aec7-6cd5aa7ee568", - "metadata": {}, - "source": [ - "## Original Case - Single Batch" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "db563737-4aa8-409a-a3f2-86495678ba2b", - "metadata": {}, - "outputs": [], - "source": [ - "# NOTE: original param sets live in model_param_sets0 but commented out, manually reproducing here\n", - "param_sets_ORIG = {'id':0,\n", - " 'purpose':'reproducibility',\n", - " 'batch_size':np.inf,\n", - " 'training':None,\n", - " 'cases':['case11'],\n", - " 'scale':0,\n", - " 'rain_do':False,\n", - "# 'verbose':False,\n", - " 'verbose':1,\n", - " 'timesteps':5,\n", - " 'activation':['linear','linear'],\n", - " 'centering':[0.0,0.0],\n", - " 'hidden_units':6,\n", - " 'dense_units':1,\n", - " 'dense_layers':1,\n", - " 'DeltaE':[0,-1], # -1.0 is to correct E bias but put at the end\n", - " 'synthetic':False, # run also synthetic cases\n", - " 'T1': 0.1, # 1/fuel class (10)\n", - " 'fm_raise_vs_rain': 2.0, # fm increase per mm rain \n", - " 'epochs':5000,\n", - " 'verbose_fit':0,\n", - " 'verbose_weights':True,\n", - " 'note':'check 5 should give zero error'\n", - " }" - ] - }, - { - "cell_type": "markdown", - "id": "785d0e34-35c7-4a8d-802d-4a176e2c19bd", - "metadata": {}, - "source": [ - "### Using Old RNN Code\n", - "\n", - "Code is deployed through the `run_case` function." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "49cb8274-7c1a-40c0-ad81-d1fbcb498884", - "metadata": {}, - "outputs": [], - "source": [ - "reproducibility.set_seed()\n", - "print('Running reproducibility')\n", - "assert param_sets_ORIG['purpose'] == 'reproducibility'\n", - "param_sets_ORIG['initialize']=False \n", - "case = 'case11'\n", - "case_data=repro[case]\n", - "case_data[\"h2\"]=300\n", - "run_case(case_data,param_sets_ORIG)" - ] - }, - { - "cell_type": "markdown", - "id": "6ddef6dc-c56b-4257-b603-783001a94262", - "metadata": {}, - "source": [ - "### Reproduce with Class Code\n", - "\n", - "Code deployed through custom class, and parameters come from yaml file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "05cc8cf3-48db-44df-9649-4a453a271957", - "metadata": {}, - "outputs": [], - "source": [ - "from tensorflow.keras.callbacks import Callback\n", - "from abc import ABC, abstractmethod\n", - "class ResetStatesCallback(Callback):\n", - " def on_epoch_end(self, epoch, logs=None):\n", - " self.model.reset_states()\n", - " \n", - "from sklearn.metrics import mean_squared_error\n", - "def rmse(a, b):\n", - " return np.sqrt(mean_squared_error(a.flatten(), b.flatten()))\n", - "\n", - "\n", - "class RNNModel(ABC):\n", - " def __init__(self, params: dict):\n", - " self.params = params\n", - " if type(self) is RNNModel:\n", - " raise TypeError(\"MLModel is an abstract class and cannot be instantiated directly\")\n", - " super().__init__()\n", - "\n", - " @abstractmethod\n", - " def fit(self, X_train, y_train, weights=None):\n", - " pass\n", - "\n", - " @abstractmethod\n", - " def predict(self, X):\n", - " pass\n", - "\n", - "class RNN(RNNModel):\n", - " def __init__(self, params, loss='mean_squared_error'):\n", - " super().__init__(params)\n", - " self.model_train = self._build_model_train()\n", - " self.model_predict = self._build_model_predict()\n", - " # self.compile_model()\n", - "\n", - " def _build_model_train(self, return_sequences=False):\n", - " inputs = tf.keras.Input(batch_shape=self.params['batch_shape'])\n", - " x = inputs\n", - " for i in range(self.params['rnn_layers']):\n", - " x = tf.keras.layers.SimpleRNN(self.params['rnn_units'],activation=self.params['activation'][0],\n", - " stateful=self.params['stateful'],return_sequences=return_sequences)(x)\n", - " for i in range(self.params['dense_layers']):\n", - " x = tf.keras.layers.Dense(self.params['dense_units'], activation=self.params['activation'][1])(x)\n", - " model = tf.keras.Model(inputs=inputs, outputs=x)\n", - " model.compile(loss='mean_squared_error', optimizer='adam')\n", - " if self.params[\"verbose_weights\"]:\n", - " print(f\"Initial Weights Hash: {hash2(model.get_weights())}\")\n", - " \n", - " return model\n", - " def _build_model_predict(self, return_sequences=True):\n", - " \n", - " inputs = tf.keras.Input(shape=self.params['pred_input_shape'])\n", - " x = inputs\n", - " for i in range(self.params['rnn_layers']):\n", - " x = tf.keras.layers.SimpleRNN(self.params['rnn_units'],activation=self.params['activation'][0],\n", - " stateful=False,return_sequences=return_sequences)(x)\n", - " for i in range(self.params['dense_layers']):\n", - " x = tf.keras.layers.Dense(self.params['dense_units'], activation=self.params['activation'][1])(x)\n", - " model = tf.keras.Model(inputs=inputs, outputs=x)\n", - " model.compile(loss='mean_squared_error', optimizer='adam') \n", - "\n", - " # Set Weights to model_train\n", - " w_fitted = self.model_train.get_weights()\n", - " model.set_weights(w_fitted)\n", - " \n", - " return model\n", - "\n", - " def fit(self, X_train, y_train, plot=True, weights=None, callbacks=[], verbose_fit=None):\n", - " # verbose_fit argument is for printing out update after each epoch, which gets very long\n", - " # These print statements at the top could be turned off with a verbose argument, but then\n", - " # there would be a bunch of different verbose params\n", - " print(f\"Training simple RNN with params: {self.params}\")\n", - " print(f\"X_train hash: {hash2(X_train)}\")\n", - " print(f\"y_train hash: {hash2(y_train)}\")\n", - " print(f\"Initial weights before training hash: {hash2(self.model_train.get_weights())}\")\n", - " # Note: we overload the params here so that verbose_fit can be easily turned on/off at the .fit call \n", - " if verbose_fit is None:\n", - " verbose_fit = self.params['verbose_fit']\n", - " # Evaluate Model once to set nonzero initial state\n", - " if self.params[\"batch_size\"]>= X_train.shape[0]:\n", - " self.model_train(X_train)\n", - " # Fit Model\n", - " history = self.model_train.fit(\n", - " X_train, y_train+self.params['centering'][1], \n", - " epochs=self.params['epochs'], \n", - " batch_size=self.params['batch_size'],\n", - " callbacks = callbacks,\n", - " verbose=verbose_fit)\n", - " if plot:\n", - " self.plot_history(history)\n", - " if self.params[\"verbose_weights\"]:\n", - " print(f\"Fitted Weights Hash: {hash2(self.model_train.get_weights())}\")\n", - "\n", - " # Update Weights for Prediction Model\n", - " w_fitted = self.model_train.get_weights()\n", - " self.model_predict.set_weights(w_fitted)\n", - " def predict(self, X_test):\n", - " print(\"Predicting with simple RNN\")\n", - " preds = self.model_predict.predict(X_test)\n", - " return preds\n", - " def plot_history(self, history):\n", - " plt.semilogy(history.history['loss'], label='Training loss')\n", - " if 'val_loss' in history.history:\n", - " plt.semilogy(history.history['val_loss'], label='Validation loss')\n", - " plt.title(case + ' Model loss')\n", - " plt.ylabel('Loss')\n", - " plt.xlabel('Epoch')\n", - " plt.legend(loc='upper left')\n", - " plt.show()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "73243595-fa7c-426e-a4ca-ee3395e3e740", - "metadata": {}, - "outputs": [], - "source": [ - "import yaml\n", - "\n", - "with open(\"../params.yaml\") as file:\n", - " params = yaml.safe_load(file)[\"rnn\"]\n", - "\n", - "params.update({\n", - " 'dropout': [0, 0], # NOTE: length must match total number of layers, default is 1 hidden recurrent layer and 1 dense output layer\n", - " 'recurrent_dropout': 0, # Length must match number of recurrent layers\n", - "})" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9507496c-d9d1-4b18-a05f-af3143d2f9e6", - "metadata": {}, - "outputs": [], - "source": [ - "N = len(repro[case][\"fm\"]) # total observations\n", - "train_ind = repro[case]['h2']\n", - "\n", - "X = np.vstack((repro[case][\"Ed\"], repro[case][\"Ew\"])).T\n", - "y = repro[case][\"fm\"]\n", - "\n", - "X_train = X[:train_ind]\n", - "X_test = X[train_ind:]\n", - "y_train = y[:train_ind].reshape(-1,1)\n", - "y_test = y[train_ind:].reshape(-1,1)\n", - "\n", - "print(f\"Total Observations: {N}\")\n", - "print(f\"Num Training: {X_train.shape[0]}\")\n", - "print(f\"Num Test: {X_test.shape[0]}\")\n", - "\n", - "from moisture_rnn import staircase\n", - "X_train, y_train = staircase(X_train, y_train, timesteps = params[\"timesteps\"], datapoints = len(y_train), verbose=True)\n", - "print(\"~\"*50)\n", - "phours, features = X_test.shape\n", - "X_test = np.reshape(X_test,(1, phours, features))\n", - "print(f\"X_test shape: {X_test.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "77b675d8-ac1c-473f-acf5-6682bfb2e2dd", - "metadata": {}, - "outputs": [], - "source": [ - "samples, timesteps, features = X_train.shape\n", - "batch_size = samples # Single batch for testing\n", - "\n", - "params.update({\n", - " 'batch_shape': (batch_size,timesteps,features),\n", - " 'batch_size': batch_size, # Single Batch for testing\n", - " 'pred_input_shape': (X.shape[0], X.shape[1]),\n", - " 'epochs': 5000,\n", - " 'stateful': True,\n", - " 'features': features\n", - "})" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0523b883-08e1-4158-8e07-27466f2588d5", - "metadata": {}, - "outputs": [], - "source": [ - "reproducibility.set_seed()\n", - "rnn = RNN(params)\n", - "m = rnn.predict(np.reshape(X,(1, X.shape[0], features)))\n", - "print(hash2(m))\n", - "rnn.fit(X_train, y_train)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "773c5c20-1278-47e7-9b69-08065fb7bc8b", - "metadata": {}, - "outputs": [], - "source": [ - "preds = rnn.predict(np.reshape(X,(1, X.shape[0], features)))\n", - "rmse(preds, y)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9bfbd951-c89a-4b69-be94-7ac4783f5eb7", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e20166f4-1a8b-4471-a9a9-e944cc4b1087", + "metadata": {}, + "source": [ + "# Getting same hash with v1 (Boise) and v2 (classes)\n", + "See the comments in the commit before PR#11 for details" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8530bc7e-61ae-4463-a14f-d5eb42f0b83e", + "metadata": {}, + "outputs": [], + "source": [ + "# Environment\n", + "import numpy as np\n", + "import pandas as pd\n", + "import tensorflow as tf\n", + "import matplotlib.pyplot as plt\n", + "import sys\n", + "# Local modules\n", + "sys.path.append('..')\n", + "from moisture_rnn import RNN\n", + "import reproducibility\n", + "from utils import print_dict_summary\n", + "from data_funcs import load_and_fix_data, rmse\n", + "from moisture_rnn0 import run_case\n", + "from moisture_rnn_pkl import pkl2train\n", + "from utils import hash2" + ] + }, + { + "cell_type": "markdown", + "id": "63d275da-b13a-405e-9e1a-aa3f972119b5", + "metadata": {}, + "source": [ + "### Reproducibility Datasets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2dfa08fa-01c9-4fd7-927b-541b0a532e4f", + "metadata": {}, + "outputs": [], + "source": [ + "# Original File\n", + "reproducibility_file='reproducibility_dict0.pickle'\n", + "\n", + "repro={}\n", + "repro.update(load_and_fix_data(reproducibility_file))\n", + "print_dict_summary(repro)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5f4c46a-6e9f-46a0-86e7-3503b83d1816", + "metadata": {}, + "outputs": [], + "source": [ + "# Restructured original file\n", + "reproducibility_file='../data/reproducibility_dict2.pickle'\n", + "repro2 = pkl2train([reproducibility_file])\n", + "print_dict_summary(repro2)" + ] + }, + { + "cell_type": "markdown", + "id": "87f59db1-fa7b-44f4-bbe4-7e49221226e9", + "metadata": {}, + "source": [ + "## RNN with Stateful Batch Training\n" + ] + }, + { + "cell_type": "markdown", + "id": "d135d6e5-505c-474b-8ed6-b70a37691b2c", + "metadata": {}, + "source": [ + "### Custom Class" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ede9568-cbfa-41b1-ab93-69155344383a", + "metadata": {}, + "outputs": [], + "source": [ + "from moisture_rnn import create_rnn_data2, RNN\n", + "import logging\n", + "from utils import logging_setup\n", + "logging_setup()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e84f8219-3f71-43d2-b159-4f200a7cf1c0", + "metadata": {}, + "outputs": [], + "source": [ + "import yaml\n", + "\n", + "with open(\"../params.yaml\") as file:\n", + " params = yaml.safe_load(file)[\"rnn_repro\"]\n", + "# params.update({'scale': 1})\n", + "params" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "749a4a1c-e3b7-4a6c-9305-ed2349ca7647", + "metadata": {}, + "outputs": [], + "source": [ + "rnn_dat = create_rnn_data2(repro2[\"reproducibility\"], params)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "458ea3bb-2b19-42b3-8ac8-fdec96c6d315", + "metadata": {}, + "outputs": [], + "source": [ + "reproducibility.set_seed()\n", + "rnn = RNN(params)\n", + "m, errs = rnn.run_model(rnn_dat)" + ] + }, + { + "cell_type": "markdown", + "id": "d4103c38-e067-4e72-a694-27080fa5265e", + "metadata": {}, + "source": [ + "### Physics Initialized" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "383e2870-a581-4ac2-8669-f16ac41a64a4", + "metadata": {}, + "outputs": [], + "source": [ + "params.update({'phys_initialize': True})\n", + "reproducibility.set_seed()\n", + "rnn = RNN(params)\n", + "m, errs = rnn.run_model(rnn_dat)" + ] + }, + { + "cell_type": "markdown", + "id": "a5ee76d9-2a0f-4bca-9fef-5d0f9361a02d", + "metadata": {}, + "source": [ + "### Using Old Code with `run_case`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6875a379-bf28-438a-b7fc-d5f81879b26f", + "metadata": {}, + "outputs": [], + "source": [ + "from module_param_sets0 import param_sets\n", + "params = param_sets['0']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29596ede-689a-4629-8f07-412289e51122", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "reproducibility.set_seed()\n", + "params['initialize']=False \n", + "case = 'case11'\n", + "case_data=repro[case]\n", + "case_data['h2']=427\n", + "run_case(case_data,params)" + ] + }, + { + "cell_type": "markdown", + "id": "f67940bd-3540-455c-862d-60d7818973eb", + "metadata": {}, + "source": [ + "### Physics Initialized" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56452fc3-3043-4882-b6bf-29cef45ed88b", + "metadata": {}, + "outputs": [], + "source": [ + "from module_param_sets0 import param_sets\n", + "params = param_sets['0']\n", + "params['verbose_weights']=True\n", + "reproducibility.set_seed()\n", + "params['initialize']=True \n", + "case = 'case11'\n", + "case_data=repro[case]\n", + "case_data['h2']=427\n", + "run_case(case_data,params)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "33584d39-cd5d-4613-b330-48ab960cb42e", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9bfbd951-c89a-4b69-be94-7ac4783f5eb7", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- 2.11.4.GIT