Какую музыку вы слушаете? Жанровая классификация на Python

Небольшое руководство по анализу и жанровой классификации аудио/музыкальных сигналов на Python.

Какую музыку вы слушаете? Жанровая классификация на Python

Разнообразные сервисы и платформы потоковой музыки, такие как Spotify и SoundCloud, стремятся постоянно улучшать способы подбора и рекомендации композиций для своих пользователей. Системы жанровой классификации музыки совершенствуются, а в их основе лежит машинное обучение.

В ход идут все известные методы: от NLP и коллаборативной фильтрации до deep learning. Песни распределяются по жанрам на основе их темпа, акустики, энергичности, танцевальности и десятков других характеристик.

В этой статье мы разбираемся, как анализировать и классифицировать музыкальные сигналы с помощью средств, которые предоставляет язык Python.

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

Обработка звука на Python

Звук – это сигнал с набором определенных параметров: частота, полоса пропускания пропускная способность, децибелы и прочее. Типичный звуковой сигнал может быть выражен как функция от амплитуды и времени:

Какую музыку вы слушаете? Жанровая классификация на Python

Компьютеры могут работать с различными аудиоформатами:

  • mp3;
  • wma (Windows Media Audio);
  • wav (Waveform Audio File).

Python библиотеки для работы со звуком

Для работы со звуком на Python существует ряд мощных библиотек, например, Librosa или PyAudio, а также встроенные модули, поддерживающие базовую функциональность.

Мы будем использовать две библиотеки:

Librosa

Librosa может работать с любыми звуковыми сигналами, но ориентирована в основном именно на музыку. Она позволяет создать полноценную систему извлечения музыкальной информации (MIR). Модуль прекрасно документирован, кроме того, существует множество руководств по использованию. Принципы разработки подробно разобраны в этой статье с конференции SciPy2015.

Установка Python библиотеки librosa выглядит так:

Python

pip install librosa

1 pip install librosa

Или так:

Python

conda install -c conda-forge librosa

1 conda install -c conda-forge librosa

Вы также можете установить модуль ffmpeg со множеством готовых решений для конвертации аудиосигналов.

IPython.display.Audio

IPython.display.Audio позволяет воспроизводить аудио непосредственно в Jupyter Notebook.

Загрузка аудиофайла

Python

import librosa
audio_path = ‘../T08-violin.wav’
x , sr = librosa.load(audio_path)
print(type(x), type(sr))
<class ‘numpy.ndarray’> <class ‘int’>
print(x.shape, sr)
(396688,) 22050

1234567 import librosaaudio_path = ‘../T08-violin.wav’x , sr = librosa.load(audio_path)print(type(x), type(sr))<class ‘numpy.ndarray’> <class ‘int’>print(x.shape, sr)(396688,) 22050

Этот код превращает временной ряд аудио в NumPy массив с частотой дискретизации (sr) 22 кГц. Дефолтное значение можно изменить, например, на 44.1 кГц:

Python

librosa.load(audio_path, sr=44100)

1 librosa.load(audio_path, sr=44100)

или совсем отключить семплирование:

Python

librosa.load(audio_path, sr=None)

1 librosa.load(audio_path, sr=None)

Частота дискретизации – это количество семплов (колебаний) звука, передаваемого в секунду, измеренное в Гц или кГц.

Воспроизведение

Для воспроизведения аудио используем IPython.display.Audio:

Python

import IPython.display as ipd
ipd.Audio(audio_path)

12 import IPython.display as ipdipd.Audio(audio_path)

Этот код в Jupyter Notebook возвращает вот такой виджет:

Какую музыку вы слушаете? Жанровая классификация на Python

Та же самая композиция в SoundCloud:

Визуализация звука
Форма волны

Используя librosa.display.waveplot, можно визуализировать массив аудиоданных:

Python

%matplotlib inline
import matplotlib.pyplot as plt
import librosa.display

plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

