{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "38a5ef11-0969-481a-948f-76dea6aa60dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://www.geeksforgeeks.org/audio-recognition-in-tensorflow/\n",
    "import os \n",
    "import tensorflow as tf \n",
    "import numpy as np \n",
    "import seaborn as sns \n",
    "import pathlib \n",
    "from IPython import display \n",
    "from matplotlib import pyplot as plt \n",
    "from sklearn.metrics import classification_report\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d39d4708-1f1e-41b7-87b8-a1f4ad4c1dc0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 800 files belonging to 2 classes.\n",
      "Using 640 files for training.\n",
      "Using 160 files for validation.\n",
      "label names: ['audioempty' 'audiowatermark']\n"
     ]
    }
   ],
   "source": [
    "# Using audio_dataset_from_directory function to create dataset with audio data \n",
    "training_set, validation_set = tf.keras.utils.audio_dataset_from_directory( \n",
    "\tdirectory='audiodataset', \n",
    "\tbatch_size=16, \n",
    "\tvalidation_split=0.2, \n",
    "\toutput_sequence_length=44100,#16000, \n",
    "\tseed=0, \n",
    "\tsubset='both') \n",
    "\n",
    "# Extracting audio labels \n",
    "label_names = np.array(training_set.class_names) \n",
    "print(\"label names:\", label_names)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "00107449-0ecf-482c-9e61-c713e833f9c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Defining the squeeze function \n",
    "def squeeze(audio, labels): \n",
    "  audio = tf.squeeze(audio, axis=-1) \n",
    "  return audio, labels \n",
    "  \n",
    "# Applying the function on the dataset obtained from previous step \n",
    "training_set = training_set.map(squeeze, tf.data.AUTOTUNE) \n",
    "validation_set = validation_set.map(squeeze, tf.data.AUTOTUNE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "3530acf1-007a-4831-8173-adce6d0e8c6b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "                <audio  controls=\"controls\" >\n",
       "                    <source src=\"data:audio/wav;base64,[encoded data, 117660 characters]\" type=\"audio/wav\" />\n",
       "                    Your browser does not support the audio element.\n",
       "                </audio>\n",
       "              "
      ],
      "text/plain": [
       "<IPython.lib.display.Audio object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Visualize the waveform \n",
    "audio, label = next(iter(training_set)) \n",
    "display.display(display.Audio(audio[0], rate=44100))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "74637a53-a921-4d51-9bd5-b6b17d661ada",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 59940 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 250536 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 66660 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 288644 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 47396 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 300804 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 38612 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 308760 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 74196 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 248768 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 29200 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 314908 characters]",
      "text/plain": [
       "<Figure size 1000x300 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the waveform \n",
    "def plot_wave(waveform, label): \n",
    "\tplt.figure(figsize=(10, 3)) \n",
    "\tplt.title(label) \n",
    "\tplt.plot(waveform) \n",
    "\tplt.xlim([0, 44100]) \n",
    "\tplt.ylim([-1, 1]) \n",
    "\tplt.xlabel('Time') \n",
    "\tplt.ylabel('Amplitude') \n",
    "\tplt.grid(True) \n",
    "\n",
    "# Convert waveform to spectrogram \n",
    "def get_spectrogram(waveform): \n",
    "\tspectrogram = tf.signal.stft(waveform, frame_length=255, frame_step=128) \n",
    "\tspectrogram = tf.abs(spectrogram) ; spectrogram = tf.cast(spectrogram, tf.float64) # Change Data Type\n",
    "\treturn spectrogram[..., tf.newaxis]\n",
    "\n",
    "# Plot the spectrogram \n",
    "def plot_spectrogram(spectrogram, label): \n",
    "\tspectrogram = np.squeeze(spectrogram, axis=-1) \n",
    "\tlog_spec = np.log(spectrogram.T + np.finfo(float).eps) \n",
    "\tplt.figure(figsize=(10, 3)) \n",
    "\tplt.title(label) \n",
    "\tplt.imshow(log_spec, aspect='auto', origin='lower') \n",
    "\tplt.colorbar(format='%+2.0f dB') \n",
    "\tplt.xlabel('Time') \n",
    "\tplt.ylabel('Frequency') \n",
    "\n",
    "for i in range(6):\n",
    "    # Plotting the waveform and the spectrogram of a random sample \n",
    "    audio, label = next(iter(training_set)) \n",
    "    \n",
    "    # Plot the wave with its label name \n",
    "    plot_wave(audio[i], label_names[label[i]]) \n",
    "    \n",
    "    # Plot the spectrogram with its label name \n",
    "    plot_spectrogram(get_spectrogram(audio[i]), label_names[label[i]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "14fd485c-2eaa-45c9-973a-65487725c35b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Creating spectrogram dataset from waveform or audio data \n",
    "def get_spectrogram_dataset(dataset): \n",
    "\tdataset = dataset.map( \n",
    "\t\tlambda x, y: (get_spectrogram(x), y), \n",
    "\t\tnum_parallel_calls=tf.data.AUTOTUNE) \n",
    "\treturn dataset \n",
    "\n",
    "# Applying the function on the audio dataset \n",
    "train_set = get_spectrogram_dataset(training_set) \n",
    "validation_set = get_spectrogram_dataset(validation_set) \n",
    "\n",
    "# Dividing validation set into two equal val and test set \n",
    "val_set = validation_set.take(validation_set.cardinality() // 2) \n",
    "test_set = validation_set.skip(validation_set.cardinality() // 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "cbf23516-138b-4189-9a5e-52ec52df50cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train set shape: (None, 343, 129, 1)\n",
      "Validation set shape: (None, 343, 129, 1)\n",
      "Testing set shape: (None, 343, 129, 1)\n"
     ]
    }
   ],
   "source": [
    "train_set_shape = train_set.element_spec[0].shape \n",
    "val_set_shape = val_set.element_spec[0].shape \n",
    "test_set_shape = test_set.element_spec[0].shape \n",
    "\n",
    "print(\"Train set shape:\", train_set_shape) \n",
    "print(\"Validation set shape:\", val_set_shape) \n",
    "print(\"Testing set shape:\", test_set_shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58989d4d-3da1-4be4-8b86-c204b23ac9e0",
   "metadata": {},
   "source": [
    "# *Можно создать последовательную модель*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "9e1b1eeb-fae7-452e-8d49-186823802e48",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input shape: (343, 129, 1)\n",
      "Model: \"sequential_4\"\n",
      "_________________________________________________________________\n",
      " Layer (type)                Output Shape              Param #   \n",
      "=================================================================\n",
      " resizing_4 (Resizing)       (None, 64, 64, 1)         0         \n",
      "                                                                 \n",
      " normalization_4 (Normaliza  (None, 64, 64, 1)         3         \n",
      " tion)                                                           \n",
      "                                                                 \n",
      " conv2d_63 (Conv2D)          (None, 62, 62, 64)        640       \n",
      "                                                                 \n",
      " conv2d_64 (Conv2D)          (None, 60, 60, 128)       73856     \n",
      "                                                                 \n",
      " conv2d_65 (Conv2D)          (None, 58, 58, 256)       295168    \n",
      "                                                                 \n",
      " conv2d_66 (Conv2D)          (None, 56, 56, 512)       1180160   \n",
      "                                                                 \n",
      " conv2d_67 (Conv2D)          (None, 54, 54, 512)       2359808   \n",
      "                                                                 \n",
      " max_pooling2d_11 (MaxPooli  (None, 27, 27, 512)       0         \n",
      " ng2D)                                                           \n",
      "                                                                 \n",
      " dropout_19 (Dropout)        (None, 27, 27, 512)       0         \n",
      "                                                                 \n",
      " flatten_4 (Flatten)         (None, 373248)            0         \n",
      "                                                                 \n",
      " dense_25 (Dense)            (None, 512)               191103488 \n",
      "                                                                 \n",
      " dropout_20 (Dropout)        (None, 512)               0         \n",
      "                                                                 \n",
      " dense_26 (Dense)            (None, 512)               262656    \n",
      "                                                                 \n",
      " dense_27 (Dense)            (None, 256)               131328    \n",
      "                                                                 \n",
      " dropout_21 (Dropout)        (None, 256)               0         \n",
      "                                                                 \n",
      " dense_28 (Dense)            (None, 64)                16448     \n",
      "                                                                 \n",
      " dropout_22 (Dropout)        (None, 64)                0         \n",
      "                                                                 \n",
      " dense_29 (Dense)            (None, 2)                 130       \n",
      "                                                                 \n",
      "=================================================================\n",
      "Total params: 195423685 (745.48 MB)\n",
      "Trainable params: 195423682 (745.48 MB)\n",
      "Non-trainable params: 3 (16.00 Byte)\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "# Defining the model \n",
    "def get_model(input_shape, num_labels): \n",
    "\tmodel = tf.keras.Sequential([ \n",
    "\t\ttf.keras.layers.Input(shape=input_shape), \n",
    "\t\t# Resizing the input to a square image of size 64 x 64 and normalizing it \n",
    "\t\ttf.keras.layers.Resizing(64, 64), \n",
    "\t\ttf.keras.layers.Normalization(), \n",
    "\t\t\n",
    "\t\t# Convolution layers followed by MaxPooling layer \n",
    "\t\ttf.keras.layers.Conv2D(64, 3, activation='relu'), \n",
    "\t\ttf.keras.layers.Conv2D(128, 3, activation='relu'), \n",
    "        tf.keras.layers.Conv2D(256, 3, activation='relu'),\n",
    "        tf.keras.layers.Conv2D(512, 3, activation='relu'),\n",
    "        tf.keras.layers.Conv2D(512, 3, activation='relu'),\n",
    "\t\ttf.keras.layers.MaxPooling2D(), \n",
    "\t\ttf.keras.layers.Dropout(0.5), \n",
    "\t\ttf.keras.layers.Flatten(), \n",
    "\t\t\n",
    "\t\t# Dense layer \n",
    "        tf.keras.layers.Dense(512, activation='relu'), \n",
    "\t\ttf.keras.layers.Dropout(0.5),\n",
    "        tf.keras.layers.Dense(512, activation='relu'),\n",
    "\t\ttf.keras.layers.Dense(256, activation='relu'), \n",
    "\t\ttf.keras.layers.Dropout(0.5),\n",
    "        tf.keras.layers.Dense(64, activation='relu'),\n",
    "        tf.keras.layers.Dropout(0.5),\n",
    "\t\t\n",
    "\t\t# Softmax layer to get the label prediction \n",
    "\t\ttf.keras.layers.Dense(num_labels, activation='softmax')\n",
    "\t]) \n",
    "\t# Printing model summary \n",
    "\tmodel.summary() \n",
    "\treturn model \n",
    "\n",
    "# Getting input shape from the sample audio and number of classes \n",
    "input_shape = next(iter(train_set))[0][0].shape \n",
    "print(\"Input shape:\", input_shape) \n",
    "num_labels = len(label_names) \n",
    "\n",
    "# Creating a model \n",
    "model = get_model(input_shape, num_labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "a5558042-7fad-43bc-9d48-1b4d5314a8c2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 42412 characters]",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import keras\n",
    "keras.utils.plot_model(model, expand_nested=True, dpi=60, show_shapes=True, to_file='audioclass.png')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca1bdf80-81d8-4712-9db5-999255be28ce",
   "metadata": {},
   "source": [
    "# *Или можно создать ResNet-подобную модель*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "90a211b8-5701-4772-98ed-29bcfc6feb32",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input shape: (343, 129, 1)\n",
      "Model: \"toy_resnet\"\n",
      "__________________________________________________________________________________________________\n",
      " Layer (type)                Output Shape                 Param #   Connected to                  \n",
      "==================================================================================================\n",
      " img (InputLayer)            [(None, 343, 129, 1)]        0         []                            \n",
      "                                                                                                  \n",
      " conv2d_55 (Conv2D)          (None, 341, 127, 32)         320       ['img[0][0]']                 \n",
      "                                                                                                  \n",
      " conv2d_56 (Conv2D)          (None, 339, 125, 128)        36992     ['conv2d_55[0][0]']           \n",
      "                                                                                                  \n",
      " max_pooling2d_10 (MaxPooli  (None, 113, 41, 128)         0         ['conv2d_56[0][0]']           \n",
      " ng2D)                                                                                            \n",
      "                                                                                                  \n",
      " conv2d_57 (Conv2D)          (None, 113, 41, 128)         147584    ['max_pooling2d_10[0][0]']    \n",
      "                                                                                                  \n",
      " conv2d_58 (Conv2D)          (None, 113, 41, 128)         147584    ['conv2d_57[0][0]']           \n",
      "                                                                                                  \n",
      " add_12 (Add)                (None, 113, 41, 128)         0         ['conv2d_58[0][0]',           \n",
      "                                                                     'max_pooling2d_10[0][0]']    \n",
      "                                                                                                  \n",
      " conv2d_59 (Conv2D)          (None, 113, 41, 64)          73792     ['add_12[0][0]']              \n",
      "                                                                                                  \n",
      " conv2d_60 (Conv2D)          (None, 113, 41, 128)         73856     ['conv2d_59[0][0]']           \n",
      "                                                                                                  \n",
      " add_13 (Add)                (None, 113, 41, 128)         0         ['conv2d_60[0][0]',           \n",
      "                                                                     'add_12[0][0]']              \n",
      "                                                                                                  \n",
      " conv2d_61 (Conv2D)          (None, 113, 41, 128)         147584    ['add_13[0][0]']              \n",
      "                                                                                                  \n",
      " add_14 (Add)                (None, 113, 41, 128)         0         ['conv2d_61[0][0]',           \n",
      "                                                                     'add_13[0][0]']              \n",
      "                                                                                                  \n",
      " conv2d_62 (Conv2D)          (None, 113, 41, 64)          73792     ['add_14[0][0]']              \n",
      "                                                                                                  \n",
      " global_average_pooling2d_1  (None, 64)                   0         ['conv2d_62[0][0]']           \n",
      "  (GlobalAveragePooling2D)                                                                        \n",
      "                                                                                                  \n",
      " dense_22 (Dense)            (None, 256)                  16640     ['global_average_pooling2d_1[0\n",
      "                                                                    ][0]']                        \n",
      "                                                                                                  \n",
      " dropout_17 (Dropout)        (None, 256)                  0         ['dense_22[0][0]']            \n",
      "                                                                                                  \n",
      " dense_23 (Dense)            (None, 64)                   16448     ['dropout_17[0][0]']          \n",
      "                                                                                                  \n",
      " dropout_18 (Dropout)        (None, 64)                   0         ['dense_23[0][0]']            \n",
      "                                                                                                  \n",
      " dense_24 (Dense)            (None, 2)                    130       ['dropout_18[0][0]']          \n",
      "                                                                                                  \n",
      "==================================================================================================\n",
      "Total params: 734722 (2.80 MB)\n",
      "Trainable params: 734722 (2.80 MB)\n",
      "Non-trainable params: 0 (0.00 Byte)\n",
      "__________________________________________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "# https://proproprogs.ru/tensorflow/keras-sozdaem-resnet-podobnuyu-arhitekturu-dlya-klassifikacii-izobrazheniy-cifar-10\n",
    "from tensorflow import keras\n",
    "from tensorflow.keras import layers\n",
    "\n",
    "input_shape = next(iter(train_set))[0][0].shape \n",
    "print(\"Input shape:\", input_shape) \n",
    "num_labels = len(label_names) \n",
    "\n",
    "\n",
    "inputs = keras.Input(shape=input_shape, name=\"img\")\n",
    "x = layers.Conv2D(32, 3, activation=\"relu\")(inputs)\n",
    "x = layers.Conv2D(128, 3, activation=\"relu\")(x)\n",
    "block_1_output = layers.MaxPooling2D(3)(x)\n",
    "x = layers.Conv2D(128, 3, activation=\"relu\", padding=\"same\")(block_1_output)\n",
    "x = layers.Conv2D(128, 3, activation=\"relu\", padding=\"same\")(x)\n",
    "block_2_output = layers.add([x, block_1_output])\n",
    "x = layers.Conv2D(64, 3, activation=\"relu\", padding=\"same\")(block_2_output)\n",
    "x = layers.Conv2D(128, 3, activation=\"relu\", padding=\"same\")(x)\n",
    "block_3_output = layers.add([x, block_2_output])\n",
    "x = layers.Conv2D(128, 3, activation=\"relu\", padding=\"same\")(block_3_output)\n",
    "block_4_output = layers.add([x, block_3_output])\n",
    "x = layers.Conv2D(64, 3, activation=\"relu\", padding=\"same\")(block_4_output)\n",
    "x = layers.GlobalAveragePooling2D()(x)\n",
    "x = layers.Dense(256, activation=\"relu\")(x)\n",
    "x = layers.Dropout(0.5)(x)\n",
    "x = layers.Dense(64, activation=\"relu\")(x)\n",
    "x = layers.Dropout(0.5)(x)\n",
    "outputs = layers.Dense(num_labels, activation='softmax')(x)\n",
    "\n",
    "model = keras.Model(inputs, outputs, name=\"toy_resnet\")\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "d571db86-8177-4672-b180-61a446e9a097",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 56872 characters]",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "keras.utils.plot_model(model, expand_nested=True, dpi=60, show_shapes=True, to_file='toy_resnet_deep-audioclass.png')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9648b708-4b60-4475-a210-1d892da0d612",
   "metadata": {},
   "source": [
    "**Переобучение** - распространенная проблема при обучении нейронных сетей. Это происходит, когда модель учится запоминать обучающие данные, а не обобщать на их основе шаблоны, что приводит к снижению производительности при работе с невидимыми данными. В то время как различные методы регуляризации, такие как отсев и снижение веса, могут помочь бороться с переобучением, ранняя остановка выделяется как простой, но эффективный метод предотвращения переобучения нейронных сетей.  \n",
    "\n",
    "*Ранняя остановка* — это стратегия в машинном обучении, которая заключается в завершении алгоритма обучения, когда на протяжении заранее заданного числа итераций не удаётся улучшить параметры по сравнению с наилучшими, запомненными ранее. \r\n",
    "Ранняя остановка позволяет управлять эффективной ёмкостью модели, определяя, сколько шагов ей может потребоваться для аппроксимации обучающего набор \r\n",
    "\r\n",
    "Эта стратегия является самой распространённой формой регуляризации в машинном обучении и отличается простотой и эффективностью. Её можно использовать автономно или в сочетании с другими стратегиями регуляриза\n",
    "\n",
    "\n",
    "## Преимущества ранней остановки:  \r",
    "+ \n",
    "Предотвращает переобучение: Основная цель ранней остановки - предотвратить переобучение путем мониторинга производительности модели на валидационном наборе данных во время обучения. Останавливая процесс обучения, когда ошибка проверки начинает увеличиваться, ранняя остановка предотвращает чрезмерную сложность модели и запоминание шума в обучающих данных\n",
    "\n",
    ".+ \r\n",
    "Экономит вычислительные ресурсы: Обучение глубоких нейронных сетей может быть трудоемким с точки зрения вычислений, особенно с большими наборами данных и сложной архитектурой. Ранняя остановка помогает экономить вычислительные ресурсы за счет прекращения процесса обучения, когда дальнейшее улучшение производительности проверки маловероятно. Это приводит к сокращению времени обучения и вычислительных затра\n",
    "\n",
    "т+ .\r\n",
    "Улучшает обобщение: Ограничивая переобучение, ранняя остановка побуждает модель лучше обобщать невидимые данные. Модели, обученные с использованием ранней остановки, демонстрируют повышенную производительность в невидимых наборах данных или реальных приложениях, поскольку они улавливают основные закономерности, не подверженные влиянию шума или несущественных детал\n",
    "\n",
    "е+ й.\r\n",
    "Простая реализация: В отличие от некоторых других методов регуляризации, которые требуют настройки гиперпараметров или модификации архитектуры модели, ранняя остановка проста в реализации и требует минимальных дополнительных усилий. Это включает мониторинг ошибки проверки во время обучения и остановку процесса, когда выполняется заранее определенный критерий, такой как отсутствие улучшений в течение определенного количества э\n",
    "\n",
    "\n",
    "Mодель, обученная с использованием ранней остановки, менее склонна к переобучению и, скорее всего, лучше обобщит невидимые данные.\n",
    "https://www.geeksforgeeks.org/using-early-stopping-to-reduce-overfitting-in-neural-networks/х.\n",
    "\n",
    "ции."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "90a3a627-a955-4c4c-b656-468db7f1ae38",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "40/40 [==============================] - 93s 2s/step - loss: 0.7011 - accuracy: 0.4875 - val_loss: 0.6961 - val_accuracy: 0.4000\n",
      "Epoch 2/100\n",
      "40/40 [==============================] - 91s 2s/step - loss: 0.6932 - accuracy: 0.5141 - val_loss: 0.6978 - val_accuracy: 0.4000\n",
      "Epoch 3/100\n",
      "40/40 [==============================] - 98s 2s/step - loss: 0.6939 - accuracy: 0.5000 - val_loss: 0.6967 - val_accuracy: 0.4000\n",
      "Epoch 4/100\n",
      "40/40 [==============================] - 98s 2s/step - loss: 0.6935 - accuracy: 0.5125 - val_loss: 0.6982 - val_accuracy: 0.4000\n"
     ]
    }
   ],
   "source": [
    "model.compile( \n",
    "\toptimizer=tf.keras.optimizers.Adam(), \n",
    "\tloss=tf.keras.losses.SparseCategoricalCrossentropy(), \n",
    "\tmetrics=['accuracy'], \n",
    ") \n",
    "\n",
    "callback = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=2)\n",
    "\n",
    "EPOCHS = 100\n",
    "history = model.fit( \n",
    "\ttrain_set, \n",
    "\tvalidation_data=val_set, \n",
    "\tepochs=EPOCHS,\n",
    "    callbacks=[callback]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "a063e27a-d131-49d1-92c0-8e47ee80a34b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 63792 characters]",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plotting the history \n",
    "metrics = history.history \n",
    "plt.figure(figsize=(10, 5)) \n",
    "\n",
    "# Plotting training and validation loss \n",
    "plt.subplot(1, 2, 1) \n",
    "plt.plot(history.epoch, metrics['loss'], metrics['val_loss']) \n",
    "plt.legend(['loss', 'val_loss']) \n",
    "plt.xlabel('Epoch') \n",
    "plt.ylabel('Loss') \n",
    "plt.grid()\n",
    "\n",
    "# Plotting training and validation accuracy \n",
    "plt.subplot(1, 2, 2) \n",
    "plt.plot(history.epoch, metrics['accuracy'], metrics['val_accuracy']) \n",
    "plt.legend(['accuracy', 'val_accuracy']) \n",
    "plt.xlabel('Epoch') \n",
    "plt.ylabel('Accuracy')\n",
    "plt.grid()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "1a5fbf9f-0abb-4ed4-b786-4a1c9b9f60ef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5/5 [==============================] - 6s 641ms/step\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 19056 characters]",
      "text/plain": [
       "<Figure size 1000x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Confusion matrix \n",
    "y_pred = np.argmax(model.predict(test_set), axis=1) \n",
    "y_true = np.concatenate([y for x, y in test_set], axis=0) \n",
    "cm = tf.math.confusion_matrix(y_true, y_pred) \n",
    "\n",
    "# Plotting the confusion matrix \n",
    "plt.figure(figsize=(10, 8)) \n",
    "sns.heatmap(cm, annot=True, fmt='g') \n",
    "plt.xlabel('Predicted') \n",
    "plt.ylabel('Actual') \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "aabea240-518e-4925-9191-18ebf8935edb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.00      0.00      0.00        38\n",
      "           1       0.53      1.00      0.69        42\n",
      "\n",
      "    accuracy                           0.53        80\n",
      "   macro avg       0.26      0.50      0.34        80\n",
      "weighted avg       0.28      0.53      0.36        80\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Peter\\AppData\\Local\\miniconda3\\Lib\\site-packages\\sklearn\\metrics\\_classification.py:1497: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
      "  _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
      "C:\\Users\\Peter\\AppData\\Local\\miniconda3\\Lib\\site-packages\\sklearn\\metrics\\_classification.py:1497: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
      "  _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
      "C:\\Users\\Peter\\AppData\\Local\\miniconda3\\Lib\\site-packages\\sklearn\\metrics\\_classification.py:1497: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
      "  _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n"
     ]
    }
   ],
   "source": [
    "report = classification_report(y_true, y_pred) \n",
    "print(report)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "4eae2cb7-a4f7-41f5-b1be-85573fbb9da4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "                <audio  controls=\"controls\" >\n",
       "                    <source src=\"data:audio/wav;base64,[encoded data, 117660 characters]\" type=\"audio/wav\" />\n",
       "                    Your browser does not support the audio element.\n",
       "                </audio>\n",
       "              "
      ],
      "text/plain": [
       "<IPython.lib.display.Audio object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 18596 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "path = 'audiodataset/audiowatermark/11.wav'\n",
    "Input = tf.io.read_file(str(path)) \n",
    "x, sample_rate = tf.audio.decode_wav(Input, desired_channels=1, desired_samples=44100,) \n",
    "audio, labels = squeeze(x, 'audiowatermark') \n",
    "\n",
    "waveform = audio \n",
    "display.display(display.Audio(waveform, rate=44100)) \n",
    "\n",
    "x = get_spectrogram(audio) \n",
    "x = tf.expand_dims(x, axis=0) \n",
    "\n",
    "prediction = model(x) \n",
    "plt.bar(label_names, tf.nn.softmax(prediction[0])) \n",
    "plt.title('Prediction : '+ label_names[np.argmax(prediction, axis=1).item()]) \n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
