Kaggle competition: Predicting Molecular Properties
<SOS> metric: GroupMeanLogMAE Kaggle data source: predicting-molecular-properties<categorify>
%matplotlib inline
md = get_data(sz,bs)
 x,y = next(iter(md.trn_dl))
print(x.shape, y[0].shape)
 def display_imgs(x,lbs=None):
columns = 3
rows = min(bs,16)
 ig,ax = plt.subplots(rows, columns, figsize=(columns*5, rows*5))
for i in range(rows):
for j in range(columns):
idx = j+i*columns
ax[i,j].imshow(( x[j][i,:,:,:]*255 ).astype(np.int))
ax[i,j].axis('off')
 if lbs is not None:
ax[i,j].text(10, 25, lbs[j][i], size=20, color='red')
 plt.subplots_adjust(wspace=0, hspace=0)
 plt.show()
to_lb = md.trn_ds.names.Id.to_dict()
lbs = [[to_lb[idx] for idx in y_cur.tolist() ] for y_cur in y]
display_imgs(( md.trn_ds.denorm(x[:,0,:,:,:]),md.trn_ds.denorm(x[:,1,:,:,:]),\
md.trn_ds.denorm(x[:,2,:,:,:])) ,lbs )<normalization>
DATA_PATH = '.. /input'
SUBMISSIONS_PATH = './'
ATOMIC_NUMBERS = {
'H': 1,
'C': 6,
'N': 7,
'O': 8,
'F': 9
}
class Metric(nn.Module):
def __init__(self, emb_sz=64):
super().__init__()
self.l = nn.Linear(emb_sz*2,emb_sz*2,False)
 def forward(self,d):
d2 = d.pow(2)
 d = self.l(torch.cat(( d,d2),dim=-1))
x = d.pow(2 ).sum(dim=-1)
 return x.view(-1 )<choose_model_class>
train_dtypes = {
'molecule_name': 'category',
'atom_index_0': 'int8',
'atom_index_1': 'int8',
'type': 'category',
'scalar_coupling_constant': 'float32'
}
train_csv = pd.read_csv(f'{DATA_PATH}/train.csv', index_col='id', dtype=train_dtypes)
 train_csv['molecule_index'] = train_csv.molecule_name.str.replace('dsgdb9nsd_', '' ).astype('int32')
 train_csv = train_csv[['molecule_index', 'atom_index_0', 'atom_index_1', 'type', 'scalar_coupling_constant']]
train_csv.head(10 )
def resnext50(pretrained=True):
model = resnext_50_32x4d()
name = 'resnext_50_32x4d.pth'
if pretrained:
path = os.path.join(MODLE_INIT,name)
 load_model(model, path)
 return model
class TripletResneXt50(nn.Module):
def __init__(self, pre=True, emb_sz=64, ps=0.5):
super().__init__()
encoder = resnext50(pretrained=pre)
 self.cnn = nn.DataParallel(nn.Sequential(encoder[0],encoder[1],nn.ReLU() ,
encoder[3],encoder[4],encoder[5],encoder[6],encoder[7]))
self.head = nn.DataParallel(nn.Sequential(AdaptiveConcatPool2d() , Flatten() ,
nn.Dropout(ps),nn.Linear(4096, 512), nn.ReLU() ,
nn.BatchNorm1d(512), nn.Dropout(ps), nn.Linear(512, emb_sz)))
 self.metric = nn.DataParallel(Metric(emb_sz))
def forward(self,x):
x1,x2,x3 = x[:,0,:,:,:],x[:,1,:,:,:],x[:,2,:,:,:]
x1 = self.head(self.cnn(x1))
x2 = self.head(self.cnn(x2))
x3 = self.head(self.cnn(x3))
x = torch.cat(( x1,x2,x3))
sz = x.shape[0]
x1 = x.unsqueeze(1 ).expand(( sz,sz,-1))
x2 = x1.transpose(0,1)
 d =(x1 - x2 ).view(sz*sz,-1)
 return self.metric(d)
 def get_embedding(self, x):
