Kaggle competition: Rainforest Connection Species Audio Detection
<SOS> metric: WeightedLabelRankingAveragePrecision Kaggle data source: rainforest-connection-species-audio-detection<sort_values>
save_to_disk = 0
if use_ucf:
train_df = train_df.sort_values('month')
 train_df = train_df.reset_index()<categorify>
!pip install resnest > /dev/null
<count_missing_values>
def horizontal_flip(img):
horizontal_flip_img = img[:, ::-1]
return addChannels(horizontal_flip_img)
 def vertical_flip(img):
vertical_flip_img = img[::-1, :]
return addChannels(vertical_flip_img)
 def addNoisy(img):
noise_img = util.random_noise(img)
 return addChannels(noise_img)
 def contrast_stretching(img):
contrast_img = exposure.rescale_intensity(img)
 return addChannels(contrast_img)
 def randomGaussian(img):
gaussian_img = gaussian(img)
 return addChannels(gaussian_img)
 def grayScale(img):
gray_img = rgb2gray(img)
 return addChannels(gray_img)
 def randomGamma(img):
img_gamma = exposure.adjust_gamma(img)
 return addChannels(img_gamma)
 def addChannels(img):
return np.stack(( img, img, img))
def spec_to_image(spec):
spec = resize(spec,(224, 400))
eps=1e-6
mean = spec.mean()
std = spec.std()
spec_norm =(spec - mean)/(std + eps)
 spec_min, spec_max = spec_norm.min() , spec_norm.max()
spec_scaled = 255 *(spec_norm - spec_min)/(spec_max - spec_min)
 spec_scaled = spec_scaled.astype(np.uint8)
 spec_scaled = np.asarray(spec_scaled)
 return spec_scaled
weather_train_df.isna().sum()<groupby>
def get_model() :
resnet_model = resnest50(pretrained=True)
 num_ftrs = resnet_model.fc.in_features
resnet_model.fc = nn.Linear(num_ftrs, num_birds)
 resnet_model = resnet_model.to(device)
 return resnet_model
weather_train_df.groupby('site_id' ).apply(lambda group: group.isna().sum() )<groupby>
class AudioData(Dataset):
def __init__(self, X, y, data_type):
self.data = []
self.labels = []
self.augs = [
addNoisy, contrast_stretching,
randomGaussian, grayScale,
randomGamma, vertical_flip,
horizontal_flip, addChannels
]
self.data_type=data_type
for i in range(0, len(X)) :
recording_id = X[i]
label = y[i]
mel_spec = audio_data[recording_id]['original']
self.data.append(mel_spec)
 self.labels.append(label)
 def __len__(self):
return len(self.data)
 def __getitem__(self, idx):
if self.data_type == "train":
aug= random.choice(self.augs)
 data = aug(self.data[idx])
 else:
data = addChannels(self.data[idx])
 return data, self.labels[idx]
weather_train_df = weather_train_df.groupby('site_id' ).apply(lambda group: group.interpolate(limit_direction='both'))<groupby>
import torch
import torch.nn as nn
import copy
weather_train_df.groupby('site_id' ).apply(lambda group: group.isna().sum() )<data_type_conversions>
class Adas(Optimizer):
r
def __init__(self, params,
lr = 0.001, lr2 =.005, lr3 =.0005,
beta_1 = 0.999, beta_2 = 0.999, beta_3 = 0.9999,
epsilon = 1e-8, **kwargs):
if not 0.0 <= lr:
raise ValueError("Invalid lr: {}".format(lr))
if not 0.0 <= lr2:
raise ValueError("Invalid lr2: {}".format(lr))
if not 0.0 <= lr3:
raise ValueError("Invalid lr3: {}".format(lr))
if not 0.0 <= epsilon:
raise ValueError("Invalid epsilon value: {}".format(eps))
if not 0.0 <= beta_1 < 1.0:
raise ValueError("Invalid beta_1 parameter: {}".format(betas[0]))
if not 0.0 <= beta_2 < 1.0:
raise ValueError("Invalid beta_2 parameter: {}".format(betas[1]))
if not 0.0 <= beta_3 < 1.0:
raise ValueError("Invalid beta_3 parameter: {}".format(betas[2]))
defaults = dict(lr=lr, lr2=lr2, lr3=lr3, beta_1=beta_1, beta_2=beta_2, beta_3=beta_3, epsilon=epsilon)
 self._varn = None
