Kaggle competition: Quick, Draw! Doodle Recognition Challenge
<SOS> metric: MAP@{K} Kaggle data source: quick,-draw!-doodle-recognition-challenge<categorify>
%matplotlib inline
InteractiveShell.ast_node_interactivity = "all"
plt.rcParams['figure.figsize'] = [16, 10]
plt.rcParams['font.size'] = 14
start = dt.datetime.now()
def read_tfrecord(example, labeled):
tfrecord_format = {
"image": tf.io.FixedLenFeature([], tf.string),
"target": tf.io.FixedLenFeature([], tf.int64)
 } if labeled else {
"image": tf.io.FixedLenFeature([], tf.string),
"image_name": tf.io.FixedLenFeature([], tf.string)
 }
example = tf.io.parse_single_example(example, tfrecord_format)
 image = decode_image(example['image'])
 if labeled:
label = tf.cast(example['target'], tf.int32)
 return image, label
idnum = example['image_name']
return image, idnum<split>
DP_DIR = '.. /input/shuffle-csvs/'
INPUT_DIR = '.. /input/quickdraw-doodle-recognition/'
BASE_SIZE = 256
NCSVS = 100
NCATS = 340
np.random.seed(seed=1987)
 tf.set_random_seed(seed=1987)
 def f2cat(filename: str)-> str:
return filename.split('.')[0]
def list_all_categories() :
files = os.listdir(os.path.join(INPUT_DIR, 'train_simplified'))
return sorted([f2cat(f)for f in files], key=str.lower )
def read_unlabeled_tfrecord(example, return_image_name):
tfrec_format = {
'image' : tf.io.FixedLenFeature([], tf.string),
'image_name' : tf.io.FixedLenFeature([], tf.string),
}
example = tf.io.parse_single_example(example, tfrec_format)
 return example['image'], example['image_name'] if return_image_name else '0'<create_dataframe>
def apk(actual, predicted, k=3):

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

 return np.mean([apk(a, p, k)for a, p in zip(actual, predicted)])
 def preds2catids(predictions):
return pd.DataFrame(np.argsort(-predictions, axis=1)[:, :3], columns=['a', 'b', 'c'])
 def top_3_accuracy(y_true, y_pred):
return top_k_categorical_accuracy(y_true, y_pred, k=3 )
def load_dataset(filenames, labeled=True, ordered=False):
ignore_order = tf.data.Options()
if not ordered:
ignore_order.experimental_deterministic = False
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)
 dataset = dataset.with_options(ignore_order)
 dataset = dataset.map(partial(read_tfrecord, labeled=labeled), num_parallel_calls=AUTOTUNE)
 return dataset<define_variables>
STEPS = 800
EPOCHS = 30
size = 128
batchsize = 340
TRAINING_FILENAMES = tf.io.gfile.glob('.. /input/cassava-leaf-disease-classification/train_tfrecords/' + '*train*.tfrec')
 TEST_FILENAMES = tf.io.gfile.glob('.. /input/cassava-leaf-disease-classification/test_tfrecords/' + 'ld_test*.tfrec' )<define_variables>
base_model = MobileNet(input_shape=(size, size,3), alpha=1., weights="imagenet", include_top = False)
 inp = base_model.input
x = base_model.output
x = GlobalAveragePooling2D()(x)
 x = Dense(NCATS, activation='softmax' )(x)
 model = Model(inp, x)
 base_model = Sequential(model.layers[:-2] )
def count_data_items(filenames):
n = [int(re.compile(r"-([0-9]*)\." ).search(filename ).group(1)) for filename in filenames]
return np.sum(n)
 NUM_TRAINING_IMAGES = int(count_data_items(TRAINING_FILENAMES)*(FOLDS-1.) /FOLDS)
 NUM_VALIDATION_IMAGES = int(count_data_items(TRAINING_FILENAMES)*(1./FOLDS))
NUM_TEST_IMAGES = count_data_items(TEST_FILENAMES)
 STEPS_PER_EPOCH = NUM_TRAINING_IMAGES // BATCH_SIZE
