├── .gitignore ├── README.md ├── binary ├── config.py ├── cough.txt ├── detector.py ├── logs │ └── fit │ │ └── 20200505-215154 │ │ ├── train │ │ ├── events.out.tfevents.1588708314.master.213418.566.v2 │ │ ├── events.out.tfevents.1588708315.master.profile-empty │ │ └── plugins │ │ │ └── profile │ │ │ └── 2020_05_05_21_51_55 │ │ │ ├── master.input_pipeline.pb │ │ │ ├── master.kernel_stats.pb │ │ │ ├── master.overview_page.pb │ │ │ ├── master.tensorflow_stats.pb │ │ │ └── master.trace.json.gz │ │ └── validation │ │ └── events.out.tfevents.1588708316.master.213418.2305.v2 ├── model.py ├── not.txt ├── processing.py ├── resize.py └── sweep.yaml ├── covid ├── model.py └── processing.ipynb ├── short-spectro ├── detector.py ├── model.py └── processing.py └── spectro ├── detector.py ├── model.py ├── processing.ipynb ├── processing.py └── sweep.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | dry_wet/dataset.json 2 | dry_wet/edited_wavs 3 | binary/data/ 4 | binary/dataset.json 5 | binary/dataset_8.json 6 | binary/wav 7 | binary/.idea 8 | binary/.idea/ 9 | binary/model.h5 10 | binary/model.json 11 | binary/test.wav 12 | binary/__pycache__/ 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoughCNN 2 | 3 | ## Covid Anomaly detection model 4 | 5 | Due to the lack of enough covid cough samples, and of the precise features in those coughs which classify it as covid; 6 | we cannot use a simple supervised learning approach. Instead the approach taken currently is an unsupervised (which will 7 | turn to semisupervised later using the avaiable data to refine the model) using an autoencoder. The autoencoder takes all 8 | the non-covid cough samples which have been detected by the model in `spectro` and uses them as a training dataset, the autoencoder 9 | learns the representation of a "normal" cough and how to recreate it (boils down the sample using convolutions and then re-builds 10 | the sample using a transposition of the convolution). When a cough that was not similar to the ones which were in the dataset 11 | (which with enough data should be singled out to the covid coughs) the error which the model will make at recreating the sample 12 | provided (calculate useing MSE of the original image with the one created by the model) will be high and the sample will be 13 | labeled as an anomaly. 14 | 15 | ### Current 16 | 17 | Under the folder `covid` there are two files: 18 | **model.py**, contains the code for the autoencoder and the MSE applied to the melspectrogram, this still does not work unfortunately 19 | I'm tweaking the input shape of the samples by increasing the sample length and the number of mels per sample but I'm still getting 20 | problems. 21 | **processing.ipynb** contains the data processing to create the dataset used 22 | 23 | **short-spectro** is a clone folder of `spectro` but contains the scripts to make the data suitable for the anomaly detection model, 24 | once a stable solution for the anomaly detection will be finished all the samples will be in the same format and usable in any model. 25 | As of now I'll be keeping both separate. 26 | 27 | Here is all the data processed by the short-spectro: https://drive.google.com/file/d/1aAMGHTFJjiv7K6DrN_1DptcCeA3Efmbk/view?usp=sharing 28 | 29 | ## Log Melspectrogram 30 | 31 | Under the folder `spectro` you can find the whole approach using the melspectrograms to train a Convolutional Neural Network 32 | 33 | ### Current 34 | 35 | Right now the data that has been used comes from a cough dataset from: https://www.karger.com/Article/FullText/504666 36 | and using manually labeled data coming from our webapp. The testing dataset is also manyally labeled data coming 37 | from our webapp but that obviosly the CNN has not seen before. 38 | 39 | This was acheived augmenting the dataset by mixing the cough sample with some background noise to make them 40 | more real world. It was used a mixing ration of 0.25 (0.25 of the noise signal added) using the musan dataset 41 | https://www.openslr.org/17/ 42 | 43 | The samples are now a grayscale melspectrogram of 0.5s. 44 | 45 | All the data of the project can be found at : https://drive.google.com/drive/folders/1deqYCDye5l95RGJCeKXlcqH9Ras7lRQr?usp=sharing 46 | 47 | Right now we have normalized the data and we use a new model structure using GlobalAveragePooling2D which gave a huge performance 48 | boost to the previous version. We went from 68-75% to 80-84% accuracy on our test set created from the webapp. 49 | Right now we are running hyperparameters optimization and you can check out everything at: 50 | https://app.wandb.ai/mastersplinter/CoughDetect/sweeps/phdtst8z 51 | 52 | ### Next 53 | 54 | - Data processing hyperparameters 55 | - Testing different sample length and optimize them 56 | 57 | ### Resources that inspired this: 58 | 59 | - https://arxiv.org/pdf/2004.01275.pdf (for initial model architecture) 60 | - https://www.mi.t.u-tokyo.ac.jp/assets/publication/LEARNING_ENVIRONMENTAL_SOUNDS_WITH_END-TO-END_CONVOLUTIONAL_NEURAL_NETWORK.pdf 61 | - https://www.cs.tut.fi/~tuomasv/papers/ijcnn_paper_valenti_extended.pdf 62 | - https://adventuresinmachinelearning.com/global-average-pooling-convolutional-neural-networks/ 63 | - https://arxiv.org/pdf/1809.04437.pdf 64 | - https://arxiv.org/pdf/1711.10282.pdf 65 | -------------------------------------------------------------------------------- /binary/config.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | DATA_FOLDER = "edited_wavs/" 4 | OUTPUT = "dataset.json" 5 | LABELS = ["cough", "not"] 6 | SR = 16000 7 | N_MFCC = 15 8 | N_FURIER = 2048 9 | HOP_LENGTH = 512 10 | SEGMENT_LENGTH = SR//2 11 | EXPECTED_MFCC = math.ceil(SEGMENT_LENGTH/HOP_LENGTH) -------------------------------------------------------------------------------- /binary/cough.txt: -------------------------------------------------------------------------------- 1 | https://www.youtube.com/watch?v=jxYNLCYTwZQ 2 | https://www.youtube.com/watch?v=qfpJg179YNk 3 | https://www.youtube.com/watch?v=d2wkdrScerU 4 | https://www.youtube.com/watch?v=ct3tHDfNKiQ 5 | https://www.youtube.com/watch?v=Dc_aoUCqw2E 6 | https://www.youtube.com/watch?v=tvHytTlGs0M 7 | https://www.youtube.com/watch?v=0QQxKN-KC1U 8 | https://www.youtube.com/watch?v=De4HdyocTHY 9 | https://www.youtube.com/watch?v=DYfjPnty2Ho 10 | https://www.youtube.com/watch?v=q6WsoL3J8U8 11 | https://www.youtube.com/watch?v=CTSLdNxN1cc 12 | https://www.youtube.com/watch?v=T2MtUVpdAxg 13 | https://www.youtube.com/watch?v=tfc5cXiXMDc 14 | https://www.youtube.com/watch?v=rkF_uMizqoc 15 | https://www.youtube.com/watch?v=5905FxXz9dI 16 | https://www.youtube.com/watch?v=IzPMbIll3LE 17 | https://www.youtube.com/watch?v=h2FLCKMcEX0 18 | https://www.youtube.com/watch?v=2Mw-s5jnqXU 19 | https://www.youtube.com/watch?v=diuuEXKzNB8 20 | https://www.youtube.com/watch?v=dg-I9j76-t8 21 | https://www.youtube.com/watch?v=TK4CveeCWfY 22 | https://www.youtube.com/watch?v=4k0ziD0j5BI 23 | https://www.youtube.com/watch?v=CsDXlt7Ei1c 24 | https://www.youtube.com/watch?v=7Ez5Wc_esBg 25 | https://www.youtube.com/watch?v=NfKZNt25L-Q 26 | https://www.youtube.com/watch?v=NaOVmYoIjbs 27 | https://www.youtube.com/watch?v=XrpB4DTNQZw 28 | https://www.youtube.com/watch?v=h-GtQfDCoaE 29 | https://www.youtube.com/watch?v=u2KMBD5-oCg 30 | https://www.youtube.com/watch?v=A5s2ZgwQ1VM 31 | https://www.youtube.com/watch?v=ekqLlw-Xe68 32 | https://www.youtube.com/watch?v=6LK6yHtIung 33 | https://www.youtube.com/watch?v=tZtJaS2ZtME 34 | https://www.youtube.com/watch?v=AQOeIVbhFm4 35 | https://www.youtube.com/watch?v=elAtjXsj8Jg 36 | https://www.soundsnap.com/node/90850 37 | https://www.soundsnap.com/node/27240 38 | https://www.soundsnap.com/node/28608 39 | https://www.soundsnap.com/node/27471 40 | https://www.soundsnap.com/node/26976 41 | https://www.youtube.com/watch?v=9RjZr8V8PNY 42 | https://www.youtube.com/watch?v=6mcpuDVN6lQ 43 | https://www.youtube.com/watch?v=zjd4HrJbc8o 44 | https://www.youtube.com/watch?v=iYxUHA-Pwsk 45 | https://www.youtube.com/watch?v=1UDFq2InljM 46 | https://www.youtube.com/watch?v=LkxvBb2VXbs 47 | -------------------------------------------------------------------------------- /binary/detector.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import librosa 4 | import argparse 5 | import numpy as np 6 | from config import * 7 | import tensorflow.keras as keras 8 | 9 | parser = argparse.ArgumentParser(description="Classify where the cough is in a file and split it up") 10 | parser.add_argument("file", metavar="f", type=str, help="Path to the audio file, must be wav") 11 | args = parser.parse_args() 12 | 13 | 14 | json_file = open('model.json', 'r') 15 | model = json_file.read() 16 | json_file.close() 17 | model = keras.models.model_from_json(model) 18 | model.load_weights("model.h5") 19 | 20 | os.system("clear") 21 | 22 | print("Loaded model from disk") 23 | 24 | try: 25 | os.system("mkdir detected/") 26 | except: 27 | pass 28 | 29 | mfccs = [] 30 | signal, sr = librosa.load(args.file, sr=SR) 31 | # Decide the segments based on length 32 | segments = len(signal) // SEGMENT_LENGTH 33 | pieces = [] 34 | curr = 0 # For segment indexing 35 | for segment in range(segments): 36 | p = signal[curr:curr + SEGMENT_LENGTH] 37 | # Extract mfcc data 38 | mfcc = librosa.feature.mfcc(p, sr=SR, n_mfcc=N_MFCC, n_fft=N_FURIER, 39 | hop_length=HOP_LENGTH).T 40 | if len(mfcc) == EXPECTED_MFCC: 41 | mfccs.append(mfcc.tolist()) 42 | pieces.append(p) 43 | 44 | curr += SEGMENT_LENGTH 45 | 46 | predictions = [] 47 | for x in mfccs: 48 | x = np.array(x) 49 | x = x[np.newaxis, ...] 50 | x = np.expand_dims(x, axis=3) 51 | pred = np.argmax(model.predict(x), axis=1) 52 | predictions.append(pred) 53 | 54 | for i in range(len(predictions)): 55 | if predictions[i][0] == 0: 56 | librosa.output.write_wav("detected/"+str(i)+".wav", pieces[i], sr=SR) 57 | 58 | end = '\033[0m' 59 | green = '\033[92m' 60 | length = 50 61 | each = "|" * (length // len(predictions)) 62 | output = "" 63 | for p in predictions: 64 | if p[0] == 0: 65 | output += green + each + end 66 | else: 67 | output += each 68 | 69 | print(output) -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/train/events.out.tfevents.1588708314.master.213418.566.v2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/train/events.out.tfevents.1588708314.master.213418.566.v2 -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/train/events.out.tfevents.1588708315.master.profile-empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/train/events.out.tfevents.1588708315.master.profile-empty -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.input_pipeline.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.input_pipeline.pb -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.kernel_stats.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.kernel_stats.pb -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.overview_page.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.overview_page.pb -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.tensorflow_stats.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.tensorflow_stats.pb -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.trace.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/train/plugins/profile/2020_05_05_21_51_55/master.trace.json.gz -------------------------------------------------------------------------------- /binary/logs/fit/20200505-215154/validation/events.out.tfevents.1588708316.master.213418.2305.v2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splinter0/CoughCNN/71005bf7056f657ea30cb676d50fff999baa1f11/binary/logs/fit/20200505-215154/validation/events.out.tfevents.1588708316.master.213418.2305.v2 -------------------------------------------------------------------------------- /binary/model.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import json 5 | import datetime 6 | import numpy as np 7 | from config import * 8 | import tensorflow as tf 9 | import tensorflow.keras as keras 10 | from pydub import AudioSegment 11 | import librosa, librosa.display 12 | from pydub.silence import split_on_silence 13 | from sklearn.model_selection import train_test_split 14 | 15 | os.system("clear") 16 | 17 | DATA = "dataset.json" 18 | 19 | def load_data(path): 20 | with open(path, "r") as j: 21 | data = json.load(j) 22 | 23 | return np.array(data["mfcc"]), np.array(data["labels"]) 24 | 25 | hyper = dict( 26 | channel_one = 60, 27 | kernel_one = (3, 3), 28 | activation = 'relu', 29 | pool_one = (3, 3), 30 | strides_one = (2, 2), 31 | padding = 'same', 32 | 33 | channel_two = 16, 34 | kernel_two = (2, 2), 35 | pool_two = (2, 2), 36 | strides_two = (2, 2), 37 | 38 | channel_three = 28, 39 | kernel_three = (2, 2), 40 | pool_three = (2, 2), 41 | strides_three = (2, 2), 42 | 43 | deep_one = 497, 44 | drop_one = 0.5998, 45 | deep_two = 80, 46 | drop_two = 0.3656 47 | ) 48 | 49 | import wandb 50 | from wandb.keras import WandbCallback 51 | wandb.init(config=hyper, project="CoughDetection", name="MainModel") 52 | 53 | def model(input_shape): 54 | m = keras.Sequential() 55 | 56 | # 1st conv layer 57 | m.add(keras.layers.Conv2D(hyper["channel_one"], hyper["kernel_one"], activation=hyper["activation"], input_shape=input_shape)) 58 | m.add(keras.layers.MaxPooling2D(hyper["pool_one"], strides=hyper["strides_one"], padding='same')) 59 | m.add(keras.layers.BatchNormalization()) 60 | 61 | m.add(keras.layers.Conv2D(hyper["channel_two"], hyper["kernel_two"], activation=hyper["activation"])) 62 | m.add(keras.layers.MaxPooling2D(hyper["pool_two"], strides=hyper["strides_two"], padding='same')) 63 | m.add(keras.layers.BatchNormalization()) 64 | 65 | m.add(keras.layers.Conv2D(hyper["channel_three"], hyper["kernel_three"], activation=hyper["activation"])) 66 | m.add(keras.layers.MaxPooling2D(hyper["pool_three"], strides=hyper["strides_three"], padding='same')) 67 | m.add(keras.layers.BatchNormalization()) 68 | 69 | m.add(keras.layers.Flatten()) 70 | m.add(keras.layers.Dense(hyper["deep_one"], activation='relu')) 71 | m.add(keras.layers.Dropout(hyper["drop_one"])) 72 | m.add(keras.layers.Dense(hyper["deep_two"], activation='relu')) 73 | m.add(keras.layers.Dropout(hyper["drop_two"])) 74 | 75 | m.add(keras.layers.Dense(2, activation='softmax')) 76 | 77 | return m 78 | 79 | def predict(mod, path): 80 | mfccs = [] 81 | signal, sr = librosa.load(path, sr=SR) 82 | # Decide the segments based on length 83 | segments = len(signal) // SEGMENT_LENGTH 84 | curr = 0 # For segment indexing 85 | for segment in range(segments): 86 | # Extract mfcc data 87 | mfcc = librosa.feature.mfcc(signal[curr:curr + SEGMENT_LENGTH], sr=SR, n_mfcc=N_MFCC, n_fft=N_FURIER, 88 | hop_length=HOP_LENGTH).T 89 | if len(mfcc) == EXPECTED_MFCC: 90 | mfccs.append(mfcc.tolist()) 91 | 92 | curr += SEGMENT_LENGTH 93 | 94 | predictions = [] 95 | for x in mfccs: 96 | x = np.array(x) 97 | x = x[np.newaxis, ...] 98 | x = np.expand_dims(x, axis=3) 99 | pred = np.argmax(mod.predict(x), axis=1) 100 | predictions.append(pred) 101 | 102 | return predictions 103 | 104 | # Pretty Print Prediction... yes 105 | def ppp(prediction): 106 | end = '\033[0m' 107 | green = '\033[92m' 108 | length = 50 109 | each = "|"*(length//len(prediction)) 110 | output = "" 111 | for p in prediction: 112 | if p[0] == 0: 113 | output += green+each+end 114 | else: 115 | output += each 116 | 117 | print(output) 118 | 119 | if __name__ == "__main__": 120 | TRAIN = True 121 | 122 | if TRAIN: 123 | x, y = load_data(DATA) 124 | x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25) 125 | x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size=0.3) 126 | 127 | x_train = x_train[..., np.newaxis] 128 | x_test = x_test[..., np.newaxis] 129 | x_val = x_val[..., np.newaxis] 130 | 131 | m = model((x_train.shape[1], x_train.shape[2], 1)) 132 | opt = keras.optimizers.Adam(learning_rate=0.000001) 133 | 134 | m.compile(optimizer=opt, 135 | loss="sparse_categorical_crossentropy", 136 | metrics=['accuracy']) 137 | 138 | log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") 139 | callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1) 140 | 141 | m.summary() 142 | m.fit(x_train, y_train, validation_data=(x_val, y_val), batch_size=32, epochs=120, callbacks=[WandbCallback()]) 143 | 144 | test_err, test_acc = m.evaluate(x_test, y_test, verbose=1) 145 | print("Accuracy on testing data", test_acc) 146 | 147 | model_json = m.to_json() 148 | with open("model.json", "w") as json_file: 149 | json_file.write(model_json) 150 | print("Saved model to disk") 151 | m.save_weights("model.h5") 152 | 153 | else: 154 | json_file = open('model.json', 'r') 155 | loaded_model_json = json_file.read() 156 | json_file.close() 157 | loaded_model = keras.models.model_from_json(loaded_model_json) 158 | # load weights into new model 159 | loaded_model.load_weights("model.h5") 160 | print("Loaded model from disk") 161 | 162 | t = predict(loaded_model, "test2.wav") 163 | ppp(t) 164 | t = predict(loaded_model, "test.wav") 165 | ppp(t) 166 | 167 | -------------------------------------------------------------------------------- /binary/not.txt: -------------------------------------------------------------------------------- 1 | https://www.youtube.com/watch?v=D7ZZp8XuUTE 2 | https://www.youtube.com/watch?v=DQqETh7E0LM 3 | https://www.youtube.com/watch?v=jAg6tyC9Xxc 4 | https://www.youtube.com/watch?v=LyvpfemDyYw 5 | -------------------------------------------------------------------------------- /binary/processing.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | import os 4 | import math 5 | import json 6 | import copy 7 | import youtube_dl 8 | import numpy as np 9 | from config import * 10 | from tqdm import tqdm 11 | from pydub import AudioSegment 12 | import librosa, librosa.display 13 | from pydub.silence import split_on_silence 14 | 15 | """ 16 | This script downloads all the youtube links in the files named after the labels, then: 17 | - Converts them into WAV 18 | - Splits them into non silent chunks 19 | - Splits the chunks into segments (the actual size of training data, so that we have same lenghts) 20 | - Extracts the mfccs out of the segments 21 | - Saves the data in a json file 22 | 23 | (I split the data fetching at conversion to the mfcc because it was taking too much memory to do it all together) 24 | 25 | Dataset from: https://www.karger.com/Article/FullText/504666 26 | """ 27 | 28 | os.system("clear") 29 | 30 | pbar = None 31 | queue = None 32 | 33 | youtube_par = { 34 | 'format': 'bestaudio/best', 35 | 'postprocessors': [{ 36 | 'key': 'FFmpegExtractAudio', 37 | 'preferredcodec': 'mp3', 38 | 'preferredquality': '192', 39 | }], 40 | 'quiet':True 41 | } 42 | 43 | data = { 44 | "mfcc":[], 45 | "labels":[] 46 | } 47 | 48 | 49 | def single(link, out, silence): 50 | conf = copy.deepcopy(youtube_par) 51 | conf["outtmpl"] = out+"%(title)s.mp3" 52 | try: 53 | f = "" 54 | # Download the video 55 | with youtube_dl.YoutubeDL(conf) as you: 56 | info = you.extract_info(link, download=True) 57 | f = out+""+info.get("title", None) 58 | pbar.update(0.25) 59 | # Convert it into WAV, needed because youtube_dl currupts wav files on dowload for some reason 60 | os.system("ffmpeg -i '" + f + ".mp3' '" + f + ".wav' >/dev/null 2>&1") 61 | os.system("rm '" + f + ".mp3'") 62 | # This doesn't run for non cough data because we want it to be noisy 63 | if silence: 64 | # Load whole wav file 65 | signal = AudioSegment.from_wav(f +".wav") 66 | # Split the wav file into chunks of non silent 67 | chunks = split_on_silence(signal, min_silence_len=500, silence_thresh=-35) 68 | pbar.update(0.25) 69 | # Exports all the chunks 70 | for i, c in enumerate(chunks): 71 | c.export(f + str(i) + ".wav", format="wav") 72 | os.system("rm '"+f+".wav'") 73 | else: 74 | pbar.update(0.25) 75 | 76 | except Exception as e: 77 | pass 78 | 79 | pbar.update(0.5) 80 | 81 | 82 | def process(folder, label): 83 | items = os.listdir(folder) 84 | if label == 1: 85 | # To make sure we get same amount of data for both classes 86 | each = len(data["labels"])//len(items) 87 | print(each) 88 | for sample in tqdm(items): 89 | if os.path.splitext(sample)[-1] != ".wav": 90 | continue 91 | # Load the chunk into librosa 92 | signal, sr = librosa.load(folder+sample, sr=SR) 93 | # Decide the segments based on length 94 | segments = len(signal) // SEGMENT_LENGTH 95 | curr = 0 # For segment indexing 96 | # print(sample, segments) 97 | count = 0 98 | for segment in range(segments): 99 | pieces = [signal[curr:curr + SEGMENT_LENGTH]] 100 | if label == 1 and count >= each: 101 | break 102 | elif label == 0: 103 | #pieces += augment(signal[curr:curr + SEGMENT_LENGTH]) 104 | pass 105 | 106 | # Extract mfcc data 107 | for p in pieces: 108 | mfcc = librosa.feature.mfcc(p, sr=SR, n_mfcc=N_MFCC, n_fft=N_FURIER, 109 | hop_length=HOP_LENGTH).T 110 | if len(mfcc) == EXPECTED_MFCC: 111 | data["mfcc"].append(mfcc.tolist()) 112 | data["labels"].append(label) 113 | count += 1 114 | 115 | curr += SEGMENT_LENGTH 116 | 117 | def augment(signal): 118 | different = [] 119 | # Add white noise 120 | noise = np.random.randn(len(signal)) 121 | different.append(signal + 0.0025*noise) 122 | # Shift sound 123 | different.append(np.roll(signal, SR)) 124 | 125 | return different 126 | 127 | 128 | if __name__ == "__main__": 129 | FETCH = False 130 | 131 | try: 132 | os.system("mkdir data >/dev/null 2>&1") 133 | except: 134 | pass 135 | 136 | for i, label in enumerate(LABELS): 137 | try: 138 | os.system("mkdir data/"+label+" >/dev/null 2>&1") 139 | except: 140 | pass 141 | 142 | if FETCH: 143 | print("Processing label: "+label) 144 | with open(label+".txt", "r") as f: 145 | links = f.read().splitlines() 146 | 147 | pbar = tqdm(total=len(links)) 148 | for l in links: 149 | if "youtube" in l: 150 | single(l, "data/"+label+"/", i == 0) 151 | else: 152 | process("data/"+label+"/", i) 153 | 154 | if not FETCH: 155 | # Dump the dat into json file 156 | print(len(data["labels"])) 157 | with open(OUTPUT, "w") as j: 158 | json.dump(data, j, indent=4) -------------------------------------------------------------------------------- /binary/resize.py: -------------------------------------------------------------------------------- 1 | import os 2 | from tqdm import tqdm 3 | from pydub import AudioSegment 4 | 5 | """ 6 | This is a helper script to chop up large audio files 7 | """ 8 | 9 | MAX=2*60*1000 10 | FOLDER = "data/not/" 11 | SKIP = 6 12 | N_PER = 5 13 | 14 | for sample in tqdm(os.listdir(FOLDER)): 15 | n = os.path.splitext(sample) 16 | if n[-1] != ".wav": 17 | continue 18 | 19 | signal = AudioSegment.from_wav(FOLDER+sample) 20 | curr = 0 21 | for i in range(N_PER): 22 | if i+1 % SKIP == 0: 23 | continue 24 | signal[curr:curr+MAX].export(FOLDER+n[0]+str(i)+".wav", format="wav") 25 | curr += MAX 26 | 27 | os.system("rm '"+FOLDER+sample+"'") -------------------------------------------------------------------------------- /binary/sweep.yaml: -------------------------------------------------------------------------------- 1 | program: model.py 2 | method: random 3 | command: 4 | - ${env} 5 | - python3 6 | - ${program} 7 | - ${args} 8 | metric: 9 | name: loss 10 | goal: minimize 11 | parameters: 12 | padding: 13 | distribution: categorical 14 | values: 15 | - same 16 | deep_one: 17 | distribution: int_uniform 18 | min: 128 19 | max: 512 20 | deep_two: 21 | distribution: int_uniform 22 | min: 32 23 | max: 128 24 | drop_one: 25 | distribution: uniform 26 | min: 0.15 27 | max: 0.6 28 | drop_two: 29 | distribution: uniform 30 | min: 0.15 31 | max: 0.6 32 | activation: 33 | distribution: categorical 34 | values: 35 | - relu 36 | channel_one: 37 | distribution: int_uniform 38 | min: 16 39 | max: 64 40 | channel_two: 41 | distribution: int_uniform 42 | min: 16 43 | max: 64 44 | channel_three: 45 | distribution: int_uniform 46 | min: 16 47 | max: 64 48 | -------------------------------------------------------------------------------- /covid/model.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import wandb 4 | import datetime 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | from tensorflow.keras.models import Model 8 | from tensorflow.keras import backend as K 9 | from tensorflow.keras.optimizers import Adam 10 | from tensorflow.keras.regularizers import l2 11 | from tensorflow.keras.layers import BatchNormalization, Conv2D, Conv2DTranspose, LeakyReLU, Activation, Flatten, Dense, Reshape, Input 12 | 13 | DATASET = "dataset.npy" 14 | 15 | def load_data(f): 16 | data = np.load(f, allow_pickle=True) 17 | data = np.array(data) 18 | train = [] 19 | validation = [] 20 | 21 | for sample in data: 22 | if sample[0] == 0: 23 | validation.append(sample[1]) 24 | else: 25 | train.append(sample[1]) 26 | 27 | start = len(train)-int(len(train)*0.3) 28 | validation += train[start:] 29 | train = train[:start] 30 | train = np.array(train) 31 | validation = np.array(validation) 32 | np.random.shuffle(validation) 33 | 34 | shape = (train.shape[1], train.shape[2], 1) 35 | 36 | train = train.reshape(train.shape[0], shape[0], shape[1], shape[2]) 37 | validation = validation.reshape(validation.shape[0], shape[0], shape[1], shape[2]) 38 | return train, validation, shape 39 | 40 | def MSE(x, y): 41 | err = np.sum((x.astype("float") - y.astype("float")) ** 2) 42 | err /= float(x * y) 43 | return err 44 | 45 | def visualize_predictions(decoded, gt, samples=10): 46 | outputs = None 47 | for i in range(0, samples): 48 | original = (gt[i] * 255).astype("uint8") 49 | recon = (decoded[i] * 255).astype("uint8") 50 | output = np.hstack([original, recon]) 51 | if outputs is None: 52 | outputs = output 53 | else: 54 | outputs = np.vstack([outputs, output]) 55 | return outputs 56 | 57 | class AutoEncoder(object): 58 | def __init__(self, name, config, hyper=False, hyper_project="", extra=None): 59 | self.name = name 60 | self.config = config 61 | 62 | if hyper: 63 | wandb.init(config=config, project=hyper_project) 64 | wandb.run.save() 65 | try: 66 | os.system("mkdir sweep/"+wandb.run.name) 67 | except: 68 | pass 69 | 70 | def build(self, input_shape): 71 | input_layer = Input(shape=input_shape) 72 | x = input_layer 73 | x = Conv2D(self.config["conv1"], self.config["kernel1"], strides=2, padding="same")(x) 74 | x = LeakyReLU(alpha=self.config["alpha"])(x) 75 | x = BatchNormalization()(x) 76 | 77 | x = Conv2D(self.config["conv2"], self.config["kernel2"], strides=2, padding="same")(x) 78 | x = LeakyReLU(alpha=self.config["alpha"])(x) 79 | x = BatchNormalization()(x) 80 | 81 | x = Conv2D(self.config["conv3"], self.config["kernel3"], strides=2, padding="same")(x) 82 | x = LeakyReLU(alpha=self.config["alpha"])(x) 83 | x = BatchNormalization()(x) 84 | 85 | magnitude = K.int_shape(x) 86 | x = Flatten()(x) 87 | 88 | hand = Dense(self.config["dense"])(x) 89 | 90 | self.encoder = Model(input_layer, hand, name="encoder") 91 | 92 | # decoder 93 | decoder_input = Input(shape=(self.config["dense"],)) 94 | x = Dense(np.prod(magnitude[1:]))(decoder_input) 95 | x = Reshape((magnitude[1], magnitude[2], magnitude[3]))(x) 96 | 97 | x = Conv2DTranspose(self.config["conv3"], self.config["kernel3"], strides=2, padding="same")(x) 98 | x = LeakyReLU(alpha=self.config["alpha"])(x) 99 | x = BatchNormalization()(x) 100 | 101 | x = Conv2DTranspose(self.config["conv2"], self.config["kernel2"], strides=2, padding="same")(x) 102 | x = LeakyReLU(alpha=self.config["alpha"])(x) 103 | x = BatchNormalization()(x) 104 | 105 | 106 | x = Conv2DTranspose(self.config["conv1"], self.config["kernel1"], strides=2, padding="same")(x) 107 | x = LeakyReLU(alpha=self.config["alpha"])(x) 108 | x = BatchNormalization()(x) 109 | 110 | x = Conv2DTranspose(self.config["trans"], self.config["kernel1"], padding="same")(x) 111 | outputs = Activation("sigmoid")(x) 112 | 113 | self.decoder = Model(decoder_input, outputs, name="decoder") 114 | 115 | self.model = Model(input_layer, self.decoder(self.encoder(input_layer)), name="autoencoder") 116 | 117 | def train(self, x_train, x_test): 118 | self.optimizer = Adam(lr=self.config["lr"], decay=self.config["lr"]/self.config["epochs"]) 119 | self.model.compile(loss="mse", optimizer=self.optimizer, metrics=['accuracy']) 120 | self.model.summary() 121 | self.model.fit( 122 | x_train, x_train, 123 | validation_data=(x_test, x_test), 124 | epochs=self.config["epochs"], 125 | batch_size=self.config["batch_size"] 126 | ) 127 | 128 | def test(self, x_test): 129 | decoded = self.model.predict(x_test) 130 | vis = visualize_predictions(decoded, x_test) 131 | cv2.imwrite("wow.png", vis) 132 | 133 | def getNormal(self, validation): 134 | errors = [] 135 | for sample in validation: 136 | pred = self.model.predict(sample) 137 | err = MSE(pred, sample) 138 | errors.append(err) 139 | 140 | error_df = pd.DataFrame({'reconstruction_error':errors}) 141 | error_df.describe() 142 | 143 | fig = plt.figure() 144 | ax = fig.add_subplot(111) 145 | _ = ax.hist(error_df.reconstruction_error.values, bins=5) 146 | fig.show() 147 | 148 | 149 | if __name__ == '__main__': 150 | train, validation, shape = load_data(DATASET) 151 | print(shape) 152 | #print(x[0], y[0], shape) 153 | config = dict( 154 | conv1 = 16, 155 | conv2 = 32, 156 | conv3 = shape[0], 157 | kernel1 = (3,3), 158 | kernel2 = (3,3), 159 | kernel3 = (3,3), 160 | 161 | dense = 16, 162 | trans = shape[-1], 163 | 164 | batch_size = 32, 165 | epochs = 30, 166 | alpha = 0.1, 167 | lr = 1e-4 168 | ) 169 | m = AutoEncoder("Covid1", config, hyper=False, hyper_project="CovidDetection") 170 | m.build(shape) 171 | m.train(train, validation) 172 | m.test(validation) 173 | m.getNormal(validation) 174 | -------------------------------------------------------------------------------- /covid/processing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stderr", 10 | "output_type": "stream", 11 | "text": [ 12 | "/home/splinter/.local/lib/python3.8/site-packages/librosa/util/decorators.py:9: NumbaDeprecationWarning: An import was requested from a module that has moved location.\n", 13 | "Import requested from: 'numba.decorators', please update to use 'numba.core.decorators' or pin to Numba version 0.48.0. This alias will not be present in Numba version 0.50.0.\n", 14 | " from numba.decorators import jit as optional_jit\n", 15 | "/home/splinter/.local/lib/python3.8/site-packages/librosa/util/decorators.py:9: NumbaDeprecationWarning: An import was requested from a module that has moved location.\n", 16 | "Import of 'jit' requested from: 'numba.decorators', please update to use 'numba.core.decorators' or pin to Numba version 0.48.0. This alias will not be present in Numba version 0.50.0.\n", 17 | " from numba.decorators import jit as optional_jit\n" 18 | ] 19 | } 20 | ], 21 | "source": [ 22 | "import os\n", 23 | "import sys\n", 24 | "import librosa\n", 25 | "import numpy as np\n", 26 | "from tqdm import tqdm\n", 27 | "\n", 28 | "sys.path.insert(0, \"/home/splinter/Desktop/VoiceMed/CoughCNN/short-spectro/\")\n", 29 | "\n", 30 | "import detector\n", 31 | "\n", 32 | "cough = detector.Detector()\n" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "DATASET = \"dataset/\"\n", 42 | "WEBAPP = \"/home/splinter/Desktop/VoiceMed/qualityCheck/data/web_app/\"\n", 43 | "OUT = \"data/positive/\"" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 4, 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "Processing WebApp data\n" 56 | ] 57 | } 58 | ], 59 | "source": [ 60 | "print(\"Processing WebApp data\")\n", 61 | "for folder in os.listdir(WEBAPP):\n", 62 | " if os.path.isdir(WEBAPP+folder):\n", 63 | " for sample in os.listdir(WEBAPP+folder):\n", 64 | " #since labels are wrong no point filtering for cough in names\n", 65 | " if os.path.splitext(sample)[-1] != \".wav\" or \"covid\" not in sample:\n", 66 | " continue\n", 67 | "\n", 68 | " cough.detect(WEBAPP+folder+\"/\"+sample, OUT, False)" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 3, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stderr", 78 | "output_type": "stream", 79 | "text": [ 80 | "\r", 81 | " 0%| | 0/33 [00:00 len(signal): 43 | sample = signal[len(signal)-SAMPLE_SIZE:] 44 | end = True 45 | else: 46 | sample = signal[current:current+SAMPLE_SIZE] 47 | current += SAMPLE_SIZE 48 | 49 | mel = melspectrogram(sample) 50 | x = np.array(mel) 51 | x = x[np.newaxis, ...] 52 | x = np.expand_dims(x, axis=3) 53 | pred = np.argmax(self.model.predict(x), axis=1) 54 | predictions.append(pred) 55 | pieces.append(sample) 56 | 57 | for i in range(len(predictions)): 58 | if predictions[i][0] == 0: 59 | librosa.output.write_wav(self.out + str(i) + os.path.split(audio)[1], pieces[i], sr=SR) 60 | 61 | if visual: 62 | end = '\033[0m' 63 | green = '\033[92m' 64 | length = 50 65 | each = "|" * (length // len(predictions)) 66 | output = "" 67 | for p in predictions: 68 | if p[0] == 0: 69 | output += green + each + end 70 | else: 71 | output += each 72 | 73 | print(output) 74 | else: 75 | return pieces, predictions 76 | 77 | 78 | if __name__ == '__main__': 79 | 80 | parser = argparse.ArgumentParser(description="Classify where the cough is in a file and split it up") 81 | parser.add_argument("file", metavar="f", type=str, help="Path to the audio file, must be wav") 82 | args = parser.parse_args() 83 | 84 | try: 85 | os.system("mkdir detected/") 86 | except: 87 | pass 88 | 89 | d = Detector("model.json", "model.h5") 90 | d.detect(args.file, "detected/", visual=True) 91 | -------------------------------------------------------------------------------- /short-spectro/model.py: -------------------------------------------------------------------------------- 1 | import os 2 | import wandb 3 | import datetime 4 | import numpy as np 5 | import tensorflow as tf 6 | import tensorflow.keras as keras 7 | from wandb.keras import WandbCallback 8 | from tensorflow.keras.regularizers import l2 9 | from tensorflow.keras.utils import to_categorical 10 | from sklearn.model_selection import train_test_split 11 | from sklearn.metrics import precision_score, f1_score, recall_score 12 | from tensorflow.keras.layers import Conv2D, MaxPooling2D, BatchNormalization, Flatten, Dense, Dropout, LeakyReLU, SpatialDropout2D, GlobalAveragePooling2D 13 | 14 | 15 | DATASET = "dataset.npy" 16 | global model 17 | 18 | def load_data(f, s=False): 19 | data = np.load(f, allow_pickle=True) 20 | x = [] 21 | y = [] 22 | 23 | for sample in data: 24 | x.append(sample[0]) 25 | y.append(to_categorical(sample[1], num_classes=2)) 26 | 27 | x = np.array(x) 28 | y = np.array(y) 29 | 30 | shape = (x.shape[1], x.shape[2], 1) 31 | 32 | x = x.reshape(x.shape[0], shape[0], shape[1], shape[2]) 33 | 34 | if s: 35 | return x, y, shape 36 | 37 | #x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25) 38 | x_train, x_val, y_train, y_val = train_test_split(x, y, test_size=0.25) 39 | 40 | return x_train, y_train, x_val, y_val, shape 41 | 42 | class ExtraCallBack(tf.keras.callbacks.Callback): 43 | def on_epoch_end(self, epoch, logs=None): 44 | acc = model.test(model.x_extra, model.y_extra, extra=True) 45 | try: 46 | wandb.log({'real_acc': acc}) 47 | except: 48 | pass 49 | #print("Evaluating over our own dataset, accuracy: "+str(acc)) 50 | 51 | class Model(object): 52 | def __init__(self, name, config, hyper=False, hyper_project="", extra=None): 53 | self.name = name 54 | self.config = config 55 | self.x_extra = extra[0] 56 | self.y_extra = extra[1] 57 | 58 | if hyper: 59 | wandb.init(config=config, project=hyper_project) 60 | wandb.run.save() 61 | self.callback = WandbCallback(data_type="image", validation_data=extra) 62 | try: 63 | os.system("mkdir sweep/"+wandb.run.name) 64 | except: 65 | pass 66 | else: 67 | log_dir = "logs/fit/"+datetime.datetime.now().strftime("%Y%m%d-%H%M%S") 68 | self.callback = keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1) 69 | 70 | self.extra_callback = ExtraCallBack() 71 | 72 | def build(self, input_shape): 73 | self.model = keras.Sequential([ 74 | Conv2D(self.config["conv1"], self.config["kernel1"], kernel_regularizer=l2(self.config["l2_rate"]), input_shape=input_shape), 75 | LeakyReLU(alpha=self.config["alpha"]), 76 | BatchNormalization(), 77 | 78 | SpatialDropout2D(self.config["drop1"]), 79 | Conv2D(self.config["conv2"], self.config["kernel2"], kernel_regularizer=l2(self.config["l2_rate"])), 80 | LeakyReLU(alpha=self.config["alpha"]), 81 | BatchNormalization(), 82 | 83 | MaxPooling2D(self.config["pool1"], padding='same'), 84 | 85 | SpatialDropout2D(self.config["drop1"]), 86 | Conv2D(self.config["conv3"], self.config["kernel3"], kernel_regularizer=l2(self.config["l2_rate"])), 87 | LeakyReLU(alpha=self.config["alpha"]), 88 | BatchNormalization(), 89 | 90 | SpatialDropout2D(self.config["drop2"]), 91 | Conv2D(self.config["conv4"], self.config["kernel4"], kernel_regularizer=l2(self.config["l2_rate"])), 92 | LeakyReLU(alpha=self.config["alpha"]), 93 | BatchNormalization(), 94 | 95 | GlobalAveragePooling2D(), 96 | 97 | Dense(2, activation='softmax') 98 | ]) 99 | 100 | def train(self, x_train, y_train, validation): 101 | self.optimizer = keras.optimizers.Adam( 102 | learning_rate=self.config["lr"], 103 | beta_1=self.config["beta_1"], 104 | beta_2=self.config["beta_2"] 105 | ) 106 | self.model.compile( 107 | optimizer=self.optimizer, 108 | loss="categorical_crossentropy", 109 | metrics=['accuracy'] 110 | ) 111 | 112 | self.model.summary() 113 | 114 | self.model.fit( 115 | x_train, 116 | y_train, 117 | validation_data=validation, 118 | batch_size=self.config["batch_size"], 119 | epochs=self.config["epochs"], 120 | callbacks=[self.callback, self.extra_callback] 121 | ) 122 | 123 | def test(self, x_test, y_test, extra=True): 124 | test_err, test_acc = self.model.evaluate(x_test, y_test, verbose=0) 125 | 126 | """# predict probabilities for test set 127 | yhat_probs = self.model.predict(x_test, verbose=0) 128 | # predict crisp classes for test set 129 | yhat_classes = self.model.predict_classes(x_test, verbose=0) 130 | precision = precision_score(y_test, yhat_classes) 131 | print('Precision: %f' % precision) 132 | # recall: tp / (tp + fn) 133 | recall = recall_score(y_test, yhat_classes) 134 | print('Recall: %f' % recall) 135 | # f1: 2 tp / (2 tp + fp + fn) 136 | f1 = f1_score(y_test, yhat_classes) 137 | print('F1 score: %f' % f1)""" 138 | 139 | if extra: 140 | return test_acc 141 | else: 142 | print("Accuracy on testing data: "+str(test_acc)) 143 | 144 | def save(self): 145 | folder = "sweep/"+wandb.run.name+"/" 146 | with open(folder+"model.json", "w") as json_file: 147 | json_file.write(self.model.to_json()) 148 | 149 | self.model.save_weights(folder+"model.h5") 150 | print("Saved model '"+self.name+"-"+wandb.run.name+"' to disk") 151 | 152 | 153 | if __name__ == '__main__': 154 | should_train = True 155 | 156 | if should_train: 157 | x_train, y_train, x_val, y_val, shape = load_data(DATASET) 158 | x_extra, y_extra, _ = load_data("test.npy", s=True) 159 | 160 | config = dict( 161 | conv1 = 32, 162 | kernel1 = (3,3), 163 | drop1 = 0.07, 164 | 165 | conv2 = 32, 166 | kernel2 = (3,3), 167 | 168 | pool1 = (2,2), 169 | 170 | conv3 = 64, 171 | kernel3 = (3,3), 172 | 173 | drop2 = 0.14, 174 | 175 | conv4 = 64, 176 | kernel4 = (3,3), 177 | 178 | batch_size = 128, 179 | epochs = 40, 180 | 181 | lr = 1e-4, 182 | beta_1 = 0.99, 183 | beta_2 = 0.999, 184 | l2_rate = 0.001, 185 | 186 | alpha = 0.1 187 | ) 188 | 189 | model = Model("Spectro3", config, hyper=True, hyper_project="WOW", extra=(x_extra, y_extra)) 190 | model.build(shape) 191 | model.train(x_train, y_train, (x_val, y_val)) 192 | model.save() 193 | 194 | else: 195 | pass 196 | -------------------------------------------------------------------------------- /short-spectro/processing.py: -------------------------------------------------------------------------------- 1 | import os 2 | import librosa 3 | import numpy as np 4 | import pandas as pd 5 | from tqdm import tqdm 6 | import librosa.display 7 | import matplotlib.pyplot as plt 8 | from speechpy.processing import cmvn 9 | 10 | SR = 44000 11 | N_FFT = 2048 12 | HOP_LENGTH = 512 13 | N_MELS = 64 14 | SILENCE = 0.0018 15 | SAMPLE_LENGTH = 32/86 #s 16 | SAMPLE_SIZE = int(np.ceil(SR*SAMPLE_LENGTH)) 17 | NOISE_RATIO = 0.25 18 | 19 | LABELS = ["cough", "not"] 20 | 21 | AUGMENT = "noise/" 22 | noises = [] 23 | 24 | def envelope(signal, rate, thresh): 25 | mask = [] 26 | y = pd.Series(signal).apply(np.abs) 27 | # Create aggregated mean 28 | y_mean = y.rolling(window=int(rate/10), min_periods=1, center=True).mean() 29 | for m in y_mean: 30 | mask.append(m > thresh) 31 | 32 | return mask 33 | 34 | def load_audio(path): 35 | signal, rate = librosa.load(path, sr=SR) 36 | mask = envelope(signal, rate, SILENCE) 37 | signal = signal[mask] 38 | 39 | return signal 40 | 41 | def melspectrogram(signal): 42 | signal = librosa.util.normalize(signal) 43 | spectro = librosa.feature.melspectrogram( 44 | signal, 45 | sr=SR, 46 | n_mels=N_MELS, 47 | n_fft=N_FFT 48 | ) 49 | spectro = librosa.power_to_db(spectro) 50 | spectro = spectro.astype(np.float32) 51 | return spectro 52 | 53 | def load_noises(n=2): 54 | ns = [] 55 | ids = [] 56 | for _ in range(n): 57 | while True: 58 | i = np.random.choice(len(noises)) 59 | if i in ids: 60 | continue 61 | ids.append(i) 62 | noise, _ = librosa.load(noises[i], sr=SR) 63 | if len(noise) < SAMPLE_SIZE: 64 | continue 65 | ns.append(noise) 66 | break 67 | 68 | return ns 69 | 70 | def augment(sample, ns): 71 | augmented = [] 72 | for noise in ns: 73 | gap = len(noise)-len(sample) 74 | point = 0 75 | if gap > 0: 76 | point = np.random.randint(low=0, high=len(noise)-len(sample)) 77 | noise = noise[point:point+len(sample)] 78 | final = [] 79 | for f in range(len(sample)): 80 | n = noise[f]*NOISE_RATIO 81 | final.append(sample[f]+n) 82 | 83 | augmented.append(final) 84 | 85 | return augmented 86 | 87 | def process(audio, aug=False): 88 | signal = load_audio(audio) 89 | 90 | if len(signal) < SAMPLE_SIZE: 91 | return [] 92 | 93 | current = 0 94 | end = False 95 | features = [] 96 | 97 | if aug: 98 | ns = load_noises() 99 | 100 | while not end: 101 | if current+SAMPLE_SIZE > len(signal): 102 | sample = signal[len(signal)-SAMPLE_SIZE:] 103 | end = True 104 | else: 105 | sample = signal[current:current+SAMPLE_SIZE] 106 | current += SAMPLE_SIZE 107 | 108 | features.append(melspectrogram(sample)) 109 | 110 | if aug: 111 | signals = augment(sample, ns) 112 | for s in signals: 113 | features.append(melspectrogram(s)) 114 | 115 | return features 116 | 117 | def generate_dataset(folder, aug=False): 118 | data = [] #contains [mel, label] 119 | for i, label in enumerate(LABELS): 120 | print("Processing: "+label) 121 | for audio in tqdm(os.listdir(folder+label)): 122 | if os.path.splitext(audio)[-1] != ".wav": 123 | continue 124 | 125 | features = process(folder+label+"/"+audio, aug=aug and i == 0) 126 | for feat in features: 127 | data.append([feat, i]) 128 | 129 | return data 130 | 131 | if __name__ == '__main__': 132 | for audio in os.listdir(AUGMENT): 133 | if os.path.splitext(audio)[-1] != ".wav": 134 | continue 135 | 136 | noises.append(AUGMENT+audio) 137 | 138 | DATA_FOLDER = "dataset/" 139 | TEST_FOLDER = "test/" 140 | 141 | data = generate_dataset(DATA_FOLDER, True) 142 | 143 | #extra = generate_dataset(EXTRA_FOLDER) 144 | #data += extra 145 | np.random.shuffle(data) 146 | np.save("dataset.npy", data) 147 | 148 | test = generate_dataset(TEST_FOLDER) 149 | np.save("test.npy", test) 150 | -------------------------------------------------------------------------------- /spectro/detector.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import librosa 4 | import argparse 5 | import numpy as np 6 | import tensorflow.keras as keras 7 | from processing import load_audio, SAMPLE_SIZE, melspectrogram, SR 8 | 9 | class Detector(object): 10 | def __init__(self, m="model.json", w="model.h5"): 11 | self.m = m 12 | self.w = w 13 | 14 | json_file = open(self.m, 'r') 15 | self.model = json_file.read() 16 | json_file.close() 17 | self.model = keras.models.model_from_json(self.model) 18 | self.model.load_weights(self.w) 19 | # os.system("clear") 20 | 21 | def detect(self, audio, out, visual): 22 | self.out = out 23 | try: 24 | signal = load_audio(audio) 25 | 26 | except ValueError: 27 | if visual: 28 | print("Recording too short!") 29 | return 30 | 31 | if len(signal) < SAMPLE_SIZE: 32 | if visual: 33 | print("Recording too short!") 34 | return 35 | 36 | current = 0 37 | end = False 38 | predictions = [] 39 | pieces = [] 40 | 41 | while not end: 42 | if current+SAMPLE_SIZE > len(signal): 43 | sample = signal[len(signal)-SAMPLE_SIZE:] 44 | end = True 45 | else: 46 | sample = signal[current:current+SAMPLE_SIZE] 47 | current += SAMPLE_SIZE 48 | 49 | mel = melspectrogram(sample) 50 | x = np.array(mel) 51 | x = x[np.newaxis, ...] 52 | x = np.expand_dims(x, axis=3) 53 | pred = np.argmax(self.model.predict(x), axis=1) 54 | predictions.append(pred) 55 | pieces.append(sample) 56 | 57 | for i in range(len(predictions)): 58 | if predictions[i][0] == 0: 59 | librosa.output.write_wav(self.out + str(i) + os.path.split(audio)[1], pieces[i], sr=SR) 60 | 61 | if visual: 62 | end = '\033[0m' 63 | green = '\033[92m' 64 | length = 50 65 | each = "|" * (length // len(predictions)) 66 | output = "" 67 | for p in predictions: 68 | if p[0] == 0: 69 | output += green + each + end 70 | else: 71 | output += each 72 | 73 | print(output) 74 | else: 75 | return pieces, predictions 76 | 77 | 78 | if __name__ == '__main__': 79 | 80 | parser = argparse.ArgumentParser(description="Classify where the cough is in a file and split it up") 81 | parser.add_argument("file", metavar="f", type=str, help="Path to the audio file, must be wav") 82 | args = parser.parse_args() 83 | 84 | try: 85 | os.system("mkdir detected/") 86 | except: 87 | pass 88 | 89 | d = Detector("model.json", "model.h5") 90 | d.detect(args.file, "detected/", visual=True) 91 | -------------------------------------------------------------------------------- /spectro/model.py: -------------------------------------------------------------------------------- 1 | import os 2 | import wandb 3 | import datetime 4 | import numpy as np 5 | import tensorflow as tf 6 | import tensorflow.keras as keras 7 | from wandb.keras import WandbCallback 8 | from tensorflow.keras.regularizers import l2 9 | from tensorflow.keras.utils import to_categorical 10 | from sklearn.model_selection import train_test_split 11 | from sklearn.metrics import precision_score, f1_score, recall_score 12 | from tensorflow.keras.layers import Conv2D, MaxPooling2D, BatchNormalization, Flatten, Dense, Dropout, LeakyReLU, SpatialDropout2D, GlobalAveragePooling2D 13 | 14 | 15 | DATASET = "dataset.npy" 16 | global model 17 | 18 | def load_data(f, s=False): 19 | data = np.load(f, allow_pickle=True) 20 | x = [] 21 | y = [] 22 | 23 | for sample in data: 24 | x.append(sample[0]) 25 | y.append(to_categorical(sample[1], num_classes=2)) 26 | 27 | x = np.array(x) 28 | y = np.array(y) 29 | 30 | shape = (x.shape[1], x.shape[2], 1) 31 | 32 | x = x.reshape(x.shape[0], shape[0], shape[1], shape[2]) 33 | 34 | if s: 35 | return x, y, shape 36 | 37 | #x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25) 38 | x_train, x_val, y_train, y_val = train_test_split(x, y, test_size=0.25) 39 | 40 | return x_train, y_train, x_val, y_val, shape 41 | 42 | class ExtraCallBack(tf.keras.callbacks.Callback): 43 | def on_epoch_end(self, epoch, logs=None): 44 | acc = model.test(model.x_extra, model.y_extra, extra=True) 45 | try: 46 | wandb.log({'real_acc': acc}) 47 | except: 48 | pass 49 | #print("Evaluating over our own dataset, accuracy: "+str(acc)) 50 | 51 | class Model(object): 52 | def __init__(self, name, config, hyper=False, hyper_project="", extra=None): 53 | self.name = name 54 | self.config = config 55 | self.x_extra = extra[0] 56 | self.y_extra = extra[1] 57 | 58 | if hyper: 59 | wandb.init(config=config, project=hyper_project) 60 | wandb.run.save() 61 | self.callback = WandbCallback(data_type="image", validation_data=extra) 62 | try: 63 | os.system("mkdir sweep/"+wandb.run.name) 64 | except: 65 | pass 66 | else: 67 | log_dir = "logs/fit/"+datetime.datetime.now().strftime("%Y%m%d-%H%M%S") 68 | self.callback = keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1) 69 | 70 | self.extra_callback = ExtraCallBack() 71 | 72 | def build(self, input_shape): 73 | self.model = keras.Sequential([ 74 | Conv2D(self.config["conv1"], self.config["kernel1"], kernel_regularizer=l2(self.config["l2_rate"]), input_shape=input_shape), 75 | LeakyReLU(alpha=self.config["alpha"]), 76 | BatchNormalization(), 77 | 78 | SpatialDropout2D(self.config["drop1"]), 79 | Conv2D(self.config["conv2"], self.config["kernel2"], kernel_regularizer=l2(self.config["l2_rate"])), 80 | LeakyReLU(alpha=self.config["alpha"]), 81 | BatchNormalization(), 82 | 83 | MaxPooling2D(self.config["pool1"], padding='same'), 84 | 85 | SpatialDropout2D(self.config["drop1"]), 86 | Conv2D(self.config["conv3"], self.config["kernel3"], kernel_regularizer=l2(self.config["l2_rate"])), 87 | LeakyReLU(alpha=self.config["alpha"]), 88 | BatchNormalization(), 89 | 90 | SpatialDropout2D(self.config["drop2"]), 91 | Conv2D(self.config["conv4"], self.config["kernel4"], kernel_regularizer=l2(self.config["l2_rate"])), 92 | LeakyReLU(alpha=self.config["alpha"]), 93 | BatchNormalization(), 94 | 95 | GlobalAveragePooling2D(), 96 | 97 | Dense(2, activation='softmax') 98 | ]) 99 | 100 | def train(self, x_train, y_train, validation): 101 | self.optimizer = keras.optimizers.Adam( 102 | learning_rate=self.config["lr"], 103 | beta_1=self.config["beta_1"], 104 | beta_2=self.config["beta_2"] 105 | ) 106 | self.model.compile( 107 | optimizer=self.optimizer, 108 | loss="categorical_crossentropy", 109 | metrics=['accuracy'] 110 | ) 111 | 112 | self.model.summary() 113 | 114 | self.model.fit( 115 | x_train, 116 | y_train, 117 | validation_data=validation, 118 | batch_size=self.config["batch_size"], 119 | epochs=self.config["epochs"], 120 | callbacks=[self.callback, self.extra_callback] 121 | ) 122 | 123 | def test(self, x_test, y_test, extra=True): 124 | test_err, test_acc = self.model.evaluate(x_test, y_test, verbose=0) 125 | 126 | """# predict probabilities for test set 127 | yhat_probs = self.model.predict(x_test, verbose=0) 128 | # predict crisp classes for test set 129 | yhat_classes = self.model.predict_classes(x_test, verbose=0) 130 | precision = precision_score(y_test, yhat_classes) 131 | print('Precision: %f' % precision) 132 | # recall: tp / (tp + fn) 133 | recall = recall_score(y_test, yhat_classes) 134 | print('Recall: %f' % recall) 135 | # f1: 2 tp / (2 tp + fp + fn) 136 | f1 = f1_score(y_test, yhat_classes) 137 | print('F1 score: %f' % f1)""" 138 | 139 | if extra: 140 | return test_acc 141 | else: 142 | print("Accuracy on testing data: "+str(test_acc)) 143 | 144 | def save(self): 145 | folder = "sweep/"+wandb.run.name+"/" 146 | with open(folder+"model.json", "w") as json_file: 147 | json_file.write(self.model.to_json()) 148 | 149 | self.model.save_weights(folder+"model.h5") 150 | print("Saved model '"+self.name+"-"+wandb.run.name+"' to disk") 151 | 152 | 153 | if __name__ == '__main__': 154 | should_train = True 155 | 156 | if should_train: 157 | x_train, y_train, x_val, y_val, shape = load_data(DATASET) 158 | x_extra, y_extra, _ = load_data("test.npy", s=True) 159 | 160 | config = dict( 161 | conv1 = 32, 162 | kernel1 = (3,3), 163 | drop1 = 0.07, 164 | 165 | conv2 = 32, 166 | kernel2 = (3,3), 167 | 168 | pool1 = (2,2), 169 | 170 | conv3 = 64, 171 | kernel3 = (3,3), 172 | 173 | drop2 = 0.14, 174 | 175 | conv4 = 64, 176 | kernel4 = (3,3), 177 | 178 | batch_size = 128, 179 | epochs = 70, 180 | 181 | lr = 1e-4, 182 | beta_1 = 0.99, 183 | beta_2 = 0.999, 184 | l2_rate = 0.001, 185 | 186 | alpha = 0.1 187 | ) 188 | 189 | model = Model("Spectro2", config, hyper=True, hyper_project="CoughDetectTests", extra=(x_extra, y_extra)) 190 | model.build(shape) 191 | model.train(x_train, y_train, (x_val, y_val)) 192 | model.save() 193 | 194 | else: 195 | pass 196 | -------------------------------------------------------------------------------- /spectro/processing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 48, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import os\n", 10 | "import librosa\n", 11 | "import numpy as np\n", 12 | "import pandas as pd\n", 13 | "from tqdm import tqdm\n", 14 | "import librosa.display\n", 15 | "import matplotlib.pyplot as plt\n", 16 | "from speechpy.processing import cmvn " 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 72, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "SR = 44000\n", 26 | "N_FFT = 2048\n", 27 | "HOP_LENGTH = 512\n", 28 | "N_MELS = 60\n", 29 | "SILENCE = 0.0018\n", 30 | "SAMPLE_LENGTH = 0.5 #s\n", 31 | "SAMPLE_SIZE = int(np.ceil(SR*SAMPLE_LENGTH))\n", 32 | "NOISE_RATIO = 0.25\n", 33 | "\n", 34 | "LABELS = [\"cough\", \"not\"]" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 59, 40 | "metadata": {}, 41 | "outputs": [ 42 | { 43 | "data": { 44 | "image/png": "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\n", 45 | "text/plain": [ 46 | "
" 47 | ] 48 | }, 49 | "metadata": { 50 | "needs_background": "light" 51 | }, 52 | "output_type": "display_data" 53 | }, 54 | { 55 | "data": { 56 | "image/png": "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\n", 57 | "text/plain": [ 58 | "
" 59 | ] 60 | }, 61 | "metadata": { 62 | "needs_background": "light" 63 | }, 64 | "output_type": "display_data" 65 | } 66 | ], 67 | "source": [ 68 | "def envelope(signal, rate, thresh):\n", 69 | " mask = []\n", 70 | " y = pd.Series(signal).apply(np.abs)\n", 71 | " # Create aggregated mean\n", 72 | " y_mean = y.rolling(window=int(rate/10), min_periods=1, center=True).mean()\n", 73 | " for m in y_mean:\n", 74 | " mask.append(m > thresh)\n", 75 | "\n", 76 | " return mask\n", 77 | "\n", 78 | "def load_audio(path):\n", 79 | " signal, rate = librosa.load(path, sr=SR)\n", 80 | " mask = envelope(signal, rate, SILENCE)\n", 81 | " signal = signal[mask]\n", 82 | " \n", 83 | " return signal\n", 84 | "\n", 85 | "def melspectrogram(signal):\n", 86 | " signal = librosa.util.normalize(signal)\n", 87 | " spectro = librosa.feature.melspectrogram(\n", 88 | " signal,\n", 89 | " sr=SR,\n", 90 | " n_mels=N_MELS,\n", 91 | " n_fft=N_FFT\n", 92 | " )\n", 93 | " spectro = librosa.power_to_db(spectro)\n", 94 | " spectro = spectro.astype(np.float32)\n", 95 | " return spectro\n", 96 | "\n", 97 | "audios = [\n", 98 | " load_audio(\"test/cough/1586532810683_cough_suspect_f_49_57022fb6-10cc-4dce-91fd-88bc0559076e.wav\"),\n", 99 | " load_audio(\"test/cough/1586538036621_cough_healthy_m_51_11e04705-602e-49be-8857-9e7d52dea3f5.wav\")\n", 100 | "]\n", 101 | "\n", 102 | "mels = []\n", 103 | "\n", 104 | "for a in audios:\n", 105 | " mel = melspectrogram(a)\n", 106 | " mels.append(mel)\n", 107 | " plt.figure(figsize=(12, 4))\n", 108 | " librosa.display.specshow(mel, x_axis='time', y_axis='mel')\n", 109 | " plt.colorbar(format='%+2.0f dB');\n", 110 | " plt.title('MEL-Scaled Spectrogram')\n", 111 | " plt.tight_layout()\n", 112 | " plt.show()" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 64, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "AUGMENT = \"noise/\"\n", 122 | "noises = []\n", 123 | "\n", 124 | "for audio in os.listdir(AUGMENT):\n", 125 | " if os.path.splitext(audio)[-1] != \".wav\":\n", 126 | " continue\n", 127 | " \n", 128 | " noises.append(AUGMENT+audio) " 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 77, 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "def load_noises(n=2):\n", 138 | " ns = []\n", 139 | " ids = []\n", 140 | " for _ in range(n):\n", 141 | " while True:\n", 142 | " i = np.random.choice(len(noises))\n", 143 | " if i in ids:\n", 144 | " continue\n", 145 | " ids.append(i)\n", 146 | " noise, _ = librosa.load(noises[i], sr=SR)\n", 147 | " if len(noise) < SAMPLE_SIZE:\n", 148 | " continue\n", 149 | " ns.append(noise)\n", 150 | " break\n", 151 | " \n", 152 | " return ns\n", 153 | "\n", 154 | "def augment(sample, ns):\n", 155 | " augmented = []\n", 156 | " for noise in ns:\n", 157 | " gap = len(noise)-len(sample)\n", 158 | " point = 0\n", 159 | " if gap > 0:\n", 160 | " point = np.random.randint(low=0, high=len(noise)-len(sample))\n", 161 | " noise = noise[point:point+len(sample)]\n", 162 | " final = []\n", 163 | " for f in range(len(sample)):\n", 164 | " n = noise[f]*NOISE_RATIO\n", 165 | " final.append(sample[f]+n)\n", 166 | " \n", 167 | " augmented.append(final)\n", 168 | " \n", 169 | " return augmented\n", 170 | "\n", 171 | "def process(audio, aug=False):\n", 172 | " signal = load_audio(audio)\n", 173 | " \n", 174 | " if len(signal) < SAMPLE_SIZE:\n", 175 | " return []\n", 176 | " \n", 177 | " current = 0\n", 178 | " end = False\n", 179 | " features = []\n", 180 | " \n", 181 | " if aug:\n", 182 | " ns = load_noises()\n", 183 | " \n", 184 | " while not end:\n", 185 | " if current+SAMPLE_SIZE > len(signal):\n", 186 | " sample = signal[len(signal)-SAMPLE_SIZE:]\n", 187 | " end = True\n", 188 | " else:\n", 189 | " sample = signal[current:current+SAMPLE_SIZE]\n", 190 | " current += SAMPLE_SIZE\n", 191 | " \n", 192 | " features.append(melspectrogram(sample))\n", 193 | " \n", 194 | " if aug:\n", 195 | " signals = augment(sample, ns)\n", 196 | " for s in signals:\n", 197 | " features.append(melspectrogram(s))\n", 198 | " \n", 199 | " return features\n", 200 | " \n", 201 | "def generate_dataset(folder, aug=False):\n", 202 | " data = [] #contains [mel, label]\n", 203 | " for i, label in enumerate(LABELS):\n", 204 | " print(\"Processing: \"+label)\n", 205 | " for audio in tqdm(os.listdir(folder+label)):\n", 206 | " if os.path.splitext(audio)[-1] != \".wav\":\n", 207 | " continue\n", 208 | " \n", 209 | " features = process(folder+label+\"/\"+audio, aug=aug and i == 0)\n", 210 | " for feat in features:\n", 211 | " data.append([feat, i])\n", 212 | " \n", 213 | " return data" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": 78, 219 | "metadata": {}, 220 | "outputs": [ 221 | { 222 | "name": "stderr", 223 | "output_type": "stream", 224 | "text": [ 225 | "\r", 226 | " 0%| | 0/36 [00:00 thresh) 31 | 32 | return mask 33 | 34 | def load_audio(path): 35 | signal, rate = librosa.load(path, sr=SR) 36 | mask = envelope(signal, rate, SILENCE) 37 | signal = signal[mask] 38 | 39 | return signal 40 | 41 | def melspectrogram(signal): 42 | signal = librosa.util.normalize(signal) 43 | spectro = librosa.feature.melspectrogram( 44 | signal, 45 | sr=SR, 46 | n_mels=N_MELS, 47 | n_fft=N_FFT 48 | ) 49 | spectro = librosa.power_to_db(spectro) 50 | spectro = spectro.astype(np.float32) 51 | return spectro 52 | 53 | def load_noises(n=2): 54 | ns = [] 55 | ids = [] 56 | for _ in range(n): 57 | while True: 58 | i = np.random.choice(len(noises)) 59 | if i in ids: 60 | continue 61 | ids.append(i) 62 | noise, _ = librosa.load(noises[i], sr=SR) 63 | if len(noise) < SAMPLE_SIZE: 64 | continue 65 | ns.append(noise) 66 | break 67 | 68 | return ns 69 | 70 | def augment(sample, ns): 71 | augmented = [] 72 | for noise in ns: 73 | gap = len(noise)-len(sample) 74 | point = 0 75 | if gap > 0: 76 | point = np.random.randint(low=0, high=len(noise)-len(sample)) 77 | noise = noise[point:point+len(sample)] 78 | final = [] 79 | for f in range(len(sample)): 80 | n = noise[f]*NOISE_RATIO 81 | final.append(sample[f]+n) 82 | 83 | augmented.append(final) 84 | 85 | return augmented 86 | 87 | def process(audio, aug=False): 88 | signal = load_audio(audio) 89 | 90 | if len(signal) < SAMPLE_SIZE: 91 | return [] 92 | 93 | current = 0 94 | end = False 95 | features = [] 96 | 97 | if aug: 98 | ns = load_noises() 99 | 100 | while not end: 101 | if current+SAMPLE_SIZE > len(signal): 102 | sample = signal[len(signal)-SAMPLE_SIZE:] 103 | end = True 104 | else: 105 | sample = signal[current:current+SAMPLE_SIZE] 106 | current += SAMPLE_SIZE 107 | 108 | features.append(melspectrogram(sample)) 109 | 110 | if aug: 111 | signals = augment(sample, ns) 112 | for s in signals: 113 | features.append(melspectrogram(s)) 114 | 115 | return features 116 | 117 | def generate_dataset(folder, aug=False): 118 | data = [] #contains [mel, label] 119 | for i, label in enumerate(LABELS): 120 | print("Processing: "+label) 121 | for audio in tqdm(os.listdir(folder+label)): 122 | if os.path.splitext(audio)[-1] != ".wav": 123 | continue 124 | 125 | features = process(folder+label+"/"+audio, aug=aug and i == 0) 126 | for feat in features: 127 | data.append([feat, i]) 128 | 129 | return data 130 | 131 | if __name__ == '__main__': 132 | for audio in os.listdir(AUGMENT): 133 | if os.path.splitext(audio)[-1] != ".wav": 134 | continue 135 | 136 | noises.append(AUGMENT+audio) 137 | 138 | DATA_FOLDER = "dataset/" 139 | TEST_FOLDER = "test/" 140 | 141 | data = generate_dataset(DATA_FOLDER, True) 142 | 143 | #extra = generate_dataset(EXTRA_FOLDER) 144 | #data += extra 145 | np.random.shuffle(data) 146 | np.save("dataset.npy", data) 147 | 148 | test = generate_dataset(TEST_FOLDER) 149 | np.save("test.npy", test) 150 | -------------------------------------------------------------------------------- /spectro/sweep.yaml: -------------------------------------------------------------------------------- 1 | program: model.py 2 | method: random 3 | command: 4 | - ${env} 5 | - python3 6 | - ${program} 7 | - ${args} 8 | metric: 9 | name: loss 10 | goal: minimize 11 | parameters: 12 | lr: 13 | distribution: uniform 14 | min: 0.000001 15 | max: 0.1 16 | --------------------------------------------------------------------------------