Вы когда-нибудь задумывались, можем ли мы сделать так, чтобы радиостанция или телеканал автоматически менялись при запуске рекламы? Что ж, многие из нас в какой-то момент думали, может ли устройство менять группу при прослушивании рекламы и настраиваться (переключаться) на группу, в которой играет песня 😄

Что ж, хорошая новость в том, что это возможно с машинным обучением!

Итак, я делюсь этим небольшим «экспериментом», который дает понимание того, как мы этого достигаем. В конце этого руководства у нас будет обученная модель, которая при передаче нового аудиофайла предскажет, является ли это рекламой или песенной дорожкой.

(В дальнейшем мы можем реализовать это в приложении для Android, которое будет прослушивать прямую трансляцию и отправлять директиву на смену радиостанции. Но я расскажу об этом позже)

Примечание:

Давайте относиться к этому только как к забавному эксперименту! Я не уверен, будет ли это разрешено компаниями или будет ли это этично.

Это не подробное руководство по машинному обучению. Вы можете пропустить это, если ожидаете основ машинного обучения или нейронных сетей. Мы обязательно рассмотрим некоторые концепции в части кодирования, которые соответствуют нашему варианту использования.

Итак, приступим!

Шаги:

  • Введение (концепция и понимание)
  • Предварительная обработка
  • Обучение и настройка
  • Прогноз

Введение

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

Для этого нам нужно понять, как выглядит типичная форма волны дорожки песни:

А вот рекламный сигнал:

Общее наблюдение: для образца песни форма волны (отображение во временной области) закрыта и имеет непрерывную форму (визуально) по сравнению с формой волны объявления, которая выглядит сломанный.

Попробуйте представить, как играет песня с постоянным звучанием вокала или музыки (почти с одинаковой громкостью), а затем воспроизводится обычная реклама (с паузами, конечно) и с небольшим количеством фоновой музыки или без нее. Уловили идею?

Однако есть несколько исключений:

  • Реклама создается как песня (или создается на мелодию песни) и воспроизводится до тех пор, пока длина выборки набора данных не превышает длины выборки.
  • Напротив, песня с длинным отрывком, в котором присутствует только вокал, что может показаться рекламой. (Ложно положительный)

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

Я не уверен насчет других стран, но здесь, в Индии, возьмите любую известную радиостанцию, и вы заметите, что реклама воспроизводится дольше, чем песни. Да, вот такая частота рекламы! (не каламбур)

Итак, переходя к вопросу, можем ли мы сами закодировать логику? Конечно нет! И даже если мы это сделаем, у нас может быть чертовски много параметров, которые нужно учитывать, например, временная область, амплитуда, шаблон, частоты, амплитуда и частота и многие другие. Таким образом, попытки вручную могут привести только к неудачному результату и потере времени.

Следовательно, мы будем использовать алгоритмы глубокого обучения, чтобы понять закономерность. Нам просто нужно подготовить обучающие и протестировать помеченные данные и передать их в алгоритм, который будет обучать, проверять и строить модель, которая предсказывает, является ли данное аудио песней или рекламой - Классический пример двоичной классификации под контролем машинное обучение!

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

Набор данных:

Вот как выглядит структура папок:

Я сохранил 100 аудиосэмплов треков - каждая по 10 секунд и то же самое для рекламы в папках с пометками «песни» и «реклама» соответственно. Эти папки я хранил в родительской папке с именем «fm_dataset».

Чтобы получить эти файлы, я записал около 2 часов радио с одного из известных каналов и обрезал звук, чтобы сделать клипы продолжительностью 10 секунд, и экспортировал несколько 110 сэмплов (в формате wav.) - несколько дополнительных файлы для прогнозирования. Это длительный процесс. Для создания помеченных данных вы должны прослушать каждый тип и соответственно экспортировать его в папку.

Примечание. 100 файлов (на ярлык) - это очень маленький набор данных для обучения и построения такой модели, и это верный случай переобучения (я объясню это позже в этом посте)