1234567 %matplotlib inline import matplotlib.pyplot as pltimport librosa.display plt.figure(figsize=(14, 5))librosa.display.waveplot(x, sr=sr)

Какую музыку вы слушаете? Жанровая классификация на Python

Мы получили график амплитудной огибающей сигнала.

Спектрограмма

Спектрограмма – это визуальное представление спектра частот звуковых или других сигналов, изменяющихся со временем. Иногда их также называют сонограммами. На двумерных графиках по первой оси задается частота, по второй – время.

Для создания спектрограммы на Python используем librosa.display.specshow.

Python

X = librosa.stft(x)
Xdb = librosa.amplitude_to_db(abs(X))
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb, sr=sr, x_axis=’time’, y_axis=’hz’)
plt.colorbar()

12345 X = librosa.stft(x)Xdb = librosa.amplitude_to_db(abs(X))plt.figure(figsize=(14, 5))librosa.display.specshow(Xdb, sr=sr, x_axis=’time’, y_axis=’hz’)plt.colorbar()

Какую музыку вы слушаете? Жанровая классификация на Python

Вертикальная ось – это частоты (от 0 до 10 кГц), а горизонтальная – время клипа. Поскольку все значимые изменения происходят в нижней части спектра, частотную ось можно преобразовать в логарифмическую.

Python

librosa.display.specshow(Xdb, sr=sr, x_axis=’time’, y_axis=’log’)
plt.colorbar()

12 librosa.display.specshow(Xdb, sr=sr, x_axis=’time’, y_axis=’log’)plt.colorbar()

Какую музыку вы слушаете? Жанровая классификация на Python

Запись аудио

librosa.output.write_wav сохраняет NumPy массив в WAV-файл:

Python

librosa.output.write_wav(‘example.wav’, x, sr)

1 librosa.output.write_wav(‘example.wav’, x, sr)

Создание звукового сигнала

Давайте теперь создадим на Python звуковой сигнал с частотой 220 Гц. Это NumPy массив, который будет передан в функцию Audio:

Python

import numpy as np
sr = 22050 # sample rate
T = 5.0    # seconds
t = np.linspace(0, T, int(T*sr), endpoint=False) # time variable
x = 0.5*np.sin(2*np.pi*220*t)# pure sine wave at 220 Hz

# Воспроизведение
ipd.Audio(x, rate=sr) # load a NumPy array

# Сохранение
librosa.output.write_wav(‘tone_220.wav’, x, sr)

1234567891011 import numpy as npsr = 22050 # sample rateT = 5.0    # secondst = np.linspace(0, T, int(T*sr), endpoint=False) # time variablex = 0.5*np.sin(2*np.pi*220*t)# pure sine wave at 220 Hz # Воспроизведениеipd.Audio(x, rate=sr) # load a NumPy array # Сохранениеlibrosa.output.write_wav(‘tone_220.wav’, x, sr)

Ура, вы создали первую композицию!

Извлечение сущностей

Каждый звуковой сигнал имеет множество характеристик, из которых следует отобрать нужные. Процесс извлечения информации для анализа называется извлечением объектов или извлечением сущностей (feature extraction).

Освоиться в мире машинного обучения помогут наши полезные руководства и книги по Python:

  • Настраиваем Python для машинного обучения на Windows
  • FeatureSelector: отбор признаков для машинного обучения на Python
  • NLP – это весело! Обработка естественного языка на Python
  • 11 книг по ИИ и Data Science для изучения в 2019

Частота перехода через нуль

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

Рассчитаем частоту перехода через нуль для нашего примера на Python:

Какую музыку вы слушаете? Жанровая классификация на Python

Python

x, sr = librosa.load(‘../T08-violin.wav’)

plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

1234 x, sr = librosa.load(‘../T08-violin.wav’) plt.figure(figsize=(14, 5))librosa.display.waveplot(x, sr=sr)

Какую музыку вы слушаете? Жанровая классификация на Python

Python