self._is_create_slots = None
self._curr_var = None
self._lr = lr
self._lr2 = lr2
self._lr3 = lr3
self._beta_1 = beta_1
self._beta_2 = beta_2
self._beta_3 = beta_3
self._epsilon = epsilon
super(Adas, self ).__init__(params, defaults)
 def __setstate__(self, state):
super(Adas, self ).__setstate__(state)
 @torch.no_grad()
def _add(self,x,y):
x.add_(y)
 return x
@torch.no_grad()
def _derivatives_normalizer(self,derivative,beta):
steps = self._make_variable(0,() ,derivative.dtype)
 self._add(steps,1)
 factor =(1.-(self._beta_1 ** steps)).sqrt()
m = self._make_variable(0,derivative.shape,derivative.dtype)
 moments = self._make_variable(0,derivative.shape,derivative.dtype)
 m.mul_(self._beta_1 ).add_(( 1 - self._beta_1)* derivative * derivative)
 np_t = derivative * factor /(m.sqrt() + self._epsilon)
 return(moments,np_t,lambda: moments.mul_(beta ).add_(( 1 - beta)* np_t))
def _make_variable(self,value,shape,dtype):
self._varn += 1
name = 'unnamed_variable' + str(self._varn)
 if self._is_create_slots:
self.state[self._curr_var][name] = torch.full(size=shape,fill_value=value,dtype=dtype,device=self._curr_var.device)
 return self.state[self._curr_var][name]
@torch.no_grad()
def _get_updates_universal_impl(self, grad, param):
lr = self._make_variable(value = self._lr,shape=param.shape[1:], dtype=param.dtype)
 moment, deriv, f = self._derivatives_normalizer(grad,self._beta_3)
 param.add_(- torch.unsqueeze(lr,0)* deriv)
 lr_deriv = torch.sum(moment * grad,0)
 f()
master_lr = self._make_variable(self._lr2,() ,dtype=torch.float32)
 m2,d2, f = self._derivatives_normalizer(lr_deriv,self._beta_2)
 self._add(lr,master_lr * lr * d2)
 master_lr_deriv2 = torch.sum(m2 * lr_deriv)
 f()
m3,d3,f = self._derivatives_normalizer(master_lr_deriv2,0.)
self._add(master_lr,self._lr3 * master_lr * d3)
 f()
@torch.no_grad()
def _get_updates_universal(self, param, grad, is_create_slots):
self._curr_var = param
self._is_create_slots = is_create_slots
self._varn = 0
return self._get_updates_universal_impl(grad,self._curr_var.data)
 @torch.no_grad()
def step(self, closure=None):

 loss = None
if closure is not None:
with torch.enable_grad() :
loss = closure()
for group in self.param_groups:
for p in group['params']:
if p.grad is None:
continue
grad = p.grad.data
if grad.is_sparse:
raise RuntimeError('Adas does not support sparse gradients')
 self._get_updates_universal(p,grad,len(self.state[p])== 0)
 return loss
def add_lag_feature(weather_df, window=3):
group_df = weather_df.groupby('site_id')
 cols = ['air_temperature', 'cloud_coverage', 'dew_temperature', 'precip_depth_1_hr', 'sea_level_pressure', 'wind_direction', 'wind_speed']
rolled = group_df[cols].rolling(window=window, min_periods=0)
 lag_mean = rolled.mean().reset_index().astype(np.float16)
 lag_max = rolled.max().reset_index().astype(np.float16)
 lag_min = rolled.min().reset_index().astype(np.float16)
 lag_std = rolled.std().reset_index().astype(np.float16)
 for col in cols:
weather_df[f'{col}_mean_lag{window}'] = lag_mean[col]
weather_df[f'{col}_max_lag{window}'] = lag_max[col]
weather_df[f'{col}_min_lag{window}'] = lag_min[col]
weather_df[f'{col}_std_lag{window}'] = lag_std[col]<feature_engineering>
num_birds = 24
if torch.cuda.is_available() :
device=torch.device('cuda:0')
 else:
device=torch.device('cpu' )
add_lag_feature(weather_train_df, window=3)
 add_lag_feature(weather_train_df, window=72 )<feature_engineering>
