Kaggle competition: Digit Recognizer
<SOS> metric: categorizationaccuracy Kaggle data source: digit-recognizer<categorify>
warnings.filterwarnings("ignore" )
def _rebuild_from_type(func, type, args, dict):
ret = func(*args ).as_subclass(type)
 ret.__dict__ = dict
return ret
@patch
def __reduce_ex__(self: TensorBase, proto):
torch.utils.hooks.warn_if_has_hooks(self)
 args =(type(self), self.storage() , self.storage_offset() , tuple(self.size()), self.stride())
 if self.is_quantized: args = args +(self.q_scale() , self.q_zero_point())
 args = args +(self.requires_grad, OrderedDict())
 f = _fa_rebuild_qtensor if self.is_quantized else _fa_rebuild_tensor
return(_rebuild_from_type,(f, type(self), args, self.__dict__))<define_variables>
train = pd.read_csv("input/digit-recognizer/train.csv")
 test = pd.read_csv("input/digit-recognizer/test.csv")
 submisssion = pd.read_csv("input/digit-recognizer/sample_submission.csv" )
DISABLE_WB = False
WB_CONFIG = {
"project": "RFCX Experiment Tracker",
"name": "baseline with n_mels=256, masked bce with TPFP, monitor LWRAP(10+30)",
"notes": "rerun baseline again, without mixup and audio aug, n_mels=256, masked bce loss with TPFP, monitor LWRAP(10+30)",
"job_type": "train",
"tags": ['resnet34', "TPFP", "Masked BCE loss", "imagenet norm"]
}
DATA_DIR = Path('.. /input/rfcx-species-audio-detection')
 MODEL_DIR = Path('.. /input/fastiai-fastaudio-rainforest-starter')
 IS_PSEUDO_LABEL = False
PSEUDO_LABEL_CSV = Path('.. /input/rainforest-model-checkpoints/df_train_pseudo_3s.csv')
 NORMALIZER = Normalizer.IMAGENET_STATS.value
SR = 48000
INTERVAL = 10
RANDOM_INTERVAL = 8
MELSPEC_CONFIG = {
'n_fft': 2048,
'sample_rate': SR,
'n_mels': 256
}
IS_MIN_MAX_RESCALE = False
RESIZE_MEL = None
IS_AUDIO_AUG = False
IS_MIXUP = False
NUM_WORKERS = 0
CHANNEL = Channel.SINGLE.value
LOSS_FUNCTION = LossFunction.MASKED_BCE_WITH_TPFP.value
IS_MULTILABEL = True
MONITOR_METRIC = RecordMetric.LWRAP.value
FOLD_ID = 0
BATCH_SIZE = 128
LR = 5e-2
FREEZE_EPOCH = 10
UNFREEZE_EPOCH = 30
RANDOM_SEED = 144 
<feature_engineering>
X = train.iloc[:,1:]/255.
 y = train.iloc[:,0]
test = test/255 .
train_path = DATA_DIR/ 'train'
test_path = DATA_DIR/ 'test'
train_fns = get_audio_files(train_path)
 df_train_tp = pd.read_csv(DATA_DIR/ 'train_tp.csv')
 df_train_tp['recording_id'] = df_train_tp['recording_id'].map(lambda x: 'train/' + x)
 df_train_tp['species_id'] = df_train_tp['species_id'].astype(str)
 skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=RANDOM_SEED)
 for fold_id,(train_idxs, val_idxs)in enumerate(skf.split(df_train_tp.recording_id.values, df_train_tp.species_id.values)) :
kfold_col = f'fold_{fold_id}'
df_train_tp[kfold_col] = 0
df_train_tp.loc[val_idxs, kfold_col] = 1
target_fold = f'fold_{FOLD_ID}'
if LOSS_FUNCTION == LossFunction.MASKED_BCE_WITH_TPFP.value:
print('Concatenating TPFP when using Masked Loss')
 df_train_fp = pd.read_csv(DATA_DIR/ 'train_fp.csv')
 df_train_fp['recording_id'] = df_train_fp['recording_id'].map(lambda x: 'train/' + x)
 df_train_fp['species_id'] = df_train_fp['species_id'].astype(str)
 for fold_id in range(5):
