{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":30746,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-24T14:12:54.263410Z","iopub.execute_input":"2024-07-24T14:12:54.263797Z","iopub.status.idle":"2024-07-24T14:12:54.273997Z","shell.execute_reply.started":"2024-07-24T14:12:54.263771Z","shell.execute_reply":"2024-07-24T14:12:54.272870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# データの準備！！！！！\n## まず解凍するよ🧊🔥","metadata":{}},{"cell_type":"code","source":"import zipfile # ZIPアーカイブを作成するためのクラス\n\n# train.zipの解凍\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/train')\n\n# test.zipの解凍\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/test')","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:12:54.275901Z","iopub.execute_input":"2024-07-24T14:12:54.276279Z","iopub.status.idle":"2024-07-24T14:13:10.830015Z","shell.execute_reply.started":"2024-07-24T14:12:54.276246Z","shell.execute_reply":"2024-07-24T14:13:10.829063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ライブラリインストール🐶😺","metadata":{}},{"cell_type":"code","source":"import numpy as np # みんな大好き numpy（Pythonでの機械学習の計算をより速く、効率的に行えるようにする拡張モジュール）\nimport pandas as pd\nimport os\nimport shutil\nimport cv2\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport tensorflow.keras as keras\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import load_model","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:10.831168Z","iopub.execute_input":"2024-07-24T14:13:10.831481Z","iopub.status.idle":"2024-07-24T14:13:10.836791Z","shell.execute_reply.started":"2024-07-24T14:13:10.831454Z","shell.execute_reply":"2024-07-24T14:13:10.835902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<font color='red'>ディレクトリ</font>はフォルダといっしょ","metadata":{}},{"cell_type":"markdown","source":"# パス管理🧚‍♀️\n- **パスとは** ファイルがどこにあるか","metadata":{}},{"cell_type":"code","source":"# trainデータのディレクトリのパスだよ\ntrain_dir = '/kaggle/working/train/train'","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:10.838210Z","iopub.execute_input":"2024-07-24T14:13:10.838613Z","iopub.status.idle":"2024-07-24T14:13:10.845830Z","shell.execute_reply.started":"2024-07-24T14:13:10.838579Z","shell.execute_reply":"2024-07-24T14:13:10.844837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# testデータのディレクトリのパスだよ\ntest_dir = '/kaggle/working/test/test'","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:10.848740Z","iopub.execute_input":"2024-07-24T14:13:10.849494Z","iopub.status.idle":"2024-07-24T14:13:10.854578Z","shell.execute_reply.started":"2024-07-24T14:13:10.849461Z","shell.execute_reply":"2024-07-24T14:13:10.853693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 一応画像サイズ統一しとく","metadata":{}},{"cell_type":"code","source":"# 画像のサイズ統一\nIMG_SIZE = 64","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:10.855737Z","iopub.execute_input":"2024-07-24T14:13:10.856098Z","iopub.status.idle":"2024-07-24T14:13:10.864146Z","shell.execute_reply.started":"2024-07-24T14:13:10.856063Z","shell.execute_reply":"2024-07-24T14:13:10.863356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# データを読み込む関数作っとく\n","metadata":{}},{"cell_type":"code","source":"# データを読み込む用の関数\ndef load_data(data_dir,sample_size=1000):\n    images = [] # 写真を入れる用のリストちゃん\n    labels = [] # その写真のラベル（わんこかにゃんこか）を入れる用のリストちゃん\n    files = os.listdir(data_dir)[:sample_size] # listdirはファイルの一覧を得ることができるやつ\n#     print(f'（発見） {len(files)} files in {data_dir}')  # デバッグ文（見つけたディレクトリを表示）\n    for file in files: # for文でくるくる回してく〜\n        img_path = os.path.join(data_dir, file) # ディレクトリのパスとファイル名（写真名）をくっつけて（join）、ファイル（写真）のパスを作る。それをimg_pathに入れる\n#         print(f'（ファイル読み込み） {img_path}')  # デバッグ文（読み込んだファイルを表示）\n        img = cv2.imread(img_path) # 写真を取得〜\n        if img is not None: # もし、写真がNoneじゃなかったら（つまり、写真がきちんとあったら）\n            img = cv2.resize(img, (IMG_SIZE, IMG_SIZE)) # その写真のサイズとかを調整〜\n            images.append(img) # リストの中に一枚ずつ入れてく〜\n            label = 1 if 'dog' in file else 0 # 写真がもし、わんこなら 1, にゃんこなら 0とラベル付して\n            labels.append(label) # そのラベルをリストに入れてく〜\n        else: #　それ以外（つまり、写真がきちんと読み込めてなかったら）\n            print(f'（エラー）ファイル読み込めてねーじゃんか！！ {img_path}')  # デバッグ文（読み込めてないとエラーを吐く）\n    return np.array(images) / 255.0, np.array(labels) # かえりち（写真とラベルのリストたち）\n\n","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:10.865734Z","iopub.execute_input":"2024-07-24T14:13:10.866206Z","iopub.status.idle":"2024-07-24T14:13:10.874945Z","shell.execute_reply.started":"2024-07-24T14:13:10.866172Z","shell.execute_reply":"2024-07-24T14:13:10.873984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## trainデータとtestデータを読み込んでく","metadata":{}},{"cell_type":"code","source":"# trainデータとtestデータを読み込んでる\nX_train, y_train = load_data(train_dir,sample_size=1000)\nX_test, y_test = load_data(test_dir, sample_size=500)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:10.876245Z","iopub.execute_input":"2024-07-24T14:13:10.876874Z","iopub.status.idle":"2024-07-24T14:13:12.461783Z","shell.execute_reply.started":"2024-07-24T14:13:10.876806Z","shell.execute_reply":"2024-07-24T14:13:12.460945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 読み込んだやつの確認","metadata":{}},{"cell_type":"code","source":"# print(f'X_train shape: {X_train.shape}')","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.462926Z","iopub.execute_input":"2024-07-24T14:13:12.463228Z","iopub.status.idle":"2024-07-24T14:13:12.467302Z","shell.execute_reply.started":"2024-07-24T14:13:12.463201Z","shell.execute_reply":"2024-07-24T14:13:12.466415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print(f'y_train shape: {y_train.shape}')","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.468664Z","iopub.execute_input":"2024-07-24T14:13:12.469015Z","iopub.status.idle":"2024-07-24T14:13:12.479607Z","shell.execute_reply.started":"2024-07-24T14:13:12.468983Z","shell.execute_reply":"2024-07-24T14:13:12.478559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'X_test shape: {X_test.shape}')","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.481191Z","iopub.execute_input":"2024-07-24T14:13:12.481643Z","iopub.status.idle":"2024-07-24T14:13:12.488595Z","shell.execute_reply.started":"2024-07-24T14:13:12.481602Z","shell.execute_reply":"2024-07-24T14:13:12.487621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'y_test shape: {y_test.shape}')","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.490117Z","iopub.execute_input":"2024-07-24T14:13:12.490542Z","iopub.status.idle":"2024-07-24T14:13:12.497534Z","shell.execute_reply.started":"2024-07-24T14:13:12.490506Z","shell.execute_reply":"2024-07-24T14:13:12.496458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# データ拡張〜\ntrainデータに色々しちゃう。性能上がるかも？","metadata":{}},{"cell_type":"markdown","source":"## 何してるかのまとめ\n\n| パラメータ | 説明 |\n| :----: | :----: |\n| rotation_range=20 | Max20°まで回転するよ |\n| width_shift_range=0.2 | 水平方向にMax20%動かすよ |\n| height_shift_range=0.2 | 垂直方向にMax20%動かすよ |\n| shear_range=0.2 | 斜めに引き伸ばすよ |\n| zoom_range=0.2 | Max20%ズームするよ |\n| horizontal_flip=True | 水平方向に反転するよ |\n| fill_mode='nearest' | 変換した後の空白をどうにかするよ |\n\nこの表にあるやつは全部ランダムに行うよ","metadata":{}},{"cell_type":"code","source":"# データ拡張しとこ〜\ndatagen = ImageDataGenerator(\n    rotation_range=20,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    fill_mode='nearest'\n)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.498895Z","iopub.execute_input":"2024-07-24T14:13:12.499249Z","iopub.status.idle":"2024-07-24T14:13:12.505916Z","shell.execute_reply.started":"2024-07-24T14:13:12.499222Z","shell.execute_reply":"2024-07-24T14:13:12.504876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# モデルを作ってく","metadata":{}},{"cell_type":"markdown","source":"## モデルを作る関数作っとく\n畳み込みニューラルネットワーク","metadata":{}},{"cell_type":"code","source":"# モデルを作る\ndef create_model(neuron):\n    # ライブラリとか関数とかをインポートする\n    Dense = keras.layers.Dense\n    Conv2D = keras.layers.Conv2D\n    MaxPooling2D = keras.layers.MaxPooling2D\n    Flatten = keras.layers.Flatten\n    Dropout = keras.layers.Dropout\n    \n    # モデルを定義する\n    model = keras.models.Sequential()\n    \n    # ここから畳み込みの醍醐味。レイヤー追加してく〜\n    \n    # まず、32このフィルターと3x3のカーネルサイズを持ってる畳み込みそう。活性化関数はRelu。あと画像の形状の指定。今回は3だからカラー（あか、あお、緑）だよ\n    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)))\n    # 2x2のプーリング層。空間サイズを半分に\n    model.add(MaxPooling2D((2, 2)))\n    \n    # 次、64このフィルターと3x3のカーネルサイズを持ってる畳み込みそう。活性化関数はRelu。\n    model.add(Conv2D(64, (3, 3), activation='relu'))\n    # 2x2のプーリング層。空間サイズを半分に\n    model.add(MaxPooling2D((2, 2)))\n    \n    # 次、128このフィルターと3x3のカーネルサイズを持ってる畳み込みそう。活性化関数はRelu。\n    model.add(Conv2D(128, (3, 3), activation='relu'))\n    # 2x2のプーリング層。空間サイズを半分に\n    model.add(MaxPooling2D((2, 2)))\n    \n    # 全部の結合そうを追加　　　　　　　　\n    # Flatten(): 3次元の特徴マップを1次元のベクトルに変換\n    model.add(Flatten())\n    # neuron数のユニットを持つ全結合層。活性化関数はRelu\n    model.add(Dense(neuron, activation='relu'))\n    # ドロップアウト正則化。半分のニューロンをランダムに無効。\n    model.add(Dropout(0.5))\n    # 出力層。シグモイド\n    model.add(Dense(1, activation='sigmoid'))\n\n    # モデルをコンパイルする\n    # バイナリクロスエントロピー損失関数。Adam。モデルの評価は精度で\n    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])\n    \n    # モデルを返す\n    return model\n","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.510295Z","iopub.execute_input":"2024-07-24T14:13:12.510682Z","iopub.status.idle":"2024-07-24T14:13:12.521559Z","shell.execute_reply.started":"2024-07-24T14:13:12.510656Z","shell.execute_reply":"2024-07-24T14:13:12.520512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# モデルを保存する関数","metadata":{}},{"cell_type":"code","source":"def save_model(model, filename):\n    model.save(filename)\n    ","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.522894Z","iopub.execute_input":"2024-07-24T14:13:12.523472Z","iopub.status.idle":"2024-07-24T14:13:12.532728Z","shell.execute_reply.started":"2024-07-24T14:13:12.523437Z","shell.execute_reply":"2024-07-24T14:13:12.531922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# モデルをロードする関数","metadata":{}},{"cell_type":"code","source":"def load_existing_model(filename):\n    return load_model(filename)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.533864Z","iopub.execute_input":"2024-07-24T14:13:12.534269Z","iopub.status.idle":"2024-07-24T14:13:12.541169Z","shell.execute_reply.started":"2024-07-24T14:13:12.534232Z","shell.execute_reply":"2024-07-24T14:13:12.540431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習して〜評価して〜その評価の値を表示〜する関数","metadata":{}},{"cell_type":"markdown","source":"\n| コード | 説明 |\n| :----: | :----: |\n| datagen.flow(X_train, y_train, batch_size=batch) | trainデータをバッチごとに作る |\n| steps_per_epoch=len(X_train) // batch | 1エポックあたりのステップ数指定 |\n| validation_data=(X_test, y_test) | 検証データとしてX_test, y_test |\n| epochs=epochs | 学習に使用するエポック数を指定 |\n| verbose=1 | 学習の進行状況を表示 |","metadata":{}},{"cell_type":"code","source":"# 学習し、テストデータで評価し、スコアを表示する関数\ndef fit_epoch(neuron, batch, epochs, initial_epoch=0, model_filename='model.h5'):\n    if initial_epoch == 0: # もし、モデルを作るのが初めてなら\n        # さっき作ったモデル作る関数を実行（ニューロン数送る）\n        model = create_model(neuron)\n    else: # もうすでに作ったことがあるなら\n        model = load_existing_model(model_filename) #モデルを読み込む\n        \n    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])\n    \n    # モデルを学習する\n    hist = model.fit(datagen.flow(X_train, y_train, batch_size=batch),\n                     steps_per_epoch=len(X_train) // batch,\n                     validation_data=(X_test, y_test),\n                     epochs=epochs,\n                     initial_epoch=initial_epoch,\n                     verbose=1)\n    \n    # モデルを評価する。そしてそれをprint\n    score = model.evaluate(X_test, y_test, verbose=1)\n    print('正解率=', score[1], 'loss=', score[0])\n    \n    # モデルを保存\n    save_model(model, model_filename)\n    \n    # 学習結果を可視化、グラフ化するよ。ほら、文字全部見るのってだるいじゃん\n    \n    # trainデータの精度の流れをグラフに\n    plt.plot(hist.history['accuracy'])\n    # testデータの精度の流れをグラフに\n    plt.plot(hist.history['val_accuracy'])\n    # グラフのタイトル。あくちゅありー\n    plt.title('Accuracy')\n    # 凡例\n    plt.legend(['train', 'test'], loc='upper left')\n    # グラフの表示\n    plt.show()\n\n    # trainデータの損失値の流れをグラフに\n    plt.plot(hist.history['loss'])\n    # testデータの損失値の流れをグラフに\n    plt.plot(hist.history['val_loss'])\n    # グラフのタイトル。\n    plt.title('Loss')\n    # 凡例\n    plt.legend(['train', 'test'], loc='upper left')\n    # グラフの表示\n    plt.show()\n    ","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.542360Z","iopub.execute_input":"2024-07-24T14:13:12.542729Z","iopub.status.idle":"2024-07-24T14:13:12.553006Z","shell.execute_reply.started":"2024-07-24T14:13:12.542705Z","shell.execute_reply":"2024-07-24T14:13:12.552079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 実際にモデル作ろ〜","metadata":{}},{"cell_type":"markdown","source":"neuronは512, batchは32で固定でいいんじゃない？<br>\nただ、<br>\n- **epochs（エポック数）** は適切な数で。多くしすぎて動くならいいけど、動かない場合があるからね\n- **initial_epoch** は初めてモデル作るなら0で。\n- **model_filename** は保存してあるモデルファイルの名前で。","metadata":{}},{"cell_type":"code","source":"total_epochs = 30  # 全体のエポック数〜\nneuron = 512  # ニューロンの数〜\nbatch = 8  # バッチサイズ〜\nmodel_filename = 'model.h5'  # モデルのファイル名（モデルの拡張子は.h5だよ）","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.554089Z","iopub.execute_input":"2024-07-24T14:13:12.554966Z","iopub.status.idle":"2024-07-24T14:13:12.563460Z","shell.execute_reply.started":"2024-07-24T14:13:12.554930Z","shell.execute_reply":"2024-07-24T14:13:12.562464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 1回目の学習\nfit_epoch(neuron=neuron, batch=batch, epochs=10, initial_epoch=0, model_filename=model_filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:12.564683Z","iopub.execute_input":"2024-07-24T14:13:12.565034Z","iopub.status.idle":"2024-07-24T14:13:28.852931Z","shell.execute_reply.started":"2024-07-24T14:13:12.565002Z","shell.execute_reply":"2024-07-24T14:13:28.851166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 2回目の学習\nfit_epoch(neuron=neuron, batch=batch, epochs=20, initial_epoch=10, model_filename=model_filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:28.854187Z","iopub.execute_input":"2024-07-24T14:13:28.854583Z","iopub.status.idle":"2024-07-24T14:13:42.472387Z","shell.execute_reply.started":"2024-07-24T14:13:28.854545Z","shell.execute_reply":"2024-07-24T14:13:42.471436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 3回目の学習\nfit_epoch(neuron=neuron, batch=batch, epochs=30, initial_epoch=20, model_filename=model_filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:42.474181Z","iopub.execute_input":"2024-07-24T14:13:42.474531Z","iopub.status.idle":"2024-07-24T14:13:56.032667Z","shell.execute_reply.started":"2024-07-24T14:13:42.474502Z","shell.execute_reply":"2024-07-24T14:13:56.031760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 予測結果をCSVファイルに保存","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport cv2\nimport tensorflow.keras as keras\nfrom tensorflow.keras.models import load_model\n\n# 定数の設定\nIMG_SIZE = 64  # 画像のサイズ\ntest_dir = '/kaggle/working/test/test'  # テストデータのディレクトリ\nmodel_filename = 'model.h5'  # 学習したモデルのファイル名\noutput_csv = '/kaggle/working/submission.csv'  # 提出するCSVファイルのパス\n\n# 画像データの読み込み関数\ndef load_test_data(data_dir):\n    images = []\n    filenames = os.listdir(data_dir)\n    for file in filenames:\n        img_path = os.path.join(data_dir, file)\n        img = cv2.imread(img_path)\n        if img is not None:\n            img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))\n            images.append(img)\n        else:\n            print(f'Error reading {img_path}')\n    return np.array(images) / 255.0, filenames\n\n# テストデータの読み込み\nX_test, test_filenames = load_test_data(test_dir)\n\n# モデルの読み込み\nmodel = load_model(model_filename)\n\n# 予測の実行\npredictions = model.predict(X_test)\n\n# 予測結果を0または1に変換\npredictions = (predictions > 0.5).astype(int).flatten()\n\n# CSVファイルの作成\noutput_df = pd.DataFrame({\n    'id': [os.path.splitext(f)[0] for f in test_filenames],  # ファイル名から拡張子を除去してIDにする\n    'label': predictions\n})\noutput_df.to_csv(output_csv, index=False)\n\nprint(f'CSVファイル {output_csv} を作成しました')\n","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:56.033978Z","iopub.execute_input":"2024-07-24T14:13:56.034335Z","iopub.status.idle":"2024-07-24T14:14:10.349782Z","shell.execute_reply.started":"2024-07-24T14:13:56.034302Z","shell.execute_reply":"2024-07-24T14:14:10.348629Z"},"trusted":true},"execution_count":null,"outputs":[]}]}