{"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":"!pip install tensorflow==2.0.0-alpha0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport sys\nimport gc\nimport psutil\n\nfrom os.path import isdir, join\nfrom time import time\nfrom pathlib import Path\nimport pandas as pd\n\nimport numpy as np\nfrom scipy import signal\nfrom scipy.io import wavfile\nfrom sklearn.decomposition import PCA\n\nfrom IPython.display import display\n\nprint('Finish Import Utilities libary')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from time import time\nimport gc\nimport tensorflow as tf\nfrom random import randint\nfrom tensorflow import keras\nfrom tensorflow.keras import activations, models\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Conv2D, BatchNormalization, MaxPool2D, Dense, Input, Dropout, Flatten\nfrom tensorflow.python.keras.callbacks import TensorBoard, ReduceLROnPlateau\nprint('Finish import model library')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_data(path):\n    '''Get data from the path and create a pandas dataframe to store it,\n    the function will return a pandas dataframe with fpath(file path) and label'''\n    \n    label_list = []\n    fname = []\n    valid_label = ['yes', 'no', 'up', 'down', 'left', 'right', 'on', 'off', 'stop', 'go', 'silence']\n\n    # Get every audio files path and label\n    files = [(str(file), file.parts[-2]) for file in Path(path).glob(\"**/*.wav\") if file]\n    file_len = len(files)\n    print('Finish getting data')\n    \n    # Valid label name\n    for file in files:\n        if file[1] == '_background_noise_':\n            label = 'silence'\n        elif file[1] not in valid_label:\n            label = 'unknown'\n        else:\n            label = file[1]\n            \n        # Normal version training set, but only got 0.6 points in kaggle\n        label_list.append(label)\n        fname.append(file[0])\n\n        # Try to only train valid-label data\n#         if label in valid_label:\n#             label_list.append(label)\n#             fname.append(file[0])\n        \n    data = pd.DataFrame({'fpath': fname, 'label': label_list})\n    \n    print('Finish appending array')\n    return data\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get train data set\ntrain_df = get_data('./train/audio')\n\n# Seperate train set and validation set\ntrain_set = train_df.sample(frac=0.8, replace=False, random_state=42)\nvalid_set = train_df.loc[set(train_df.index) - set(train_set.index)]\n\ny_train = np.array(train_set.label)\ny_train = pd.get_dummies(y_train, dtype=bool)\nx_train = np.array(train_set.fpath)\n\ny_valid = np.array(valid_set.label)\ny_valid = pd.get_dummies(y_valid, dtype=bool)\nx_valid = np.array(valid_set.fpath)\n\ndisplay(train_set.info())\ndisplay(valid_set.info())\ngc.collect()\n\nprint(len(x_valid), len(y_valid))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_model(shape):\n    '''Create a keras functional model'''\n    \n    inputlayer = Input(shape=shape)\n    \n    # Nornal model\n    nclass = 12\n    \n    # Experience model\n#     nclass = 11\n    \n    norm_input = BatchNormalization()(inputlayer)\n    model = Conv2D(16, kernel_size=2, padding='same', activation=activations.relu)(norm_input)\n    model = Conv2D(16, kernel_size=2, padding='same', activation=activations.relu)(model)\n    model = MaxPool2D(pool_size=(2, 2))(model)\n    model = Dropout(rate=0.2)(model)\n    model = Conv2D(32, kernel_size=3, padding='same', activation=activations.relu)(model)\n    model = Conv2D(32, kernel_size=3, padding='same', activation=activations.relu)(model)\n    model = MaxPool2D(pool_size=(2, 2))(model)\n    model = Dropout(rate=0.2)(model)\n    model = Conv2D(64, kernel_size=3, padding='same', activation=activations.relu)(model)\n    model = MaxPool2D(pool_size=(2, 2))(model)\n    model = Dropout(rate=0.2)(model)\n    model = Flatten()(model) \n\n    dense_1 = BatchNormalization()(Dense(128, activation=activations.relu)(model))\n    dense_1 = BatchNormalization()(Dense(128, activation=activations.relu)(dense_1))\n    dense_1 = Dense(nclass, activation=activations.softmax)(dense_1)\n\n    model = models.Model(inputs=inputlayer, outputs=dense_1)\n    model.compile(optimizer='adam', loss=tf.losses.binary_crossentropy, metrics=['accuracy'])\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"shape = (99, 161, 1)\nmodel = get_model(shape)\n# model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def log_specgram(audio, sample_rate, window_size=20,\n                 step_size=10, eps=1e-10):\n    nperseg = int(round(window_size * sample_rate / 1e3))\n    noverlap = int(round(step_size * sample_rate / 1e3))\n    freqs, times, spec = signal.spectrogram(audio,\n                                    fs=sample_rate,\n                                    window='hann',\n                                    nperseg=nperseg,\n                                    noverlap=noverlap,\n                                    detrend=False)\n    return freqs, times, np.log(spec.T.astype(np.float32) + eps)\n\ndef get_spectrogram(paths, y=None, nsamples=16000):\n    wavs = [wavfile.read(path)[1] for path in paths]\n    \n    data = []\n    label = []\n    for wav in wavs:\n        try:\n            if wav.size < 16000:\n                d = np.pad(wav, (nsamples - wav.size, 0), mode='constant')\n            else:\n                d = wav[0:nsamples]\n            data.append(d)\n        except:\n            pass\n\n    spg = [log_specgram(d, nsamples)[2] for d in data]\n    spg = [s.reshape(99, 161, -1) for s in spg]\n    return (spg)\n\n# Need to fix if wavfile.read() fail, the length of [spgs] would not be the same as y\ndef batch_generator(x, y, batch_size=16):\n    # Return a random image from X, y\n    ylen = len(y)\n    loopcount = ylen // batch_size\n    while True:\n        i = randint(0,loopcount)\n        x_list = x[i * batch_size:(i + 1) * batch_size]\n        spgs = get_spectrogram(x_list)\n        \n        yield np.concatenate([spgs]), y[i * batch_size:(i + 1) * batch_size]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train the model\nbatch_size = 10\nepochs = 12\npath = './tensorboard/keras_' + str(time())\nhistory = model.fit_generator(\n    generator=batch_generator(x_train, y_train, batch_size),\n    validation_data=batch_generator(x_valid, y_valid, batch_size),\n    epochs=epochs,\n    steps_per_epoch=y_train.shape[0] // batch_size,\n    validation_steps=y_valid.shape[0] // batch_size,\n#     callbacks=[TensorBoard(log_dir=path)],\n    verbose=1,\n)\n\n# Save the model\n# path = './model/model_' + str(time()) + '.h5'\n# model.save(path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''log_specgram() and get_spectrogram() defined before '''\n\ndef get_prediction(path, model, pred_list, nsamples=16000):\n    '''Predict the test files and return a pandas dataframe with submission format'''\n    prediction = []\n    file_name = []\n    \n    # Get every files path and file's label in test directory\n    file_names = [(str(file), file.parts[-2]) for file in Path(path).glob(\"**/*.wav\") if file]\n    i, file_len = 0, len(file_names)\n    \n    start_time = time()\n    for name in file_names[0:None]:\n        try:\n            spg = get_spectrogram([name[0]])\n            pred = model.predict(np.array(spg))\n\n            # Add threshold to prediction\n            if (pred.max() > 0.5):    \n                pred = np.argmax(pred, axis=1)\n                pred = pred_list[pred[0]]\n            else:\n                pred = 'unknown'\n        except:\n            pred = 'unknown'\n        prediction.append(pred)\n        file_name.append(name[0].split('/')[-1])\n\n        # Fancy progress bar\n        i = i + 1\n        if i % 100 == 0:\n            print(\"%d/%d, time: %.4f s\" % (i, file_len, time() - start_time), end='\\r')\n    print('\\nFinish prediction')\n\n    submission = pd.DataFrame({'fname': file_name, 'label': prediction})\n    return submission\nsubmission = get_prediction('./test/audio/', model1, pred_list)\nsubmission.to_csv('submission1.csv', index=False)\nprint('Saved csv file')\nprint(pd.value_counts(submission.label.values))","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}