|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +"""AlexNet.ipynb |
| 3 | +
|
| 4 | +Automatically generated by Colaboratory. |
| 5 | +
|
| 6 | +Original file is located at |
| 7 | + https://colab.research.google.com/drive/1ABqe0qMluk3sfqmwdxABpyUl93efb4Al |
| 8 | +""" |
| 9 | + |
| 10 | +from google.colab import drive |
| 11 | +drive.mount('/content/drive') |
| 12 | + |
| 13 | +pip install cnn_finetune |
| 14 | + |
| 15 | +import skimage |
| 16 | +import pandas |
| 17 | +from __future__ import print_function, division |
| 18 | +import os |
| 19 | +import torch |
| 20 | +import pandas as pd |
| 21 | +from skimage import io, transform |
| 22 | +import numpy as np |
| 23 | +import matplotlib.pyplot as plt |
| 24 | +from torch.utils.data import Dataset, DataLoader |
| 25 | +from torchvision import transforms, utils |
| 26 | +from PIL import Image |
| 27 | +import pandas as pd |
| 28 | +# Ignore warnings |
| 29 | +import warnings |
| 30 | +warnings.filterwarnings("ignore") |
| 31 | +from torch.utils.data.sampler import SubsetRandomSampler |
| 32 | +from torch.utils.data import DataLoader |
| 33 | + |
| 34 | +import torch.nn as nn |
| 35 | +import torch.nn.functional as F |
| 36 | +import argparse |
| 37 | +import torch |
| 38 | +import torchvision |
| 39 | +import torchvision.transforms as transforms |
| 40 | +from torch.autograd import Variable |
| 41 | +import torch.nn as nn |
| 42 | +import torch.optim as optim |
| 43 | + |
| 44 | +from cnn_finetune import make_model |
| 45 | + |
| 46 | +parser = argparse.ArgumentParser(description='cnn_finetune') |
| 47 | +parser.add_argument('-f') |
| 48 | +parser.add_argument('--batch-size', type=int, default=16, metavar='N', |
| 49 | + help='input batch size for training (default: 4)') |
| 50 | +parser.add_argument('--epochs', type=int, default=30, metavar='N', |
| 51 | + help='number of epochs to train (default: 30)') |
| 52 | +parser.add_argument('--lr', type=float, default=0.001, metavar='LR', |
| 53 | + help='learning rate (default: 0.001)') |
| 54 | +parser.add_argument('--momentum', type=float, default=0.9, metavar='M', |
| 55 | + help='SGD momentum (default: 0.9)') |
| 56 | +parser.add_argument('--no-cuda', action='store_true', default=False, |
| 57 | + help='disables CUDA training') |
| 58 | +parser.add_argument('--model-name', type=str, default='alexnet', metavar='M', |
| 59 | + help='model name (default: alexnet)') |
| 60 | + |
| 61 | +args = parser.parse_args() |
| 62 | +use_cuda = not args.no_cuda and torch.cuda.is_available() |
| 63 | +device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") |
| 64 | + |
| 65 | +class FloodTinyDataset(Dataset): |
| 66 | + |
| 67 | + def __init__(self, df, transform = None): |
| 68 | + |
| 69 | + self.flood_tiny_data = df |
| 70 | + ''' Change self.root_dir to load images ''' |
| 71 | + # self.root_dir = f"/content/drive/My Drive/ladi/Images/flood_tiny/" |
| 72 | + self.transform = transform |
| 73 | + |
| 74 | + def __len__(self): |
| 75 | + return len(self.flood_tiny_data) |
| 76 | + |
| 77 | + def __getitem__(self, idx): |
| 78 | + if torch.is_tensor(idx): |
| 79 | + idx = idx.tolist() |
| 80 | + |
| 81 | + # pos = self.flood_tiny_data.iloc[idx, 9].rfind('/')+1 |
| 82 | + # img_name = os.path.join(self.root_dir, self.flood_tiny_data.iloc[idx, 9][pos:]) |
| 83 | + img_name = self.flood_tiny_data.iloc[idx, 10] |
| 84 | + |
| 85 | + image = Image.fromarray(io.imread(img_name)) |
| 86 | + uuid = self.flood_tiny_data.iloc[idx, 1] |
| 87 | + timestamp = self.flood_tiny_data.iloc[idx, 2] |
| 88 | + gps_lat = self.flood_tiny_data.iloc[idx, 3] |
| 89 | + gps_lon = self.flood_tiny_data.iloc[idx, 4] |
| 90 | + gps_alt = self.flood_tiny_data.iloc[idx, 5] |
| 91 | + file_size = self.flood_tiny_data.iloc[idx, 6] |
| 92 | + width = self.flood_tiny_data.iloc[idx, 7] |
| 93 | + height = self.flood_tiny_data.iloc[idx, 8] |
| 94 | + ### Labels should be numerical, not bool for training ### |
| 95 | + if self.flood_tiny_data.iloc[idx, -1] == True: |
| 96 | + label = 1 |
| 97 | + else: |
| 98 | + label = 0 |
| 99 | + |
| 100 | + if self.transform: |
| 101 | + image = self.transform(image) |
| 102 | + |
| 103 | + sample = {'image': image, 'image_name': img_name, 'label': label, 'uuid': uuid, 'timestamp': timestamp, 'gps_lat': gps_lat, 'gps_lon': gps_lon, 'gps_alt': gps_alt, 'orig_file_size': file_size, 'orig_width': width, 'orig_height': height} |
| 104 | + |
| 105 | + return sample |
| 106 | + |
| 107 | +csv_file = '/content/drive/My Drive/DS440_Model/flood_tiny_metadata_L.csv' |
| 108 | +label_csv = '/content/drive/My Drive/DS440_Model/flood_tiny_label_L.csv' |
| 109 | + |
| 110 | +metadata = pd.read_csv(csv_file) |
| 111 | +label = pd.read_csv(label_csv) |
| 112 | +all_data = pd.merge(metadata, label, on="s3_path") |
| 113 | + |
| 114 | +class_zero = all_data[all_data['label']==False] |
| 115 | +class_one = all_data[all_data['label']==True] |
| 116 | +flood_tiny_data = pd.concat([class_zero, class_one]).sample(frac=1).reset_index(drop=True) |
| 117 | + |
| 118 | +flood_tiny_dataset = FloodTinyDataset(df=flood_tiny_data) |
| 119 | + |
| 120 | +transformed_dataset = FloodTinyDataset(df=flood_tiny_data, transform=transforms.Compose([transforms.Resize(256), |
| 121 | +transforms.RandomRotation(10), |
| 122 | +transforms.RandomCrop(256), |
| 123 | +transforms.RandomHorizontalFlip(), |
| 124 | +transforms.ToTensor()])) |
| 125 | + |
| 126 | +batch_size=args.batch_size |
| 127 | +test_split_ratio = .2 |
| 128 | +shuffle_dataset = True |
| 129 | +random_seed= 42 |
| 130 | +# Creating data indices for training and validation splits: |
| 131 | +dataset_size = len(transformed_dataset) |
| 132 | +indices = list(range(dataset_size)) |
| 133 | +split = int(np.floor(test_split_ratio * dataset_size)) |
| 134 | +if shuffle_dataset : |
| 135 | + np.random.seed(random_seed) |
| 136 | + np.random.shuffle(indices) |
| 137 | +train_indices, test_indices = indices[split:], indices[:split] |
| 138 | + |
| 139 | +train_sampler = SubsetRandomSampler(train_indices) |
| 140 | +test_sampler = SubsetRandomSampler(test_indices) |
| 141 | + |
| 142 | +train_loader = torch.utils.data.DataLoader(transformed_dataset, batch_size=batch_size, |
| 143 | + sampler=train_sampler) |
| 144 | +test_loader = torch.utils.data.DataLoader(transformed_dataset, batch_size=batch_size, |
| 145 | + sampler=test_sampler) |
| 146 | + |
| 147 | +def train(model, epoch, optimizer, train_loader, criterion=nn.CrossEntropyLoss()): |
| 148 | + running_loss = 0 |
| 149 | + total_size = 0 |
| 150 | + model.train() |
| 151 | + for i, data in enumerate(train_loader, 0): |
| 152 | + |
| 153 | + # get the inputs; data is a list of [inputs, labels] |
| 154 | + inputs = data['image'] |
| 155 | + labels = data['label'] |
| 156 | + inputs = inputs.to(device) |
| 157 | + labels = labels.to(device) |
| 158 | + # casting int to long for loss calculation# |
| 159 | + labels = labels.long() |
| 160 | + |
| 161 | + # zero the parameter gradients |
| 162 | + optimizer.zero_grad() |
| 163 | + |
| 164 | + # forward + backward + optimize |
| 165 | + outputs = model(inputs) |
| 166 | + loss = criterion(outputs, labels) |
| 167 | + |
| 168 | + running_loss += loss.item() |
| 169 | + total_size += inputs.size(0) |
| 170 | + loss.backward() |
| 171 | + optimizer.step() |
| 172 | + |
| 173 | + if i % 20 == 19: |
| 174 | + print('[%d, %3d] loss: %.3f' % |
| 175 | + (epoch + 1, i + 1, running_loss / 20)) |
| 176 | + running_loss = 0.0 |
| 177 | + |
| 178 | +print('Finished Training') |
| 179 | + |
| 180 | +def test(model, test_loader, criterion=nn.CrossEntropyLoss()): |
| 181 | + model.eval() |
| 182 | + correct = 0 |
| 183 | + total = 0 |
| 184 | + with torch.no_grad(): |
| 185 | + for data in test_loader: |
| 186 | + inputs = data['image'] |
| 187 | + labels = data['label'] |
| 188 | + inputs = inputs.to(device) |
| 189 | + labels = labels.to(device) |
| 190 | + |
| 191 | + outputs = model(inputs) |
| 192 | + |
| 193 | + _, predicted = torch.max(outputs.data, 1) |
| 194 | + #test_loss += criterion(output, target).item() |
| 195 | + total += labels.size(0) |
| 196 | + correct += (predicted == labels).sum().item() |
| 197 | + |
| 198 | + #correct += pred.eq(target.data.view_as(pred)).long().cpu().sum().item() |
| 199 | + accuracy = 100 * (correct / total) |
| 200 | + print('Accuracy of the network on test images: %d %%' % (accuracy)) |
| 201 | + state = {'epoch': epoch, 'state_dict': model.state_dict(), |
| 202 | + 'optimizer_state_dict': optimizer.state_dict()} |
| 203 | + model_name = 'Alexnet_%d_%d.pth' % (epoch, accuracy) |
| 204 | + PATH = f"/content/drive/My Drive/{model_name}" |
| 205 | + torch.save(state, PATH) |
| 206 | + |
| 207 | +model_name = args.model_name |
| 208 | + |
| 209 | +# classes = ('0','1') |
| 210 | +model = make_model( |
| 211 | + model_name, |
| 212 | + pretrained=True, |
| 213 | + num_classes=2, |
| 214 | + input_size= (256,256), |
| 215 | + ) |
| 216 | +model = model.to(device) |
| 217 | +optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum= args.momentum) |
| 218 | +scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1) |
| 219 | +for epoch in range(0, args.epochs): |
| 220 | + scheduler.step(epoch) |
| 221 | + train(model, epoch, optimizer, train_loader) |
| 222 | + test(model, test_loader) |
0 commit comments