Kaggle competition: Bengali.AI Handwritten Grapheme Classification
best_model = ReverseModel().to('cuda')
 best_model.load_state_dict(torch.load('logs/checkpoints/best.pth')['model_state_dict'] )<set_options>
!pip install.. /input/pretrainedmodels/pretrainedmodels-0.7.4/pretrainedmodels-0.7.4/ > /dev/null
%load_ext Cython<init_hyperparams>
import numpy as np
import pandas as pd
import os
import torch
import torch.nn as nn
from torch.utils.data import Dataset,DataLoader
from torchvision import transforms,models
from tqdm import tqdm_notebook as tqdm
import math
import torch.nn.functional as F
from torch.nn import init
import gc
import cv2
import pretrainedmodels
import torchvision
%%cython
c
@cython.cdivision(True)
 @cython.boundscheck(False)
 @cython.nonecheck(False)
 @cython.wraparound(False)
 cdef int calc_neighs(unsigned char[:, :] field, int i, int j, int n, int k):
cdef:
int neighs = 0;
int i_min = i - 1;
int i_pl = i + 1;
int j_min = j - 1;
int j_pl = j + 1;
neighs = 0
if i_min >= 0:
if j_min >= 0:
neighs += field[i_min, j_min]
neighs += field[i_min, j]
if j_pl < k:
neighs += field[i_min, j_pl]
if j_min >= 0:
neighs += field[i, j_min]
if j_pl < k:
neighs += field[i, j_pl]
if i_pl < n:
if j_min >= 0:
neighs += field[i_pl, j_min]
neighs += field[i_pl, j]
if j_pl < k:
neighs += field[i_pl, j_pl]
return neighs
@cython.cdivision(True)
 @cython.boundscheck(False)
 @cython.nonecheck(False)
 @cython.wraparound(False)
 cpdef make_move_cython(unsigned char[:, :] field, int moves):
cdef:
int _, i, j, neighs;
int n, k;
int switch = 0;
unsigned char[:, :] cur_field;
unsigned char[:, :] next_field;
cur_field = np.copy(field)
 next_field = np.zeros_like(field, 'uint8')
 n = field.shape[0]
k = field.shape[1]
for _ in range(moves):
if switch == 0:
for i in range(n):
for j in range(k):
neighs = calc_neighs(cur_field, i, j, n, k)
 if cur_field[i, j] and neighs == 2:
next_field[i, j] = 1
elif neighs == 3:
next_field[i, j] = 1
else:
next_field[i, j] = 0
else:
for i in range(n):
for j in range(k):
neighs = calc_neighs(next_field, i, j, n, k)
 if next_field[i, j] and neighs == 2:
cur_field[i, j] = 1
elif neighs == 3:
cur_field[i, j] = 1
else:
cur_field[i, j] = 0
switch =(switch + 1)% 2
return np.array(next_field if switch else cur_field)
<categorify>
HEIGHT = 137
WIDTH = 236
TRAIN = False
def make_move(board: Union[torch.Tensor, np.ndarray], moves: Union[int, List[int]] = 1):

 if isinstance(board, torch.Tensor):
return torch.tensor(_evolve_board(board.detach().cpu().numpy() , moves),
dtype=board.dtype, device=board.device)
 return np.array(_evolve_board(board, moves), dtype=board.dtype)
 def _evolve_board(board, moves):
board = np.array(board ).astype(np.uint8)
 if len(board.shape)== 4:
assert board.shape[1:] ==(1, 25, 25)
 board_evolved = _move_board_3dim(board[:, 0], moves)[:, None]
elif len(board.shape)== 3:
board_evolved = _move_board_3dim(board, moves)
 else:
assert board.shape ==(25, 25)
 board_evolved = make_move_cython(board, moves)
 return np.array(board_evolved, dtype=np.float32)
 def _move_board_3dim(board, moves):
if board.shape ==(1, 25, 25):
board_evolved = make_move_cython(board[0], moves)[:, None]
else:
assert board.shape[1:] ==(25, 25)
 if isinstance(moves, int):
moves = [moves] * len(board)
 assert len(moves)== len(board)
 board_evolved = np.array([make_move_cython(b, move)for b, move in zip(board, moves)])
 return board_evolved 
