Как использовать трансформатор для классификации аудио

Особое внимание к позиционному кодированию и экспериментам с ним.

Преобразователь пришел для решения различных проблем в области NPL, в основном в задачах seq2seq, где RNN получают вычислительную неэффективность, когда последовательности становятся длинными [1].

В статье Внимание - это все, что вам нужно [1] представлена ​​новая архитектура под названием Transformer, которая следует схеме кодировщика-декодера.

Прежде чем наш ввод перейдет на первый уровень кодировщика, каждое слово будет встроено и добавлена ​​позиционная кодировка, затем:

  1. Это перетекает к многоголовому вниманию.
  2. Затем реализуется остаточное соединение, которое добавляется к результату Multi-Head Attention. После этого применяется нормализация слоя. Это означает, что результатом этого шага будет LayerNorm (x + Sublayer (x)), где Sublayer - это функция, реализованная самим подслоем.
  3. Позиционная полностью подключенная сеть с прямой связью.
  4. Снова применяются остаточное соединение и нормализация слоев.
  5. Если у вас более одного уровня кодировщика, он возвращается к шагу 1 для следующего уровня кодировщика.
  6. Выход N уровня кодера (последний) - это тот, который идет на каждый уровень декодера.

Для декодера аналогичен, но имеет два отличия:

  1. Вход декодера замаскирован, что позволяет декодеру не видеть «будущее» и
  2. Перед тем, как перейти к позиционно полностью подключенной сети с прямой связью, он имеет два режима Multi-Head Attention в ряд. Один из них предназначен для выхода кодировщика, а другой - для входа декодера.

Наконец, после последнего остаточного соединения и нормализации уровня выходные данные декодера проходят линейную проекцию, а затем softmax, которая получает вероятности для каждого слова.

Это краткое объяснение того, как это работает, но я настоятельно рекомендую вам взглянуть на это руководство для более глубокого объяснения и понимания.

Теперь давайте узнаем, как реализовать это с аудиоданными.

Набор данных

Мы будем использовать набор данных FreeSound AudioTagging из Kaggle [5], где у нас есть два набора данных для обучения: курируемые и зашумленные подмножества. Мы будем использовать специально подобранное подмножество, которое подразумевает общую продолжительность 10,5 часов, 4970 аудиоклипов и их продолжительность от 0,3 до 30 секунд. Полное описание находится здесь.

Предварительная обработка

Перед загрузкой нашего алгоритма нам нужно обработать наши данные и получить мел-спектрограмму для каждого аудиоклипа. Мел-спектрограмма - это спектрограмма в мел-шкале, которая показывает, как люди слышат звуки. Например, мы замечаем большое изменение частоты 100 Гц, когда она меняется на 150 Гц, но это не происходит так же, когда частота составляет 10000 Гц, а затем 10050 Гц, поэтому мел-спектрограмма показывает большее изменение в частоте в первом случае даже абсолютная величина изменения одинакова.

Нам нужно определить некоторые параметры того, как мы будем обрабатывать наши аудиоклипы. Параметр n_fft показывает, сколько интервалов у нас будет для распределения разных частот, больше интервалов означает, что мы можем обнаружить больше частот и, следовательно, у нас будет лучшее разрешение по этой вертикальной оси.

Длина шага следует той же идее, но для горизонтальной оси, поэтому меньшая длина шага дает нам больше временных шагов. Например, если у нас есть продолжительность 7 секунд, частота дискретизации 44100 и длина скачка 128, у нас будет около 2411 временных шагов.

number_time_steps= (duration * sampling_rate) / hop_length
number_time_steps= samples / hop_length

Мы также обрежем аудиоклипы, если они длиннее, чем «сэмплы», или дополним их, если они короче «сэмплов». Это связано с тем, что, как мы описали в предыдущем разделе, их продолжительность составляет от 0,3 до 30 секунд, и легче работать с аудиоклипами, продолжительность которых одинакова.

Другая предварительная обработка, которую мы можем сделать, - это изменить форму наших данных [2], применив следующую формулу, уменьшив количество временных шагов, которые у нас есть:

В следующем блоке кода мы устанавливаем настройку предварительной обработки:

