{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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":31040,"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-18T04:12:28.771822Z","iopub.execute_input":"2025-07-18T04:12:28.772104Z","iopub.status.idle":"2025-07-18T04:12:31.186821Z","shell.execute_reply.started":"2025-07-18T04:12:28.772076Z","shell.execute_reply":"2025-07-18T04:12:31.186044Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"初心者はCNNがいいらしい．CNNなら知っているので先ずはそれでやってみる．","metadata":{}},{"cell_type":"code","source":"import os\nimport zipfile\nimport shutil\nimport random\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Dropout\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# GPUの有無確認（CPUでも問題なし）\nprint(\"Num GPUs Available:\", len(tf.config.list_physical_devices('GPU')))\n\n# =========================\n# 1. データの解凍と整理\n# =========================\n\nbase_dir = '/kaggle/working/dogs-vs-cats-data'\ntrain_zip = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip'\n\nif not os.path.exists(base_dir):\n    os.makedirs(base_dir)\n\n# 解凍\nwith zipfile.ZipFile(train_zip, 'r') as zip_ref:\n    zip_ref.extractall(base_dir)\n\noriginal_train_dir = os.path.join(base_dir, 'train')\n\n# 画像ファイルをクラス別フォルダに分ける（cats, dogs）\nsplit_train_dir = os.path.join(base_dir, 'split')\ntrain_cats_dir = os.path.join(split_train_dir, 'train/cats')\ntrain_dogs_dir = os.path.join(split_train_dir, 'train/dogs')\nval_cats_dir = os.path.join(split_train_dir, 'val/cats')\nval_dogs_dir = os.path.join(split_train_dir, 'val/dogs')\n\nfor path in [train_cats_dir, train_dogs_dir, val_cats_dir, val_dogs_dir]:\n    os.makedirs(path, exist_ok=True)\n\n# データ分割（train:val = 90:10）\nall_filenames = os.listdir(original_train_dir)\ncats = [f for f in all_filenames if f.startswith('cat')]\ndogs = [f for f in all_filenames if f.startswith('dog')]\n\nrandom.seed(42)\nrandom.shuffle(cats)\nrandom.shuffle(dogs)\n\ndef split_and_copy(images, train_dir, val_dir, split_ratio=0.9):\n    split_idx = int(len(images) * split_ratio)\n    train_images = images[:split_idx]\n    val_images = images[split_idx:]\n    for f in train_images:\n        shutil.copy(os.path.join(original_train_dir, f), os.path.join(train_dir, f))\n    for f in val_images:\n        shutil.copy(os.path.join(original_train_dir, f), os.path.join(val_dir, f))\n\nsplit_and_copy(cats, train_cats_dir, val_cats_dir)\nsplit_and_copy(dogs, train_dogs_dir, val_dogs_dir)\n\n# =========================\n# 2. モデルと学習設定\n# =========================\n\nimg_height = 150\nimg_width = 150\nbatch_size = 32\n\ntrain_datagen = ImageDataGenerator(rescale=1.0/255)\nval_datagen = ImageDataGenerator(rescale=1.0/255)\n\ntrain_generator = train_datagen.flow_from_directory(\n    os.path.join(split_train_dir, 'train'),\n    target_size=(img_height, img_width),\n    batch_size=batch_size,\n    class_mode='binary'\n)\n\nval_generator = val_datagen.flow_from_directory(\n    os.path.join(split_train_dir, 'val'),\n    target_size=(img_height, img_width),\n    batch_size=batch_size,\n    class_mode='binary'\n)\n\n# CNNモデル構築\nmodel = Sequential([\n    Input(shape=(img_height, img_width, 3)),\n    Conv2D(32, (3, 3), activation='relu'),\n    MaxPooling2D(2, 2),\n    Conv2D(64, (3, 3), activation='relu'),\n    MaxPooling2D(2, 2),\n    Flatten(),\n    Dense(128, activation='relu'),\n    Dropout(0.5),\n    Dense(1, activation='sigmoid')\n])\n\nmodel.compile(optimizer='adam',\n              loss='binary_crossentropy',\n              metrics=['accuracy'])\n\n# 学習\nhistory = model.fit(\n    train_generator,\n    epochs=5,\n    validation_data=val_generator\n)\n\n# =========================\n# 3. モデル保存（任意）\n# =========================\nmodel.save(\"/kaggle/working/dogs_vs_cats_model.h5\")\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-18T04:12:31.187702Z","iopub.execute_input":"2025-07-18T04:12:31.188034Z","iopub.status.idle":"2025-07-18T04:49:18.551776Z","shell.execute_reply.started":"2025-07-18T04:12:31.188013Z","shell.execute_reply":"2025-07-18T04:49:18.550931Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# 4. テスト画像の準備\n# =========================\n\ntest_zip = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip'\ntest_dir = '/kaggle/working/test'\n\n# 解凍\nwith zipfile.ZipFile(test_zip, 'r') as zip_ref:\n    zip_ref.extractall(test_dir)\n\ntest_datagen = ImageDataGenerator(rescale=1.0/255)\n\ntest_generator = test_datagen.flow_from_directory(\n    directory='/kaggle/working',  # test/ ディレクトリの親\n    classes=['test'],             # test/ ディレクトリ内を指定\n    target_size=(img_height, img_width),\n    batch_size=1,\n    class_mode=None,\n    shuffle=False\n)\n\n# 推論\npred = model.predict(test_generator, steps=len(test_generator), verbose=1)\n\nimport pandas as pd\nimport numpy as np\nimport os\n\n# ファイル名からIDを取得\nfilenames = test_generator.filenames\nids = [int(os.path.basename(name).split('.')[0]) for name in filenames]\nlabels = (pred > 0.5).astype(int).flatten()\n\nsubmission = pd.DataFrame({'id': ids, 'label': labels})\nsubmission = submission.sort_values('id')  # id順に並べる（重要）\n\nsubmission.to_csv('/kaggle/working/submission.csv', index=False)\n\nimport matplotlib.pyplot as plt\n\nplt.plot(history.history['accuracy'], label='train acc')\nplt.plot(history.history['val_accuracy'], label='val acc')\nplt.legend()\nplt.title('Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.show()\n\nplt.plot(history.history['loss'], label='train loss')\nplt.plot(history.history['val_loss'], label='val loss')\nplt.legend()\nplt.title('Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.show()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-18T04:49:18.554601Z","iopub.execute_input":"2025-07-18T04:49:18.555970Z","iopub.status.idle":"2025-07-18T04:51:35.045277Z","shell.execute_reply.started":"2025-07-18T04:49:18.555942Z","shell.execute_reply":"2025-07-18T04:51:35.044406Z"}},"outputs":[],"execution_count":null}]}