Kaggle competition: Conway's Reverse Game of Life 2020
models.sort_values(by=['LB_for_3opt_features', 'LB_for_16_features'], ascending=False )<sort_values>
neighbor_alive2_cell_alive = {}
neighbor_alive2_cell_dead = {}
neighbor_alive3_cell_alive = {}
neighbor_alive3_cell_dead = {}
for cell in range(8):
neighbor_alive2_cell_alive[cell] = [(cell,j)for j in range(8)if j!=cell]
neighbor_alive2_cell_alive[cell] = [([j]+[8+k for k in range(8)if(k!=i and k!=j)])for i,j in neighbor_alive2_cell_alive[cell]]
neighbor_alive2_cell_dead[cell] = [(i,j)for i in range(8)for j in range(i)if i!=cell and j!=cell]
neighbor_alive2_cell_dead[cell] = [([i,j]+[8+k for k in range(8)if(k!=i and k!=j and k!=cell)])for i,j in neighbor_alive2_cell_dead[cell]]
neighbor_alive3_cell_alive[cell] = [(i,j,cell)for i in range(8)for j in range(i)if i!=cell and j!=cell]
neighbor_alive3_cell_alive[cell] = [([i,j]+[8+l for l in range(8)if(l!=i and l!=j and l!=k)])for i,j,k in neighbor_alive3_cell_alive[cell]]
neighbor_alive3_cell_dead[cell] = [(i,j,k)for i in range(8)for j in range(i)for k in range(j)if i!=cell and j!=cell and k!=cell]
neighbor_alive3_cell_dead[cell] = [([i,j,k]+[8+l for l in range(8)if(l!=i and l!=j and l!=k and l!=cell)])for i,j,k in neighbor_alive3_cell_dead[cell]]
def get_neighbors_backward(grad_output):
return torch.stack([torch.roll(torch.roll(grad_output[idx], -i, 2), -j, 3)for idx,(i,j)in enumerate(neighbors_roll_axes)] ).sum(dim=0)
 def n_neigbors_nearby_prob_backward(grad_output, neighbors, neighbor_nearby=2):
if neighbor_nearby==2:
combination_cell_alive = neighbor_alive2_cell_alive
combination_cell_dead = neighbor_alive2_cell_dead
else:
combination_cell_alive = neighbor_alive3_cell_alive
combination_cell_dead = neighbor_alive3_cell_dead
neighbors = torch.cat([neighbors, 1 - neighbors])
 coef = []
for cell in range(8):
cell_live_coef = torch.stack([neighbors[l].prod(dim=0)for l in combination_cell_alive[cell]] ).sum(dim=0)
 cell_dead_coef = torch.stack([neighbors[d].prod(dim=0)for d in combination_cell_dead[cell]] ).sum(dim=0)
 coef.append(cell_live_coef-cell_dead_coef)
 coef = torch.stack(coef)
 return coef*grad_output
class ProbabilisticForwardIteration(torch.autograd.Function):
@staticmethod
def forward(ctx, grid, delta=1):
ctx.grid = grid
return probabilistic_forward_iteration_autograd(grid)
 @staticmethod
def backward(ctx, grad_out):
grid = ctx.grid
neighbors = get_neighbors(grid)
 neighbors_p2 = n_neigbors_nearby_prob(neighbors, neighbor_nearby=2)
 grad_n2_out = grad_out*grid
grad_n3_out = grad_out
grad_n2_inp = n_neigbors_nearby_prob_backward(grad_n2_out, neighbors, neighbor_nearby=2)
 grad_n3_inp = n_neigbors_nearby_prob_backward(grad_n3_out, neighbors, neighbor_nearby=3)
 grad_neighbors_out = grad_n2_inp + grad_n3_inp
grad_neighbors_inp = get_neighbors_backward(grad_neighbors_out)
 grad_inp = grad_neighbors_inp + neighbors_p2*grad_out
return grad_inp, None
models.sort_values(by=['LB_for_16_features', 'LB_for_3opt_features'], ascending=False )<import_modules>
def probabilistic_forward_iteration(grid, delta=1, autograd=True):

 if autograd:
for _ in range(delta):
grid = probabilistic_forward_iteration_autograd(grid)
 else:
for _ in range(delta):
grid = ProbabilisticForwardIteration.apply(grid)
 return grid
import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import accuracy_score<load_from_csv>
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
train=pd.read_csv(".. /input/titanic/train.csv")
 tit1=train.select_dtypes(include=['float64','int64','object'])
 train.info()
test=pd.read_csv(".. /input/titanic/test.csv")
 tit2=test.select_dtypes(include=['float64','int64','object'])
 test.info()<feature_engineering>
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
tit2['survived']=np.nan
tit2.head()<feature_engineering>
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
percent=round(np.mean(train['Survived']),3)*100
print("Percentage of Survivors:",percent )<count_values>
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
total=train['Survived'].sum()
total
men=train[train['Sex']=='male']
women=train[train['Sex']=='female']
m=men['Sex'].count()
w=women['Sex'].count()
print("male:",m)
 print("female:",w)
 print("percentage of women:",round(w/(m+w)*100))
print("percentage of men:",round(m/(m+w)*100))<count_missing_values>
N_iter = 2000
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()
train.isnull().sum()<count_missing_values>
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}' )
train.isnull().sum()<data_type_conversions>
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()
train['Cabin'] = train['Cabin'].fillna('X')
 test['Cabin']=test['Cabin'].fillna('X' )<categorify>
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' )
train.loc[train.Age.isnull() ,'Age']=train.groupby("Pclass" ).Age.transform('median')
 test.loc[test.Age.isnull() ,'Age']=test.groupby("Pclass" ).Age.transform('median')
 print(train['Age'].isnull().sum() )<categorify>
for delta in range(1,6):
mask = test['delta']==delta
data = test[mask].iloc[:,1:]
submission[mask] = direct_gradient_optimization_predict(data, delta, 100, 1 )
category = {'A':1, 'B':2, 'C':3, 'D':4, 'E':5, 'F':6, 'G':7, 'X':8, 'T':9}
train['Cabin'] = train['Cabin'].map(category)
 train['Cabin'].unique().tolist()<count_missing_values>
submission.to_csv('submission.csv')
 submission
print(train.isnull().sum() )<feature_engineering>
def evaluate_results(test, submission):
test = test.copy()
test['socre'] = 0
for delta in range(1,6):
mask = test['delta']==delta
data = FloatTensor(submission[mask].to_numpy() ).reshape(-1,1,25,25)
 for _ in range(delta):
data = binary_forward_iteration(data)
 data = data.reshape(-1,625 ).numpy()
result = test.loc[mask].iloc[:,1:-1] == data
test.loc[mask, 'socre'] = result.mean(axis=1)
 print(f"Delta {delta} score: {test.loc[mask, 'socre'].mean() }")
 test.loc[mask, 'socre'].hist(bins=30)
 plt.show()
print(f"LB : {1-test['socre'].mean() }" )
<count_missing_values><EOS> 
evaluate_results(test, submission )