{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31089,"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-28T00:26:52.078312Z","iopub.execute_input":"2025-07-28T00:26:52.079061Z","iopub.status.idle":"2025-07-28T00:26:52.084672Z","shell.execute_reply.started":"2025-07-28T00:26:52.079024Z","shell.execute_reply":"2025-07-28T00:26:52.084095Z"}},"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-28T00:26:54.772374Z","iopub.execute_input":"2025-07-28T00:26:54.772999Z","iopub.status.idle":"2025-07-28T00:26:54.776917Z","shell.execute_reply.started":"2025-07-28T00:26:54.772977Z","shell.execute_reply":"2025-07-28T00:26:54.776233Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_size = 224\n\nbatch_size = 16\n\nepochs = 30","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:26:57.727296Z","iopub.execute_input":"2025-07-28T00:26:57.728117Z","iopub.status.idle":"2025-07-28T00:26:57.731379Z","shell.execute_reply.started":"2025-07-28T00:26:57.728082Z","shell.execute_reply":"2025-07-28T00:26:57.730832Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# データを初期化\n!rm -rf ../data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:27:13.151997Z","iopub.execute_input":"2025-07-28T00:27:13.152617Z","iopub.status.idle":"2025-07-28T00:27:13.283985Z","shell.execute_reply.started":"2025-07-28T00:27:13.152593Z","shell.execute_reply":"2025-07-28T00:27:13.283175Z"}},"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-28T00:27:15.964029Z","iopub.execute_input":"2025-07-28T00:27:15.964789Z","iopub.status.idle":"2025-07-28T00:27:25.742821Z","shell.execute_reply.started":"2025-07-28T00:27:15.964743Z","shell.execute_reply":"2025-07-28T00:27:25.742291Z"}},"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-28T00:27:53.147809Z","iopub.execute_input":"2025-07-28T00:27:53.148073Z","iopub.status.idle":"2025-07-28T00:27:53.153569Z","shell.execute_reply.started":"2025-07-28T00:27:53.148053Z","shell.execute_reply":"2025-07-28T00:27:53.152761Z"}},"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-28T00:27:56.491498Z","iopub.execute_input":"2025-07-28T00:27:56.491764Z","iopub.status.idle":"2025-07-28T00:27:56.518482Z","shell.execute_reply.started":"2025-07-28T00:27:56.491744Z","shell.execute_reply":"2025-07-28T00:27:56.517560Z"}},"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])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:28:00.736691Z","iopub.execute_input":"2025-07-28T00:28:00.737153Z","iopub.status.idle":"2025-07-28T00:28:00.759215Z","shell.execute_reply.started":"2025-07-28T00:28:00.737128Z","shell.execute_reply":"2025-07-28T00:28:00.758479Z"}},"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)    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:28:04.465988Z","iopub.execute_input":"2025-07-28T00:28:04.466569Z","iopub.status.idle":"2025-07-28T00:28:23.055352Z","shell.execute_reply.started":"2025-07-28T00:28:04.466544Z","shell.execute_reply":"2025-07-28T00:28:23.054767Z"}},"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)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:29:07.191799Z","iopub.execute_input":"2025-07-28T00:29:07.192789Z","iopub.status.idle":"2025-07-28T00:29:17.059512Z","shell.execute_reply.started":"2025-07-28T00:29:07.192762Z","shell.execute_reply":"2025-07-28T00:29:17.058931Z"}},"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})","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:29:41.432557Z","iopub.execute_input":"2025-07-28T00:29:41.432798Z","iopub.status.idle":"2025-07-28T00:29:41.457767Z","shell.execute_reply.started":"2025-07-28T00:29:41.432781Z","shell.execute_reply":"2025-07-28T00:29:41.457005Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\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=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)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:29:44.689961Z","iopub.execute_input":"2025-07-28T00:29:44.690432Z","iopub.status.idle":"2025-07-28T00:29:44.881747Z","shell.execute_reply.started":"2025-07-28T00:29:44.690400Z","shell.execute_reply":"2025-07-28T00:29:44.880916Z"}},"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)    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:29:48.393729Z","iopub.execute_input":"2025-07-28T00:29:48.394319Z","iopub.status.idle":"2025-07-28T00:29:52.193976Z","shell.execute_reply.started":"2025-07-28T00:29:48.394293Z","shell.execute_reply":"2025-07-28T00:29:52.193390Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#学習\nhistory = model.fit(\n    train_gen,\n    validation_data=val_gen,\n    epochs=10\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:31:24.178272Z","iopub.execute_input":"2025-07-28T00:31:24.178573Z","iopub.status.idle":"2025-07-28T00:48:27.601135Z","shell.execute_reply.started":"2025-07-28T00:31:24.178551Z","shell.execute_reply":"2025-07-28T00:48:27.600555Z"}},"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)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:48:40.256359Z","iopub.execute_input":"2025-07-28T00:48:40.256637Z","iopub.status.idle":"2025-07-28T00:49:59.089138Z","shell.execute_reply.started":"2025-07-28T00:48:40.256616Z","shell.execute_reply":"2025-07-28T00:49:59.088372Z"}},"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()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:50:32.075035Z","iopub.execute_input":"2025-07-28T00:50:32.075664Z","iopub.status.idle":"2025-07-28T00:50:32.450481Z","shell.execute_reply.started":"2025-07-28T00:50:32.075633Z","shell.execute_reply":"2025-07-28T00:50:32.449772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q keras-cv","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:50:39.485071Z","iopub.execute_input":"2025-07-28T00:50:39.485855Z","iopub.status.idle":"2025-07-28T00:51:17.192110Z","shell.execute_reply.started":"2025-07-28T00:50:39.485823Z","shell.execute_reply":"2025-07-28T00:51:17.191148Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.applications import ConvNeXtBase\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout, Input\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\n\nimg_size = 224\n\nbase_model = ConvNeXtBase(\n    include_top=False,\n    weights=\"imagenet\",\n    input_shape=(img_size, img_size, 3),\n    pooling=None\n)\n\nx = GlobalAveragePooling2D()(base_model.output)\nx = Dropout(0.5)(x)\noutput = Dense(1, activation=\"sigmoid\")(x)\n\nmodel = Model(inputs=base_model.input, outputs=output)\n\nmodel.compile(\n    optimizer=Adam(learning_rate=1e-4),\n    loss=\"binary_crossentropy\",\n    metrics=[\"accuracy\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:51:25.352105Z","iopub.execute_input":"2025-07-28T00:51:25.352957Z","iopub.status.idle":"2025-07-28T00:51:29.297798Z","shell.execute_reply.started":"2025-07-28T00:51:25.352922Z","shell.execute_reply":"2025-07-28T00:51:29.297229Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow import keras","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:51:47.538563Z","iopub.execute_input":"2025-07-28T00:51:47.538838Z","iopub.status.idle":"2025-07-28T00:51:47.542508Z","shell.execute_reply.started":"2025-07-28T00:51:47.538818Z","shell.execute_reply":"2025-07-28T00:51:47.541815Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_gen,\n    validation_data=val_gen,\n    epochs=epochs,   # 例：epochs=8 くらいから様子見\n    callbacks=[\n        keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True)\n    ]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:51:52.014594Z","iopub.execute_input":"2025-07-28T00:51:52.014857Z","iopub.status.idle":"2025-07-28T00:51:52.342054Z","shell.execute_reply.started":"2025-07-28T00:51:52.014836Z","shell.execute_reply":"2025-07-28T00:51:52.341172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\n\nimg_size = 224\n\nbase_model = ResNet50(\n    include_top=False,\n    weights=\"imagenet\",\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)\n\nmodel = Model(inputs=base_model.input, outputs=output)\nmodel.compile(\n    optimizer=Adam(learning_rate=1e-4),\n    loss=\"binary_crossentropy\",\n    metrics=[\"accuracy\"]\n)    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:52:00.899871Z","iopub.execute_input":"2025-07-28T00:52:00.900372Z","iopub.status.idle":"2025-07-28T00:52:02.640275Z","shell.execute_reply.started":"2025-07-28T00:52:00.900345Z","shell.execute_reply":"2025-07-28T00:52:02.639665Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow import keras\nhistory = model.fit(\n    train_gen,\n    validation_data=val_gen,\n    epochs=10,  # まずは10エポックくらいで\n    callbacks=[\n        keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True)\n    ]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:52:09.709909Z","iopub.execute_input":"2025-07-28T00:52:09.710237Z","iopub.status.idle":"2025-07-28T00:52:09.847048Z","shell.execute_reply.started":"2025-07-28T00:52:09.710184Z","shell.execute_reply":"2025-07-28T00:52:09.846108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\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()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:52:13.949024Z","iopub.execute_input":"2025-07-28T00:52:13.949625Z","iopub.status.idle":"2025-07-28T00:52:14.082150Z","shell.execute_reply.started":"2025-07-28T00:52:13.949600Z","shell.execute_reply":"2025-07-28T00:52:14.081623Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\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()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:52:17.961903Z","iopub.execute_input":"2025-07-28T00:52:17.962428Z","iopub.status.idle":"2025-07-28T00:52:18.098388Z","shell.execute_reply.started":"2025-07-28T00:52:17.962404Z","shell.execute_reply":"2025-07-28T00:52:18.097674Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\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    class_mode=None,\n    target_size=(img_size, img_size),\n    batch_size=1,\n    shuffle=False\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:52:25.172811Z","iopub.execute_input":"2025-07-28T00:52:25.173534Z","iopub.status.idle":"2025-07-28T00:52:25.254259Z","shell.execute_reply.started":"2025-07-28T00:52:25.173510Z","shell.execute_reply":"2025-07-28T00:52:25.253675Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q transformers timm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:52:29.650648Z","iopub.execute_input":"2025-07-28T00:52:29.651301Z","iopub.status.idle":"2025-07-28T00:53:48.724275Z","shell.execute_reply.started":"2025-07-28T00:52:29.651272Z","shell.execute_reply":"2025-07-28T00:53:48.723511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 画像のパスからnumpy配列への変換例\ndef preprocess_images(image_paths):\n    images = [Image.open(p).convert('RGB') for p in image_paths]\n    return processor(images=images, return_tensors=\"pt\")['pixel_values']\n\n# 例: val_listやtest_listを使って推論データ作成\npixel_values = preprocess_images(test_list[:8])  # 8枚だけ例","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:53:55.676973Z","iopub.execute_input":"2025-07-28T00:53:55.677621Z","iopub.status.idle":"2025-07-28T00:53:55.730312Z","shell.execute_reply.started":"2025-07-28T00:53:55.677588Z","shell.execute_reply":"2025-07-28T00:53:55.729355Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\nwith torch.no_grad():\n    outputs = model(pixel_values)\n    logits = outputs.logits\n    preds = torch.argmax(logits, dim=1).numpy()\nprint(preds)  # 0, 1で出る（ラベルに合わせてマッピングを工夫）","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:53:59.746796Z","iopub.execute_input":"2025-07-28T00:53:59.747066Z","iopub.status.idle":"2025-07-28T00:53:59.765022Z","shell.execute_reply.started":"2025-07-28T00:53:59.747045Z","shell.execute_reply":"2025-07-28T00:53:59.764094Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import glob\nimport os\nfrom sklearn.model_selection import train_test_split\n\ntrain_dir = '/kaggle/working/data/train'\ntest_dir = '/kaggle/working/data/test'\n\ntrain_list = glob.glob(os.path.join(train_dir, '*.jpg'))\ntest_list = glob.glob(os.path.join(test_dir, '*.jpg'))\n\ndef get_label_from_path(path):\n    filename = os.path.basename(path)\n    return 1 if filename.startswith('dog') else 0\n\nlabels = [get_label_from_path(p) for p in train_list]\ntrain_imgs, val_imgs, train_labels, val_labels = train_test_split(train_list, labels, test_size=0.2, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:54:03.955424Z","iopub.execute_input":"2025-07-28T00:54:03.955985Z","iopub.status.idle":"2025-07-28T00:54:04.047696Z","shell.execute_reply.started":"2025-07-28T00:54:03.955961Z","shell.execute_reply":"2025-07-28T00:54:04.047129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\nfrom torch.utils.data import Dataset, DataLoader\nfrom transformers import ViTImageProcessor\n\nprocessor = ViTImageProcessor.from_pretrained('google/vit-base-patch16-224-in21k')\n\nclass CatsDogsDataset(Dataset):\n    def __init__(self, file_list, labels=None, processor=None):\n        self.file_list = file_list\n        self.labels = labels\n        self.processor = processor\n\n    def __len__(self):\n        return len(self.file_list)\n\n    def __getitem__(self, idx):\n        img_path = self.file_list[idx]\n        img = Image.open(img_path).convert(\"RGB\")\n        inputs = self.processor(images=img, return_tensors=\"pt\")\n        inputs = {k: v.squeeze(0) for k, v in inputs.items()}\n        if self.labels is not None:\n            label = self.labels[idx]\n            return inputs, label\n        else:\n            return inputs\n\nbatch_size = 8  # ViTは重いので小さめ\ntrain_ds = CatsDogsDataset(train_imgs, train_labels, processor)\nval_ds   = CatsDogsDataset(val_imgs,   val_labels,   processor)\ntest_ds  = CatsDogsDataset(test_list,  None,         processor)\n\ntrain_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True)\nval_loader   = DataLoader(val_ds,   batch_size=batch_size)\ntest_loader  = DataLoader(test_ds,  batch_size=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:54:09.286808Z","iopub.execute_input":"2025-07-28T00:54:09.287486Z","iopub.status.idle":"2025-07-28T00:54:12.616033Z","shell.execute_reply.started":"2025-07-28T00:54:09.287451Z","shell.execute_reply":"2025-07-28T00:54:12.615334Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom transformers import ViTForImageClassification\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = ViTForImageClassification.from_pretrained(\n    \"google/vit-base-patch16-224-in21k\",\n    num_labels=2  # 犬猫\n)\nmodel.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:54:18.965679Z","iopub.execute_input":"2025-07-28T00:54:18.966671Z","iopub.status.idle":"2025-07-28T00:54:24.330974Z","shell.execute_reply.started":"2025-07-28T00:54:18.966636Z","shell.execute_reply":"2025-07-28T00:54:24.330241Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\nfrom torch.utils.data import Dataset\nfrom transformers import ViTImageProcessor\n\nprocessor = ViTImageProcessor.from_pretrained('google/vit-base-patch16-224-in21k')\n\nclass CatsDogsDataset(Dataset):\n    def __init__(self, file_list, labels=None, processor=None):\n        self.file_list = file_list\n        self.labels = labels\n        self.processor = processor\n\n    def __len__(self):\n        return len(self.file_list)\n\n    def __getitem__(self, idx):\n        img_path = self.file_list[idx]\n        img = Image.open(img_path).convert(\"RGB\")\n        inputs = self.processor(images=img, return_tensors=\"pt\")\n        inputs = {k: v.squeeze(0) for k, v in inputs.items()}\n        if self.labels is not None:\n            label = self.labels[idx]\n            return inputs, label\n        else:\n            return inputs        ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:54:38.287162Z","iopub.execute_input":"2025-07-28T00:54:38.287539Z","iopub.status.idle":"2025-07-28T00:54:38.388646Z","shell.execute_reply.started":"2025-07-28T00:54:38.287511Z","shell.execute_reply":"2025-07-28T00:54:38.387941Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"batch_size = 8  # ViTは重いので小さめ\ntrain_ds = CatsDogsDataset(train_imgs, train_labels, processor)\nval_ds   = CatsDogsDataset(val_imgs,   val_labels,   processor)\ntest_ds  = CatsDogsDataset(test_list,  None,         processor)\n\nfrom torch.utils.data import DataLoader\ntrain_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True)\nval_loader   = DataLoader(val_ds,   batch_size=batch_size)\ntest_loader  = DataLoader(test_ds,  batch_size=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:54:41.918437Z","iopub.execute_input":"2025-07-28T00:54:41.918717Z","iopub.status.idle":"2025-07-28T00:54:41.924623Z","shell.execute_reply.started":"2025-07-28T00:54:41.918697Z","shell.execute_reply":"2025-07-28T00:54:41.923786Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn as nn\nfrom torch.optim import AdamW\nfrom tqdm import tqdm\n\nepochs = 3  # Kaggleなら3〜5くらいで様子見\noptimizer = AdamW(model.parameters(), lr=2e-5)\nloss_fn = nn.CrossEntropyLoss()\n\nfor epoch in range(epochs):\n    model.train()\n    total_loss = 0\n    for batch in tqdm(train_loader):\n        inputs, labels = batch\n        for k in inputs:\n            inputs[k] = inputs[k].to(device)\n        labels = torch.tensor(labels).to(device)\n        optimizer.zero_grad()\n        outputs = model(**inputs)\n        loss = loss_fn(outputs.logits, labels)\n        loss.backward()\n        optimizer.step()\n        total_loss += loss.item()\n    avg_loss = total_loss / len(train_loader)\n    print(f\"Epoch {epoch+1}/{epochs} Train Loss: {avg_loss:.4f}\")\n    \n    # Validation\n    model.eval()\n    correct, total = 0, 0\n    with torch.no_grad():\n        for batch in val_loader:\n            inputs, labels = batch\n            for k in inputs:\n                inputs[k] = inputs[k].to(device)\n            labels = torch.tensor(labels).to(device)\n            outputs = model(**inputs)\n            preds = outputs.logits.argmax(dim=1)\n            correct += (preds == labels).sum().item()\n            total += len(labels)\n    acc = correct / total\n    print(f\"Validation Accuracy: {acc:.4f}\")        ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T00:54:45.141765Z","iopub.execute_input":"2025-07-28T00:54:45.142035Z","iopub.status.idle":"2025-07-28T01:39:47.650334Z","shell.execute_reply.started":"2025-07-28T00:54:45.142014Z","shell.execute_reply":"2025-07-28T01:39:47.649511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\nall_preds = []\nwith torch.no_grad():\n    for batch in tqdm(test_loader):\n        inputs = batch\n        for k in inputs:\n            inputs[k] = inputs[k].to(device)\n        outputs = model(**inputs)\n        pred = outputs.logits.argmax(dim=1).item()\n        all_preds.append(pred)\n\nids = [int(os.path.basename(x).split('.')[0]) for x in test_list]\nimport pandas as pd\nsubmission = pd.DataFrame({'id': ids, 'label': all_preds})\nsubmission = submission.sort_values('id')\nsubmission.to_csv('submission.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T01:39:54.747382Z","iopub.execute_input":"2025-07-28T01:39:54.747665Z","iopub.status.idle":"2025-07-28T01:43:56.261898Z","shell.execute_reply.started":"2025-07-28T01:39:54.747642Z","shell.execute_reply":"2025-07-28T01:43:56.261377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\nall_preds = []\nwith torch.no_grad():\n    for batch in test_loader:\n        inputs = batch\n        for k in inputs:\n            inputs[k] = inputs[k].to(device)\n        outputs = model(**inputs)\n        pred = outputs.logits.argmax(dim=1).item()\n        all_preds.append(pred)\n\n# 提出ファイル作成\nids = [int(os.path.basename(x).split('.')[0]) for x in test_list]\nimport pandas as pd\nsubmission = pd.DataFrame({'id': ids, 'label': all_preds})\nsubmission = submission.sort_values('id')\nsubmission.to_csv('submission.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T01:52:39.814075Z","iopub.execute_input":"2025-07-28T01:52:39.814904Z","iopub.status.idle":"2025-07-28T01:56:37.524543Z","shell.execute_reply.started":"2025-07-28T01:52:39.814868Z","shell.execute_reply":"2025-07-28T01:56:37.523979Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# すでにtest_genがある前提\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')\nsubmission.to_csv('submission.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T01:57:46.082404Z","iopub.execute_input":"2025-07-28T01:57:46.082990Z","iopub.status.idle":"2025-07-28T01:57:46.103845Z","shell.execute_reply.started":"2025-07-28T01:57:46.082964Z","shell.execute_reply":"2025-07-28T01:57:46.102824Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\nimport numpy as np","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T01:57:52.096093Z","iopub.execute_input":"2025-07-28T01:57:52.096396Z","iopub.status.idle":"2025-07-28T01:57:52.100226Z","shell.execute_reply.started":"2025-07-28T01:57:52.096373Z","shell.execute_reply":"2025-07-28T01:57:52.099409Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\nimport torch\n\n# 推論とラベル収集\nmodel.eval()\nval_preds = []\nval_trues = []\n\nwith torch.no_grad():\n    for batch in val_loader:\n        inputs = batch['pixel_values'].to(model.device)\n        labels = batch['labels'].to(model.device)\n\n        outputs = model(inputs)\n        logits = outputs.logits\n        probs = torch.sigmoid(logits).squeeze().cpu().numpy()  # 2クラスの片方の確率\n\n        preds = (probs > 0.5).astype(int)  # 0 or 1\n        val_preds.extend(preds.tolist())\n        val_trues.extend(labels.cpu().numpy().tolist())\n\n# スコア計算\nacc = accuracy_score(val_trues, val_preds)\nprec = precision_score(val_trues, val_preds)\nrec = recall_score(val_trues, val_preds)\nf1 = f1_score(val_trues, val_preds)\n\nprint('--- Validation Data ---')\nprint(f\"Accuracy : {acc:.4f}\")\nprint(f\"Precision: {prec:.4f}\")\nprint(f\"Recall   : {rec:.4f}\")\nprint(f\"F1 Score : {f1:.4f}\")        ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-28T01:57:56.887701Z","iopub.execute_input":"2025-07-28T01:57:56.887974Z","iopub.status.idle":"2025-07-28T01:57:56.981271Z","shell.execute_reply.started":"2025-07-28T01:57:56.887951Z","shell.execute_reply":"2025-07-28T01:57:56.980207Z"}},"outputs":[],"execution_count":null}]}