<jupyter_start><jupyter_text>**Upload the sample files to Google Colab and extract .zip**<jupyter_code>from google.colab import files
uploaded = files.upload()

#!unzip Samples.zip<jupyter_output><empty_output><jupyter_text>Load the files to a list and add corresponding label. *Skip problematic files*<jupyter_code>import os
from scipy.io import wavfile
import numpy as np
data = []
labels = []
directory = './Samples/Kicks/'
!cd Samples/Kicks
for filename in os.listdir(directory):
  try:
    if filename.endswith(".wav") or filename.endswith(".WAV"):
        fs, new_data = wavfile.read(directory + filename)
        data.append(np.array(new_data))
        labels.append(0)
        continue
    else:
      continue
  except:
    print("Oops")
    continue
    
directory = './Samples/Snares/'
for filename in os.listdir(directory):
  try:
    if filename.endswith(".wav") or filename.endswith(".WAV"):
        fs, new_data = wavfile.read(directory + filename)
        data.append(np.array(new_data))
        labels.append(1)
        continue
    else:
        continue
  except:
    print("Oops")
    continue
directory = './Samples/HHT/'
for filename in os.listdir(directory):
  try:
    if filename.endswith(".wav") or filename.endswith(".WAV"):
        fs, new_data = wavfile.read(directory + filename)
        data.append(np.array(new_data))
        labels.append(2)
        continue
    else:
        continue
  except:
    print("Oops")
    continue
    
    
print(len(data), len(labels))<jupyter_output>/usr/local/lib/python3.6/dist-packages/scipy/io/wavfile.py:273: WavFileWarning: Chunk (non-data) not understood, skipping it.
  WavFileWarning)<jupyter_text>Remove items with unusual shape<jupyter_code>for i, item in enumerate(data):
  if len(item.shape) != 2:
    del data[i]
    del labels[i]
    print(len(data))
    print(len(labels))<jupyter_output>465
465
464
464
463
463
462
462
461
461
460
460
459
459
458
458
457
457<jupyter_text>Process items to give them same size (size of max file+220) and put into numpy array for further processing.<jupyter_code>desired_shape = (np.max([np.max(item.shape) for item in data ]) + 220 , 2)
print(desired_shape)
processed_data = None
for i, item in enumerate(data):
  if (len(item.shape) == 2):
    result = np.zeros(desired_shape).astype(np.int16)
    result[:item.shape[0],:item.shape[1]] = item.astype(np.int16)
    result = result.reshape((1, desired_shape[0], desired_shape[1]))
    if processed_data is None:
      processed_data = result
    else:
      print("\r"+str( result.shape) + " ==> " + str(processed_data.shape), end="")
      processed_data = np.append(processed_data, result, axis=0)
  else:
    del labels[i]
print(processed_data.shape)

labels = np.array(labels).astype(np.int16)<jupyter_output><empty_output><jupyter_text>Now we need to get processed_data to be in range of [-1;1] instead of current [-32000; 32000]<jupyter_code>processed_data[200]
max_val = np.max(processed_data)
processed_data = processed_data.astype(np.float16)
processed_data = processed_data/max_val
processed_data[200]
from keras.utils import to_categorical

categorical_labels = to_categorical(labels, num_classes=3)
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, LSTM
from tensorflow.keras.callbacks import ModelCheckpoint
## extra imports to set GPU options
import tensorflow as tf
from keras import backend as k
 
###################################
# TensorFlow wizardry
config = tf.ConfigProto()
 
# Don't pre-allocate memory; allocate as-needed
config.gpu_options.allow_growth = True
 
