{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"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","execution":{"iopub.status.busy":"2023-06-10T16:56:48.672911Z","iopub.execute_input":"2023-06-10T16:56:48.673257Z","iopub.status.idle":"2023-06-10T16:56:48.681709Z","shell.execute_reply.started":"2023-06-10T16:56:48.673229Z","shell.execute_reply":"2023-06-10T16:56:48.680662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport os","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:56:48.683958Z","iopub.execute_input":"2023-06-10T16:56:48.684806Z","iopub.status.idle":"2023-06-10T16:56:48.693486Z","shell.execute_reply.started":"2023-06-10T16:56:48.684619Z","shell.execute_reply":"2023-06-10T16:56:48.692483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!unzip -q -o /kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:56:48.695784Z","iopub.execute_input":"2023-06-10T16:56:48.696549Z","iopub.status.idle":"2023-06-10T16:56:59.613922Z","shell.execute_reply.started":"2023-06-10T16:56:48.696517Z","shell.execute_reply":"2023-06-10T16:56:59.612695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob # 파일의 리스트를 뽑을 때 사용\nglob.glob('/kaggle/working/train/*')[:5]","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:56:59.615472Z","iopub.execute_input":"2023-06-10T16:56:59.615868Z","iopub.status.idle":"2023-06-10T16:56:59.714221Z","shell.execute_reply.started":"2023-06-10T16:56:59.615827Z","shell.execute_reply":"2023-06-10T16:56:59.713203Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image\nImage.open('./train/dog.3942.jpg')","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:56:59.71705Z","iopub.execute_input":"2023-06-10T16:56:59.717521Z","iopub.status.idle":"2023-06-10T16:56:59.80891Z","shell.execute_reply.started":"2023-06-10T16:56:59.717486Z","shell.execute_reply":"2023-06-10T16:56:59.808056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.DataFrame({'path': glob.glob('/kaggle/working/train/*')})\ntrain","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:56:59.809837Z","iopub.execute_input":"2023-06-10T16:56:59.810124Z","iopub.status.idle":"2023-06-10T16:56:59.922564Z","shell.execute_reply.started":"2023-06-10T16:56:59.810098Z","shell.execute_reply":"2023-06-10T16:56:59.921516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['label'] = train['path'].apply(lambda x: x.split('/')[-1].split('.')[0])\ntrain","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:56:59.925324Z","iopub.execute_input":"2023-06-10T16:56:59.925655Z","iopub.status.idle":"2023-06-10T16:56:59.962242Z","shell.execute_reply.started":"2023-06-10T16:56:59.925624Z","shell.execute_reply":"2023-06-10T16:56:59.961389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 데이터 전처리","metadata":{}},{"cell_type":"markdown","source":"## fit_transform()\n- fit으로부터 데이터의 mean, variance를 학습\n- train data로부터 얻어와서 test data에서도 적용해 스케일링 함\n\n## transform()\n- fit이 없으므로 이미 얻어진 mean, variance를 적용해서 스케일링 함","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder \nle = LabelEncoder()\n\ntrain['label'] = le.fit_transform(train['label']) #딥러닝에서도 machine learning의 LabelEncoder를 쓰면 편리하게 mean, variance를 이용해 스케일링 할 수 있음\ntrain","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:56:59.965226Z","iopub.execute_input":"2023-06-10T16:56:59.965483Z","iopub.status.idle":"2023-06-10T16:57:00.779491Z","shell.execute_reply.started":"2023-06-10T16:56:59.96546Z","shell.execute_reply":"2023-06-10T16:57:00.77853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"## train, valid로 나누기 \n- test는 따로 이미 있으니, train을 가지고 train2와 valid로 나누어서 사용","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nX_train, X_valid = train_test_split(train, test_size=0.2, random_state=42, stratify=train['label'])\nX_train","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:00.782082Z","iopub.execute_input":"2023-06-10T16:57:00.78236Z","iopub.status.idle":"2023-06-10T16:57:00.910689Z","shell.execute_reply.started":"2023-06-10T16:57:00.782336Z","shell.execute_reply":"2023-06-10T16:57:00.909667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 이미지를 텐서로 바꾸는 과정에서 Dataset을 상속받아 사용","metadata":{}},{"cell_type":"code","source":"import torch\nfrom torch.utils.data import Dataset, DataLoader\nimport cv2\nimport albumentations as A #이미지 augmentation\nimport torchvision.models as models\nimport torch.nn as nn\nimport matplotlib.pyplot as plt\nimport torch.optim as optim","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:00.912755Z","iopub.execute_input":"2023-06-10T16:57:00.913167Z","iopub.status.idle":"2023-06-10T16:57:06.092932Z","shell.execute_reply.started":"2023-06-10T16:57:00.913133Z","shell.execute_reply":"2023-06-10T16:57:06.091963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 데이터 읽기\n- iloc : pandas에서 index로 데이터 읽기\n- loc : pandas에서 label로 데이터 읽기","metadata":{}},{"cell_type":"code","source":"image = cv2.imread(train['path'].iloc[1]) #이미지읽기\nimage.shape","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.096785Z","iopub.execute_input":"2023-06-10T16:57:06.097122Z","iopub.status.idle":"2023-06-10T16:57:06.126431Z","shell.execute_reply.started":"2023-06-10T16:57:06.097096Z","shell.execute_reply":"2023-06-10T16:57:06.125497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Datset을 상속받는 클래스 만들기","metadata":{}},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, df, transform):\n        self.df = df\n        self.transform = transform\n    def __len__(self):\n        return len(self.df)\n    def __getitem__(self, idx):  # 이미지, 오디오, 분류, 회귀 등에 맞춰 설정\n        path = self.df['path'].iloc[idx]\n        label = self.df['label'].iloc[idx]\n        image = cv2.imread(path)\n        \n        if self.transform is not None:\n            image = self.transform(image=image)['image']\n        \n        return image, label","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.127701Z","iopub.execute_input":"2023-06-10T16:57:06.128119Z","iopub.status.idle":"2023-06-10T16:57:06.136924Z","shell.execute_reply.started":"2023-06-10T16:57:06.128088Z","shell.execute_reply":"2023-06-10T16:57:06.136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transform = A.Compose([A.Resize(224, 224)])\ntrain_transform","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.138452Z","iopub.execute_input":"2023-06-10T16:57:06.1392Z","iopub.status.idle":"2023-06-10T16:57:06.150166Z","shell.execute_reply.started":"2023-06-10T16:57:06.139166Z","shell.execute_reply":"2023-06-10T16:57:06.149248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = CustomDataset(X_train, train_transform)\ntrain_dataset[0]\nvalid_dataset = CustomDataset(X_valid, train_transform)\nvalid_dataset[0]","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.151391Z","iopub.execute_input":"2023-06-10T16:57:06.152252Z","iopub.status.idle":"2023-06-10T16:57:06.178577Z","shell.execute_reply.started":"2023-06-10T16:57:06.152218Z","shell.execute_reply":"2023-06-10T16:57:06.177503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True)\nvalid_loader = DataLoader(valid_dataset, batch_size=128, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.179836Z","iopub.execute_input":"2023-06-10T16:57:06.180832Z","iopub.status.idle":"2023-06-10T16:57:06.186182Z","shell.execute_reply.started":"2023-06-10T16:57:06.180799Z","shell.execute_reply":"2023-06-10T16:57:06.185059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model 이용","metadata":{}},{"cell_type":"code","source":"class BaseModel(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.backbone = models.efficientnet_b0(pretrained=True)\n        self.classifier = nn.Linear(1000,2)\n    \n    def forward(self, x):\n        x = x/255\n        x = x.permute(0, 3, 1, 2)\n        x = self.backbone(x) \n        x = self.classifier(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.187642Z","iopub.execute_input":"2023-06-10T16:57:06.188042Z","iopub.status.idle":"2023-06-10T16:57:06.197652Z","shell.execute_reply.started":"2023-06-10T16:57:06.188008Z","shell.execute_reply":"2023-06-10T16:57:06.196581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\n\n# 이미지와 정답(label)을 표시\ntrain_features, train_labels = next(iter(train_loader))\nprint(f\"Feature batch shape: {train_features.size()}\")\nprint(f\"Labels batch shape: {train_labels.size()}\")\n\nfor i, data in enumerate(train_features):\n    img = train_features[i].squeeze() #squeeze함수는 차원이 1인 차원을 모두 제거해줌\n    label = train_labels[i]\n    plt.imshow(img, cmap=\"gray\")\n    plt.show()\n    print(f\"Label: {label}\")\n    break","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.199376Z","iopub.execute_input":"2023-06-10T16:57:06.19974Z","iopub.status.idle":"2023-06-10T16:57:06.937524Z","shell.execute_reply.started":"2023-06-10T16:57:06.199711Z","shell.execute_reply":"2023-06-10T16:57:06.936502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel = BaseModel()\nmodel.to(device)\n\nn_epochs = 10\nloss_fn = nn.BCELoss()\noptimizer = optim.SGD(model.parameters(), lr=0.1)\ncriterion = nn.CrossEntropyLoss()","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:06.939192Z","iopub.execute_input":"2023-06-10T16:57:06.939932Z","iopub.status.idle":"2023-06-10T16:57:10.529464Z","shell.execute_reply.started":"2023-06-10T16:57:06.939894Z","shell.execute_reply":"2023-06-10T16:57:10.528418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  forward() 함수를 호출하지 않았는데 model 파라미터로 전달하면 바로 forward function이 시작됨. 이것은 nn.Module을 상속받은 클래스의 특징이라고 볼 수 있다.\n# train_features, train_labels = next(iter(train_loader))\n# train_loader를 for문을 돌리며 배치단위 사이즈로 읽어오기\n\n# train the model\n\nfor epoch in range(n_epochs):\n    running_loss = 0.0\n    running_acc = 0.0\n    for i, (train_data, train_label)  in enumerate(train_loader, 0):\n        train_data = train_data.to(device)\n        train_label = train_label.to(device)\n        \n        optimizer.zero_grad()\n        train_pred = model(train_data)\n        # 순전파 - 모델의 결과와 실제 label사이 loss 연산\n        loss = criterion(train_pred, train_label)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n        \n        if i % 1000 == 0:    \n            print('[%d, %5d] loss: %.3f' %\n                  (epoch + 1, i + 1, running_loss / 1000))\n            running_loss = 0.0\n    model.eval()\n    accuracy = 0.0\n    total = 0.0\n    \n    with torch.no_grad():\n        for valid_data, valid_label in valid_loader:\n            valid_data = valid_data.to(device)\n            valid_label = valid_label.to(device)\n            \n            valid_pred = model(valid_data)\n            _, predicted = torch.max(valid_pred.data, 1)\n            total += valid_label.size(0)\n            accuracy += (predicted == valid_label).sum().item()\n    \n    # compute the accuracy over all test images\n    accuracy = (100 * accuracy / total)\n    print('For epoch', epoch+1,'the test accuracy over the whole test set is %d %%' % (accuracy))\n\n    ","metadata":{"execution":{"iopub.status.busy":"2023-06-10T16:57:10.531008Z","iopub.execute_input":"2023-06-10T16:57:10.531457Z","iopub.status.idle":"2023-06-10T17:35:20.870164Z","shell.execute_reply.started":"2023-06-10T16:57:10.531421Z","shell.execute_reply":"2023-06-10T17:35:20.869053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# K-fold 교차 검증을 이용한 점수 올리기","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}