df_train_fp[f'fold_{fold_id}'] = 0
df_train_tp['label_type'] = 'TP'
df_train_fp['label_type'] = 'FP'
df_train_tp = pd.concat([df_train_tp, df_train_fp] ).reset_index(drop=True)
 print(f'DataFrame size after concat TPFP: {df_train_tp.shape[0]}')
 print(f'
assert DATA_DIR.is_dir()
assert MODEL_DIR.is_dir()<filter>
y = to_categorical(y)
 Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, test_size =0.3,random_state=29 )
SAMPLE_IDX = 1
test_row = df_train_tp.loc[SAMPLE_IDX]
test_row<define_variables>
mean_px = Xtrain.mean().astype(np.float32)
 std_px = Xtrain.std().astype(np.float32)
 def standardize(x):
return(x-mean_px)/std_px
def create_audio_tensor(row, is_truncate=True):
if is_truncate:
t_min, t_max = row.t_min, row.t_max
center =(t_max + t_min)/ 2
start_t = center -(INTERVAL/2.)
_frame_offset = int(max(0, start_t)* SR)
 _num_frames = int(INTERVAL * SR)
 else:
_frame_offset = 0
_num_frames = -1
audio_fn = DATA_DIR.resolve() /f'{row.recording_id}.flac'
audio = AudioTensor.create(audio_fn,
frame_offset=_frame_offset,
num_frames=_num_frames)
 return audio<feature_engineering>
def cnn() :
model = models.Sequential()
model.add(Lambda(standardize,input_shape=(28,28,1)))
 model.add(Convolution2D(32,(3,3), activation = 'relu'))
model.add(BatchNormalization(axis=1))
model.add(Convolution2D(64,(3,3), activation = 'relu'))
model.add(MaxPooling2D())
 model.add(Convolution2D(128,(3,3), activation = 'relu'))
