Kaggle competition: Plant Pathology 2020 - FGVC7
<SOS> metric: MCAUC Kaggle data source: plant-pathology-2020-fgvc7<load_pretrained>
!pip install -q git+https://github.com/fastai/fastai2
!pip install -q git+https://github.com/fastai/fastcore
model = EfficientNet.from_name('efficientnet-b0')
 in_features = model._fc.in_features
model._fc = nn.Linear(in_features, num_classes)
 model.load_state_dict(torch.load('.. /input/enet-test/weight_best(3 ).pt'))
model.cuda()<find_best_params>
from fastai2.vision.all import *
for param in model.parameters() :
param.requires_grad = False<load_from_csv>
path = Path("/kaggle/input/plant-pathology-2020-fgvc7" )
sample = pd.read_csv('.. /input/aptos2019-blindness-detection/sample_submission.csv' )<predict_on_test>
train_df = pd.read_csv(path/"train.csv")
 train_df.head()
%%time
test_pred = np.zeros(( len(sample), 1))
model.eval()
for _ in range(TTA):
with torch.no_grad() :
for i, data in tqdm(enumerate(test_loader)) :
images, _ = data
images = images.cuda()
pred = model(images)
 test_pred[i * 16:(i + 1)* 16] += pred.detach().cpu().squeeze().numpy().reshape(-1, 1)
 output = test_pred / TTA<define_search_space>
train_df.iloc[0, 1:][train_df.iloc[0, 1:] == 1].index[0]
coef = [0.57, 1.37, 2.57, 3.57]<feature_engineering>
BS = 8
for i, pred in enumerate(output):
if pred < coef[0]:
output[i] = 0
elif pred >= coef[0] and pred < coef[1]:
output[i] = 1
elif pred >= coef[1] and pred < coef[2]:
output[i] = 2
elif pred >= coef[2] and pred < coef[3]:
output[i] = 3
else:
output[i] = 4<save_to_csv>
def get_data(size=224):
return DataBlock(blocks =(ImageBlock, CategoryBlock),
get_x=ColReader(0, pref=path/"images", suff=".jpg"),
get_y=lambda o:o.iloc[1:][o.iloc[1:] == 1].index[0],
splitter=RandomSplitter(seed=42),
item_tfms=Resize(size),
batch_tfms=aug_transforms(flip_vert=True),
).dataloaders(train_df, bs=BS )
submission = pd.DataFrame({'id_code':pd.read_csv('.. /input/aptos2019-blindness-detection/sample_submission.csv' ).id_code.values,
'diagnosis':np.squeeze(output ).astype(int)})
 print(submission.head())
 submission.to_csv('submission.csv', index=False)
 print(os.listdir('./'))<define_variables>
dls = get_data(( 450, 800))
DEVICE = torch.device("cuda:0")
 DATA_SOURCE = os.path.join(".. ","input","aptos2019-blindness-detection")
 MODEL_SOURCE = os.path.join(".. ","input","torchvisionmodelspartial1")
 MODEL_SIZE = 224<prepare_x_and_y>
def roc_auc(preds, targs, labels=range(4)) :
targs = np.eye(4)[targs]
return np.mean([roc_auc_score(targs[:,i], preds[:,i])for i in labels])
 def healthy_roc_auc(*args):
return roc_auc(*args, labels=[0])
 def multiple_diseases_roc_auc(*args):
return roc_auc(*args, labels=[1])
 def rust_roc_auc(*args):
return roc_auc(*args, labels=[2])
 def scab_roc_auc(*args):
return roc_auc(*args, labels=[3] )
def crop_image(img,tol=7):
w, h = img.shape[1],img.shape[0]
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 gray_img = cv2.blur(gray_img,(5,5))
shape = gray_img.shape
gray_img = gray_img.reshape(-1,1)
 quant = quantile_transform(gray_img, n_quantiles=256, random_state=0, copy=True)
 quant =(quant*256 ).astype(int)
 gray_img = quant.reshape(shape)
 xp =(gray_img.mean(axis=0)>tol)
 yp =(gray_img.mean(axis=1)>tol)
 x1, x2 = np.argmax(xp), w-np.argmax(np.flip(xp))
y1, y2 = np.argmax(yp), h-np.argmax(np.flip(yp))
if x1 >= x2 or y1 >= y2 :
return img
else:
img1=img[y1:y2,x1:x2,0]
img2=img[y1:y2,x1:x2,1]
img3=img[y1:y2,x1:x2,2]
img = np.stack([img1,img2,img3],axis=-1)
 return img
def process_image(image, size=512):
image = cv2.resize(image,(size,int(size*image.shape[0]/image.shape[1])))
 image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
 try:
image = crop_image(image, tol=15)
 except Exception as e:
