Kaggle competition: Quick, Draw! Doodle Recognition Challenge
train_df["coverage"] = train_df.masks.map(np.sum)/ pow(img_size_ori, 2)
 def cov_to_class(val):
for i in range(0, 11):
if val * 10 <= i :
return i
train_df["coverage_class"] = train_df.coverage.map(cov_to_class)
<split>
%matplotlib inline
device = torch.device('cuda' if torch.cuda.is_available() else "cpu" )
ids_train, ids_valid, x_train, x_valid, y_train, y_valid, cov_train, cov_test, depth_train, depth_test = train_test_split(
 train_df.index.values,
np.array(train_df.images.tolist() ).reshape(-1, img_size_target, img_size_target, 1),
np.array(train_df.masks.tolist() ).reshape(-1, img_size_target, img_size_target, 1),
train_df.coverage.values,
train_df.z.values,
test_size=0.2, stratify=train_df.coverage_class, random_state= 1234 )<define_search_model>
NROWS = 10000
VAL_NROWS = 500
path = '.. /input/train_simplified/'
filenames = glob.glob(os.path.join(path, '*.csv'))
NUM_CLASSES = len(filenames )
ACTIVATION = "relu"
def convolution_block(x, filters, size, strides=(1,1), padding='same', activation=True, bn=True):
x = Conv2D(filters, size, strides=strides, padding=padding )(x)
 if bn == True:
x = BatchNormalization()(x)
 if activation == True:
x = Activation(ACTIVATION )(x)
 return x
def residual_block(blockInput, num_filters=16):
x = BatchNormalization()(blockInput)
 x = Activation(ACTIVATION )(x)
 x = convolution_block(x, num_filters,(3,3))
x = convolution_block(x, num_filters,(3,3), activation=False, bn=False)
 x = Add()([x, blockInput])
 return x 
<choose_model_class>
encode_dict = {}
path = '.. /input/train_simplified/'
filenames = glob.glob(os.path.join(path, '*.csv'))
filenames = sorted(filenames)
 print(len(filenames))
for ix, filename in enumerate(filenames):
class_name = filename.split('/')[-1].split('.')[0].replace(' ', '_')
 encode_dict[class_name] = ix