model.add(BatchNormalization(axis=1))
model.add(Convolution2D(128,(2,2), activation = 'relu'))
model.add(MaxPooling2D())
 model.add(Flatten())
 model.add(Dense(256, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy',
metrics=['accuracy'])
 return model
truncated_audio = create_audio_tensor(test_row, is_truncate=True)
 orig_audio = create_audio_tensor(test_row, is_truncate=False)
 assert truncated_audio.shape[1] <= INTERVAL * SR
assert orig_audio.shape[1] == 60 * SR<categorify>
classifier = cnn()
classifier.fit(Xtrain, ytrain, epochs=20,batch_size=1000,validation_data=(Xtest,ytest))
if NORMALIZER == Normalizer.IMAGENET_STATS.value:
batch_tfms = IntToFloatTensor
elif NORMALIZER == Normalizer.SAMPLE_STATS.value:
class SampleNormalize(Transform):
order=99
def encodes(self, o:AudioSpectrogram):
means = o.mean(axis=(1,2,3), keepdim=True)
 stds = o.std(axis=(1,2,3), keepdim=True)
 return(o-means)/stds
batch_tfms = SampleNormalize
else:
raise NotImplementedError
class CustomAudioBlock(TransformBlock):
"A `TransformBlock` for audios"
@delegates(audio_item_tfms)
 def __init__(self, batch_tfms, cache_folder=None, **kwargs):
item_tfms = audio_item_tfms(**kwargs)
 type_tfm = None
return super().__init__(type_tfms=type_tfm,
item_tfms=item_tfms,
batch_tfms=batch_tfms)
 vocab = list(map(str, range(24)))
 if LOSS_FUNCTION == LossFunction.MASKED_BCE_WITH_TPFP.value:
def label_encodes_dict(self, d: dict):
o = d['label']
if not all(elem in self.vocab.o2i.keys() for elem in o):
diff = [elem for elem in o if elem not in self.vocab.o2i.keys() ]
diff_str = "', '".join(diff)
 raise KeyError(f"Labels '{diff_str}' were not included in the training dataset")
 t = TensorMultiCategory([self.vocab.o2i[o_] for o_ in o])
 t.label_type = d['type']
return t
def one_hot_with_metadata(self, o: TensorMultiCategory):
t = TensorMultiCategory(one_hot(o, self.c ).float())
 t.__dict__ = o.__dict__
return t
class NegateFP(Transform):
order = OneHotEncode.order + 1
def encodes(self, o: TensorMultiCategory):
assert getattr(o, 'label_type')
 assert o.label_type in('TP', 'FP')
 if o.label_type == 'FP':
o *= -1
return o
def decodes(self, o: TensorMultiCategory):
assert getattr(o, 'label_type')
 assert o.label_type in('TP', 'FP')
 if o.label_type == 'FP':
o *= -1
return o
def MultiCategoryBlockForMetadata(vocab):
tfm = [MultiCategorize(vocab=vocab), OneHotEncode, NegateFP]
return TransformBlock(type_tfms=tfm)
 MultiCategorize.encodes.add(label_encodes_dict)
 OneHotEncode.encodes.add(one_hot_with_metadata)
 blocks =(
 partial(CustomAudioBlock, batch_tfms=batch_tfms, sample_rate=SR),
partial(MultiCategoryBlockForMetadata, vocab=vocab)
)
 elif IS_MULTILABEL:
blocks =(
 partial(CustomAudioBlock, batch_tfms=batch_tfms, sample_rate=SR),
partial(MultiCategoryBlock, vocab=vocab)
)
 else:
blocks =(
 partial(CustomAudioBlock, batch_tfms=batch_tfms, sample_rate=SR),
partial(CategoryBlock, vocab=vocab)
)
 item_tfms = [ResizeSignal(duration=RANDOM_INTERVAL*1000, pad_mode=AudioPadType.Repeat)]
if IS_AUDIO_AUG:
data_augmentation = [
AddNoise(color=NoiseColor.White, noise_level=0.1),
SignalShifter(max_pct=0.3)
 ]
item_tfms += data_augmentation
db_batch_tfms = []
db_batch_tfms += [
AudioToSpec.from_cfg(
 AudioConfig.BasicMelSpectrogram(**MELSPEC_CONFIG)
)
 ]
if IS_MIN_MAX_RESCALE:
class MinMaxRescale(Transform):
def encodes(self, o: AudioSpectrogram):
BS, C, W, H = o.shape
_min = o.reshape(BS, C, W*H ).min(axis=2, keepdim=True)[0][:,:,:,None]
_max = o.reshape(BS, C, W*H ).max(axis=2, keepdim=True)[0][:,:,:,None]
return(o - _min)/ _max
db_batch_tfms += [MinMaxRescale() ]
if RESIZE_MEL is not None:
assert isinstance(RESIZE_MEL, tuple)
 resize_tfms = TfmResizeGPU(size=RESIZE_MEL)
 db_batch_tfms += [resize_tfms]
if CHANNEL == Channel.THREE.value:
class SpectrogramStacker(Transform):
def encodes(self, o: AudioSpectrogram):
return o.expand(-1, 3, -1, -1)
 def decodes(self, o: AudioSpectrogram):
return o[:, :1, :, :]
db_batch_tfms += [SpectrogramStacker() ]
if IS_PSEUDO_LABEL:
df_pseudo = pd.read_csv(PSEUDO_LABEL_CSV)
 df_pseudo.recording_id = df_pseudo.recording_id.apply(lambda _id: f'train/{_id}')
 for _idx in range(5):
df_pseudo[f'fold_{_idx}'] = None
df_train_tp = pd.concat([df_train_tp, df_pseudo])
 df_train_tp = df_train_tp.reset_index(drop=True)
 df_train_tp['species_id'] = df_train_tp['species_id'].astype(str)
 val_idxs = df_train_tp[df_train_tp[target_fold] == 1].index.tolist()
splitter=IndexSplitter(val_idxs)
 if LOSS_FUNCTION == LossFunction.MASKED_BCE_WITH_TPFP.value:
def label_to_list_v2(row):

 y_reader = ColReader('species_id')
 label = y_reader(row)
 try:
label_type = row.label_type
except:
label_type = 'TP'
return {'label': [label], 'type': label_type}
y_getter = label_to_list_v2
else:
y_reader = ColReader('species_id')
 def label_to_list(row):
label = y_reader(row)
 return [label]
y_getter = label_to_list if IS_MULTILABEL else y_reader
datablock = DataBlock(
 blocks=blocks,
item_tfms=item_tfms,
batch_tfms=db_batch_tfms,
get_x=create_audio_tensor,
get_y=y_getter,
splitter=splitter
)<define_variables>
prediction = classifier.predict(test)
 predictions = np.argmax(prediction, axis=1 )
<categorify><EOS> 
submissions=pd.DataFrame({"ImageId": list(range(1,len(predictions)+1)) ,
"Label": predictions})
 submissions.to_csv("working/simple_cnn_kaggle.csv", index=False, header=True)
 submissions.shape