Kaggle competition: Rainforest Connection Species Audio Detection
<SOS> metric: WeightedLabelRankingAveragePrecision Kaggle data source: rainforest-connection-species-audio-detection<categorify>
from IPython.display import Image
class EmbeddingHook:
def __init__(self, m):
self.embeddings, self.m = tensor([] ).to(device), m
if len(m._forward_hooks)> 0: self.reset()
self.hook = Hook(m, self.hook_fn, cpu=False)
 def hook_fn(self, m, inp, out):
"Stack and save computed embeddings"
self.embeddings = torch.cat([self.embeddings, out])
 def reset(self):
self.m._forward_hooks = OrderedDict()<define_variables>
Image(".. /input/rcfx-training-logs/history_0.png" )
meta_feat_cols = ['scaled_position']<normalization>
Image(".. /input/rcfx-training-logs/history_1.png" )
def minmax_scaler(o): return(o - min(o)) /(max(o)- min(o))<load_pretrained>
Image(".. /input/rcfx-training-logs/history_2.png" )
def read_dcm_img_v2(dcm, windows=windows):
"Read single slice in RGB"
return [dcm.windowed(*w)for w in windows]<predict_on_test>
Image(".. /input/rcfx-training-logs/history_3.png" )
def predict_study(study_dirname):
study_df = test_df.query(f'StudyInstanceUID == "{study_dirname.stem}"')
 sop_ids = study_df['SOPInstanceUID'].values
study_files = str(testdatapath)+ "/" + study_df['StudyInstanceUID'] + "/" + study_df['SeriesInstanceUID'] + '/' + sop_ids + '.dcm'
dcm_ds = array([pydicom.read_file(o)for o in study_files])
 z_positions = array([int(o.ImagePositionPatient[-1])for o in dcm_ds])
 sortidxs = np.argsort(z_positions)
 sop_ids = sop_ids[sortidxs]
dcm_ds = dcm_ds[sortidxs]
z_positions = z_positions[sortidxs]
imgs = []
for o in dcm_ds: imgs += read_dcm_img_v2(o)
 h,w = imgs[0].size()
imgs = torch.stack(imgs ).view(-1,3,h,w)
 meta_embeddings = tensor(( minmax_scaler(z_positions)- mean)/std ).unsqueeze(1)
 emb_hook0 = EmbeddingHook(model0[1][1])
 emb_hook1 = EmbeddingHook(model1[1][1])
 emb_hook2 = EmbeddingHook(model2[1][1])
 emb_hook3 = EmbeddingHook(model3[1][1])
 emb_hook4 = EmbeddingHook(model4[1][1])
 with torch.no_grad() :
test_dl = learn2d_fold0.dls.test_dl(imgs.numpy() , bs=32, num_workers=2)
 outs0, outs1, outs2, outs3, outs4, outs5 = [],[],[],[],[],[]
