{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"collapsed":true},"cell_type":"markdown","source":"# Import Libraries"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# To store data\nimport pandas as pd\n\n# To do linear algebra\nimport numpy as np\n\n# To create plots\nimport matplotlib.pyplot as plt\n\n# To create nicer plots\nimport seaborn as sns\n\n# To search directories\nimport os\n\n# To get progression bars\nfrom tqdm import tqdm\n\n# To play sound in notebooks\nimport IPython.display as ipd\n\n# To create models\nfrom keras.models import Sequential\nfrom keras.layers import Conv1D, Dense, Dropout, MaxPool1D, Flatten","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"be9db931baf53aa42a5334dfb0fd399b8e8674d4"},"cell_type":"markdown","source":"# Load Data"},{"metadata":{"trusted":true,"_uuid":"5c6561acd827798fc578ef6e2b7be8bcf1dd23bd","_kg_hide-input":true},"cell_type":"code","source":"# Load sample and ids\ntrain = pd.read_csv('../input/train.csv')\nsample_submission = pd.read_csv('../input/sample_submission.csv')\n\n# Path to files\ntrain_path = '../input/audio_train/'\ntest_path = '../input/audio_test/'\n\nprint('Each file in the csv-submission has three possible concatenated labels.')\nprint('Sample Submission Shape:\\t{}'.format(sample_submission.shape))\nsample_submission.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"26de815cfe2039bd5b7a881185461d12b0daad85","_kg_hide-input":true},"cell_type":"code","source":"print('Each file has a label and a marker weather it has been verified by a human.')\nprint('Train Shape:\\t{}'.format(train.shape))\ntrain_df = pd.read_csv('../input/train.csv')\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"544f951e3194580a78d23164db960045f221c0b9","_kg_hide-input":true},"cell_type":"code","source":"train_files = os.listdir(train_path)\nprint('Number Of Train Files:\\t{}'.format(len(train_files)))\n\ntest_files = os.listdir(test_path)\nprint('Number Of Test Files:\\t{}'.format(len(test_files)))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"05827cad433ba1d3993bdbc9e5f936c673429389"},"cell_type":"markdown","source":"# Label Exploration"},{"metadata":{"trusted":true,"_uuid":"700ebfc8f56c908524d617bb08da31b4944cfce7","_kg_hide-input":true},"cell_type":"code","source":"title = 'Distribution Of Labels'\nlabels_grouped = train_df.groupby(['label', 'manually_verified']).count().rename(columns={'fname':'Verified'})\nlabels_grouped = labels_grouped.unstack().reindex(labels_grouped.unstack().sum(axis=1).sort_values(ascending=False).index)\nlabels_grouped.columns = ['Unverified', 'Verified']\nlabels_grouped.plot(kind='barh', stacked=True, title=title, figsize=(16,9))\nplt.xlabel('Count')\nplt.ylabel('Label')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4583e9e0bb6fb92e04f414cfca7580153c29bf41"},"cell_type":"markdown","source":"# Single Example Exploration"},{"metadata":{"trusted":true,"_uuid":"0f73b0ab0a764672911a980038582188c265332c","_kg_hide-input":true},"cell_type":"code","source":"from scipy.io import wavfile\nfname, label, verified = train_df.sample(1).values[0]\nrate, data = wavfile.read(train_path+fname)\nprint(label)\nprint('Sampling Rate:\\t{}'.format(rate))\nprint('Total Frames:\\t{}'.format(data.shape[0]))\nprint(data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"412e292ea440b9e5d7826da6e30f9ef32b14107b","_kg_hide-input":true},"cell_type":"code","source":"n = 3\nfig, axarr = plt.subplots(n, 1, figsize=(16, 2*n))\nfor i, (fname, label) in enumerate(train_df.sample(n)[['fname', 'label']].values):\n    rate, data = wavfile.read(train_path+fname)\n    axarr[i].plot(data)\n    axarr[i].set_title(label)\nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"d6d49a4c268500e3b1b434e6c53eeb4df952dbdc"},"cell_type":"code","source":"print('Sound:\\t{}'.format(train[train['fname']==fname]['label'].values[0]))\nipd.Audio(train_path+fname)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"08dde10ec26a9cce0f3c7e11a4a0496da0075b15"},"cell_type":"markdown","source":"# File Lengths"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"36b30b52df19d938e9e5aa90f5b0a43439c18dba"},"cell_type":"code","source":"file_length = []\nfor file in tqdm([train_path+file for file in os.listdir(train_path)] + [test_path+file for file in os.listdir(test_path)]):\n    rate, data = wavfile.read(file)\n    file_length.append([len(data)/rate, rate, file])\nlength_df = pd.DataFrame(file_length, columns=['length', 'rate', 'file'])\nlength_df['data'] = 'test'\nlength_df.loc[:train_df.shape[0], 'data'] = 'train'\n\nfig, axarr = plt.subplots(1, 2, figsize=(16,4))\nsns.distplot(length_df[length_df['data']=='train']['length'], ax=axarr[0])\naxarr[0].set_title('Train: Distribution File-Lengths')\naxarr[0].set_xlabel('Seconds')\nsns.distplot(length_df[length_df['data']=='test']['length'], ax=axarr[1])\naxarr[1].set_title('Test: Distribution File-Lengths')\naxarr[1].set_xlabel('Seconds')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0ef61d8d4639fd9240dda8298258570a05846bc6","_kg_hide-input":true},"cell_type":"code","source":"train_df['duration'] = length_df[length_df['data']=='train']['length']\n\nplt.figure(figsize=(16,4))\nsns.violinplot(data=train_df, y='duration', x='label')\nplt.title('File-Lengths Per Label')\nplt.xlabel('Label')\nplt.ylabel('Seconds')\nplt.xticks(rotation=90)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0b828732a0cd28ea47bd10c6cacf03c960046f76"},"cell_type":"markdown","source":"# Create Model"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"39e6540f3091c4b285c5d9df62ec6f5641d5a2b4"},"cell_type":"code","source":"# Setup variables\ninput_length = 44100*10 # First 10 seconds for classification\nn_classes = train['label'].unique().shape[0]\n\n# Create model\nmodel = Sequential()\nmodel.add(Conv1D(filters=4, kernel_size=16, activation='relu', padding='same', input_shape=(input_length, 1)))\nmodel.add(MaxPool1D(pool_size=5))\nmodel.add(Dropout(rate=0.1))\nmodel.add(Conv1D(filters=6, kernel_size=16, activation='relu', padding='same'))\nmodel.add(MaxPool1D(pool_size=5))\nmodel.add(Dropout(rate=0.1))\nmodel.add(Conv1D(filters=9, kernel_size=16, activation='relu', padding='same'))\nmodel.add(MaxPool1D(pool_size=5))\nmodel.add(Dropout(rate=0.1))\nmodel.add(Conv1D(filters=14, kernel_size=16, activation='relu', padding='same'))\nmodel.add(MaxPool1D(pool_size=5))\nmodel.add(Dropout(rate=0.1))\nmodel.add(Conv1D(filters=21, kernel_size=16, activation='relu', padding='same'))\nmodel.add(MaxPool1D(pool_size=5))\nmodel.add(Dropout(rate=0.1))\nmodel.add(Conv1D(filters=31, kernel_size=16, activation='relu', padding='same'))\nmodel.add(MaxPool1D(pool_size=5))\nmodel.add(Dropout(rate=0.1))\nmodel.add(Conv1D(filters=46, kernel_size=16, activation='relu', padding='same'))\nmodel.add(MaxPool1D(pool_size=5))\nmodel.add(Dropout(rate=0.1))\nmodel.add(Flatten())\nmodel.add(Dense(units=100, activation='relu'))\nmodel.add(Dense(units=n_classes, activation='softmax'))\n\n# Compile model\nmodel.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"b508269bad4c6f8a0f82fabed30a29a2a22d1a5b"},"cell_type":"code","source":"# Map files to label\nfile_label_dict = {fname:label for fname, label in train[['fname', 'label']].values}\n\nexample_file = '6a446a35.wav'\nprint('File Label \"{}\":\\n{}'.format(example_file, file_label_dict[example_file]))\n\n\n# Create vector encoded labels\nlabelEncoder = {}\nfor i, label in enumerate(train['label'].unique()):\n    label_array = np.zeros(n_classes)\n    label_array[i] = 1\n    labelEncoder[label] = label_array\n\nexample_label = 'Cello'\nprint('\\nEncoded Label \"{}\":\\n{}'.format(example_label, labelEncoder[example_label]))\n\n# Remap predictions to label\nprediction_to_label = {np.argmax(array):label for label, array in labelEncoder.items()}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4a7829608df17d348b6ba08a9e0937a0d162c6cb","_kg_hide-input":true,"collapsed":true},"cell_type":"code","source":"# Define batch generator to yield random data batches\ndef batchGenerator(files, batch_size):\n    # Generate infinite random batches\n    while True:\n        # Get random files\n        batch_files = np.random.choice(files, batch_size, replace=False)\n\n        # Get labels and data\n        batch_label = []\n        batch_data = []\n        # Combine batch\n        for file in batch_files:\n            # Get label and data\n            label = file_label_dict[file]\n            rate, data = wavfile.read(train_path+file)\n            # Trim data to get uniform length\n            data_uniform_length = np.zeros(input_length)\n            minimum = min(input_length, data.shape[0])\n            data_uniform_length[:minimum] = data[:minimum]\n            # Encode label\n            encoded_label = labelEncoder[label]\n            # Create label and data batch\n            batch_label.append(encoded_label)\n            batch_data.append(data_uniform_length)\n        # Format batches\n        batch_label = np.array(batch_label)\n        batch_data = np.array(batch_data).reshape(-1, input_length, 1)\n\n        # Batch normalisation\n        minimum, maximum = batch_data.min().astype(float), batch_data.max().astype(float)\n        batch_data = (batch_data - minimum) / (maximum - minimum)\n\n        # Yield batches for training\n        yield batch_data, batch_label","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"9a666ee4f60ecfec8d6b8d0f1e46fc7c3e3328b2","collapsed":true},"cell_type":"code","source":"# Create random mask to split files in train and validation set\ntrain_val_split_mask  = np.zeros(train.shape[0], dtype=bool)\ntrain_val_split_mask[:8500] = True\nnp.random.shuffle(train_val_split_mask)\n\n# Get train and validation files\ntrain_files = train['fname'][train_val_split_mask]\nval_files = train['fname'][~train_val_split_mask]\n\n\n# Specify train and validation generators\nbatch_size = 50\ntrain_generator = batchGenerator(train_files, batch_size=batch_size)\nval_generator = batchGenerator(val_files, batch_size=50)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e0c7e373858c35c93ac34da7f6ef57c3861be45b"},"cell_type":"markdown","source":"# Train Model"},{"metadata":{"trusted":true,"_uuid":"8c84817a36998ef22efd4a2a0cfa2453dd721589","_kg_hide-input":true},"cell_type":"code","source":"model.fit_generator(generator=train_generator, validation_data=val_generator, validation_steps=10, epochs=20, steps_per_epoch=train.shape[0]//batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f77f7f03e04949e37db15076f9ceb3aec8458820","_kg_hide-input":true},"cell_type":"code","source":"prediction = []\ntest_data = []\ntest_files = os.listdir(test_path)\nfor fname in tqdm(test_files):\n    rate, data = wavfile.read(test_path + fname)\n    # Trim data to get uniform length\n    data_uniform_length = np.zeros(input_length)\n    minimum = min(input_length, data.shape[0])\n    data_uniform_length[:minimum] = data[:minimum]\n    test_data.append(data_uniform_length)\n    \n    if len(test_data)==50:\n        test_data = np.array(test_data).reshape(-1, input_length, 1)\n        prediction.extend(model.predict(test_data))\n        test_data = []\ntest_data = np.array(test_data).reshape(-1, input_length, 1)\nprediction.extend(model.predict(test_data))\n\n#prediction = model.predict(test_data)\nprediction = np.array(prediction)\nbest_prediction = np.flip(prediction.argsort(), axis=1)[:, :3]\n\nfinal_prediction = []\nfor entry in best_prediction:\n    best_file_predictions = []\n    for label in entry:\n        best_file_predictions.append(prediction_to_label[label])\n    final_prediction.append(' '.join(best_file_predictions))\nfinal_prediction[:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2587875dc6ccac1cb22127cfca1f3bfe7a76779a","_kg_hide-input":true},"cell_type":"code","source":"submission = pd.DataFrame()\nsubmission['fname'] = test_files\nsubmission['label'] = final_prediction\nsubmission.to_csv('Submission.csv', index=False)\nsubmission.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"9d6710798a162f95a8355d0f61eeeb686b46e341"},"cell_type":"code","source":"","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}