{"cells": [{"source": ["Based on tensorflow starter code from https://www.kaggle.com/alexozerin/end-to-end-baseline-tf-estimator-lb-0-72"], "cell_type": "markdown", "metadata": {"_cell_guid": "c2883459-a9c2-45f1-9df1-1986a0488f07", "_uuid": "8e9ff83b354d98b475b9924ddeb81984c7f1f02f"}}, {"source": ["import os\n", "import re\n", "from glob import glob\n", "import pandas as pd\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "679e0d3e-646d-4e96-9eb0-b362d8c6e51f", "collapsed": true, "_uuid": "0d05e5ce89af3e25d1c1fb244d021a1cfa1a058c", "ExecuteTime": {"end_time": "2017-11-17T09:03:29.196238Z", "start_time": "2017-11-17T09:03:28.644004Z"}}}, {"source": ["POSSIBLE_LABELS = 'yes no up down left right on off stop go silence unknown'.split()\n", "id2name = {i: name for i, name in enumerate(POSSIBLE_LABELS)}\n", "name2id = {name: i for i, name in id2name.items()}\n", "len(id2name)"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "8ab00801-08b9-44d3-a063-32e82dbf8f58", "collapsed": true, "_uuid": "53c19941676690454dd4b91109976b6c59cb7a40", "ExecuteTime": {"end_time": "2017-11-17T09:03:29.210749Z", "start_time": "2017-11-17T09:03:29.19832Z"}}}, {"source": ["def load_data(data_dir):\n", "    \"\"\" Return 2 lists of tuples:\n", "    [(class_id, user_id, path), ...] for train\n", "    [(class_id, user_id, path), ...] for validation\n", "    \"\"\"\n", "    # Just a simple regexp for paths with three groups:\n", "    # prefix, label, user_id\n", "    pattern = re.compile(\"(.+\\/)?(\\w+)\\/([^_]+)_.+wav\")\n", "    all_files = glob(os.path.join(data_dir, 'train/audio/*/*wav'))\n", "\n", "    with open(os.path.join(data_dir, 'train/validation_list.txt'), 'r') as fin:\n", "        validation_files = fin.readlines()\n", "    valset = set()\n", "    for entry in validation_files:\n", "        r = re.match(pattern, entry)\n", "        if r:\n", "            valset.add(r.group(3))\n", "\n", "    possible = set(POSSIBLE_LABELS)\n", "    train, val = [], []\n", "    for entry in all_files:\n", "        r = re.match(pattern, entry)\n", "        if r:\n", "            label, uid = r.group(2), r.group(3)\n", "            if label == '_background_noise_':\n", "                label = 'silence'\n", "            if label not in possible:\n", "                label = 'unknown'\n", "\n", "            label_id = name2id[label]\n", "\n", "            sample = (label, label_id, uid, entry)\n", "            if uid in valset:\n", "                val.append(sample)\n", "            else:\n", "                train.append(sample)\n", "\n", "    print('There are {} train and {} val samples'.format(len(train), len(val)))\n", "    \n", "    columns_list = ['label', 'label_id', 'user_id', 'wav_file']\n", "    \n", "    train_df = pd.DataFrame(train, columns = columns_list)\n", "    valid_df = pd.DataFrame(val, columns = columns_list)\n", "    \n", "    return train_df, valid_df"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "8d7ebf53-700b-4c06-b5c2-ccf9ed5f27e0", "collapsed": true, "_uuid": "133424c750b26df37900f9cebcfd2f2fb803cb8b", "ExecuteTime": {"end_time": "2017-11-17T09:03:29.325023Z", "start_time": "2017-11-17T09:03:29.215137Z"}}}, {"source": ["train_df, valid_df = load_data('./data/')"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "27b5bff1-e5f8-409d-ab51-46e698342eb1", "collapsed": true, "_uuid": "ad204124a777e6677dcca8aac32d34de8e0cfc5d", "ExecuteTime": {"end_time": "2017-11-17T09:03:30.166379Z", "start_time": "2017-11-17T09:03:29.327228Z"}}}, {"source": ["train_df.head()"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "3fc0b536-7c1f-41de-8266-94221d53d7dd", "collapsed": true, "_uuid": "5f5434462366b087b747875c071a02a49a0509c0", "ExecuteTime": {"end_time": "2017-11-17T09:03:30.195961Z", "start_time": "2017-11-17T09:03:30.171067Z"}}}, {"source": ["train_df.label.value_counts()"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "2e846e85-3902-4f06-95c5-e83a25a074d2", "collapsed": true, "_uuid": "44caca4db5dd9a17807b602a1bc1f79c2a8b3450", "ExecuteTime": {"end_time": "2017-11-17T09:03:30.297759Z", "start_time": "2017-11-17T09:03:30.197702Z"}}}, {"source": ["silence_files = train_df[train_df.label == 'silence']\n", "train_df      = train_df[train_df.label != 'silence']"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "65ea1b22-6563-4879-a622-f45d8818e465", "collapsed": true, "_uuid": "4ebfe2201a69fa3bbfd83eff917645ea4a0a0d22", "ExecuteTime": {"end_time": "2017-11-17T09:03:30.448259Z", "start_time": "2017-11-17T09:03:30.299457Z"}}}, {"source": ["from scipy.io import wavfile"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "bd5dd795-f697-463f-820c-e20703df0856", "collapsed": true, "_uuid": "785bd06c8f570cff089fd72b469b4dcfaf37502d", "ExecuteTime": {"end_time": "2017-11-17T09:03:30.702013Z", "start_time": "2017-11-17T09:03:30.450046Z"}}}, {"source": ["def read_wav_file(fname):\n", "    _, wav = wavfile.read(fname)\n", "    wav = wav.astype(np.float32) / np.iinfo(np.int16).max\n", "    return wav"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "f57505d4-c817-4806-9c04-5e0615bec690", "collapsed": true, "_uuid": "1eb04c7b9b2aac48481ef66b14d67ef20e3b2156", "ExecuteTime": {"end_time": "2017-11-17T09:03:30.708917Z", "start_time": "2017-11-17T09:03:30.703891Z"}}}, {"source": ["silence_data = np.concatenate([read_wav_file(x) for x in silence_files.wav_file.values])"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "b3dec272-d1e1-464b-8085-d0348f160a4e", "collapsed": true, "_uuid": "397e1c89a92c605f59715544324f372ca030b477", "ExecuteTime": {"end_time": "2017-11-17T09:03:30.877178Z", "start_time": "2017-11-17T09:03:30.711856Z"}}}, {"source": ["from scipy.signal import stft"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "fbfb2ae5-7228-4b92-bae1-9c859f2e07fe", "collapsed": true, "_uuid": "3ac12db0f462320ee1dd56c1b600017910b53f03", "ExecuteTime": {"end_time": "2017-11-17T09:03:31.104194Z", "start_time": "2017-11-17T09:03:30.87932Z"}}}, {"source": ["def process_wav_file(fname):\n", "    wav = read_wav_file(fname)\n", "    \n", "    L = 16000  # 1 sec\n", "    \n", "    if len(wav) > L:\n", "        i = np.random.randint(0, len(wav) - L)\n", "        wav = wav[i:(i+L)]\n", "    elif len(wav) < L:\n", "        rem_len = L - len(wav)\n", "        i = np.random.randint(0, len(silence_data) - rem_len)\n", "        silence_part = silence_data[i:(i+L)]\n", "        j = np.random.randint(0, rem_len)\n", "        silence_part_left  = silence_part[0:j]\n", "        silence_part_right = silence_part[j:rem_len]\n", "        wav = np.concatenate([silence_part_left, wav, silence_part_right])\n", "    \n", "    specgram = stft(wav, 16000, nperseg = 400, noverlap = 240, nfft = 512, padded = False, boundary = None)\n", "    phase = np.angle(specgram[2]) / np.pi\n", "    amp = np.log1p(np.abs(specgram[2]))\n", "    \n", "    return np.stack([phase, amp], axis = 2)"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "9e32f039-712e-4f1d-9173-ed9804d7771f", "collapsed": true, "_uuid": "36562e906f4fd6739b55582239ab55d947a80766", "ExecuteTime": {"end_time": "2017-11-17T09:03:31.144688Z", "start_time": "2017-11-17T09:03:31.105987Z"}}}, {"source": ["import random\n", "import tensorflow as tf\n", "from tensorflow.python.keras.models import Model\n", "from tensorflow.python.keras.layers import Input, Conv2D, MaxPooling2D, Activation, BatchNormalization, GlobalAveragePooling2D, GlobalMaxPool2D, concatenate, Dense, Dropout\n", "from tensorflow.python.keras.optimizers import RMSprop\n", "from tensorflow.python.keras.utils import to_categorical"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "d4d0b322-0aea-4c37-962b-8ed5a44e68b0", "collapsed": true, "_uuid": "ce4df9dec0990c4e38ef21108166e97b1a77e565", "ExecuteTime": {"end_time": "2017-11-17T09:03:32.481032Z", "start_time": "2017-11-17T09:03:31.1464Z"}}}, {"source": ["def train_generator(train_batch_size):\n", "    while True:\n", "        this_train = train_df.groupby('label_id').apply(lambda x: x.sample(n = 2000))\n", "        shuffled_ids = random.sample(range(this_train.shape[0]), this_train.shape[0])\n", "        for start in range(0, len(shuffled_ids), train_batch_size):\n", "            x_batch = []\n", "            y_batch = []\n", "            end = min(start + train_batch_size, len(shuffled_ids))\n", "            i_train_batch = shuffled_ids[start:end]\n", "            for i in i_train_batch:\n", "                x_batch.append(process_wav_file(this_train.wav_file.values[i]))\n", "                y_batch.append(this_train.label_id.values[i])\n", "            x_batch = np.array(x_batch)\n", "            y_batch = to_categorical(y_batch, num_classes = len(POSSIBLE_LABELS))\n", "            yield x_batch, y_batch"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "144c6e60-8a83-437d-8b8a-ea065af90923", "collapsed": true, "_uuid": "22e0e6c718171167089fb6df36d3dc43a1029992", "ExecuteTime": {"end_time": "2017-11-17T09:03:32.519795Z", "start_time": "2017-11-17T09:03:32.483881Z"}}}, {"source": ["def valid_generator(val_batch_size):\n", "    while True:\n", "        ids = list(range(valid_df.shape[0]))\n", "        for start in range(0, len(ids), val_batch_size):\n", "            x_batch = []\n", "            y_batch = []\n", "            end = min(start + val_batch_size, len(ids))\n", "            i_val_batch = ids[start:end]\n", "            for i in i_val_batch:\n", "                x_batch.append(process_wav_file(valid_df.wav_file.values[i]))\n", "                y_batch.append(valid_df.label_id.values[i])\n", "            x_batch = np.array(x_batch)\n", "            y_batch = to_categorical(y_batch, num_classes = len(POSSIBLE_LABELS))\n", "            yield x_batch, y_batch"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "59a13393-9bc3-4b27-abe2-9c78b3c32ead", "collapsed": true, "_uuid": "6f9a8fbf6e352b1c77b9c22dddf1c5d69382bd5b", "ExecuteTime": {"end_time": "2017-11-17T09:03:32.624289Z", "start_time": "2017-11-17T09:03:32.521828Z"}}}, {"source": ["x_in = Input(shape = (257,98,2))\n", "x = BatchNormalization()(x_in)\n", "for i in range(4):\n", "    x = Conv2D(16*(2 ** i), (3,3))(x)\n", "    x = Activation('elu')(x)\n", "    x = BatchNormalization()(x)\n", "    x = MaxPooling2D((2,2))(x)\n", "x = Conv2D(128, (1,1))(x)\n", "x_branch_1 = GlobalAveragePooling2D()(x)\n", "x_branch_2 = GlobalMaxPool2D()(x)\n", "x = concatenate([x_branch_1, x_branch_2])\n", "x = Dense(256, activation = 'relu')(x)\n", "x = Dropout(0.5)(x)\n", "x = Dense(len(POSSIBLE_LABELS), activation = 'soft')(x)\n", "model = Model(inputs = x_in, outputs = x)\n", "model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])\n", "model.summary()"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "0e13c01e-5662-4679-9b31-bf9347080ae5", "collapsed": true, "_uuid": "a17b3ea5c15c781260f3473f37dd0d36a932a565", "ExecuteTime": {"end_time": "2017-11-17T09:03:33.180074Z", "start_time": "2017-11-17T09:03:32.625939Z"}}}, {"source": ["from keras_tqdm import TQDMNotebookCallback\n", "from tensorflow.python.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "fe93068e-e948-4086-beb3-4f16733da01a", "collapsed": true, "_uuid": "917c6ad351d05ee67a3fcddc5c43a321c866d61a", "ExecuteTime": {"end_time": "2017-11-17T09:03:33.295244Z", "start_time": "2017-11-17T09:03:33.181863Z"}}}, {"source": ["callbacks = [EarlyStopping(monitor='val_loss',\n", "                           patience=5,\n", "                           verbose=1,\n", "                           min_delta=0.01,\n", "                           mode='min'),\n", "             ReduceLROnPlateau(monitor='val_loss',\n", "                               factor=0.1,\n", "                               patience=3,\n", "                               verbose=1,\n", "                               epsilon=0.01,\n", "                               mode='min'),\n", "             ModelCheckpoint(monitor='val_loss',\n", "                             filepath='weights/starter.hdf5',\n", "                             save_best_only=True,\n", "                             save_weights_only=True,\n", "                             mode='min'),\n", "             TQDMNotebookCallback()]"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "d6614a4b-d640-41fe-b0ba-ed766728866f", "collapsed": true, "_uuid": "52c2547fcd8a0bf62edbccfbf5958fe5fe42d9e9", "ExecuteTime": {"end_time": "2017-11-17T09:03:33.351284Z", "start_time": "2017-11-17T09:03:33.297768Z"}}}, {"source": ["history = model.fit_generator(generator=train_generator(64),\n", "                              steps_per_epoch=344,\n", "                              epochs=20,\n", "                              verbose=2,\n", "                              callbacks=callbacks,\n", "                              validation_data=valid_generator(64),\n", "                              validation_steps=int(np.ceil(valid_df.shape[0]/64)))"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "5f3d1b09-500f-410e-820a-8eaab24b6ebb", "collapsed": true, "_uuid": "528ec66a0a6caca952273ab916e609625839b19e", "ExecuteTime": {"end_time": "2017-11-17T09:42:31.48233Z", "start_time": "2017-11-17T09:03:33.355603Z"}}}, {"source": ["model.load_weights('./weights/starter.hdf5')"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "0c99ba3b-e8ca-40cb-8d29-2b0e89a385c7", "collapsed": true, "_uuid": "429139ca4f71487c6cfe3e8dfbb6a659eb9bb9c8", "ExecuteTime": {"end_time": "2017-11-17T10:24:59.198625Z", "start_time": "2017-11-17T10:24:59.081762Z"}}}, {"source": ["test_paths = glob(os.path.join('./data/', 'test/audio/*wav'))"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "72f27090-c0d1-4d0b-8027-34c915429a79", "collapsed": true, "_uuid": "1007977fccadecdae582ec5d8d52dd3c4c3010aa", "ExecuteTime": {"end_time": "2017-11-17T10:28:14.451612Z", "start_time": "2017-11-17T10:28:13.307142Z"}}}, {"source": ["def test_generator(test_batch_size):\n", "    while True:\n", "        for start in range(0, len(test_paths), test_batch_size):\n", "            x_batch = []\n", "            end = min(start + test_batch_size, len(test_paths))\n", "            this_paths = test_paths[start:end]\n", "            for x in this_paths:\n", "                x_batch.append(process_wav_file(x))\n", "            x_batch = np.array(x_batch)\n", "            yield x_batch"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "c6d9b369-9979-4bcd-8540-4653e6544f84", "collapsed": true, "_uuid": "6a0bb3c22b7b5c43db0ec5673333ab3de8f08724", "ExecuteTime": {"end_time": "2017-11-17T10:32:14.882322Z", "start_time": "2017-11-17T10:32:14.863617Z"}}}, {"source": ["predictions = model.predict_generator(test_generator(64), int(np.ceil(len(test_paths)/64)))"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "1fb8aed4-de12-43c5-84bf-b803e3d640fa", "collapsed": true, "_uuid": "631a38cb0013e5772f6987854145ad76ecf6c430", "ExecuteTime": {"start_time": "2017-11-17T10:32:45.947Z"}}}, {"source": ["classes = np.argmax(predictions, axis=1)"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "b1cdab5c-9816-4690-87d8-de2c97cf0e7d", "collapsed": true, "_uuid": "24eb7e512eace4567494e0a8e356a826f4283c4d", "ExecuteTime": {"end_time": "2017-11-17T11:30:44.236246Z", "start_time": "2017-11-17T11:30:44.21858Z"}}}, {"source": ["# last batch will contain padding, so remove duplicates\n", "submission = dict()\n", "for i in range(len(test_paths)):\n", "    fname, label = os.path.basename(test_paths[i]), id2name[classes[i]]\n", "    submission[fname] = label"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "1da523cf-fdbf-4ab1-9300-0147155aa247", "collapsed": true, "_uuid": "f25d4e626202aa115bd0460f4de8d07f9727c83e", "ExecuteTime": {"end_time": "2017-11-17T11:31:11.212517Z", "start_time": "2017-11-17T11:31:10.786357Z"}}}, {"source": ["with open('starter_submission.csv', 'w') as fout:\n", "    fout.write('fname,label\\n')\n", "    for fname, label in submission.items():\n", "        fout.write('{},{}\\n'.format(fname, label))"], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "9a95d147-3f4b-4386-8597-5fa60be43542", "collapsed": true, "_uuid": "bdf63bce43a0525a02ac18ca3f90aeba06ce6e99", "ExecuteTime": {"end_time": "2017-11-17T11:32:05.154527Z", "start_time": "2017-11-17T11:32:04.983371Z"}}}, {"source": [], "outputs": [], "cell_type": "code", "execution_count": null, "metadata": {"_cell_guid": "8bea6850-15c6-44e7-bdb4-9555ad196f85", "collapsed": true, "_uuid": "555315ef622793711ff5643928dac874c8cb0ed2"}}], "nbformat_minor": 1, "nbformat": 4, "metadata": {"kernelspec": {"name": "python3", "language": "python", "display_name": "Python 3"}, "toc": {"toc_cell": false, "nav_menu": {}, "number_sections": true, "toc_section_display": "block", "sideBar": true, "toc_window_display": true, "skip_h1_title": false, "toc_position": {}}, "anaconda-cloud": {}, "language_info": {"version": "3.6.3", "mimetype": "text/x-python", "file_extension": ".py", "pygments_lexer": "ipython3", "codemirror_mode": {"version": 3, "name": "ipython"}, "nbconvert_exporter": "python", "name": "python"}}}