class conf:
sampling_rate = 44100
duration = 4  #in seconds
hop_length = 300
fmin = 20
fmax = sampling_rate // 2
n_mels = 128
n_fft = n_mels * 20
samples = sampling_rate * duration

Если вы хотите узнать больше, вы можете проверить этот курс на Coursera и / или это ядро на Kaggle.

Эксперимент

Для нашего эксперимента мы хотим сравнить производительность с использованием линейной проекции перед добавлением позиционного кодирования [3] со сценарием, где мы просто добавляем позиционное кодирование к mel-спектрограмме. Последнее может быть вредным для процесса обучения [2], и это причина использования линейной проекции, потому что мел-спектрограмма не изучается, как встраивание слов.

В этом эксперименте мы подберем 20 моделей по 10 эпох, каждая с одинаковой конфигурацией, за исключением того, что 10 моделей будут обучены с линейной проекцией, а остальные - без нее. После этого мы выберем наивысшую val_accuracy для каждой модели, учитывая все ее эпохи. Наконец, мы получим среднее значение для обоих сценариев, а затем сравним их.

Архитектура модели

Для нашей цели мы будем использовать только структуру кодировщика, и его выход будет направлен на полностью связанный слой с функцией активации softmax для классификации различных звуков.

Мы будем иметь:

NUM_LAYERS = 2 
D_MODEL = X.shape[2] ## Number of mel bands
NUM_HEADS = 4
UNITS = 1024
DROPOUT = 0.1
TIME_STEPS = X.shape[1] 
OUTPUT_SIZE=80

Для реализации этого мы будем использовать большую часть кода из Tensorflow Tutorial, но адаптируя его под нашу задачу. Полный код находится здесь.

Результаты

После проведения эксперимента среднее значение val_accuracy для каждого сценария будет следующим:

Стандартное отклонение составляет:

Выводы

Во-первых, точность очень низкая для обоих сценариев. Мы можем объяснить это тем фактом, что было предложено 48 слоев [3], 2048 нейронов, 8 головок и размерность модели 512. Мы только обучили их с 2 слоями, 1024 нейронами, 4 головами и размерностью модели 128 .

Во-вторых, использование описанной здесь линейной проекции [3] дает в среднем улучшение на 17% по сравнению с простым добавлением позиционного кодирования.

Наконец, есть много возможностей для дополнительных экспериментов, таких как добавление уровней объединения, реализация другого типа позиционного кодирования, реализация расписания скорости обучения, описанного в [1], изменение настройки преобразователя (больше слоев [3], количество Heads и т. д.) и применяя к аудиоклипам другую предварительную обработку или проектирование функций.

Ссылки

[1] Васвани А., Шазир Н., Пармар Н., Ушкорейт Дж., Гомес А. Н., Кайзер Л. и Полосухин И. (2017, 6 декабря). Внимание - все, что вам нужно. Получено с https://arxiv.org/abs/1706.03762

[2] Спербер М., Ниеуэс Дж., Нойбиг Г., Штюкер С. и Вайбель А. (18 июня 2018 г.). Акустические модели с самовниманием. Источник https://arxiv.org/abs/1803.09519

[3] Pham, N.-Q., Nguyen, T.-S., Niehues, J., Muller, M., Stuker, S., & Waibel, A. (3 мая 2019 г.). Сети с очень глубоким самовниманием для сквозного распознавания речи. Получено с https://arxiv.org/abs/1904.13377.

[4] Учебное пособие по чат-боту-трансформеру с Tensorflow 2.0. Получено с https://medium.com/tensorflow/a-transformer-chatbot-tutorial-with-tensorflow-2-0-88bf59e66fe2

[5] Эдуардо Фонсека, Манодж Плакал, Фредерик Фонт, Дэниел П. У. Эллис, Ксавье Серра. Аудиометки с шумными метками и минимальным контролем. В материалах семинара DCASE2019, Нью-Йорк, США (2019). Получено с https://arxiv.org/abs/1906.02975.

[6] https://www.kaggle.com/maxwell110/beginner-s-guide-to-audio-data-2

[7] https://www.kaggle.com/daisukelab/cnn-2d-basic-solution-powered-by-fast-ai

Вам понравился этот пост?
Порекомендуйте, поделившись им в социальных сетях

Хотите вместе со мной читать и изучать науку о данных?
Подписывайтесь на меня на Medium