Kaggle competition: Prostate cANcer graDe Assessment (PANDA) Challenge
<SOS> metric: QuadraticWeightedKappa Kaggle data source: prostate-cancer-grade-assessment-(panda)-challenge<load_from_csv>
import os
import cv2
import skimage.io
from tqdm.notebook import tqdm
import zipfile
import numpy as np
import matplotlib.pyplot as plt
import time
from skimage import morphology
from pdb import set_trace
import PIL
import torch
from torch import tensor
from torch.utils.data import DataLoader, Dataset
import pandas as pd
from torch import nn
import fastai
from fastai.vision import *
from joblib import Parallel, delayed
submission = pd.read_csv('.. /input/vsb-power-line-fault-detection/sample_submission.csv')
 print(len(submission))
submission.head()<predict_on_test>
SAMPLE = '.. /input/prostate-cancer-grade-assessment/sample_submission.csv'
sub_df = pd.read_csv(SAMPLE)
 sub_df.to_csv('submission.csv', index=False )
preds_test = []
for i in range(N_SPLITS):
model.load_weights('weights_{}.h5'.format(i))
pred = model.predict(X_test_input, batch_size=300, verbose=1)
 pred_3 = []
for pred_scalar in pred:
for i in range(3):
pred_3.append(pred_scalar)
 preds_test.append(pred_3)
<data_type_conversions>
def get_drhb_best(debug=False):
N_FOLDS = 1
sz = 224
bs = 2
N = 81
nworkers = 2
imagenet_stats = [[0.485, 0.456, 0.406], [0.229, 0.224, 0.225]]
DATA = '.. /input/prostate-cancer-grade-assessment/test_images'
TEST = '.. /input/prostate-cancer-grade-assessment/test.csv'
if debug:
DATA = '.. /input/prostate-cancer-grade-assessment/train_images'
TEST = '.. /input/prostate-cancer-grade-assessment/train.csv'
SAMPLE = '.. /input/prostate-cancer-grade-assessment/sample_submission.csv'
MODELS = ['.. /input/exp-80/EXP_80_RESNET_34_TILES_81_SQ_FT_NBN_SE_DUAL_0_sq_features_41.pth']
IMG_OUT = 'imgs'
class OptimizedRounder() :
def __init__(self):
self.coef_ = 0
def _kappa_loss(self, coef, X, y):
X_p = np.copy(X)
 for i, pred in enumerate(X_p):
if pred < coef[0]:
X_p[i] = 0
elif pred >= coef[0] and pred < coef[1]:
X_p[i] = 1
elif pred >= coef[1] and pred < coef[2]:
X_p[i] = 2
elif pred >= coef[2] and pred < coef[3]:
X_p[i] = 3
elif pred >= coef[3] and pred < coef[4]:
X_p[i] = 4
else:
X_p[i] = 5
ll = quadratic_weighted_kappa(y, X_p)
 return -ll
def fit(self, X, y):
loss_partial = partial(self._kappa_loss, X=X, y=y)
 initial_coef = [0.5, 1.5, 2.5, 3.5, 4.5]
self.coef_ = sp.optimize.minimize(loss_partial, initial_coef, method='nelder-mead')
 def predict(self, X, coef):
X_p = np.copy(X)
 for i, pred in enumerate(X_p):
if pred < coef[0]:
X_p[i] = 0
elif pred >= coef[0] and pred < coef[1]:
X_p[i] = 1
elif pred >= coef[1] and pred < coef[2]:
X_p[i] = 2
elif pred >= coef[2] and pred < coef[3]:
X_p[i] = 3
elif pred >= coef[3] and pred < coef[4]:
X_p[i] = 4
else:
X_p[i] = 5
return X_p
def coefficients(self):
return self.coef_['x']
def prepare_df(df):
uniq_id = list(df['image_id'].unique())
 return df, uniq_id
