Commit d7199aa3 authored by Smit Gangurde's avatar Smit Gangurde

Added CustomCNN notebook and code

parent 6bc2fe0d
This source diff could not be displayed because it is too large. You can view the blob instead.
import math
import torch
from torch.nn import Module
class Base_Model(Module):
def __init__(self, kernel, stride, padding, img_size, num_cnn_layers, out_channels):
super(Base_Model, self).__init__()
self.kernel = kernel
self.stride = stride
self.padding = padding
self.img_size = img_size
self.num_cnn = num_cnn_layers
self.out_channels = out_channels
self.out_dim = 0
#out_dim calc
self.out_dim = math.floor( (self.img_size + 2*self.padding[0] - self.kernel[0])/self.stride[0] ) + 1
self.out_dim = math.floor( (self.out_dim + 2*self.padding[0] - self.kernel[0])/self.stride[0] ) + 1
self.out_dim = math.floor( (self.out_dim - self.kernel[0])/self.stride[0] ) + 1
for i in range(self.num_cnn - 1):
self.out_dim = math.floor( (self.out_dim + 2*self.padding[0] - self.kernel[0])/self.stride[0] ) + 1
self.out_dim = math.floor( (self.out_dim + 2*self.padding[0] - self.kernel[0])/self.stride[0] ) + 1
self.out_dim = math.floor( (self.out_dim - self.kernel[0])/self.stride[0] ) + 1
self.out_dim = (self.out_dim**2)*self.out_channels
self.cnn_layers = None
self.classifier = None
def feature_extraction(self, x):
if self.cnn_layers == None:
print("CNN layers not defined...")
return
else:
features = self.cnn_layers(x)
return features.view(features.size(0), -1)
def forward(self, x):
if self.cnn_layers == None or self.classifier == None:
print("Layers not defined...")
return
else:
features = self.feature_extraction(x)
output = self.classifier(features)
return output
#return features
{"0": "bharatanatyam", "1": "kathak", "2": "kathakali", "3": "kuchipudi", "4": "manipuri", "5": "mohiniyattam", "6": "odissi", "7": "sattriya"}
\ No newline at end of file
import numpy as np
class Confusion_Matrix():
def __init__(self, classes):
self.classes = classes
self.matrix = np.zeros( (len(classes), len(classes)) )
def update_matrix(self, predicted, target):
zipped = zip(predicted, target)
for i in zipped:
self.matrix[i[0], i[1]] = self.matrix[i[0], i[1]] + 1
def get_accuracy(self):
tp = np.trace(self.matrix)
tot = np.sum(self.matrix)
return tp/tot
def weighted_f1_score(self):
row_sums = np.sum(self.matrix, axis=1)
col_sums = np.sum(self.matrix, axis=0)
f1_scores = []
weighted_f1 = 0
for i in range(self.matrix.shape[0]):
if row_sums[i]==0 or col_sums[i]==0:
f1_scores.append(0.0)
continue
precision = self.matrix[i,i]/row_sums[i]
recall = self.matrix[i,i]/col_sums[i]
if precision==0 or recall==0:
f1_scores.append(0.0)
else:
f1 = (2.0*precision*recall)/(precision+recall)
f1_scores.append(f1)
for i in range(len(f1_scores)):
weighted_f1 += f1_scores[i]*col_sums[i]
return weighted_f1/np.sum(col_sums)
import copy
import torch
from torch import optim
from sklearn import svm, metrics
import numpy as np
from . import confusion_matrix as cm
def cross_validation(models, learning_rate, criterion, block_imgs, block_labels, cuda_available, epochs):
loss_matrix = []
confusion_matrices = []
for model in models:
print("Evaluating model: {}".format(model))
accuracies = []
con_mats = []
for test_holdout in range(len(block_imgs)):
temp_model = copy.deepcopy(model)
con_mat = cm.Confusion_Matrix(range(8))
optimizer = optim.Adam(temp_model.parameters(), lr=learning_rate)
if cuda_available: temp_model.to("cuda")
for epoch in range(epochs):
temp_model.train()
for block in range(len(block_imgs)):
if block == test_holdout: continue
if cuda_available: images, labels = block_imgs[block].to("cuda"), block_labels[block].to("cuda")
else: images, labels = block_imgs[block], block_labels[block]
optimizer.zero_grad()
op = temp_model.forward(images)
loss = criterion(op, labels)
loss.backward()
optimizer.step()
temp_model.eval()
with torch.no_grad():
acc, probabilities = get_accuracy(temp_model, block_imgs[test_holdout], block_labels[test_holdout], cuda_available)
accuracies.append(acc)
print("Validation test block: {}\tAccuracy: {}".format(test_holdout, accuracies[-1]))
y_pred = probabilities.max(dim=1)[1]
con_mat.update_matrix(y_pred.tolist(), block_labels[test_holdout].tolist())
con_mats.append(con_mat)
del temp_model
if cuda_available: torch.cuda.empty_cache()
loss_matrix.append(accuracies)
confusion_matrices.append(con_mats)
return loss_matrix, confusion_matrices
def get_accuracy(model, imgs, labels, cuda_available):
accuracy = 0.0
if cuda_available: images, labels = imgs.to("cuda"), labels.to("cuda")
else: images, labels = imgs, labels
op = model.forward(images)
probabilities = torch.exp(op)
equalities = (labels.data == probabilities.max(dim=1)[1])
accuracy = equalities.type(torch.FloatTensor).mean()
return accuracy, probabilities
def cross_validation_svm(models, learning_rate, gamma_val, block_imgs, block_labels, criterion, cuda_available, epochs):
loss_matrix = []
confusion_matrices = []
for model in models:
print("Evaluating model: {}".format(model))
accuracies = []
con_mats = []
for test_holdout in range(len(block_imgs)):
temp_model = copy.deepcopy(model)
optimizer = optim.Adam(temp_model.parameters(), lr=learning_rate)
if cuda_available: temp_model.to("cuda")
svm_imgs = []
svm_labels = []
for k in range(len(block_imgs)):
if k == test_holdout: continue
svm_imgs.append(block_imgs[k])
svm_labels.append(block_labels[k])
for e in range(epochs):
temp_model.train()
for block in range(len(block_imgs)):
if block == test_holdout: continue
if cuda_available: images, labels = block_imgs[block].to("cuda"), block_labels[block].to("cuda")
else: images, labels = block_imgs[block], block_labels[block]
optimizer.zero_grad()
output = temp_model.forward(images)
loss = criterion(output, labels)
loss.backward()
optimizer.step()
temp_model.eval()
with torch.no_grad():
classifier = svm.SVC(gamma=gamma_val)
svm_train = svm_imgs[0]
svm_lbls = svm_labels[0]
for i in range(1, len(svm_imgs)):
svm_train = torch.cat((svm_train, svm_imgs[i]))
svm_lbls = torch.cat((svm_lbls, svm_labels[i]))
if cuda_available: classifier.fit(temp_model.feature_extraction(svm_train.to("cuda")).cpu().numpy(), svm_lbls.numpy())
else: classifier.fit(temp_model.feature_extraction(svm_train).numpy(), svm_lbls.numpy())
if cuda_available: y_pred = classifier.predict(temp_model.feature_extraction(block_imgs[test_holdout].to("cuda")).cpu().numpy())
else: y_pred = classifier.predict(temp_model.feature_extraction(block_imgs[test_holdout]).numpy())
equalities = (block_labels[test_holdout].data == torch.IntTensor(y_pred))
accuracy = equalities.type(torch.FloatTensor).mean()
accuracies.append(accuracy)
con_mat = cm.Confusion_Matrix(range(8))
con_mat.update_matrix(torch.IntTensor(y_pred).tolist(), block_labels[test_holdout].tolist())
con_mats.append(con_mat)
print("Validation test block: {}\tAccuracy: {}".format(test_holdout, accuracies[-1]))
del temp_model
if cuda_available: torch.cuda.empty_cache()
loss_matrix.append(accuracies)
confusion_matrices.append(con_mats)
return loss_matrix, confusion_matrices
def get_accuracy_svm(model, imgs, labels, cuda_available):
accuracy = 0.0
if cuda_available:
y_pred = model.classifier.predict(model.feature_extraction(imgs.to("cuda")).cpu().numpy())
else:
y_pred = model.classifier.predict(model.feature_extraction(imgs).numpy())
equalities = (labels.data == torch.IntTensor(y_pred))
accuracy = equalities.type(torch.FloatTensor).mean()
return accuracy
import torch
from torch.utils.data import DataLoader
from torchvision.datasets import ImageFolder
def train_test_split(img_folder, img_transforms, k, total_imgs):
image_set = ImageFolder(img_folder, transform=img_transforms)
image_loader = DataLoader(image_set, batch_size=int(total_imgs/k), shuffle=True)
image_blocks = []
label_blocks = []
for i,j in iter(image_loader):
image_blocks.append(i)
label_blocks.append(j)
return (image_blocks, label_blocks, image_set.classes)
def evaluate(model, img, lbl, criterion, cuda_available):
val_loss = 0
accuracy = 0
if cuda_available: images, labels = img.to('cuda'), lbl.to('cuda')
else: images, labels = img, lbl
output = model.forward(images)
val_loss += criterion(output, labels).item()
probabilities = torch.exp(output)
equality = (labels.data == probabilities.max(dim=1)[1])
accuracy += equality.type(torch.FloatTensor).mean()
return val_loss, accuracy, probabilities
def train_classifier(model, optimizer, criterion, epochs, image_blocks, image_labels, holdout, cuda_available):
steps = 0
model.to('cuda')
for epoch in range(epochs):
model.train()
train_loss = 0
for i in range(len(image_blocks)):
if i==holdout: continue
if cuda_available: images, labels = image_blocks[i].to('cuda'), image_labels[i].to('cuda')
else: images, labels = image_blocks[i], image_labels[i]
optimizer.zero_grad()
output = model.forward(images)
loss = criterion(output, labels)
loss.backward()
optimizer.step()
train_loss += loss.item()
model.eval()
with torch.no_grad():
validation_loss, accuracy, probabilities = evaluate(model, image_blocks[holdout], image_labels[holdout], criterion, cuda_available)
print("Epoch: [{}/{}]\tTraining Loss: {}\tValidation Loss: {}\t Validation Accuracy: {}".format(epoch+1, epochs, train_loss/image_blocks[0].shape[0], validation_loss, accuracy))
train_loss = 0
model.train()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment