{"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":"import glob\nimport os.path as osp\n\nimport pandas as pd\nimport numpy as np\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\n\nfrom tqdm.notebook import tqdm\nfrom PIL import Image\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.utils.data as data\nimport torchvision\nfrom torchvision import models, transforms\nimport cv2\nimport albumentations as A\n\nimport os\nimport time\nfrom PIL import Image\nfrom IPython.display import display","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import Data","metadata":{}},{"cell_type":"code","source":"df_train = pd.read_csv(\"/kaggle/input/plant-pathology-2021-fgvc8/train.csv\")\ndf_sub = pd.read_csv(\"/kaggle/input/plant-pathology-2021-fgvc8/sample_submission.csv\")\ntrain_image_path = '../input/plant-pathology-2021-fgvc8/train_images'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# thống tập dữ liệu train\ncount_dict = df_train.labels.value_counts()\nclasses = list(count_dict.index)\nclasses_count = list(count_dict.values)\nprint(\"Number of unique labels: \",len(classes))\nprint(\"-------------------------------------------\")\ndf_train.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nhận thấy tập dữ liệu train có 6 loại nhãn, từ các nhãn này được phan thành 12 nhãn cụ thể.","metadata":{}},{"cell_type":"code","source":"# in kích thước của mảng\ndf_train.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mô hình sẽ được train với 18632 ảnh","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(35,15))\nplt.bar(classes,classes_count)\nplt.xticks(rotation=20,fontsize = 20,fontweight = \"bold\")\nplt.xticks(fontsize = 20,fontweight = \"bold\")\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"# mã hóa các nhãn thành chuẩn số nguyên để có thể train model\ndef to_label(df):\n    \"\"\"\n    Hàm mã hóa cho các nhãn.\n    \"\"\"\n    le = LabelEncoder()\n    df[\"labels_n\"] = le.fit_transform(df.labels.values)\n    return df\n\n# Lưu từ điển mã hóa\ndf_train = to_label(df_train)\ndf_labels_idx = df_train.loc[df_train.duplicated([\"labels\", \"labels_n\"])==False]\\\n                [[\"labels_n\", \"labels\"]].set_index(\"labels_n\").sort_index()\ndisplay(df_labels_idx)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Nạp, giải nén tinh chỉnh model zoo\n! ls /kaggle/input/finetuningmodelzoo","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_IMAGE_PATH = '../input/plant-pathology-2021-fgvc8/test_images'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_datapath_list(phase=\"train\", val_size=0.25):\n    \"\"\"\n    Hàm tạo PATH cho dữ liệu.\n    \n    Thông số\n    ----------\n    biến : 'train' or 'val' or 'test'\n         Chỉ định sử dụng dữ liệu train, validation, test.\n    val_size : float\n        Tỷ lệ dữ liệu xác thực để đào tạo dữ liệu.\n        \n    Trả về\n    -------\n    path_lsit : list\n        Một list chứa các PATH chỉ tới dữ liệu.\n    \"\"\"\n    \n    if phase in [\"train\", \"val\"]:\n        phase_path = \"train_images\"\n    elif phase in [\"test\"]:\n        phase_path = \"test_images\"\n    else:\n        print(f\"{phase} not in path\")\n    rootpath = \"/kaggle/input/plant-pathology-2021-fgvc8/\"\n#     rootpath = \"/kaggle/input/resized-plant2021/img_sz_256/\"\n    target_path = osp.join(TRAIN_IMAGE_PATH , '*.jpg') if  phase in ['train', 'val'] else osp.join(TEST_IMAGE_PATH, \"*.jpg\")\n\n    path_list = []\n    \n    for path in glob.glob(target_path):\n        path_list.append(path)\n        \n    if phase in [\"train\", \"val\"]:\n        train, val = train_test_split(path_list, test_size=val_size, random_state=0, shuffle=True)\n        if phase == \"train\":\n            path_list = train\n        else:\n            path_list = val\n    \n    return path_list","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageTransform():\n    \"\"\"\n    Lớp tiền sử lý hình ảnh.\n    \n    Thuộc tính\n    ----------\n    resize : int\n        224\n    mean : (R, G, B)\n        Giá trị trung bình cho mỗi kênh màu\n    std : (R, G, B)\n        Độ lệch tiêu chuẩn cho mỗi kênh màu\n    \"\"\"\n    \n    def __init__(self, resize, mean, std):\n        self.data_transform = {\n#             'train': A.Compose(albumentation_list),\n            'train': transforms.Compose([\n                transforms.Resize(resize),\n                transforms.RandomResizedCrop(resize, scale=(0.5, 1.0)),\n                transforms.RandomHorizontalFlip(),\n                transforms.RandomPerspective(),\n                transforms.ToTensor(),\n#                 transforms.RandomRotation(),\n                transforms.Normalize(mean, std)\n            ]),\n            'val': transforms.Compose([\n                transforms.Resize(resize),\n                transforms.CenterCrop(resize),\n                transforms.ToTensor(),\n                transforms.Normalize(mean, std)\n            ]),\n            'test': transforms.Compose([\n                transforms.Resize(resize),\n                transforms.CenterCrop(resize),\n                transforms.ToTensor(),\n                transforms.Normalize(mean, std)\n            ])\n        }\n    \n    def __call__(self, img, phase=\"train\"):\n        \"\"\"\n        Thông số\n        ----------\n        biến: 'train' or 'val' or 'test'\n            Chỉ định chế độ xử tiền xử lý\n        \"\"\"\n        \n        return self.data_transform[phase](img)\n#         return self.data_transform[phase](image=img).get('image')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PlantDataset(data.Dataset):\n    \"\"\"\n    Lớp tạo tập dữ liệu\n    \n    Thuộc tính\n    ----------\n    df_train : DataFrame\n        DataFrame chứa các nhãn hình ảnh.\n    file_list : list\n        Danh sách chứa các đường dẫn đến hình ảnh\n    transform : object\n        Phiên bản của lớp tiền xử lý (ImageTransform)\n    biến : 'train' or 'val' or 'test'\n        Chỉ định sử dụng dữ liệu train, validation, test\n    \"\"\"\n    def __init__(self, df_train, file_list, transform=None, phase='train'):\n        self.df_train = df_train\n        self.df_labels_idx = df_labels_idx\n        self.file_list = file_list\n        self.transform = transform\n        self.phase = phase\n   \n    def __len__(self):\n        \"\"\"\n        Returns the number of images.\n        \"\"\"\n        return len(self.file_list)\n    \n    def __getitem__(self, index):\n        \"\"\"\n        Nhận dữ liệu ở định dạng Tensor và nhãn của tiền xử lý hình ảnh.\n        \"\"\"\n        #print(index)\n        \n        # Load the index number image.\n        img_path = self.file_list[index]\n        img = Image.open(img_path)\n#         img = cv2.imread(img_path)\n#         img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        \n        # Tiền xử lý hình ảnh\n        img_transformed = self.transform(img, self.phase)\n        \n        # image name\n        image_name = img_path[-20:]\n        \n        # Trích xuất các nhãn\n        if self.phase in [\"train\", \"val\"]:\n            label = df_train.loc[df_train[\"image\"]==image_name][\"labels_n\"].values[0]\n        elif self.phase in [\"test\"]:\n            label = -1\n        \n        return img_transformed, label, image_name","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"size=224\nmean = (0.485, 0.355, 0.406)\nstd = (0.229, 0.224, 0.225)\ntest_list = make_datapath_list(phase=\"test\")\ntest_dataset = PlantDataset(df_train, test_list, transform=ImageTransform(size, mean, std), phase='test')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 128\n\n# Create DataLoader\ntest_dataloader = data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False)\n\n# to Dictionary\ndataloaders_dict = {\"test\": test_dataloader}\n\n# Operation check\n# batch_iterator = iter(dataloaders_dict[\"train\"])\n# inputs, labels = next(batch_iterator)\n# print(inputs.size())  # torch.Size([3, 3, 224, 224]) : [batch_size, Channel, H, W]\n# print(labels)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Model","metadata":{}},{"cell_type":"code","source":"SELECTION_MODEL = 'AlexNet' # AlexNet, VGG16, DenseNet","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if SELECTION_MODEL == 'AlexNet':\n    net = models.alexnet(pretrained=False)\n    net.classifier[6] = nn.Linear(in_features=4096, out_features=12)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if SELECTION_MODEL == 'VGG16':\n    net = models.vgg16(pretrained=False)\n    net.classifier[6] = nn.Linear(in_features=4096, out_features=12)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if SELECTION_MODEL == 'DenseNet':\n    net = models.densenet161(pretrained=False)\n    prev_out_feature = net.classifier.in_features\n    \n    new_last_layer = [\n        nn.Linear(prev_out_feature, 2208),\n        nn.ReLU(inplace = True),\n        nn.Dropout(p=0.5, inplace=False),\n        \n        nn.Linear(2208, 1104),\n        nn.ReLU(inplace = True),\n        nn.Dropout(p=0.5, inplace=False),\n        \n        nn.Linear(1104, 552),\n        nn.ReLU(inplace = True),\n        nn.Dropout(p=0.2, inplace=False),\n        \n        nn.Linear(552, 138),\n        nn.ReLU(inplace = True),\n        nn.Dropout(p=0.2, inplace=False),\n        \n        nn.Linear(138, 12),\n    ]\n    \n    net.classifier = nn.Sequential(*new_last_layer)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"load_path = ''\nif SELECTION_MODEL == 'DenseNet':\n    load_path = \"../input/finetuningmodelzoo/densenet_second10epoch_fine_tuning_v1.h\"\nelif SELECTION_MODEL == 'AlexNet':\n    load_path = '/kaggle/input/finetuningmodelzoo/alexnet_final200epoch_fine_tuning_v1.h'\nelif SELECTION_MODEL == 'VGG16':\n    load_path = '../input/finetuningmodelzoo/vgg16_final-50epoch_fine_tuning_v1.h'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if torch.cuda.is_available():\n    load_weights = torch.load(load_path)\n    net.load_state_dict(load_weights)\nelse:\n    load_weights = torch.load(load_path, map_location={\"cuda:0\": \"cpu\"})\n    net.load_state_dict(load_weights)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PlantPredictor():\n    \"\"\"\n    Lớp dự đoán nhãn từ kết quả đầu ra\n    \n    Thuộc tính\n    ----------\n    df_labels_idx: DataFrame\n        DataFrame liên kết INDEX với tên nhãn \n    \"\"\"\n    \n    def __init__(self, net, df_labels_idx, dataloaders_dict):\n        self.net = net\n        self.df_labels_idx = df_labels_idx\n        self.dataloaders_dict = dataloaders_dict\n        self.df_submit = pd.DataFrame()\n        \n    \n    def __predict_max(self, out):\n        \"\"\"\n        Lấy tên nhãn với xác suất cao nhất.\n        \n        Thong số\n        ----------\n        predicted_label_name: str\n            Tên nhãn có xác suất dự đoán cao nhất\n        \"\"\"\n        maxid = np.argmax(out.detach().numpy(), axis=1)\n        df_predicted_label_name = self.df_labels_idx.iloc[maxid]\n        \n        return df_predicted_label_name\n    \n    def inference(self):\n        device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n        print(f\"Devices to be used : {device}\")\n        df_pred_list = []\n        for inputs, _, image_name in tqdm(self.dataloaders_dict['test']):\n            device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n            self.net.to(device)\n            inputs = inputs.to(device)\n            out = self.net(inputs)\n            device = torch.device(\"cpu\")\n            out = out.to(device)\n            df_pred = self.__predict_max(out).reset_index(drop=True)\n            df_pred[\"image\"] = image_name\n            df_pred_list.append(df_pred)\n            \n        self.df_submit = pd.concat(df_pred_list, axis=0)\n        self.df_submit = self.df_submit[[\"image\", \"labels\"]].reset_index(drop=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictor = PlantPredictor(net, df_labels_idx, dataloaders_dict)\npredictor.inference()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_submit = predictor.df_submit.copy()\ndf_submit.to_csv(\"/kaggle/working/submission.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}