Чтобы наша модель работала лучше, нам потребуется примерно от 10 000 до 50 000 образцов обучающих данных. Но для этого эксперимента мы будем использовать те же данные, что и выше, которых достаточно, чтобы получить представление.

Вы также можете попробовать использовать больше семплов с другого канала. Для этого вам необходимо записать радиопередачу с микрофона или линейного входа, обрезать 10-секундные клипы для каждой дорожки и рекламы и экспортировать в формате .wav. Для этого я использовал logic pro. Вы также можете использовать любую DAW с открытым исходным кодом, например Audacity.

Почему 10 секунд?

Это было мое предположение. Вы можете выбрать любую длину. Просто он не должен быть слишком маленьким, чтобы понять закономерность, и не очень длинным. (Хотя есть вероятность большей точности, если длина больше, вы подождете более 20 секунд только для того, чтобы он предсказал объявление и изменился? Нет.) Просто относитесь к нему как к человеку ( В нашем случае - трехлетний ребенок, поскольку мы тренировались на меньшем количестве данных).

Пожалуйста, поймите, что нет никаких ограничений для размера или длины данных. Ты можешь играть джаз!

Итак, собираемся ли мы загружать наш набор данных (аудиосэмплы) непосредственно в алгоритм? Нет. Мы создадим из него несколько кодировок. Скажем, мы конвертируем его в какой-то числовой формат, прежде чем вводить его. Этот процесс называется извлечением признаков.

Мы извлечем признаки и сгенерируем коэффициенты (числа), которые будут использоваться в качестве входных данных. Эти векторные коэффициенты могут быть получены из заданных аудиофайлов с помощью алгоритма MFCC (Mel-Frequency Cepstral Coefficients) алгоритма.

Почему MFCC?

Существует множество других алгоритмов для получения коэффициентов, но мы выбираем MFCC, потому что он является наиболее распространенным и подходит для задач, связанных с речью / голосом, и вычисляется на основе частотных диапазонов человеческого слуха (от 20 Гц до 20 кГц. )

Обучение и настройка

Итак, здесь начинается раздел глубокого обучения. Мы собираемся использовать CNN (сверточные нейронные сети) для этой задачи.

Мы будем использовать библиотеку под названием librosa для получения коэффициентов MFCC из аудио. Мы также будем использовать keras, tensorflow, numpy и scipy. Весь код (вместе с набором данных) находится здесь. Поэтому я просто объясню последовательность действий и некоторые части кода.

Вот рабочий процесс:

  • Прочитать аудиофайлы по пути
  • Вычислить MFCC с помощью librosa
  • Заполните выходные векторы (я немного объясню, почему)
  • Подготовьте набор поездов и набор для проверки
  • Постройте модель CNN

Во фрагменте ниже функция to_mfcc преобразует аудиофайл в MFCC.

def to_mfcc(file_path, max_len=11):
    wave, sr = librosa.load(file_path, mono=True, sr=None)
    wave = wave[::3]
    mfcc = librosa.feature.mfcc(wave, sr=16000)
if (max_len > mfcc.shape[1]):
        pad_width = max_len - mfcc.shape[1]
        mfcc = np.pad(mfcc, pad_width=((0, 0), (0, pad_width)),
                      mode='constant')
    else:
        mfcc = mfcc[:, :max_len]
    return mfcc

Как видите, мы добавили к коэффициентам ноль. Когда вычисляется MFCC, данные передаются в FFT (быстрое преобразование Фурье), которое ожидает, что размер кадра звука будет степенью двойки. Чтобы добиться этого, нам нужно выполнить нулевое заполнение (чтобы довести до ближайшей длины степень к двум). Вы можете узнать больше о MFCC по ссылкам в разделе ссылок.

Следующая функция будет читать аудиофайлы в обоих каталогах и сохранять коэффициенты в файле .npy после имени метки.

def save_coefficients(path=DATA_PATH, max_len=11):
    labels, _, _ = get_data_labels(path)
for label in labels:
        # Init mfcc coefficients
        mfcc_coeffs = []