decode_dict = {value:key for key, value in encode_dict.items() }
def build_model(input_layer, start_neurons, DropoutRatio = 0.5):
conv1 = Conv2D(start_neurons * 1,(3, 3), activation=None, padding="same" )(input_layer)
 conv1 = residual_block(conv1,start_neurons * 1)
 conv1 = residual_block(conv1,start_neurons * 1)
 conv1 = Activation(ACTIVATION )(conv1)
 pool1 = MaxPooling2D(( 2, 2))(conv1)
 pool1 = Dropout(DropoutRatio/2 )(pool1)
 conv2 = Conv2D(start_neurons * 2,(3, 3), activation=None, padding="same" )(pool1)
 conv2 = residual_block(conv2,start_neurons * 2)
 conv2 = residual_block(conv2,start_neurons * 2)
 conv2 = Activation(ACTIVATION )(conv2)
 pool2 = MaxPooling2D(( 2, 2))(conv2)
 pool2 = Dropout(DropoutRatio )(pool2)
 conv3 = Conv2D(start_neurons * 4,(3, 3), activation=None, padding="same" )(pool2)
 conv3 = residual_block(conv3,start_neurons * 4)
 conv3 = residual_block(conv3,start_neurons * 4)
 conv3 = Activation(ACTIVATION )(conv3)
 pool3 = MaxPooling2D(( 2, 2))(conv3)
 pool3 = Dropout(DropoutRatio )(pool3)
 conv4 = Conv2D(start_neurons * 8,(3, 3), activation=None, padding="same" )(pool3)
 conv4 = residual_block(conv4,start_neurons * 8)
 conv4 = residual_block(conv4,start_neurons * 8)
 conv4 = Activation(ACTIVATION )(conv4)
 pool4 = MaxPooling2D(( 2, 2))(conv4)
 pool4 = Dropout(DropoutRatio )(pool4)
 convm = Conv2D(start_neurons * 16,(3, 3), activation=None, padding="same" )(pool4)
 convm = residual_block(convm,start_neurons * 16)
 convm = residual_block(convm,start_neurons * 16)
 convm = Activation(ACTIVATION )(convm)
 deconv4 = Conv2DTranspose(start_neurons * 8,(3, 3), strides=(2, 2), padding="same" )(convm)
 uconv4 = concatenate([deconv4, conv4])
 uconv4 = Dropout(DropoutRatio )(uconv4)
 uconv4 = Conv2D(start_neurons * 8,(3, 3), activation=None, padding="same" )(uconv4)
 uconv4 = residual_block(uconv4,start_neurons * 8)
 uconv4 = residual_block(uconv4,start_neurons * 8)
 uconv4 = Activation(ACTIVATION )(uconv4)
 deconv3 = Conv2DTranspose(start_neurons * 4,(3, 3), strides=(2, 2), padding="valid" )(uconv4)
 uconv3 = concatenate([deconv3, conv3])
 uconv3 = Dropout(DropoutRatio )(uconv3)
 uconv3 = Conv2D(start_neurons * 4,(3, 3), activation=None, padding="same" )(uconv3)
 uconv3 = residual_block(uconv3,start_neurons * 4)
 uconv3 = residual_block(uconv3,start_neurons * 4)
 uconv3 = Activation(ACTIVATION )(uconv3)
 deconv2 = Conv2DTranspose(start_neurons * 2,(3, 3), strides=(2, 2), padding="same" )(uconv3)
 uconv2 = concatenate([deconv2, conv2])
 uconv2 = Dropout(DropoutRatio )(uconv2)
 uconv2 = Conv2D(start_neurons * 2,(3, 3), activation=None, padding="same" )(uconv2)
 uconv2 = residual_block(uconv2,start_neurons * 2)
 uconv2 = residual_block(uconv2,start_neurons * 2)
 uconv2 = Activation(ACTIVATION )(uconv2)
 deconv1 = Conv2DTranspose(start_neurons * 1,(3, 3), strides=(2, 2), padding="valid" )(uconv2)
 uconv1 = concatenate([deconv1, conv1])
 uconv1 = Dropout(DropoutRatio )(uconv1)
 uconv1 = Conv2D(start_neurons * 1,(3, 3), activation=None, padding="same" )(uconv1)
 uconv1 = residual_block(uconv1,start_neurons * 1)
 uconv1 = residual_block(uconv1,start_neurons * 1)
 uconv1 = Activation(ACTIVATION )(uconv1)
 uconv1 = Dropout(DropoutRatio/2 )(uconv1)
 output_layer = Conv2D(1,(1,1), padding="same", activation="sigmoid" )(uconv1)
 return output_layer<compute_train_metric>
class ClassDataset(Dataset):
def __init__(self, csv_file_path, mode='train', nrows=15000, skiprows=0, size=128):
super().__init__()
self.df = pd.read_csv(csv_file_path, usecols=['drawing'], nrows=nrows, skiprows=0)
 self.mode = mode
self.size = size
if self.mode == 'train':
self.class_name = csv_file_path.split('/')[-1].split('.')[0].replace(' ', '_')
 self.label = encode_dict[self.class_name]
def __len__(self):
return len(self.df)
 def __getitem__(self, index):
raw_strokes = ast.literal_eval(self.df.drawing[index])
 image = draw_cv2(raw_strokes, size=self.size)
 image = image.transpose(2, 0, 1)
 if self.mode == 'train':
return(image/255 ).astype('float32'), self.label
else:
return(image/255 ).astype('float32')
iou_thresholds = np.array([0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95])
 def iou(img_true, img_pred):
i = np.sum(( img_true*img_pred)>0)
 u = np.sum(( img_true + img_pred)>0)
 if u == 0:
return u
return i/u
def iou_metric(imgs_true, imgs_pred):
num_images = len(imgs_true)
 scores = np.zeros(num_images)
 for i in range(num_images):
if imgs_true[i].sum() == imgs_pred[i].sum() == 0:
scores[i] = 1
else:
scores[i] =(iou_thresholds <= iou(imgs_true[i], imgs_pred[i])).mean()
return scores.mean()<concatenate>
%%time
val_dset = ConcatDataset([ClassDataset(filename, nrows=VAL_NROWS, skiprows=0)for filename in filenames])
 dset = ConcatDataset([ClassDataset(filename, nrows=NROWS, skiprows=VAL_NROWS)for filename in filenames] )
x_train = np.append(x_train, [np.fliplr(x)for x in x_train], axis=0)
 y_train = np.append(y_train, [np.fliplr(x)for x in y_train], axis=0)
 print(x_train.shape)
 print(y_valid.shape )<choose_model_class>