n0 = 9000
n1 = 9100
plt.figure(figsize=(14, 5))
plt.plot(x[n0:n1])
plt.grid()

12345 n0 = 9000n1 = 9100plt.figure(figsize=(14, 5))plt.plot(x[n0:n1])plt.grid()

На графике мы видим 6 пересечений нуля. Давайте проверим:

Python

zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
print(sum(zero_crossings))

# 6

1234 zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)print(sum(zero_crossings)) # 6

Все правильно.

Спектральный центроид

Спектральный центроид указывает, где расположен «центр масс» звука, и рассчитывается как средневзвешенное значение всех частот.

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

Вычислим спектральный центроид для каждого фрейма с помощью librosa.feature.spectral_centroid:

Python

spectral_centroids = librosa.feature.spectral_centroid(x, sr=sr)[0]
spectral_centroids.shape
(775,)

# Вычисление времени для визуализации
frames = range(len(spectral_centroids))
t = librosa.frames_to_time(frames)

# Нормализация спектрального центроида
def normalize(x, axis=0):
return sklearn.preprocessing.minmax_scale(x, axis=axis)

# Построение графика
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_centroids), color=’r’)

123456789101112131415 spectral_centroids = librosa.feature.spectral_centroid(x, sr=sr)[0]spectral_centroids.shape(775,) # Вычисление времени для визуализацииframes = range(len(spectral_centroids))t = librosa.frames_to_time(frames) # Нормализация спектрального центроидаdef normalize(x, axis=0):  return sklearn.preprocessing.minmax_scale(x, axis=axis) # Построение графикаlibrosa.display.waveplot(x, sr=sr, alpha=0.4)plt.plot(t, normalize(spectral_centroids), color=’r’)

Какую музыку вы слушаете? Жанровая классификация на Python

На графике ярко выражен рост частот к концу спектра.

Спектральный спад частоты

Это мера формы сигнала, представляющая собой частоту, ниже которой лежит определенный процент от общей спектральной энергии, к примеру, 85%.

librosa.feature.spectral_rolloff вычисляет спад частоты для каждого фрейма:

Python

spectral_rolloff = librosa.feature.spectral_rolloff(x+0.01, sr=sr)[0]
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_rolloff), color=’r’)

123 spectral_rolloff = librosa.feature.spectral_rolloff(x+0.01, sr=sr)[0]librosa.display.waveplot(x, sr=sr, alpha=0.4)plt.plot(t, normalize(spectral_rolloff), color=’r’)

Какую музыку вы слушаете? Жанровая классификация на Python

Мел-частотные кепстральные коэффициенты

Мел-частотные кепстральные коэффициенты (MFCC) сигнала – небольшой набор характеристик (обычно около 10-20) которые сжато описывают общую форму спектральной огибающей. Этот параметр моделирует характеристики человеческого голоса.

Для примера возьмем простую циклическую волну:

Какую музыку вы слушаете? Жанровая классификация на Python

Python

x, fs = librosa.load(‘../simple_loop.wav’)
librosa.display.waveplot(x, sr=sr)

12 x, fs = librosa.load(‘../simple_loop.wav’)librosa.display.waveplot(x, sr=sr)

И вычислим с помощью librosa.feature.mfcc эти коэффициенты:

Python

mfccs = librosa.feature.mfcc(x, sr=fs)
print mfccs.shape
(20, 97)

# Отображение
librosa.display.specshow(mfccs, sr=sr, x_axis=’time’)

123456 mfccs = librosa.feature.mfcc(x, sr=fs)print mfccs.shape(20, 97) # Отображениеlibrosa.display.specshow(mfccs, sr=sr, x_axis=’time’)

Какую музыку вы слушаете? Жанровая классификация на Python

Мы также можем выполнить масштабирование таким образом, чтобы каждое измерение коэффициента имело нулевое среднее и единичную дисперсию:

Python

import sklearn
mfccs = sklearn.preprocessing.scale(mfccs, axis=1)
print(mfccs.mean(axis=1))
print(mfccs.var(axis=1))