for xb in test_dl:
out0 = model0(*xb); outs0.append(out0)
 out1 = model1(*xb); outs1.append(out1)
 out2 = model2(*xb); outs2.append(out2)
 out3 = model3(*xb); outs3.append(out3)
 out4 = model4(*xb); outs4.append(out4)
 outs0 = torch.cat(outs0)[:,1].view(-1,1)
 outs1 = torch.cat(outs1)[:,1].view(-1,1)
 outs2 = torch.cat(outs2)[:,1].view(-1,1)
 outs3 = torch.cat(outs3)[:,1].view(-1,1)
 outs4 = torch.cat(outs4)[:,1].view(-1,1)
 seq_inp0 = torch.cat([emb_hook0.embeddings, meta_embeddings.to(device), outs0],1)
 seq_inp1 = torch.cat([emb_hook1.embeddings, meta_embeddings.to(device), outs1],1)
 seq_inp2 = torch.cat([emb_hook2.embeddings, meta_embeddings.to(device), outs2],1)
 seq_inp3 = torch.cat([emb_hook3.embeddings, meta_embeddings.to(device), outs3],1)
 seq_inp4 = torch.cat([emb_hook4.embeddings, meta_embeddings.to(device), outs4],1)
 seq_img_preds0, posneg_preds0, rvlv_preds0, lrc_preds0, chroacute_preds0 = seq_model0.predict(seq_inp0[None,...])
 seq_img_preds1, posneg_preds1, rvlv_preds1, lrc_preds1, chroacute_preds1 = seq_model1.predict(seq_inp1[None,...])
 seq_img_preds2, posneg_preds2, rvlv_preds2, lrc_preds2, chroacute_preds2 = seq_model2.predict(seq_inp2[None,...])
 seq_img_preds3, posneg_preds3, rvlv_preds3, lrc_preds3, chroacute_preds3 = seq_model3.predict(seq_inp3[None,...])
 seq_img_preds4, posneg_preds4, rvlv_preds4, lrc_preds4, chroacute_preds4 = seq_model4.predict(seq_inp4[None,...])
 seq_img_preds0_tta, posneg_preds0_tta, rvlv_preds0_tta, lrc_preds0_tta, chroacute_preds0_tta = seq_model0.predict(seq_inp0.flip(dims=[0])[None,...])
 seq_img_preds1_tta, posneg_preds1_tta, rvlv_preds1_tta, lrc_preds1_tta, chroacute_preds1_tta = seq_model1.predict(seq_inp1.flip(dims=[0])[None,...])
 seq_img_preds2_tta, posneg_preds2_tta, rvlv_preds2_tta, lrc_preds2_tta, chroacute_preds2_tta = seq_model2.predict(seq_inp2.flip(dims=[0])[None,...])
 seq_img_preds3_tta, posneg_preds3_tta, rvlv_preds3_tta, lrc_preds3_tta, chroacute_preds3_tta = seq_model3.predict(seq_inp3.flip(dims=[0])[None,...])
 seq_img_preds4_tta, posneg_preds4_tta, rvlv_preds4_tta, lrc_preds4_tta, chroacute_preds4_tta = seq_model4.predict(seq_inp4.flip(dims=[0])[None,...])
 seq_img_preds0_tta = seq_img_preds0_tta.flip(dims=[1])
 seq_img_preds1_tta = seq_img_preds1_tta.flip(dims=[1])
 seq_img_preds2_tta = seq_img_preds2_tta.flip(dims=[1])
 seq_img_preds3_tta = seq_img_preds3_tta.flip(dims=[1])
 seq_img_preds4_tta = seq_img_preds4_tta.flip(dims=[1])
 seq_img_preds0,posneg_preds0,rvlv_preds0,lrc_preds0,chroacute_preds0 =(( seq_img_preds0+seq_img_preds0_tta)/2, 
(posneg_preds0+posneg_preds0_tta)/2, 
(rvlv_preds0+rvlv_preds0_tta)/2, 
(lrc_preds0+lrc_preds0_tta)/2, 
(chroacute_preds0+chroacute_preds0_tta)/2)
 seq_img_preds1,posneg_preds1,rvlv_preds1,lrc_preds1,chroacute_preds1 =(( seq_img_preds1+seq_img_preds1_tta)/2, 
(posneg_preds1+posneg_preds1_tta)/2, 
(rvlv_preds1+rvlv_preds1_tta)/2, 
(lrc_preds1+lrc_preds1_tta)/2, 
(chroacute_preds1+chroacute_preds1_tta)/2)
 seq_img_preds2,posneg_preds2,rvlv_preds2,lrc_preds2,chroacute_preds2 =(( seq_img_preds2+seq_img_preds2_tta)/2, 
(posneg_preds2+posneg_preds2_tta)/2, 
(rvlv_preds2+rvlv_preds2_tta)/2, 
(lrc_preds2+lrc_preds2_tta)/2, 
(chroacute_preds2+chroacute_preds2_tta)/2)
 seq_img_preds3,posneg_preds3,rvlv_preds3,lrc_preds3,chroacute_preds3 =(( seq_img_preds3+seq_img_preds3_tta)/2, 
(posneg_preds3+posneg_preds3_tta)/2, 
(rvlv_preds3+rvlv_preds3_tta)/2, 
(lrc_preds3+lrc_preds3_tta)/2, 
(chroacute_preds3+chroacute_preds3_tta)/2)
 seq_img_preds4,posneg_preds4,rvlv_preds4,lrc_preds4,chroacute_preds4 =(( seq_img_preds4+seq_img_preds4_tta)/2, 
(posneg_preds4+posneg_preds4_tta)/2, 
(rvlv_preds4+rvlv_preds4_tta)/2, 
(lrc_preds4+lrc_preds4_tta)/2, 
(chroacute_preds4+chroacute_preds4_tta)/2)
 seq_img_preds0 = seq_img_preds0.sigmoid()
seq_img_preds1 = seq_img_preds1.sigmoid()
seq_img_preds2 = seq_img_preds2.sigmoid()
seq_img_preds3 = seq_img_preds3.sigmoid()
seq_img_preds4 = seq_img_preds4.sigmoid()
posneg_preds =((
posneg_preds0.softmax(1)
 + posneg_preds1.softmax(1)
 + posneg_preds2.softmax(1)
 + posneg_preds3.softmax(1)
 + posneg_preds4.softmax(1)) / 5)[0]
rvlv_preds =((
rvlv_preds0.softmax(1)
 + rvlv_preds1.softmax(1)
 + rvlv_preds2.softmax(1)
 + rvlv_preds3.softmax(1)
 + rvlv_preds4.softmax(1)) / 5)[0]
lrc_preds =((
lrc_preds0.sigmoid()
+ lrc_preds1.sigmoid()
+ lrc_preds2.sigmoid()
+ lrc_preds3.sigmoid()
+ lrc_preds4.sigmoid())/ 5)[0]
chroacute_preds =((
chroacute_preds0.softmax(1)
 + chroacute_preds1.softmax(1)
 + chroacute_preds2.softmax(1)
 + chroacute_preds3.softmax(1)
 + chroacute_preds4.softmax(1)) / 5)[0]
