Kaggle competition: Global Wheat Detection
<SOS> metric: custom metric Kaggle data source: global-wheat-detection<compute_train_metric>
InteractiveShell.ast_node_interactivity = "all"
%matplotlib inline
fpr, tpr, thresholds = roc_curve(y_val.numpy() , preds_val.numpy() [:,1], pos_label=1)
 pred_score = auc(fpr, tpr)
 print(f'ROC area is {pred_score}' )<predict_on_test>
image_folder_path = "/kaggle/input/global-wheat-detection/train/"
chosen_image = cv2.imread(os.path.join(image_folder_path, "1ee6b9669.jpg")) [:,:,::-1]
plt.figure(figsize =(20,10))
plt.imshow(chosen_image )
preds_test,y_test = learner.TTA(ds_type=DatasetType.Test)
<load_from_csv>
class InsectAugmentation(ImageOnlyTransform):

 def __init__(self, insects=2, dark_insect=False, always_apply=False, p=0.5):
super().__init__(always_apply, p)
 self.insects = insects
self.dark_insect = dark_insect
self.insects_folder = "/kaggle/input/bee-augmentation/"
def apply(self, image, **kwargs):

 n_insects = random.randint(1, self.insects)
 if not n_insects:
return image
height, width, _ = image.shape
insects_images = [im for im in os.listdir(self.insects_folder)if 'png' in im]
for _ in range(n_insects):
insect = cv2.cvtColor(cv2.imread(os.path.join(self.insects_folder, random.choice(insects_images))), cv2.COLOR_BGR2RGB)
 insect = cv2.flip(insect, random.choice([-1, 0, 1]))
insect = cv2.rotate(insect, random.choice([0, 1, 2]))
h_height, h_width, _ = insect.shape
roi_ho = random.randint(0, image.shape[0] - insect.shape[0])
 roi_wo = random.randint(0, image.shape[1] - insect.shape[1])
 roi = image[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width]
img2gray = cv2.cvtColor(insect, cv2.COLOR_BGR2GRAY)
 ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
 mask_inv = cv2.bitwise_not(mask)
 img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
 if self.dark_insect:
img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
 insect_fg = cv2.bitwise_and(img_bg, img_bg, mask=mask)
 else:
insect_fg = cv2.bitwise_and(insect, insect, mask=mask)
 dst = cv2.add(img_bg, insect_fg, dtype=cv2.CV_64F)
 image[roi_ho:roi_ho + h_height, roi_wo:roi_wo + h_width] = dst
return image
sub=pd.read_csv(f'{path}/sample_submission.csv' ).set_index('id')
 sub.head()<data_type_conversions>
img = InsectAugmentation(insects=2, always_apply=True )(image=chosen_image)['image']
plt.figure(figsize =(20,10))
plt.imshow(img )
names=np.vectorize(lambda img_name: str(img_name ).split('/')[-1][:-4])
 file_names= names(data.test_ds.items ).astype(str )<save_to_csv>
chosen_image = cv2.imread(os.path.join(image_folder_path, "1ee6b9669.jpg")) [:,:,::-1]
img = InsectAugmentation(insects=2, dark_insect=True, always_apply=True )(image=chosen_image)['image']
plt.figure(figsize =(20,10))
plt.imshow(img )
sub.loc[file_names,'label']=preds_test.numpy() [:,1]
sub.to_csv(f'submission_{pred_score}.csv' )<set_options>
!pip install --no-deps '.. /input/timm-0130/timm-0.1.30-py3-none-any.whl' > /dev/null
!pip install --no-deps '.. /input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl' > /dev/null
%matplotlib inline<import_modules>
def get_valid_transforms() :
return A.Compose([
A.Resize(height=1024, width=1024, p=1.0),
ToTensorV2(p=1.0),
], p=1.0 )
!pip install livelossplot 
<define_variables>
DATA_ROOT_PATH = '.. /input/global-wheat-detection/test'
class DatasetRetriever(Dataset):
def __init__(self, image_ids, transforms=None):
super().__init__()
self.image_ids = image_ids
self.transforms = transforms
def __getitem__(self, index: int):
image_id = self.image_ids[index]
image = cv2.imread(f'{DATA_ROOT_PATH}/{image_id}.jpg', cv2.IMREAD_COLOR)
 image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB ).astype(np.float32)
 image /= 255.0
if self.transforms:
sample = {'image': image}
sample = self.transforms(**sample)
 image = sample['image']