def tile(img_name):
img = skimage.io.MultiImage(img_name)[-2]
result = []
shape = img.shape
pad0,pad1 =(sz - shape[0]%sz)%sz,(sz - shape[1]%sz)%sz
img = np.pad(img,[[pad0//2,pad0-pad0//2],[pad1//2,pad1-pad1//2],[0,0]],
constant_values=255)
 img = img.reshape(img.shape[0]//sz,sz,img.shape[1]//sz,sz,3)
 img = img.transpose(0,2,1,3,4 ).reshape(-1,sz,sz,3)
 idxs = np.argsort(img.reshape(img.shape[0],-1 ).sum(-1))
img = img[idxs][:N]
if len(img)<N:
n = N-len(img)
 img = np.concatenate([img, np.full(( n,sz,sz,3),255,dtype=np.uint8)],0)
 for i in range(len(img)) :
result.append({'img':img[i], 'idx':i})
 return result
def save_imgs(image_name, folder_path=DATA, image_folder_out=IMG_OUT):
image_nm = folder_path + '/' + image_name + '.tiff'
try:
tiles = tile(image_nm)
 for t in tiles:
img,idx = t['img'], t['idx']
cv2.imwrite(f'{image_folder_out}/{image_name}_{idx}.png', cv2.cvtColor(img, cv2.COLOR_RGB2BGR))
except:
pass
class CustomEnd(nn.Module):
def __init__(self, scaler = SigmoidRange(-1, 6.0)) :
super().__init__()
self.scaler_ = scaler
def forward(self, x):
classif = x[:, :-1]
regress = self.scaler_(x[:, -1])
 return classif, regress
def make_divisible(v, divisor=8, min_value=None):
min_value = min_value or divisor
new_v = max(min_value, int(v + divisor / 2)// divisor * divisor)
 if new_v < 0.9 * v:
new_v += divisor
return new_v
def sigmoid(x, inplace: bool = False):
return x.sigmoid_() if inplace else x.sigmoid()
class SqueezeExcite(nn.Module):
def __init__(self, in_chs, se_ratio=0.25, reduced_base_chs=None,
act_layer=nn.ReLU, gate_fn=sigmoid, divisor=1, **_):
super(SqueezeExcite, self ).__init__()
self.gate_fn = gate_fn
reduced_chs = make_divisible(( reduced_base_chs or in_chs)* se_ratio, divisor)
 self.avg_pool = nn.AdaptiveAvgPool2d(1)
 self.conv_reduce = nn.Conv2d(in_chs, reduced_chs, 1, bias=True)
 self.act1 = act_layer(inplace=True)
 self.conv_expand = nn.Conv2d(reduced_chs, in_chs, 1, bias=True)
 def forward(self, x):
x_se = self.avg_pool(x)
 x_se = self.conv_reduce(x_se)
 x_se = self.act1(x_se)
 x_se = self.conv_expand(x_se)
 x = x * self.gate_fn(x_se)
 return x
class CustomEnd(nn.Module):
def __init__(self, scaler = SigmoidRange(-1, 6.0)) :
super().__init__()
self.scaler_ = scaler
def forward(self, x):
classif = x[:, :-1]
regress = self.scaler_(x[:, -1])
 return classif, regress
class ModelSeDul(nn.Module):
def __init__(self):
super().__init__()
m = fastai.vision.models.resnet34()
self.enc = nn.Sequential(*list(m.children())[:-2])
 nc = list(m.children())[-1].in_features
self.cb = SqueezeExcite(nc)
 self.head = nn.Sequential(AdaptiveConcatPool2d() ,
Flatten() ,
nn.Linear(2*nc,512),
nn.ReLU(inplace=True),
nn.Dropout(0.4),
nn.Linear(512,7),
CustomEnd())
 def forward(self, x):
shape = x.shape
n = shape[1]
x = x.view(-1,shape[2],shape[3],shape[4])
 x = self.enc(x)
 shape = x.shape
x = x.view(-1, n, x.shape[1], x.shape[2], x.shape[3] ).permute(0, 2, 1, 3, 4 ).contiguous().\
view(-1, x.shape[1], x.shape[2] * n, x.shape[3])
 x = x.view(x.shape[0], x.shape[1], x.shape[2]//int(np.sqrt(N)) , -1)
 x = self.cb(x)
 x = self.head(x)
 return x[1]
class PandasDSST2(Dataset):
def __init__(self, fnames, stats=imagenet_stats, N=N, sz=sz, path = IMG_OUT):
self.items = fnames
self.stats = list(map(tensor, stats))
self.sz = sz
self.N =N
self.path = path
def __len__(self):
return len(self.items)
 def __getitem__(self, idx):
imgs = []
fns = [f'{self.path}/{self.items[idx]}_{i}.png' for i in range(self.N)]
for fn in fns:
img = PIL.Image.open(fn ).convert('RGB')
 img = tensor(np.array(img)).float() /255
img = self.normalize(img)
 imgs.append(img)
 return torch.cat(imgs ).reshape(self.N, self.sz, self.sz, 3 ).permute(0, 3, 1, 2), self.items[idx]
def normalize(self, x):
return(x-self.stats[0])/self.stats[1]
models = []
for path in MODELS:
state_dict = torch.load(path,map_location=torch.device('cpu')) ['model']
model = ModelSeDul()
model.load_state_dict(state_dict)
 model.float()
model.eval()
model.cuda()
models.append(model)
 optR = OptimizedRounder()
coefficients = [0.5, 1.5, 2.5, 3.5, 4.5]
def get_preds(N, nm, md_, TTA=False):
print('getting predictions:')
 print(f"{N}")
 ds = PandasDSST2(nm, N=N)
 dl = DataLoader(ds, batch_size=bs, num_workers=nworkers, shuffle=False)
 names,preds = [],[]
if TTA:
with torch.no_grad() :
for x,y in tqdm(dl):
x = x.cuda()
x = torch.stack([x,x.flip(-1),x.flip(-2),x.flip(-1,-2),
x.transpose(-1,-2),x.transpose(-1,-2 ).flip(-1),
x.transpose(-1,-2 ).flip(-2),x.transpose(-1,-2 ).flip(-1,-2)],1)
 x = x.view(-1,N,3,sz,sz)
 p = [model(x)for model in md_]
p = torch.stack(p,1)
 try:
p = p.view(bs, 8*len(md_),-1 ).mean(1 ).cpu()
except:
bs_= p.shape[0]
p = p.view(bs_, 8*len(md_),-1 ).mean(1 ).cpu()
names.append(y)
 preds.append(p)
 else:
with torch.no_grad() :
for x,y in tqdm(dl):
x = x.cuda()
x = x.view(-1,N,3,sz,sz)
 p = [model(x)for model in md_]
p = torch.stack(p,1)
 try:
p = p.view(bs, len(md_),-1 ).mean(1 ).cpu()
except:
bs_= p.shape[0]
p = p.view(bs_, len(md_),-1 ).mean(1 ).cpu()
names.append(y)
 preds.append(p)
 names = np.concatenate(names)
 preds = torch.cat(preds ).numpy().reshape(-1)
 sub_df = pd.DataFrame({'image_id': names, 'isup_grade': preds})
 sub_df.to_csv('submission.csv', index=False)
 return sub_df
sub_df = pd.read_csv(SAMPLE)
 if os.path.exists(DATA):
nm = pd.read_csv(TEST ).image_id.to_list()
if debug:
nm=nm[:100]
!mkdir imgs
Parallel(n_jobs=nworkers )(delayed(save_imgs )(i)for i in tqdm(nm)) ;
sub_df = get_preds(81, nm, models, TTA=True)
 sub_df.to_csv('submission.csv', index=False)
 !rm -rf 'imgs'
sub_df.to_csv('submission.csv', index=False)
 return sub_df
preds_test =(np.squeeze(np.mean(preds_test, axis=0)) > best_threshold ).astype(np.int)
 preds_test.shape<save_to_csv>
DATA = '.. /input/prostate-cancer-grade-assessment/test_images'
if os.path.exists(DATA):
res_drhb = get_drhb_best(False )
submission['target'] = preds_test
submission.to_csv('submission.csv', index=False)
 submission.head()<load_from_csv>
torch.cuda.empty_cache()
print(dirname+'/sample_submission.csv')
 test_df = pd.read_csv(dirname+'/sample_submission.csv')
 test_df.head(20)
<data_type_conversions>
def get_igor_preds(debug=False):
weights = '/kaggle/input/rnx50ws7ep28/fold0_ep28pb2.pt'
def fix_weights(weights):
state_dict = torch.load(weights)['model']
new_state_dict = collections.OrderedDict()
for k, v in state_dict.items() :
name = k[7:]
new_state_dict[name] = v
return new_state_dict
def sigmoid_scale(x, low=-1.0, high=6.0):
return torch.sigmoid(x)*(high-low)+ low
def make_divisible(v, divisor=8, min_value=None):
min_value = min_value or divisor
new_v = max(min_value, int(v + divisor / 2)// divisor * divisor)
 if new_v < 0.9 * v:
new_v += divisor
return new_v
def sigmoid(x, inplace: bool = False):
return x.sigmoid_() if inplace else x.sigmoid()
class SqueezeExcite(nn.Module):
def __init__(self, in_chs, se_ratio=0.25, reduced_base_chs=None,
act_layer=nn.ReLU, gate_fn=sigmoid, divisor=1, **_):
super(SqueezeExcite, self ).__init__()
self.gate_fn = gate_fn
reduced_chs = make_divisible(( reduced_base_chs or in_chs)* se_ratio, divisor)
 self.avg_pool = nn.AdaptiveAvgPool2d(1)
 self.conv_reduce = nn.Conv2d(in_chs, reduced_chs, 1, bias=True)
 self.act1 = act_layer(inplace=True)
 self.conv_expand = nn.Conv2d(reduced_chs, in_chs, 1, bias=True)
 def forward(self, x):
x_se = self.avg_pool(x)
 x_se = self.conv_reduce(x_se)
 x_se = self.act1(x_se)
 x_se = self.conv_expand(x_se)
 x = x * self.gate_fn(x_se)
 return x
class AdaptiveConcatPool2d(nn.Module):
def __init__(self, sz=1):
super().__init__()
self.output_size = sz or 1
self.ap = nn.AdaptiveAvgPool2d(self.output_size)
 self.mp = nn.AdaptiveMaxPool2d(self.output_size)
 def forward(self, x):
return torch.cat([self.mp(x), self.ap(x)], 1)
 class c_Conv2d(nn.Conv2d):
def __init__(self, in_channels, out_channels, kernel_size, stride=1,
padding=0, dilation=1, groups=1, bias=True):
super(c_Conv2d, self ).__init__(in_channels, out_channels, kernel_size, stride,
padding, dilation, groups, bias)
 def forward(self, x):
weight = self.weight
weight_mean = weight.mean(dim=1, keepdim=True ).mean(dim=2,
keepdim=True ).mean(dim=3, keepdim=True)
 weight = weight - weight_mean
std = weight.view(weight.size(0), -1 ).std(dim=1 ).view(-1, 1, 1, 1)+ 1e-5
weight = weight / std.expand_as(weight)
 return F.conv2d(x, weight, self.bias, self.stride,
self.padding, self.dilation, self.groups)
 def c_BatchNorm2d(num_features):
return nn.GroupNorm(num_channels=num_features, num_groups=32)
 class Bottleneck(nn.Module):
expansion = 4
def __init__(self, inplanes, planes, baseWidth, cardinality, stride=1, downsample=None):
super(Bottleneck, self ).__init__()
D = int(math.floor(planes *(baseWidth / 64)))
 C = cardinality
self.conv1 = c_Conv2d(inplanes, D*C, kernel_size=1, stride=1, padding=0, bias=False)
 self.bn1 = c_BatchNorm2d(D*C)
 self.conv2 = c_Conv2d(D*C, D*C, kernel_size=3, stride=stride, padding=1, groups=C, bias=False)
 self.bn2 = c_BatchNorm2d(D*C)
 self.conv3 = c_Conv2d(D*C, planes * 4, kernel_size=1, stride=1, padding=0, bias=False)
 self.bn3 = c_BatchNorm2d(planes * 4)
 self.relu = nn.ReLU(inplace=True)
 self.downsample = downsample
def forward(self, x):
residual = x
out = self.conv1(x)
 out = self.bn1(out)
 out = self.relu(out)
 out = self.conv2(out)
 out = self.bn2(out)
 out = self.relu(out)
 out = self.conv3(out)
 out = self.bn3(out)
 if self.downsample is not None:
residual = self.downsample(x)
 out += residual
out = self.relu(out)
 return out
class ResNeXt(nn.Module):
def __init__(self, baseWidth, cardinality, layers, num_classes):
super(ResNeXt, self ).__init__()
block = Bottleneck
self.cardinality = cardinality
self.baseWidth = baseWidth
self.num_classes = num_classes
self.inplanes = 64
self.output_size = 64
self.conv1 = c_Conv2d(3, 64, 7, 2, 3, bias=False)
 self.bn1 = c_BatchNorm2d(64)
 self.relu = nn.ReLU(inplace=True)
 self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
 self.layer1 = self._make_layer(block, 64, layers[0])
 self.layer2 = self._make_layer(block, 128, layers[1], 2)
 self.layer3 = self._make_layer(block, 256, layers[2], 2)
 self.layer4 = self._make_layer(block, 512, layers[3], 2)
 self.avgpool = nn.AvgPool2d(7)
 self.fc = nn.Linear(512 * block.expansion, num_classes)
 for m in self.modules() :
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2./ n))
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
 m.bias.data.zero_()
def _make_layer(self, block, planes, blocks, stride=1):
downsample = None
if stride != 1 or self.inplanes != planes * block.expansion:
downsample = nn.Sequential(
 c_Conv2d(self.inplanes, planes * block.expansion,
kernel_size=1, stride=stride, bias=False),
c_BatchNorm2d(planes * block.expansion), 
)
 layers = []
layers.append(block(self.inplanes, planes, self.baseWidth, self.cardinality, stride, downsample))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes, self.baseWidth, self.cardinality))
return nn.Sequential(*layers)
 def forward(self, x):
x = self.conv1(x)
 x = self.bn1(x)
 x = self.relu(x)
 x = self.maxpool1(x)
 x = self.layer1(x)
 x = self.layer2(x)
 x = self.layer3(x)
 x = self.layer4(x)
 x = self.avgpool(x)
 x = x.view(x.size(0), -1)
 x = self.fc(x)
 return x
class Resnext50_ws(nn.Module):
def __init__(self, baseWidth=4, cardinality=32):
super(Resnext50_ws, self ).__init__()
base_model = ResNeXt(baseWidth, cardinality, [3, 4, 6, 3], 1000)
 self.base_model = nn.Sequential(*list(base_model.children())[:-2])
 nc = list(base_model.children())[-1].in_features
self.conv_block = SqueezeExcite(nc)
 self.head = nn.Sequential(AdaptiveConcatPool2d() ,
nn.Flatten() ,
nn.Linear(2 * nc, 512),
nn.ReLU() ,
nn.Dropout(0.4),
nn.Linear(512, 1, bias=False))
def forward(self, x):
n = x.shape[1]
x = x.view(-1, x.shape[2], x.shape[3], x.shape[4])
 x = self.base_model(x)
 x = x.view(-1, n, x.shape[1], x.shape[2], x.shape[3] ).permute(0, 2, 1, 3, 4 ).contiguous().view(-1, x.shape[1], x.shape[2] * n, x.shape[3])
 x = x.view(x.shape[0], x.shape[1], x.shape[2]//7, -1)
 x = self.conv_block(x)
 x = self.head(x)
 return sigmoid_scale(x)
 def crop(img, tol=254):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 mask = gray < tol
img1 = img[:, :, 0][np.ix_(mask.any(1), mask.any(0)) ]
img2 = img[:, :, 1][np.ix_(mask.any(1), mask.any(0)) ]
img3 = img[:, :, 2][np.ix_(mask.any(1), mask.any(0)) ]
img = np.stack([img1, img2, img3], axis=-1)
 _, img = cv2.threshold(img, 0, 255, cv2.THRESH_TOZERO)
 return img
def pad_if_needed(img, tile):
if img.shape[0] % tile != 0 or img.shape[1] % tile != 0:
pad1 = int(np.ceil(img.shape[0] / tile))
pad1 = tile * pad1 - img.shape[0]
pad2 = int(np.ceil(img.shape[1] / tile))
pad2 = tile * pad2 - img.shape[1]
img_pad = np.pad(img,(( pad1, 0),(pad2, 0),(0, 0)) , constant_values=255)
 return img_pad
else:
return img
def windows(img_fn, tiles=49, tile_size=224, overlap=1, threshold=254):
res = skimage.io.MultiImage(img_fn)[-2]
res = crop(res)
 res = pad_if_needed(res, tile_size)
 windows = view_as_windows(res,(tile_size, tile_size, 1),(int(tile_size*overlap), int(tile_size*overlap), 1)) [..., 0].transpose(0, 1, 3, 4, 2)
 windows_orig = windows.reshape(windows.shape[0] * windows.shape[1], windows.shape[2], windows.shape[3], windows.shape[4])
 mean = np.mean(windows_orig, axis=(1, 2, 3))
windows = np.delete(windows_orig, np.where(mean >= threshold), axis=0)
 if windows.shape[0] == 0:
windows = windows_orig
idxs = np.argsort(windows.reshape(windows.shape[0], -1 ).sum(-1)) [:tiles]
if windows.shape[0] < tiles:
windows_pad = np.repeat(255*np.ones_like(np.expand_dims(windows[0], 0)) , tiles - windows.shape[0], axis=0)
 windows = np.concatenate(( windows, windows_pad), axis=0)
 else:
windows = windows[idxs]
return windows
def embed_output(output):
thrs = [0.5, 1.5, 2.5, 3.5, 4.5]
output[output < thrs[0]] = 0
output[(output >= thrs[0])&(output < thrs[1])] = 1
output[(output >= thrs[1])&(output < thrs[2])] = 2
output[(output >= thrs[2])&(output < thrs[3])] = 3
output[(output >= thrs[3])&(output < thrs[4])] = 4
output[output >= thrs[4]] = 5
return output
class TestDataset(Dataset):
def __init__(self, df, path):
self.df = df
self.path = path
def __len__(self):
return len(self.df)
 def __getitem__(self, idx):
row = self.df.iloc[idx]
img_path = '%s%s.tiff' %(self.path, row.image_id)
 image = windows(img_path)
 return torch.tensor(image.transpose(0, 3, 1, 2)).float() /255, row.image_id
model = Resnext50_ws().cuda()
model.load_state_dict(fix_weights(weights))
preds = []
preds_raw = []
names = []
path = '/kaggle/input/prostate-cancer-grade-assessment/test_images/'
submission = pd.read_csv('/kaggle/input/prostate-cancer-grade-assessment/test.csv')
 if debug:
path = '/kaggle/input/prostate-cancer-grade-assessment/train_images/'
submission = pd.read_csv('/kaggle/input/prostate-cancer-grade-assessment/train.csv')[:100]
if os.path.exists(path):
test_dataset = TestDataset(submission, path)
 test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)
 for i,(images, name)in enumerate(test_loader):
images = images.cuda()
with torch.no_grad() :
y_preds = model(images)
 preds.append(embed_output(y_preds.cpu().numpy()))
preds_raw.append(y_preds.cpu().numpy())
 names.extend(name)
 preds_out = np.concatenate(preds)
 preds_out_raw = np.concatenate(preds_raw ).reshape(-1)
 result = pd.DataFrame({
'image_id':names,
'isup_grade':preds_out_raw
})
 return result
test_df['store_id'] = test_df['id'].str[:20]
test_df['visit_date'] = test_df['id'].str[21:]
test_df.drop(['visitors'],axis=1,inplace=True)
 test_df['visit_date'] = pd.to_datetime(test_df['visit_date'])
 test_df.info()
test_df.head()<load_from_csv>
DATA = '.. /input/prostate-cancer-grade-assessment/test_images'
if os.path.exists(DATA):
res_igor = get_igor_preds(False)
 torch.cuda.empty_cache()
gc.collect()
air_data = pd.read_csv(dirname+'/air_visit_data.csv',parse_dates=['visit_date'])
 air_data.shape
air_data.head()<feature_engineering>
def get_prediction_medianse50(debug=False):
model_path= [".. /input/pandamsesmoothse50/se_resnext50_32x4d_fold0_bestOptimQWK.pth",
".. /input/pandamsesmoothse50/se_resnext50_32x4d_fold1_bestOptimQWK.pth",
".. /input/pandamsesmoothse50/se_resnext50_32x4d_fold2_bestOptimQWK.pth",
".. /input/pandamsesmoothse50/se_resnext50_32x4d_fold3_bestOptimQWK.pth",
".. /input/pandamsesmoothse50/se_resnext50_32x4d_fold4_bestOptimQWK.pth"]
if debug:
img_dir=".. /input/prostate-cancer-grade-assessment/train_images/"
df=pd.read_csv(".. /input/prostate-cancer-grade-assessment/train.csv")[:100]
else:
df=pd.read_csv(".. /input/prostate-cancer-grade-assessment/test.csv")
 img_dir=".. /input/prostate-cancer-grade-assessment/test_images/"
def tile(img,sz=128,N=12):
img = img.reshape(img.shape[0]//sz,sz,img.shape[1]//sz,sz,3)
 img = img.transpose(0,2,1,3,4 ).reshape(-1,sz,sz,3)
 if len(img)< N:
img = np.pad(img,[[0,N-len(img)],[0,0],[0,0],[0,0]],constant_values=255)
 idxs = np.argsort(img.reshape(img.shape[0],-1 ).sum(-1)) [:N]
img = img[idxs]
return 1-img.astype(np.float32)/255
def crop_white(image: np.ndarray, value: int = 255)-> np.ndarray:
assert image.shape[2] == 3
assert image.dtype == np.uint8
ys, =(image.min(( 1, 2)) < value ).nonzero()
xs, =(image.min(0 ).min(1)< value ).nonzero()
if len(xs)== 0 or len(ys)== 0:
return image
return image[ys.min() :ys.max() + 1, xs.min() :xs.max() + 1]
class DataSet_Test(object):
def __init__(self,
df,
img_dir,
size,
num_patch,
grid_offset=(0,1/3,2/3),
mean=(0.485, 0.456, 0.406),
std=(0.229, 0.224, 0.225), 
):
self.image_ids=df.image_id.tolist()
self.img_dir=img_dir
self.mean=mean
self.std=std
self.size=size
self.num_patch=num_patch
self.grid_offset=grid_offset
def __getitem__(self, idx):
img_id=self.image_ids[idx]
image=skimage.io.MultiImage(os.path.join(self.img_dir, "{}.tiff".format(img_id)))[1]
image=crop_white(image)
 _, encoded_img = cv2.imencode(".jpg", image,(int(cv2.IMWRITE_JPEG_QUALITY), 100))
image = cv2.imdecode(encoded_img, cv2.IMREAD_UNCHANGED)
 shape = image.shape
pad0, pad1 =(self.size - shape[0] % self.size)% self.size,(self.size - shape[1] % self.size)% self.size
pad_up = pad0 // 2
pad_left = pad1 // 2
all_patches=[]
for offset in self.grid_offset:
pad_up_tmp=pad_up+int(offset*self.size)
 pad_left_tmp=pad_left+int(offset*self.size)
 tmp_img = np.pad(image, [[pad_up_tmp, self.size+pad0 - pad_up_tmp], [pad_left_tmp, self.size+pad1 - pad_left_tmp], [0, 0]],constant_values=255)
 patch=tile(tmp_img,sz=self.size,N=self.num_patch)
 all_patches.append(patch)
 all_patches=np.stack(all_patches,axis=0)
 all_patches=(all_patches-self.mean)/self.std
return torch.tensor(all_patches,dtype=torch.float32 ).permute(0,1,4,2,3),img_id
def __len__(self):
return len(self.image_ids)
 class SEModule(nn.Module):
def __init__(self, channels, reduction):
super(SEModule, self ).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
 self.fc1 = nn.Conv2d(channels, channels // reduction, kernel_size=1,
padding=0)
 self.relu = nn.ReLU(inplace=True)
 self.fc2 = nn.Conv2d(channels // reduction, channels, kernel_size=1,
padding=0)
 self.sigmoid = nn.Sigmoid()
def forward(self, x):
module_input = x
x = self.avg_pool(x)
 x = self.fc1(x)
 x = self.relu(x)
 x = self.fc2(x)
 x = self.sigmoid(x)
 return module_input * x
class Bottleneck(nn.Module):

 def forward(self, x):
residual = x
out = self.conv1(x)
 out = self.bn1(out)
 out = self.relu(out)
 out = self.conv2(out)
 out = self.bn2(out)
 out = self.relu(out)
 out = self.conv3(out)
 out = self.bn3(out)
 if self.downsample is not None:
residual = self.downsample(x)
 out = self.se_module(out)+ residual
out = self.relu(out)
 return out
class SEBottleneck(Bottleneck):

 expansion = 4
def __init__(self, inplanes, planes, groups, reduction, stride=1,
downsample=None):
super(SEBottleneck, self ).__init__()
self.conv1 = nn.Conv2d(inplanes, planes * 2, kernel_size=1, bias=False)
 self.bn1 = nn.BatchNorm2d(planes * 2)
 self.conv2 = nn.Conv2d(planes * 2, planes * 4, kernel_size=3,
stride=stride, padding=1, groups=groups,
bias=False)
 self.bn2 = nn.BatchNorm2d(planes * 4)
 self.conv3 = nn.Conv2d(planes * 4, planes * 4, kernel_size=1,
bias=False)
 self.bn3 = nn.BatchNorm2d(planes * 4)
 self.relu = nn.ReLU(inplace=True)
 self.se_module = SEModule(planes * 4, reduction=reduction)
 self.downsample = downsample
self.stride = stride
class SEResNetBottleneck(Bottleneck):

 expansion = 4
def __init__(self, inplanes, planes, groups, reduction, stride=1,
downsample=None):
super(SEResNetBottleneck, self ).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False,
stride=stride)
 self.bn1 = nn.BatchNorm2d(planes)
 self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, padding=1,
groups=groups, bias=False)
 self.bn2 = nn.BatchNorm2d(planes)
 self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
 self.bn3 = nn.BatchNorm2d(planes * 4)
 self.relu = nn.ReLU(inplace=True)
 self.se_module = SEModule(planes * 4, reduction=reduction)
 self.downsample = downsample
self.stride = stride
class SEResNeXtBottleneck(Bottleneck):

 expansion = 4
def __init__(self, inplanes, planes, groups, reduction, stride=1,
downsample=None, base_width=4):
super(SEResNeXtBottleneck, self ).__init__()
width = math.floor(planes *(base_width / 64)) * groups
self.conv1 = nn.Conv2d(inplanes, width, kernel_size=1, bias=False,
stride=1)
 self.bn1 = nn.BatchNorm2d(width)
 self.conv2 = nn.Conv2d(width, width, kernel_size=3, stride=stride,
padding=1, groups=groups, bias=False)
 self.bn2 = nn.BatchNorm2d(width)
 self.conv3 = nn.Conv2d(width, planes * 4, kernel_size=1, bias=False)
 self.bn3 = nn.BatchNorm2d(planes * 4)
 self.relu = nn.ReLU(inplace=True)
 self.se_module = SEModule(planes * 4, reduction=reduction)
 self.downsample = downsample
self.stride = stride
class SENet(nn.Module):
def __init__(self, block, layers, groups, reduction, dropout_p=0.2,
inplanes=128, input_3x3=True, downsample_kernel_size=3,
downsample_padding=1, num_classes=1000):

 super(SENet, self ).__init__()
self.inplanes = inplanes
if input_3x3:
layer0_modules = [ 
('conv1', nn.Conv2d(3, 64, 3, stride=2, padding=1,
bias=False)) , 
('bn1', nn.BatchNorm2d(64)) , 
('relu1', nn.ReLU(inplace=True)) , 
('conv2', nn.Conv2d(64, 64, 3, stride=1, padding=1,
bias=False)) , 
('bn2', nn.BatchNorm2d(64)) , 
('relu2', nn.ReLU(inplace=True)) , 
('conv3', nn.Conv2d(64, inplanes, 3, stride=1, padding=1,
bias=False)) , 
('bn3', nn.BatchNorm2d(inplanes)) , 
('relu3', nn.ReLU(inplace=True)) ,
]
else:
layer0_modules = [ 
('conv1', nn.Conv2d(3, inplanes, kernel_size=7, stride=2,
padding=3, bias=False)) , 
('bn1', nn.BatchNorm2d(inplanes)) , 
('relu1', nn.ReLU(inplace=True)) ,
]
layer0_modules.append(( 'pool', nn.MaxPool2d(3, stride=2,
ceil_mode=True)))
 self.layer0 = nn.Sequential(OrderedDict(layer0_modules))
self.layer1 = self._make_layer(
 block,
planes=64,
blocks=layers[0],
groups=groups,
reduction=reduction,
downsample_kernel_size=1,
downsample_padding=0 
)
 self.layer2 = self._make_layer(
 block,
planes=128,
blocks=layers[1],
stride=2,
groups=groups,
reduction=reduction,
downsample_kernel_size=downsample_kernel_size,
downsample_padding=downsample_padding 
)
 self.layer3 = self._make_layer(
 block,
planes=256,
blocks=layers[2],
stride=2,
groups=groups,
reduction=reduction,
downsample_kernel_size=downsample_kernel_size,
downsample_padding=downsample_padding 
)
 self.layer4 = self._make_layer(
 block,
planes=512,
blocks=layers[3],
stride=2,
groups=groups,
reduction=reduction,
downsample_kernel_size=downsample_kernel_size,
downsample_padding=downsample_padding 
)
 self.avg_pool = nn.AvgPool2d(7, stride=1)
 self.dropout = nn.Dropout(dropout_p)if dropout_p is not None else None
self.last_linear = nn.Linear(512 * block.expansion, num_classes)
 def _make_layer(self, block, planes, blocks, groups, reduction, stride=1,
downsample_kernel_size=1, downsample_padding=0):
downsample = None
if stride != 1 or self.inplanes != planes * block.expansion:
downsample = nn.Sequential(
 nn.Conv2d(self.inplanes, planes * block.expansion,
kernel_size=downsample_kernel_size, stride=stride,
padding=downsample_padding, bias=False),
nn.BatchNorm2d(planes * block.expansion), 
)
 layers = []
layers.append(block(self.inplanes, planes, groups, reduction, stride,
downsample))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes, groups, reduction))
return nn.Sequential(*layers)
 def features(self, x):
