{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true},"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 in \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 \"../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# Any results you write to the current directory are saved as output.\nimport cv2\nimport torch\nimport torch.nn as nn\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport torchvision\nfrom torchvision import transforms\nfrom tqdm import tqdm_notebook as tqdm\nfrom torch.utils.data import Dataset,DataLoader\nimport warnings\nwarnings.filterwarnings(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"path = os.path.join(\"/kaggle/input/coic2\")\nos.listdir(path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_path = os.path.join(path,'flowers')\n#classes = {label: idx for idx, label in enumerate(os.listdir(os.path.join(train_path)))}\nclasses = {'daisy':0 ,'dandelion':1, 'rose':2,'sunflower':3,'tulip':4}\nclasses","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_samples():\n    images = []\n    \n    for class_name in sorted(classes.keys()):\n\n        dir = os.path.join(train_path,class_name)\n        \n        for root, _, fnames in sorted(os.walk(dir,followlinks=True)):\n            for fname in sorted(fnames):\n                if '.jpg' in fname:\n                    path = os.path.join(root,fname)\n                    item = (path, classes[class_name])\n                    images.append(item)\n    images = pd.DataFrame(images).rename(columns={0:'fname',1:'label'})\n    return images\nsamples = make_samples()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Check classes are balanced\n\nIt seems like balanced;)"},{"metadata":{"trusted":true},"cell_type":"code","source":"ax = sns.countplot(samples.label.map({idx:i for idx,i in enumerate(classes)}))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.RandomRotation(10,resample=False, expand=False, center=None),\n    transforms.CenterCrop(224),\n    transforms.RandomVerticalFlip(p=0.2),\n    transforms.RandomHorizontalFlip(p=0.5),\n    transforms.ToTensor(),\n    transforms.Normalize((0, 0, 0), (1, 1, 1)),\n])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class FlowerDataset(Dataset):\n    \n    def __init__(self,df,transforms = None):\n        \n        self.df = df\n        self.img = self.df.fname.values\n        if 'label' not in self.df.columns:\n            self.label = None\n        else:\n            self.label = self.df.label.values\n        self.transforms = transforms\n        \n    def __len__(self):\n        \n        return len(self.img)\n    \n    def __getitem__(self,idx):\n        \n        img = cv2.imread(self.img[idx])\n        # Change BGR to RGB\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        img = cv2.resize(img,(224,224))\n        if self.label is not None:\n            target = self.label[idx]\n            if self.transforms:\n                img = Image.fromarray(img)\n                img = self.transforms(img)\n                #permute dimensions compatible with before augmentation and pytorch format\n                return torch.tensor(img).permute(0,2,1),target\n            else:\n                # rearrange dimensions compatible with pytorch format\n                return torch.tensor(img).permute(2,1,0),target\n        else:\n            return torch.tensor(img).permute(2,1,0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Before Augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_images = FlowerDataset(samples)\ntrain_dataloader = torch.utils.data.DataLoader(train_images, batch_size=6, shuffle=True)\na = next(iter(train_dataloader))\nfig,ax = plt.subplots(2,3, figsize=(25,25))\nfor i in range(6):\n    j = i//3\n    k = i%3\n    ax[j,k].imshow(torch.transpose(a[0][i],0,2))\n    ax[j,k].set_title(list(classes.keys())[a[1][i]])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### After Augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_images = FlowerDataset(samples,transforms=transform)\ntrain_dataloader = torch.utils.data.DataLoader(train_images, batch_size=6, shuffle=True)\na = next(iter(train_dataloader))\nfig,ax = plt.subplots(2,3, figsize=(25,25))\nfor i in range(6):\n    j = i//3\n    k = i%3\n    ax[j,k].imshow(torch.transpose(a[0][i],0,2))\n    ax[j,k].set_title(list(classes.keys())[a[1][i]])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Flowers look beautiful! ;-)"},{"metadata":{},"cell_type":"markdown","source":"### Build NN Model(With pretrained resnet152)"},{"metadata":{"trusted":true},"cell_type":"code","source":"from torchvision import transforms, models","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class FlowerNet(nn.Module):\n    def __init__(self):\n        super(FlowerNet, self).__init__()\n        self.resnet = models.resnet152(pretrained=True, progress=False)\n        self.fc1 = nn.Linear(1000,500)\n        self.fc2 = nn.Linear(500,128)\n        self.fc3 = nn.Linear(128, 5)\n        for param in self.resnet.parameters():\n            param.requires_grad = False\n    def forward(self,x):\n        x = self.resnet(x)\n        # Adding classifier layers\n        x = self.fc1(x)\n        x = self.fc2(x)\n        x = self.fc3(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel = FlowerNet().to(device)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### I found useful package which is convinient to see the summary of structure ;-)"},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install torchsummary\nfrom torchsummary import summary","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Since resnet152 is needed (224,224) input size, you need to resize it.(as I modified the size in the dataset(FlowerDataset) class)"},{"metadata":{"trusted":true},"cell_type":"code","source":"summary(model,(3,224,224)) #input = (Channel,Height,Width)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_losses = []\ntrain_accs = []\nval_losses = []\nval_accs = []\ndef Train(model):\n    model.train()\n    epochs=10\n    for epoch in range(epochs):\n        print('epochs : {}/{}'.format(epoch+1,epochs))\n        running_loss = 0.\n        running_acc = 0.\n        for idx, (inputs,labels) in tqdm(enumerate(train_loader),total=len(train_loader)):\n            optimizer.zero_grad()\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            preds = model(inputs.float())\n            loss_val = loss(preds, labels)\n            pred_classes = preds.argmax(dim=1)\n            loss_val.backward()\n            optimizer.step()\n            running_loss += loss_val\n            running_acc += (pred_classes == labels.data).float().mean()\n        \n        train_loss = running_loss/len(train_loader)\n        train_acc = running_acc/len(train_loader)\n        print('train_loss : {:.4f}, train_acc : {:.2f}%'.format(train_loss,train_acc))\n        train_losses.append(train_loss)\n        train_accs.append(train_acc)\n        Valid(model)\n    return model\ndef Valid(model):\n    #model.eval()\n    running_loss = 0.\n    running_acc = 0.\n    with torch.no_grad():\n        \n        for idx, (inputs,labels) in enumerate(valid_loader):\n            \n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            \n            preds = model(inputs.float())\n            loss_val = loss(preds,labels)\n            pred_classes = preds.argmax(dim=1)\n            \n            running_loss += loss_val\n            running_acc += (pred_classes == labels.data).float().mean()\n            \n        val_loss = running_loss/len(valid_loader)\n        val_acc = running_acc/len(valid_loader)\n        print('val_loss : {:.2f}, val_acc : {:.2f}%'.format(val_loss,val_acc))\n        val_losses.append(val_loss)\n        val_accs.append(val_acc)\ndef Test(model):\n    prediction = []\n    test_images = FlowerDataset(pd.DataFrame(test_samples))\n    test_loader = torch.utils.data.DataLoader(test_images, batch_size=32, shuffle=False)\n    model.eval()\n\n    for idx, (inputs) in enumerate(test_loader):\n            inputs = inputs.to(device)\n            preds = model(inputs.float())\n            pred_classes = preds.argmax(dim=1)\n            prediction.append(pred_classes.cpu().detach().numpy())\n    prediction = np.hstack(prediction)\n    return prediction\n            ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Train and Valid Split (Stratified way 8:2) ver.1\n\n#### Stratified KFOLD (5 Fold) ver.2\n\n#### Train and Valid Split (Stratified way 95:5) ver.3\n\n#### Stratified KFOLD (10 Fold) ver.4"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nfrom sklearn.model_selection import train_test_split\ntrain_set, valid_set, _, _ = train_test_split(samples, samples.label,\n                                                    stratify=samples.label, \n                                                    test_size=0.05)\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_test_samples():\n    images = []\n    \n    path = '/kaggle/input/coic2'\n    dir = os.path.join(path,'unlabel-flowers')\n        \n    for root, _, fnames in os.walk(dir,followlinks=True):\n        for fname in fnames:\n            if '.jpg' in fname:\n                path = os.path.join(root,fname)\n                item = (path)\n                images.append(item)\n    images = pd.DataFrame(images).rename(columns= {0:'fname'})\n    return images\ntest_samples = make_test_samples()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import StratifiedKFold\nfolds  = 10\nskf = StratifiedKFold(n_splits=folds, random_state=7, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loss = torch.nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=2e-4)\n#scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.9)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for idx, (train_idx,valid_idx) in enumerate(skf.split(samples,samples.label)):\n    train_images = FlowerDataset(samples.iloc[train_idx],transforms=transform)\n    train_loader = torch.utils.data.DataLoader(train_images, batch_size=32, shuffle=True)\n    valid_images = FlowerDataset(samples.iloc[valid_idx])\n    valid_loader = torch.utils.data.DataLoader(valid_images, batch_size=32, shuffle=True)\n    model = Train(model)\nprediction = Test(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"prediction = Test(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, axs = plt.subplots(2, 2, figsize=(15, 5))\naxs[0,0].plot(train_accs)\naxs[0,0].set_title('Train Accuracy')\naxs[0,1].plot(train_losses)\naxs[0,1].set_title('Train Loss')\naxs[1,0].plot(val_accs)\naxs[1,0].set_title('Val Accuracy')\naxs[1,1].plot(val_losses)\naxs[1,1].set_title('Val Loss')\nfig.tight_layout()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Evaluation"},{"metadata":{},"cell_type":"markdown","source":"### This is prediction Result ;-)"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_samples['label'] = prediction\ntest_images = FlowerDataset(test_samples)\ntest_loader = torch.utils.data.DataLoader(test_images, batch_size=15, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"a = next(iter(test_loader))\nfig,ax = plt.subplots(5,3, figsize=(25,25))\nfor i in range(15):\n    j = i//3\n    k = i%3\n    ax[j,k].imshow(torch.transpose(a[0][i],0,2))\n    ax[j,k].set_title(list(classes.keys())[a[1][i]])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### It is unclear how to format the submission file ;-), so this is arbitrary one."},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.DataFrame(test_samples.fname.str.split('/').str.get(-1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#decode = {'daisy':1 ,'dandelion':2, 'rose':3,'sunflower':4,'tulip':5}\n#decode = {'daisy':1 ,'dandelion':2, 'rose':3,'sunflower':4,'tulip':5}\ndecode = {0:1,1:2,2:3,3:4,4:5}\nsubmission['label'] = prediction\nsubmission.label = submission.label.map(decode)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.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":1}