Kaggle competition: State Farm Distracted Driver Detection
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[:, [3,1]]
res_boxes[:, [1,3]] = boxes[:, [0,2]]
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 )<concatenate>
! nvidia-smi
tta_transforms = []
for tta_combination in product([TTAHorizontalFlip() , None],
[TTAVerticalFlip() , None],
[TTARotate90() , None]):
tta_transforms.append(TTACompose([tta_transform for tta_transform in tta_combination if tta_transform]))<categorify>
! pip install torch
! pip install torchvision
def make_tta_predictions(images, score_threshold=0.5):
with torch.no_grad() :
images = torch.stack(images ).float().to(DEVICE)
 predictions = []
for tta_transform in tta_transforms:
result = []
outputs = model(tta_transform.batch_augment(images.clone()))
for i, image in enumerate(images):
boxes = outputs[i]['boxes'].data.cpu().numpy()
scores = outputs[i]['scores'].data.cpu().numpy()
indexes = np.where(scores > score_threshold)[0]
boxes = boxes[indexes]
boxes = tta_transform.deaugment_boxes(boxes.copy())
 result.append({
'boxes': boxes,
'scores': scores[indexes],
})
 predictions.append(result)
 return predictions<compute_train_metric>
import pandas as pd
import subprocess
import torch
import torch.optim as optim
from torch import nn
from torch.utils.data import Dataset
from torch.utils.data.sampler import SubsetRandomSampler
import torchvision
from torchvision import transforms
import os
import random
from glob import glob
import cv2
import numpy as np
from tqdm.notebook import tqdm
def run_wbf(predictions, image_index, image_size=1024, iou_thr=0.5, 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<predict_on_test>
EPOCH = 20
BATCH_SIZE = 16
PATIENCE = 5
DATA_PATH = '.. /input/state-farm-distracted-driver-detection'
results = []
for images, image_ids in test_data_loader:
predictions = make_tta_predictions(images)
 for i, image in enumerate(images):
boxes, scores, labels = run_wbf(predictions, image_index=i)
 boxes = boxes.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 )<prepare_output>
transform = transforms.Compose([
transforms.Resize(( 224, 224)) ,
transforms.ToTensor() ,
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])] )
test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])
 test_df.head()<save_to_csv>
classes = [f'c{i}' for i in range(10)]
seed = 2020
validation_split = 0.2
driver_list = pd.read_csv(f'{DATA_PATH}/driver_imgs_list.csv')
 drivers = np.unique(driver_list['subject'].values)
 split = int(np.floor(validation_split * len(drivers)))
 np.random.seed(seed)
 trn_idx, val_idx = drivers[split:], drivers[:split]
test_df.to_csv('submission.csv', index=False )<load_from_csv>
! ls -ahl driver_split
train = pd.read_csv(".. /input/Kannada-MNIST/train.csv")
 test = pd.read_csv(".. /input/Kannada-MNIST/test.csv")
 submission = pd.read_csv(".. /input/Kannada-MNIST/sample_submission.csv" )<drop_column>
train_dataset = torchvision.datasets.ImageFolder(f'./{split_dir}/train',
transform=transform)
 train_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=BATCH_SIZE,
shuffle=True,
num_workers=2)
 valid_dataset = torchvision.datasets.ImageFolder(f'./{split_dir}/valid',
transform=transform)
 valid_loader = torch.utils.data.DataLoader(valid_dataset,
batch_size=BATCH_SIZE,
num_workers=2 )
X = train.drop(['label'], axis = 1)
 X_valid = test.drop(['id'], axis = 1 )<split>
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
 print(device )