x = self.layer0(x)
 x = self.layer1(x)
 x = self.layer2(x)
 x = self.layer3(x)
 x = self.layer4(x)
 return x
def features_ckpt(self,x):
x.requires_grad=True
x = checkpoint(self.layer0,x)
 x = checkpoint_sequential(self.layer1,3,x)
 x = checkpoint_sequential(self.layer2,4,x)
 x = checkpoint_sequential(self.layer3,6,x)
 x = checkpoint_sequential(self.layer4,3,x)
 return x
def logits(self, x):
x = self.avg_pool(x)
 if self.dropout is not None:
x = self.dropout(x)
 x = x.view(x.size(0), -1)
 x = self.last_linear(x)
 return x
def forward(self, x):
x = self.features(x)
 x = self.logits(x)
 return x
def se_resnext50_32x4d(num_classes=1000, pretrained='imagenet'):
model = SENet(SEResNeXtBottleneck, [3, 4, 6, 3], groups=32, reduction=16,
dropout_p=None, inplanes=64, input_3x3=False,
downsample_kernel_size=1, downsample_padding=0,
num_classes=num_classes)
 return model
class AttentionPool(nn.Module):
def __init__(self,in_ch,hidden=512,dropout=True):
super().__init__()
self.in_ch=in_ch
module=[nn.Linear(in_ch,hidden,bias=True),
nn.Tanh()
]
if dropout:
module.append(nn.Dropout(0.25))
module.append(nn.Linear(hidden,1,bias=True))
self.attention=nn.Sequential(*module)
 def forward(self,x):
