From 01e67507c2ea1a1aa0a7a3d3ca53170621ecd248 Mon Sep 17 00:00:00 2001 From: Sergey Malyshevsky Date: Tue, 14 Dec 2021 11:24:58 +0300 Subject: [PATCH] homework 2 Malyshevsky --- week06/hw/malyshevsky.ipynb | 761 ++++++++++++++++++++++++++++++++++++ 1 file changed, 761 insertions(+) create mode 100644 week06/hw/malyshevsky.ipynb diff --git a/week06/hw/malyshevsky.ipynb b/week06/hw/malyshevsky.ipynb new file mode 100644 index 0000000..55c6035 --- /dev/null +++ b/week06/hw/malyshevsky.ipynb @@ -0,0 +1,761 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "spotter_malyshevskiy_sergey.ipynb", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + }, + "accelerator": "GPU", + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "60bd4ede8e804a268a295f0fd1378c83": { + "model_module": "@jupyter-widgets/output", + "model_name": "OutputModel", + "model_module_version": "1.0.0", + "state": { + "_view_name": "OutputView", + "msg_id": "", + "_dom_classes": [], + "_model_name": "OutputModel", + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA8gAAAFSCAYAAAAuMPYOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOzdeXjU1dn/8fdMlsmeTMi+syesEjYRgQqIqChqtLhUW21d2rpS+9OnoVLQaLFKW2urj2vr0selUVCkogJuiAiCgkDYQxayk4RMMpksM78/QiKRLZNMMpPweV1XLjPf+S73HDLO3N9zzn0MDofDgYiIiIiIiMgZzujuAEREREREREQ8gRJkEREREREREZQgi4iIiIiIiABKkEVEREREREQAJcgiIiIiIiIigBJkEREREREREUAJskif8Itf/IK3337b5fs6Y8OGDUydOtXl5xURERER6Sne7g5A5Ew1ZsyYtt+tViu+vr54eXkBsGjRIi699NIOn+u5557rln1FRET6Old+HgNcf/31XHrppVx11VUujVNEeoYSZBE32bJlS9vv06dP56GHHuKcc845br+mpia8vfVWFRER6Q4d/TzuK/S9QuTUNMRaxMO0DlV+5plnmDx5Mv/zP/9DdXU1t956K2effTbjx4/n1ltvpbi4uO2Y66+/njfffBOAt956i2uuuYYlS5Ywfvx4pk+fzieffNKpffPz87nuuusYM2YMP/vZz1i0aBH33ntvh17Hvn37uP766xk3bhwXX3wxq1evbnvuk08+4aKLLmLMmDFMmTKF559/HoDDhw9z6623Mm7cOCZMmMC1116L3W7vfGOKiIh0kt1u55lnnmHmzJlMnDiRu+66i6qqKgBsNhv33nsvEydOZNy4cWRkZFBeXs6f//xnNm3axOLFixkzZgyLFy8+4bnvvPNOJk+ezNixY7nuuuvYs2dP23P19fX88Y9/5LzzzmPs2LFcc8011NfXA7Bp0yauvvpqxo0bx7Rp03jrrbeA9p/t8P3ne6uhQ4fy6quvMmvWLGbNmgXAQw89xLRp00hPT+eKK65g06ZNbfs3Nzfz9NNPM3PmTMaMGcMVV1xBUVERixYt4o9//GO713Lbbbfxz3/+swstLeJZlCCLeKDy8nKqq6tZu3YtDz74IHa7nSuuuIK1a9eydu1aTCbTST90AbZu3Ur//v358ssv+cUvfkFmZiYOh8Ppfe+9915GjRrFhg0buP3221m+fHmH4m9sbOS2225j8uTJfPHFFyxYsIB7772X/fv3A5CZmcnixYvZsmULK1as4OyzzwbgxRdfJDo6mvXr17Nu3Trmz5+PwWBwpulERERc4uWXX+ajjz7ilVde4bPPPiM0NLTts/ftt9/GYrHw8ccfs2HDBhYtWoSfnx/33HMP48aN44EHHmDLli088MADJzz31KlTWbVqFevXr2fYsGHtbj4vWbKE7du389prr/HVV1/x29/+FqPRSGFhITfffDM/+clPWL9+PcuWLSMtLa3Dr+ejjz7ijTfeYOXKlQCMHDmSZcuW8dVXXzFnzhzuuusubDYb0PJ5/N577/HMM8+wefNmHn74Yfz8/Lj88stZsWJF283rw4cPs379eubMmdOpNhbxREqQRTyQ0WjkzjvvxNfXFz8/P8xmMxdccAH+/v4EBQXxy1/+ko0bN570+Li4OH784x/j5eXF5ZdfTllZGeXl5U7te+jQIbZt29YWx7hx45g+fXqH4v/222+pq6vjlltuwdfXl0mTJnHeeefx3nvvAeDt7c3evXuxWCyEhoYyfPjwtu1lZWUcOnQIHx8fxo0bpwRZRETc4rXXXuOee+4hJiYGX19fbr/9dlatWtU2RLmqqoqDBw/i5eXFiBEjCAoK6vC5r7zySoKCgvD19eWOO+4gJyeHmpoa7HY72dnZZGZmEh0djZeXF+np6fj6+rJixQrOOecc5syZg4+PD2az2akE+ZZbbiEsLAw/Pz8A5s6di9lsxtvbm5tuuomGhgYOHDgAwJtvvsldd93FgAEDMBgMpKamYjabGTVqFMHBwaxfvx6AlStXMmHCBCIiIpxoWRHPpgkIIh7IbDZjMpnaHlutVh555BE+++wzqqurAaitraW5ubmtkMixjv2g8vf3B6Curu6E1zrZvpWVlYSGhrZtA4iNjaWoqOi08ZeWlhITE4PR+P09uLi4OEpKSgB44okneOqpp3j88ccZOnQov/nNbxgzZgw///nPefLJJ7npppsAmDdvHrfccstpryciIuJqhw4d4te//nW7zzKj0UhFRQVz586luLiY+fPnc+TIES699FLuuecefHx8Tnve5uZm/vznP/P+++9z+PDhtvNXVlbS0NCAzWYjMTHxuOOKiopISkrq9OuJjY1t9/j555/nP//5D6WlpRgMBiwWC5WVlQAUFxef9FqXX34577zzDpMnT+add97hhhtu6HRMIp5IPcgiHuiHvaYvvPACBw4c4I033mDz5s28+uqrACcdNu0KkZGRVFdXY7Va27Z1JDkGiIqKori4uN384aKiIqKjowEYNWoUTz31FF988QUzZ87k7rvvBiAoKIj777+f1atX89RTT/Hiiy+23aUWERHpSTExMTz77LNs2rSp7Wfbtm1ER0fj4+PD7bffzsqVK3nttdf4+OOPWbZsWYfO++6777J69WpefPFFvv76a9asWQO0fKa33iDPz88/7rjY2Fjy8vJOeE5/f/92n9cnGjV27HeLTZs28dxzz/GXv/yFjRs3smnTJoKDg9u+V8TExJz0WpdeeimrV68mJyeHffv2MXPmzA69bpHeQgmySC9QW1uLyWQiJCSEqqoqnnzyyW6/Znx8PCNGjOBvf/sbDQ0NbNmyhbVr13bo2FGjRuHn58dzzz1HY2MjGzZsYM2aNVx00UU0NDTwzjvvUFNTg4+PD4GBgW13z9euXcvBgwdxOBwEBwfj5eWlIdYiIuIW11xzDX/5y18oLCwEWubbfvTRRwB8+eWX7Nq1i+bmZoKCgvD29m77LIuIiDhhgtuqtrYWX19fzGYzVquVpUuXtj1nNBrJyMjgkUceoaSkhObmZrZs2UJDQwOXXHIJX3zxBStXrqSpqYnKykp27twJQFpaGh9++CFWq5WDBw/yn//855Svrba2Fi8vL8LDw2lqauLJJ5/EYrG0PX/VVVfx17/+ldzcXBwOBzk5OW29yzExMYwcOZLf/va3zJo1q23ItkhfoQRZpBf46U9/is1m4+yzz2bevHlMmTKlR6772GOP8c033zBx4kT+8pe/cNFFF+Hr63va43x9fXn66af59NNPOfvss1m0aBGPPvooAwcOBGD58uVMnz6d9PR0XnvtNf70pz8BcPDgQW688UbGjBnDvHnzuOaaa9oKeImIiPSkG264genTp3PTTTcxZswYfvzjH7N161agpYf2zjvvZOzYsVx00UVMmDCBuXPnth23atUqxo8fz0MPPXTceS+77DLi4uKYMmUKF198MWeddVa75++77z6GDBnClVdeyYQJE3jsscew2+3ExcXx7LPP8uKLLzJhwgQuu+wycnJygJbvCT4+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9Y4UFbSiUp1/Nrjh9s49yHq9ioyv43D3aWDiwlTmjp4G9E0CtDutjKOnqrll7mj8PF365BzC+ty1jri5OHAsvxZAinSJHumXPchr165lzpw5REdHk5197l6iKSkpLFmyhMTERJYsWcK7777b/buOjg7WrFnDlVdeybx58/j444/7I2whhDinW64cjYuTPW9/mYXJJIVaxPDwyiuvsHHjRjZu3MisWbMwmUysWrWKp556ii1btpCQkMCLL75o6zBFHziWV4tJUYizYHn1z3UVtWptcqYi15+60s6K0H4+9hdMjgGSkoysW9dKUJAJxaSm5MBkXJzVZDcd6pPOAjUNrby//QRRQSOYmxBk9dcXfSvIx7X7fSEzyKIn+iVBnjt3LuvXr0en0533MQsWLODTTz9l48aNvP/++7z99ttkZWUB8Nlnn1FQUMDWrVv58MMP+fOf/0xRUVF/hC6EEGdxdXbglitHk1vawFW3VPR72xEhBoL09HQ0Gg0JCQkA3HzzzWzevNnGUYm+kJ5bjbPGngjd2e2dzLV6tQFn5zNvKFpS7CopyUhqajPl5U38sNvEwzeOo6ymhX9sykRRrHejUlEU/rk5iw6TiV8uikF9keRdDDy6kZ37kB0d1Dhr5LosLNcvCXJCQgIBAQEXfIyrq2v3HcTW1lba29u7f960aRM33HADarUaLy8vrrzySrkICyFsquiYjqp8X/zGZeEZWENVnYFHVzmYnSTbqqenED316KOPsmTJEp555hkaGhooLS0lMDCw+/deXl6YTCbq6qTK+1CiKAppOTWMDfXETt3zj42nzwKrVApBQSbWrWvtcbGrmFGe3HB5JAePV7J5X0GP4/q5XUdLSc+p4frLIvCVpdWDUnlh542cmgpnJk92leursNiAesds376ddevWUVBQwMqVK4mOjgY46yIcEBBAWVnZ+V7mvLy9rbdX0MfHzWqvNRzIeFlOxsxy/Tlma9dCec0ELrvja2bctKv7+KfH7NhfrcFd6/jTl8tp32s1/LDHkT8+p9BQqwIcKSpSs3KlM25usGxZv/0RAHmf9cRwHLP169cTEBBAW1sbycnJPPvss8ybN88qry3XZtsxZ7zySxuobTQwfbyu1+N7772dX51UgHOvXu+2RWMprmkhZecpJkT7MWG0T69er7JWz4dfn2RchDc3LYg5Z79neY9Zrj/H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\n", + "text/plain": "
" + }, + "metadata": {} + } + ], + "_view_module": "@jupyter-widgets/output", + "_model_module_version": "1.0.0", + "_view_count": null, + "_view_module_version": "1.0.0", + "layout": "IPY_MODEL_7fc4f45841334254a71d8dab2a14232e", + "_model_module": "@jupyter-widgets/output" + } + }, + "7fc4f45841334254a71d8dab2a14232e": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "model_module_version": "1.2.0", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + } + } + } + }, + "cells": [ + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DLqUa76aAHIg", + "outputId": "945f975b-ff9c-4e74-b689-360d63245f41" + }, + "source": [ + "!apt install sox" + ], + "execution_count": 1, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Reading package lists... Done\n", + "Building dependency tree \n", + "Reading state information... Done\n", + "The following additional packages will be installed:\n", + " libmagic-mgc libmagic1 libopencore-amrnb0 libopencore-amrwb0 libsox-fmt-alsa\n", + " libsox-fmt-base libsox3\n", + "Suggested packages:\n", + " file libsox-fmt-all\n", + "The following NEW packages will be installed:\n", + " libmagic-mgc libmagic1 libopencore-amrnb0 libopencore-amrwb0 libsox-fmt-alsa\n", + " libsox-fmt-base libsox3 sox\n", + "0 upgraded, 8 newly installed, 0 to remove and 37 not upgraded.\n", + "Need to get 760 kB of archives.\n", + "After this operation, 6,717 kB of additional disk space will be used.\n", + "Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libopencore-amrnb0 amd64 0.1.3-2.1 [92.0 kB]\n", + "Get:2 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libopencore-amrwb0 amd64 0.1.3-2.1 [45.8 kB]\n", + "Get:3 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libmagic-mgc amd64 1:5.32-2ubuntu0.4 [184 kB]\n", + "Get:4 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libmagic1 amd64 1:5.32-2ubuntu0.4 [68.6 kB]\n", + "Get:5 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libsox3 amd64 14.4.2-3ubuntu0.18.04.1 [226 kB]\n", + "Get:6 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libsox-fmt-alsa amd64 14.4.2-3ubuntu0.18.04.1 [10.6 kB]\n", + "Get:7 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libsox-fmt-base amd64 14.4.2-3ubuntu0.18.04.1 [32.1 kB]\n", + "Get:8 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 sox amd64 14.4.2-3ubuntu0.18.04.1 [101 kB]\n", + "Fetched 760 kB in 0s (6,655 kB/s)\n", + "Selecting previously unselected package libopencore-amrnb0:amd64.\n", + "(Reading database ... 155222 files and directories currently installed.)\n", + "Preparing to unpack .../0-libopencore-amrnb0_0.1.3-2.1_amd64.deb ...\n", + "Unpacking libopencore-amrnb0:amd64 (0.1.3-2.1) ...\n", + "Selecting previously unselected package libopencore-amrwb0:amd64.\n", + "Preparing to unpack .../1-libopencore-amrwb0_0.1.3-2.1_amd64.deb ...\n", + "Unpacking libopencore-amrwb0:amd64 (0.1.3-2.1) ...\n", + "Selecting previously unselected package libmagic-mgc.\n", + "Preparing to unpack .../2-libmagic-mgc_1%3a5.32-2ubuntu0.4_amd64.deb ...\n", + "Unpacking libmagic-mgc (1:5.32-2ubuntu0.4) ...\n", + "Selecting previously unselected package libmagic1:amd64.\n", + "Preparing to unpack .../3-libmagic1_1%3a5.32-2ubuntu0.4_amd64.deb ...\n", + "Unpacking libmagic1:amd64 (1:5.32-2ubuntu0.4) ...\n", + "Selecting previously unselected package libsox3:amd64.\n", + "Preparing to unpack .../4-libsox3_14.4.2-3ubuntu0.18.04.1_amd64.deb ...\n", + "Unpacking libsox3:amd64 (14.4.2-3ubuntu0.18.04.1) ...\n", + "Selecting previously unselected package libsox-fmt-alsa:amd64.\n", + "Preparing to unpack .../5-libsox-fmt-alsa_14.4.2-3ubuntu0.18.04.1_amd64.deb ...\n", + "Unpacking libsox-fmt-alsa:amd64 (14.4.2-3ubuntu0.18.04.1) ...\n", + "Selecting previously unselected package libsox-fmt-base:amd64.\n", + "Preparing to unpack .../6-libsox-fmt-base_14.4.2-3ubuntu0.18.04.1_amd64.deb ...\n", + "Unpacking libsox-fmt-base:amd64 (14.4.2-3ubuntu0.18.04.1) ...\n", + "Selecting previously unselected package sox.\n", + "Preparing to unpack .../7-sox_14.4.2-3ubuntu0.18.04.1_amd64.deb ...\n", + "Unpacking sox (14.4.2-3ubuntu0.18.04.1) ...\n", + "Setting up libmagic-mgc (1:5.32-2ubuntu0.4) ...\n", + "Setting up libmagic1:amd64 (1:5.32-2ubuntu0.4) ...\n", + "Setting up libopencore-amrnb0:amd64 (0.1.3-2.1) ...\n", + "Setting up libopencore-amrwb0:amd64 (0.1.3-2.1) ...\n", + "Setting up libsox3:amd64 (14.4.2-3ubuntu0.18.04.1) ...\n", + "Setting up libsox-fmt-base:amd64 (14.4.2-3ubuntu0.18.04.1) ...\n", + "Setting up libsox-fmt-alsa:amd64 (14.4.2-3ubuntu0.18.04.1) ...\n", + "Setting up sox (14.4.2-3ubuntu0.18.04.1) ...\n", + "Processing triggers for libc-bin (2.27-3ubuntu1.3) ...\n", + "/sbin/ldconfig.real: /usr/local/lib/python3.7/dist-packages/ideep4py/lib/libmkldnn.so.0 is not a symbolic link\n", + "\n", + "Processing triggers for man-db (2.8.3-2ubuntu0.1) ...\n", + "Processing triggers for mime-support (3.60ubuntu1) ...\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "eX_UvnL9FOB2" + }, + "source": [ + "### Baseline commands recognition (2-5 points)\n", + "\n", + "We're now going to train a classifier to recognize voice. More specifically, we'll use the [Speech Commands Dataset] that contains around 30 different words with a few thousand voice records each." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "FvHkw2rfY9k7", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "4787ccad-f8be-4580-b3e1-b244fa7e585c" + }, + "source": [ + "import os\n", + "import time\n", + "from IPython.display import display, Audio, clear_output\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline\n", + "import numpy as np\n", + "import librosa\n", + "import torch\n", + "from torch.utils.data import TensorDataset, DataLoader\n", + "\n", + "datadir = \"speech_commands\"\n", + "\n", + "!wget http://download.tensorflow.org/data/speech_commands_v0.01.tar.gz -O speech_commands_v0.01.tar.gz\n", + "# alternative url: https://www.dropbox.com/s/j95n278g48bcbta/speech_commands_v0.01.tar.gz?dl=1\n", + "!mkdir {datadir} && tar -C {datadir} -xvzf speech_commands_v0.01.tar.gz 1> log\n", + "\n", + "samples_by_target = {\n", + " cls: [os.path.join(datadir, cls, name) for name in os.listdir(\"./speech_commands/{}\".format(cls))]\n", + " for cls in os.listdir(datadir)\n", + " if os.path.isdir(os.path.join(datadir, cls))\n", + "}\n", + "print('Classes:', ', '.join(sorted(samples_by_target.keys())[1:]))" + ], + "execution_count": 3, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "--2021-12-13 19:10:39-- http://download.tensorflow.org/data/speech_commands_v0.01.tar.gz\n", + "Resolving download.tensorflow.org (download.tensorflow.org)... 108.177.15.128, 2a00:1450:400c:c0c::80\n", + "Connecting to download.tensorflow.org (download.tensorflow.org)|108.177.15.128|:80... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 1489096277 (1.4G) [application/gzip]\n", + "Saving to: ‘speech_commands_v0.01.tar.gz’\n", + "\n", + "speech_commands_v0. 100%[===================>] 1.39G 48.9MB/s in 18s \n", + "\n", + "2021-12-13 19:10:56 (80.5 MB/s) - ‘speech_commands_v0.01.tar.gz’ saved [1489096277/1489096277]\n", + "\n", + "mkdir: cannot create directory ‘speech_commands’: File exists\n", + "Classes: bed, bird, cat, dog, down, eight, five, four, go, happy, house, left, marvin, nine, no, off, on, one, right, seven, sheila, six, stop, three, tree, two, up, wow, yes, zero\n" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "ME4cVShQ916w", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "cf4f7f0d-a5cb-41bc-d3fe-ce59cce2d95c" + }, + "source": [ + "!sox --info speech_commands/bed/00176480_nohash_0.wav" + ], + "execution_count": 4, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "Input File : 'speech_commands/bed/00176480_nohash_0.wav'\n", + "Channels : 1\n", + "Sample Rate : 16000\n", + "Precision : 16-bit\n", + "Duration : 00:00:01.00 = 16000 samples ~ 75 CDDA sectors\n", + "File Size : 32.0k\n", + "Bit Rate : 256k\n", + "Sample Encoding: 16-bit Signed Integer PCM\n", + "\n" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "cvF5l-PCyd8z", + "outputId": "f99836ec-35fc-41c2-a861-afb4c2d69c6f" + }, + "source": [ + "from sklearn.model_selection import train_test_split\n", + "from itertools import chain\n", + "from tqdm import tqdm\n", + "import joblib as jl\n", + "\n", + "classes = (\"left\", \"right\", \"up\", \"down\", \"stop\")\n", + "\n", + "def preprocess_sample(filepath, max_length=150):\n", + " amplitudes, sr = librosa.core.load(filepath)\n", + " spectrogram = librosa.feature.melspectrogram(amplitudes, sr=sr)[:, :max_length]\n", + " spectrogram = np.pad(spectrogram, [[0, 0], [0, max(0, max_length - spectrogram.shape[1])]], mode='constant')\n", + " target = classes.index(filepath.split(os.sep)[-2])\n", + " return np.float32(spectrogram), np.int64(target)\n", + "\n", + "all_files = chain(*(samples_by_target[cls] for cls in classes))\n", + "spectrograms_and_targets = jl.Parallel(n_jobs=-1)(tqdm(list(map(jl.delayed(preprocess_sample), all_files))))\n", + "X, y = map(np.stack, zip(*spectrograms_and_targets))\n", + "X = X.transpose([0, 2, 1]) # to [batch, time, channels]\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)" + ], + "execution_count": 5, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "100%|██████████| 11834/11834 [07:36<00:00, 25.94it/s]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "X_train.shape" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "W4tlrQ-3ci1S", + "outputId": "e8aaccd7-8e0a-4d94-cec6-9b38172ac1fa" + }, + "execution_count": 6, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(8875, 150, 128)" + ] + }, + "metadata": {}, + "execution_count": 6 + } + ] + }, + { + "cell_type": "code", + "source": [ + "X_test.shape" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-WsatRBAeTFB", + "outputId": "66ab0b7f-d1de-4124-8330-a57589543c45" + }, + "execution_count": 7, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(2959, 150, 128)" + ] + }, + "metadata": {}, + "execution_count": 7 + } + ] + }, + { + "cell_type": "code", + "source": [ + "X_train = np.expand_dims(X_train, axis=1)\n", + "X_test = np.expand_dims(X_test, axis=1)" + ], + "metadata": { + "id": "1X_Ib7ZMemr0" + }, + "execution_count": 8, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "X_train.shape" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "cmFAViWpeovJ", + "outputId": "4bd34916-9239-412d-bcc8-0535c807b784" + }, + "execution_count": 9, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(8875, 1, 150, 128)" + ] + }, + "metadata": {}, + "execution_count": 9 + } + ] + }, + { + "cell_type": "code", + "source": [ + "X_test.shape" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "OxGp9yK6etSa", + "outputId": "ff7d3aa5-61bd-4996-8589-e2b18be48e58" + }, + "execution_count": 10, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(2959, 1, 150, 128)" + ] + }, + "metadata": {}, + "execution_count": 10 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "7Ol6sywTG_Y9" + }, + "source": [ + "device = 'cuda'\n", + "\n", + "batch_size = 16\n", + "\n", + "tensor_x = torch.Tensor(X_train)\n", + "tensor_y = torch.LongTensor(y_train)\n", + "\n", + "train_dataset = TensorDataset(tensor_x, tensor_y)\n", + "\n", + "tensor_x = torch.Tensor(X_test) # transform to torch tensor\n", + "tensor_y = torch.LongTensor(y_test)\n", + "\n", + "test_dataset = TensorDataset(tensor_x, tensor_y)\n", + "\n", + "\n", + "trainloader = DataLoader(train_dataset, batch_size=batch_size,\n", + " shuffle=True, num_workers=2)\n", + "testloader = DataLoader(test_dataset, batch_size=batch_size,\n", + " shuffle=False, num_workers=2)" + ], + "execution_count": 23, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "\n", + "\n", + "class Net(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " # TODO: define your layers here\n", + " self.conv1 = nn.Conv2d(1, 64, 5)\n", + " self.bn1 = nn.BatchNorm2d(64)\n", + " self.dropout1 = nn.Dropout(0.2)\n", + "\n", + " self.conv2 = nn.Conv2d(64, 128, 5)\n", + " self.bn2 = nn.BatchNorm2d(128)\n", + " self.max_pool1 = nn.MaxPool2d(2)\n", + "\n", + " self.conv3 = nn.Conv2d(128, 256, 5)\n", + " self.bn3 = nn.BatchNorm2d(256)\n", + " self.max_pool2 = nn.MaxPool2d(4)\n", + "\n", + " self.conv4 = nn.Conv2d(256, 256, 5)\n", + " self.bn4 = nn.BatchNorm2d(256)\n", + " self.max_pool3 = nn.MaxPool2d(6)\n", + "\n", + " self.flatten = nn.Flatten()\n", + " self.fc1 = nn.Linear(512, 256)\n", + " self.fc2 = nn.Linear(256, 5)\n", + "\n", + " def forward(self, x):\n", + " # TODO: apply your layers here\n", + " x = F.relu(self.bn1(self.conv1(x)))\n", + " x = self.dropout1(x)\n", + " x = F.relu(self.bn2(self.conv2(x)))\n", + " x = self.max_pool1(x)\n", + " x = F.relu(self.bn3(self.conv3(x)))\n", + " x = self.max_pool2(x)\n", + " x = F.relu(self.bn4(self.conv4(x)))\n", + " x = self.max_pool3(x)\n", + " x = F.relu(self.fc1(self.flatten(x)))\n", + " x = self.fc2(x)\n", + " x = F.softmax(x)\n", + " return x\n", + "\n", + "net = Net().to(device)" + ], + "metadata": { + "id": "Q1HOBrwiRUSZ" + }, + "execution_count": 31, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "import torch.optim as optim\n", + "\n", + "criterion = nn.CrossEntropyLoss()\n", + "optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)" + ], + "metadata": { + "id": "op5omhm8RUGV" + }, + "execution_count": 32, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def accuracy(loader, model):\n", + " correct_count = 0\n", + " sample_count = 0\n", + " model.eval()\n", + " \n", + " with torch.no_grad():\n", + " for x, y in loader:\n", + " x = x.to(device)\n", + " y = y.to(device) \n", + " scores = model(x)\n", + " _, preds = scores.max(1)\n", + " correct_count += (preds == y).sum()\n", + " sample_count += preds.size(0)\n", + " model.train()\n", + " return float(correct_count)/float(sample_count)*100" + ], + "metadata": { + "id": "_pn34OnIRT60" + }, + "execution_count": 33, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "import seaborn as sn\n", + "sn.set()\n", + "from tqdm.auto import trange\n", + "from ipywidgets import Output\n", + "\n", + "def plot_progress(losses, scores, disp):\n", + " with disp:\n", + " fig, ax = plt.subplots(1, 2, figsize=(16, 5))\n", + " ax[0].plot([i*100 for i in range(len(losses))], losses)\n", + " ax[1].plot([i*100 for i in range(len(scores))], scores)\n", + " ax[0].scatter([i*100 for i in range(len(losses))], losses, color='blue')\n", + " ax[1].scatter([i*100 for i in range(len(scores))], scores, color='blue')\n", + "\n", + "\n", + " ax[0].set(xlabel='samples', ylabel='loss', title=f'Training loss')\n", + " ax[1].set(xlabel='samples', ylabel='accuracy', title=f'Test accuracy')\n", + " clear_output(wait=True)\n", + " plt.show()\n", + " time.sleep(0.5)" + ], + "metadata": { + "id": "llYYATB2RTlm" + }, + "execution_count": 34, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "losses = []\n", + "scores = []\n", + "out = Output()\n", + "display.display(out)\n", + "\n", + "for epoch in range(5): # loop over the dataset multiple times\n", + "\n", + " running_loss = 0.0\n", + " for i, data in enumerate(trainloader, 0):\n", + " # get the inputs; data is a list of [inputs, labels]\n", + " inputs, labels = data\n", + " inputs = inputs.to(device)\n", + " labels = labels.to(device)\n", + "\n", + " # zero the parameter gradients\n", + " optimizer.zero_grad()\n", + "\n", + " # forward + backward + optimize\n", + " outputs = net(inputs)\n", + " loss = criterion(outputs, labels)\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " # print statistics\n", + " running_loss += loss.item()\n", + " if i % 100 == 99: # print every 100 mini-batches\n", + " acc = accuracy(testloader, net)\n", + " print('[%d, %5d] loss: %.3f, accuracy: %.3f' %\n", + " (epoch + 1, i + 1, running_loss / 100, acc))\n", + " losses.append(running_loss / 100)\n", + " scores.append(acc)\n", + " plot_progress(losses, scores, out)\n", + " running_loss = 0.0\n", + "\n", + "print('Finished Training')" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 824, + "referenced_widgets": [ + "60bd4ede8e804a268a295f0fd1378c83", + "7fc4f45841334254a71d8dab2a14232e" + ] + }, + "id": "EvyFLlsURTaE", + "outputId": "1df1c214-d2de-47a9-f516-1765161556ef" + }, + "execution_count": 36, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "60bd4ede8e804a268a295f0fd1378c83", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:41: UserWarning: Implicit dimension choice for softmax has been deprecated. Change the call to include dim=X as an argument.\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[1, 100] loss: 1.528, accuracy: 43.765\n", + "[1, 200] loss: 1.517, accuracy: 44.779\n", + "[1, 300] loss: 1.509, accuracy: 43.325\n", + "[1, 400] loss: 1.507, accuracy: 39.743\n", + "[1, 500] loss: 1.494, accuracy: 41.872\n", + "[2, 100] loss: 1.459, accuracy: 44.306\n", + "[2, 200] loss: 1.464, accuracy: 51.909\n", + "[2, 300] loss: 1.482, accuracy: 50.558\n", + "[2, 400] loss: 1.437, accuracy: 50.727\n", + "[2, 500] loss: 1.435, accuracy: 47.989\n", + "[3, 100] loss: 1.422, accuracy: 51.200\n", + "[3, 200] loss: 1.386, accuracy: 58.770\n", + "[3, 300] loss: 1.389, accuracy: 54.309\n", + "[3, 400] loss: 1.376, accuracy: 59.142\n", + "[3, 500] loss: 1.349, accuracy: 54.714\n", + "[4, 100] loss: 1.358, accuracy: 53.802\n", + "[4, 200] loss: 1.331, accuracy: 62.014\n", + "[4, 300] loss: 1.299, accuracy: 49.645\n", + "[4, 400] loss: 1.298, accuracy: 70.091\n", + "[4, 500] loss: 1.269, accuracy: 61.642\n", + "[5, 100] loss: 1.245, accuracy: 73.302\n", + "[5, 200] loss: 1.236, accuracy: 67.590\n", + "[5, 300] loss: 1.216, accuracy: 71.071\n", + "[5, 400] loss: 1.218, accuracy: 74.282\n", + "[5, 500] loss: 1.205, accuracy: 66.036\n", + "Finished Training\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ojEuXjx5DlDW" + }, + "source": [ + "Train a model: finally, lets' build and train a classifier neural network. You can use any library you like. If in doubt, consult the model & training tips below." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hwgnOrZy1E8p" + }, + "source": [ + "__Training tips:__ here's what you can try:\n", + "* __Layers:__ 1d or 2d convolutions, perhaps with some batch normalization in between;\n", + "* __Architecture:__ VGG-like, residual, highway, densely-connected, MatchboxNet, Dilated convs - you name it :)\n", + "* __Batch size matters:__ smaller batches usually train slower but better. Try to find the one that suits you best.\n", + "* __Data augmentation:__ add background noise, faster/slower, change pitch;\n", + "* __Average checkpoints:__ you can make model more stable with [this simple technique (arxiv)](https://arxiv.org/abs/1803.05407)\n", + "* __For full scale stage:__ make sure you're not losing too much data due to max_length in the pre-processing stage!\n", + "\n", + "These are just recommendations. As long as your model works, you're not required to follow them." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Fvf8UCsPDvj2" + }, + "source": [ + "### Full scale commands recognition (3+ points)\n", + "\n", + "Your final task is to train a full-scale voice command spotter and apply it to a video:\n", + "1. Build the dataset with all 30+ classes (directions, digits, names, etc.)\n", + " * __Optional:__ include a special \"noise\" class that contains random unrelated sounds\n", + " * You can download youtube videos with [`youtube-dl`](https://ytdl-org.github.io/youtube-dl/index.html) library.\n", + "2. Train a model on this full dataset. Kudos for tuning its accuracy :)\n", + "3. Apply it to a audio/video of your choice to spot the occurences of each keyword\n", + " * Here's one [video about primes](https://www.youtube.com/watch?v=EK32jo7i5LQ) that you can try. It should be full of numbers :)\n", + " * There are multiple ways you can analyze the performance of your network, e.g. plot probabilities predicted for every time-step. Chances are you'll discover something useful about how to improve your model :)\n", + "\n", + "\n", + "Please briefly describe what you did in a short informal report." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "16Ux38uFD2g-" + }, + "source": [ + "" + ], + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file