Kaggle competition: Bengali.AI Handwritten Grapheme Classification
<SOS> metric: WeightedCategorizationAccuracy Kaggle data source: bengali.ai-handwritten-grapheme-classification<set_options>
!pip install /kaggle/input/timm-model/timm-0.3.2-py3-none-any.whl
def seed_everything(seed=0):
random.seed(seed)
 np.random.seed(seed)
 tf.random.set_seed(seed)
 os.environ['PYTHONHASHSEED'] = str(seed)
 os.environ['TF_DETERMINISTIC_OPS'] = '1'
SEED = 0
seed_everything(SEED )<define_variables>
import pandas as pd
import cv2
import numpy as np
from tqdm.auto import tqdm
from matplotlib import pyplot as plt
import time
import pyarrow.parquet as pq
HEIGHT = 256
WIDTH = 256
HEIGHT_RESIZE = 128
WIDTH_RESIZE = 128
CHANNELS = 3
BATCH_SIZE = 16
EPOCHS = 120
TRANSFORMER_BLOCKS = 6
GENERATOR_LR = 2e-4
DISCRIMINATOR_LR = 2e-4<normalization>
class BengaliDataset(Dataset):
def __init__(self, label_csv, unique_csv, train_folder, parquet_path, transforms, cache=True, test=True):
self.label_csv = label_csv
self.unique_csv = unique_csv
self.train_folder = train_folder
self.parquet_path = parquet_path
self.label = pd.read_csv(self.label_csv)
 self.label = self.label[self.label['component']=='grapheme_root']
self.label = self.label.reset_index(drop=True)
 unique_df = pd.read_csv(self.unique_csv)
 self.names = self.label['image_id'].values
self.uniques = unique_df.grapheme.unique()
self.transforms = transforms
self.img = [None] * self.label.shape[0]
self.test = test
if cache:
self.cache_images()
def cache_images(self):
count = 0
root = './test_graphemes/'
self.p = p = pd.read_parquet(self.parquet_path ).drop(['image_id'], axis=1)
 def load_image(self, idx):
img = resize(self.p.iloc[[idx]] ).values.reshape(-1 ).reshape(IMG_SIZE, IMG_SIZE ).astype(np.uint8)
 return self.transforms(img)
 img = self.img[idx]
if img is None:
img = resize(p.iloc[[i]] ).values.reshape(-1 ).reshape(IMG_SIZE, IMG_SIZE ).astype(np.uint8)
 return self.transforms(img)
 else:
return self.transforms(img)
 def __getitem__(self, idx):
if not self.test:
img = self.load_image(idx)
 root = self.label.loc[idx]['grapheme_root']
consonant = self.label.loc[idx]['consonant_diacritic']
vowel = self.label.loc[idx]['vowel_diacritic']
unique = np.where(self.uniques == self.label.grapheme[idx])[0][0]
return transforms.ToTensor()(img), root, consonant, vowel, unique
else:
img = self.load_image(idx)
 root = 0
consonant = 0
vowel = 0
unique = 0
return transforms.ToTensor()(img), root, consonant, vowel, unique
def __len__(self):
return self.p.shape[0]
def postprocess(preds, num_classes, EXP = -1.2):
p0 = np.argmax(preds,axis=1)
 s = pd.Series(p0)
 vc = s.value_counts().sort_index()
df = pd.DataFrame({'a':np.arange(num_classes),'b':np.ones(num_classes)})
 df.b = df.a.map(vc)
 df.fillna(df.b.min() ,inplace=True)
 mat1 = np.diag(df.b.astype('float32')**EXP)
 p0 = np.argmax(preds.dot(mat1), axis=1)
 return p0
class Tester:
def __init__(self,
dataset_path='./drive/MyDrive/datasets/car classification/train_data',
batch_size=1,
model_name='tf_efficientnet_b3_ns',
test_csv='./train_labels.csv',
unique_csv='./train_labels.csv',
output_dir='.. /drive/MyDrive/ckpt/grapheme/submission.csv',
ckpt='.. /drive/MyDrive/ckpt/grapheme/20.pth'):
self.dataset_path = dataset_path
self.batch_size = batch_size
self.model_name = model_name
self.test_csv = test_csv
self.unique_csv = unique_csv
self.output_dir = output_dir
self.ckpt = ckpt
if model_name == 'tf_efficientnet_b0_ns':
self.input_size =(224, 224)
 elif model_name == 'tf_efficientnet_b2_ns':