num_patch=x.size(1)
 x=x.view(-1,x.size(2))
A=self.attention(x)
 A=A.view(-1,num_patch,1)
 wt=F.softmax(A,dim=1)
 return(x.view(-1,num_patch,self.in_ch)*wt ).sum(dim=1),A
class AdaptiveConcatPool2d_Attention(nn.Module):
def __init__(self, in_ch,hidden=512,dropout=True):
super().__init__()
sz =(1,1)
 self.ap = AttentionPool(in_ch,hidden=hidden,dropout=dropout)
 self.mp = nn.AdaptiveMaxPool2d(sz)
 self.in_ch=in_ch
def forward(self, x):
ap,A=self.ap(x)
 mp=torch.max(x,dim=1)[0]
return torch.cat([ap, mp], dim=1),A
class PANDA_Model_Attention_Concat_MultiTask_Headv2(nn.Module):
def __init__(self,arch='se_resnext50_32x4d',dropout=0.25,num_classes=6,checkpoint=False,scale_op=True):
super().__init__()
if "se" in arch:
self.base_model=se_resnext50_32x4d(pretrained=None)
 back_feature=self.base_model.last_linear.in_features
elif "efficientnet" in arch:
self.base_model = EfficientNet.from_pretrained(arch, num_classes=num_classes)
 back_feature = self.base_model._fc.in_features
else:
self.base_model= resnet34(pretrained=None)
 back_feature=self.base_model.last_linear.in_features
self.checkpoint=checkpoint
self.avg_pool=nn.AdaptiveAvgPool2d(1)
 self.scale_op=scale_op
self.attention=AdaptiveConcatPool2d_Attention(in_ch=back_feature,hidden=512,dropout=dropout>0)
 self.label_head=nn.Sequential(
 nn.Dropout(p=dropout),
nn.Linear(back_feature,1,bias=True)
)
 self.reg_head = nn.Sequential(
 nn.Dropout(p=dropout),
nn.Linear(2*back_feature,1,bias=True), 
)
 self.cls_head = nn.Sequential(
 nn.Dropout(p=dropout),
nn.Linear(2*back_feature,num_classes,bias=True), 
)
 def forward(self,x):
B,N,C,H,W=x.shape
x=x.view(-1,C,H,W)
 if self.checkpoint:
x=self.base_model.features_ckpt(x)
 else:
x=self.base_model.features(x)
 x=self.avg_pool(x ).view(x.size(0),-1)
 patch_pred=self.label_head(x)
 x=x.view(B,N,-1)
 x,A=self.attention(x)
 reg_pred=self.reg_head(x ).view(-1)
 if self.scale_op:
reg_pred=7.*torch.sigmoid(reg_pred)-1.
 cls_pred=self.cls_head(x)
 return reg_pred,cls_pred,patch_pred,A
modellist=[]
for path in model_path:
model=PANDA_Model_Attention_Concat_MultiTask_Headv2(arch='se_resnext50_32x4d',dropout=0.4,num_classes=6,scale_op=True)
 model.cuda()
print("Loading",path)
 ckpt=torch.load(path)
 model.load_state_dict(ckpt['state_dict'])
 model.eval()
modellist.append(model)
 print(len(modellist),"models Loaded")
 grid_offset=[0,1/2]
num_offset=len(grid_offset)
 num_patch=48
patch_size=192
dataset=DataSet_Test(df,img_dir,size=patch_size,num_patch=num_patch,grid_offset=grid_offset)
 dataloader=DataLoader(dataset,batch_size=4,shuffle=False,num_workers=2)
 def get_expectation(cls_output,label):
prob=torch.softmax(cls_output.cpu() ,dim=2)
 prob=torch.mean(prob,dim=1)
 return(label*prob ).sum(dim=1)
 label=torch.tensor([0,1,2,3,4,5],dtype=torch.float32 ).view(1,-1)
 reg_weight=1
if os.path.exists(img_dir):
prediction=[]
name=[]
for images,img_ids in tqdm(dataloader):
images=images.cuda()
images=images.view(-1,num_patch,3,patch_size,patch_size)
 reg_pred=0.
 cls_pred=0.
 with torch.no_grad() :
for model in modellist:
reg_output,cls_output,patch_pred,A=model(images)
 cls_output=cls_output.view(-1,num_offset,6)
 reg_output=reg_output.view(-1,num_offset)
 reg_pred+=reg_output.detach().cpu().numpy().mean(axis=1)
 cls_pred+=get_expectation(cls_output,label ).numpy()
reg_pred/=len(modellist)
 cls_pred/=len(modellist)
 pred_batch=reg_weight*reg_pred+(1-reg_weight)*cls_pred
prediction.append(pred_batch)
 name.extend(img_ids)
 prediction=np.concatenate(prediction ).reshape(-1)
 result=pd.DataFrame({
'image_id':name,
'isup_grade':prediction
})
 return result
else:
df=pd.read_csv(".. /input/prostate-cancer-grade-assessment/sample_submission.csv")
 return df
air_data['dow']=air_data['visit_date'].dt.dayofweek
train=air_data[air_data['visit_date']>'2017-01-28'].reset_index()
train['dow']=train['visit_date'].dt.dayofweek
test_df['dow']=test_df['visit_date'].dt.dayofweek
test_df.head()
train.head()<groupby>
DATA = '.. /input/prostate-cancer-grade-assessment/test_images'
if os.path.exists(DATA):
res_rs50 = get_prediction_medianse50(debug=False)
 torch.cuda.empty_cache()
gc.collect()
aggregation={'visitors':'median'}
agg_data=train.groupby(['air_store_id','dow'] ).agg(aggregation ).reset_index()
agg_data.colums=['air_store_id','dow','visitors']
agg_data['visitors']=agg_data['visitors']
agg_data.head(12 )<merge>
torch.backends.cudnn.benchmark = False
model_path_last_level=[]
model_path_this_level=[]
for f in range(5):
model_path_last_level.append(".. /input/panda-sekfold/se_resnext50_32x4d_fold{}_bestOptimQWK.pth".format(f,f))
print("Last level weight")
 print(model_path_last_level)
 model_path_this_level.append(".. /input/panda-efb0-largebs/efficientnet-b0_fold0_bestOptimQWK.pth")
 model_path_this_level.append(".. /input/panda-efb0-largebs/efficientnet-b0_fold1_bestOptimQWK.pth")
 model_path_this_level.append(".. /input/panda-efb0-largebs/efficientnet-b0_fold2_bestOptimQWK.pth")
 model_path_this_level.append(".. /input/panda-efb0-largebs/efficientnet-b0_fold4_bestOptimQWK.pth")
 print("This level weight")
 print(model_path_this_level)
 tiff_dir=".. /input/prostate-cancer-grade-assessment/test_images/"
df=pd.read_csv(".. /input/prostate-cancer-grade-assessment/test.csv")
 class SEModule(nn.Module):
def __init__(self, channels, reduction):
super(SEModule, self ).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
 self.fc1 = nn.Conv2d(channels, channels // reduction, kernel_size=1,
padding=0)
 self.relu = nn.ReLU(inplace=True)
 self.fc2 = nn.Conv2d(channels // reduction, channels, kernel_size=1,
padding=0)
 self.sigmoid = nn.Sigmoid()
def forward(self, x):
module_input = x
x = self.avg_pool(x)
 x = self.fc1(x)
 x = self.relu(x)
 x = self.fc2(x)
 x = self.sigmoid(x)
 return module_input * x
class Bottleneck(nn.Module):

 def forward(self, x):
residual = x
out = self.conv1(x)
 out = self.bn1(out)
 out = self.relu(out)
 out = self.conv2(out)
 out = self.bn2(out)
 out = self.relu(out)
 out = self.conv3(out)
 out = self.bn3(out)
 if self.downsample is not None:
residual = self.downsample(x)
 out = self.se_module(out)+ residual
out = self.relu(out)
 return out
class SEBottleneck(Bottleneck):

 expansion = 4
def __init__(self, inplanes, planes, groups, reduction, stride=1,
downsample=None):
super(SEBottleneck, self ).__init__()
self.conv1 = nn.Conv2d(inplanes, planes * 2, kernel_size=1, bias=False)
 self.bn1 = nn.BatchNorm2d(planes * 2)
 self.conv2 = nn.Conv2d(planes * 2, planes * 4, kernel_size=3,
stride=stride, padding=1, groups=groups,
bias=False)
 self.bn2 = nn.BatchNorm2d(planes * 4)
 self.conv3 = nn.Conv2d(planes * 4, planes * 4, kernel_size=1,
bias=False)
 self.bn3 = nn.BatchNorm2d(planes * 4)
 self.relu = nn.ReLU(inplace=True)
 self.se_module = SEModule(planes * 4, reduction=reduction)
 self.downsample = downsample
self.stride = stride
class SEResNetBottleneck(Bottleneck):

 expansion = 4
def __init__(self, inplanes, planes, groups, reduction, stride=1,
downsample=None):
super(SEResNetBottleneck, self ).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False,
stride=stride)
 self.bn1 = nn.BatchNorm2d(planes)
 self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, padding=1,
groups=groups, bias=False)
 self.bn2 = nn.BatchNorm2d(planes)
 self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
 self.bn3 = nn.BatchNorm2d(planes * 4)
 self.relu = nn.ReLU(inplace=True)
 self.se_module = SEModule(planes * 4, reduction=reduction)
 self.downsample = downsample
self.stride = stride
class SEResNeXtBottleneck(Bottleneck):

 expansion = 4
def __init__(self, inplanes, planes, groups, reduction, stride=1,
downsample=None, base_width=4):
super(SEResNeXtBottleneck, self ).__init__()
width = math.floor(planes *(base_width / 64)) * groups
self.conv1 = nn.Conv2d(inplanes, width, kernel_size=1, bias=False,
stride=1)
 self.bn1 = nn.BatchNorm2d(width)
 self.conv2 = nn.Conv2d(width, width, kernel_size=3, stride=stride,
padding=1, groups=groups, bias=False)
 self.bn2 = nn.BatchNorm2d(width)
 self.conv3 = nn.Conv2d(width, planes * 4, kernel_size=1, bias=False)
 self.bn3 = nn.BatchNorm2d(planes * 4)
 self.relu = nn.ReLU(inplace=True)
 self.se_module = SEModule(planes * 4, reduction=reduction)
 self.downsample = downsample