_, negative, indeterminate = posneg_preds
rvlv_gte, rvlv_lt, _ = rvlv_preds
left_pe, right_pe, central_pe = lrc_preds
chro_pe, acute_chro_pe, _ = chroacute_preds
seq_exam_preds = torch.stack([negative, rvlv_gte, rvlv_lt, left_pe, chro_pe, right_pe, acute_chro_pe, central_pe, indeterminate])
 seq_img_preds =(( seq_img_preds0
+ seq_img_preds1
+ seq_img_preds2
+ seq_img_preds3
+ seq_img_preds4)/ 5)[0]
return(sop_ids, to_cpu(seq_img_preds), to_cpu(seq_exam_preds))<compute_train_metric>
Image(".. /input/rcfx-training-logs/history_4.png" )
def get_study_res(sid, sop_ids, img_preds, exam_preds):
"Get preds from 2D and 3D cnn models"
sub_res = []
for sopid, p in zip(sop_ids, to_np(img_preds)) :
sub_res.append(( sopid, p))
target_cols = [
'negative_exam_for_pe',
'rv_lv_ratio_gte_1',
'rv_lv_ratio_lt_1',
'leftsided_pe',
'chronic_pe',
'rightsided_pe',
'acute_and_chronic_pe',
'central_pe',
'indeterminate'
]
for tcol, p in zip(target_cols, to_np(exam_preds)) :
sub_res.append(( f"{sid}_{tcol}", p))
return sub_res<predict_on_test>
!pip install image-classifiers
%%time
do_full = False
n = 20
if Path('.. /input/rsna-str-pulmonary-embolism-detection/train' ).exists() and not do_full:
test_study_dirnames = [datapath/'test'/o for o in test_df['StudyInstanceUID'].unique() ]
test_study_dirnames = np.random.choice(test_study_dirnames, n, replace=False)
 sub_res = []
for study_dirname in test_study_dirnames:
sop_ids, seq_img_preds, seq_exam_preds = predict_study(study_dirname)
 study_res = get_study_res(study_dirname.stem, sop_ids, seq_img_preds, seq_exam_preds)
 sub_res += study_res<prepare_output>
tf.__version__
final_sub_df = pd.DataFrame(sub_res, columns=['id', 'label'])
 final_sub_df['label'] = np.clip(final_sub_df['label'], 0.0001, 0.9999 )<save_to_csv>
SEED = 42
def seed_everything(seed):
random.seed(seed)
 os.environ['PYTHONHASHSEED'] = str(seed)
 np.random.seed(seed)
 tf.random.set_seed(seed)
 seed_everything(SEED )
final_sub_df.to_csv("submission.csv", index=False )<feature_engineering>
ResNet34, preprocess_input = Classifiers.get('resnet34' )
def check_consistency(sub, test):

 df_tmp = sub.loc[sub.id.str.contains('_', regex = False)].reset_index(drop = True)
 df_tmp['StudyInstanceUID'] = df_tmp['id'].apply(lambda x:str(x ).split('_')[0])
 df_tmp['label_type'] = df_tmp['id'].apply(lambda x:'_'.join(str(x ).split('_')[1:]))
df_exam = df_tmp.pivot(index = 'StudyInstanceUID', columns = 'label_type', values = 'label')
 df_image = sub.loc[sub.id.isin(test.SOPInstanceUID)].reset_index(drop = True)
 df_image = df_image.merge(test, how = 'left', left_on = 'id', right_on = 'SOPInstanceUID')
 df_image.rename(columns = {"label": "pe_present_on_image"}, inplace = True)
 del df_image['id']
df = df_exam.merge(df_image, how = 'left', on = 'StudyInstanceUID')
 ids = ['StudyInstanceUID', 'SeriesInstanceUID', 'SOPInstanceUID']
labels = [c for c in df.columns if c not in ids]
df = df[ids + labels]
df['positive_images_in_exam'] = df['StudyInstanceUID'].map(df.groupby(['StudyInstanceUID'] ).pe_present_on_image.max())
 df_pos = df.loc[df.positive_images_in_exam > 0.5]
df_neg = df.loc[df.positive_images_in_exam <= 0.5]
rule1a = df_pos.loc[(( df_pos.rv_lv_ratio_lt_1 > 0.5)& 
(df_pos.rv_lv_ratio_gte_1 > 0.5)) | 
(( df_pos.rv_lv_ratio_lt_1 <= 0.5)& 
(df_pos.rv_lv_ratio_gte_1 <= 0.5)) ].reset_index(drop = True)
 rule1a['broken_rule'] = '1a'
rule1b = df_pos.loc[(df_pos.central_pe <= 0.5)& 
(df_pos.rightsided_pe <= 0.5)& 
(df_pos.leftsided_pe <= 0.5)].reset_index(drop = True)
 rule1b['broken_rule'] = '1b'
rule1c = df_pos.loc[(df_pos.acute_and_chronic_pe > 0.5)& 
(df_pos.chronic_pe > 0.5)].reset_index(drop = True)
 rule1c['broken_rule'] = '1c'
rule1d = df_pos.loc[(df_pos.indeterminate > 0.5)| 
(df_pos.negative_exam_for_pe > 0.5)].reset_index(drop = True)
 rule1d['broken_rule'] = '1d'
rule2a = df_neg.loc[(( df_neg.indeterminate > 0.5)& 
(df_neg.negative_exam_for_pe > 0.5)) | 
(( df_neg.indeterminate <= 0.5)& 
(df_neg.negative_exam_for_pe <= 0.5)) ].reset_index(drop = True)
 rule2a['broken_rule'] = '2a'
