Kaggle competition: Prostate cANcer graDe Assessment (PANDA) Challenge
<SOS> metric: QuadraticWeightedKappa Kaggle data source: prostate-cancer-grade-assessment-(panda)-challenge<statistical_test>
sys.path = [
'.. /input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master',
] + sys.path
EMBEDDING_FILE = '.. /input/embeddings/wiki-news-300d-1M/wiki-news-300d-1M.vec'
def get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')
 embeddings_index = dict(get_coefs(*o.split(" ")) for o in open(EMBEDDING_FILE)if len(o)>100)
 all_embs = np.stack(embeddings_index.values())
 emb_mean,emb_std = all_embs.mean() , all_embs.std()
embed_size = all_embs.shape[1]
word_index = tokenizer.word_index
nb_words = min(max_features, len(word_index))
embedding_matrix2 = np.random.normal(emb_mean, emb_std,(nb_words, embed_size))
for word, i in word_index.items() :
if i >= max_features: continue
embedding_vector = embeddings_index.get(word)
 if embedding_vector is not None: embedding_matrix2[i] = embedding_vector<choose_model_class>
data_dir = '.. /input/prostate-cancer-grade-assessment'
df_train = pd.read_csv(os.path.join(data_dir, 'train.csv'))
df_test = pd.read_csv(os.path.join(data_dir, 'test.csv'))
df_sub = pd.read_csv(os.path.join(data_dir, 'sample_submission.csv'))
model_dir = '.. /input/panda-base-model'
image_folder = os.path.join(data_dir, 'test_images')
 is_test = os.path.exists(image_folder)
 image_folder = image_folder if is_test else os.path.join(data_dir, 'train_images')
 df = df_test if is_test else df_train.loc[:3]
print(df.shape)
 tile_size = 256
image_size = 256
n_tiles = 36
batch_size = 4
num_workers = 4
device = torch.device('cuda')
 print(image_folder )
inp = Input(shape=(maxlen,))
model1_out = Embedding(max_features, embed_size, weights=[embedding_matrix1],trainable=False )(inp)
 model1_out = Bidirectional(CuDNNGRU(128, return_sequences=True))(model1_out)
 model1_out = AttentionWithContext()(model1_out)
 model1_out = Dense(64, activation="relu" )(model1_out)
 model1_out = Dropout(0.1 )(model1_out)
 model1_out = Dense(32, activation="relu" )(model1_out)
 model1_out = Dropout(0.1 )(model1_out)
 model1_out = Dense(1, activation="sigmoid" )(model1_out)
 model = Model(inputs=inp, outputs=model1_out)
 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
 print(model.summary() )<choose_model_class>
class enetv2(nn.Module):
def __init__(self, backbone, out_dim):
super(enetv2, self ).__init__()
self.enet = enet.EfficientNet.from_name(backbone)
 self.myfc = nn.Linear(self.enet._fc.in_features, out_dim)
 self.enet._fc = nn.Identity()
def extract(self, x):
return self.enet(x)
 def forward(self, x):
x = self.extract(x)
 x = self.myfc(x)
 return x
def load_models(model_files):
models = []
for model_dict in model_files:
model_f = model_dict['name']
model_f = os.path.join(model_dir, model_f)
 backbone = 'efficientnet-b0'
model = enetv2(backbone, out_dim=model_dict['out_dim'])
 if model_dict['parallel']:
model = nn.DataParallel(model)
 model.load_state_dict(torch.load(model_f, map_location=lambda storage, loc: storage), strict=True)
 model.eval()
model.to(device)
 models.append(model)
 print(f'{model_f} loaded!')
 return models
model_files = [
{
'name': 'model_2_bce_0.881.pth',
'parallel': True,
'out_dim': 6,
'n_tiles': 36
},
{
'name': 'model_0_bce_4x4_0.884.pth',
'parallel': False,
'out_dim': 5,
'n_tiles': 16
},
{
'name': 'model_2_bce_5x5_total_0.883.pth',
'parallel': False,
'out_dim': 5,
'n_tiles': 25
},
{
'name': 'model_3_bce_6x6_total_0.883.pth',
'parallel': False,
'out_dim': 5,
'n_tiles': 36
}
]
models = load_models(model_files )
inp = Input(shape=(maxlen,))
model2_out = Embedding(max_features, embed_size, weights=[embedding_matrix2],trainable=False )(inp)
 model2_out = Bidirectional(CuDNNGRU(128, return_sequences=True))(model2_out)
 model2_out = AttentionWithContext()(model2_out)
 model2_out = Dense(64, activation="relu" )(model2_out)
 model2_out = Dropout(0.1 )(model2_out)
 model2_out = Dense(32, activation="relu" )(model2_out)
 model2_out = Dropout(0.1 )(model2_out)
 model2_out = Dense(1, activation="sigmoid" )(model2_out)
 model2 = Model(inputs=inp, outputs=model2_out)
 model2.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
 print(model2.summary() )<train_model>