learning_rate = 2e-4
epochs = 20
loss_fn = nn.CrossEntropyLoss()
def train(model, loss_fn, train_loader, valid_loader, epochs, optimizer, scheduler):
best_model_wts = copy.deepcopy(model.state_dict())
 best_acc = 0.0
train_losses = []
valid_losses = []
for epoch in tqdm(range(1,epochs+1)) :
model.train()
batch_losses=[]
for i, data in enumerate(train_loader):
x, y = data
optimizer.zero_grad()
x = x.to(device, dtype=torch.float32)
 y = y.to(device, dtype=torch.long)
 y_hat = model(x)
 loss = loss_fn(y_hat, y)
 loss.backward()
batch_losses.append(loss.item())
 optimizer.step()
train_losses.append(batch_losses)
 print(f'Epoch - {epoch} Train-Loss : {np.mean(train_losses[-1])}')
 model.eval()
batch_losses=[]
trace_y = []
trace_yhat = []
for i, data in enumerate(valid_loader):
x, y = data
x = x.to(device, dtype=torch.float32)
 y = y.to(device, dtype=torch.long)
 y_hat = model(x)
 loss = loss_fn(y_hat, y)
 trace_y.append(y.cpu().detach().numpy())
 trace_yhat.append(y_hat.cpu().detach().numpy())
 batch_losses.append(loss.item())
 valid_losses.append(batch_losses)
 trace_y = np.concatenate(trace_y)
 trace_yhat = np.concatenate(trace_yhat)
 accuracy = np.mean(trace_yhat.argmax(axis=1)==trace_y)
 print(f'Epoch - {epoch} Valid-Loss : {np.mean(valid_losses[-1])} Valid-Accuracy : {accuracy}')
 scheduler.step(np.mean(valid_losses[-1]))
if accuracy > best_acc:
best_acc = accuracy
best_model_wts = copy.deepcopy(model.state_dict())
 model.load_state_dict(best_model_wts)
 return model
year_map = building_meta_df.year_built.value_counts()
building_meta_df['year_cnt'] = building_meta_df.year_built.map(year_map)
 bid_map = train_df.building_id.value_counts()
train_df['bid_cnt'] = train_df.building_id.map(bid_map )<categorify>
fft = 2048
hop = 512
sr = 48000
length = 10 * sr
with open('/kaggle/input/rfcx-species-audio-detection/train_tp.csv')as f:
reader = csv.reader(f)
 next(reader, None)
 data = list(reader)
 fmin = 24000
fmax = 0
for i in range(0, len(data)) :
if fmin > float(data[i][4]):
fmin = float(data[i][4])
 if fmax < float(data[i][6]):
fmax = float(data[i][6])
 fmin = int(fmin * 0.9)
 fmax = int(fmax * 1.1)
 print('Minimum frequency: ' + str(fmin)+ ', maximum frequency: ' + str(fmax))
label_list = []
data_list = []
audio_data = {}
for d in data:
recording_id = d[0]
species_id = int(d[1])
 data_list.append(recording_id)
 label_list.append(species_id)
 audio_data[recording_id] = {}
wav, sr = librosa.load('/kaggle/input/rfcx-species-audio-detection/train/' + recording_id + '.flac', sr=None)
 t_min = float(d[3])* sr
t_max = float(d[5])* sr
center = np.round(( t_min + t_max)/ 2)
 beginning = center - length / 2
if beginning < 0:
beginning = 0
ending = beginning + length
if ending > len(wav):
ending = len(wav)
 beginning = ending - length
slice = wav[int(beginning):int(ending)]
spec=librosa.feature.melspectrogram(slice, sr=sr,n_fft=fft,hop_length=hop,fmin=fmin,fmax=fmax)
 spec_db=librosa.power_to_db(spec,top_db=80)
 img = spec_to_image(spec_db)
 audio_data[recording_id]["original"] = img
primary_use_list = building_meta_df['primary_use'].unique()
primary_use_dict = {key: value for value, key in enumerate(primary_use_list)}
print('primary_use_dict: ', primary_use_dict)
 building_meta_df['primary_use'] = building_meta_df['primary_use'].map(primary_use_dict)
 gc.collect()<feature_engineering>
nfold = 5
skf = KFold(n_splits=nfold, shuffle=True, random_state=32)
 for fold_id,(train_index, val_index)in enumerate(skf.split(data_list, label_list)) :