%%time
dloader = DataLoader(dset, batch_size=128, shuffle=True, num_workers=2)
 val_dloader = DataLoader(val_dset, batch_size=128, num_workers=2, shuffle=False )
input_layer = Input(( img_size_target, img_size_target, 1))
output_layer = build_model(input_layer, 16,0.5)
 model = Model(input_layer, output_layer)
 model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["acc"] )<train_model>
class Conv(nn.Module):
def __init__(self, in_channel, out_channel, kernel_size=3, stride=1, padding=1):
super().__init__()
self.layers = nn.Sequential(
 nn.Conv2d(in_channel, out_channel, kernel_size=kernel_size, stride=stride, padding=padding, bias=False),
nn.BatchNorm2d(out_channel),
nn.ReLU(inplace=True)
)
 def forward(self, input):
return self.layers(input)
 class Conv_dw_Conv(nn.Module):
def __init__(self, in_channel, out_channel, kernel_size=3, stride=1, padding=1):
super().__init__()
self.layers = nn.Sequential(
 nn.Conv2d(in_channel, in_channel, kernel_size, stride, padding, bias=False, groups=in_channel),
nn.BatchNorm2d(in_channel),
nn.ReLU(inplace=True),
Conv(in_channel, out_channel, kernel_size=1, stride=1, padding=0)
)
 def forward(self, input):
return self.layers(input)
 class MobileNet(nn.Module):
def __init__(self, num_classes):
super().__init__()
self.num_classes = num_classes
self.model = nn.Sequential(
 Conv(3, 32, stride=2),
Conv_dw_Conv(32, 64, kernel_size=3, stride=1),
Conv_dw_Conv(64, 128, kernel_size=3, stride=2),
Conv_dw_Conv(128, 128, kernel_size=3, stride=1),
Conv_dw_Conv(128, 256, kernel_size=3, stride=2),
Conv_dw_Conv(256, 256, kernel_size=3, stride=1),
Conv_dw_Conv(256, 512, kernel_size=3, stride=2),
Conv_dw_Conv(512, 512, kernel_size=3, stride=1),
Conv_dw_Conv(512, 512, kernel_size=3, stride=1),
Conv_dw_Conv(512, 512, kernel_size=3, stride=1),
Conv_dw_Conv(512, 512, kernel_size=3, stride=1),
Conv_dw_Conv(512, 512, kernel_size=3, stride=1),
Conv_dw_Conv(512, 1024, kernel_size=3, stride=2),
Conv_dw_Conv(1024, 1024, kernel_size=3, stride=1)
)
 self.avg_pool = nn.AdaptiveAvgPool2d(1)
 self.fc = nn.Linear(1024, num_classes)
 def forward(self, input):
x = self.model(input)
 x = self.avg_pool(x)
 x = x.view(-1, 1024)
 out = self.fc(x)
 return out
early_stopping = EarlyStopping(monitor='val_acc', mode = 'max',patience=20, verbose=1)
 model_checkpoint = ModelCheckpoint("./unet_best1.model",monitor='val_acc',
mode = 'max', save_best_only=True, verbose=1)
 reduce_lr = ReduceLROnPlateau(monitor='val_acc', mode = 'max',factor=0.5, patience=6, min_lr=0.001, verbose=1)
 epochs = 200
batch_size = 32
history = model.fit(x_train, y_train,
validation_data=[x_valid, y_valid],
epochs=epochs,
batch_size=batch_size,
callbacks=[early_stopping, model_checkpoint, reduce_lr],
verbose=1 )<load_pretrained>
def apk(actual, predicted, k=3):

 if len(predicted)>k:
predicted = predicted[:k]
score = 0.0
for i,p in enumerate(predicted):
if p == actual:
score = 1 /(i+1.0)
 return score
def mapk(actual, predicted, k=3):

 return np.mean([apk(a,p,k)for a,p in zip(actual, predicted)] )
model = load_model("./unet_best1.model" )<predict_on_test>
def validation_score(model, val_data_loader):
model.eval()
sum_score = 0
count = 0
for images, labels in val_data_loader:
images = images.to(device)
 labels = labels.to(device)
 batch_size = images.size(0)
 output = model(images)
 topk = output.detach().topk(3, dim=1)[1]