return self.head(self.cnn(x))
def get_d(self, x0, x):
d =(x - x0)
 return self.metric(d)
 class ResNeXt50Model() :
def __init__(self,pre=True,name='TripletResneXt50',**kwargs):
self.model = to_gpu(TripletResneXt50(pre=True,**kwargs))
self.name = name
def get_layer_groups(self, precompute):
m = self.model.module if isinstance(self.model,FP16)else self.model
if precompute:
return [m.head] + [m.metric]
c = children(m.cnn.module)
 return list(split_by_idxs(c,[5])) + [m.head] + [m.metric]<choose_model_class>
test_csv = pd.read_csv(f'{DATA_PATH}/test.csv', index_col='id', dtype=train_dtypes)
 test_csv['molecule_index'] = test_csv['molecule_name'].str.replace('dsgdb9nsd_', '' ).astype('int32')
 test_csv = test_csv[['molecule_index', 'atom_index_0', 'atom_index_1', 'type']]
test_csv.head(10 )
def get_densenet169(pre=True):
with warnings.catch_warnings() :
warnings.simplefilter("ignore")
 layers = cut_model(cut_model(densenet169(pre), -1)[0],-1)
 return nn.Sequential(*layers)
 class TripletDenseNet169(nn.Module):
def __init__(self, pre=True, emb_sz=64, ps=0.5):
super().__init__()
encoder = get_densenet169(pre)
 self.cnn = nn.DataParallel(nn.Sequential(encoder[0],encoder[1],nn.ReLU() ,
encoder[3],encoder[4],encoder[5],encoder[6],encoder[7],
encoder[8],encoder[9],encoder[10]))
self.head = nn.DataParallel(nn.Sequential(AdaptiveConcatPool2d() , Flatten() ,
nn.Dropout(ps),nn.Linear(3328, 512), nn.ReLU() ,
nn.BatchNorm1d(512), nn.Dropout(ps), nn.Linear(512, emb_sz)))
 self.metric = nn.DataParallel(Metric(emb_sz))
def forward(self,x):
x1,x2,x3 = x[:,0,:,:,:],x[:,1,:,:,:],x[:,2,:,:,:]
x1 = self.head(self.cnn(x1))
x2 = self.head(self.cnn(x2))
x3 = self.head(self.cnn(x3))
x = torch.cat(( x1,x2,x3))
sz = x.shape[0]
x1 = x.unsqueeze(1 ).expand(( sz,sz,-1))
x2 = x1.transpose(0,1)
 d =(x1 - x2 ).view(sz*sz,-1)
 return self.metric(d)
 def get_embedding(self, x):
return self.head(self.cnn(x))
def get_d(self, x0, x):
d =(x - x0)
 return self.metric(d)
 class DenseNet169Model() :
def __init__(self,pre=True,name='TripletDenseNet169',**kwargs):
self.model = to_gpu(TripletDenseNet169(pre=True,**kwargs))
self.name = name
def get_layer_groups(self, precompute):
m = self.model.module if isinstance(self.model,FP16)else self.model
if precompute:
return [m.head] + [m.metric]
c = children(m.cnn.module)
 return list(split_by_idxs(c,[8])) + [m.head] + [m.metric]<choose_model_class>
structures_dtypes = {
'molecule_name': 'category',
'atom_index': 'int8',
'atom': 'category',
'x': 'float32',
'y': 'float32',
'z': 'float32'
}
structures_csv = pd.read_csv(f'{DATA_PATH}/structures.csv', dtype=structures_dtypes)
 structures_csv['molecule_index'] = structures_csv.molecule_name.str.replace('dsgdb9nsd_', '' ).astype('int32')
 structures_csv = structures_csv[['molecule_index', 'atom_index', 'atom', 'x', 'y', 'z']]
structures_csv['atom'] = structures_csv['atom'].replace(ATOMIC_NUMBERS ).astype('int8')
 structures_csv.head(10 )