librosa.display.specshow(mfccs, sr=sr, x_axis=’time’)

123456 import sklearnmfccs = sklearn.preprocessing.scale(mfccs, axis=1)print(mfccs.mean(axis=1))print(mfccs.var(axis=1)) librosa.display.specshow(mfccs, sr=sr, x_axis=’time’)

Какую музыку вы слушаете? Жанровая классификация на Python

Частота цветности

Цветность (chroma features) – это интересное и мощное представление для музыкального звука, при котором весь спектр проецируется на 12 контейнеров, представляющих 12 различных полутонов музыкальной октавы.

Для вычислений используем librosa.feature.chroma_stft:

Python

# Загрузка файла
x, sr = librosa.load(‘../simple_piano.wav’)

hop_length = 512
chromagram = librosa.feature.chroma_stft(x, sr=sr, hop_length=hop_length)
plt.figure(figsize=(15, 5))
librosa.display.specshow(chromagram, x_axis=’time’, y_axis=’chroma’, hop_length=hop_length, cmap=’coolwarm’)

1234567 # Загрузка файлаx, sr = librosa.load(‘../simple_piano.wav’) hop_length = 512chromagram = librosa.feature.chroma_stft(x, sr=sr, hop_length=hop_length)plt.figure(figsize=(15, 5))librosa.display.specshow(chromagram, x_axis=’time’, y_axis=’chroma’, hop_length=hop_length, cmap=’coolwarm’)

Какую музыку вы слушаете? Жанровая классификация на Python

Пример: классификация песен по жанрам

Теперь вы знакомы со структурой акустического сигнала и особенностями процесса извлечения музыкальной информации. Пришла пора использовать полученные знания на практике, используя Python библиотеки для работы со звуком.

Цель

Попробуем смоделировать жанровый классификатор музыки. Он вам очень пригодится, если понадобится разобрать кучу неизвестных mp3-файлов.

Набор данных

Возьмем знаменитый набор данных GITZAN. Он использовался для известного исследования Musical genre classification of audio signals (G. Tzanetakis, P. Cook).

Набор состоит из 1000 звуковых дорожек длиной 30 секунд и содержит 10 жанров: блюз, классика, кантри, диско, хип-хоп, джаз, регги, рок, метал и поп. В каждом жанре 100 звуковых клипов.

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

Перед обучением модели классификации нужно преобразовать необработанные данные из звуковых выборок в более осмысленное представление. Преобразуем клипы в формат wav, чтобы Python мог с ними мог работать, с помощью модуля SoX.

Python

sox input.au output.wav

1 sox input.au output.wav

Вы можете воспользоваться удобной шпаргалкой по SoX.

Классификация
Извлечение сущностей

Теперь извлечем из аудиофайлов всю необходимую информацию:

  • мел-частотные кепстральные коэффициенты,
  • спектральный центроид,
  • частоту перехода через нуль,
  • частоты цветности,
  • спектральный спад частоты.

Все эти функции сохраним в .csv-файле.

Классификация

Теперь можно использовать существующие алгоритмы классификации для распределения песен по жанрам.

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

Здесь вы можете изучить пример использования сверточной нейронной сети (CNN) на спектрограммах.

Что дальше

Жанровая классификация – лишь одна из многих прикладных отраслей извлечения музыкальной информации.

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

Анализ музыкальной информации – это очень широкая и интересная сфера деятельности.

: Music Genre Classification with Python

Если вы еще не знакомы с Python, обязательно почитайте наши статьи по обучению Python с нуля:

  • Изучение Python: ТОП-10 вопросов разной направленности
  • Самые эффективные ресурсы и материалы для изучения Python
  • Крупнейшая подборка Python-каналов на Youtube
  • 15 вопросов по Python: как джуниору пройти собеседование

Какую музыку вы слушаете? Жанровая классификация на Python

Просмотров:

Добавить комментарий