# Only allow a total of half the GPU memory to be allocated
config.gpu_options.per_process_gpu_memory_fraction = 0.95
config.inter_op_parallelism_threads=4
config.intra_op_parallelism_threads=4
# Create a session with the above options specified.
k.tensorflow_backend.set_session(tf.Session(config=config))
###################################<jupyter_output><empty_output><jupyter_text>**Create a NN model utilizing AveragePooling(for incoming samples); Temporal 1D convolutions and MaxPooling layers and finish with Fully Connected layer and Softmax output layer**<jupyter_code>model = Sequential()
model.add(tf.keras.layers.InputLayer(input_shape=(desired_shape[0], desired_shape[1])))
model.add(tf.keras.layers.AveragePooling1D(22, 2))
model.add(tf.keras.layers.Conv1D(4, 3, 2, "valid", activation="relu"))
model.add(tf.keras.layers.MaxPooling1D(3, 2))
model.add(tf.keras.layers.Conv1D(16, 3, 2, "valid", activation="relu"))
model.add(tf.keras.layers.MaxPooling1D(3, 2))
model.add(tf.keras.layers.Conv1D(64, 3, 2, "valid", activation="relu"))
model.add(tf.keras.layers.MaxPooling1D(3, 2))
model.add(tf.keras.layers.Flatten())
model.add(Dense(16, activation='relu'))
model.add(Dense(3, activation='softmax'))
opt = tf.keras.optimizers.RMSprop(lr=0.002)

model.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'],
)
model.summary()
# checkpoint
filepath="weights.best.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')
callbacks_list = [checkpoint]
model.fit(processed_data, categorical_labels, epochs=20, verbose=1, validation_split=0.2, batch_size= 16, shuffle=True, callbacks=callbacks_list)<jupyter_output>Train on 364 samples, validate on 92 samples
Epoch 1/20
352/364 [============================>.] - ETA: 0s - loss: 0.8128 - acc: 0.6648
Epoch 00001: val_loss improved from inf to 2.67035, saving model to weights.best.hdf5
364/364 [==============================] - 5s 15ms/sample - loss: 0.8038 - acc: 0.6676 - val_loss: 2.6703 - val_acc: 0.0000e+00
Epoch 2/20
352/364 [============================>.] - ETA: 0s - loss: 0.3995 - acc: 0.8295
Epoch 00002: val_loss improved from 2.67035 to 2.11387, saving model to weights.best.hdf5
364/364 [==============================] - 4s 12ms/sample - loss: 0.3926 - acc: 0.8297 - val_loss: 2.1139 - val_acc: 0.0000e+00
Epoch 3/20
352/364 [============================>.] - ETA: 0s - loss: 0.3403 - acc: 0.8778
Epoch 00003: val_loss improved from 2.11387 to 0.69377, saving model to weights.best.hdf5
364/364 [==============================] - 4s 12ms/sample - loss: 0.3419 - acc: 0.8791 - val_loss: 0.6938 - val_acc: 0.8804
Epoch 4/20
352/364 [================[...]<jupyter_text>Load the weights with best validation performance and save our model.<jupyter_code>model.load_weights("weights.best.hdf5")
model.save('sound_rec_model.h5')
from google.colab import files
#files.download('sound_rec_model.h5')<jupyter_output><empty_output><jupyter_text>Now we can test the Classification accuracy with other samples not used in training/validation<jupyter_code>from google.colab import files
#uploaded = files.upload()


fs, data = wavfile.read('Phonotix Kick 1.wav')
test_data = np.array(data).astype(np.int16)
result = np.zeros(desired_shape).astype(np.float16)
result[:test_data.shape[0],:test_data.shape[1]] = test_data/max_val
test_data = result.reshape((1, desired_shape[0], desired_shape[1]))

np.argmax(model.predict(test_data))
model.predict(processed_data[0].reshape(1, 1254620, 2))
model.predict(processed_data[250].reshape(1, 1254620, 2))
model.predict(processed_data[400].reshape(1, 1254620, 2))
type(test_data[0][0][0])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15936689862191294, 'fraction_numerical': 0.05703370173284213, 'mean_word_length': 5.108333333333333, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '399023', 'license': 'MIT', 'n_tokens_mistral': 2823, 'n_tokens_neox': 2514, 'n_words': 568, 'path': 'Sound_Recognition_Conv1D.ipynb', 'repo_name': 'renowator/My_ML', 'size': '7329'}