{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.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":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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","trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:23.098389Z","iopub.execute_input":"2025-07-27T21:30:23.099016Z","iopub.status.idle":"2025-07-27T21:30:23.105761Z","shell.execute_reply.started":"2025-07-27T21:30:23.098988Z","shell.execute_reply":"2025-07-27T21:30:23.104684Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"CatとDog","metadata":{}},{"cell_type":"code","source":"# 使用する外部ライブラリーのインポート\nimport zipfile\nimport os\nimport tensorflow as tf\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport glob\nfrom sklearn.model_selection import train_test_split\nimport shutil\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import EfficientNetB3\nfrom tensorflow.keras.callbacks import EarlyStopping\nimport random","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:23.107397Z","iopub.execute_input":"2025-07-27T21:30:23.107773Z","iopub.status.idle":"2025-07-27T21:30:23.123443Z","shell.execute_reply.started":"2025-07-27T21:30:23.107750Z","shell.execute_reply":"2025-07-27T21:30:23.122596Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 訓練データとテストデータをそれぞれ解凍\n\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/')\n\n\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:23.124386Z","iopub.execute_input":"2025-07-27T21:30:23.124733Z","iopub.status.idle":"2025-07-27T21:30:35.174748Z","shell.execute_reply.started":"2025-07-27T21:30:23.124710Z","shell.execute_reply":"2025-07-27T21:30:35.174009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 本当にファイルが生成されているのかの確認\nfile_list = os.listdir('/kaggle/working')\nprint(file_list)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:35.176307Z","iopub.execute_input":"2025-07-27T21:30:35.176619Z","iopub.status.idle":"2025-07-27T21:30:35.181789Z","shell.execute_reply.started":"2025-07-27T21:30:35.176596Z","shell.execute_reply":"2025-07-27T21:30:35.180947Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"画像を表示","metadata":{}},{"cell_type":"code","source":"# 解凍済みの画像フォルダ\nimg_dir = '/kaggle/working/train'\n\n# 画像ファイル名一覧（JPEGのみ）\nall_images = [f for f in os.listdir(img_dir) if f.endswith('.jpg')]\n\n# 猫と犬のファイルを分ける\ncat_images = [f for f in all_images if f.startswith('cat')]\ndog_images = [f for f in all_images if f.startswith('dog')]\n\n# 猫・犬からそれぞれランダムに3枚ずつ\nsample_cats = random.sample(cat_images, 3)\nsample_dogs = random.sample(dog_images, 3)\n\n# 画像表示（3枚 × 2行）\nplt.figure(figsize=(12, 6))\n\n# 猫画像（1行目）\nfor i, fname in enumerate(sample_cats):\n    img_path = os.path.join(img_dir, fname)\n    img = Image.open(img_path)\n    plt.subplot(2, 3, i + 1)\n    plt.imshow(img)\n    plt.title(f\"Cat: {fname}\")\n    plt.axis('off')  # ← インデント修正\n\n# 犬画像（2行目）\nfor i, fname in enumerate(sample_dogs):\n    img_path = os.path.join(img_dir, fname)\n    img = Image.open(img_path)\n    plt.subplot(2, 3, i + 4)\n    plt.imshow(img)\n    plt.title(f\"Dog: {fname}\")\n    plt.axis('off')\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:35.182588Z","iopub.execute_input":"2025-07-27T21:30:35.182830Z","iopub.status.idle":"2025-07-27T21:30:36.264575Z","shell.execute_reply.started":"2025-07-27T21:30:35.182806Z","shell.execute_reply":"2025-07-27T21:30:36.263281Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"前処理","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = 128  # EfficientNetB3に合わせる\nBATCH_SIZE = 32","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:36.265701Z","iopub.execute_input":"2025-07-27T21:30:36.266098Z","iopub.status.idle":"2025-07-27T21:30:36.271131Z","shell.execute_reply.started":"2025-07-27T21:30:36.266063Z","shell.execute_reply":"2025-07-27T21:30:36.270249Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ファイルパスとラベルのペアを作成\nall_files = [(os.path.join(img_dir, fname), 0 if fname.startswith('cat') else 1) for fname in all_images]\nrandom.shuffle(all_files)\n\n# train/valid分割\ntrain_files, val_files = train_test_split(all_files, test_size=0.2, random_state=42)\n\n# 画像読み込みと加工\ndef process_image(path, label):\n    img = tf.io.read_file(path)\n    img = tf.image.decode_jpeg(img, channels=3)\n    img = tf.image.resize(img, [IMG_SIZE, IMG_SIZE])\n    img = img / 255.0\n    return img, label\n\n# Dataset生成関数\ndef create_dataset(file_label_list):\n    paths, labels = zip(*file_label_list)\n    ds = tf.data.Dataset.from_tensor_slices((list(paths), list(labels)))\n    ds = ds.map(process_image).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)  # ← インデント修正\n    return ds\n\n# データセット作成\ntrain_ds = create_dataset(train_files)\nval_ds = create_dataset(val_files)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:36.272707Z","iopub.execute_input":"2025-07-27T21:30:36.273209Z","iopub.status.idle":"2025-07-27T21:30:36.509912Z","shell.execute_reply.started":"2025-07-27T21:30:36.273180Z","shell.execute_reply":"2025-07-27T21:30:36.509072Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = models.Sequential([\n    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n    layers.MaxPooling2D(2, 2),\n    \n    layers.Conv2D(64, (3, 3), activation='relu'),\n    layers.MaxPooling2D(2, 2),\n    \n    layers.Conv2D(128, (3, 3), activation='relu'),\n    layers.MaxPooling2D(2, 2),\n    \n    layers.Flatten(),\n    layers.Dense(128, activation='relu'),\n    layers.Dropout(0.3),\n    layers.Dense(1, activation='sigmoid')  # 2クラス分類\n    ])\n\n\nmodel.compile(optimizer='adam',\n              loss='binary_crossentropy',\n              metrics=['accuracy'])\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:36.511210Z","iopub.execute_input":"2025-07-27T21:30:36.511515Z","iopub.status.idle":"2025-07-27T21:30:36.659385Z","shell.execute_reply.started":"2025-07-27T21:30:36.511483Z","shell.execute_reply":"2025-07-27T21:30:36.658577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"early_stop = EarlyStopping(patience=3, restore_best_weights=True)\n\nhistory = model.fit(\n    train_ds,\n    validation_data=val_ds,\n    epochs=10,\n    callbacks=[early_stop]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T21:30:36.661563Z","iopub.execute_input":"2025-07-27T21:30:36.661833Z","iopub.status.idle":"2025-07-27T22:09:37.187135Z","shell.execute_reply.started":"2025-07-27T21:30:36.661810Z","shell.execute_reply":"2025-07-27T22:09:37.185131Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loss, acc = model.evaluate(val_ds)\nprint(f\"✅ 検証データでの精度: {acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T22:09:37.189445Z","iopub.execute_input":"2025-07-27T22:09:37.190068Z","iopub.status.idle":"2025-07-27T22:10:18.163214Z","shell.execute_reply.started":"2025-07-27T22:09:37.189992Z","shell.execute_reply":"2025-07-27T22:10:18.162105Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dir = '/kaggle/working/test'\ntest_images = sorted([os.path.join(test_dir, fname) for fname in os.listdir(test_dir) if fname.endswith('.jpg')])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T22:10:18.164386Z","iopub.execute_input":"2025-07-27T22:10:18.164865Z","iopub.status.idle":"2025-07-27T22:10:18.193375Z","shell.execute_reply.started":"2025-07-27T22:10:18.164830Z","shell.execute_reply":"2025-07-27T22:10:18.192393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_test_image(path):\n    img = tf.io.read_file(path)\n    img = tf.image.decode_jpeg(img, channels=3)\n    img = tf.image.resize(img, [IMG_SIZE, IMG_SIZE])\n    img = img / 255.0\n    return img\n\n# Dataset作成\ntest_ds = tf.data.Dataset.from_tensor_slices(test_images)\ntest_ds = test_ds.map(process_test_image).batch(BATCH_SIZE)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T22:10:18.194506Z","iopub.execute_input":"2025-07-27T22:10:18.194768Z","iopub.status.idle":"2025-07-27T22:10:18.368736Z","shell.execute_reply.started":"2025-07-27T22:10:18.194747Z","shell.execute_reply":"2025-07-27T22:10:18.367878Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds = model.predict(test_ds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T22:10:18.370072Z","iopub.execute_input":"2025-07-27T22:10:18.370374Z","iopub.status.idle":"2025-07-27T22:11:14.970940Z","shell.execute_reply.started":"2025-07-27T22:10:18.370350Z","shell.execute_reply":"2025-07-27T22:11:14.970268Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 画像IDを取得（ファイル名 '1234.jpg' → 1234）\nimage_ids = [int(os.path.basename(path).split('.')[0]) for path in test_images]\n\n# 確率（そのまま出力）\nprobs = preds.reshape(-1)\n\n# 提出用DataFrame作成\nsubmission_df = pd.DataFrame({'id': image_ids, 'label': probs})\n\n# ID順に並び替え（Kaggleの仕様に合わせる）\nsubmission_df = submission_df.sort_values('id')\n\n# CSV出力（小数点はfloatのままでOK）\nsubmission_df.to_csv('/kaggle/working/submission.csv', index=False)\n\nprint(\"✅ 犬である確率を含む submission.csv を出力しました！\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-27T22:11:14.972152Z","iopub.execute_input":"2025-07-27T22:11:14.972392Z","iopub.status.idle":"2025-07-27T22:11:15.053844Z","shell.execute_reply.started":"2025-07-27T22:11:14.972374Z","shell.execute_reply":"2025-07-27T22:11:15.052938Z"}},"outputs":[],"execution_count":null}]}