def get_densenet121(pre=True):
with warnings.catch_warnings() :
warnings.simplefilter("ignore")
 layers = cut_model(cut_model(densenet121(pre), -1)[0],-1)
 return nn.Sequential(*layers)
 class TripletDenseNet121(nn.Module):
def __init__(self, pre=True, emb_sz=64, ps=0.5):
super().__init__()
encoder = get_densenet121(pre)
 self.cnn = nn.DataParallel(nn.Sequential(encoder[0],encoder[1],nn.ReLU() ,
encoder[3],encoder[4],encoder[5],encoder[6],encoder[7],
encoder[8],encoder[9],encoder[10]))
self.head = nn.DataParallel(nn.Sequential(AdaptiveConcatPool2d() , Flatten() ,
nn.BatchNorm1d(2048),nn.Dropout(ps),nn.Linear(2048, 1024), nn.ReLU() ,
nn.BatchNorm1d(1024), nn.Dropout(ps), nn.Linear(1024, emb_sz)))
 self.metric = nn.DataParallel(Metric(emb_sz))
def forward(self,x):
x1,x2,x3 = x[:,0,:,:,:],x[:,1,:,:,:],x[:,2,:,:,:]
x1 = self.head(self.cnn(x1))
x2 = self.head(self.cnn(x2))
x3 = self.head(self.cnn(x3))
x = torch.cat(( x1,x2,x3))
sz = x.shape[0]
x1 = x.unsqueeze(1 ).expand(( sz,sz,-1))
x2 = x1.transpose(0,1)
 d =(x1 - x2 ).view(sz*sz,-1)
 return self.metric(d)
 def get_embedding(self, x):
return self.head(self.cnn(x))
def get_d(self, x0, x):
d =(x - x0)
 return self.metric(d)
 class DenseNet121Model() :
def __init__(self,pre=True,name='TripletDenseNet21',**kwargs):
self.model = to_gpu(TripletDenseNet121(pre=True,**kwargs))
self.name = name
def get_layer_groups(self, precompute):
m = self.model.module if isinstance(self.model,FP16)else self.model
if precompute:
return [m.head] + [m.metric]
c = children(m.cnn.module)
 return list(split_by_idxs(c,[8])) + [m.head] + [m.metric]<normalization>
def build_type_dataframes(base, structures, coupling_type):
base = base[base['type'] == coupling_type].drop('type', axis=1 ).copy()
base = base.reset_index()
base['id'] = base['id'].astype('int32')
 structures = structures[structures['molecule_index'].isin(base['molecule_index'])]
return base, structures
class Contrastive_loss(nn.Module):
def __init__(self, m=10.0, wd=1e-4):
super().__init__()
self.m, self.wd = m, wd
def forward(self, d, target):
d = d.float()
t = torch.cat(target)
 sz = t.shape[0]
t1 = t.unsqueeze(1 ).expand(( sz,sz))
t2 = t1.transpose(0,1)
 y =(( t1==t2)+ to_gpu(torch.eye(sz ).byte())).view(-1)
 loss_p = d[y==1]
loss_n = F.relu(self.m - torch.sqrt(d[y==0])) **2
loss = torch.cat(( loss_p,loss_n),0)
 loss = loss[torch.nonzero(loss ).squeeze() ]
loss = loss.mean() if loss.shape[0] > 0 else loss.sum()
loss += self.wd*(d**2 ).mean()
return loss
def T_acc(d, target):
sz = target[0].shape[0]
lp = [3*sz*i + i+sz for i in range(sz)]
ln = [3*sz*i + i+2*sz for i in range(sz)]
dp, dn = d[lp], d[ln]
return(dp < dn ).float().mean()
def BH_acc(d, target):
t = torch.cat(target)
 sz = t.shape[0]
t1 = t.unsqueeze(1 ).expand(( sz,sz))
t2 = t1.transpose(0,1)
 y =(t1==t2)
 d = d.float().view(sz,sz)
 BH = []
for i in range(sz):
dp = d[i,y[i,:] == 1].max()
dn = d[i,y[i,:] == 0].min()
BH.append(dp < dn)
 return torch.FloatTensor(BH ).float().mean()<train_model>