def get_tiles(img, n_tiles, mode=0):
result = []
h, w, c = img.shape
pad_h =(tile_size - h % tile_size)% tile_size
pad_w =(tile_size - w % tile_size)% tile_size
mode_pad_h =(tile_size * mode)// 4
mode_pad_w =(tile_size * mode)// 4
img2 = np.pad(img,[[pad_h // 2 + mode_pad_h, pad_h - pad_h // 2 + tile_size - mode_pad_h],
[pad_w // 2 + mode_pad_w, pad_w - pad_w // 2 + tile_size - mode_pad_w], [0,0]], constant_values=255)
 img3 = img2.reshape(
 img2.shape[0] // tile_size,
tile_size,
img2.shape[1] // tile_size,
tile_size,
3 
)
 img3 = img3.transpose(0,2,1,3,4 ).reshape(-1, tile_size, tile_size,3)
 n_tiles_with_info =(img3.reshape(img3.shape[0],-1 ).sum(1)< tile_size ** 2 * 3 * 255 ).sum()
if len(img3)< n_tiles:
img3 = np.pad(img3, [[0, n_tiles - len(img3)], [0, 0] , [0, 0] , [0, 0]], constant_values=255)
 idxs = np.argsort(img3.reshape(img3.shape[0],-1 ).sum(-1)) [:n_tiles]
img3 = img3[idxs]
for i in range(len(img3)) :
result.append({'img':img3[i], 'idx':i})
 return result, n_tiles_with_info >= n_tiles
class PANDADataset(Dataset):
def __init__(self,
df,
image_size,
n_tiles=n_tiles,
tile_mode=0,
rotate=False,
rand=False,
sub_imgs=False 
):
self.df = df.reset_index(drop=True)
 self.image_size = image_size
self.n_tiles = n_tiles
self.tile_mode = tile_mode
self.rotate = rotate
self.rand = rand
self.sub_imgs = sub_imgs
def __len__(self):
return self.df.shape[0]
def __getitem__(self, index):
row = self.df.iloc[index]
img_id = row.image_id
tiff_file = os.path.join(image_folder, f'{img_id}.tiff')
 image = skimage.io.MultiImage(tiff_file)[1]
tiles, OK = get_tiles(image, n_tiles=self.n_tiles, mode=self.tile_mode)
 if self.rand:
idxes = np.random.choice(list(range(self.n_tiles)) , self.n_tiles, replace=False)
 else:
idxes = list(range(self.n_tiles))
idxes = np.asarray(idxes)+ self.n_tiles if self.sub_imgs else idxes
n_row_tiles = int(np.sqrt(self.n_tiles))
images = np.zeros(( image_size * n_row_tiles, image_size * n_row_tiles, 3))
for h in range(n_row_tiles):
for w in range(n_row_tiles):
i = h * n_row_tiles + w
if len(tiles)> idxes[i]:
this_img = tiles[idxes[i]]['img']
else:
this_img = np.ones(( self.image_size, self.image_size, 3)).astype(np.uint8)* 255
this_img = 255 - this_img
h1 = h * image_size
w1 = w * image_size
if self.rotate:
this_img = this_img.transpose(1, 0, 2)[::-1]
images[h1:h1+image_size, w1:w1+image_size] = this_img
images = images.astype(np.float32)
 images /= 255
images = images.transpose(2, 0, 1)
 return torch.tensor(images )
def train_model(model, all_train_X, all_train_y, all_val_X, all_val_y, epochs=2):
filepath="weights_best.h5"
checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=2, save_best_only=True, mode='min')
 reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=1, min_lr=0.0001, verbose=2)
 earlystopping = EarlyStopping(monitor='val_loss', min_delta=0.0001, patience=2, verbose=2, mode='auto')
 callbacks = [checkpoint, reduce_lr]
for e in range(epochs):
model.fit(all_train_X, all_train_y, batch_size=1024, epochs=1, validation_data=(all_val_X, all_val_y), callbacks=callbacks)
 model.load_weights(filepath)
 return model<train_model>
model_loaders = []
for model_dict, model in zip(model_files, models):
loaders = []
for mode in [0, 1, 2, 3]:
for rotate in [False, True]:
dataset = PANDADataset(df, image_size, n_tiles=model_dict['n_tiles'], tile_mode=mode, rotate=rotate)
 loader = DataLoader(dataset, batch_size=batch_size, num_workers=num_workers, shuffle=False)
 loaders.append(loader)
 model_loaders.append(( model, loaders))
print(f'{len(model_loaders)* len(model_loaders[0][1])} predictions in total' )
<predict_on_test><EOS> 
LOGITSS = []
with torch.no_grad() :
for model, loaders in model_loaders:
for loader in loaders:
LOGITS = []
for data in tqdm(loader):
data = data.to(device)
 logits = model(data)
 LOGITS.append(logits)
 LOGITS = torch.cat(LOGITS ).sigmoid().cpu().numpy().sum(1)
 LOGITSS.append(LOGITS)
 LOGITS = np.array(LOGITSS ).mean(0)
 PREDS = LOGITS.round()
df['isup_grade'] = PREDS.astype(int)
 df[['image_id', 'isup_grade']].to_csv('submission.csv', index=False)
 print(df.head())
 print()
print(df.isup_grade.value_counts() )