<compute_train_metric>
def prepare_image(dataType = 'train', indices = [0,1,2,3]):
assert dataType in ['train', 'test']
HEIGHT = 137
WIDTH = 236
images = []
for i in indices:
image_df = pd.read_parquet(f'.. /input/bengaliai-cv19/{dataType}_image_data_{i}.parquet')
 images.append(image_df.iloc[:,1:].values.reshape(-1,HEIGHT,WIDTH))
del image_df
gc.collect()
images = np.concatenate(images, axis = 0)
 return images
def batch_accuracy(x, y_pred):
return torch.sum(torch.abs(x - y_pred), dim=(1, 2, 3))
def postprocessor(y_pred, x, moves):

 thresholds = torch.linspace(0, 1, 11, device=x.device)
 errors = torch.cat([batch_accuracy(x.float() ,
make_move(( y_pred > threshold ).float() , moves)
)[None]
for threshold in thresholds],
0)
 best_thresholds = thresholds[torch.argmin(errors, 0)][:, None, None, None]
return(y_pred > best_thresholds ).float() 
<predict_on_test>
if TRAIN:
train = pd.read_csv('/kaggle/input/bengaliai-cv19/train.csv')
 train_labels = train[['grapheme_root', 'vowel_diacritic', 'consonant_diacritic']].values
train_images = prepare_image()
def predict_batch(model, batch):
model.eval()
with torch.no_grad() :
prediction = model(batch['stop'], batch['delta'])
 prediction = torch.sigmoid(prediction ).detach().cpu().numpy()
return prediction
def predict_loader(model, loader):
predict = [predict_batch(model, batch)for batch in loader]
predict = np.concatenate(predict)
 return predict
def validate_loader(model, loader, lb_delta=None, threshold=0.5):
prediction_val = predict_loader(best_model, loader)
 y_val = loader.dataset.start.detach().cpu().numpy()
score_unoptimized =(( prediction_val > threshold)== y_val ).mean(axis=(1,2,3))
delta_val = loader.dataset.delta.detach().cpu().numpy()
prediction_val = postprocessor(torch.tensor(prediction_val),
x=loader.dataset.stop.cpu() ,
moves=delta_val ).cpu().numpy()
score =(prediction_val == y_val ).mean(axis=(1,2,3))
print(f'All data accuracy(global threshold): {score_unoptimized.mean() }')
 print(f'All data accuracy(optimized threshold): {score.mean() }')
 delta_score = {}
for i in range(1, 6):
delta_score[i] = score[delta_val==i].mean()
print(f'delta={i} accuracy: {delta_score[i]}')
 if lb_delta is not None:
lb_delta = lb_delta.value_counts(normalize=True)
 test_score = sum([lb_delta[i]*delta_score[i] for i in range(1,6)])
 print(f'VAL score : {1-score.mean() }')
 print(f'LB score estimate: {1-test_score}')
 def make_submission(prediction, x, moves, sample_submission_path='/kaggle/input/conways-reverse-game-of-life-2020/sample_submission.csv'):
prediction = postprocessor(prediction, x, moves ).numpy().astype(int ).reshape(-1, 625)
 sample_submission = pd.read_csv(sample_submission_path, index_col='id')
 sample_submission.iloc[:] = prediction
return sample_submission<compute_test_metric>
class BengaliAIDataset(Dataset):
def __init__(self, images, labels=None, indices=None):
super(BengaliAIDataset, self ).__init__()
self.images = images
self.labels = labels
if indices is None:
indices = np.arange(len(images))
self.indices = indices
self.train = labels is not None
def __len__(self):

 return len(self.indices)
 def __getitem__(self, i):

 i = self.indices[i]
x = self.images[i]
x =(255 - x ).astype(np.float32)
 x =(x*(255.0/x.max())).astype(np.float32)
 x = crop_resize(x,224)
 x = np.stack(( x,)*3,axis=-1)
 x = x * [0.229, 0.224, 0.225]
x = np.rollaxis(x, 2, 0)
 x = x.astype(np.float32)/255.0