rule2b = df_neg.loc[(df_neg.rv_lv_ratio_lt_1 > 0.5)| 
(df_neg.rv_lv_ratio_gte_1 > 0.5)| 
(df_neg.central_pe > 0.5)| 
(df_neg.rightsided_pe > 0.5)| 
(df_neg.leftsided_pe > 0.5)| 
(df_neg.acute_and_chronic_pe > 0.5)| 
(df_neg.chronic_pe > 0.5)].reset_index(drop = True)
 rule2b['broken_rule'] = '2b'
errors = pd.concat([rule1a, rule1b, rule1c, rule1d, rule2a, rule2b], axis = 0)
 print('Found', len(errors), 'inconsistent predictions')
 if len(errors)> 0:
print(errors.broken_rule.value_counts())
 return errors<compute_test_metric>
cfg = {
'parse_params': {
'cut_time': 10,
},
'data_params': {
'sample_time': 6,
'spec_fmax': 24000.0,
'spec_fmin': 40.0,
'spec_mel': 384,
'mel_power': 2,
'img_shape':(384, 768)
 },
'model_params': {
'batchsize_per_tpu': 16,
'iteration_per_epoch': 64,
'epoch': 18,
'arch': ResNet34,
'arch_preprocess': preprocess_input,
'freeze_to': 0,
'loss': {
'fn': tfa.losses.SigmoidFocalCrossEntropy,
'params': {},
},
'optim': {
'fn': tfa.optimizers.RectifiedAdam,
'params': {'lr': 2e-3, 'total_steps': 18*64, 'warmup_proportion': 0.3, 'min_lr': 1e-6},
},
'mixup': True
}
}
%%time
consistency_df0 = check_consistency(final_sub_df, test_df )<count_values>
strategy = tf.distribute.experimental.TPUStrategy(tpu)
 AUTOTUNE = tf.data.experimental.AUTOTUNE
GCS_DS_PATH = KaggleDatasets().get_gcs_path('rfcx-species-audio-detection')
 TRAIN_TFREC = GCS_DS_PATH + "/tfrecords/train"
TEST_TFREC = GCS_DS_PATH + "/tfrecords/test"
consistency_df0['broken_rule'].value_counts()<import_modules>
CUT = cfg['parse_params']['cut_time']
SR = 48000
TIME = cfg['data_params']['sample_time']
FMAX = cfg['data_params']['spec_fmax']
FMIN = cfg['data_params']['spec_fmin']
N_MEL = cfg['data_params']['spec_mel']
HEIGHT, WIDTH = cfg['data_params']['img_shape']
CLASS_N = 24
from scipy.special import softmax<find_best_params>
raw_dataset = tf.data.TFRecordDataset([TRAIN_TFREC + '/00-148.tfrec'])
 raw_dataset
def solve_rule_1b(sub, errors, log=False):
studies_break_rule = errors.query("(central_pe <= 0.5)&(rightsided_pe <= 0.5)&(leftsided_pe <= 0.5)")['StudyInstanceUID'].unique()
if log:
print(studies_break_rule,studies_break_rule.shape)
 for i in studies_break_rule:
idx = sub[sub['id'].str.contains(i)].index.values
old = sub.loc[idx[[3,5,7]], 'label'].values
best = np.argmax(old)
 new = old.copy()
if(old[0] == 0.5)and(old[1] == 0.5)and(old[2] == 0.5):
pass
else:
new[best] = new[best] + 0.5
new = np.clip(new , 0, 0.51)
 if log:
print(old, new)
 sub.loc[idx[[3,5,7]], 'label'] = new<find_best_params>
feature_description = {
'recording_id': tf.io.FixedLenFeature([], tf.string, default_value=''),
'audio_wav': tf.io.FixedLenFeature([], tf.string, default_value=''),
'label_info': tf.io.FixedLenFeature([], tf.string, default_value=''),
}
parse_dtype = {
'audio_wav': tf.float32,
'recording_id': tf.string,
'species_id': tf.int32,
'songtype_id': tf.int32,
't_min': tf.float32,
'f_min': tf.float32,
't_max': tf.float32,
'f_max':tf.float32,
'is_tp': tf.int32
}
@tf.function
def _parse_function(example_proto):
sample = tf.io.parse_single_example(example_proto, feature_description)
 wav, _ = tf.audio.decode_wav(sample['audio_wav'], desired_channels=1)
 label_info = tf.strings.split(sample['label_info'], sep='"')[1]
labels = tf.strings.split(label_info, sep=';')
 @tf.function
def _cut_audio(label):
items = tf.strings.split(label, sep=',')
 spid = tf.squeeze(tf.strings.to_number(items[0], tf.int32))
soid = tf.squeeze(tf.strings.to_number(items[1], tf.int32))
tmin = tf.squeeze(tf.strings.to_number(items[2]))
fmin = tf.squeeze(tf.strings.to_number(items[3]))
tmax = tf.squeeze(tf.strings.to_number(items[4]))
fmax = tf.squeeze(tf.strings.to_number(items[5]))
tp = tf.squeeze(tf.strings.to_number(items[6], tf.int32))
tmax_s = tmax * tf.cast(SR, tf.float32)
 tmin_s = tmin * tf.cast(SR, tf.float32)
 cut_s = tf.cast(CUT * SR, tf.float32)
 all_s = tf.cast(60 * SR, tf.float32)
 tsize_s = tmax_s - tmin_s