return image, image_id
def __len__(self)-> int:
return self.image_ids.shape[0]
TRAINING_LOGS_FILE = "training_logs.csv"
MODEL_SUMMARY_FILE = "model_summary.txt"
MODEL_FILE = "histopathologic_cancer_detector.h5"
TRAINING_PLOT_FILE = "training.png"
VALIDATION_PLOT_FILE = "validation.png"
ROC_PLOT_FILE = "roc.png"
KAGGLE_SUBMISSION_FILE = "kaggle_submission.csv"
INPUT_DIR = '.. /input/'<define_variables>
dataset = DatasetRetriever(
 image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{DATA_ROOT_PATH}/*.jpg')]),
transforms=get_valid_transforms() 
)
 def collate_fn(batch):
return tuple(zip(*batch))
data_loader = DataLoader(
 dataset,
batch_size=4,
shuffle=False,
num_workers=2,
drop_last=False,
collate_fn=collate_fn
)
SAMPLE_COUNT = 85000
TRAINING_RATIO = 0.9
IMAGE_SIZE = 96
EPOCHS = 12
BATCH_SIZE = 216
VERBOSITY = 1
TESTING_BATCH_SIZE = 5000<feature_engineering>
def get_net(best_weight=None, checkpoint_path=None, validation=False, test=False):
config = get_efficientdet_config('tf_efficientdet_d7')
 net = EfficientDet(config, pretrained_backbone=False)
 config.num_classes = 1
config.image_size = 1024
net.class_net = HeadNet(config, num_outputs=config.num_classes, norm_kwargs=dict(eps=.001, momentum=.01))
if checkpoint_path != None:
checkpoint = torch.load(checkpoint_path)
 net.load_state_dict(checkpoint['model_state_dict'])
 del checkpoint
gc.collect()
elif best_weight != None:
net.load_state_dict(best_weight)
 gc.collect()
else:
raise RuntimeError()
if not test:
net = DetBenchTrain(net, config)
 else:
net = DetBenchPredict(net, config)
 if validation:
net.eval() ;
elif not test:
net.train()
return net.cuda()
net = get_net(None, ".. /input/wheatfold4/best-checkpoint-fold4-0.40127.bin", test = True )
training_dir = INPUT_DIR + 'train/'
data_frame = pd.DataFrame({'path': glob(os.path.join(training_dir,'*.tif')) })
 data_frame['id'] = data_frame.path.map(lambda x: x.split('/')[3].split('.')[0])
 labels = pd.read_csv(INPUT_DIR + 'train_labels.csv')
 data_frame = data_frame.merge(labels, on = 'id')
 negatives = data_frame[data_frame.label == 0].sample(SAMPLE_COUNT)
 positives = data_frame[data_frame.label == 1].sample(SAMPLE_COUNT)
 data_frame = pd.concat([negatives, positives] ).reset_index()
data_frame = data_frame[['path', 'id', 'label']]
data_frame['image'] = data_frame['path'].map(imread)
 training_path = '.. /training'
validation_path = '.. /validation'
for folder in [training_path, validation_path]:
for subfolder in ['0', '1']:
path = os.path.join(folder, subfolder)
 os.makedirs(path, exist_ok=True)
 training, validation = train_test_split(data_frame, train_size=TRAINING_RATIO, stratify=data_frame['label'])
 data_frame.set_index('id', inplace=True)
 for images_and_path in [(training, training_path),(validation, validation_path)]:
images = images_and_path[0]
path = images_and_path[1]
for image in images['id'].values:
file_name = image + '.tif'
label = str(data_frame.loc[image,'label'])
 destination = os.path.join(path, label, file_name)
 if not os.path.exists(destination):
source = os.path.join(INPUT_DIR + 'train', file_name)
 shutil.copyfile(source, destination )<train_model>
class BaseWheatTTA:

 image_size = 1024
def augment(self, image):
raise NotImplementedError
def batch_augment(self, images):
raise NotImplementedError
def deaugment_boxes(self, boxes):
raise NotImplementedError
class TTAHorizontalFlip(BaseWheatTTA):

 def augment(self, image):
return image.flip(1)
 def batch_augment(self, images):
return images.flip(2)
 def deaugment_boxes(self, boxes):
boxes[:, [1,3]] = self.image_size - boxes[:, [3,1]]
return boxes
class TTAVerticalFlip(BaseWheatTTA):

 def augment(self, image):
return image.flip(2)
 def batch_augment(self, images):
return images.flip(3)
 def deaugment_boxes(self, boxes):
boxes[:, [0,2]] = self.image_size - boxes[:, [2,0]]
return boxes
class TTARotate90(BaseWheatTTA):

 def augment(self, image):
return torch.rot90(image, 1,(1, 2))
def batch_augment(self, images):
return torch.rot90(images, 1,(2, 3))
def deaugment_boxes(self, boxes):
res_boxes = boxes.copy()
res_boxes[:, [0,2]] = self.image_size - boxes[:, [1,3]]
res_boxes[:, [1,3]] = boxes[:, [2,0]]
return res_boxes
class TTARotate180(BaseWheatTTA):

 def augment(self, image):
return torch.rot90(image, 2,(1, 2))
def batch_augment(self, images):
return torch.rot90(images, 2,(2, 3))
def deaugment_boxes(self, boxes):
boxes[:, [0,1,2,3]] = self.image_size - boxes[:, [2,3,0,1]]
return boxes
class TTARotate270(BaseWheatTTA):

 def augment(self, image):
return torch.rot90(image, 3,(1, 2))
def batch_augment(self, images):
return torch.rot90(images, 3,(2, 3))
def deaugment_boxes(self, boxes):
res_boxes = boxes.copy()
res_boxes[:, [0,2]] = boxes[:, [1,3]]
res_boxes[:, [1,3]] = self.image_size - boxes[:, [2,0]]
return res_boxes
class TTACompose(BaseWheatTTA):

 def __init__(self, transforms):
self.transforms = transforms
def augment(self, image):
for transform in self.transforms:
image = transform.augment(image)
 return image
def batch_augment(self, images):
for transform in self.transforms:
images = transform.batch_augment(images)
 return images
def prepare_boxes(self, boxes):
result_boxes = boxes.copy()
result_boxes[:,0] = np.min(boxes[:, [0,2]], axis=1)
 result_boxes[:,2] = np.max(boxes[:, [0,2]], axis=1)
 result_boxes[:,1] = np.min(boxes[:, [1,3]], axis=1)
 result_boxes[:,3] = np.max(boxes[:, [1,3]], axis=1)
 return result_boxes
def deaugment_boxes(self, boxes):
for transform in self.transforms[::-1]:
boxes = transform.deaugment_boxes(boxes)
 return self.prepare_boxes(boxes )
training_data_generator = ImageDataGenerator(rescale=1./255,
horizontal_flip=True,
vertical_flip=True,
rotation_range=90,
zoom_range=0.2,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.05,
channel_shift_range=0.1 )<train_model>
def process_det(index, det, score_threshold=0.33):
boxes = det[index].detach().cpu().numpy() [:,:4]
scores = det[index].detach().cpu().numpy() [:,4]
boxes[:, 2] = boxes[:, 2] + boxes[:, 0]
boxes[:, 3] = boxes[:, 3] + boxes[:, 1]
boxes =(boxes ).clip(min=0, max=511 ).astype(int)
 indexes = np.where(scores>score_threshold)
 boxes = boxes[indexes]
scores = scores[indexes]
return boxes, scores
training_generator = training_data_generator.flow_from_directory(training_path,
target_size=(IMAGE_SIZE,IMAGE_SIZE),
batch_size=BATCH_SIZE,
class_mode='binary')
 validation_generator = ImageDataGenerator(rescale=1./255 ).flow_from_directory(validation_path,
target_size=(IMAGE_SIZE,IMAGE_SIZE),
batch_size=BATCH_SIZE,
class_mode='binary' )<choose_model_class>
IMAGE_SIZE = 1024
input_shape =(IMAGE_SIZE, IMAGE_SIZE, 3)
 inputs = Input(input_shape)
 xception = Xception(include_top=False, input_shape=input_shape)
 nas_net = NASNetMobile(include_top=False, input_shape=input_shape)
 outputs = Concatenate(axis=-1 )([GlobalAveragePooling2D()(xception(inputs)) ,
GlobalAveragePooling2D()(nas_net(inputs)) ])
 outputs = Dropout(0.5 )(outputs)
 outputs = Dense(1, activation='sigmoid' )(outputs)
 model = Model(inputs, outputs)
 model.compile(optimizer=Adam(lr=0.0001, decay=0.00001),
loss='binary_crossentropy',
metrics=['accuracy'])
 model.summary()
SVG(model_to_dot(model ).create(prog='dot', format='svg'))
plot_model(model, to_file='model_plot.png', show_shapes=True, show_layer_names=True, expand_nested=True )<train_model>
tta_transforms = []
for tta_combination in product([TTAHorizontalFlip() , None],
[TTAVerticalFlip() , None],
[TTARotate90() , TTARotate180() , TTARotate270() , None]):
tta_transforms.append(TTACompose([tta_transform for tta_transform in tta_combination if tta_transform]))
history = model.fit_generator(training_generator,
steps_per_epoch=len(training_generator),
validation_data=validation_generator,
validation_steps=len(validation_generator),
epochs=EPOCHS,
verbose=VERBOSITY,
callbacks=[PlotLossesKeras() ,
ModelCheckpoint(MODEL_FILE,
monitor='val_acc',
verbose=VERBOSITY,
save_best_only=True,
mode='max'),
CSVLogger(TRAINING_LOGS_FILE,
append=False,
separator=';')])
 model.load_weights(MODEL_FILE )<prepare_output>
def make_tta_predictions(images, score_threshold=0.33):
with torch.no_grad() :
images = torch.stack(images ).float().cuda()
predictions = []
for tta_transform in tta_transforms:
result = []
det = net(tta_transform.batch_augment(images.clone()),
torch.tensor([1]*images.shape[0] ).float().cuda() ,
torch.tensor([[IMAGE_SIZE,IMAGE_SIZE]]*images.shape[0] ).float().cuda())
 for i in range(images.shape[0]):
boxes = det[i].detach().cpu().numpy() [:,:4]
scores = det[i].detach().cpu().numpy() [:,4]
indexes = np.where(scores > score_threshold)[0]
boxes = boxes[indexes]
boxes[:, 2] = boxes[:, 2] + boxes[:, 0]
boxes[:, 3] = boxes[:, 3] + boxes[:, 1]
boxes = tta_transform.deaugment_boxes(boxes.copy())
 result.append({
'boxes': boxes,
'scores': scores[indexes],
})
 predictions.append(result)
 return predictions
def run_wbf(predictions, image_index, image_size=1024, iou_thr=0.43, skip_box_thr=0.43, weights=None):
boxes = [(prediction[image_index]['boxes']/(image_size-1)).tolist() for prediction in predictions]
scores = [prediction[image_index]['scores'].tolist() for prediction in predictions]
labels = [np.ones(prediction[image_index]['scores'].shape[0] ).astype(int ).tolist() for prediction in predictions]
boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=iou_thr, skip_box_thr=skip_box_thr)
 boxes = boxes*(image_size-1)
 return boxes, scores, labels
testing_files = glob(os.path.join(INPUT_DIR+'test/','*.tif'))
submission = pd.DataFrame()
for index in range(0, len(testing_files), TESTING_BATCH_SIZE):
data_frame = pd.DataFrame({'path': testing_files[index:index+TESTING_BATCH_SIZE]})
 data_frame['id'] = data_frame.path.map(lambda x: x.split('/')[3].split(".")[0])
 data_frame['image'] = data_frame['path'].map(imread)
 images = np.stack(data_frame.image, axis=0)
 predicted_labels = [model.predict(np.expand_dims(image/255.0, axis=0)) [0][0] for image in images]
predictions = np.array(predicted_labels)
 data_frame['label'] = predictions
submission = pd.concat([submission, data_frame[["id", "label"]]])
 submission.to_csv(KAGGLE_SUBMISSION_FILE, index=False, header=True )<import_modules>
def format_prediction_string(boxes, scores):
pred_strings = []
for j in zip(scores, boxes):
pred_strings.append("{0:.4f} {1} {2} {3} {4}".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))
return " ".join(pred_strings )
from fastai.conv_learner import *
from fastai.dataset import *
import pandas as pd
import numpy as np
import os
from sklearn.model_selection import train_test_split<define_variables>
results = []
for images, image_ids in data_loader:
predictions = make_tta_predictions(images)
 for i, image in enumerate(images):
boxes, scores, labels = run_wbf(predictions, image_index=i)
 boxes =(boxes*2 ).round().astype(np.int32 ).clip(min=0, max=1023)
 image_id = image_ids[i]
boxes[:, 2] = boxes[:, 2] - boxes[:, 0]
boxes[:, 3] = boxes[:, 3] - boxes[:, 1]
result = {
'image_id': image_id,
'PredictionString': format_prediction_string(boxes, scores)
 }
results.append(result )
MODEL_PATH = 'Dn121_v1'
TRAIN = '.. /input/train/'
TEST = '.. /input/test/'
LABELS = '.. /input/train_labels.csv'
SAMPLE_SUB = '.. /input/sample_submission.csv'
ORG_SIZE=96
BATCH_SIZE = 64<choose_model_class>
test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])
 test_df.to_csv('submission.csv', index=False)
 test_df.head()