wavfiles = [path + label + '/' + wavfile for wavfile in 
                    os.listdir(path + '/' + label)]
        for wavfile in tqdm(wavfiles, 
                            "Saving coeffs of label - '{}'".format(label)):
            mfcc = to_mfcc(wavfile, max_len=max_len)
            mfcc_coeffs.append(mfcc)
        np.save(label + '.npy', mfcc_coeffs)

Теперь мы произвольно выбираем 20% в качестве размера тестирования. Следующая функция прочитает данные и разделит их на данные для обучения и тестирования:

def get_split_data_train_test(split_ratio=0.8, random_state=42):
    # Get labels from the data path
    labels, indices, _ = get_data_labels(DATA_PATH)
X = np.load(labels[0] + '.npy')
    y = np.zeros(X.shape[0])
# Append all of the dataset into one single array, same goes for y
    for i, label in enumerate(labels[1:]):
        x = np.load(label + '.npy')
        X = np.vstack((X, x))
        y = np.append(y, np.full(x.shape[0], fill_value= (i + 1)))
assert X.shape[0] == len(y)
return train_test_split(X, y, test_size= (1 - split_ratio),
                            random_state=random_state, shuffle=True)

Теперь давайте построим модель

def get_model():
    model = Sequential()
    model.add(Conv2D(32, kernel_size=(2, 2), activation='relu', 
                     input_shape=(feature_dim_1, feature_dim_2, channel)))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Conv2D(64, kernel_size=(2, 2), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.40))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dense(64, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(optimizer='adam',loss = 'binary_crossentropy',
                  metrics=['accuracy'])
    return model

Мы использовали размер пакета, равный 10, и будем передавать данные из алгоритма обучения за 115 эпох. Мы также добавили еще один слой для свертки и один полностью связанный слой в качестве шага настройки. Как видите, также добавляется некоторая регуляризация (отсев).

Сигмоидальная функция используется в качестве активации для выходного слоя, потому что у нас есть двоичный результат (реклама или песня). По той же причине мы использовали функцию потерь как binary_crossentropy.

Рассмотрим сценарий с еще одной категорией: например, Розыгрыш или интервью, которые вы хотите, чтобы наша модель рассмотрела и не поместила в категорию рекламы. Здесь вы создадите еще одну помеченную папку с этими образцами и передадите ее в сеть. Поскольку теперь это становится многоклассовой проблемой, функцией активации будет «softmax», а функцией потерь - «категориальная_кросцентропия».

Итак, вот результат после подбора нашей модели:

Здесь я получаю точность проверки 80%, что не очень хорошо. Существует ряд факторов, которые могут повысить точность, например добавление большего количества скрытых слоев, полностью связанных слоев и некоторых методов регуляризации (выпадение).

Как мы видим, существует небольшая погрешность (~ 3,5%) и огромная дисперсия (~ 20%), произошло переобучение данных обучения. Как обсуждалось ранее, этого можно в значительной степени избежать, увеличив размер набора данных, и это повысит точность проверки, а также уменьшит дисперсию. Таким образом, если бы нам пришлось сделать это производственным вариантом использования, мы бы сначала добавили тысячи выборок данных, прежде чем добавлять какие-либо слои, исключения или любую настройку параметров.

Эта модель смогла правильно идентифицировать 19 из 20 аудиосэмплов :)

Итак, теперь вы знаете, как отличить песню от рекламы с помощью глубокого обучения и обработки звука. Пожалуйста, попробуйте это и посмотрите, работает ли это для ваших данных. Вы также можете написать мне на почту, если у вас есть дополнительные предложения / вопросы. Я хотел бы получить известие от вас. Надеюсь, вам понравилось 😄

Ваше здоровье !

Использованная литература:

MFCC: http://mirlab.org/jang/books/audioSignalProcessing/speechFeatureMfcc.asp?title=12-2%20MFCC

Http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/

Https://blog.manash.me/building-a-dead-simple-word-recognition-engine-using-convnet-in-keras-25e72c19c12b

Узнайте больше о Logic Pro: https://www.apple.com/in/logic-pro/ (или Audacity: https://www.audacityteam.org/about/)