self.stride = stride
class SENet(nn.Module):
def __init__(self, block, layers, groups, reduction, dropout_p=0.2,
inplanes=128, input_3x3=True, downsample_kernel_size=3,
downsample_padding=1, num_classes=1000):

 super(SENet, self ).__init__()
self.inplanes = inplanes
if input_3x3:
layer0_modules = [ 
('conv1', nn.Conv2d(3, 64, 3, stride=2, padding=1,
bias=False)) , 
('bn1', nn.BatchNorm2d(64)) , 
('relu1', nn.ReLU(inplace=True)) , 
('conv2', nn.Conv2d(64, 64, 3, stride=1, padding=1,
bias=False)) , 
('bn2', nn.BatchNorm2d(64)) , 
('relu2', nn.ReLU(inplace=True)) , 
('conv3', nn.Conv2d(64, inplanes, 3, stride=1, padding=1,
bias=False)) , 
('bn3', nn.BatchNorm2d(inplanes)) , 
('relu3', nn.ReLU(inplace=True)) ,
]
else:
layer0_modules = [ 
('conv1', nn.Conv2d(3, inplanes, kernel_size=7, stride=2,
padding=3, bias=False)) , 
('bn1', nn.BatchNorm2d(inplanes)) , 
('relu1', nn.ReLU(inplace=True)) ,
]
layer0_modules.append(( 'pool', nn.MaxPool2d(3, stride=2,
ceil_mode=True)))
 self.layer0 = nn.Sequential(OrderedDict(layer0_modules))
self.layer1 = self._make_layer(
 block,
planes=64,
blocks=layers[0],
groups=groups,
reduction=reduction,
downsample_kernel_size=1,
downsample_padding=0 
)
 self.layer2 = self._make_layer(
 block,
planes=128,
blocks=layers[1],
stride=2,
groups=groups,
reduction=reduction,
downsample_kernel_size=downsample_kernel_size,
downsample_padding=downsample_padding 
)
 self.layer3 = self._make_layer(
 block,
planes=256,
blocks=layers[2],
stride=2,
groups=groups,
reduction=reduction,
downsample_kernel_size=downsample_kernel_size,
downsample_padding=downsample_padding 
)
 self.layer4 = self._make_layer(
 block,
planes=512,
blocks=layers[3],
stride=2,
groups=groups,
reduction=reduction,
downsample_kernel_size=downsample_kernel_size,
downsample_padding=downsample_padding 
)
 self.avg_pool = nn.AvgPool2d(7, stride=1)
 self.dropout = nn.Dropout(dropout_p)if dropout_p is not None else None
self.last_linear = nn.Linear(512 * block.expansion, num_classes)
 def _make_layer(self, block, planes, blocks, groups, reduction, stride=1,
downsample_kernel_size=1, downsample_padding=0):
downsample = None
if stride != 1 or self.inplanes != planes * block.expansion:
downsample = nn.Sequential(
 nn.Conv2d(self.inplanes, planes * block.expansion,
kernel_size=downsample_kernel_size, stride=stride,
padding=downsample_padding, bias=False),
nn.BatchNorm2d(planes * block.expansion), 
)
 layers = []
layers.append(block(self.inplanes, planes, groups, reduction, stride,
downsample))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes, groups, reduction))
return nn.Sequential(*layers)
 def features(self, x):
x = self.layer0(x)
 x = self.layer1(x)
 x = self.layer2(x)
 x = self.layer3(x)
 x = self.layer4(x)
 return x
def features_ckpt(self,x):
x.requires_grad=True
x = checkpoint(self.layer0,x,preserve_rng_state=False)
 x = checkpoint_sequential(self.layer1,3,x,preserve_rng_state=False)
 x = checkpoint_sequential(self.layer2,4,x,preserve_rng_state=False)
 x = checkpoint_sequential(self.layer3,6,x,preserve_rng_state=False)
 x = checkpoint_sequential(self.layer4,3,x,preserve_rng_state=False)
 return x
def logits(self, x):
x = self.avg_pool(x)
 if self.dropout is not None:
x = self.dropout(x)
 x = x.view(x.size(0), -1)
 x = self.last_linear(x)
 return x
def forward(self, x):
x = self.features(x)
 x = self.logits(x)
 return x
def se_resnext50_32x4d(num_classes=1000, pretrained='imagenet'):
model = SENet(SEResNeXtBottleneck, [3, 4, 6, 3], groups=32, reduction=16,
dropout_p=None, inplanes=64, input_3x3=False,
downsample_kernel_size=1, downsample_padding=0,
num_classes=num_classes)
 if pretrained is not None:
settings = pretrained_settings['se_resnext50_32x4d'][pretrained]
initialize_pretrained_model(model, num_classes, settings)
 return model
class ResNet(nn.Module):
def __init__(self, model):
super(ResNet, self ).__init__()
self.conv1 = model.conv1
self.bn1 = model.bn1
self.relu = model.relu
self.maxpool = model.maxpool
self.layer1 = model.layer1
self.layer2 = model.layer2
self.layer3 = model.layer3
self.layer4 = model.layer4
self.avgpool = model.avgpool
self.last_linear = model.fc
def features(self, input):
x = self.conv1(input)
 x = self.bn1(x)
 x = self.relu(x)
 x = self.maxpool(x)
 x = self.layer1(x)
 x = self.layer2(x)
 x = self.layer3(x)
 x = self.layer4(x)
 return x
def features_ckpt(self, input):
x = self.conv1(input)
 x = self.bn1(x)
 x = self.relu(x)
 x = self.maxpool(x)
 x = checkpoint_sequential(self.layer1,3,x)
 x = checkpoint_sequential(self.layer2,4,x)
 x = checkpoint_sequential(self.layer3,6,x)
 x = checkpoint_sequential(self.layer4,3,x)
 return x
def logits(self, features):
x = self.avgpool(features)
 x = x.view(x.size(0), -1)
 x = self.last_linear(x)
 return x
def forward(self, input):
x = self.features(input)
 x = self.logits(x)
 return x
def resnet34(num_classes=1000, pretrained='imagenet'):

 model = models.resnet34(pretrained=False, num_classes=num_classes)
 if pretrained is not None:
settings = pretrained_settings['resnet34'][pretrained]
model = load_pretrained(model, num_classes, settings)
 model = ResNet(model)
 return model

 GlobalParams = collections.namedtuple('GlobalParams', [
'batch_norm_momentum', 'batch_norm_epsilon', 'dropout_rate',
'num_classes', 'width_coefficient', 'depth_coefficient',
'depth_divisor', 'min_depth', 'drop_connect_rate', 'image_size'])
 BlockArgs = collections.namedtuple('BlockArgs', [
'kernel_size', 'num_repeat', 'input_filters', 'output_filters',
'expand_ratio', 'id_skip', 'stride', 'se_ratio'])
 GlobalParams.__new__.__defaults__ =(None,)* len(GlobalParams._fields)
 BlockArgs.__new__.__defaults__ =(None,)* len(BlockArgs._fields)
 class SwishImplementation(torch.autograd.Function):
@staticmethod
def forward(ctx, i):
result = i * torch.sigmoid(i)
 ctx.save_for_backward(i)
 return result
@staticmethod
def backward(ctx, grad_output):
i = ctx.saved_variables[0]
sigmoid_i = torch.sigmoid(i)
 return grad_output *(sigmoid_i *(1 + i *(1 - sigmoid_i)))
 class MemoryEfficientSwish(nn.Module):
def forward(self, x):
return SwishImplementation.apply(x)
 class Swish(nn.Module):
def forward(self, x):
return x * torch.sigmoid(x)
 def round_filters(filters, global_params):

 multiplier = global_params.width_coefficient
