{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31041,"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","trusted":true,"execution":{"iopub.status.busy":"2025-07-04T07:36:23.567103Z","iopub.execute_input":"2025-07-04T07:36:23.56733Z","iopub.status.idle":"2025-07-04T07:36:26.035452Z","shell.execute_reply.started":"2025-07-04T07:36:23.567307Z","shell.execute_reply":"2025-07-04T07:36:26.034698Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport os, glob, time, copy, zipfile\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.utils.data as data\nimport torch.nn.functional as F\nfrom torchvision import models, transforms","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T07:36:43.984173Z","iopub.execute_input":"2025-07-04T07:36:43.984459Z","iopub.status.idle":"2025-07-04T07:36:55.555923Z","shell.execute_reply.started":"2025-07-04T07:36:43.984436Z","shell.execute_reply":"2025-07-04T07:36:55.555399Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# データを初期化\n!rm -rf ../data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:43:21.120339Z","iopub.execute_input":"2025-07-04T00:43:21.120749Z","iopub.status.idle":"2025-07-04T00:43:21.253044Z","shell.execute_reply.started":"2025-07-04T00:43:21.120725Z","shell.execute_reply":"2025-07-04T00:43:21.252222Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# データの解凍\nbase_dir = '/kaggle/input/dogs-vs-cats-redux-kernels-edition'\ndata_dir = \"/kaggle/working/data/\"\ntrain_dir = '/kaggle/working/data/train'\ntest_dir = '/kaggle/working/data/test'\n\nos.makedirs('./data', exist_ok=True)\n\n# 学習データの解凍\nwith zipfile.ZipFile(os.path.join(base_dir, 'train.zip')) as train_zip:\n    train_zip.extractall(data_dir)\n    \n#推論データの解凍\nwith zipfile.ZipFile(os.path.join(base_dir, 'test.zip')) as test_zip:\n    test_zip.extractall(data_dir)\n\n\ntrain_list = glob.glob(os.path.join(train_dir, '*.jpg'))\ntest_list = glob.glob(os.path.join(test_dir, '*.jpg'))\n\n# 学習データから検証データを分割(8:2)\ntrain_list, val_list = train_test_split(train_list, test_size=0.2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:43:24.402646Z","iopub.execute_input":"2025-07-04T00:43:24.402978Z","iopub.status.idle":"2025-07-04T00:43:38.71533Z","shell.execute_reply.started":"2025-07-04T00:43:24.402948Z","shell.execute_reply":"2025-07-04T00:43:38.714534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ImageTransform():\n    \n    def __init__(self, resize, mean, std):\n        self.data_transform = {\n            'train': transforms.Compose([\n                transforms.Resize((resize, resize)),  # 画像サイズを224にリサイズ\n                transforms.RandomHorizontalFlip(),    # ランダム水平反転\n                transforms.RandomVerticalFlip(),      # ランダム垂直反転\n                transforms.ToTensor(),                # テンソルに変換\n                transforms.Normalize(mean, std)       # 正規化\n            ]),\n            'val': transforms.Compose([\n                transforms.Resize((resize, resize)),  # 画像サイズを224にリサイズ\n                transforms.ToTensor(),                # テンソルに変換\n                transforms.Normalize(mean, std)       # 正規化\n            ])\n        }\n        \n    def __call__(self, img, phase):\n        return self.data_transform[phase](img)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:43:45.657355Z","iopub.execute_input":"2025-07-04T00:43:45.657948Z","iopub.status.idle":"2025-07-04T00:43:45.663295Z","shell.execute_reply.started":"2025-07-04T00:43:45.657921Z","shell.execute_reply":"2025-07-04T00:43:45.662372Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ImageDataset(data.Dataset):\n    \n    def __init__(self, file_list, transform=None, phase='train'):    \n        self.file_list = file_list\n        self.transform = transform\n        self.phase = phase\n        \n    def __len__(self):\n        return len(self.file_list)\n    \n    def __getitem__(self, idx):\n        \n        img_path = self.file_list[idx]\n        img = Image.open(img_path)\n        \n        img_transformed = self.transform(img, self.phase)\n        \n        # ファイル名からラベルを取得\n        label = img_path.split('/')[-1].split('.')[0]\n        if label == 'dog': #ファイル名がdogであれば 1\n            label = 1\n        elif label == 'cat':#ファイル名がcatであれば 0\n            label = 0\n\n        return img_transformed, label\n\n\n# データの前処理\ntrain_dataset = ImageDataset(train_list, transform=ImageTransform(size, mean, std), phase='train')\nval_dataset = ImageDataset(val_list, transform=ImageTransform(size, mean, std), phase='val')\n\n# データの読み込み\ntrain_dataloader = data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_dataloader = data.DataLoader(val_dataset, batch_size=batch_size, shuffle=False)\n\ndataloader_dict = {'train': train_dataloader, 'val': val_dataloader}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:43:48.795739Z","iopub.execute_input":"2025-07-04T00:43:48.796047Z","iopub.status.idle":"2025-07-04T00:43:48.822877Z","shell.execute_reply.started":"2025-07-04T00:43:48.796023Z","shell.execute_reply":"2025-07-04T00:43:48.82202Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\n\ndef get_label_from_path(path):\n    filename = os.path.basename(path)\n    if filename.startswith('dog'):\n        return 1\n    else:\n        return 0\n\ntrain_labels = np.array([get_label_from_path(p) for p in train_list])\nval_labels = np.array([get_label_from_path(p) for p in val_list])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:43:55.214351Z","iopub.execute_input":"2025-07-04T00:43:55.214662Z","iopub.status.idle":"2025-07-04T00:43:55.241852Z","shell.execute_reply.started":"2025-07-04T00:43:55.214637Z","shell.execute_reply":"2025-07-04T00:43:55.240961Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ndef get_label_from_path(path):\n    filename = os.path.basename(path)\n    return 'dog' if filename.startswith('dog') else 'cat'\n\ntrain_labels = [get_label_from_path(p) for p in train_list]\nval_labels = [get_label_from_path(p) for p in val_list]\n\ndf_train = pd.DataFrame({'filename': train_list, 'label': train_labels})\ndf_val = pd.DataFrame({'filename': val_list, 'label': val_labels})\n\nimg_size = 128\n\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    horizontal_flip=True,\n    rotation_range=10\n)\nval_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_gen = train_datagen.flow_from_dataframe(\n    df_train, \n    x_col='filename',\n    y_col='label',\n    target_size=(img_size, img_size),\n    class_mode='binary',\n    batch_size=32,\n    shuffle=True\n)\nval_gen = val_datagen.flow_from_dataframe(\n    df_val,\n    x_col='filename',\n    y_col='label',\n    target_size=(img_size, img_size),\n    class_mode='binary',\n    batch_size=32,\n    shuffle=False\n)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:43:58.515701Z","iopub.execute_input":"2025-07-04T00:43:58.516395Z","iopub.status.idle":"2025-07-04T00:44:18.626316Z","shell.execute_reply.started":"2025-07-04T00:43:58.516368Z","shell.execute_reply":"2025-07-04T00:44:18.625712Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_dir = '/kaggle/input/dogs-vs-cats-redux-kernels-edition'\ndata_dir = \"/kaggle/working/data/\"\ntrain_dir = '/kaggle/working/data/train'\ntest_dir = '/kaggle/working/data/test'\n\nos.makedirs(data_dir, exist_ok=True)\n\n# zip解凍\nimport zipfile\nwith zipfile.ZipFile(os.path.join(base_dir, 'train.zip')) as train_zip:\n    train_zip.extractall(data_dir)\nwith zipfile.ZipFile(os.path.join(base_dir, 'test.zip')) as test_zip:\n    test_zip.extractall(data_dir)\n\nimport glob\n# 画像ファイル一覧\ntrain_list_all = glob.glob(os.path.join(train_dir, '*.jpg'))\ntest_list = glob.glob(os.path.join(test_dir, '*.jpg'))\n\n# train/val分割\nfrom sklearn.model_selection import train_test_split\ntrain_list, val_list = train_test_split(train_list_all, test_size=0.2, random_state=42)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:44:26.135689Z","iopub.execute_input":"2025-07-04T00:44:26.136518Z","iopub.status.idle":"2025-07-04T00:44:36.74288Z","shell.execute_reply.started":"2025-07-04T00:44:26.136481Z","shell.execute_reply":"2025-07-04T00:44:36.742005Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#ラベル作成データフレイム化\ndef get_label_from_path(path):\n    filename = os.path.basename(path)\n    return 'dog' if filename.startswith('dog') else 'cat'\n\ntrain_labels = [get_label_from_path(p) for p in train_list]\nval_labels = [get_label_from_path(p) for p in val_list]\n\ndf_train = pd.DataFrame({'filename': train_list, 'label': train_labels})\ndf_val = pd.DataFrame({'filename': val_list, 'label': val_labels})\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:44:40.618251Z","iopub.execute_input":"2025-07-04T00:44:40.61856Z","iopub.status.idle":"2025-07-04T00:44:40.643868Z","shell.execute_reply.started":"2025-07-04T00:44:40.618538Z","shell.execute_reply":"2025-07-04T00:44:40.643211Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#データローダーの作成\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    horizontal_flip=True,\n    rotation_range=10\n)\nval_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_gen = train_datagen.flow_from_dataframe(\n    df_train, \n    x_col='filename',\n    y_col='label',\n    target_size=(img_size, img_size),\n    class_mode='binary',\n    batch_size=8,\n    shuffle=True\n)\nval_gen = val_datagen.flow_from_dataframe(\n    df_val,\n    x_col='filename',\n    y_col='label',\n    target_size=(img_size, img_size),\n    class_mode='binary',\n    batch_size=8,\n    shuffle=False\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:45:22.158098Z","iopub.execute_input":"2025-07-04T00:45:22.158682Z","iopub.status.idle":"2025-07-04T00:45:22.337118Z","shell.execute_reply.started":"2025-07-04T00:45:22.158649Z","shell.execute_reply":"2025-07-04T00:45:22.336528Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#EfficientNetB0でモデル構築\nfrom tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\n\nbase_model = EfficientNetB0(\n    weights='imagenet',\n    include_top=False,\n    input_shape=(img_size, img_size, 3)\n)\nbase_model.trainable = False  # 転移学習なのでまずは特徴抽出層を凍結\n\nx = GlobalAveragePooling2D()(base_model.output)\nx = Dropout(0.5)(x)\noutput = Dense(1, activation='sigmoid')(x)\nmodel = Model(inputs=base_model.input, outputs=output)\n\nmodel.compile(\n    optimizer=Adam(learning_rate=1e-3),\n    loss='binary_crossentropy',\n    metrics=['accuracy']\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:45:25.815816Z","iopub.execute_input":"2025-07-04T00:45:25.816576Z","iopub.status.idle":"2025-07-04T00:45:29.588329Z","shell.execute_reply.started":"2025-07-04T00:45:25.816552Z","shell.execute_reply":"2025-07-04T00:45:29.587469Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#学習\nhistory = model.fit(\n    train_gen,\n    validation_data=val_gen,\n    epochs=50\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-04T00:45:34.157676Z","iopub.execute_input":"2025-07-04T00:45:34.158151Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#推論\ndf_test = pd.DataFrame({'filename': test_list})\n\ntest_datagen = ImageDataGenerator(rescale=1./255)\ntest_gen = test_datagen.flow_from_dataframe(\n    df_test,\n    x_col='filename',\n    target_size=(img_size, img_size),\n    class_mode=None,\n    batch_size=1,\n    shuffle=False\n)\n\npred = model.predict(test_gen, steps=len(test_gen), verbose=1)\nlabels = (pred > 0.5).astype(int).flatten()\n\nids = [int(os.path.basename(x).split('.')[0]) for x in test_list]\nsubmission = pd.DataFrame({'id': ids, 'label': labels})\nsubmission = submission.sort_values('id')\n\nsubmission.to_csv('submission.csv', index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-03T11:25:00.745222Z","iopub.status.idle":"2025-07-03T11:25:00.745565Z","shell.execute_reply.started":"2025-07-03T11:25:00.745391Z","shell.execute_reply":"2025-07-03T11:25:00.745406Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# 精度の推移\nplt.plot(history.history['accuracy'], label='train_acc')\nplt.plot(history.history['val_accuracy'], label='val_acc')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.show()\n\n# 損失の推移\nplt.plot(history.history['loss'], label='train_loss')\nplt.plot(history.history['val_loss'], label='val_loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-03T11:26:29.214224Z","iopub.execute_input":"2025-07-03T11:26:29.214892Z","iopub.status.idle":"2025-07-03T11:26:29.238932Z","shell.execute_reply.started":"2025-07-03T11:26:29.21486Z","shell.execute_reply":"2025-07-03T11:26:29.23782Z"}},"outputs":[],"execution_count":null}]}