{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","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":30919,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 어떤 데이터들이 주어져 있는지 확인해볼까?","metadata":{}},{"cell_type":"code","source":"import os\n\nprint(os.listdir(\"../input\"))\nprint(os.listdir(\"../input/dogs-vs-cats-redux-kernels-edition\"))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:40.265927Z","iopub.execute_input":"2025-02-22T17:07:40.266194Z","iopub.status.idle":"2025-02-22T17:07:40.271791Z","shell.execute_reply.started":"2025-02-22T17:07:40.266173Z","shell.execute_reply":"2025-02-22T17:07:40.270841Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 압축 풀기","metadata":{"execution":{"iopub.status.busy":"2025-02-22T16:48:21.201469Z","iopub.execute_input":"2025-02-22T16:48:21.201817Z","iopub.status.idle":"2025-02-22T16:48:21.205802Z","shell.execute_reply.started":"2025-02-22T16:48:21.201789Z","shell.execute_reply":"2025-02-22T16:48:21.204702Z"}}},{"cell_type":"code","source":"from zipfile import ZipFile\n\ndata_path = \"../input/dogs-vs-cats-redux-kernels-edition/\"\n\n# 훈련 이미지 파일 압축 풀기\nwith ZipFile(data_path + 'train.zip') as zipper:\n    zipper.extractall()\n\n# 테스트 이미지 파일 압축 풀기\nwith ZipFile(data_path + 'test.zip') as zipper:\n    zipper.extractall()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:40.272632Z","iopub.execute_input":"2025-02-22T17:07:40.272920Z","iopub.status.idle":"2025-02-22T17:07:54.690207Z","shell.execute_reply.started":"2025-02-22T17:07:40.272889Z","shell.execute_reply":"2025-02-22T17:07:54.689288Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 데이터가 각각 몇 개씩이나 있나?","metadata":{}},{"cell_type":"code","source":"print(\"훈련 데이터 개수:\", len(os.listdir('train/')))\nprint(\"테스트 데이터 개수:\", len(os.listdir('test/')))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:54.691067Z","iopub.execute_input":"2025-02-22T17:07:54.691298Z","iopub.status.idle":"2025-02-22T17:07:54.716278Z","shell.execute_reply.started":"2025-02-22T17:07:54.691277Z","shell.execute_reply":"2025-02-22T17:07:54.715381Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 어떤 파일들이 있나?","metadata":{}},{"cell_type":"code","source":"print(os.listdir(\"train/\")[0:5])\nprint(os.listdir(\"test/\")[0:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:54.717136Z","iopub.execute_input":"2025-02-22T17:07:54.717419Z","iopub.status.idle":"2025-02-22T17:07:54.740712Z","shell.execute_reply.started":"2025-02-22T17:07:54.717395Z","shell.execute_reply":"2025-02-22T17:07:54.740035Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 데이터프레임 만들기","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\nfilenames = []\nlabels = []\nfor filename in os.listdir(\"train/\"):\n    filenames.append(filename)\n    if filename.split('.')[0] == \"cat\":\n        labels.append(0)\n    else:\n        labels.append(1)\n\ndf = pd.DataFrame({\n    'filename': filenames,\n    'label': labels\n})\n\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:54.741538Z","iopub.execute_input":"2025-02-22T17:07:54.741845Z","iopub.status.idle":"2025-02-22T17:07:55.119051Z","shell.execute_reply.started":"2025-02-22T17:07:54.741813Z","shell.execute_reply":"2025-02-22T17:07:55.118247Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 강아지 사진과 고양이 사진이 각각 몇 개씩 있는가?","metadata":{}},{"cell_type":"code","source":"import numpy as np\n\ndf[\"label\"].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:55.121516Z","iopub.execute_input":"2025-02-22T17:07:55.121883Z","iopub.status.idle":"2025-02-22T17:07:55.132910Z","shell.execute_reply.started":"2025-02-22T17:07:55.121861Z","shell.execute_reply":"2025-02-22T17:07:55.132172Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 이미지 출력","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport random as r\nimport cv2\n\nplt.figure(figsize=(15, 15))\n\nrow = 3\ncol = 3\n\nfor i in range(row * col):\n    img_idx = r.randint(0, len(df))\n    filename = df[\"filename\"][img_idx]\n    img = cv2.imread(\"train/\" + filename)\n\n    plt.subplot(row, col, i+1)\n    plt.imshow(img)\n    plt.title(filename)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:55.134175Z","iopub.execute_input":"2025-02-22T17:07:55.134387Z","iopub.status.idle":"2025-02-22T17:07:58.056983Z","shell.execute_reply.started":"2025-02-22T17:07:55.134369Z","shell.execute_reply":"2025-02-22T17:07:58.055863Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 모델 설계","metadata":{}},{"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Rescaling\n\nIMAGE_WIDTH = 112\nIMAGE_HEIGHT = 112\nIMAGE_SIZE = (IMAGE_WIDTH, IMAGE_HEIGHT)\nIMAGE_CHANNELS = 3\n\nmodel = Sequential()\n\nmodel.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS)))\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3, 3), activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dropout(0.50))\nmodel.add(Dense(1, activation='sigmoid'))\n\nmodel.compile(loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=['accuracy'])\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:07:58.058202Z","iopub.execute_input":"2025-02-22T17:07:58.058607Z","iopub.status.idle":"2025-02-22T17:08:12.773619Z","shell.execute_reply.started":"2025-02-22T17:07:58.058572Z","shell.execute_reply":"2025-02-22T17:08:12.772726Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 데이터 라벨링","metadata":{}},{"cell_type":"code","source":"directory = \"train/\"\nsorted_filenames = sorted(filenames)\nlabels = [0 if filename.split(\".\")[0] == \"cat\" else 1 for filename in sorted_filenames]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:08:12.774544Z","iopub.execute_input":"2025-02-22T17:08:12.775184Z","iopub.status.idle":"2025-02-22T17:08:12.791822Z","shell.execute_reply.started":"2025-02-22T17:08:12.775151Z","shell.execute_reply":"2025-02-22T17:08:12.790688Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 데이터셋 만들기","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.utils import image_dataset_from_directory\n\ntraining_data, validation_data = image_dataset_from_directory(\n    directory,\n    labels=labels,\n    label_mode=\"binary\",\n    image_size=IMAGE_SIZE,\n    seed=42,\n    validation_split=0.15,\n    subset=\"both\"\n)\n\ntraining_data = training_data.map(lambda x, y : (x/255.0, y))\nvalidation_data = validation_data.map(lambda x, y : (x/255.0, y))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:08:12.792626Z","iopub.execute_input":"2025-02-22T17:08:12.793029Z","iopub.status.idle":"2025-02-22T17:08:15.109374Z","shell.execute_reply.started":"2025-02-22T17:08:12.792992Z","shell.execute_reply":"2025-02-22T17:08:15.108736Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 데이터셋에서 데이터를 꺼내오고, 라벨링 결과 확인하기","metadata":{}},{"cell_type":"code","source":"# 배치에서 이미지와 라벨 가져오기\nimage_batch, label_batch = next(iter(training_data))\n\n# 9개 이미지 출력\nplt.figure(figsize=(10, 10))\nfor i in range(9):\n    plt.subplot(3, 3, i + 1)\n    plt.imshow(image_batch[i])  # 이미지 변환\n    plt.title(f\"Label: {label_batch[i].numpy()}\")  # 라벨 표시\n    plt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:08:15.110208Z","iopub.execute_input":"2025-02-22T17:08:15.110509Z","iopub.status.idle":"2025-02-22T17:08:16.002866Z","shell.execute_reply.started":"2025-02-22T17:08:15.110478Z","shell.execute_reply":"2025-02-22T17:08:16.001827Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 모델 학습","metadata":{}},{"cell_type":"code","source":"history = model.fit(training_data, epochs=10, validation_data=validation_data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:08:16.003854Z","iopub.execute_input":"2025-02-22T17:08:16.004147Z","iopub.status.idle":"2025-02-22T17:10:18.210406Z","shell.execute_reply.started":"2025-02-22T17:08:16.004121Z","shell.execute_reply":"2025-02-22T17:10:18.209736Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 성능 평가","metadata":{}},{"cell_type":"code","source":"loss, accuracy = model.evaluate(validation_data)\nprint(f\"📌 모델 평가 결과 - 손실(loss): {loss:.4f}, 정확도(accuracy): {accuracy:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:10:18.211299Z","iopub.execute_input":"2025-02-22T17:10:18.211587Z","iopub.status.idle":"2025-02-22T17:10:19.655748Z","shell.execute_reply.started":"2025-02-22T17:10:18.211553Z","shell.execute_reply":"2025-02-22T17:10:19.655066Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 모델 실행 결과 직접 확인하기","metadata":{}},{"cell_type":"code","source":"# 배치에서 이미지와 라벨 가져오기\nimage_batch, label_batch = next(iter(validation_data))\n\n# 9개 이미지 출력\nplt.figure(figsize=(10, 10))\nfor i in range(9):\n    plt.subplot(3, 3, i + 1)\n    plt.imshow(image_batch[i])\n    ans = \"dog\" if label_batch[i] else \"cat\"\n    model_output = model(image_batch[i:i+1])\n    pred = \"dog\" if (model_output[0][0] >= 0.5) else \"cat\"\n    plt.title(f\"Predict: {pred}({round(float(model_output[0][0]), 2)}), Answer: {ans}\")  # 라벨 표시\n    plt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:10:32.326204Z","iopub.execute_input":"2025-02-22T17:10:32.326483Z","iopub.status.idle":"2025-02-22T17:10:33.981052Z","shell.execute_reply.started":"2025-02-22T17:10:32.326461Z","shell.execute_reply":"2025-02-22T17:10:33.980112Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 테스트 데이터 예측","metadata":{}},{"cell_type":"code","source":"test_data = image_dataset_from_directory(\n    \"test/\",\n    labels=None,\n    label_mode=\"binary\",\n    image_size=IMAGE_SIZE,\n    shuffle=False\n).map(lambda x : x/255.0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:11:24.381038Z","iopub.execute_input":"2025-02-22T17:11:24.381499Z","iopub.status.idle":"2025-02-22T17:11:24.809937Z","shell.execute_reply.started":"2025-02-22T17:11:24.381455Z","shell.execute_reply":"2025-02-22T17:11:24.809040Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds = model.predict(test_data)  \npred_list = preds.flatten() \n\nprint(pred_list)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:12:08.098381Z","iopub.execute_input":"2025-02-22T17:12:08.098691Z","iopub.status.idle":"2025-02-22T17:12:14.222617Z","shell.execute_reply.started":"2025-02-22T17:12:08.098666Z","shell.execute_reply":"2025-02-22T17:12:14.221616Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# 첫 번째 배치 가져오기\niterator = iter(test_data)\nfirst_batch = next(iterator)\n\n# 32개 이미지 출력\nplt.figure(figsize=(10, 20))\nfor i in range(32):\n    plt.subplot(8, 4, i + 1)\n    plt.imshow(first_batch[i])  # 이미지 변환\n    plt.title(f\"Predict: {'dog' if int(round(pred_list[i])) else 'cat'} ({round(float(pred_list[i]), 2)})\")  # 라벨 표시\n    plt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:14:33.794965Z","iopub.execute_input":"2025-02-22T17:14:33.795260Z","iopub.status.idle":"2025-02-22T17:14:35.972533Z","shell.execute_reply.started":"2025-02-22T17:14:33.795237Z","shell.execute_reply":"2025-02-22T17:14:35.971317Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"filenames = sorted(os.listdir(\"test/\"))  \nsubmission_df = pd.DataFrame({\n    \"id\": [int(f.split(\".\")[0]) for f in filenames],  # 파일 이름에서 ID 추출\n    \"label\": pred_list  # 예측 결과 \n})\n\nsubmission_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-22T17:14:55.278411Z","iopub.execute_input":"2025-02-22T17:14:55.278715Z","iopub.status.idle":"2025-02-22T17:14:55.307853Z","shell.execute_reply.started":"2025-02-22T17:14:55.278691Z","shell.execute_reply":"2025-02-22T17:14:55.306866Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_df.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}