if self.train:
y = self.labels[i]
return x, y
else:
return x
validate_loader(best_model, dataloader_val, test['delta'] )<save_to_csv>
def MyModel() :
model = pretrainedmodels.__dict__['densenet161'](pretrained=None)
 model.last_linear = nn.Linear(model.last_linear.in_features, 186)
 return model
prediction_test = predict_loader(best_model, dataloader_test)
 submission = make_submission(torch.tensor(prediction_test),
x=dataloader_test.dataset.stop.cpu() ,
moves=dataloader_test.dataset.delta.detach().cpu().numpy())
 submission.to_csv('submission.csv')
 submission.head()<load_from_csv>
device = torch.device('cuda:0' )
sample = pd.read_csv('/kaggle/input/conways-reverse-game-of-life-2020/sample_submission.csv')
 test = pd.read_csv('/kaggle/input/conways-reverse-game-of-life-2020/test.csv')
 train = pd.read_csv('/kaggle/input/conways-reverse-game-of-life-2020/train.csv')
<count_unique_values>
model = MyModel().to(device )
train.id.nunique()<count_values>
if TRAIN:
optimizer = torch.optim.Adam(model.parameters() , lr=4e-4)
 scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', patience=2, factor=0.3)
 criterion = nn.CrossEntropyLoss()
batch_size=32
num_images = len(train_images)
 train_data_size = int(num_images*0.9)
 test_data_size = num_images - train_data_size
perm = np.random.RandomState(111 ).permutation(num_images)
 train_dataset = BengaliAIDataset(train_images, train_labels, indices=perm[:train_data_size])
 valid_dataset = BengaliAIDataset(train_images, train_labels, indices=perm[train_data_size:train_data_size+test_data_size])
 train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size,shuffle=True)
 valid_loader = torch.utils.data.DataLoader(valid_dataset,batch_size=batch_size,shuffle=True)
 epochs = 10
losses=[]
accs=[]
train_root_accs = []
val_root_accs = []
train_vowel_accs = []
val_vowel_accs = []
train_con_accs = []
val_con_accs = []
train_accs = []
val_accs = []
train.delta.value_counts()<count_values>
if not TRAIN:
load_model_path = '/kaggle/input/dense161/seresnet50(3 ).pth'
checkpoint = torch.load(load_model_path)
 model.load_state_dict(checkpoint['model_state_dict'] )
train.start_0.value_counts()<count_values>
import numpy
train.stop_0.value_counts()<define_variables>
if TRAIN:
for epoch in range(epochs):
gc.collect()
print('epochs {}/{} '.format(epoch+1,epochs))
running_loss = 0.0
root_acc = 0.0
vowel_acc = 0.0
con_acc = 0.0
model.train()
for idx,(inputs,labels)in tqdm(enumerate(train_loader),total=len(train_loader)) :
inputs = inputs.to(device)
 labels = labels.to(device)
 output = model(inputs.float())
 outputs = torch.split(output, [168, 11, 7], dim=1)
 loss1 = criterion(outputs[0],labels[:,0])
 loss2 = criterion(outputs[1],labels[:,1])
 loss3 = criterion(outputs[2],labels[:,2])
 running_loss +=(2*loss1 + loss2 + loss3)
 root_acc +=(outputs[0].argmax(1)==labels[:,0] ).float().mean()
vowel_acc +=(outputs[1].argmax(1)==labels[:,1] ).float().mean()
con_acc +=(outputs[2].argmax(1)==labels[:,2] ).float().mean() 
(2*loss1 + loss2 + loss3 ).backward()
optimizer.step()
del inputs
del labels
losses.append(running_loss/len(train_loader))
train_root_acc = root_acc/(len(train_loader))
train_vowel_acc = vowel_acc/(len(train_loader))
train_con_acc = con_acc/(len(train_loader))
train_root_accs.append(train_root_acc)
 train_vowel_accs.append(train_vowel_acc)
 train_con_accs.append(train_con_acc)
 act_train =(2*train_root_acc+train_vowel_acc+train_con_acc)/4.0
accs.append(act_train)
 print('acc : {:.4f}'.format(act_train))
print('root_acc : {:.4f}'.format(train_root_acc))
print('vowel_acc : {:.4f}'.format(train_vowel_acc))
print('con acc : {:.4f}'.format(train_con_acc))
print('loss : {:.4f}'.format(running_loss/len(train_loader)))
 val_loss = 0.0
