{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Speaker Vector" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "This tutorial is available as an IPython notebook at [malaya-speech/example/speaker-vector](https://github.com/huseinzol05/malaya-speech/tree/master/example/speaker-vector).\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "This module is language independent, so it save to use on different languages. Pretrained models trained on multilanguages.\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "This is an application of malaya-speech Pipeline, read more about malaya-speech Pipeline at [malaya-speech/example/pipeline](https://github.com/huseinzol05/malaya-speech/tree/master/example/pipeline).\n", " \n", "
" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from malaya_speech import Pipeline\n", "import malaya_speech\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### List available deep model" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:root:tested on VoxCeleb2 test set. Lower EER is better.\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Size (MB)Quantized Size (MB)Embedding SizeEER
deep-speaker96.724.40512.00.21870
vggvox-v170.817.701024.00.14070
vggvox-v243.27.92512.00.04450
speakernet35.08.887205.00.02122
\n", "
" ], "text/plain": [ " Size (MB) Quantized Size (MB) Embedding Size EER\n", "deep-speaker 96.7 24.40 512.0 0.21870\n", "vggvox-v1 70.8 17.70 1024.0 0.14070\n", "vggvox-v2 43.2 7.92 512.0 0.04450\n", "speakernet 35.0 8.88 7205.0 0.02122" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "malaya_speech.speaker_vector.available_model()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Smaller EER the better model is**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Load deep model\n", "\n", "```python\n", "def deep_model(model: str = 'speakernet', quantized: bool = False, **kwargs):\n", " \"\"\"\n", " Load Speaker2Vec model.\n", "\n", " Parameters\n", " ----------\n", " model : str, optional (default='speakernet')\n", " Model architecture supported. Allowed values:\n", "\n", " * ``'vggvox-v1'`` - VGGVox V1, embedding size 1024\n", " * ``'vggvox-v2'`` - VGGVox V2, embedding size 512\n", " * ``'deep-speaker'`` - Deep Speaker, embedding size 512\n", " * ``'speakernet'`` - SpeakerNet, embedding size 7205\n", "\n", " quantized : bool, optional (default=False)\n", " if True, will load 8-bit quantized model. \n", " Quantized model not necessary faster, totally depends on the machine.\n", "\n", " Returns\n", " -------\n", " result : malaya_speech.supervised.classification.load function\n", " \"\"\"\n", "```" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "model = malaya_speech.speaker_vector.deep_model('speakernet')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Load Quantized deep model\n", "\n", "To load 8-bit quantized model, simply pass `quantized = True`, default is `False`.\n", "\n", "We can expect slightly accuracy drop from quantized model, and not necessary faster than normal 32-bit float model, totally depends on machine." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:Load quantized model will cause accuracy drop.\n", "/Users/huseinzolkepli/Documents/tf-1.15/env/lib/python3.7/site-packages/tensorflow_core/python/client/session.py:1750: UserWarning: An interactive session is already active. This can cause out-of-memory errors in some cases. You must explicitly call `InteractiveSession.close()` to release resources held by the other session(s).\n", " warnings.warn('An interactive session is already active. This can '\n" ] } ], "source": [ "quantized_model = malaya_speech.speaker_vector.deep_model('speakernet', quantized = True)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [], "source": [ "from glob import glob\n", "\n", "speakers = ['speech/example-speaker/khalil-nooh.wav',\n", "'speech/example-speaker/mas-aisyah.wav',\n", "'speech/example-speaker/shafiqah-idayu.wav',\n", "'speech/example-speaker/husein-zolkepli.wav']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pipeline" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def load_wav(file):\n", " return malaya_speech.load(file)[0]\n", "\n", "p = Pipeline()\n", "frame = p.foreach_map(load_wav).map(model)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAARcAAAD7CAYAAABAItCZAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOzdd1yT594/8E9C2GEvmSLIciEoVhRH3aJUPdZRpdjaFq3a06en1Q6f9niOPafbbutorVarFbdVa60FRIajIKhMkU0A2YQkhIR8f3/4cP+MDEEJCXi9X6/7Bbkzru+d8bn3dfOIiMAwDNPD+NougGGY/omFC8MwGsHChWEYjRBouwBGN8jlctTV1aGurg6NjY2QSCRobm4GACiVSojFYu6xRkZGMDY25m5bWVnB0NAQlpaWsLS0hFAo7PX6Gd3DwqWfk0gkuHXrFgoLC1FcXIzy8nKUlJRAJBKhtLQUtbW1qKurg0wm67E2BQIBLCwsYG1tDQcHB7i4uMDR0RGurq4YMGAABg4cCC8vL9jZ2fVYm4zu4bG9Rf1DfX09UlNTkZqaiqysLOTk5ODWrVsoLi7mHmNnZwdHR0fux+7i4gJra2tYWFhwSx0WFhYwNzdXWzrh8XiwtLTkXqe9pRqZTIb6+nrU1dVxf2tqalBRUcGFWnFxMSoqKqBUKgHcXeLx8vKCj48PfHx8MHz4cAQEBMDV1bUX3zlGU1i49EHNzc24cuUK4uPjkZKSgpSUFOTl5YGIYGdnhyFDhsDb2xteXl7w9vaGr68v3N3dYWhoqO3SoVKpUFpaipycHC4AW8Pw3mkICAhAQEAAgoODMWHCBFhbW2u7dKabWLj0AUqlEomJiYiJicGFCxdw6dIlyGQyODs7Y/To0QgICEBgYCACAgLg4uKi7XIfWkNDA65du4Zr165xoZmZmQkAGDZsGCZPnoxJkyZhypQpaktSjG5i4aKjJBIJoqOjcejQIZw6dQq1tbVwdHRESEgIpk2bhvHjx2Po0KHaLlPjxGIxLl++jPPnzyM+Ph5XrlyBSqXC2LFjERYWhnnz5sHX11fbZTLtYOGiQ2QyGY4dO4a9e/fizz//BBFhwoQJCAsLQ1hYGAYPHqztErWupqYGZ8+exa+//oqzZ8+irq4Ow4cPR3h4OMLDw+Hk5KTtEpn/w8JFByQmJmLXrl04fPgwJBIJZs2ahWeeeQazZ8+GlZWVtsvTWQqFAnFxcThy5Ah++eUXNDQ0YNq0aYiIiMDTTz8NAwMDbZf4WGPhoiUqlQqnT5/Ghx9+iMTERAwZMgQRERF47rnn4ODgoO3y+hy5XI5z585h7969OH78OKytrbF69WqsW7cOtra22i7v8URMr5LL5fTFF1+Qq6srCQQCWrRoESUlJWm7rH6lpKSE3nrrLbKysiITExNas2YNlZaWarusxw4Ll16iUqno559/pkGDBpGxsTG99tprlJ+fr+2y+rXGxkb65ptvyM3NjUxNTWnjxo1UX1+v7bIeGyxcekFycjKNGjWK9PT06Pnnn6fi4mJtl/RYkclk9Mknn5C1tTXZ2dnRjz/+qO2SHgvsxEUNam5uxnvvvYexY8dCKBQiNTUVu3bt6tPHovRFRkZGeOONN5Cbm4tly5bhhRdewJw5c1BaWqrt0vo1tkFXQ/Ly8rBgwQLcvn0bH374IdauXQsej6ftshgACQkJeP7551FZWYndu3dj3rx52i6pX2JLLhoQHx+PJ554AgKBANevX8e6detYsOiQ8ePHIzU1FYsWLcLf/vY3fPzxx9ouqV9i4dLDDh06hGnTpmHChAmIi4uDh4eHtkti2mFiYoIdO3Zgy5YteOeddxAZGQm2EN+zWJcLPeiPP/5AeHg4Vq9ejc8//xx8PstuXffqq6/C09MTCxcuhLm5OT799FNtl9Rv6G3atGmTtovoD1JSUhAaGoqnn34a27dv13iwxMXFITExETdv3uSG3NxcNDY2QigUwsjIiHtsXl4eXn/9dYwaNQrm5uY90n5zczNiY2Px9ddfQ6VSwcvLS2NtaVrrGeTr16+HmZkZgoODtV1S/6DlvVX9glwupyFDhtDUqVOpubm5V9qsrq6mDRs2EABydHSkH374gTZt2kQzZswgExMTWrt2LTU1NRER0aFDhwgAnTlzpsfaT05OpsjISAJAO3fu5MZroq3e8sknn5C+vj6lpaVpu5R+gYVLD9i0aROZmJhQXl5er7abmZlJAGjixIlq4//9738TAIqIiODGVVZW9nj7aWlpbcJFU231hpaWFgoJCaGgoCBSKpXaLqfPYxsFHlF1dTU+/PBDbN68GYMGDerVtjta7Vi7di34fD6ioqK4HuM0cX6NQHB3k939e8L66rk8fD4f27dvR2pqKg4dOqTtcvo8Fi6PaP/+/RAIBIiMjNR2KRwjIyPw+XyoVCoAd0+SjImJwdWrV7nHlJSUYOvWrSAixMbG4u2338Y333zTpi9dkUiEXbt24d///jf+/PPPB7bdXlvFxcX48ssvoVKpcPPmTfznP//B3r17ufoeti1NGDJkCEJDQ7F7926ttN+vaHvRqa8LCgqiF154QSttl5aWtrtadPToUQJAU6ZMofT0dHr66acJAH333XdERLRv3z6ysrIiY2NjWr16Na1cuZJCQ0MJAAUFBXHbjaKjo+mll16ilJQUioqKIqFQSGvWrOHaSU9PJwD0/fffc7fvb+vkyZNkZ2dHAOjzzz+n559/nubOnUsA6L///S/3Wg9qqzcdP36c+Hw+O9nxEbFweQQSiYT09PTo8OHDWmm/NVxGjx5N+fn5FBsbS5988gmZmJiQv78/lZWVERHR9evX1X7wRETh4eHE4/Ho5s2b3Lh3332XANC2bdtILBaTh4cHNTY2cve/8MILBIA7i/v+cOmorbfeeosA0Pnz57lxgYGBNGrUKCKiLrXVm6RSKenp6dGhQ4d6ve3+hB3n8giKi4vR0tLC7YbVltLSUnzwwQfQ19eHi4sLzpw5g0mTJnH3t9cxt6mpKQQCgVpXmW+99RY++OADxMXFgc/nQyaTYcOGDdz9ZWVl8PT0RG5uLsaOHdtuLe211XoVgXu7oxwyZAh+//13AMCBAwceqi1NMTY2houLCwoKCnq13f6GhcsjaGpqAgC1Y0q0wcvLC9u3b3/k1zExMYGLiwsqKyuRnp4OR0dHfPvttz1QYVt6enrcEbGabuthGBsbQyqVaruMPo1t0H0ErT3Q19bWarmSniGXy1FeXg4PDw/o6ekhOzsbCoVC4+32ZltdVV1dzS5n8ohYuDwCV1dXrisFbaAePhfm0qVLaGpqwty5c+Hv7w+JRIJt27apPaaurg5bt27t0XZ7s62uEIlEqKyshJ+fX6+33Z+wcHkEfD4fs2bNQlRUlFbar6urA4AHbhuQy+UAgKqqKrXxSqWSuy4QABw+fBiTJk3C3LlzsWTJEri6uuKNN97AJ598gszMTERFRSEyMhLPPvssgLtXeQSAxsbGTttqaGgAAO6Ym9b75XI5iKhLbfWmX375BRYWFuw0gEel5Q3Kfd6pU6eIz+f3+tG5Z8+epenTpxMAAkCRkZF05cqVNo+7dOkSt3t42LBhdOrUKSIiWrVqFenp6dG6deto/fr1tHTpUgoLC6OGhgbuuRkZGeTt7c21MXToUEpJSSEiosuXL9PMmTMJAAUEBNCZM2fabSs2NpY8PDwIAL344otUVlZGBw4cIHNzcwJAmzZtIoVC0WlbvW3EiBG0atUqrbTdn7DOoh6RUqmEj48PRo8ejYMHD2q7nC5bvXo1du3ahebmZhQXF3PXiG5PYWEheDwe3NzcNF5Xb7bVnp9//hkRERH466+/EBAQoJUa+gu2WvSIBAIBtm7diqioKJw4cULb5TwUV1fXTs9gHjhwYK/92HuzrftVV1fjH//4B9auXcuCpQewcOkBM2fORHh4OCIjI5Gbm6vtcrpEKpVCqVSqbS95nDU3N2PZsmUwNDTEf/7zH22X0y+wcOkh27dvh6enJ2bOnIny8nJtl9Opn3/+GefOnQMR4c0339Ta3i5dQUSIjIxEUlISTpw4ATMzM22X1C+wbS49qLKyEuPHj4ehoSFOnTqFgQMHarukdtXX16vtxjY0NOSOon3cNDc3Y9WqVdi/fz9Onz6NadOmabukfoOFSw8rLi5GWFgYysvLcfz48V4/dJ3puqqqKixcuBDXrl3DL7/8gtDQUG2X1K+w1aIe5urqivj4eIwZMwZPPvkk19UAo1suXLiAoKAgFBUVITExkQWLBrBw0QChUIhjx47h7bffxvr16zF58uQ+s6G3v5NKpXj11VcxZcoUjBgxAleuXMGwYcO0XVa/xMJFQ/T09PDee+/h6tWrEIvF8Pf3xz//+U+IxWJtl/ZYIiIcPHgQw4YNw969e7F7926cOHECdnZ22i6t/9LW0XuPk+bmZvroo4/I0tKS7O3t6Ztvvum1jrwZoj///JNGjx5NfD6fVqxYQSKRSNslPRZYuPSimpoaevPNN8nIyIgcHR3pn//8J1VXV2u7rH6ppaWFTp48SdOmTSMANG3aNLp27Zq2y3qssHDRgsLCQnrttdfI3NyczMzM6H/+538oKytL22X1CzU1NfTVV1+Rp6cn8fl8mjdvHsXFxWm7rMcS2xWtRQ0NDdi5cye+/vprFBYWYuzYsXj22WexdOlS1pdINygUCpw9exY//fQTfv31VwgEAkREROC1117Tei+BjzMWLjpApVIhOjoaP/30E44ePQqlUokZM2YgLCwMc+fOhaOjo7ZL1DlSqRTnz5/Hr7/+ihMnTqC6uhoTJ05EREQEnn76aXaUrQ5g4aJjGhsbceTIERw9ehTnz59HU1MTRo8ejbCwMEyZMgVBQUHQ19fXdplakZ2djdjYWJw+fRrnz5+HXC7H6NGjMX/+fCxbtkxnj4h+XLFw0WFSqRR//vknTp48iTNnzkAkEsHU1BTBwcGYOHEiJk2ahICAgH45l1YqlcjIyEB8fDzi4uJw4cIFlJeXw9TUFFOmTEFYWBjCwsIwYMAAbZfKdICFSx+SnZ2NuLg4xMXFITY2FiUlJeDz+fD29kZgYCACAwMREBCAIUOG9KkfnVgsRnZ2NlJTU5GSkoLk5GRcv34dTU1NMDMzQ0hICBemo0ePfmyX3PoaFi59WGFhIVJSUtSG1jOyzc3N4eXlBS8vL3h7e8PT0xNOTk5wcnKCi4tLp/239DS5XA6RSITS0lKUlpaiqKgIOTk5uHXrFrKzs7maTU1NMXLkSC4oAwMDMXToUOjp6fVarUzPYeHSz5SXlyMrKwu3bt1S+wEXFhaqXarV1NQUrq6usLKygqWlJSwsLLi/VlZW4PF43NUNgLth1fojr6+v586XkkgkaG5uRmNjI+rr61FXV8f9ra2tRXl5OSorK7nXEQgEcHJyUgu+1qH1qgNM/8DC5TFSU1MDkUiE4uJilJeXo7i4GLW1tVwYtA719fVQKpVqpyrU1dVx3TQIhUJu1cTIyAjGxsYwMTGBpaUlN7SGlIODA9zc3ODo6AhnZ2c4ODiwAHlMsHBhuqSlpQUCgQCHDx/GwoULtV0O0wewExcZhtEIFi4Mw2gECxeGYTSChQvDMBrBwoVhGI1g4cIwjEawcGEYRiNYuDAMoxEsXBiG0QgWLgzDaAQLF4ZhNIKFC8MwGsHChWEYjWDhwjCMRrBwYRhGI1i4MAyjESxcGIbRCBYuDMNoBAsXhmE0goULwzAawcKFYRiNYOHCMIxGsHBhGEYjWLgwDKMRLFwYhtEIFi4Mw2gECxeGYTSChQvDMBrBwoVhGI1g4cIwjEawcGEYRiNYuDAMoxE8IiJtF8HonvDwcKSlpamNy8nJgZOTE4RCITdOX18fZ86cwYABA3q7REbHCbRdAKObvL298fPPP7cZX1BQoHZ7xIgRLFiYdrHVIqZdy5cvB4/H6/Qx+vr6WLFiRS9VxPQ1bLWI6VBAQADS0tLQ0VeEx+OhqKgILi4uvVwZ0xewJRemQxEREdDT02v3Pj6fj3HjxrFgYTrEwoXp0NKlS6FSqdq9j8fjISIiopcrYvoSFi5MhxwdHRESEgI+v/2vycKFC3u5IqYvYeHCdOrZZ59ts2FXT08PM2fOhI2NjZaqYvoCFi5MpxYuXNhmyYWIEB4erqWKmL6ChQvTKSsrK8yaNQsCwf8/JEpfXx9hYWFarIrpC1i4MA+0fPlytLS0AAAEAgEWLFigdpQuw7SHhQvzQGFhYTAyMgIAtLS0YPny5VquiOkLWLgwD2RiYoIFCxYAAMzMzDBjxgwtV8T0Bezcon6srq4ORASZTIampiYQEerq6rj75XI5pFJph8+XSqWQy+UAADc3NwDAmDFjcOLECQB3D6SzsLDo8Pn6+vpqq0+mpqYwMDCAnp4ezM3NAdwNq3u35zD9Bzv8X8vq6+tRW1vLDY2NjZDJZKivr+f+F4vFEIvFkEqlkEgkqK+vh1QqhUwmQ21tLfc6KpXqgYGhq+4NInNzc+jp6UEoFMLY2BhmZmYwNzeHsbExTE1NYWFhARMTExgbG8PKygrGxsYwMTGBhYUFzM3NYWVlxQ0dHWHMaB4Llx7S2NiIiooK3LlzB1VVVaisrMSdO3dQV1enFh73327v7W+ds9/74zIzM4OxsTGEQmGbHxqfz4dQKIS+vn67P1IDAwOYmpoCACwtLbnjVng8HiwtLTucJoFAADMzM+725s2b8c4773A/2O4s+QCAWCyGUqlEc3MzJBIJgPZDsTUwGxoaIJPJuECVyWSQSqWoq6uDTCbjwrV1yaw9ZmZmXNBYWlqqBY+lpSWsra3h4OAAe3t72NnZwc7ODra2th1OE9N1LFw60dzcjNLSUpSWlqK4uBhlZWUoLy/nAuTOnTuoqKhAZWUlZDKZ2nOFQiHs7OxgbW3d5gvd2W0zMzMYGBhoaYo7p1QqdXYVpnWVr6GhodMwv/92TU0Nqqqq1EJeIBBwIXN/8Li4uMDJyQnOzs5wc3Nje8068diGi1KpRHFxMQoKClBcXIySkhKIRCK1/8vLy7nHCwQCDBgwAA4ODnBwcICtrS3s7OwwYMAA7otnb28PBwcH2NnZcXtXGN3X0tKCyspKbigvL0dlZSWqqqrazExKS0vVZiTm5uZwcXGBi4sLnJ2d4erqCmdnZzg7O8Pd3R0eHh4wNjbW4tRpT78Ol9raWohEIpSVlSEvL09tyMjI4L4kBgYGsLGxgZOTEzw8PODo6Njmfzc3N52dazO9SyaTcd+pe79frf+3/m1lZWUFDw+PdoeBAwf22+1CfT5cVCoV8vPzkZGRgczMTGRmZiI9PR25ubncuruenh5cXFza/XDd3d1hb2+v5alg+huJRIL8/Pw2M7W8vDzk5+dz24iMjIzg4eEBPz8/+Pn5YciQIfDz84Ovr2+fX/rtU+GSl5eHa9eucQGSlZWFrKws7oNydXXlPiBvb2+1uYOubsdgHj9EBJFIxIXNrVu3kJWVhYyMDOTm5kKhUIDP52PQoEFc2Pj5+WHEiBEYNmxYn/ku62y4iEQiJCcnc8Ply5dRWVkJ4G5XAEOHDsWQIUO4vyNGjOCOnWCYvkqpVKKoqAjp6enIyMhAXl4e0tPTkZqaColEAoFAAG9vb4waNYobAgMDYWJiou3S29CJcKmoqMDFixcRHx+Pv/76C2lpaWhsbIS+vj6GDRuGgIAABAYGIjAwEP7+/jr5RjKMJrW0tCA7OxspKSnckJqaivr6eggEAvj5+SEwMBDjxo3DhAkT4Ovr+8A+kDVNK+GSl5eHixcvcoGSnZ0NPT09+Pv7Y8yYMVyQDB8+vM8sAjJMbyMi3L59mwubq1ev4vLly5BIJLCzs0NISAgmTJiACRMmYOTIkb2+Q6JXwqW2tha///47zpw5g+joaJSWlsLIyAhBQUGYOHEiQkJCMG7cOLZawzCPSKlUIiUlBfHx8YiLi0NCQgKqqqogFAoREhKC2bNnY86cOfD09NR4LRoLl5s3b+L06dM4c+YMEhMTAQAhISGYPn06Jk6ciKCgIBgaGmqiaYZh/g8RITMzExcvXkR0dDTOnTuHuro6+Pj4YO7cuQgNDcWECROgr6/f4233aLjcvHkTe/bswaFDh1BYWAh7e3vMnj0boaGhmDFjRqeHmjMMo3lKpRLx8fE4c+YMTp8+jYyMDJibm2POnDmIiIjA9OnTe+y4m0cOl6qqKuzfvx8//fQTkpOTMWjQICxbtgxhYWEICgrqsHNnhmG0Lz8/H6dPn8bBgweRkJAAR0dHLF++HCtWrMDQoUMf6bUfOlxiY2Px1Vdf4fTp0zA0NMTTTz+N5557DhMmTND6VmqGYbovNzcXe/fuxd69e5Gfn49Ro0bh5ZdfRnh4+MNtwqBuUKlUdOTIEQoMDCQANGHCBNq7dy9JJJLuvAzDMDpMpVJRbGwsRUREkKGhIQ0YMIA++OADamxs7NbrdDlcYmNjKSgoiPh8Pj399NN05cqVbhfd2+Li4mjz5s20fPlyOn78uLbL6ZBEIqGTJ0/S22+/re1SeoVcLqfz58/T//zP/9Dp06c12pZYLKaTJ0/Shg0bNNpOfyUSiejtt98mMzMzcnBwoG+++YaUSmWXnvvAcKmpqaHnnnuOeDwezZo1i65du/bIBfeGv/76i8LCwkgul9O//vUvMjQ01NklrKNHj9LAgQPJxcVF26X0iuTkZIqMjCQAtHPnTo22dejQIXJ3dyc3NzeNttPfVVZW0j/+8Q8yMDCg0aNHdykHOg2XlJQUGjRoEDk5OdGRI0d6rNDeMHv2bNq8eTMR3V3MKy0t1XJFnXv22Wcfm3AhIkpLS+uVcCEiWrx4MXl4eGi8ncdBeno6hYSEkJGREe3YsaPTx3a4K+fixYuYOHEi3NzckJKSgr/97W8PvaFIG9LT07ldajweD05OTlquqHP99bT7jrQeLdobG//5fD7ba9lDhgwZgri4OGzatAmrV6/Gm2++2eFj2z0eOD09HbNnz0ZYWBj27t3bp/oxuXDhAtLT01FcXIwrV65g+/btcHR0xFNPPQXgbleLZ86cQWZmJlxdXTFjxgy4urpyz6+trcWBAwewZs0a/Pbbb7h+/Tpef/11CAQCiEQinD17FiUlJRg/fjymTp2q1nZOTg4uXbqE69evY/z48VyP+a0aGxtx/PhxZGdnY/jw4Zg5c2abDq6JCFeuXMHvv/8OT09PLFu2rFs/QJlMhhMnTuCpp57CnTt3cObMGTg5OSEsLAx6enqoqKjAyZMnwefzsWjRojZHRXc2DSUlJTh58iRefvllXLhwAb///jucnZ3xwgsvcB0iicVibN26FYsXL8agQYO6XHerB30+D6oRAGpqanD48GEUFBRg9OjRIKJuvYexsbG4fPkyAMDf3x+TJk3Czp07uf5/goODMXHiRJSUlODgwYMwMTHByy+/3GltMTExuHLlCgDAxsYGL774olpb9vb2eP7557v9fmkDj8fDm2++CXt7e7z44otwcXHBK6+80vaB9y/KqFQqGjlyJI0fP54UCoWGFq40Jz8/n2JiYggArVq1iq5evUqZmZlERJSamkrDhw+nI0eO0J07d+jTTz8loVBIe/bsISKi3bt3k4mJCQkEAvr666/J39+fAFBaWhpFR0fTSy+9RCkpKRQVFUVCoZDWrFnDtfv555/T5MmTSaVSUX5+Prm7u9PWrVu5+zMzMyk0NJTS0tJIoVDQM888QzY2NnT79m0iInruuefI0dGR1q5dSy+88ALNmzePeDwevf/++12e9tjYWPLy8iIA9Nlnn1FkZCRt2LCBTExMaOHChbRz505avnw5LV26lHg8HoWFhak9v7Np2LdvH1lZWZGxsTGtXr2aVq5cSaGhoQSAgoKCqLm5mYiIjhw5QgBo/fr1ndaanp5OAOj777/nxj3o8+nK+5yVlUVBQUGUmJhICoWCtm/fToaGhuTt7d3l97GlpYWGDRtGRkZG3MbLzMxMEggENH/+fLXHvvjii3TgwIEu1fbUU08RAEpKSuLGqVQqGjRoEJWUlHS5Pl2yefNmMjIyouzs7Db3tQmX3377jXg8HqWnp/dKcZpQX19PAOjf//43N04ul5Ovry+99957ao9dtmwZGRgYcNO7fPlyAkBHjx4lortfKrFYTB4eHmq74l544QW1L8rgwYNp7dq13P3z58+n0NBQIiJSKpU0cuRItXXU5ORkMjAwoF9//ZWI7oaLoaGh2oc0atQoGjVqVLemfcuWLQSADh06xI176623CIDadrONGzeSoaEhtbS0cOM6mwYiovDwcOLxeHTz5k1u3LvvvksAaNu2bUREJJVKaefOnSQSiTqt8/5w6ern86Aan3jiCbVgU6lU5OHh0a1wISLavn07AaCUlBS1tgYOHEgqlYobN2vWLC6AHlTb7du3ic/n08aNG7lxBQUF9NJLL3WrNl2iVCrJx8dHbUbbqs2KaHR0NAICAjBkyBCNLFJpy9mzZ5GVlYWxY8eqjZ85cyaam5vxww8/AAC3bWbevHkAAF9fXxw4cAAymQwbNmzA2rVrsXbtWpSVlcHT0xO5ubkA7i7evv/++wCAjIwMFBcX49atWwCAM2fOIDU1FXPmzOHaDQwMhFgsxty5c7lxxsbG8Pb25m4PGzYMt2/f7tZ0tq5mDR8+nBvn4+MD4O4ifitfX1/I5XKIRCJuXGfTANy97pBAIFA7cvOtt96CQCBAXFwcNw0vvvgiHB0du1V3Vz+fzmqMjo7G5cuX8eSTT3LP5/F4CAoK6va2nWXLlsHMzAz79u3jxllYWKCwsBDR0dEAgMuXL+OJJ57gtpc96P3z8PDArFmzsGvXLiiVSgDArl27EBkZ2a3adImenh6WLl3KvSf3ahMu1dXV/bLbx4yMDABo01v7hAkTAACZmZkAwG34u3cDYHp6OhwdHfHtt99yw+nTp5Gbm4vw8HAAgLOzM65cuYK///3vyMzMhKenJ1QqFQAgLS0NpqamsLOzU2v7Qd1JCAQC7hrNj6K97hJbT1RrvcQH0Pk0dMTExAQuLi5cR14Pq6ufz4PeZ+BuKN/rYTYaC4VChIeH46effuKuAiGRSODp6Yldu3YBABZPE50AACAASURBVHbs2MFtO3lQba1aZ0wnT56ESqVCWloaRo8e3e36dImDg0O7n3+bLbUeHh74448/oFKp+tUWdmtrawBAUlIS94UFgIEDB0JfXx9WVlYdPldPTw/Z2dlQKBQdnj367rvvchs5jY2NceTIEe4+lUoFiUSCmJgYnb4UamfT0BG5XI7y8nLMnDnzkdru6ufTWY0NDQ0A7i5R3L8R+GECZvXq1fjuu+9w9OhRJCcn44033kBsbCw2bdqEvLw8SCQSuLi4cI/vyvs3e/ZseHh4YPv27TAyMsLs2bO7XZeuSUtLw+DBg9uMb5MeS5YsQWlpKaKionqlsN7yxBNPAAC3+N7q5s2bUCgUCA4O7vC5/v7+kEgk2LZtm9r4uro6bN26Ffn5+Xj//fcRHh7O7TW5d47Vuoqyf/9+tedXV1fj2LFjDz9RPehB09CRS5cuoampSW317mF05fPp6vvc3iL6wxgxYgSCg4OxZcsW5OTk4IknnsDKlSuhUqmwYMECrFixgntsV98/Ho+Hl19+GX/88Qc+++wzLFu2rEdq1ZaysjLs378fzzzzTNs729tIExkZSTY2NpSbm6vxDUKakJGRQQDabGRasWIFmZmZUWFhITfu22+/JS8vL5LL5UREtG7dOgJAVVVV3GOamprI1dWVDAwM6OOPP6aMjAw6ePAgLVq0iBoaGuj69esEgCZPnkz19fUUFxdHjo6OZG1tTWKxmGpraykgIIDbg3X+/HnasmULPfXUU9TU1ERERGFhYSQQCLjbREQLFiwgPT09kslkXZ72L774gtvD1Wrnzp0EQO2UjR9++EHtcQ+ahoaGBlq1ahXxeDzKyMjgXmfdunU0adIk7nZ6ejqNHTuWPvroo07rTExMJAD0xRdfcOMe9Pk8qMaamhry9fUloVBIFy5cICKi0tJScnR0JKFQyO2p6449e/YQADp37hw3bsmSJeTu7q62Mbwr71+r6upqMjY2psjIyG7VomvkcjlNmTKFvLy82j3vqN1waWxspNGjR5OrqytlZWVpvMielJSURAsWLCAA5OrqSnv27KG6ujoiIpLJZLR27VoaOnQo7d69m77//nuaM2cOFRUVERHR999/T87OzgSAFi9eTJcvX+ZeNyMjg7y9vQkAAaChQ4eq7UlYuXIlCQQCGjx4MG3bto0OHz5MBgYGNGXKFKqurqaSkhKaPn068Xg84vF4NHnyZG7344EDB8ja2poA0Ouvv04NDQ30888/k42NDQGgN954gwu/ziQmJnK7z1esWEF5eXkUExPDnWg6Z84cSk9Pp8TERBo7diw3nTk5OV2ahlWrVpGenh6tW7eO1q9fT0uXLqWwsDC1H07r3kZ9fX3ufb/f5cuXaebMmQSAAgIC6MyZM136fLpSY35+PgUFBREA8vDwoGXLllFYWBiFhITQd999162gJrq792v69Olq42JiYui///1vm8c+qLb7H5ucnNytWnSJRCKhsLAwsrCwUPsd3KvDw/9rampo7NixZG5urrZbsz+oq6ujhIQEKi4u7vZzCwoK1Oas97r3R0ZEakshrWpra9t80XRJZ9OwatUq0tfXJyKioqIiqq+vb/c1qqqq6OWXX1abs3fHgz6frrzPd+7c4eamYrH4oepoJZVK24zrKKS6UhsR6ex5bl2RlZVFw4cPJxsbG7Vjdu7XaX8ucrkcr732Gr777jssXLgQX375JZydnXtkXY3pnjVr1jzwMZGRkRg5cqTGali9ejV27dqF5ubmTh8XExODoqIitW0SukIX3se+Si6X4+OPP8Z///tfjBgxAlFRURg4cGCHj+/0uH5DQ0Ns3boVS5YswerVq+Ht7Y0XX3wRGzdu7Je7q3XZvcdudOT+Xd09TSqVQqlUorGxscMLsCuVSshkMp0MFkA33se+RqVS4ciRI3j77bchEonw5ptv4p133nnwlTm6uigkk8loy5YtZGdnR2ZmZvSPf/yjw9UDpv/Zt28fOTg4cBvK+0rXG8zDk0gk9O2335Knpyfp6+tTZGRktzYldLubS7FYjB07duDLL79EWVkZZs2ahRUrViAsLIz15t+P1dfX496viqGhIbfLlelfLl26hJ9++gm//PILmpqa8Nxzz+H111/v9uVIHroPXYVCgaNHj2L37t34448/YG5ujiVLliAiIqLTY0YYhtE9RUVFXP+52dnZGDp0KFasWIHnnnvuoVcTe+TSIiKRCPv378eePXtw8+ZNeHp6IiwsDKGhoZg0aRK7aiLD6KC0tDTuEiNJSUmwsbHBM888gxUrViAwMPCRX7/HL4qWkpKCqKgonDlzBjdu3IBQKMT06dMxZ84chIaGdvuENoZheoZUKsWff/7JXaywuLgYDg4OmDNnDubPn49Zs2b16MXRNHo518LCQi4Zo6Oj0dTUhGHDhnGXcJ0wYQLbtc0wGtLY2IikpCTuuuyXLl1Cc3MzAgMDMWfOHMydOxeBgYEaO4ew1y5EL5PJEBMTgz///BPx8fFISUmBUqmEh4cHd7HskJAQrnsAhmG6586dO0hISEBcXBzi4+ORmpoKpVKJwYMHIyQkBJMmTcLs2bPh4ODQK/X0WrjcTyqVIiUlBQkJCYiPj8fFixdRX18Pc3NzDB8+HKNGjeIGPz+/fnWGNsM8qtraWqSnpyM5OZkbMjMzwePx4Ovri5CQEIwfPx6TJk3q9EA3TdJauNxPoVBwb1JKSgpSUlKQnp4OhUIBMzMzjBw5EoGBgQgICMDQoUPh6+vb4YFcDNNfKJVK3L59G+np6UhLS+N+G62dfA0aNAiBgYHcEBwc3KZfZm3RmXBpj1wux40bN5CSksKFzo0bNyCXy8Hj8eDm5gZfX18ubIYMGQI/Pz+ubxCG6SuampqQlZWFrKwsZGRkIDMzE5mZmbh16xaam5vB4/EwePBgtSAZNWpUp/0QaZtOh0t7WlpakJeXp/YBZGRkICsrC42NjQAAe3t7+Pj4wMPDA56envDw8OCG3lrfZJj7icVi5OXltRlu3bqFgoICtLS0QF9fHx4eHm1mmL6+vjAxMdH2JHRLnwuXzhQWFnLJf+vWLe7DKyws5E62MzU1VQubQYMGwdXVFU5OTnBxccGAAQPY9h3modTU1EAkEqGoqAgikQgFBQVqIdLaFWTrdbRav4ODBw/mgmTw4MH95riwfhUuHWlpaUFJSQn3Iefn53P/FxQUoKKignusQCDAgAED4ObmBicnJzg7O3Ph4+rqCjs7Ozg4OMDS0lKLU8T0JqlUisrKSpSXl6O8vJwLj9LSUhQXF0MkEqG4uJi7rhEAmJmZwd3dnZuB3T9Da69f4/7msQiXB2ntBf/+L0tpaSlEIhEKCwtRUVHB9dgO3O1c287ODvb29hgwYADs7Oxga2sLR0dH2NnZcYOVlRU3sCUi3dDQ0IDa2lrU1dWhuroa5eXlqKys5AKk9f+KigpUVFSodWIO3D1runVm4+LiAicnpzYzIzMzMy1Nne5g4dJFLS0tqKio6PALWFVVhTt37nD33TsXa2Vubg4rKytYWlpygdP6f+tfU1NTCIVCWFhYwNjYGCYmJrC0tFT7/3ElkUgglUohFoshFoshk8nQ2NiIhoYGSKVSSCQS1NXVoba2lhtab987/v6+bQUCATczcHBwgL29vdqMw9bWFnZ2dhgwYAAGDBjwWCx19AQWLhrS2NiIysrKDr/g949r/SuRSLgN0x0xMTGBsbExLCwsYGpqCgMDAxgYGMDU1BTA3evr8Pl8GBkZcWcut+5VMDY2Vvtx8Hi8TgNLKBR2eEh4XV0dOvr6SCQStU6lWlpauN75GxsboVAooFQqIRaLAdxdmmhpaUFzczMkEgmICHV1dZBKpZDJZKivr+/0PTE0NISpqekDw7u9+1j/LZrBwkVHtc6NpVKp2o+srq4OEokEMpkMDQ0NEIvFUCqVaGpq4paWamtrAdzdViCXy6FSqbgf5/0/+tYfc0daX6s9rcHWnnvDDlAPMRMTExgaGoLP53PHZLS+lkAg4FYp7l9iMzExgYmJCczNzSEUCmFiYsIt5bFVTt3DwoXpkpaWFggEAhw+fBgLFy7UdjlMH8DinmEYjWDhwjCMRrBwYRhGI1i4MAyjESxcGIbRCBYuDMNoBAsXhmE0goULwzAawcKFYRiNYOHCMIxGsHBhGEYjWLgwDKMRLFwYhtEIFi4Mw2gECxeGYTSChQvDMBrBwoVhGI1g4cIwjEawcGEYRiNYuDAMoxEsXBiG0QgWLgzDaAQLF4ZhNIKFC8MwGsHChWEYjWDhwjCMRrBwYRhGI1i4MAyjESxcGIbRCBYuDMNoBAsXhmE0goULwzAawSMi0nYRjO4JDw9HWlqa2ricnBw4OTlBKBRy4/T19XHmzBkMGDCgt0tkdJxA2wUwusnb2xs///xzm/EFBQVqt0eMGMGChWkXWy1i2rV8+XLweLxOH6Ovr48VK1b0UkVMX8NWi5gOBQQEIC0tDR19RXg8HoqKiuDi4tLLlTF9AVtyYToUEREBPT29du/j8/kYN24cCxamQyxcmA4tXboUKpWq3ft4PB4iIiJ6uSKmL2HhwnTI0dERISEh4PPb/5osXLiwlyti+hIWLkynnn322TYbdvX09DBz5kzY2NhoqSqmL2DhwnRq4cKFbZZciAjh4eFaqojpK1i4MJ2ysrLCrFmzIBD8/0Oi9PX1ERYWpsWqmL6AhQvzQMuXL0dLSwsAQCAQYMGCBWpH6TJMe1i4MA8UFhYGIyMjAEBLSwuWL1+u5YqYvoCFC/NAJiYmWLBgAQDAzMwMM2bM0HJFTF/Azi16DKhUKtTX1wMAamtrAQD19fXcMSxisRhKpbLd57Y+3s3NDQAwZswYnDhxAgAgFAqhr6/f7vMsLS25vUxmZmYQCAQwNTWFgYEBjI2NuSUhpv9ih//rqJqaGlRVVaG6uhr19fUQi8Wora2FWCxGY2MjxGIxN+7e22KxGHK5HFKpFAqFAo2NjdqelA4ZGhrCxMQE+vr6EAqFMDIygpmZGczMzGBlZQWhUMjdNjMzg6WlJfe/hYUFbGxsuKGjkGO0h4VLL6mpqUFZWRk3VFRU4M6dO6iurm53aN2Aeq97f3BCoRDm5uawtLRUG2dhYQGBQAAzMzPw+XxYWFhwzwUACwsL8Pl8bmkCAIyMjGBsbNxu3fcunWzevBnvvPMOd0pAXV1du+cdKZVKiMVi7nbrUlLrEpJEIkFzczOkUinkcjmampogk8kglUq5oKyrq+PCsnVca5AqFIo2bVpYWMDW1ha2trZqoWNjY4MBAwZgwIABcHJygqOjI+zt7Ts8rYHpOSxcHpFKpYJIJEJBQQHy8/NRVFSEiooKlJaWory8HCKRCOXl5WhqauKeY2hoCAcHB9jZ2XE/hvt/FPf+UFrn2NqmVCrVdklrS1NTE+rq6toEcmVlJaqrq7klvtahrKxMLez09PRgb28PR0dHODk5ccHj7OwMd3d3uLu7Y+DAgTA0NNTiVPZ9LFy6oKamBjk5OcjLy0NBQYHaUFhYiObmZgCAgYEBXFxcuDlk69B6u/WLzI5s7X1SqbRN4N97u6ysDMXFxVwI8Xg8ODo6YtCgQRg0aBAXOu7u7vDy8oKrq+sDu6R43LFw+T9KpRJFRUXIy8tDXl4e0tPTkZGRwd0G7h48ZmtrCycnJ3h4eLQZBg4cyBa3+7ja2loubFo/+9YhNzeX2zBuYGCAwYMHY+jQodznP2TIEPj7++vEUqYueCzDpaqqCteuXUNqaipSU1ORlpaGW7ducUsgzs7O8PHxgY+PD3x9fbn/XV1dWXg85iorK5GTk4OsrCxkZ2cjOzsbWVlZyM/Ph0KhAI/Hg5ubG4YPH46RI0dyg4eHx2O3pNPvw6W0tBSXLl1SC5PS0lIAgJOTE0aOHAl/f38MGzYMPj4+8Pb2ZnMeptsUCgXy8vKQmZmJ7Oxs7rt269YttLS0wNzcHP7+/lzYBAUFYejQoR2ecd4f9KtwaWlpQVZWFhISEhAfH4/k5GRkZGQAuNt9wKhRo7ghKCiI9f3KaFxzczNu3bqF5ORkbkhNTYVEIoFQKIS/vz9CQkIwfvx4jB8/HtbW1touucf06XBRKpW4dOkSzp07h7i4OFy9ehVSqRRWVlYIDg5GcHAwxo0bhzFjxrBzYRid0dLSghs3biAhIQFJSUlITExEfn4+9PT0MHToUISEhGDatGmYOnUqzM3NtV3uQ+tz4VJQUIDff/8d586dw59//on6+nq4u7vjySefxPjx4xEcHAw/P7/Hbv2W6dvKysqQlJSEhIQEXLx4EcnJyeDz+QgODsaMGTMwc+ZMjBo1qk+tRvWJcElOTkZUVBSOHz+OnJwcmJqaYvLkyZg5cyZmzpwJb29vbZfIMD2qqqoK58+fx7lz5/D7779DJBLB1tYWs2fPxuLFizFjxgwYGBhou8xO6Wy4XL9+HQcPHkRUVBRyc3MxaNAgLFq0CLNmzcL48eN1/o1lmJ5048YNnDt3DseOHUNiYiIsLCywYMECLF68GFOnTtXJ0x90Klzq6+vx448/YseOHcjMzISrqysWL16MJUuWICgoSNvlMYxOKC4uxqFDh3Dw4EFcuXIFNjY2WL58OdatWwcvLy9tl8fRiXDJzs7G119/jT179gC4229reHg4goOD2bYThulEfn4+fvnlF+zYsQNFRUWYNWsW/v73v2PGjBna/+2QFiUnJ9Ps2bOJx+ORp6cnbdmyherq6rRZEsP0SUqlko4dO0ZTpkwhAOTj40N79+4llUqltZq0Ei4lJSW0YsUK4vP5NG7cOPr111+ppaVFG6UwTL9z48YNWrlyJenp6VFQUBBdvHhRK3X06n4thUKBf/3rX/Dx8UFcXBx++eUXxMfHY+7cuX1qF9vjrKmpCWfPnsWrr76q7VKYDgwbNgw//PADrl27BisrK0yYMAGLFi3ijkzvNb2VYrm5uRQUFERCoZA+/vhjampq6q2mmR506NAh8vPzo1786jCP6PTp0+Tt7U02NjZ08uTJXmu3VxYXrl69iuDgYCiVSiQnJ2P9+vWsr4w+6umnn0ZoaKi2y9CIn376SdslaERoaChSUlIwb948zJ8/H19++WWvtKvxcLlx4wamT5+OoKAgXLx4kR3w1g/oQodRPS06Ohpvv/22tsvQGFNTU/zwww/46KOP8Nprr+Hbb7/VeJt6mzZt2qSpF29sbMTEiRPh5+eHU6dOddiVoq6QyWQ4cuQIPDw8UFpaiv3796O0tBReXl7g8/moqKjAgQMHkJqaisGDB7dZ+srJycHp06exd+9eSCQS+Pn5cfeVlJRg3759GD16NC5cuIDt27cjKysLw4cP5w6AEovF+OKLL+Ds7Mx1S9keIsKFCxdw/PhxXL16FQ0NDfD09OxyOwAgEolw6NAh/Prrr1AqlfDw8OjytJw/fx4JCQlo/eqcOnUKiYmJSE1NhUgk4o616KyN2tpa/PjjjwgKCsJvv/2Go0ePYuzYsW22vcXExCAqKgoJCQnIyspCYGAgACA2NhYHDx7ErVu3EBAQ0KVpamxsRFRUFA4dOoSqqiq4uLjAyMgIMTExmD9/PhQKBaytrVFWVgYfHx/uMzl+/DgOHz6M27dvw87Ojus6tDvToSvGjRsHQ0NDbNiwAVOnTuU6XtcITa5zvfPOO2RtbU0VFRWabKZHxMbGkpeXFwGgzz77jCIjI2nDhg1kYmJCCxcupJ07d9Ly5ctp6dKlxOPxKCwsTO35n3/+OU2ePJlUKhXl5+eTu7s7bd26lYiI9u3bR1ZWVmRsbEyrV6+mlStXUmhoKAGgoKAgam5uJiKiI0eOEABav359p7W+8847tHPnTiIiunr1Ko0ZM6Zb7URHR9NLL71EKSkpFBUVRUKhkNasWdOlaSEievPNN9W2uSQlJdETTzxBiYmJpFAoHtjG7t27ycTEhAQCAX399dfk7+9PACgtLa3d6X3qqacIACUlJXHjVCoVDRo0iEpKSro0TZmZmRQaGkppaWmkUCjomWeeIRsbG7p9+zZdu3aNxo8fT3Z2dhQTE0PXrl0jIqLU1FQaPnw4HTlyhO7cuUOffvopCYVC2rNnz0NNhy6ZPXs2DR8+XKO7qjUWLgqFguzt7Wnz5s2aaqLHbdmyhQDQoUOHuHFvvfUWAaAjR45w4zZu3EiGhoZqu88HDx5Ma9eu5W7Pnz+fQkNDudvh4eHE4/Ho5s2b3Lh3332XANC2bduIiEgqldLOnTtJJBJ1WKNKpSJbW1uKiYnhxr3//vtdbkcsFpOHhwc1NjZy97/wwgtqP94HTcu94RITE0Nr1qwhuVzO3d+VNpYvX04A6OjRo0R098ffkdu3bxOfz6eNGzdy4woKCuill17qUntKpZJGjhxJO3bs4O5PTk4mAwMD+vXXX7lpdHV15e6Xy+Xk6+tL7733nloty5YtIwMDA0pPT+/2dOiStLQ0AqDR3dQaW3nOzc3FnTt3+tQ1hVsXd4cPH86Na1089vf358b5+vpCLpdDJBLBxcUFwN3FdFNTUwBARkYGiouL0dDQwD3H1NQUAoEAQ4cO5ca99dZb+OCDDxAXF4dVq1bB2NgYL774Yqc18ng8+Pj4YMmSJdixYwfmzZuHN954o8vt8Pl8yGQybNiwgbu/rKwMnp6eyM3NxdixYx84La0OHDiA+Ph4fPPNN2pHgx44cOCBbTg5OQEA5s2bx72nHfHw8MCsWbOwa9cubNq0CQKBALt27UJkZGSX2qusrERqairmzJnD3R8YGAixWKx2jtq903D27FlkZWVh7NixarXMnDkT+/fvxw8//IDPPvusW9OhS0aMGIGBAwciISEBISEhGmlDY+HSejGtvt4ZdXsX72rddiGRSLhxzs7OOHfuHE6dOoVJkybB09MTycnJnb62iYkJXFxcUFlZ2a2avvnmGyxatAjz58/H1KlT8fPPP8PBwaFL7aSnp8PR0bHTDXpdnZZNmzZBT0+P6/ioVVfaaN0m0dVtE2vXrsWcOXNw8uRJzJ8/H2lpafjXv/7Vpfbef/99mJqaws7OTm38/Se/3hsurZ2M3d8P0IQJEwAAmZmZDzUdusTW1hY1NTUae32NvSOtG4qys7M11YROeffdd/H+++/jo48+wsKFC7vU165cLkd5eXmbDY8PMnLkSKSkpGDNmjWIjY1FYGBgp1+Se9vR09NDdnZ2u9f+6e60REVFIT8/Hy+99JLa+K600V2zZ8+Gh4cHtm/fjrNnz2L27Nldbk+lUkEikSAmJqbTNu4Nl9Ye4ZKSktQeM3DgQOjr63e6wb0vUCgUuH37Ntzd3TXWhsbCxdnZGYGBgfjxxx811YTOyM/Px/vvv4/w8HBuj1jrpVI7c+nSJTQ1NWHu3Lldbksul2Pv3r0wMzPDt99+i9OnT6OsrAxHjx7tUjv+/v6QSCTYtm2b2mPq6uqwdevWbk2Lv78/vvnmG/zyyy/47LPP1MZ31sbD4PF4ePnll/HHH3/gs88+w7Jly7rcXutq7v79+9Xur66uxrFjx7jXv/dCdE888QQAIC4uTu05N2/ehEKhQHBw8ENNh644evQoGhoauvXd6zaNbc2hu0dz8ng8io6O1mQzPeaLL75os7V/586dBICuXLnCjfvhhx/UHnf9+nUCQJMnT6b6+nqKi4sjR0dHsra2JrFYTA0NDbRq1Sri8XiUkZHBvc66deto0qRJ3O309HQaO3YsffTRRx3WKJPJaNy4cdxWfpVKRXZ2dnTs2DEioge209TURK6urmRgYEAff/wxZWRk0MGDB2nRokXU0NDQpWl55ZVXCAC3ZygiIoL09PS4Gh7URmtNAKiqqqrLn091dTUZGxtTZGSk2vgHtadUKikgIIAA0KpVq+j8+fO0ZcsWeuqpp7gjxdesWUP6+vp0+/Ztys3NpcbGRlqxYgWZmZlRYWEh19a3335LXl5e3Absh5kObaupqSE3NzeKiIjQaDsaP4Z78eLFZGNjo/Zl10WJiYncrsQVK1ZQXl4excTEUGBgIAGgOXPmUHp6OiUmJtLYsWMJAC1evJhycnKIiGjlypUkEAho8ODBtG3bNjp8+DAZGBjQlClTqLq6mlatWkV6enq0bt06Wr9+PS1dupTCwsK4HxsR0W+//UY8Ho/09fU7PDtcJpORo6MjLV26lA4dOkSffvqp2h6NrrSTkZFB3t7eBIAA0NChQyklJYW7v7Np+fLLL8nNzY0A0KuvvkoFBQV07tw5AkD6+voUGRlJIpGo0za+//57cnZ25t7Dy5cvd/lzWrlyJSUnJ7cZ/6BpKikpoenTpxOPxyMej0eTJ0/mdmMT3d3rJRAIyNLSkr766ivuvV67di0NHTqUdu/eTd9//z3NmTOHioqKHnk6tEUqldKTTz5Jbm5udOfOHY22pfFwkUqlFBISQra2tpSYmKjp5rTq3h8wEamdP7Vq1SrS19cnIqKioiKqr69v9zWqqqro5Zdf7vQscYVCQXK5XG2O2t12iO7uzm3vNR40Ld3RWRsPQyKRPFJ7tbW1VF1d3e59dXV1baa7dXxCQgIVFxd3r1gdU1lZSePHjydra2u6fv26xtvrlbPPJBIJhYWFkYGBAX3yySePZfcK9/7oOxMdHU27d+/WeDvM4yUmJoZcXFzI3d2919YiemX/mYmJCU6cOIGPP/4YGzduRFBQEC5cuNAbTesMqVQKpVKJxsbGDh+jVCohk8mwYsUKjbbDPD5KS0uxatUqTJ06FaNHj0ZycrLaqRwa1SsRdo+srCxatGgRAaC5c+fSrVu3eruEXrdv3z5ycHAgALRmzRru8PK+2g6j+yQSCX344YckFArJzc2N9uzZ0+u90mmtD92zZ8/i9ddfR25uLhYvXoxXXnkFY8aM0UYpGldfX49732ZDQ0ONnMTZW+0wuqu0tBTbtm3Djh07IJfLsXHjRvz973/XThcnvRpl91EoSlX5MAAABYBJREFUFLR7925uN+GYMWNo3759auepMAzzYPHx8bRkyRLS19cne3t7+t///V+N7w16EJ3o/R8A4uPj8dVXX+HYsWOwtrbmLikybty4PnloNcNo2u3btxEVFYUDBw7gxo0bGD16NF555RUsWbJEJzpj05lwaVVSUoJdu3bh4MGDyMjIgIuLCxYtWoQlS5ZgzJgx2r9cAsNoUVFREXfNoqtXr8LW1hYLFy7Ec8891+YkS23TuXC5182bN3Hw4EGuU6CBAwdi5syZmDFjBqZOnQpLS0ttl8gwGqVQKJCUlMRdHz05ORmWlpZYsGABlixZgilTpuhsz4A6HS73unbtGo4fP45z587h6tWrAIAxY8ZwYTNmzJgunSzIMLouNzcX586dw7lz5xAdHQ2xWAxPT0/MmDEDc+fOxbRp0/rE5Yz7TLjcq7GxETExMTh16hR+//13FBYWwtTUFCNHjkRISAjGjx+PcePG9fnuHpj+T6lUIjs7GwkJCYiPj8fFixdRUFAAExMTjBs3DtOmTcO0adMwatQobZfabX0yXO6XkZGBuLg4JCUlITExEbm5ueDz+RgyZAjGjRuHcePGISAgAH5+fjp5wW7m8VFQUIDU1FRcvnwZCQkJ+OuvvyCTyWBjY4Pg4GCMGzcOISEhGDt2bJ//rvaLcLnfnTt3kJSUhISEBCQmJiI5ORlNTU0wMDDAsGHDMHLkSPj7+3N/7+1wmWF6QnNzMzIyMpCamoq0tDSkpqYiNTUVdXV14PP58PX1RXBwMMaPH4/g4GD4+Pj0u50V/TJc7qdUKpGVlcV9wK1DdXU1gLvdKPr5+cHPzw/e3t7w8fGBn59fm57LGOZ+EokE2dnZyMnJQWZmJrKzs5GVlYWMjAwoFAoYGRlh2LBhCAgI4GZmI0aMgJmZmbZL17jHIlw6UlxcjLS0NKSlpSEjI4P7kojFYgCAlZUVFzQ+Pj4YNGgQ3N3d4e7uDnt7ey1Xz/SWxsZGFBQUcENWVhZycnKQnZ2NoqIiAHe7Pm2dSfn4+GDEiBHw9/eHj4+Pzu7N0bTHOlw6UlJSguzsbG4u1Pp/SUkJ11uZsbGxWti4u7tj4MCBcHNzg4uLCxwcHPr8OvPjoqKiAhUVFSgqKlILkYKCAhQWFqKqqop7rJ2dHby8vODr6wsfHx/4+PjA19cXHh4e7PO+DwuXblAoFCguLlb74uXn53O3RSKRWleJDg4OcHBw4MLm/r82Njaws7Njx+togFQqRXV1NaqqqlBWVoaKigqUlJS0+/fevndtbW3VZhat/7fOSFqvisA8GAuXHqRQKFBaWgqRSISysjK1v+Xl5SgtLUV5ebnanBC428G0jY1Nm8HW1ha2trawsLCAlZUVhEIhzMzMuMHS0hJmZmb9do5ZW1sLsViMxsZGiMViiMVi1NbWorGxEfX19aiuruaGyspKtdtNTU1qr9V6BYT/197drDgIQ1EAPtpYS42pIIJQ+v6LeTJx0SYRJfjXRYlUzWwGpDPO/UDUKKILjxfFxBXy1+sVeZ7jdrutevsnP0fh8gHGGBRF4bwpllNZllBKTUO1uIRhiDiOIYRAkiTwPG+aCyFwOBzAOUcQBDifzwjDEKfTafbHtG1fYow5Xz4aY1DX9ap9GAZIKaf1ruugtZ6122uRUmIYBmitp/3ew+Q7nHMIIWZBnGWZM6DTNEWe5//iBepvQ+Hyh7ie4nbZbrvf7xjHEY/HA8CrB/xxHKGUQt/3qKoKbduirmsYY6Zj2xt9qWmaVRUAvKotIYTzPG2gAa/xfOynfjscx+Vyge/7iOMYjDFEUYTj8YgoiqaqzAble6Vmq7W9fbLdKwoXQsgmqC8DQsgmKFwIIZugcCGEbIIB+Pr0SRBC9ucJF0ooZ0tZzIoAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.visualize()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "r = p.emit(speakers)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "quantized_p = Pipeline()\n", "quantized_frame = quantized_p.foreach_map(load_wav).map(quantized_model)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "quantized_r = quantized_p.emit(speakers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Calculate similarity" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1. , 0.85895569, 0.85036787, 0.919863 ],\n", " [0.85895569, 1. , 0.88895719, 0.85086463],\n", " [0.85036787, 0.88895719, 1. , 0.86070389],\n", " [0.919863 , 0.85086463, 0.86070389, 1. ]])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from scipy.spatial.distance import cdist\n", "\n", "1 - cdist(r['speaker-vector'], r['speaker-vector'], metric = 'cosine')" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1. , 0.86325292, 0.8574443 , 0.92556189],\n", " [0.86325292, 1. , 0.88897938, 0.85685812],\n", " [0.8574443 , 0.88897938, 1. , 0.86453416],\n", " [0.92556189, 0.85685812, 0.86453416, 1. ]])" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from scipy.spatial.distance import cdist\n", "\n", "1 - cdist(quantized_r['speaker-vector'], quantized_r['speaker-vector'], metric = 'cosine')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remember, our files are,\n", "\n", "```python\n", "['speech/example-speaker/khalil-nooh.wav',\n", " 'speech/example-speaker/mas-aisyah.wav',\n", " 'speech/example-speaker/shafiqah-idayu.wav',\n", " 'speech/example-speaker/husein-zolkepli.wav']\n", "```\n", "\n", "If we check first row,\n", "\n", "```python\n", "[1. , 0.86325292, 0.8574443 , 0.92556189]\n", "```\n", "\n", "second biggest is `0.91986299`, which is 4th column, for `husein-zolkepli.wav`. So the speaker vector knows `khalil-nooh.wav` sounds similar to `husein-zolkepli.wav` due to gender factor." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reference\n", "\n", "1. deep-speaker, https://github.com/philipperemy/deep-speaker, exported from Keras to TF checkpoint.\n", "2. vggvox-v1, https://github.com/linhdvu14/vggvox-speaker-identification, exported from Keras to TF checkpoint.\n", "3. vggvox-v2, https://github.com/WeidiXie/VGG-Speaker-Recognition, exported from Keras to TF checkpoint.\n", "4. speakernet, Nvidia NeMo, https://github.com/NVIDIA/NeMo/tree/main/examples/speaker_recognition, exported from Pytorch to TF.\n", "5. VoxCeleb2, speaker verification dataset, http://www.robots.ox.ac.uk/~vgg/data/voxceleb/index.html#about" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" } }, "nbformat": 4, "nbformat_minor": 4 }