cut_min = tf.cast(
 tf.maximum(0.0,
tf.minimum(tmin_s -(cut_s - tsize_s)/ 2,
tf.minimum(tmax_s +(cut_s - tsize_s)/ 2, all_s)- cut_s)
), tf.int32 
)
 cut_max = cut_min + CUT * SR
_sample = {
'audio_wav': tf.reshape(wav[cut_min:cut_max], [CUT*SR]),
'recording_id': sample['recording_id'],
'species_id': spid,
'songtype_id': soid,
't_min': tmin - tf.cast(cut_min, tf.float32)/tf.cast(SR, tf.float32),
'f_min': fmin,
't_max': tmax - tf.cast(cut_min, tf.float32)/tf.cast(SR, tf.float32),
'f_max': fmax,
'is_tp': tp
}
return _sample
samples = tf.map_fn(_cut_audio, labels, dtype=parse_dtype)
 return samples
parsed_dataset = raw_dataset.map(_parse_function ).unbatch()
def solve_rule_1c(sub, errors, log=False):
studies_break_rule = errors.query("(acute_and_chronic_pe > 0.5)&(chronic_pe > 0.5)")['StudyInstanceUID'].unique()
if log:
print(studies_break_rule, studies_break_rule.shape)
 for i in studies_break_rule:
idx = sub[sub['id'].str.contains(i)].index.values
old = sub.loc[idx[[4,6]], 'label'].values
new = softmax(old)
 if log:
print(old , new)
 sub.loc[idx[[4,6]], 'label'] == new<find_best_params>
@tf.function
def _cut_wav(x):
cut_min = tf.random.uniform([], maxval=(CUT-TIME)*SR, dtype=tf.int32)
 cut_max = cut_min + TIME * SR
cutwave = tf.reshape(x['audio_wav'][cut_min:cut_max], [TIME*SR])
 y = {}
y.update(x)
 y['audio_wav'] = cutwave
y['t_min'] = tf.maximum(0.0, x['t_min'] - tf.cast(cut_min, tf.float32)/ SR)
 y['t_max'] = tf.maximum(0.0, x['t_max'] - tf.cast(cut_min, tf.float32)/ SR)
 return y
@tf.function
def _cut_wav_val(x):
cut_min =(CUT-TIME)*SR // 2
cut_max = cut_min + TIME * SR
cutwave = tf.reshape(x['audio_wav'][cut_min:cut_max], [TIME*SR])
 y = {}
y.update(x)
 y['audio_wav'] = cutwave
y['t_min'] = tf.maximum(0.0, x['t_min'] - tf.cast(cut_min, tf.float32)/ SR)
 y['t_max'] = tf.maximum(0.0, x['t_max'] - tf.cast(cut_min, tf.float32)/ SR)
 return y
def solve_rule_1d(sub, errors, log=False):
studies_break_rule = errors.query("(indeterminate > 0.5)|(negative_exam_for_pe > 0.5)")['StudyInstanceUID'].unique()
if log:
print(studies_break_rule, studies_break_rule.shape)
 for i in studies_break_rule:
idx = sub[sub['id'].str.contains(i)].index.values
old = sub.loc[idx[[0,-1]], 'label'].values
new = np.clip(old, 0., 0.4)
 if log:
print(old , new)
 sub.loc[idx[[0,-1]], 'label'] = new<feature_engineering>
@tf.function
def _filtTP(x):
return x['is_tp'] == 1
def solve_negative(sub, errors):
negative_sopids = errors.query("negative_exam_for_pe > 0.5")['SOPInstanceUID'].values
neg_clip_idxs = sub[sub['id'].isin(negative_sopids)].index
sub.loc[neg_clip_idxs, 'label'] = np.clip(sub.loc[neg_clip_idxs, 'label'], 0, 0.5 )<compute_train_metric>
def show_wav(sample, ax):
wav = sample["audio_wav"].numpy()
rate = SR
ax.plot(np.arange(len(wav)) / rate, wav)
 ax.set_title(
 sample["recording_id"].numpy().decode()
+("/%d" % sample["species_id"])
 +("TP" if sample["is_tp"] else "FP"))
return Audio(( wav * 2**15 ).astype(np.int16), rate=rate)
 fig, ax = plt.subplots(figsize=(15, 3))
show_wav(next(iter(parsed_dataset)) , ax )
%%time
solve_negative(sub=final_sub_df, errors=consistency_df0 )<concatenate>
@tf.function
def _wav_to_spec(x):
mel_power = cfg['data_params']['mel_power']
stfts = tf.signal.stft(x["audio_wav"], frame_length=2048, frame_step=512, fft_length=2048)
 spectrograms = tf.abs(stfts)** mel_power