image = image
print(str(e))
return image<load_from_csv>
metric = partial(AccumMetric, flatten=False)
 def get_learner(size=224):
dls = get_data(size)
 return cnn_learner(dls, resnet152, metrics=[
error_rate,
metric(healthy_roc_auc),
metric(multiple_diseases_roc_auc),
metric(rust_roc_auc),
metric(scab_roc_auc),
metric(roc_auc)],
).to_fp16()
class RetinopathyDataset(Dataset):
def __init__(self, transform, is_test=False):
self.transform = transform
self.base_transform = transforms.Resize(( MODEL_SIZE, MODEL_SIZE))
self.is_test = is_test
if not os.path.exists("cache"): os.mkdir("cache")
 if is_test : file = "test.csv"
else : file = "train.csv"
csv_file = os.path.join(DATA_SOURCE, file)
 df = pd.read_csv(csv_file)
 self.data = df.reset_index(drop=True)
 def __len__(self):
return len(self.data)
 def __getitem__(self, idx):
if self.is_test : archive = "test_images"
else : archive = "train_images"
folder = os.path.join(DATA_SOURCE, archive)
 code = str(self.data.loc[idx, 'id_code'])
 file = code + ".png"
cache_path = os.path.join("cache",code+".png")
 cached = os.path.exists(cache_path)
 if not cached :
path = os.path.join(folder, file)
 image = cv2.imread(path)
 image = process_image(image)
 imgpil = Image.fromarray(image)
 imgpil = self.base_transform(imgpil)
 imgpil.save(cache_path,"PNG")
 imgpil = Image.open(cache_path)
 img_tensor = self.transform(imgpil)
 if self.is_test : return {'image': img_tensor}
else :
label = self.data.loc[idx, "diagnosis"]
return {'image': img_tensor, 'label': label}
def get_df(self):
return self.data<split>
learn = get_learner(( 450, 800))
NUM_FOLDS = 5
data_augmentation = transforms.Compose([
transforms.RandomRotation(( -15, 15)) ,
transforms.Resize(224),
transforms.RandomHorizontalFlip() ,
transforms.RandomVerticalFlip() ,
transforms.ToTensor() ,
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
 ])
 DATA = RetinopathyDataset(data_augmentation)
 df = DATA.get_df()
skf = StratifiedKFold(n_splits=NUM_FOLDS)
 folds_generator = skf.split(df.index.values, df.diagnosis.values)
 data_train, data_eval = [], []
for t, e in folds_generator:
data_train.append(t)
 data_eval.append(e )<load_pretrained>
lr = 3e-3
def get_dataloader_for_fold(n, data, train_data, eval_data, batch_size):

 train_sampler = SubsetRandomSampler(train_data[n])
 valid_sampler = SubsetRandomSampler(eval_data[n])
 data_loader_train = torch.utils.data.DataLoader(data,
batch_size=batch_size, drop_last=False,
sampler=train_sampler)
 data_loader_eval = torch.utils.data.DataLoader(data,
batch_size=batch_size, drop_last=False,
sampler=valid_sampler)
 return data_loader_train, data_loader_eval<choose_model_class>
m = "multiple_diseases_roc_auc"
d = 0.005
learn.fine_tune(50, lr, freeze_epochs=1, cbs=[EarlyStoppingCallback(monitor=m, min_delta=d, patience=10),
SaveModelCallback(monitor=m, min_delta=d),
ReduceLROnPlateau(monitor=m, min_delta=d, patience=4)] )
class Classificator(nn.Module):

 def __init__(self, size=128):
super(Classificator, self ).__init__()
self.size = size
self.network = nn.Sequential(
 nn.BatchNorm1d(size),
nn.Dropout(p=0.3),
nn.Linear(in_features=size, out_features=5, bias=True), 
)
 def forward(self, x):
return self.network(x )<load_pretrained>
interp = ClassificationInterpretation.from_learner(learn )
def get_base_model() :

 model = torchvision.models.densenet161(pretrained=False)
 model_path = os.path.join(MODEL_SOURCE, "densenet161.pth")
 model.load_state_dict(torch.load(model_path))
in_features = model.classifier.in_features
model.classifier = Classificator(in_features)
 model = model.to(DEVICE)
 model.eval()
return model<choose_model_class>
test_df = pd.read_csv(path/"test.csv")
 test_df.head()
def train_model(model, optimizer, scheduler, train_data_loader, eval_data_loader,
file_name, num_epochs = 50, patience = 7, prev_loss = 1000.00):

 criterion = nn.CrossEntropyLoss()
countdown = patience
best_loss = 1000.00
since = time.time()
for epoch in range(num_epochs):
running_loss = 0.0
counter = 0
for bi, d in enumerate(train_data_loader):
inputs = d["image"].to(DEVICE, dtype=torch.float)
 labels = d["label"].to(DEVICE, dtype=torch.long)
 if inputs.shape[0] > 1 :