def add_coordinates(base, structures, index):
df = pd.merge(base, structures, how='inner',
left_on=['molecule_index', f'atom_index_{index}'],
right_on=['molecule_index', 'atom_index'] ).drop(['atom_index'], axis=1)
 df = df.rename(columns={
'atom': f'atom_{index}',
'x': f'x_{index}',
'y': f'y_{index}',
'z': f'z_{index}'
})
 return df
class BH_loss(nn.Module):
def __init__(self, n=1, m=0.0):
super().__init__()
self.n = n
self.m = m
def forward(self, input, target, size_average=True):
t = torch.cat(target)
 sz = t.shape[0]
t1 = t.unsqueeze(1 ).expand(( sz,sz))
t2 = t1.transpose(0,1)
 y =(( t1==t2)+ to_gpu(torch.eye(sz ).byte()))
d = input.float().view(sz,sz)
 D = []
for i in range(2*sz//3):
dp = d[i,y[i,:] == 1].max()
dn = d[i,y[i,:] == 0]
dist, idxs = torch.sort(dn)
 n = min(self.n,dn.shape[0])
 for j in range(n):
D.append(( self.m + dp - dn[idxs[j]] ).unsqueeze(0))
loss = torch.log1p(torch.exp(torch.cat(D)))
 loss = loss.mean() if size_average else loss.sum()
return loss<choose_model_class>
def add_atoms(base, atoms):
df = pd.merge(base, atoms, how='inner',
on=['molecule_index', 'atom_index_0', 'atom_index_1'])
 return df
learner = ConvLearner(md,DenseNet121Model(ps=0.0,emb_sz=n_embedding))
learner.opt_fn = optim.Adam
learner.clip = 1.0
learner.crit = Contrastive_loss()
learner.metrics = [T_acc,BH_acc]
learner.freeze_to(-2)
 learner<train_model>
def merge_all_atoms(base, structures):
df = pd.merge(base, structures, how='left',
left_on=['molecule_index'],
right_on=['molecule_index'])
 df = df[(df.atom_index_0 != df.atom_index)&(df.atom_index_1 != df.atom_index)]
return df
lr = 1e-3
with warnings.catch_warnings() :
warnings.simplefilter("ignore")
 learner.fit(lr,1 )<train_model>
def add_center(df):
df['x_c'] =(( df['x_1'] + df['x_0'])* np.float32(0.5))
df['y_c'] =(( df['y_1'] + df['y_0'])* np.float32(0.5))
df['z_c'] =(( df['z_1'] + df['z_0'])* np.float32(0.5))
def add_distance_to_center(df):
df['d_c'] =(( 
(df['x_c'] - df['x'])**np.float32(2)+ 
(df['y_c'] - df['y'])**np.float32(2)+ 
(df['z_c'] - df['z'])**np.float32(2)
)**np.float32(0.5))
def add_distance_between(df, suffix1, suffix2):
df[f'd_{suffix1}_{suffix2}'] =(( 
(df[f'x_{suffix1}'] - df[f'x_{suffix2}'])**np.float32(2)+ 
(df[f'y_{suffix1}'] - df[f'y_{suffix2}'])**np.float32(2)+ 
(df[f'z_{suffix1}'] - df[f'z_{suffix2}'])**np.float32(2)
)**np.float32(0.5))
with warnings.catch_warnings() :
warnings.simplefilter("ignore")
 learner.fit(lrs/2,4,cycle_len=1,use_clr=(10,20))
learner.fit(lrs/4,4,cycle_len=2,use_clr=(10,20))
learner.save('model0' )<load_pretrained>
def add_distances(df):
n_atoms = 1 + max([int(c.split('_')[1])for c in df.columns if c.startswith('x_')])
 for i in range(1, n_atoms):
for vi in range(min(4, i)) :
add_distance_between(df, i, vi )
def extract_embedding(model,path):
tfms = tfms_from_model(resnet34, sz, crop_type=CropType.NO)
 tfms[0].tfms = [tfms[0].tfms[2],tfms[0].tfms[3]]
tfms[1].tfms = [tfms[1].tfms[2],tfms[1].tfms[3]]
ds = ImageData.get_ds(FilesDataset_single,(None,TRAIN),(None,TRAIN),
tfms, test=(None,path))
md = ImageData(PATH, ds, 3*bs, num_workers=nw, classes=None)
 model.eval()
with torch.no_grad() :
preds = torch.zeros(( len(md.test_dl.dataset), n_embedding))
start=0
for i,(x,y)in tqdm_notebook(enumerate(md.test_dl,start=0),
total=len(md.test_dl)) :
size = x.shape[0]
m = model.module if isinstance(model,FP16)else model
preds[start:start+size,:] = m.get_embedding(x.half())
 start+= size
return preds, [os.path.basename(name)for name in md.test_dl.dataset.fnames]<save_to_csv>
def add_n_atoms(base, structures):
dfs = structures['molecule_index'].value_counts().rename('n_atoms' ).to_frame()
return pd.merge(base, dfs, left_on='molecule_index', right_index=True )
emb, names = extract_embedding(learner.model,TRAIN)
 df = pd.DataFrame({'files':names,'emb':emb.tolist() })
 df.emb = df.emb.map(lambda emb: ' '.join(list([str(i)for i in emb])))
 df.to_csv('train_emb.csv', header=True, index=False)
 emb, names = extract_embedding(learner.model,TEST)
 df_test = pd.DataFrame({'files':names,'emb':emb.tolist() })
 df_test.emb = df_test.emb.map(lambda emb: ' '.join(list([str(i)for i in emb])))
 df_test.to_csv('test_emb.csv', header=True, index=False )<train_model>
def build_couple_dataframe(some_csv, structures_csv, coupling_type, n_atoms=10):
base, structures = build_type_dataframes(some_csv, structures_csv, coupling_type)
 base = add_coordinates(base, structures, 0)
 base = add_coordinates(base, structures, 1)
 base = base.drop(['atom_0', 'atom_1'], axis=1)
 atoms = base.drop('id', axis=1 ).copy()
if 'scalar_coupling_constant' in some_csv:
atoms = atoms.drop(['scalar_coupling_constant'], axis=1)
 add_center(atoms)
 atoms = atoms.drop(['x_0', 'y_0', 'z_0', 'x_1', 'y_1', 'z_1'], axis=1)
 atoms = merge_all_atoms(atoms, structures)
 add_distance_to_center(atoms)
 atoms = atoms.drop(['x_c', 'y_c', 'z_c', 'atom_index'], axis=1)
 atoms.sort_values(['molecule_index', 'atom_index_0', 'atom_index_1', 'd_c'], inplace=True)
 atom_groups = atoms.groupby(['molecule_index', 'atom_index_0', 'atom_index_1'])
 atoms['num'] = atom_groups.cumcount() + 2
atoms = atoms.drop(['d_c'], axis=1)
 atoms = atoms[atoms['num'] < n_atoms]
atoms = atoms.set_index(['molecule_index', 'atom_index_0', 'atom_index_1', 'num'] ).unstack()
atoms.columns = [f'{col[0]}_{col[1]}' for col in atoms.columns]
atoms = atoms.reset_index()
for col in atoms.columns:
if col.startswith('atom_'):
atoms[col] = atoms[col].fillna(0 ).astype('int8')
 atoms['molecule_index'] = atoms['molecule_index'].astype('int32')
 full = add_atoms(base, atoms)
 add_distances(full)
 full.sort_values('id', inplace=True)
 return full
dcut = 18.0
get_val_nbs(learner.model,df,dcut=dcut,out='val0.csv' )<load_from_csv>
def take_n_atoms(df, n_atoms, four_start=4):
labels = []
for i in range(2, n_atoms):
label = f'atom_{i}'
labels.append(label)
 for i in range(n_atoms):
num = min(i, 4)if i < four_start else 4
for j in range(num):
labels.append(f'd_{i}_{j}')
 if 'scalar_coupling_constant' in df:
labels.append('scalar_coupling_constant')
 return df[labels]
def get_test_nbs(model,trn_emb,test_emb,out='test.csv',\
submission='submission.csv',dcut=None):
trn_emb = trn_emb.copy()
data = pd.read_csv(LABELS ).set_index('Image')
 trn_emb['emb'] = [[float(i)for i in s.split() ] for s in trn_emb['emb']]
trn_emb.set_index('files',inplace=True)
 train_df = data.join(trn_emb)
 train_df = train_df.reset_index()
train_preds = np.array(train_df.emb.tolist())
 test_emb = test_emb.copy()
test_emb['emb'] = [[float(i)for i in s.split() ] for s in test_emb['emb']]
test_emb['Image'] = test_emb['files']
test_emb.set_index('files',inplace=True)
 test_df = test_emb.reset_index()
test_preds = np.array(test_df.emb.tolist())
 train_preds = torch.from_numpy(train_preds ).half().cuda()
test_preds = torch.from_numpy(test_preds ).half().cuda()
test_d,test_idxs = get_nbs(model,test_preds,train_preds)
 s = []
for l1 in test_d.tolist() :
s.append(' '.join([str(l2)for l2 in l1]))
test_df['d'] = s
test_df['nbs'] = [' '.join(train_df.loc[test_idxs[index]].Id.tolist())\
for index, row in test_df.iterrows() ]
test_df[['Image','nbs','d']].to_csv(out, header=True, index=False)
 if dcut is not None:
pred = []
for idx, row in test_df.iterrows() :
nbs = dict()
for i in range(0,16):
nb = test_idxs[idx,i]
l, s = train_df.loc[nb].Id, test_d[idx,i]
if s > dcut and 'new_whale' not in nbs: nbs['new_whale'] = dcut
if l not in nbs: nbs[l] = s
if len(nbs)>= 5: break
nbs_sorted = list(nbs.items())
 p = ' '.join([lb[0] for lb in nbs_sorted])
 pred.append({'Image':row.files,'Id':p})
 pd.DataFrame(pred ).to_csv(submission,index=False )<load_from_csv>
%%time
full = build_couple_dataframe(train_csv, structures_csv, '1JHN', n_atoms=10)
 print(full.shape )
get_test_nbs(learner.model,df,df_test,dcut=dcut,out='test0.csv',\
submission='submission0.csv' )<normalization>
X_data = df.drop(['scalar_coupling_constant'], axis=1 ).values.astype('float32')
 y_data = df['scalar_coupling_constant'].values.astype('float32')
 X_train, X_val, y_train, y_val = train_test_split(X_data, y_data, test_size=0.2, random_state=128)
 X_train.shape, X_val.shape, y_train.shape, y_val.shape
md = get_data(sz,bs,'train_emb.csv',learner.model)
 learner.set_data(md)
 learner.unfreeze()
learner.half()
x,y = next(iter(md.trn_dl))
to_lb = md.trn_ds.names.Id.to_dict()
lbs = [[to_lb[idx] for idx in y_cur.tolist() ] for y_cur in y]
display_imgs(( md.trn_ds.denorm(x[:,0,:,:,:]),md.trn_ds.denorm(x[:,1,:,:,:]),\
md.trn_ds.denorm(x[:,2,:,:,:])) ,lbs )<train_model>
model = CatBoostRegressor(iterations=750,
learning_rate=0.2,
depth=10,
eval_metric='RMSE',
random_seed = 42,
bagging_temperature = 0.2,
od_type='Iter',
metric_period = 50,
od_wait=20,
reg_lambda=0.3)
 model.fit(X_train, y_train,
eval_set=[(X_train, y_train),(X_val, y_val)])
 y_pred = model.predict(X_val)
 np.log(mean_absolute_error(y_val, y_pred))
with warnings.catch_warnings() :
warnings.simplefilter("ignore")
 learner.fit(lrs/16,5,cycle_len=4,use_clr=(10,20))
learner.save('model' )<save_to_csv>
def build_x_y_data(some_csv, coupling_type, n_atoms):
full = build_couple_dataframe(some_csv, structures_csv, coupling_type, n_atoms=n_atoms)
 df = take_n_atoms(full, n_atoms)
 df = df.fillna(0)
 print(df.columns)
 if 'scalar_coupling_constant' in df:
X_data = df.drop(['scalar_coupling_constant'], axis=1 ).values.astype('float32')
 y_data = df['scalar_coupling_constant'].values.astype('float32')
 else:
X_data = df.values.astype('float32')
 y_data = None
return X_data, y_data
emb, names = extract_embedding(learner.model,TRAIN)
 df = pd.DataFrame({'files':names,'emb':emb.tolist() })
 df.emb = df.emb.map(lambda emb: ' '.join(list([str(i)for i in emb])))
 df.to_csv('train_emb.csv', header=True, index=False)
 emb, names = extract_embedding(learner.model,TEST)
 df_test = pd.DataFrame({'files':names,'emb':emb.tolist() })
 df_test.emb = df_test.emb.map(lambda emb: ' '.join(list([str(i)for i in emb])))
 df_test.to_csv('test_emb.csv', header=True, index=False )<load_from_csv>
def train_and_predict_for_one_coupling_type(coupling_type, submission, n_atoms, n_folds=3, n_splits=5, random_state=128):
print(f'*** Training Model for {coupling_type} ***')
 X_data, y_data = build_x_y_data(train_csv, coupling_type, n_atoms)
 X_test, _ = build_x_y_data(test_csv, coupling_type, n_atoms)
 y_pred = np.zeros(X_test.shape[0], dtype='float32')
 cv_score = 0
if n_folds > n_splits:
n_splits = n_folds
kfold = KFold(n_splits=n_splits, shuffle=True, random_state=random_state)
 for fold,(train_index, val_index)in enumerate(kfold.split(X_data, y_data)) :
if fold >= n_folds:
break
X_train, X_val = X_data[train_index], X_data[val_index]
y_train, y_val = y_data[train_index], y_data[val_index]
model = CatBoostRegressor(iterations=500,
learning_rate=0.2,
depth=10,
eval_metric='RMSE',
random_seed = 42,
bagging_temperature = 0.2,
od_type='Iter',
metric_period = 50,
od_wait=20,
reg_lambda=0.3)
 model.fit(X_train, y_train,
eval_set=[(X_train, y_train),(X_val, y_val)])
 y_val_pred = model.predict(X_val)
 val_score = np.log(mean_absolute_error(y_val, y_val_pred))
print(f'{coupling_type} Fold {fold}, logMAE: {val_score}')
 cv_score += val_score / n_folds
y_pred += model.predict(X_test)/ n_folds
submission.loc[test_csv['type'] == coupling_type, 'scalar_coupling_constant'] = y_pred
return cv_score
dcut = 23.0
get_val_nbs(learner.model,df,dcut=dcut,out='val.csv')
 get_test_nbs(learner.model,df,df_test,dcut=dcut,out='test.csv',\
submission='submission.csv' )<install_modules>
submission_csv = pd.read_csv(f'{DATA_PATH}/sample_submission.csv', index_col='id' )
!pip install albumentations > /dev/null<set_options>
model_params = {
'1JHN': 7,
'1JHC': 10,
'2JHH': 9,
'2JHN': 9,
'2JHC': 9,
'3JHH': 9,
'3JHC': 10,
'3JHN': 10
}
N_FOLDS = 5
submission = submission_csv.copy()
cv_scores = {}
for coupling_type in model_params.keys() :
cv_score = train_and_predict_for_one_coupling_type(
 coupling_type, submission, n_atoms=model_params[coupling_type], n_folds=N_FOLDS)
 cv_scores[coupling_type] = cv_score
%matplotlib inline
warnings.simplefilter("ignore", category=DeprecationWarning )<load_from_csv>
submission.to_csv(f'{SUBMISSIONS_PATH}/submission.csv' )