Kaggle competition: Bengali.AI Handwritten Grapheme Classification
<SOS> metric: WeightedCategorizationAccuracy Kaggle data source: bengali.ai-handwritten-grapheme-classification<define_variables>
!pip install.. /input/kaggle-efficientnet-repo/efficientnet-1.0.0-py3-none-any.whl
neighbors_roll_axes = [(i,j)for i in range(-1,2)for j in range(-1, 2)if not(i==0 and j==0)]
def generate_random_start_batch(batch_size):
return np.random.randint(low=0, high=2, size=(batch_size, 1, 25, 25), dtype=bool)
 def straight_iter_binary_numpy(grid, delta=1):
for _ in range(delta):
neighbor_sum = np.concatenate([np.roll(np.roll(grid, i, 2), j, 3)for i,j in neighbors_roll_axes], axis=1)
 neighbor_sum = neighbor_sum.sum(axis=1, keepdims=True)
 grid =(( neighbor_sum == 3)|(( grid==1)&(neighbor_sum == 2)))
 return grid
class DataStream() :
def __init__(self, delta=None, batch_size=128, drop_empty=False, drop_ch_dim=False):
self.init_delta = delta
self.batch_size = batch_size
self.drop_empty= drop_empty
self.drop_ch_dim = drop_ch_dim
def __iter__(self):
while True:
x = generate_random_start_batch(self.batch_size)
 delta = self.init_delta if self.init_delta else np.random.randint(1,6)
 x = straight_iter_binary_numpy(x, 5+delta)
 if self.drop_empty:
x = x[x.any(axis=2 ).any(axis=2 ).reshape(-1)]
if self.drop_ch_dim:
x = x[:,0,:,:]
yield x.astype(float), delta<choose_model_class>
%matplotlib inline
start_time = time.time()
class DataStreamTorch(IterableDataset):
def __init__(self, delta=None, batch_size=128, drop_empty=False, drop_ch_dim=False):
self.ds = DataStream(delta, batch_size, drop_empty, drop_ch_dim)
 def __iter__(self):
for x, delta in self.ds:
yield FloatTensor(x), delta
def pass_collate(batch):
return batch[0]
def get_datastream_loader(delta=None, batch_size=128, drop_empty=False, drop_ch_dim=False, num_workers=1):
dataset = DataStreamTorch(delta, batch_size, drop_empty, drop_ch_dim)
 dataloader = DataLoader(dataset, batch_size=1, collate_fn=pass_collate, num_workers=num_workers)
 return dataloader<choose_model_class>
dataset = '/kaggle/input/bengaliai-cv19'
pretrained = '.. /input/bangla-graphemes-pretrained-weights'
class Model(nn.Module):
def __init__(self):
super().__init__()
self.relu = nn.ReLU()
self.conv1 = nn.Conv2d(1, 512, 7, padding=3, padding_mode='circular')
 self.conv2 = nn.Conv2d(512, 256, 5, padding=2, padding_mode='circular')
 self.conv3 = nn.Conv2d(256, 256, 3, padding=1, padding_mode='circular')
 self.conv4 = nn.Conv2d(256, 1, 1)
 self.sigmoid = nn.Sigmoid()
def forward(self, x):
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.relu(self.conv3(x))
x = self.sigmoid(self.conv4(x))
return x<define_search_model>
if os.path.isfile(os.path.join(pretrained,"efficientNetB3.h5")) \
and os.path.isfile(os.path.join(pretrained,"enet.csv")) :
print('Model is present')
 else:
print("Error.No Model Found" )
class FixPredictBlock(nn.Module):
def __init__(self):
super().__init__()
self.relu = nn.ReLU()
self.conv1 = nn.Conv2d(5, 256, 5, padding=2, padding_mode='circular')
 self.conv2 = nn.Conv2d(256, 256, 3, padding=1, padding_mode='circular')
 self.conv3 = nn.Conv2d(256, 256, 1)
 self.conv4 = nn.Conv2d(256, 1, 3, padding=1, padding_mode='circular')
 self.sigmoid = nn.Sigmoid()
def forward(self, x, x_prev_pred):
with torch.no_grad() :
x_prev_pred_bin = x_prev_pred>0.5
x_pred_bin = binary_forward_iteration(x_prev_pred_bin)
 x_pred = probabilistic_forward_iteration(x_prev_pred)
 x = torch.cat([x, x_prev_pred, x_prev_pred_bin.float() , x_pred, x_pred_bin.float() ], dim=1)
 x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.relu(self.conv3(x))
x = self.sigmoid(self.conv4(x))
return x
class Model(nn.Module):
def __init__(self):
super().__init__()
self.fix_pred = FixPredictBlock()
def forward(self, x, n_it=5):
x_prev_pred = x
for i in range(n_it):
x_prev_pred = self.fix_pred(x, x_prev_pred)
 return x_prev_pred<choose_model_class>
SIZE = 80
N_ch = 1
N_iter = 200
device = 'cuda'
loader = get_datastream_loader(batch_size=128, num_workers=8, drop_empty=True, delta=1)
 model = Model().to(device)
 criterion = BCELoss()
optimizer = Adam(model.parameters() , lr=1e-3)
 tqdm_loader = tqdm(loader)
 for i,(stop_state, _)in enumerate(tqdm_loader):
stop_state = stop_state.to(device)
 optimizer.zero_grad()
start_state_prediction = model(stop_state)
 stop_state_prediction = probabilistic_forward_iteration(start_state_prediction)
 loss = criterion(stop_state_prediction, stop_state)
 loss.backward()