counter += inputs.size(0)
 model.to(DEVICE)
 model.train()
optimizer.zero_grad()
outputs = model(inputs)
 loss = criterion(outputs, labels)
 loss.backward()
optimizer.step()
running_loss += loss.item() * inputs.size(0)
 loss_val = running_loss / counter
print("{:7} {:.4f} {:.4f}".format(counter, loss.item() *1, loss_val), end="\r")
 epoch_loss = running_loss /(len(train_data_loader)* train_data_loader.batch_size)
 time_elapsed = time.time() - since
print(" T{:3}/{:3} loss: {:.4f}({:3.0f}m {:2.0f}s)".format(
 epoch, num_epochs - 1, epoch_loss,time_elapsed // 60, time_elapsed % 60))
running_loss = 0.0
counter = 0
for bi, d in enumerate(eval_data_loader):
inputs = d["image"].to(DEVICE, dtype=torch.float)
 counter += inputs.size(0)
 labels = d["label"].to(DEVICE, dtype=torch.long)
 model.to(DEVICE)
 model.eval()
with torch.no_grad() :
outputs = model(inputs)
 loss = criterion(outputs, labels)
 running_loss += loss.item() * inputs.size(0)
 loss_val = running_loss / counter
print("{:7} {:.4f} {:.4f}".format(counter, loss.item() *1, loss_val), end="\r")
 epoch_loss = running_loss /(len(eval_data_loader)* eval_data_loader.batch_size)
 if epoch_loss < best_loss :
best_loss = epoch_loss
if epoch_loss < prev_loss:
torch.save(model.state_dict() , file_name)
 prev_loss = epoch_loss
print("*", end="")
 else:
print(".", end="")
 countdown = patience
else:
print("{:1}".format(countdown), end="")
 countdown -= 1
time_elapsed = time.time() - since
print("E{:3}/{:3} loss: {:.4f}({:3.0f}m {:2.0f}s)".format(
 epoch, num_epochs - 1, epoch_loss,time_elapsed // 60, time_elapsed % 60))
scheduler.step()
if countdown <= 0 : break
return prev_loss
print("done.")
<load_pretrained>
tst_dl = learn.dls.test_dl(test_df )
batch_size = 56
num_round_per_fold = 3
for no in range(NUM_FOLDS):
print("-"*22, "fold",no)
 bst_loss = 10000.00
for r in range(num_round_per_fold):
print("-"*11,"round",r)
 data_loader_train, data_loader_eval = get_dataloader_for_fold(no,
DATA, data_train, data_eval, batch_size)
 model = get_base_model()
plist = [{"params": model.features.denseblock3.parameters() , "lr":0.0001},
{"params": model.features.denseblock4.parameters() , "lr":0.0001},
{"params": model.classifier.parameters() }]
optimizer = optim.Adam(plist, lr=0.001, amsgrad=True)
 scheduler = optim.lr_scheduler.MultiStepLR(optimizer, [1,5], gamma=0.1, last_epoch=-1)
 bst_loss = train_model(model, optimizer, scheduler,
data_loader_train, data_loader_eval,
"tmp"+str(no)+".pth", prev_loss=bst_loss,
num_epochs=9, patience=3)
 print("-"*22, "best loss", bst_loss)
 print("")
<load_pretrained>
preds, _ = learn.get_preds(dl=tst_dl )
def get_trained_model(no):

 extractor = torchvision.models.densenet161(pretrained=False)
 in_features = extractor.classifier.in_features
extractor.classifier = Classificator(in_features)
 model_path = os.path.join("tmp"+str(no)+".pth")
 extractor.load_state_dict(torch.load(model_path))
extractor = extractor.to(DEVICE)
 extractor.eval()
return extractor<choose_model_class>
subm = pd.read_csv(path/"sample_submission.csv" )
def get_extractor_model(no):

 extractor = get_trained_model(no)
 extractor.classifier = nn.Identity()
extractor = extractor.to(DEVICE)
 extractor.eval()
return extractor<categorify>
subm.iloc[:, 1:] = preds
def get_train_features(data_loader, extractor):

 for bi, d in enumerate(data_loader):
print(".", end="")
 img_tensor = d["image"].to(DEVICE)
 target = d["label"].numpy()
with torch.no_grad() : feature = extractor(img_tensor)
 feature = feature.cpu().detach().squeeze(0 ).numpy()
if bi == 0 :
features = feature
targets = target
else :
features = np.concatenate([features, feature], axis=0)
 targets = np.concatenate([targets, target], axis=0)
 return features, targets<init_hyperparams>
subm.to_csv("submission.csv", index=False )
<feature_engineering><EOS> 
pd.read_csv("submission.csv" )