X_train, X_dev, Y_train, Y_dev = train_test_split(X, Y, test_size = 0.2 )<choose_model_class>
model_conv = torchvision.models.resnet50(pretrained=True )
f = 2**2
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(f*16,kernel_size=(3,3),padding="same",activation='relu',
kernel_initializer='he_uniform',
input_shape=(28,28,1)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.Conv2D(f*16,(3,3), padding='same',
activation ='relu',
kernel_regularizer=regularizers.l2(0.01)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.Conv2D(f*16,(5,5), padding='same', activation ='relu',
kernel_regularizer=regularizers.l2(0.01)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(f*32,(3,3), padding='same', activation ='relu',
kernel_regularizer=regularizers.l2(0.01)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.Conv2D(f*32,(3,3), padding='same', activation ='relu',
kernel_regularizer=regularizers.l2(0.01)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.Conv2D(f*32,(5,5), padding='same', activation ='relu',
kernel_regularizer=regularizers.l2(0.01)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Dropout(0.15),
tf.keras.layers.Conv2D(f*64,kernel_size=(3,3),padding="same",activation='relu',
kernel_regularizer=regularizers.l2(0.01)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.Conv2D(f*64,kernel_size=(3,3),padding="same",activation='relu',
kernel_regularizer=regularizers.l2(0.01)) ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Dropout(0.15),
tf.keras.layers.Flatten() ,
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
 ])
 print(model.summary() )<choose_model_class>
num_ftrs = model_conv.fc.in_features
model_conv.fc = nn.Sequential(
 nn.Linear(num_ftrs, num_ftrs),
nn.ReLU() ,
nn.Dropout(0.5),
nn.Linear(num_ftrs, num_ftrs),
nn.ReLU() ,
nn.Dropout(0.5),
nn.Linear(num_ftrs, len(classes)))
 print(f'
model_conv = model_conv.to(device )
initial_learningrate=0.001
model.compile(optimizer=
RMSprop(lr=initial_learningrate),
loss = 'sparse_categorical_crossentropy',
metrics = ['accuracy'] )<choose_model_class>
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model_conv.parameters() , lr=0.0001, weight_decay=1e-6, momentum=0.9)
 softmax = nn.Softmax(dim=1)
 best_valid_score = 999
patience = 0
lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='acc',
patience=300,
verbose=1,
factor=0.5,
min_lr=0.00001 )<normalization>
def train(model_conv, train_loader, optimizer, criterion, trn_cnt):
running_loss = 0.
 running_acc = 0.
 pbar = tqdm(total=trn_cnt)
 cnt = 0
for i, data in enumerate(train_loader, 0):
inputs, labels = data
inputs = inputs.to(device)
 labels = labels.to(device)
 optimizer.zero_grad()
model_conv.train()
outputs = model_conv(inputs)
 probs = softmax(outputs)
 _, preds = probs.max(axis=1)
 running_acc += sum(labels == preds)/(1.* BATCH_SIZE)
 loss = criterion(outputs, labels)
 loss.backward()
optimizer.step()
running_loss += loss.item()
cnt += 1
pbar.update(BATCH_SIZE)
 pbar.close()
return running_loss / cnt, running_acc / cnt
def lr_decay(epoch, initial_learningrate = 0.001):
return initial_learningrate * 0.99 ** epoch<choose_model_class>
def evaluate(model_conv, valid_loader, criterion):
with torch.no_grad() :
model_conv.eval()
valid_loss = 0.0
valid_acc = 0.0
cnt = 0
pbar = tqdm(total=val_cnt)
 for data in valid_loader:
inputs, labels = data
inputs = inputs.to(device)
 labels = labels.to(device)
 outputs = model_conv(inputs)
 probs = softmax(outputs)
 _, preds = probs.max(axis=1)
 valid_acc += sum(labels == preds)/(1.* BATCH_SIZE)
 labels.require_grad = False
loss = criterion(outputs, labels)
 valid_loss += loss
cnt += 1
pbar.update(BATCH_SIZE)
 pbar.close()
return valid_loss / cnt, valid_acc / cnt
train_datagen = ImageDataGenerator(
 rotation_range=10,
width_shift_range=0.25,
height_shift_range=0.25,
shear_range=0.1,
zoom_range=0.25,
horizontal_flip=False)
 valid_datagen = ImageDataGenerator(
 horizontal_flip=False,
rotation_range=15,
width_shift_range=0.25,
height_shift_range=0.25,
shear_range=0.15,
zoom_range=0.25, 
)
 callback = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=5)
 batchsize = 512*4
epoch = 45
history = model.fit_generator(train_datagen.flow(X, Y, batch_size = batchsize),
steps_per_epoch = 100,
epochs = epoch,
callbacks=[callback,
LearningRateScheduler(lr_decay),
lr
],
validation_data=valid_datagen.flow(X_dev, Y_dev),
validation_steps=50,
)<train_model>
for epoch in range(EPOCH):
print(f'
trn_loss, trn_acc = train(model_conv, train_loader, optimizer, criterion, trn_cnt)
 print(f'
valid_loss, valid_acc = evaluate(model_conv, valid_loader, criterion)
 print(f'
if valid_loss < best_valid_score:
best_valid_score = valid_loss
print(f'
torch.save(model_conv, './model.baseline.driver_split')
 patience = 0
patience += 1
if patience == PATIENCE:
break
print('Finished Training' )
<save_to_csv><EOS> 
TEST_SIZE = 79726
BATCH_SIZE = 128
test_ids = [os.path.basename(fl)for fl in glob(f'{DATA_PATH}/imgs/test/img_*.jpg')]
test_ids.sort()
transform = transforms.Compose([
transforms.Resize(( 224, 224)) ,
transforms.ToTensor() ,
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
 test_dataset = torchvision.datasets.ImageFolder(f'{DATA_PATH}/imgs',
transform=transform)
 test_loader = torch.utils.data.DataLoader(test_dataset,
batch_size=BATCH_SIZE,
num_workers=2)
 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
 print(device)
 model_conv = torch.load('model.baseline.driver_split')
 print(f'
model_conv = model_conv.to(device)
 softmax = nn.Softmax(dim=1)
 pbar = tqdm(total=TEST_SIZE)
 end_flag = False
with open('submission.csv', 'w')as out:
out.write('img,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9
')
 for i, data in enumerate(test_loader, 0):
inputs, labels = data
inputs = inputs.to(device)
 labels = labels.to(device)
 with torch.no_grad() :
model_conv.eval()
outputs = model_conv(inputs)
 probs = softmax(outputs)
 for j, prob in enumerate(probs):
if BATCH_SIZE * i + j >= TEST_SIZE:
end_flag = True
break
test_id = test_ids[i * BATCH_SIZE + j]
prob = ','.join([str(round(val, 3)) for val in prob.cpu().detach().numpy() ])
 out.write(f'{test_id},{prob}
')
 pbar.update(BATCH_SIZE)
 if end_flag:
break
pbar.close()
print('Finished Eval' )