optimizer.step()
with torch.no_grad() :
bce = loss.item()
start_state_alive =(start_state_prediction>0.5 ).float().mean().item()
accuracy =(( stop_state_prediction > 0.5)==(stop_state>0.5)).float().mean().item()
accuracy_true =(binary_forward_iteration(start_state_prediction>0.5)==(stop_state>0.5)).float().mean().item()
tqdm_loader.postfix = 'bce: {:0.10f} | start_state_alive: {:0.5f} | accuracy: {:0.10f} | accuracy_true: {:0.10f}'\ 
.format(bce, start_state_alive, accuracy, accuracy_true)
 if i > N_iter:
tqdm_loader.close()
break
for param in model.parameters() :
param.requires_grad = False
model.eval()<define_search_space>
model = load_model(os.path.join(pretrained, 'efficientNetB3.h5'))
for batch in loader:
stop_state = batch[0].cuda()
break
for n_iter in [1,10,100]:
acc =(stop_state == binary_forward_iteration(model(stop_state, n_iter)> 0.5)).float().mean().item()
print(f'model n_iter={n_iter} accuracy: {acc}' )<choose_model_class>
def resize(df, size=80):
resized = {}
resize_size=80
angle=0
for i in range(df.shape[0]):
image=df.loc[df.index[i]].values.reshape(137,236)
 image_center = tuple(np.array(image.shape[1::-1])/ 2)
 matrix = cv2.getRotationMatrix2D(image_center, angle, 1.0)
 image = cv2.warpAffine(image, matrix, image.shape[1::-1], flags=cv2.INTER_AREA,
borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0))
matrix = cv2.getRotationMatrix2D(image_center, 0, 1.0)
 image = cv2.warpAffine(image, matrix, image.shape[1::-1], flags=cv2.INTER_AREA,
borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0))
augBright=A.RandomBrightnessContrast(p=1.0)
 image = augBright(image=image)['image']
_, thresh = cv2.threshold(image, 30, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
 contours, _ = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[-2:]
idx = 0
ls_xmin = []
ls_ymin = []
ls_xmax = []
ls_ymax = []
for cnt in contours:
idx += 1
x,y,w,h = cv2.boundingRect(cnt)
 ls_xmin.append(x)
 ls_ymin.append(y)
 ls_xmax.append(x + w)
 ls_ymax.append(y + h)
 xmin = min(ls_xmin)
 ymin = min(ls_ymin)
 xmax = max(ls_xmax)
 ymax = max(ls_ymax)
 roi = image[ymin:ymax,xmin:xmax]
resized_roi = cv2.resize(roi,(resize_size, resize_size),interpolation=cv2.INTER_AREA)
 resized[df.index[i]] = resized_roi.reshape(-1)
 resized_df = pd.DataFrame(resized ).T
return resized_df
def direct_gradient_optimization(batch, n_iter, lr, device='cuda', reduse_alife=False):
stop_state = batch
start_state = nn.Parameter(torch.rand(stop_state.shape ).to(device)-1)
 criterion = BCELoss()
optimizer = Adam([start_state], lr=lr,)
 tqdm_loader = trange(n_iter)
 for _ in tqdm_loader:
optimizer.zero_grad()
start_state_prob = torch.sigmoid(start_state)
 stop_state_prediction = probabilistic_forward_iteration(start_state_prob, autograd=False)
 bce_loss = criterion(stop_state_prediction, stop_state)
 start_state_alive = start_state_prob.mean()
if reduse_alife and start_state_alive.item() > 0:
loss = bce_loss + start_state_alive
else:
loss = bce_loss
loss.backward()
optimizer.step()
with torch.no_grad() :
bce = bce_loss.item()
alive_cells = start_state_alive.item()
accuracy =(( stop_state_prediction > 0.5)==(stop_state>0.5)).float().mean().item()
accuracy_true =(binary_forward_iteration(start_state_prob>0.5)==(stop_state>0.5)).float().mean().item()
tqdm_loader.postfix = 'bce: {:0.10f} | start_state_alive: {:0.5f} | accuracy: {:0.10f} | accuracy_true: {:0.10f}'.format(bce, alive_cells, accuracy, accuracy_true)
 return torch.sigmoid(start_state.detach())
 def direct_gradient_optimization_predict(data, delta, n_iter=100, lr=1, device='cuda'):
data = FloatTensor(np.array(data)).reshape(( -1, 1, 25, 25)).to(device)
 for i in range(delta-1):
data = direct_gradient_optimization(data, n_iter, lr, reduse_alife=True)
 data =(data>0.5 ).float()
data = direct_gradient_optimization(data, n_iter, 1, reduse_alife=False)
 return(data>0.5 ).detach().cpu().int().reshape(-1,625 ).numpy()<load_from_csv>
tgt_cols = ['grapheme_root','vowel_diacritic','consonant_diacritic']
test = pd.read_csv('.. /input/conways-reverse-game-of-life-2020/test.csv', index_col='id')
 submission = pd.read_csv('.. /input/conways-reverse-game-of-life-2020/sample_submission.csv', index_col='id' )<find_best_params>
row_ids = []
targets = []
id = 0
for i in range(4):
img_df = pd.read_parquet(os.path.join(
 dataset, 'test_image_data_'+str(i)+'.parquet'))
img_df = img_df.drop('image_id', axis = 1)
 img_df = resize(img_df, SIZE)/ 255
X_test = img_df.values.reshape(-1, SIZE, SIZE, N_ch)
 preds = model.predict(X_test)
 for j in range(len(X_test)) :
for k in range(3):
row_ids.append('Test_'+str(id)+'_'+tgt_cols[k])
 targets.append(np.argmax(preds[k][j]))
id += 1
<save_to_csv><EOS> 
df_submit = pd.DataFrame({'row_id':row_ids,'target':targets},
columns = ['row_id','target'])
 df_submit.to_csv('submission.csv',index=False)
 df_submit.head(10 )