print("Fold", fold_id)
 X_train = np.take(data_list, train_index)
 y_train = np.take(label_list, train_index, axis = 0)
 X_val = np.take(data_list, val_index)
 y_val = np.take(label_list, val_index, axis = 0)
 train_data = AudioData(X_train, y_train, "train")
 valid_data = AudioData(X_val, y_val, "valid")
 train_loader = DataLoader(train_data, batch_size=8, shuffle=True, drop_last=True)
 valid_loader = DataLoader(valid_data, batch_size=8, shuffle=True, drop_last=True)
 resnet_model = get_model()
optimizer = Adas(resnet_model.parameters() , lr=learning_rate)
 scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=3)
 resnet_model = train(resnet_model, loss_fn, train_loader, valid_loader, epochs, optimizer, scheduler)
 torch.save(resnet_model.state_dict() , "model"+str(fold_id)+".pt")
 del train_data, valid_data, train_loader, valid_loader, resnet_model, X_train, X_val, y_train, y_val
train_df = reduce_mem_usage(train_df, use_float16=True)
 building_meta_df = reduce_mem_usage(building_meta_df, use_float16=True)
 weather_train_df = reduce_mem_usage(weather_train_df, use_float16=True )<feature_engineering>
def load_test_file(f):
wav, sr = librosa.load('/kaggle/input/rfcx-species-audio-detection/test/' + f, sr=None)
 segments = len(wav)/ length
segments = int(np.ceil(segments))
mel_array = []
for i in range(0, segments):
if(i + 1)* length > len(wav):
slice = wav[len(wav)- length:len(wav)]
else:
slice = wav[i * length:(i + 1)* length]
spec=librosa.feature.melspectrogram(slice, sr=sr,n_fft=fft,hop_length=hop,fmin=fmin,fmax=fmax)
 spec_db=librosa.power_to_db(spec,top_db=80)
 img = spec_to_image(spec_db)
 mel_spec = np.stack(( img, img, img))
mel_array.append(mel_spec)
 return mel_array
def add_sg(df):
w = 11
p = 2
for si in df.site_id.unique() :
index = df.site_id == si
df.loc[index, 'air_smooth'] = sg(df[index].air_temperature, w, p)
 df.loc[index, 'dew_smooth'] = sg(df[index].dew_temperature, w, p)
 df.loc[index, 'air_diff'] = sg(df[index].air_temperature, w, p, 1)
 df.loc[index, 'dew_diff'] = sg(df[index].dew_temperature, w, p, 1)
 df.loc[index, 'air_diff2'] = sg(df[index].air_temperature, w, p, 2)
 df.loc[index, 'dew_diff2'] = sg(df[index].dew_temperature, w, p, 2 )<feature_engineering>
del audio_data
members = []
for i in range(nfold):
model = get_model()
model.load_state_dict(torch.load('/kaggle/working/model'+str(i)+'.pt'))
model.eval()
members.append(model )
<define_variables><EOS> 
if save_to_disk == 0:
for f in os.listdir('/kaggle/working/'):
os.remove('/kaggle/working/' + f)
 print('Starting prediction loop')
 with open('submission.csv', 'w', newline='')as csvfile:
submission_writer = csv.writer(csvfile, delimiter=',')
 submission_writer.writerow(['recording_id','s0','s1','s2','s3','s4','s5','s6','s7','s8','s9','s10','s11',
's12','s13','s14','s15','s16','s17','s18','s19','s20','s21','s22','s23'])
 test_files = os.listdir('/kaggle/input/rfcx-species-audio-detection/test/')
 print(len(test_files))
for i in range(0, len(test_files)) :
data = load_test_file(test_files[i])
 data = torch.tensor(data)
 data = data.float()
if torch.cuda.is_available() :
data = data.cuda()
output_list = []
for m in members:
output = m(data)
 maxed_output = torch.max(output, dim=0)[0]
maxed_output = maxed_output.cpu().detach()
output_list.append(maxed_output)
 avg_maxed_output = torch.mean(torch.stack(output_list), dim=0)
 file_id = str.split(test_files[i], '.')[0]
write_array = [file_id]
for out in avg_maxed_output:
write_array.append(out.item())
 submission_writer.writerow(write_array)
 if i % 100 == 0 and i > 0:
print('Predicted for ' + str(i)+ ' of ' + str(len(test_files)+ 1)+ ' files')
 print('Submission generated' )