self.input_size =(260, 260)
 elif model_name == 'tf_efficientnet_b3_ns':
self.input_size =(300, 300)
 elif model_name == 'tf_efficientnet_b4_ns':
self.input_size =(380, 380)
 elif model_name == 'tf_efficientnet_b6_ns':
self.input_size =(528, 528)
 else:
raise Exception('non-valid model name')
 transform = []
transform += [transforms.ToPILImage() ]
transform += [transforms.Resize(self.input_size)]
self.transform = transforms.Compose(transform)
 self.device = torch.device('cuda')
 self.model_root = create_model(self.model_name, pretrained=False, num_classes=168 ).to(self.device)
 self.model_consonant = create_model(self.model_name, pretrained=False, num_classes=8 ).to(self.device)
 self.model_vowel = create_model(self.model_name, pretrained=False, num_classes=11 ).to(self.device)
 ckpt = torch.load(self.ckpt)
 self.model_root.load_state_dict(ckpt['model_root_state_dict'])
 self.model_consonant.load_state_dict(ckpt['model_consonant_state_dict'])
 self.model_vowel.load_state_dict(ckpt['model_vowel_state_dict'])
 def test(self):
output_roots = []
output_consonants = []
output_vowels = []
count = 0
for ii in range(4):
self.test_dataset = BengaliDataset(self.test_csv, self.unique_csv, self.dataset_path, f'/kaggle/input/bengaliai-cv19/test_image_data_{ii}.parquet', self.transform, cache=True)
 self.names = self.test_dataset.names
self.test_dataloader = DataLoader(self.test_dataset, batch_size=self.batch_size, num_workers=0, shuffle=False)
 pbar = tqdm.tqdm(self.test_dataloader)
 pbar.set_description('testing process')
 self.model_root.eval()
self.model_consonant.eval()
self.model_vowel.eval()
with torch.no_grad() :
for it, data in enumerate(pbar):
inputs = data[0].to(self.device)
 inputs = inputs.repeat(1, 3, 1, 1)
 roots = data[1].to(self.device ).long()
consonants = data[2].to(self.device ).long()
vowels = data[3].to(self.device ).long()
uniques = data[4].to(self.device ).long()
root_preds = self.model_root(inputs)
 self.model_root.zero_grad()
consonant_preds = self.model_consonant(inputs)
 self.model_consonant.zero_grad()
vowel_preds = self.model_vowel(inputs)
 self.model_vowel.zero_grad()
root_preds = postprocess(torch.nn.Softmax(1 )(root_preds ).cpu().numpy() , 168, -0.6)
 consonant_preds = postprocess(torch.nn.Softmax(1 )(consonant_preds ).cpu().numpy() , 8, -0.6)
 vowel_preds = postprocess(torch.nn.Softmax(1 )(vowel_preds ).cpu().numpy() , 11, -1.1)
 for index in range(inputs.shape[0]):
output_roots.append(root_preds[index].item())
 output_consonants.append(consonant_preds[index].item())
 output_vowels.append(vowel_preds[index].item())
 del self.test_dataset.p
del self.test_dataset
del self.test_dataloader
row_id, target = [], []
for iid, r, c, v in zip(self.names, output_roots, output_consonants, output_vowels):
row_id.append(iid + '_grapheme_root')
 target.append(int(r))
row_id.append(iid + '_vowel_diacritic')
 target.append(int(v))
row_id.append(iid + '_consonant_diacritic')
 target.append(int(c))
count += 1
sub_fn = self.output_dir
sub = pd.DataFrame({'row_id': row_id, 'target': target})
 sub.to_csv(sub_fn, index=False)
 print(f'Done wrote to {sub_fn}')
 tester = Tester(dataset_path='./test_graphemes',
batch_size=128,
model_name='tf_efficientnet_b2_ns',
test_csv='/kaggle/input/bengaliai-cv19/test.csv',
unique_csv='/kaggle/input/bengaliai-cv19/train.csv',
output_dir='./submission.csv',
ckpt='/kaggle/input/graphemesingle/27.pth' 
)
 tester.test()