{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"#Imports\nimport keras\nimport pickle\nimport random\nimport scipy\n\nfrom keras.models import load_model\n\nfrom pathlib import Path\nfrom subprocess import check_output\n\nfrom scipy import signal\nfrom scipy.io import wavfile\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bdad9aee59862a55e07b356a983672a66c3d3919"},"cell_type":"code","source":"with open('../input/speech-recognition-data-processing/SavedPartition.pickle', 'rb') as handle:\n    partition = pickle.load(handle)\nwith open('../input/speech-recognition-data-processing/SavedLabels.pickle', 'rb') as handle:\n    labels = pickle.load(handle)\nprint(\"loaded data.\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3e3cb80614e4769b8157eabae9c88ca2253137d4"},"cell_type":"code","source":"# Data Augmenting\ndef bandpass(sample_rate, samples):\n    \n    fs = sample_rate  # Sample frequency (Hz)\n    fl = 180.0  # Human voices range from 85 Hz to 255 Hz\n    fh = 240.0\n    Q = 1.0  # Quality factor\n    w0 = fl/(fs/2)  # Normalized Frequency\n    w1 = fh/(fs/2)\n    # Design notch filter\n    b, a = scipy.signal.butter(3, [w0, w1], btype='bandpass', analog=True)\n    samples = scipy.signal.lfilter(b,a,samples)*30\n\n    return sample_rate, samples","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6cb66d747eaac975206bcbbd565803c79e416bba"},"cell_type":"code","source":"train_audio_path = '../input/tensorflow-speech-recognition-challenge/train/audio'\n\ndef stft(sample_rate, samples):\n\n    eps=1e-10\n\n    frequencies, times, Zxx = signal.stft(samples, sample_rate, nperseg = sample_rate/50, noverlap = sample_rate/75)\n    \n    # silence can end up being empty files, in this case we can just return one second of zeros\n    if len(Zxx.shape) < 2:\n        return np.zeros((151,161))\n    else:\n        return np.log(np.abs(Zxx).T+eps)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"785fc878871f9e3abe31967b0bcba1b051a74708"},"cell_type":"code","source":"class DataGenerator(keras.utils.Sequence):\n    # Generates data for Keras\n    def __init__(self, list_IDs, labels, batch_size=32, dim=(151,161), x1dim=16000, x2dim=(151,161), n_channels=1,\n                 n_classes=12, shuffle=True, input_type='wav', testing=False, augment=True):\n        # Initialization\n        self.dim = dim\n        self.x1dim = x1dim\n        self.x2dim = x2dim\n        self.batch_size = batch_size\n        self.labels = labels\n        self.list_IDs = list_IDs\n        self.n_channels = n_channels\n        self.n_classes = n_classes\n        self.shuffle = shuffle\n        self.input_type = input_type\n        self.testing = testing\n        self.augment = augment\n        self.on_epoch_end()\n\n    def __len__(self):\n        # Denotes the number of batches per epoch\n        return int(np.floor(len(self.list_IDs) / self.batch_size))\n\n    def __getitem__(self, index):\n        # Generate one batch of data\n        # Generate indexes of the batch\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n\n        # Find list of IDs\n        list_IDs_temp = [self.list_IDs[k] for k in indexes]\n\n        # Generate data\n        if self.input_type == 'all':\n            X1, X2, y = self.__data_generation(list_IDs_temp)\n            if self.testing:\n                return [X1,X2]\n            else:\n                return [X1,X2], [y]\n        else:\n            X, y = self.__data_generation(list_IDs_temp)\n            \n            return X, y\n\n    def on_epoch_end(self):\n        # Updates indexes after each epoch\n        self.indexes = np.arange(len(self.list_IDs))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __data_generation(self, list_IDs_temp):\n        # Generates data containing batch_size samples # X : (n_samples, *dim, n_channels)\n        # Initialization\n        if self.input_type == 'wav':\n            X = np.empty((self.batch_size, self.dim, self.n_channels))\n        elif self.input_type == 'all':\n            X1 = np.empty((self.batch_size, self.x1dim, self.n_channels))\n            X2 = np.empty((self.batch_size, *self.x2dim, self.n_channels))\n        else:\n            X = np.empty((self.batch_size, *self.dim, self.n_channels))\n        y = np.empty((self.batch_size), dtype=int)\n\n        # Generate data\n        if self.input_type == 'wav':\n            for i, ID in enumerate(list_IDs_temp):\n                wav = wavread(ID, self.labels[ID])\n                padded = np.zeros((self.dim))\n                padded[:wav.shape[0]] = wav\n                X[i,] = padded[:, np.newaxis]\n                y[i] = self.labels[ID]\n                \n            return X, keras.utils.to_categorical(y, num_classes=self.n_classes)\n            \n        elif self.input_type == 'spectrogram':\n            for i, ID in enumerate(list_IDs_temp):\n                spect = spectrogram(ID, self.labels[ID])\n                #last = ID, self.dim, spect.shape\n\n                padded = np.zeros((self.dim))\n                padded[:spect.shape[0], :spect.shape[1]] = spect\n                X[i,] = padded[:, :, np.newaxis]\n                y[i] = self.labels[ID]\n                \n            return X, keras.utils.to_categorical(y, num_classes=self.n_classes)\n        \n        elif self.input_type == 'stft':\n            \n            for i, ID in enumerate(list_IDs_temp):\n                if self.labels[ID] == 11:\n                    path = '../input/'\n                else:\n                    path = train_audio_path + '/'\n                sample_rate, samples = wavfile.read(path + ID)\n\n                if self.augment:\n                    if random.randint(1,101) < 51:\n                        sample_rate, samples = bandpass(sample_rate, samples)\n                        \n                trans = stft(sample_rate, samples)\n                #last = ID, self.dim, spect.shape\n\n                padded = np.zeros((self.dim))\n                padded[:trans.shape[0], :trans.shape[1]] = trans\n                X[i,] = padded[:, :, np.newaxis]\n                y[i] = self.labels[ID]\n                \n            return X, keras.utils.to_categorical(y, num_classes=self.n_classes)\n        \n        elif self.input_type == 'all':\n            for i, ID in enumerate(list_IDs_temp):\n                wav = wavread(ID)\n                padded = np.zeros((self.x1dim))\n                padded[:wav.shape[0]] = wav\n                X1[i,] = padded[:, np.newaxis]\n                y[i] = self.labels[ID]\n        \n            for i, ID in enumerate(list_IDs_temp):\n                spect = spectrogram(ID)\n                padded = np.zeros((self.x2dim))\n                padded[:spect.shape[0], :spect.shape[1]] = spect\n                X2[i,] = padded[:, :, np.newaxis]        \n                \n            return X1, X2, keras.utils.to_categorical(y, num_classes=self.n_classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"64bcbe1e47936b5c491d1a61e4e6b9777a0b04d9"},"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.callbacks import LearningRateScheduler\nfrom keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D, BatchNormalization\nfrom keras.models import Model\nfrom keras.optimizers import Adam\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.utils.np_utils import to_categorical\n\n# Parameters\ntrain_params = {'dim': (151,161),\n                'batch_size': 64,\n                'n_classes':12,\n                'n_channels': 1,\n                'shuffle': True,\n                'input_type': 'stft',\n                'augment': True\n               }\nval_params = {'dim': (151,161),\n              'batch_size': 64,\n              'n_classes':12,\n              'n_channels': 1,\n              'shuffle': False,\n              'input_type': 'stft',\n              'augment': False\n             }\n\n# Generators\nstft_training_generator = DataGenerator(partition['train'], labels, **train_params)\nstft_validation_generator = DataGenerator(partition['validation'], labels, **val_params)\n\nif False:\n    # Design model\n    stft_input = keras.Input(shape=(151, 161, 1))\n    x = Conv2D(32, 3, activation='relu')(stft_input)\n    x = BatchNormalization()(x)\n    x = Conv2D(32, 3, activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Conv2D(32, 5, strides=2, padding='same', activation='relu')(x)\n    x = Dropout(0.4)(x)\n\n    x = Conv2D(64, 3, activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Conv2D(64, 3, activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Conv2D(64, 5, strides=2, padding='same', activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.4)(x)\n\n    x = Conv2D(128, 4, activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Flatten()(x)\n    #x = Dense(32, activation='relu')(x)\n    x = Dropout(0.4)(x)\n\n    stft_prediction = Dense(12, activation='softmax')(x)\n\n    stft_model = Model(stft_input, stft_prediction)\n\n    stft_model.compile(optimizer = 'adam',\n                        loss='categorical_crossentropy',\n                        metrics=[\"accuracy\"])\n\n    stft_model.summary()\n\n    stft_annealer = LearningRateScheduler(lambda x: 1e-3 * 0.97 ** x)\nelse:\n\n    stft_annealer = LearningRateScheduler(lambda x: 1e-4 * 0.98 ** x)\n    stft_model = load_model('../input/stft-model/stft_model.h5')\n    \n# Train model on dataset\nstft_history = stft_model.fit_generator(generator=stft_training_generator,\n                                          validation_data=stft_validation_generator,\n                                          steps_per_epoch=300,\n                                          epochs=30,\n                                          verbose=2,\n                                          callbacks=[stft_annealer]\n                                         )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e672106ada3580c3c0624262d49eea47612a0379"},"cell_type":"code","source":"acc = stft_history.history['acc']\nval_acc = stft_history.history['val_acc']\nloss = stft_history.history['loss']\nval_loss = stft_history.history['val_loss']\n\nepochs = range(1, len(acc) + 1)\n\nplt.plot(epochs, acc, 'bo', label='Training acc')\nplt.plot(epochs, val_acc, 'b', label='Validation acc')\nplt.title('CNN Accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('CNN Loss')\nplt.legend()\n\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bf41386be6943f02503a6168d7f0bf68a868156a"},"cell_type":"code","source":"stft_model.save('stft_model.h5')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}