num_spectrogram_bins = stfts.shape[-1]
lower_edge_hertz, upper_edge_hertz, num_mel_bins = FMIN, FMAX, N_MEL
linear_to_mel_weight_matrix = tf.signal.linear_to_mel_weight_matrix(
 num_mel_bins, num_spectrogram_bins, SR, lower_edge_hertz,
upper_edge_hertz)
 mel_spectrograms = tf.tensordot(
 spectrograms, linear_to_mel_weight_matrix, 1)
 mel_spectrograms.set_shape(spectrograms.shape[:-1].concatenate(
 linear_to_mel_weight_matrix.shape[-1:]))
log_mel_spectrograms = tf.math.log(mel_spectrograms + 1e-6)
 y = {
'audio_spec': tf.transpose(log_mel_spectrograms),
}
y.update(x)
 return y
spec_dataset = parsed_dataset.filter(_filtTP ).map(_cut_wav ).map(_wav_to_spec )
%%time
consistency_df0 = check_consistency(sub=final_sub_df, test=test_df )<find_best_params>
@tf.function
def _create_annot(x):
targ = tf.one_hot(x["species_id"], CLASS_N, on_value=x["is_tp"], off_value=0)
 return {
'input': x["audio_spec"],
'target': tf.cast(targ, tf.float32)
 }
annot_dataset = spec_dataset.map(_create_annot )
%%time
solve_rule_1a(sub=final_sub_df, errors=consistency_df0, log=False)
 solve_rule_1b(sub=final_sub_df, errors=consistency_df0, log=False)
 solve_rule_1c(sub=final_sub_df, errors=consistency_df0, log=False)
 solve_rule_1d(sub=final_sub_df, errors=consistency_df0, log=False )<compute_test_metric>
@tf.function
def _preprocess_img(x, training=False, test=False):
image = tf.expand_dims(x, axis=-1)
 image = tf.image.resize(image, [HEIGHT, WIDTH])
 image = tf.image.per_image_standardization(image)
 @tf.function