sum_score += mapk(labels.cpu().numpy() , topk.cpu().numpy())* batch_size
count += batch_size
model.train()
return sum_score / count
def predict_result(model,x_test,img_size_target):
preds_test = model.predict(x_test ).reshape(-1, img_size_target, img_size_target)
 preds_test += np.array([ np.fliplr(a)for a in model.predict(np.array([np.fliplr(x)for x in x_test])).reshape(-1, img_size_target, img_size_target)])
 return preds_test/2.0<predict_on_test>
model = MobileNet(NUM_CLASSES ).to(device)
 criterion = nn.CrossEntropyLoss().to(device)
 optimizer = torch.optim.Adam(model.parameters() , lr=0.002)
 scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[60000, 130000, 160000, 190000], gamma=0.5 )
preds_valid = predict_result(model,x_valid,img_size_target )<define_search_space>
%%time
print("Start training...")
 epochs = 8
print_every = 1000
validate_every = 10000
model.train()
best_val_score = 0
curr_iter = 0
avg_loss = 0
avg_score = 0
for epoch in range(epochs):
del dset
del dloader
dset = ConcatDataset([ClassDataset(filename, nrows=NROWS, skiprows=VAL_NROWS + NROWS * epoch)for filename in filenames])
 dloader = DataLoader(dset, batch_size=128, shuffle=True, num_workers=2)
 for ix,(images, labels)in enumerate(dloader):
images = images.to(device)
 labels = labels.to(device)
 model.zero_grad()
output = model(images)
 loss = criterion(output, labels)
 loss.backward()
optimizer.step()
avg_loss += loss.item()
topk = output.detach().topk(3, dim=1)[1]
avg_score += mapk(labels.cpu().numpy() , topk.cpu().numpy())
 curr_iter += 1
if(curr_iter)% print_every == 0:
print('Epoch {}, Iteration {} - Train Loss: {:.4f}, MAP@3: {:.3f}'.format(epoch + 1, curr_iter, avg_loss/print_every, avg_score/print_every))
avg_loss = 0
avg_score = 0
if curr_iter % validate_every == 0:
val_score = validation_score(model, val_dloader)
 print('Epoch {}, Iteration {}: validation map@3: {}'.format(epoch + 1, curr_iter, val_score))
if val_score > best_val_score:
print('New best validation score: {}, saving model...'.format(val_score))
best_val_score = val_score
torch.save(model.state_dict() , 'model_checkpoint_best_val.ckpt')
def filter_image(img):
if img.sum() < 100:
return np.zeros(img.shape)
 else:
return img
thresholds = np.linspace(0.3, 0.7, 31)
 ious = np.array([iou_metric(y_valid.reshape(( -1, img_size_target, img_size_target)) , [filter_image(img)for img in preds_valid > threshold])for threshold in tqdm_notebook(thresholds)])
<categorify>
test_dset = ClassDataset('.. /input/test_simplified.csv', mode='test', nrows=None)
 test_dloader = DataLoader(test_dset, batch_size=128, shuffle=False, num_workers=0)
 model.eval()
labels = []
for images in tqdm.tqdm(test_dloader):
images = images.to(device)
 output = model(images)
 _, pred = output.topk(3, 1)
 for i in range(len(images)) :
labels.append(' '.join([decode_dict[pred[i][j].item() ]for j in range(3)]))
def rle_encode(im):
pixels = im.flatten(order = 'F')
 pixels = np.concatenate([[0], pixels, [0]])
 runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
runs[1::2] -= runs[::2]
return ' '.join(str(x)for x in runs )<drop_column>
%%time
submission = pd.read_csv('.. /input/test_simplified.csv', index_col='key_id' ,usecols=['key_id'])
 print(len(submission))
submission['word'] = labels
del x_train, x_valid, y_train, y_valid, preds_valid
gc.collect()<predict_on_test>
submission.to_csv('submission_final.csv' )
<compute_test_metric><EOS> 
model.load_state_dict(torch.load('model_checkpoint_best_val.ckpt'))
model.eval()
labels = []
for images in tqdm.tqdm(test_dloader):
images = images.to(device)
 output = model(images)
 _, pred = output.topk(3, 1)
 for i in range(len(images)) :
labels.append(' '.join([decode_dict[pred[i][j].item() ]for j in range(3)]))
print(len(labels))
submission = pd.read_csv('.. /input/test_simplified.csv', index_col='key_id' ,usecols=['key_id'])
 print(len(submission))
submission['word'] = labels
submission.to_csv('submission_best_val.csv' )