{"cells":[{"metadata":{},"cell_type":"markdown","source":"아래 Notebook을 참고했습니다.\n- https://www.kaggle.com/vkehfdl1/for-korean-cassava\n- https://www.kaggle.com/ihelon/cassava-leaf-disease-exploratory-data-analysis"},{"metadata":{},"cell_type":"markdown","source":"# 0. 목차\n1. 데이터 살펴보기\n    - 데이터를 살펴보고 필요한 자료를 불러옵니다. \n2. 모델링\n    - 모델을 설계합니다.\n3. 학습시키기\n    - 모델을 학습시킵니다.\n4. 제출하기 \n    - 결과를 제출합니다.\n    \n\n\n    "},{"metadata":{},"cell_type":"markdown","source":"# 1. 데이터 살펴보기\n각각을 불러와 내용을 살펴봅시다.\n학습 데이터가 아래와 같음을 확인할 수 있습니다.\n- CSV\n    - image id : label\n- JSON\n    - label : disease\n- Image"},{"metadata":{},"cell_type":"markdown","source":"## 1.1 CSV 살펴보기\npd.read_csv(path)"},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\ntrain_data = pd.read_csv(\"../input/cassava-leaf-disease-classification/train.csv\")\ntrain_data.head(3)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.2 JSON 살펴보기\npd.read_json(path, line=True)"},{"metadata":{"trusted":true},"cell_type":"code","source":"# JSON을 pd.Dataframe으로 읽기\n# https://stackoverflow.com/questions/48614158/read-json-file-as-pandas-dataframe\ntrain_json = pd.read_json(\"../input/cassava-leaf-disease-classification/label_num_to_disease_map.json\", lines=True)\ntrain_json","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.3 데이터 통합\npd.Series = pd.Series.map(labda x: x)"},{"metadata":{"trusted":true},"cell_type":"code","source":"# pd.Dataframe 맵핑\n# http://www.leejungmin.org/post/2018/04/21/pandas_apply_and_map/\ntrain_data[\"class\"] = train_data[\"label\"].map(lambda x : train_json[x][0])\ntrain_data.head(3)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"결측값 확인"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.info()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- 데이터 분포 확인\n- https://datascienceschool.net/01%20python/05.04%20%EC%8B%9C%EB%B3%B8%EC%9D%84%20%EC%82%AC%EC%9A%A9%ED%95%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EB%B6%84%ED%8F%AC%20%EC%8B%9C%EA%B0%81%ED%99%94.html"},{"metadata":{"trusted":true},"cell_type":"code","source":"import seaborn as sns\nsns.countplot(data=train_data, y =\"class\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.4 이미지 살펴보기\n- os.listdir()\n    - 디렉토리 내 모든 파일과 디렉토리 리스트를 리턴한다."},{"metadata":{"trusted":true},"cell_type":"code","source":"import os \npath = \"../input/cassava-leaf-disease-classification/train_images\"\nimages = os.listdir(path)\nprint(\"# Image :\", len(images))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- dict.get(a, b) : key a에 해당하는 value를 반환\n    - a : 찾으려는 key\n    - b : 없을 경우 리턴할 값"},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nshape = {}\nfor image in images[:300]:\n    img = cv2.imread(f\"{path}/{image}\")\n    shape[img.shape] = shape.get(img.shape, 0) + 1\nprint(shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 2. 모델링"},{"metadata":{},"cell_type":"markdown","source":"## 2.1 데이터 로더 만들기\n- path 에서 img array 를 추출하기 위해, custom dataloader를 사용했습니다.\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport math\nfrom tensorflow.keras.utils import Sequence\n\nclass Dataloader(Sequence):\n    def __init__(self, x_set, y_set, batch_size, shuffle=False):\n        self.x, self.y = x_set, y_set\n        self.batch_size = batch_size\n        self.shuffle=shuffle\n        self.on_epoch_end()\n\n    def __len__(self):\n        return math.ceil(len(self.x) / self.batch_size)\n\n    def __getitem__(self, idx):\n        indices = self.indices[idx*self.batch_size:(idx+1)*self.batch_size]\n        batch_x = [cv2.imread(x[i]) for i in indices]\n        batch_y = [self.y[i] for i in indices]\n\n        return np.array(batch_x), np.array(batch_y)\n\n    def on_epoch_end(self):\n        self.indices = np.arange(len(self.x))\n        if self.shuffle == True:\n            np.random.shuffle(self.indices)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data['path'] = train_data['image_id'].map(lambda x : f\"../input/cassava-leaf-disease-classification/train_images/{x}\")\ntrain_data.head(3)\ntrain_data.describe()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 2.2 데이터 셋 만들기"},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nx = train_data['path'].array\ny = train_data['label'].array\n\nx_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=34)\ntrain_loader = Dataloader(x_train, y_train, 16, shuffle=True)\nvalid_loader = Dataloader(x_test, y_test, 16)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 2.3 레이어 쌓기"},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\n\ndata_augmentation_layers = tf.keras.Sequential(\n    [\n        tf.keras.layers.experimental.preprocessing.RandomFlip(\"horizontal_and_vertical\"), #랜덤으로 이미지를 좌우로 뒤집어줌.\n        tf.keras.layers.experimental.preprocessing.RandomRotation(0.25), #이미지를 좌우로 25% 이내로 랜덤으로 돌립니다. \n        tf.keras.layers.experimental.preprocessing.RandomZoom((-0.2, 0)), #이미지를 0~20%만큼 랜덤으로 축소합니다.\n        \n    ]\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"SOTA 모델인 EfficientNet을 사용해보겠습니다.\n- https://paperswithcode.com/sota/image-classification-on-imagenet\n- https://keras.io/api/applications/efficientnet/"},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\n\nmobile_net = tf.keras.applications.MobileNetV2(\n    include_top=False, weights='imagenet', input_shape=(600,800,3)\n)\nmobile_net.trainable=True\n'''\nefficient_net = tf.keras.applications.EfficientNetB7(\n    include_top=False, weights='imagenet', input_shape=(600,800,3)\n)\nefficient_net.trainable=True\n'''","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- sparse_categorical_crossentropy : label\n- categorical_crossentropy : one_hot"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.layers import Dense, Dropout, Activation, Input, BatchNormalization, GlobalAveragePooling2D, Flatten\nfrom tensorflow.keras import layers\n\nmodel = Sequential() \nmodel.add(Input(shape=(600,800,3)))\nmodel.add(data_augmentation_layers) \nmodel.add(mobile_net) \n#model.add(efficient_net) \nmodel.add(layers.GlobalAveragePooling2D())\nmodel.add(layers.Dropout(0.5)) \nmodel.add(Flatten())\nmodel.add(Dense(5, activation=\"softmax\"))\nmodel.summary()\nmodel.trainable=True","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- check point"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\ncallbacks = [ModelCheckpoint(filepath='./model.h5', monitor='val_loss', save_best_only=True), EarlyStopping(monitor='val_loss', patience = 5, verbose=1)]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 3. 학습시키기"},{"metadata":{"trusted":true},"cell_type":"code","source":"# model = tf.keras.models.load_model(\"./model.h5\")\nmodel.compile(optimizer=\"Adam\", loss=\"sparse_categorical_crossentropy\", metrics=[\"acc\"])\nhistory  = model.fit(train_loader, validation_data=valid_loader, epochs=100, workers=8, callbacks=callbacks)\n# model.save(\"./model.h5\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 4. 제출하기"},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\n# model = tf.keras.models.load_model(\"./model.h5\")\ntest_image = cv2.imread(\"../input/cassava-leaf-disease-classification/test_images/2216849948.jpg\")\nresult = model.predict(np.array([test_image]))\nprint(np.argmax(result))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.read_csv(\"../input/cassava-leaf-disease-classification/sample_submission.csv\")\nsubmission[\"label\"] = np.argmax(result)\nsubmission.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}