def _specaugment(image):
ERASE_TIME = 50
ERASE_MEL = 16
image = tf.expand_dims(image, axis=0)
 xoff = tf.random.uniform([2], minval=ERASE_TIME//2, maxval=WIDTH-ERASE_TIME//2, dtype=tf.int32)
 xsize = tf.random.uniform([2], minval=ERASE_TIME//2, maxval=ERASE_TIME, dtype=tf.int32)
 yoff = tf.random.uniform([2], minval=ERASE_MEL//2, maxval=HEIGHT-ERASE_MEL//2, dtype=tf.int32)
 ysize = tf.random.uniform([2], minval=ERASE_MEL//2, maxval=ERASE_MEL, dtype=tf.int32)
 image = tfa.image.cutout(image, [HEIGHT, xsize[0]], offset=[HEIGHT//2, xoff[0]])
 image = tfa.image.cutout(image, [HEIGHT, xsize[1]], offset=[HEIGHT//2, xoff[1]])
 image = tfa.image.cutout(image, [ysize[0], WIDTH], offset=[yoff[0], WIDTH//2])
 image = tfa.image.cutout(image, [ysize[1], WIDTH], offset=[yoff[1], WIDTH//2])
 image = tf.squeeze(image, axis=0)
 return image
if training:
gau = tf.keras.layers.GaussianNoise(0.3)
 image = tf.cond(tf.random.uniform([])< 0.5, lambda: gau(image, training=True), lambda: image)
 image = tf.image.random_brightness(image, 0.2)
 image = tf.image.random_flip_left_right(image)
 image = tf.cond(tf.random.uniform([])< 0.5, lambda: _specaugment(image), lambda: image)
 if test:
pass
image =(image - tf.reduce_min(image)) /(tf.reduce_max(image)- tf.reduce_min(image)) * 255.0
image = tf.image.grayscale_to_rgb(image)
 image = cfg['model_params']['arch_preprocess'](image)
 return image
@tf.function
def _preprocess(x):
image = _preprocess_img(x['input'], training=True, test=False)
 return(image, x["target"])
 @tf.function
def _preprocess_val(x):
image = _preprocess_img(x['input'], training=False, test=False)
 return(image, x["target"])
 @tf.function
def _preprocess_test(x):
image = _preprocess_img(x['audio_spec'], training=False, test=True)
 return(image, x["recording_id"] )
consistency_df_final = check_consistency(final_sub_df, test_df )<save_to_csv>
def create_model() :
with strategy.scope() :
backbone = cfg['model_params']['arch'](( 224, 224, 3), include_top=False, weights='imagenet')
 if cfg['model_params']['freeze_to'] is None:
for layer in backbone.layers:
layer.trainable = False
else:
for layer in backbone.layers[:cfg['model_params']['freeze_to']]:
layer.trainable = False
model = tf.keras.Sequential([
backbone,
tf.keras.layers.GlobalAveragePooling2D() ,
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.Dropout(0.4),
tf.keras.layers.Dense(1024, activation='relu', kernel_initializer=tf.keras.initializers.he_normal()),
tf.keras.layers.BatchNormalization() ,
tf.keras.layers.Dropout(0.4),
tf.keras.layers.Dense(CLASS_N, bias_initializer=tf.keras.initializers.Constant(-2.))])
 return model
model = create_model()
model.summary()
submit_fixed = True
if submit_fixed:
final_sub_df.to_csv("submission.csv", index=False )<groupby>
@tf.function
def _mixup(inp, targ):
indice = tf.range(len(inp))
indice = tf.random.shuffle(indice)
 sinp = tf.gather(inp, indice, axis=0)
 starg = tf.gather(targ, indice, axis=0)
 alpha = 0.2
t = tf.compat.v1.distributions.Beta(alpha, alpha ).sample([len(inp)])
 tx = tf.reshape(t, [-1, 1, 1, 1])
 ty = tf.reshape(t, [-1, 1])
 x = inp * tx + sinp *(1-tx)
 y = targ * ty + starg *(1-ty)
 return x, y
final_sub_df['label_prefix'] = final_sub_df.apply(lambda o: "_".join(o['id'].split("_")[1:]), 1)
 stats = final_sub_df.groupby("label_prefix" ).agg(['min', 'max', 'mean', 'median'])
 stats<load_from_zip>
tfrecs = sorted(tf.io.gfile.glob(TRAIN_TFREC + '/*.tfrec'))
parsed_trainval =(tf.data.TFRecordDataset(tfrecs, num_parallel_reads=AUTOTUNE)
.map(_parse_function, num_parallel_calls=AUTOTUNE ).unbatch() 
.filter(_filtTP ).enumerate() )
!cp.. /input/gdcm-conda-install/gdcm.tar.
 !tar -xvzf gdcm.tar
!conda install --offline./gdcm/gdcm-2.8.9-py37h71b2a6d_0.tar.bz2<define_variables>
indices = []
spid = []
recid = []
for i, sample in tqdm(parsed_trainval.prefetch(AUTOTUNE)) :
indices.append(i.numpy())
 spid.append(sample['species_id'].numpy())
 recid.append(sample['recording_id'].numpy().decode() )
sys.path = [
'.. /input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master',
] + sys.path<import_modules>
table = pd.DataFrame({'indices': indices, 'species_id': spid, 'recording_id': recid})
 table
import os
import cv2
import glob
import torch
import random
import pydicom
import datetime
import warnings
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from tqdm.notebook import tqdm
from torch.utils.data import Dataset
from scipy.ndimage.interpolation import zoom
from sklearn.model_selection import *<set_options>
def create_idx_filter(indice):
@tf.function
def _filt(i, x):
return tf.reduce_any(indice == i)
 return _filt
@tf.function
def _remove_idx(i, x):
return x
def seed_everything(seed):

 random.seed(seed)
 os.environ["PYTHONHASHSEED"] = str(seed)
 np.random.seed(seed)
 torch.manual_seed(seed)
 torch.cuda.manual_seed(seed)
 torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = True<define_variables>
def create_train_dataset(batchsize, train_idx):
global parsed_trainval
parsed_train =(parsed_trainval 
.filter(create_idx_filter(train_idx)) 
.map(_remove_idx))
dataset =(parsed_train.cache() 
.shuffle(len(train_idx)) 
.repeat() 
.map(_cut_wav, num_parallel_calls=AUTOTUNE)
.map(_wav_to_spec, num_parallel_calls=AUTOTUNE)
.map(_create_annot, num_parallel_calls=AUTOTUNE)
.map(_preprocess, num_parallel_calls=AUTOTUNE)
.batch(batchsize))
if cfg['model_params']['mixup']:
dataset =(dataset.map(_mixup, num_parallel_calls=AUTOTUNE)
.prefetch(AUTOTUNE))
else:
dataset = dataset.prefetch(AUTOTUNE)
 return dataset
def create_val_dataset(batchsize, val_idx):
global parsed_trainval
parsed_val =(parsed_trainval 
.filter(create_idx_filter(val_idx)) 
.map(_remove_idx))
vdataset =(parsed_val 
.map(_cut_wav_val, num_parallel_calls=AUTOTUNE)
.map(_wav_to_spec, num_parallel_calls=AUTOTUNE)
.map(_create_annot, num_parallel_calls=AUTOTUNE)
.map(_preprocess_val, num_parallel_calls=AUTOTUNE)
.batch(8*strategy.num_replicas_in_sync)
.cache())
 return vdataset
SEED = 2020
seed_everything(SEED)
 MEAN = np.array([0.485, 0.456, 0.406])
 STD = np.array([0.229, 0.224, 0.225])
 DEVICE = torch.device("cuda")if torch.cuda.is_available() else torch.device("cpu")
 SIZE = 256
IMG_TARGET = "pe_present_on_image"
EXAM_TARGETS = [
"negative_exam_for_pe",
"rv_lv_ratio_gte_1",
"rv_lv_ratio_lt_1",
"leftsided_pe",
"chronic_pe",
"rightsided_pe",
"acute_and_chronic_pe",
"central_pe",
"indeterminate",
]
NUM_EXAM_TARGETS = len(EXAM_TARGETS )<define_variables>
@tf.function
def _one_sample_positive_class_precisions(example):
y_true, y_pred = example
retrieved_classes = tf.argsort(y_pred, direction='DESCENDING')
 class_rankings = tf.argsort(retrieved_classes)
 retrieved_class_true = tf.gather(y_true, retrieved_classes)
 retrieved_cumulative_hits = tf.math.cumsum(tf.cast(retrieved_class_true, tf.float32))
idx = tf.where(y_true)[:, 0]
i = tf.boolean_mask(class_rankings, y_true)
 r = tf.gather(retrieved_cumulative_hits, i)
 c = 1 + tf.cast(i, tf.float32)
 precisions = r / c
dense = tf.scatter_nd(idx[:, None], precisions, [y_pred.shape[0]])
 return dense
class LWLRAP(tf.keras.metrics.Metric):
def __init__(self, num_classes, name='lwlrap'):
super().__init__(name=name)
 self._precisions = self.add_weight(
 name='per_class_cumulative_precision',
shape=[num_classes],
initializer='zeros', 
)
 self._counts = self.add_weight(
 name='per_class_cumulative_count',
shape=[num_classes],
initializer='zeros', 
)
 def update_state(self, y_true, y_pred, sample_weight=None):
precisions = tf.map_fn(
 fn=_one_sample_positive_class_precisions,
elems=(y_true, y_pred),
dtype=(tf.float32), 
)
 increments = tf.cast(precisions > 0, tf.float32)
 total_increments = tf.reduce_sum(increments, axis=0)
 total_precisions = tf.reduce_sum(precisions, axis=0)
 self._precisions.assign_add(total_precisions)
 self._counts.assign_add(total_increments)
 def result(self):
per_class_lwlrap = self._precisions / tf.maximum(self._counts, 1.0)
 per_class_weight = self._counts / tf.reduce_sum(self._counts)
 overall_lwlrap = tf.reduce_sum(per_class_lwlrap * per_class_weight)
 return overall_lwlrap
def reset_states(self):
self._precisions.assign(self._precisions * 0)
 self._counts.assign(self._counts * 0 )
DATA_PATH = ".. /input/rsna-str-pulmonary-embolism-detection/"<categorify>
def _parse_function_test(example_proto):
sample = tf.io.parse_single_example(example_proto, feature_description)
 wav, _ = tf.audio.decode_wav(sample['audio_wav'], desired_channels=1)
 @tf.function
def _cut_audio(i):
_sample = {
'audio_wav': tf.reshape(wav[i*SR*TIME:(i+1)*SR*TIME], [SR*TIME]),
'recording_id': sample['recording_id']
}
return _sample
return tf.map_fn(_cut_audio, tf.range(60//TIME), dtype={
'audio_wav': tf.float32,
'recording_id': tf.string
})
 def inference(model):
tdataset =(tf.data.TFRecordDataset(tf.io.gfile.glob(TEST_TFREC + '/*.tfrec'), num_parallel_reads=AUTOTUNE)
.map(_parse_function_test, num_parallel_calls=AUTOTUNE ).unbatch() 
.map(_wav_to_spec, num_parallel_calls=AUTOTUNE)
.map(_preprocess_test, num_parallel_calls=AUTOTUNE)
.batch(128*(60//TIME)).prefetch(AUTOTUNE))
rec_ids = []
probs = []
for inp, rec_id in tqdm(tdataset):
with strategy.scope() :
pred = model.predict_on_batch(tf.reshape(inp, [-1, HEIGHT, WIDTH, 3]))
prob = tf.sigmoid(pred)
 prob = tf.reduce_max(tf.reshape(prob, [-1, 60//TIME, CLASS_N]), axis=1)
 rec_id_stack = tf.reshape(rec_id, [-1, 60//TIME])
 for rec in rec_id.numpy() :
assert len(np.unique(rec)) == 1
rec_ids.append(rec_id_stack.numpy() [:,0])
 probs.append(prob.numpy())
 crec_ids = np.concatenate(rec_ids)
 cprobs = np.concatenate(probs)
 sub = pd.DataFrame({
'recording_id': list(map(lambda x: x.decode() , crec_ids.tolist())) ,
**{f's{i}': cprobs[:,i] for i in range(CLASS_N)}
})
 sub = sub.sort_values('recording_id')
 return sub
def normalizer(mean=MEAN, std=STD):
return albu.Compose([
albu.Normalize(mean=mean, std=std),
AT.transforms.ToTensor() ,
],
p=1,
)<save_to_csv>
def train_and_inference(splits, split_id):
batchsize = cfg['model_params']['batchsize_per_tpu'] * strategy.num_replicas_in_sync
print("batchsize", batchsize)
 loss_fn = cfg['model_params']['loss']['fn'](from_logits=True, **cfg['model_params']['loss']['params'])
 optimizer = cfg['model_params']['optim']['fn'](**cfg['model_params']['optim']['params'])
 model = create_model()
with strategy.scope() :
model.compile(optimizer=optimizer, loss=loss_fn, metrics=[LWLRAP(CLASS_N)])
 model.load_weights('.. /input/rcfx-resnet34-weights/model_best_%d.h5' % split_id)
 return inference(model )
def to_jpg(img, name='img'):
cv2.imwrite(name + ".jpg", img)
 return cv2.imread(name + ".jpg" )<categorify>
sub = sum(
 map(
 lambda i: train_and_inference(splits, i ).set_index('recording_id'),
range(len(splits)) 
)
 ).reset_index()
<load_pretrained><EOS> 
sub.to_csv("submission.csv", index=False )