root_acc = 0.0
vowel_acc = 0.0
con_acc = 0.0
model.eval()
with torch.no_grad() :
for idx,(inputs,labels)in tqdm(enumerate(valid_loader),total=len(valid_loader)) :
inputs = inputs.to(device)
 labels = labels.to(device)
 output = model(inputs.float())
 outputs = torch.split(output, [168, 11, 7], dim=1)
 loss11 = criterion(outputs[0],labels[:,0])
 loss21 = criterion(outputs[1],labels[:,1])
 loss31 = criterion(outputs[2],labels[:,2])
 val_loss +=(2*loss11 + loss21 + loss31)
 root_acc +=(outputs[0].argmax(1)==labels[:,0] ).float().mean()
vowel_acc +=(outputs[1].argmax(1)==labels[:,1] ).float().mean()
con_acc +=(outputs[2].argmax(1)==labels[:,2] ).float().mean()
del inputs
del labels
gc.collect()
val_root_acc = root_acc/(len(valid_loader))
val_vowel_acc = vowel_acc/(len(valid_loader))
val_con_acc = con_acc/(len(valid_loader))
val_root_accs.append(val_root_acc)
 val_vowel_accs.append(val_vowel_acc)
 val_con_accs.append(val_con_acc)
 act_val =(2*val_root_acc+val_vowel_acc+val_con_acc)/4.0
val_loss = val_loss/3.0
scheduler.step(val_loss)
 print('val_acc : {:.4f}'.format(act_val))
print('root_acc : {:.4f}'.format(val_root_acc))
print('vowel_acc : {:.4f}'.format(val_vowel_acc))
print('con acc : {:.4f}'.format(val_con_acc))
print('loss : {:.4f}'.format(val_loss/len(valid_loader)))
 file_name = str(act_train)+'_'+str(act_val)+'_.tar'
torch.save({
'model_state_dict':model.state_dict() ,
'optimizer_state_dict':optimizer.state_dict() ,
},'weight.pth')
 print()
print()
sample_start_1 = train.loc[1, train.columns.str.startswith('start')]
sample_stop_1 = train.loc[1, train.columns.str.startswith('stop')]<prepare_x_and_y>
data_type = 'test'
test_preds_list = []
for i in range(4):
gc.collect()
indices = [i]
test_images = prepare_image(data_type,indices=indices)
 n_dataset = len(test_images)
 print(f'i={i}, n_dataset={n_dataset}')
 test_dataset = BengaliAIDataset(test_images)
 print('test_dataset', len(test_dataset))
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16, shuffle=False)
 for idx, inputs in enumerate(test_loader):
inputs = inputs.to(device)
 output = model(inputs.float())
 outputs = torch.split(output, [168, 11, 7], dim=1)
 outputs = outputs[0].argmax(1), outputs[1].argmax(1), outputs[2].argmax(1)
 test_preds_list.append(outputs)
 del test_images
gc.collect()
sample_start_1 = np.asarray(sample_start_1 ).reshape(25, 25)
 sample_stop_1 = np.asarray(sample_stop_1 ).reshape(25, 25 )<sort_values>
p0 = np.concatenate([test_preds[0].cpu().detach().numpy() for test_preds in test_preds_list], axis=0)
 p1 = np.concatenate([test_preds[1].cpu().detach().numpy() for test_preds in test_preds_list], axis=0)
 p2 = np.concatenate([test_preds[2].cpu().detach().numpy() for test_preds in test_preds_list], axis=0)
 print('p0', p0.shape, 'p1', p1.shape, 'p2', p2.shape )
train.sum() [1:].sort_values()<define_variables>
row_id = []
target = []
for i in range(len(p0)) :
row_id += [f'Test_{i}_consonant_diacritic', f'Test_{i}_grapheme_root',
f'Test_{i}_vowel_diacritic']
target += [p2[i], p0[i], p1[i]]
<init_hyperparams><EOS> 
submission_df = pd.DataFrame({'row_id': row_id, 'target': target})
 submission_df.to_csv('submission.csv', index=False )