print('Dataset: {} training images, {} validation images, {} unlabeled test images'.format(NUM_TRAINING_IMAGES, NUM_VALIDATION_IMAGES, NUM_TEST_IMAGES))<categorify>
inp = Input(shape =(70,3))
x = BatchNormalization()(inp)
 x = Conv1D(256,(5,), activation = "relu" )(x)
 x = Dropout(0.2 )(x)
 x = Conv1D(256,(5,), activation = 'relu' )(x)
 x = Dropout(0.2 )(x)
 x = Conv1D(256,(3,), activation = 'relu' )(x)
 x = Dropout(0.2 )(x)
 x = Bidirectional(LSTM(128, return_sequences = True))(x)
 x = Dropout(0.2 )(x)
 x = Bidirectional(LSTM(128, return_sequences = False))(x)
 x = Dropout(0.2 )(x)
 x = Dense(512, activation = 'relu' )(x)
 x = Dense(NCATS, activation='softmax' )(x)
 stroke_read_model = Model(inp,x)
 stroke_read_model.compile(optimizer = 'adam',
loss = 'categorical_crossentropy',
metrics = ['categorical_accuracy', top_3_accuracy])
 stroke_read_model = Sequential(stroke_read_model.layers[:-1])
 stroke_read_model.summary()
def data_augment(image, label):
image = tf.image.random_flip_left_right(image)
 return image, label<create_dataframe>
inp = base_model.input
y = base_model.output
y = GlobalAveragePooling2D()(y)
 inp2 = Input(shape =(70, 3))
z = stroke_read_model(inp2)
 x = concatenate([y, z])
 x = Dropout(0.3 )(x)
 x = Dense(NCATS, activation='softmax' )(x)
 model = Model([inp, inp2], x)
 model.compile(optimizer=Adam(lr=0.001), loss='categorical_crossentropy',
metrics=[categorical_crossentropy, categorical_accuracy, top_3_accuracy] )
def get_test_dataset(ordered=False):
dataset = load_dataset(TEST_FILENAMES, labeled=False, ordered=ordered)
 dataset = dataset.batch(BATCH_SIZE)
 dataset = dataset.prefetch(AUTOTUNE)
 return dataset<groupby>
def _stack_it(raw_strokes):

 stroke_vec = literal_eval(raw_strokes)
 in_strokes = [(xi,yi,i)
 for i,(x,y)in enumerate(stroke_vec)
 for xi,yi in zip(x,y)]
c_strokes = np.stack(in_strokes)
 c_strokes[:,2] = [1]+np.diff(c_strokes[:,2] ).tolist()
c_strokes[:,2] += 1
return pad_sequences(c_strokes.swapaxes(0, 1),
maxlen=70,
padding='post' ).swapaxes(0, 1)
def count_data_items(filenames):
n = [int(re.compile(r"-([0-9]*)\." ).search(filename ).group(1)) for filename in filenames]
return np.sum(n )<categorify>
train_datagen = image_generator_xd(size=size, batchsize=batchsize, ks=range(NCSVS - 1))
val_datagen = image_generator_xd(size=size, batchsize=batchsize, ks=range(NCSVS - 1, NCSVS))
def onehot(image,label):
CLASSES = 5
return image,tf.one_hot(label,CLASSES )<categorify>
callbacks = [
ReduceLROnPlateau(monitor='val_categorical_accuracy', factor=0.5, patience=3,
min_delta=0.005, mode='max', cooldown=3, verbose=1),
ModelCheckpoint("mobilenet_lstm.model",monitor='val_top_3_accuracy',
mode = 'max', save_best_only=True, verbose=1)
 ]
hists = []
hist = model.fit_generator(
 train_datagen, steps_per_epoch=STEPS, epochs=EPOCHS, verbose=1,
validation_data=val_datagen, validation_steps = 100,
callbacks = callbacks 
)
 hists.append(hist )
def get_validation_dataset(dataset, do_onehot=True):
dataset = dataset.batch(BATCH_SIZE)
 if do_onehot: dataset = dataset.map(onehot, num_parallel_calls=AUTOTUNE)
 dataset = dataset.cache()
dataset = dataset.prefetch(AUTOTUNE)
 return dataset<create_dataframe>