if not multiplier:
return filters
divisor = global_params.depth_divisor
min_depth = global_params.min_depth
filters *= multiplier
min_depth = min_depth or divisor
new_filters = max(min_depth, int(filters + divisor / 2)// divisor * divisor)
 if new_filters < 0.9 * filters:
new_filters += divisor
return int(new_filters)
 def round_repeats(repeats, global_params):

 multiplier = global_params.depth_coefficient
if not multiplier:
return repeats
return int(math.ceil(multiplier * repeats))
def drop_connect(inputs, p, training):

 if not training: return inputs
batch_size = inputs.shape[0]
keep_prob = 1 - p
random_tensor = torch.rand([batch_size, 1, 1, 1], dtype=inputs.dtype, device=inputs.device)+keep_prob
binary_tensor = torch.floor(random_tensor)
 output = inputs / keep_prob * binary_tensor
return output
def get_same_padding_conv2d(image_size=None):

 if image_size is None:
return Conv2dDynamicSamePadding
else:
return partial(Conv2dStaticSamePadding, image_size=image_size)
 class Conv2dDynamicSamePadding(nn.Conv2d):

 def __init__(self, in_channels, out_channels, kernel_size, stride=1, dilation=1, groups=1, bias=True):
super().__init__(in_channels, out_channels, kernel_size, stride, 0, dilation, groups, bias)
 self.stride = self.stride if len(self.stride)== 2 else [self.stride[0]] * 2
def forward(self, x):
ih, iw = x.size() [-2:]
kh, kw = self.weight.size() [-2:]
sh, sw = self.stride
oh, ow = math.ceil(ih / sh), math.ceil(iw / sw)
 pad_h = max(( oh - 1)* self.stride[0] +(kh - 1)* self.dilation[0] + 1 - ih, 0)
 pad_w = max(( ow - 1)* self.stride[1] +(kw - 1)* self.dilation[1] + 1 - iw, 0)
 if pad_h > 0 or pad_w > 0:
x = F.pad(x, [pad_w // 2, pad_w - pad_w // 2, pad_h // 2, pad_h - pad_h // 2])
 return F.conv2d(x, self.weight, self.bias, self.stride, self.padding, self.dilation, self.groups)
 class Conv2dStaticSamePadding(nn.Conv2d):

 def __init__(self, in_channels, out_channels, kernel_size, image_size=None, **kwargs):
super().__init__(in_channels, out_channels, kernel_size, **kwargs)
 self.stride = self.stride if len(self.stride)== 2 else [self.stride[0]] * 2
assert image_size is not None
ih, iw = image_size if type(image_size)== list else [image_size, image_size]
kh, kw = self.weight.size() [-2:]
sh, sw = self.stride
oh, ow = math.ceil(ih / sh), math.ceil(iw / sw)
 pad_h = max(( oh - 1)* self.stride[0] +(kh - 1)* self.dilation[0] + 1 - ih, 0)
 pad_w = max(( ow - 1)* self.stride[1] +(kw - 1)* self.dilation[1] + 1 - iw, 0)
 if pad_h > 0 or pad_w > 0:
self.static_padding = nn.ZeroPad2d(( pad_w // 2, pad_w - pad_w // 2, pad_h // 2, pad_h - pad_h // 2))
else:
self.static_padding = Identity()
def forward(self, x):
x = self.static_padding(x)
 x = F.conv2d(x, self.weight, self.bias, self.stride, self.padding, self.dilation, self.groups)
 return x
class Identity(nn.Module):
def __init__(self,):
super(Identity, self ).__init__()
def forward(self, input):
return input
def efficientnet_params(model_name):

 params_dict = {
'efficientnet-b0':(1.0, 1.0, 224, 0.2),
'efficientnet-b1':(1.0, 1.1, 240, 0.2),
'efficientnet-b2':(1.1, 1.2, 260, 0.3),
'efficientnet-b3':(1.2, 1.4, 300, 0.3),
'efficientnet-b4':(1.4, 1.8, 380, 0.4),
'efficientnet-b5':(1.6, 2.2, 456, 0.4),
'efficientnet-b6':(1.8, 2.6, 528, 0.5),
'efficientnet-b7':(2.0, 3.1, 600, 0.5),
'efficientnet-b8':(2.2, 3.6, 672, 0.5),
'efficientnet-l2':(4.3, 5.3, 800, 0.5),
}
return params_dict[model_name]
class BlockDecoder(object):

 @staticmethod
def _decode_block_string(block_string):

 assert isinstance(block_string, str)
 ops = block_string.split('_')
 options = {}
for op in ops:
splits = re.split(r'(\d.*)', op)
 if len(splits)>= 2:
key, value = splits[:2]
options[key] = value
assert(( 's' in options and len(options['s'])== 1)or 
(len(options['s'])== 2 and options['s'][0] == options['s'][1]))
return BlockArgs(
 kernel_size=int(options['k']),
num_repeat=int(options['r']),
input_filters=int(options['i']),
output_filters=int(options['o']),
expand_ratio=int(options['e']),
id_skip=('noskip' not in block_string),
se_ratio=float(options['se'])if 'se' in options else None,
stride=[int(options['s'][0])])
 @staticmethod
def _encode_block_string(block):

 args = [
'r%d' % block.num_repeat,
'k%d' % block.kernel_size,
's%d%d' %(block.strides[0], block.strides[1]),
'e%s' % block.expand_ratio,
'i%d' % block.input_filters,
'o%d' % block.output_filters
]
if 0 < block.se_ratio <= 1:
args.append('se%s' % block.se_ratio)
 if block.id_skip is False:
args.append('noskip')
 return '_'.join(args)
 @staticmethod
def decode(string_list):

 assert isinstance(string_list, list)
 blocks_args = []
for block_string in string_list:
blocks_args.append(BlockDecoder._decode_block_string(block_string))
return blocks_args
@staticmethod
def encode(blocks_args):

 block_strings = []
for block in blocks_args:
block_strings.append(BlockDecoder._encode_block_string(block))
return block_strings
def efficientnet(width_coefficient=None, depth_coefficient=None, dropout_rate=0.2,
drop_connect_rate=0.2, image_size=None, num_classes=1000):

 blocks_args = [
'r1_k3_s11_e1_i32_o16_se0.25', 'r2_k3_s22_e6_i16_o24_se0.25',
'r2_k5_s22_e6_i24_o40_se0.25', 'r3_k3_s22_e6_i40_o80_se0.25',
'r3_k5_s11_e6_i80_o112_se0.25', 'r4_k5_s22_e6_i112_o192_se0.25',
'r1_k3_s11_e6_i192_o320_se0.25',
]
blocks_args = BlockDecoder.decode(blocks_args)
 global_params = GlobalParams(
 batch_norm_momentum=0.99,
batch_norm_epsilon=1e-3,
dropout_rate=dropout_rate,
drop_connect_rate=drop_connect_rate,
num_classes=num_classes,
width_coefficient=width_coefficient,
depth_coefficient=depth_coefficient,
depth_divisor=8,
min_depth=None,
image_size=image_size, 
)
 return blocks_args, global_params
def get_model_params(model_name, override_params):

 if model_name.startswith('efficientnet'):
w, d, s, p = efficientnet_params(model_name)
 blocks_args, global_params = efficientnet(
 width_coefficient=w, depth_coefficient=d, dropout_rate=p, image_size=s)
 else:
raise NotImplementedError('model name is not pre-defined: %s' % model_name)
 if override_params:
global_params = global_params._replace(**override_params)
 return blocks_args, global_params
url_map = {
'efficientnet-b0': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b0-355c32eb.pth',
'efficientnet-b1': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b1-f1951068.pth',
'efficientnet-b2': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b2-8bb594d6.pth',
'efficientnet-b3': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b3-5fb5a3c3.pth',
'efficientnet-b4': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b4-6ed6700e.pth',
'efficientnet-b5': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b5-b6417697.pth',
'efficientnet-b6': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b6-c76e70fd.pth',
'efficientnet-b7': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b7-dcc49843.pth',
}
url_map_advprop = {
'efficientnet-b0': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b0-b64d5a18.pth',
'efficientnet-b1': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b1-0f3ce85a.pth',
'efficientnet-b2': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b2-6e9d97e5.pth',
'efficientnet-b3': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b3-cdd7c0f4.pth',
'efficientnet-b4': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b4-44fb3a87.pth',
'efficientnet-b5': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b5-86493f6b.pth',
'efficientnet-b6': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b6-ac80338e.pth',
'efficientnet-b7': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b7-4652b6dd.pth',
'efficientnet-b8': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b8-22a8fe65.pth',
}
def load_pretrained_weights(model, model_name, load_fc=True, advprop=False):

 url_map_ = url_map_advprop if advprop else url_map
state_dict = model_zoo.load_url(url_map_[model_name])
 if load_fc:
model.load_state_dict(state_dict)
 else:
state_dict.pop('_fc.weight')
 state_dict.pop('_fc.bias')
 res = model.load_state_dict(state_dict, strict=False)
 assert set(res.missing_keys)== set(['_fc.weight', '_fc.bias']), 'issue loading pretrained weights'
print('Loaded pretrained weights for {}'.format(model_name))
class AttentionPool(nn.Module):
def __init__(self,in_ch,hidden=512,dropout=True):
super().__init__()
self.in_ch=in_ch
module=[nn.Linear(in_ch,hidden,bias=True),
nn.Tanh()
]
if dropout:
module.append(nn.Dropout(0.25))
module.append(nn.Linear(hidden,1,bias=True))
self.attention=nn.Sequential(*module)
 def forward(self,x):
num_patch=x.size(1)
 x=x.view(-1,x.size(2))
A=self.attention(x)
 A=A.view(-1,num_patch,1)
 wt=F.softmax(A,dim=1)
 return(x.view(-1,num_patch,self.in_ch)*wt ).sum(dim=1),A
class AdaptiveConcatPool2d_Attention(nn.Module):
def __init__(self, in_ch,hidden=512,dropout=True):
super().__init__()
sz =(1,1)
 self.ap = AttentionPool(in_ch,hidden=hidden,dropout=dropout)
 self.mp = nn.AdaptiveMaxPool2d(sz)
 self.in_ch=in_ch
def forward(self, x):
ap,A=self.ap(x)
 mp=torch.max(x,dim=1)[0]
return torch.cat([ap, mp], dim=1),A
class PANDA_Model_Attention_Concat_MultiTask_Headv2(nn.Module):
def __init__(self,arch='se_resnext50_32x4d',dropout=0.25,num_classes=6,checkpoint=False,scale_op=True):
super().__init__()
self.scale_op=scale_op
if "se" in arch:
self.base_model=se_resnext50_32x4d(pretrained=None)
 back_feature=self.base_model.last_linear.in_features
elif "efficientnet" in arch:
self.base_model = EfficientNet.from_pretrained(arch, num_classes=num_classes)
 back_feature = self.base_model._fc.in_features
else:
self.base_model= resnet34(pretrained=None)
 back_feature=self.base_model.last_linear.in_features
self.checkpoint=checkpoint
self.avg_pool=nn.AdaptiveAvgPool2d(1)
 self.attention=AdaptiveConcatPool2d_Attention(in_ch=back_feature,hidden=512,dropout=dropout>0)
 self.label_head=nn.Sequential(
 nn.Dropout(p=dropout),
nn.Linear(back_feature,1,bias=True)
)
 self.reg_head = nn.Sequential(
 nn.Dropout(p=dropout),
nn.Linear(2*back_feature,1,bias=True), 
)
 self.cls_head = nn.Sequential(
 nn.Dropout(p=dropout),
nn.Linear(2*back_feature,num_classes,bias=True), 
)
 def forward(self,x):
B,N,C,H,W=x.shape
x=x.view(-1,C,H,W)
 if self.checkpoint:
x=self.base_model.features_ckpt(x)
 else:
x=self.base_model.features(x)
 x=self.avg_pool(x ).view(x.size(0),-1)
 patch_pred=self.label_head(x)
 x=x.view(B,N,-1)
 x,A=self.attention(x)
 reg_pred=self.reg_head(x ).view(-1)
 if self.scale_op:
reg_pred=7.*torch.sigmoid(reg_pred)-1.
 cls_pred=self.cls_head(x)
 return reg_pred,cls_pred,patch_pred,A
def crop_white(image, value=255):
assert image.shape[2] == 3
assert image.dtype == np.uint8
ys, =(image.min(( 1, 2)) < value ).nonzero()
xs, =(image.min(0 ).min(1)< value ).nonzero()
if len(xs)== 0 or len(ys)== 0:
return image,np.array([0,0], dtype=np.int)
 return image[ys.min() :ys.max() + 1, xs.min() :xs.max() + 1],np.array([ys.min() , xs.min() ], dtype=np.int)
 def crop_patches(img,bg_threshold, sz=192):
W=img.shape[1]
img = img.reshape(img.shape[0] // sz, sz, img.shape[1] // sz, sz, 3)
 img = img.transpose(0, 2, 1, 3, 4 ).reshape(-1, sz * sz, 3)
 sat = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)[:, :, 1]
background_ratio =(sat < 20 ).astype(np.float32 ).reshape(img.shape[0], -1 ).sum(1)/(sz * sz)
 fg_idx = np.where(background_ratio < bg_threshold)[0]
img = img[fg_idx]
coord = np.stack([fg_idx //(W // sz), fg_idx %(W // sz)], axis=1)*sz
return img.reshape(-1, sz, sz, 3), coord, background_ratio[fg_idx]
def crop_upper_level(img_id, coords, sz, scale=0.5):
image = openslide.OpenSlide(os.path.join(tiff_dir,"{}.tiff".format(img_id)))
 patches = []
for coord in coords:
x = coord[1] * 4
y = coord[0] * 4
x = max(0,x)
 y = max(0,y)
 region_sz = int(sz * 4)
 patch = image.read_region(( x, y), 0,(region_sz, region_sz))
patch = np.asarray(patch.convert("RGB"))
if scale != 1:
patch = cv2.resize(patch, dsize=(int(scale * patch.shape[1]), int(scale * patch.shape[0])))
 patches.append(patch)
 return patches
def get_next_level_patches(img_id,attention,coords,sz=192,scale=0.5,max_patch=64):
idx=np.argsort(attention)[::-1]
N=min(max_patch,len(idx))
idx=idx[:N]
coords=coords[idx]
next_level_patches=crop_upper_level(img_id,coords,sz,scale)
 return next_level_patches,attention[idx],idx
def prepare_next_level_input(next_level_patches,patch_num=32,crop_func=None,
mean=(0.485, 0.456, 0.406),
std=(0.229, 0.224, 0.225),):
next_level_patches=np.stack(next_level_patches,axis=0)
 patches=[]
for patch in next_level_patches:
_, encoded_img = cv2.imencode(".jpg", patch,(int(cv2.IMWRITE_JPEG_QUALITY), 95))
patch = cv2.imdecode(encoded_img, cv2.IMREAD_UNCHANGED)
 patches.append(patch)
 if crop_func is not None:
patches=[crop_func(image=x)['image'] for x in patches]
patches=np.stack(patches,axis=0)
 if len(patches)<patch_num:
patches=np.pad(patches,[[0,patch_num-len(patches)],[0,0],[0,0],[0,0]],constant_values=255)
 patches = 1.0 - patches.astype(np.float32)/ 255
patches =(patches - mean)/std
return torch.tensor(patches,dtype=torch.float32,device='cuda' ).permute(0,3,1,2 ).unsqueeze(0)
 class MBConvBlock(nn.Module):

 def __init__(self, block_args, global_params):
super().__init__()
self._block_args = block_args
self._bn_mom = 1 - global_params.batch_norm_momentum
self._bn_eps = global_params.batch_norm_epsilon
self.has_se =(self._block_args.se_ratio is not None)and(0 < self._block_args.se_ratio <= 1)
 self.id_skip = block_args.id_skip
Conv2d = get_same_padding_conv2d(image_size=global_params.image_size)
 inp = self._block_args.input_filters
oup = self._block_args.input_filters * self._block_args.expand_ratio
if self._block_args.expand_ratio != 1:
self._expand_conv = Conv2d(in_channels=inp, out_channels=oup, kernel_size=1, bias=False)
 self._bn0 = nn.BatchNorm2d(num_features=oup, momentum=self._bn_mom, eps=self._bn_eps)
 k = self._block_args.kernel_size
s = self._block_args.stride
self._depthwise_conv = Conv2d(
 in_channels=oup, out_channels=oup, groups=oup,
kernel_size=k, stride=s, bias=False)
 self._bn1 = nn.BatchNorm2d(num_features=oup, momentum=self._bn_mom, eps=self._bn_eps)
 if self.has_se:
num_squeezed_channels = max(1, int(self._block_args.input_filters * self._block_args.se_ratio))
self._se_reduce = Conv2d(in_channels=oup, out_channels=num_squeezed_channels, kernel_size=1)
 self._se_expand = Conv2d(in_channels=num_squeezed_channels, out_channels=oup, kernel_size=1)
 final_oup = self._block_args.output_filters
self._project_conv = Conv2d(in_channels=oup, out_channels=final_oup, kernel_size=1, bias=False)
 self._bn2 = nn.BatchNorm2d(num_features=final_oup, momentum=self._bn_mom, eps=self._bn_eps)
 self._swish = MemoryEfficientSwish()
def forward(self, inputs, drop_connect_rate=None):

 x = inputs
if self._block_args.expand_ratio != 1:
x = self._swish(self._bn0(self._expand_conv(inputs)))
 x = self._swish(self._bn1(self._depthwise_conv(x)))
 if self.has_se:
x_squeezed = F.adaptive_avg_pool2d(x, 1)
 x_squeezed = self._se_expand(self._swish(self._se_reduce(x_squeezed)))
 x = torch.sigmoid(x_squeezed)* x
x = self._bn2(self._project_conv(x))
input_filters, output_filters = self._block_args.input_filters, self._block_args.output_filters
if self.id_skip and self._block_args.stride == 1 and input_filters == output_filters:
if drop_connect_rate:
x = drop_connect(x, p=drop_connect_rate, training=self.training)
 x = x + inputs
return x
def set_swish(self, memory_efficient=True):

 self._swish = MemoryEfficientSwish() if memory_efficient else Swish()
class EfficientNet(nn.Module):

 def __init__(self, blocks_args=None, global_params=None):
super().__init__()
assert isinstance(blocks_args, list), 'blocks_args should be a list'
assert len(blocks_args)> 0, 'block args must be greater than 0'
self._global_params = global_params
self._blocks_args = blocks_args
Conv2d = get_same_padding_conv2d(image_size=global_params.image_size)
 bn_mom = 1 - self._global_params.batch_norm_momentum
bn_eps = self._global_params.batch_norm_epsilon
in_channels = 3
out_channels = round_filters(32, self._global_params)
 self._conv_stem = Conv2d(in_channels, out_channels, kernel_size=3, stride=2, bias=False)
 self._bn0 = nn.BatchNorm2d(num_features=out_channels, momentum=bn_mom, eps=bn_eps)
 self._blocks = nn.ModuleList([])
 for block_args in self._blocks_args:
block_args = block_args._replace(
 input_filters=round_filters(block_args.input_filters, self._global_params),
output_filters=round_filters(block_args.output_filters, self._global_params),
num_repeat=round_repeats(block_args.num_repeat, self._global_params)
)
 self._blocks.append(MBConvBlock(block_args, self._global_params))
if block_args.num_repeat > 1:
block_args = block_args._replace(input_filters=block_args.output_filters, stride=1)
 for _ in range(block_args.num_repeat - 1):
self._blocks.append(MBConvBlock(block_args, self._global_params))
in_channels = block_args.output_filters
out_channels = round_filters(1280, self._global_params)
 self._conv_head = Conv2d(in_channels, out_channels, kernel_size=1, bias=False)
 self._bn1 = nn.BatchNorm2d(num_features=out_channels, momentum=bn_mom, eps=bn_eps)
 self._avg_pooling = nn.AdaptiveAvgPool2d(1)
 self._dropout = nn.Dropout(self._global_params.dropout_rate)
 self._fc = nn.Linear(out_channels, self._global_params.num_classes)
 self._swish = MemoryEfficientSwish()
def set_swish(self, memory_efficient=True):

 self._swish = MemoryEfficientSwish() if memory_efficient else Swish()
for block in self._blocks:
block.set_swish(memory_efficient)
 def features(self, inputs):

 x = self._swish(self._bn0(self._conv_stem(inputs)))
 for idx, block in enumerate(self._blocks):
drop_connect_rate = self._global_params.drop_connect_rate
if drop_connect_rate:
drop_connect_rate *= float(idx)/ len(self._blocks)
 x = block(x, drop_connect_rate=drop_connect_rate)
 x = self._swish(self._bn1(self._conv_head(x)))
 return x
def features_ckpt(self, inputs):

 x = self._swish(self._bn0(self._conv_stem(inputs)))
 for idx, block in enumerate(self._blocks):
drop_connect_rate = self._global_params.drop_connect_rate
if drop_connect_rate:
drop_connect_rate *= float(idx)/ len(self._blocks)
 x=checkpoint(block,x,torch.tensor(drop_connect_rate ).cuda() ,preserve_rng_state=True)
 x = self._swish(self._bn1(self._conv_head(x)))
 return x
def forward(self, inputs):

 bs = inputs.size(0)
 x = self.features(inputs)
 x = self._avg_pooling(x)
 x = x.view(bs, -1)
 x = self._dropout(x)
 x = self._fc(x)
 return x
@classmethod
def from_name(cls, model_name, override_params=None):
cls._check_model_name_is_valid(model_name)
 blocks_args, global_params = get_model_params(model_name, override_params)
 return cls(blocks_args, global_params)
 @classmethod
def from_pretrained(cls, model_name, advprop=False, num_classes=1000, in_channels=3):
model = cls.from_name(model_name, override_params={'num_classes': num_classes})
 if in_channels != 3:
Conv2d = get_same_padding_conv2d(image_size = model._global_params.image_size)
 out_channels = round_filters(32, model._global_params)
 model._conv_stem = Conv2d(in_channels, out_channels, kernel_size=3, stride=2, bias=False)
 return model
@classmethod
def get_image_size(cls, model_name):
cls._check_model_name_is_valid(model_name)
 _, _, res, _ = efficientnet_params(model_name)
 return res
@classmethod
def _check_model_name_is_valid(cls, model_name):

 valid_models = ['efficientnet-b'+str(i)for i in range(9)]
if model_name not in valid_models:
raise ValueError('model_name should be one of: ' + ', '.join(valid_models))
class PANDAPatchExtraction_Test(object):
def __init__(self,
df,
tiff_dir,
patch_size=192,
bg_threshold=0.8,
trail_offset=[0,1/2],
mean=(0.485, 0.456, 0.406),
std=(0.229, 0.224, 0.225), 
):
self.image_ids = df['image_id'].tolist()
self.tiff_dir = tiff_dir
self.patch_size = patch_size
self.bg_threshold = bg_threshold
self.trail_offset=trail_offset
self.mean = np.array(mean, dtype=np.float32)
 self.std = np.array(std, dtype=np.float)
 def __getitem__(self, idx):
img_id = self.image_ids[idx]
image = skimage.io.MultiImage(os.path.join(self.tiff_dir, "{}.tiff".format(img_id)))[1]
image,offset = crop_white(image)
 _, encoded_img = cv2.imencode(".jpg", image,(int(cv2.IMWRITE_JPEG_QUALITY), 100))
image = cv2.imdecode(encoded_img, cv2.IMREAD_UNCHANGED)
 shape = image.shape
pad0 =(self.patch_size - shape[0] % self.patch_size)% self.patch_size
pad1 =(self.patch_size - shape[1] % self.patch_size)% self.patch_size
pad_up = pad0 // 2
pad_left = pad1 // 2
best_mean_bg_ratio=1000
best_patch=None
best_coord=None
best_pad_offset=None
for trail_offset in self.trail_offset:
trail_pad_up = pad_up + int(self.patch_size * trail_offset)
 trail_pad_left = pad_left + int(self.patch_size * trail_offset)
 image_tmp = np.pad(image, [[trail_pad_up, pad0+self.patch_size - trail_pad_up], [trail_pad_left, pad1+self.patch_size - trail_pad_left], [0, 0]], constant_values=255)
 patches, coords,bg_ratio = crop_patches(image_tmp,self.bg_threshold, sz=self.patch_size)
 if np.mean(bg_ratio)<best_mean_bg_ratio:
best_mean_bg_ratio=np.mean(bg_ratio)
 best_patch=patches
best_coord=coords
best_pad_offset=(trail_pad_up,trail_pad_left)
 offset[0] -= best_pad_offset[0]
offset[1] -= best_pad_offset[1]
if len(best_patch)==0:
best_patch=255*np.ones(( 1,self.patch_size,self.patch_size,3))
best_coord=np.zeros(( 1,2))
best_coord = best_coord + offset.reshape(1, 2)
 best_patch = 1.0 - best_patch.astype(np.float32)/ 255
best_patch =(best_patch - self.mean)/ self.std
return torch.tensor(best_patch, dtype=torch.float32 ).permute(0, 3, 1, 2), best_coord, img_id
def __len__(self):
return len(self.image_ids)
 def safe_run(model,images,max_bs=128):
num_patch=images.shape[1]
split_dim=[max_bs]*(num_patch//max_bs)
 if num_patch%max_bs>0:
split_dim+=[num_patch%max_bs]
attention=[]
for split_img in torch.split(images,split_dim,dim=1):
with torch.no_grad() :
split_img=split_img.cuda()
output,_,_,A=model(split_img)
 attention.append(A.cpu())
 return torch.cat(attention,dim=1)
 model_last_level=[]
model_this_level=[]
for p in model_path_last_level:
print("Loading last level",p)
 model=PANDA_Model_Attention_Concat_MultiTask_Headv2(arch='se_resnext50_32x4d',
dropout=0.25,
num_classes=6,
scale_op=False, 
)
 model.cuda()
ckpt=torch.load(p)
 model.load_state_dict(ckpt['state_dict'])
 model.eval()
model_last_level.append(model)
 for p in model_path_this_level:
print("Loading this level",p)
 model=PANDA_Model_Attention_Concat_MultiTask_Headv2(arch='efficientnet-b0',
dropout=0.4,
num_classes=6,
scale_op=True, 
)
 model.cuda()
ckpt=torch.load(p)
 model.load_state_dict(ckpt['state_dict'])
 model.eval()
model_this_level.append(model)
 print(len(model_last_level),"Median resolution models")
 print(len(model_this_level),"High resolution models")
 dataset=PANDAPatchExtraction_Test(df,
tiff_dir,
patch_size=192,
bg_threshold=0.95,
trail_offset=[0,1/2], 
)
 dataloader=DataLoader(dataset,batch_size=1,shuffle=False,num_workers=2)
 coef=[0.5,1.5,2.5,3.5,4.5]
def predict(X, coef):
return pd.cut(X, [-np.inf] + list(np.sort(coef)) + [np.inf], labels=[0, 1, 2, 3,4,5])
 if os.path.exists(tiff_dir):
prediction=[]
name=[]
for images,coords,img_ids in tqdm(dataloader):
with torch.no_grad() :
A=[]
for model in model_last_level:
att=safe_run(model,images ).view(-1 ).numpy()
A.append(att)
 A=np.stack(A,axis=0 ).mean(axis=0)
 coords=coords.numpy().reshape(-1,2)
 next_level_patches,attention,idx=get_next_level_patches(img_ids[0],A,coords,sz=192,scale=0.5,max_patch=36)
 next_level_patches=prepare_next_level_input(next_level_patches,patch_num=36,crop_func=None)
 reg_pred = 0.
 cls_pred = 0.
 next_level_patches = torch.cat(
 [next_level_patches,next_level_patches.flip(( 3,4)) ],dim=0)
 for model in model_this_level:
reg_output, cls_output, patch_pred, A = model(next_level_patches)
 cls_output = cls_output.view(-1, 6 ).mean(dim=0)
 reg_output = reg_output.view(-1 ).mean(dim=0)
 reg_pred += reg_output.cpu().numpy()
cls_pred += cls_output.cpu().numpy()
reg_pred /= len(model_this_level)
 cls_pred /= len(model_this_level)
 prediction.append(reg_pred)
 name.extend(img_ids)
 prediction=np.array(prediction ).reshape(-1)
 res_ruef=pd.DataFrame({
'image_id':name,
'isup_grade':prediction
})
 print(res_ruef.head())
 else:
df=pd.read_csv(".. /input/prostate-cancer-grade-assessment/sample_submission.csv")
 df.to_csv("./submission.csv",index=False )
marged=pd.merge(test_df,agg_data,how='left',left_on=['store_id','dow'],right_on=['air_store_id','dow'])
 marged.head()
final = marged[['id','visitors']]
final.head()<count_missing_values>
del dataloader
del dataset
del model_last_level
del model_this_level
torch.cuda.empty_cache()
gc.collect()
def missing_values_table(df):
mis_val = df.isnull().sum()
mis_val_percent=100*df.isnull().sum() /len(df)
 mis_val_table=pd.concat([mis_val,mis_val_percent],axis=1)
 mis_val_table_ren_columns=mis_val_table.rename(
 columns={0:'MisiingValues',1:'% of Total Values'})
 return mis_val_table_ren_columns
missing_values_table(final )<count_missing_values>
print('Tensorflow version : {}'.format(tf.__version__))
final.fillna(0,inplace=True)
 missing_values_table(final )<feature_engineering>
def predict(X, coef=[0.5,1.5,2.5,3.5,4.5]):
return pd.cut(X, [-np.inf] + list(np.sort(coef)) + [np.inf], labels=[0, 1, 2, 3,4,5] )
dfs = { re.search('/([^/\.]*)\.csv', fn ).group(1):pd.read_csv(fn)for fn in glob.glob(dirname+'/*.csv')}
for k, v in dfs.items() : locals() [k] = v
print('data frames read:{}'.format(list(dfs.keys())))
<feature_engineering>
def get_xie29_raw_prediction(debug=False):
class FixedDropout(tf.keras.layers.Dropout):
def _get_noise_shape(self, inputs):
if self.noise_shape is None:
return self.noise_shape
symbolic_shape = tf.keras.backend.shape(inputs)
 noise_shape = [symbolic_shape[axis] if shape is None else shape
for axis, shape in enumerate(self.noise_shape)]
return tuple(noise_shape)
 class Generalized_mean_pooling2D(tf.keras.layers.Layer):
def __init__(self, p=3, epsilon=1e-6, name='', trainable=True, **kwargs):
super(Generalized_mean_pooling2D, self ).__init__()
self.init_p = p
self.epsilon = epsilon
def build(self, input_shape):
if isinstance(input_shape, list)or len(input_shape)!= 4:
raise ValueError('`GeM` pooling layer only allow 1 input with 4 dimensions(b, h, w, c)')
 self.build_shape = input_shape
self.p = self.add_weight(
 name='p',
shape=[1,],
initializer=tf.keras.initializers.Constant(value=self.init_p),
regularizer=None,
trainable=True,
dtype=tf.float32 
)
 self.built=True
def call(self, inputs):
input_shape = inputs.get_shape()
if isinstance(inputs, list)or len(input_shape)!= 4:
raise ValueError('`GeM` pooling layer only allow 1 input with 4 dimensions(b, h, w, c)')
 return(tf.reduce_mean(tf.abs(inputs**self.p), axis=[1,2], keepdims=False)+ self.epsilon)**(1.0/self.p)
 def get_config(self):
config = super().get_config().copy()
config.update({
'p': self.init_p,
'epsilon': self.epsilon
})
 return config
class TestGenerator(tf.keras.utils.Sequence):
def __init__(self,
image_shape,
batch_size,
load_dir,
test_df 
):
self.image_shape = image_shape
self.batch_size = batch_size
self.test_df = test_df
self.image_ids = test_df['image_id'].values
self.load_dir = load_dir
self.indices = range(test_df.shape[0])
 def __len__(self):
return self.test_df.shape[0] // self.batch_size
def __getitem__(self, index):
batch_indices = self.indices[self.batch_size * index : self.batch_size *(index+1)]
image_ids = self.image_ids[batch_indices]
batch_images = [self.__getimages__(image_id)for image_id in image_ids]
return np.stack(batch_images)
 def glue_tiles(self, images, y_tiles_num=3, x_tiles_num=4, sz=128):
glued_image = np.zeros(( sz*y_tiles_num, sz*x_tiles_num, 3), np.uint8)
 for i, image in enumerate(images):
y_start = int(i / x_tiles_num)* sz
y_end = y_start + sz
x_start = int(i % x_tiles_num)* sz
x_end = x_start + sz
glued_image[y_start:y_end, x_start:x_end, :] = image
return glued_image
def get_foreground(self, image):
grayscale = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
 _, thresh = cv2.threshold(grayscale, 200, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
 if np.sum(thresh)== 0:
return image
bbox = cv2.boundingRect(thresh)
 x, y, w, h = bbox
foreground = image[y:y+h, x:x+w]
return foreground
def __getimages__(self, img_id):
read_in_path = os.path.join(self.load_dir, img_id + '.tiff')
 img = skimage.io.MultiImage(read_in_path)[1]
shape = img.shape
pad0,pad1 =(sz - shape[0]%sz)%sz,(sz - shape[1]%sz)%sz
img = np.pad(img,[[pad0//2,pad0-pad0//2],[pad1//2,pad1-pad1//2],[0,0]],constant_values=255)
 img = img.reshape(img.shape[0]//sz,sz,img.shape[1]//sz,sz,3)
 img = img.transpose(0,2,1,3,4 ).reshape(-1,sz,sz,3)
 if len(img)< N:
img = np.pad(img,[[0,N-len(img)],[0,0],[0,0],[0,0]],constant_values=255)
 idxs = np.argsort(img.reshape(img.shape[0],-1 ).sum(-1)) [:N]
img = img[idxs]
slim_images = []
for i in img:
i = self.get_foreground(i)
 slim_images.append(cv2.resize(i,(resize_sz, resize_sz), cv2.INTER_AREA))
del img
glued_image = self.glue_tiles(slim_images, y_tiles_num, x_tiles_num, resize_sz)

return glued_image/255.0
def prediction_decode(y_preds):
for i, pred in enumerate(y_preds):
if pred < 0.5:
y_preds[i] = 0
elif pred >= 0.5 and pred < 1.5:
y_preds[i] = 1
elif pred >= 1.5 and pred < 2.5:
y_preds[i] = 2
elif pred >= 2.5 and pred < 3.5:
y_preds[i] = 3
elif pred >= 3.5 and pred < 4.5:
y_preds[i] = 4
else:
y_preds[i] = 5
return y_preds.astype(np.int32)
 @tf.function
def inference_step(images):
preds = model(images, training=False)
 return preds
def inference(model, test_generator):
prediction = []
for step in range(test_generator.__len__()):
print('=', end='', flush=True)
 images = test_generator.__getitem__(step)
 preds = model(images, training=False)
 preds = preds[0].numpy()
for y_pred in preds:
prediction.append(y_pred)
 print('')
 return np.array(prediction, dtype=np.float32)
 get_custom_objects().update({'swish': tf.keras.layers.Activation(tf.nn.swish)})
 get_custom_objects().update({'FixedDropout':FixedDropout})
 get_custom_objects().update({'Generalized_mean_pooling2D':Generalized_mean_pooling2D})
 MAIN_DIR = '.. /input/prostate-cancer-grade-assessment'
sample_csv = pd.read_csv(os.path.join(MAIN_DIR, 'sample_submission.csv'))
main_folder = 'test'
if debug:
sample_csv = pd.read_csv(os.path.join(MAIN_DIR, 'train.csv')) [:100]
main_folder = 'train'
x_tiles_num = 12
y_tiles_num = 12
sz = 128
resize_sz = 128
IMG_DIM =(int(resize_sz*y_tiles_num), int(resize_sz*x_tiles_num))
CLASSES_NUM = 1
BATCH_SIZE = 32
N= 144
PRETRAIN_PATH = ['.. /input/panda-best-weights/fold0_b3_144tiles_128tilesize_mse_huber_0905kcv_0853rcv_0706.h5',
'.. /input/panda-best-weights/fold2_b3_144tiles_128tilesize_mse_huber_09174kcv_0841rcv_0719.h5']
raw_prediction = sample_csv['isup_grade'].values
print(f'folder using: {main_folder}')
 test_generator = TestGenerator(image_shape=IMG_DIM,
batch_size=1,
load_dir=os.path.join(MAIN_DIR, f'{main_folder}_images'),
test_df=sample_csv)
 for idx in range(len(PRETRAIN_PATH)) :
if PRETRAIN_PATH[idx]:
print('load xies model pretrain weights.. ')
 model = tf.keras.models.load_model(PRETRAIN_PATH[idx],
custom_objects={
'Generalized_mean_pooling2D' : Generalized_mean_pooling2D
})
 if os.path.exists(f'.. /input/prostate-cancer-grade-assessment/{main_folder}_images'):
if idx == 0:
raw_prediction = inference(model, test_generator)
 else:
raw_prediction += inference(model, test_generator)
 print('Clean usage memory of xie29...')
 del model
tf.keras.backend.clear_session()
gc.collect()
raw_prediction = raw_prediction / len(PRETRAIN_PATH)
 sample_csv['isup_grade'] = raw_prediction
return sample_csv
<feature_engineering><EOS> 
DATA = '.. /input/prostate-cancer-grade-assessment/test_images'
if os.path.exists(DATA):
xie = get_xie29_raw_prediction(debug=False)
 res_drhb = res_drhb.rename(columns={'isup_grade': 'res_drhb'})
 res_igor = res_igor.rename(columns={'isup_grade': 'res_igor'})
 res_rs50 = res_rs50.rename(columns={'isup_grade': 'res_rs50'})
 res_ruef = res_ruef.rename(columns={'isup_grade': 'res_ruef'})
 xie = xie.rename(columns={'isup_grade': 'res_xief'})
 sub_df = reduce(lambda x,y: pd.merge(x,y, on='image_id'), [res_drhb, res_igor, res_rs50, res_ruef, xie])
 sub_df['med_level'] =(sub_df['res_drhb'] +
sub_df['res_igor'] +
sub_df['res_rs50'])/3
sub_df['isup_grade'] = predict(( sub_df['med_level'] +
sub_df['res_ruef' ] +
sub_df['res_xief' ])/3)
 sub_df = sub_df[['image_id', 'isup_grade']].copy()
sub_df.to_csv("./submission.csv",index=False)
 print('Clean usage memory of xie29...' )