From: https://www.kaggle.com/gskdhiman/pytorch-resnet50-starter
Author: Gursewak Dhiman
Score: 0.449
import os
import pandas as pd
import numpy as np
from random import seed
from random import randint
import torch
from torch import nn
from torch import optim
import torch.nn.functional as F
from torchvision import datasets, transforms, models
from PIL import Image
from matplotlib import pyplot as plt
%matplotlib inline
input_dir = os.path.join('..','input','imet-2019-fgvc6')
train_dir = os.path.join(input_dir,'train')
test_dir = os.path.join(input_dir,'test')
labels_csv= os.path.join(input_dir,'labels.csv')
train_csv = os.path.join(input_dir,'train.csv')
resnet_weights_path = os.path.join('..','input','resnet50','resnet50.pth')
BATCH_SIZE = 128
NUM_EPOCHS = 20
PERCENTILE = 99.7
LEARNING_RATE = 0.002
df = pd.read_csv(labels_csv)
attribute_dict = dict(zip(df.attribute_id,df.attribute_name))
del df,labels_csv
tag_count = 0
culture_count = 0
for idx,data in attribute_dict.items():
if data.split("::")[0] == 'tag':
tag_count+=1
if data.split("::")[0] == 'culture':
culture_count+=1
print('total_categories: {0}\ntag_categories: {1} \nculture_categories: {2} ' \
.format(len(attribute_dict),tag_count,culture_count))
#cross check your results
assert tag_count+culture_count == len(attribute_dict)
df = pd.read_csv(train_csv)
labels_dict = dict(zip(df.id,df.attribute_ids))
idx = len(os.listdir(train_dir))
number = randint(0,idx)
image_name = os.listdir(train_dir)[number]
def imshow(image):
"""Display image"""
plt.figure(figsize=(6, 6))
plt.imshow(image)
plt.show()
# Example image
x = Image.open(os.path.join(train_dir,image_name))
for i in labels_dict[os.listdir(train_dir)[number].split('.')[0]].split():
print(attribute_dict[int(i)])
np.array(x).shape
imshow(x)
# need to add more transforms here
data_transforms = transforms.Compose([
transforms.Resize((224,224)),
transforms.ToTensor(),
])
from collections import Counter
from torch.utils import data
class ImageData(data.Dataset):
def __init__(self,df,dirpath,transform,test = False):
self.df = df
self.test = test
self.dirpath = dirpath
self.conv_to_tensor = transform
#image data
if not self.test:
self.image_arr = np.asarray(str(self.dirpath)+'/'+self.df.iloc[:, 0]+'.png')
else:
self.image_arr = np.asarray(str(self.dirpath)+'/'+self.df.iloc[:, 0])
#labels data
if not self.test:
data_labels = self.df.iloc[:,1].str.split().apply(lambda x: [int(i) for i in x]).apply(Counter)
data = pd.DataFrame.from_records(data_labels).fillna(value=0)
self.label_arr = np.asarray(data)
# Calculate length of df
self.data_len = len(self.df.index)
def __len__(self):
return self.data_len
def __getitem__(self, idx):
image_name = self.image_arr[idx]
img = Image.open(image_name)
img_tensor = self.conv_to_tensor(img)
if not self.test:
image_label = self.label_arr[idx]
image_label = torch.tensor(image_label,dtype= torch.float32)
return (img_tensor,image_label)
return (img_tensor)
train_df = pd.read_csv(train_csv)
train_dataset = ImageData(train_df,train_dir,data_transforms)
train_loader = data.DataLoader(dataset=train_dataset,batch_size=BATCH_SIZE,shuffle=False)
test_df = pd.DataFrame(os.listdir(test_dir))
test_dataset = ImageData(test_df,test_dir,data_transforms,test = True)
test_loader = data.DataLoader(dataset=test_dataset,batch_size=BATCH_SIZE,shuffle=False)
print("************Train*****************")
features, labels = next(iter(train_loader))
print(f'Features Size: {features.shape}\nLabels Size: {labels.shape}')
print()
print("************Test*****************")
features = next(iter(test_loader))
print(f'Features Size: {features.shape}\n')
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
device
resnet_cls = models.resnet50()
resnet_cls.load_state_dict(torch.load(resnet_weights_path))
class AvgPool(nn.Module):
def forward(self, x):
return F.avg_pool2d(x, x.shape[2:])
class ResNet50(nn.Module):
def __init__(self,num_outputs):
super(ResNet50,self).__init__()
self.resnet = resnet_cls
self.resnet.avgpool = AvgPool()
self.resnet.fc = nn.Linear(2048, num_outputs)
for param in self.resnet.parameters():
param.requires_grad = False
for param in self.resnet.layer4.parameters():
param.requires_grad = True
for param in self.resnet.fc.parameters():
param.requires_grad = True
def forward(self,x):
out = self.resnet(x)
return out
output_dim = len(attribute_dict)
NeuralNet = ResNet50(num_outputs = output_dim)
total_params = sum(p.numel() for p in NeuralNet.parameters())
print(f'{total_params:,} total parameters.')
total_trainable_params = sum(p.numel() for p in NeuralNet.parameters() if p.requires_grad)
print(f'{total_trainable_params:,} training parameters.')
print("training examples: ",len(train_dataset))
print("batch size: ",BATCH_SIZE)
print("batches available: ",len(train_loader))
import time
from torch import optim
NeuralNet = NeuralNet.to(device)
loss_func = torch.nn.BCEWithLogitsLoss()
optimizer = optim.Adam(NeuralNet.parameters() ,lr = LEARNING_RATE)
from tqdm import tqdm_notebook as tqdm
total_loss = {}
for epoch in range(NUM_EPOCHS):
start_time = time.time()
NeuralNet.train()
avg_loss = 0.
avg_loss_history = {}
i = 0
for images_batch, labels_batch in tqdm(train_loader):
images_batch = images_batch.to(device)
labels_batch = labels_batch.to(device)
pred_batch = NeuralNet(images_batch)
loss = loss_func(pred_batch, labels_batch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
avg_loss += loss.item() / len(train_loader)
if i%250 == 0:
print(avg_loss)
avg_loss_history[i]=avg_loss
i+=1
print("Epoch: {}/{} | loss: {} | time: {:.3f}sec".format(epoch+1,NUM_EPOCHS,avg_loss,time.time()-start_time))
total_loss[epoch] = avg_loss_history
# total_loss dict can be used for loss visualization
NeuralNet.eval()
predictions = np.zeros((len(test_dataset), output_dim))
i = 0
for test_batch in tqdm(test_loader):
test_batch = test_batch.to(device)
batch_prediction = NeuralNet(test_batch).detach().cpu().numpy()
predictions[i * BATCH_SIZE:(i+1) * BATCH_SIZE, :] = batch_prediction
i+=1
"""credits to https://www.kaggle.com/ateplyuk/keras-starter"""
"""this is little modified version of above with tqdm and percentile addition"""
"""np.where will be much faster than this"""
import operator
predicted_class_idx = []
for i in tqdm(range(len(predictions))):
d = {}
for index, value in enumerate(predictions[i]):
if value > np.percentile(predictions[i],PERCENTILE):
d[index] = value
sorted_d = sorted(d.items(), key=operator.itemgetter(1), reverse=True)
predicted_class_idx.append([i[0] for i in sorted_d[:10]])
test_df['attribute_ids'] = predicted_class_idx
test_df['attribute_ids'] = test_df['attribute_ids'].apply(lambda x : ' '.join(map(str,list(x))))
test_df = test_df.rename(columns={0: 'id'})
test_df['id'] = test_df['id'].apply(lambda x : x.split('.')[0])
test_df.head()
test_df.to_csv('submission.csv',index = False)