df = pd.read_csv(os.path.join(DP_DIR, 'train_k{}.csv.gz'.format(NCSVS)) , nrows=34000)
 for i in range(10):
valid_df = df.loc[i*3400:(i+1)*3400,:].copy()
x_valid, x2 = df_to_image_array_xd(valid_df, size)
 y_valid = keras.utils.to_categorical(valid_df.y, num_classes=NCATS)
 print(x_valid.shape, y_valid.shape)
 print('Validation array memory {:.2f} GB'.format(x_valid.nbytes / 1024.**3))
valid_predictions = model.predict([x_valid, x2], batch_size=128, verbose=1)
 map3 = mapk(valid_df[['y']].values, preds2catids(valid_predictions ).values)
 print('Map3: {:.3f}'.format(map3))
def get_dataset(files, augment = False, shuffle = False, repeat = False,
labeled=True, return_image_names=False, batch_size=16, dim=512):
ds = tf.data.TFRecordDataset(files, num_parallel_reads=AUTOTUNE)
 ds = ds.cache()
if repeat:
ds = ds.repeat()
if shuffle:
ds = ds.shuffle(1024*8)
 opt = tf.data.Options()
opt.experimental_deterministic = False
ds = ds.with_options(opt)
 if labeled:
ds = ds.map(read_labeled_tfrecord, num_parallel_calls=AUTOTUNE)
 else:
ds = ds.map(lambda example: read_unlabeled_tfrecord(example, return_image_names),
num_parallel_calls=AUTOTUNE)
 ds = ds.map(lambda img, imgname_or_label:(prepare_image(img, augment=augment, dim=dim),
imgname_or_label),
num_parallel_calls=AUTOTUNE)
 ds = ds.batch(batch_size * REPLICAS)
 ds = ds.prefetch(AUTOTUNE)
 return ds<define_variables>
test = pd.read_csv(os.path.join(INPUT_DIR, 'test_simplified.csv'))
for i in range(10):
end = min(( i+1)*11220, 112199)
 subtest= test.iloc[i*11220:end].copy().reset_index(drop=True)
 x_test = df_to_image_array_xd(subtest, size)
 test_predictions = model.predict(x_test, batch_size=128, verbose=1)
 top3 = preds2catids(test_predictions)
 cats = list_all_categories()
id2cat = {k: cat.replace(' ', '_')for k, cat in enumerate(cats)}
top3cats = top3.replace(id2cat)
 subtest['word'] = top3cats['a'] + ' ' + top3cats['b'] + ' ' + top3cats['c']
subtest.head()
if i ==0:
submission = subtest[['key_id', 'word']]
else:
submission = submission.append(subtest[['key_id', 'word']], ignore_index=True)
class DataGenerator(Sequence):
def __init__(self, path, list_IDs, labels, batch_size, img_size, img_channel):
self.path = path
self.list_IDs = list_IDs
self.labels = labels
self.batch_size = batch_size
self.img_size = img_size
self.img_channel = img_channel
self.indexes = np.arange(len(self.list_IDs))
def __len__(self):
return int(np.floor(len(self.list_IDs)/self.batch_size))
def __getitem__(self, index):
indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]
list_IDs_temp = [self.list_IDs[k] for k in indexes]
X, y = self.__data_generation(list_IDs_temp)
 return X, y
def __data_generation(self, list_IDs_temp):
X = np.empty(( self.batch_size, self.img_size, self.img_size, self.img_channel))
y = np.empty(( self.batch_size, 5), dtype=int)
 for i, ID in enumerate(list_IDs_temp):
data_file = cv2.imread(self.path+ID)
 img = cv2.resize(data_file,(self.img_size, self.img_size))
X[i, ] = img
y[i, ] = self.labels[i]
X = X.astype('float32')
 X /= 255.
 return X, y<prepare_x_and_y>
submission.to_csv('lstm_mobilenet.csv', index=False)
 submission.head()
submission.shape
<define_variables><EOS> 
end = dt.datetime.now()
print('Latest run {}.
 Total time {}s'.format(end,(end - start ).seconds))