Если музыка — это место, то джаз — это город, фолк — это пустыня, рок — это дорога, классика — это храм.
— Вера Назарян
Музыка является неотъемлемой частью нашей жизни, и компании, занимающиеся потоковой передачей музыки, такие как Spotify, в настоящее время используют машинное обучение для создания рекомендаций для нас. Музыкальные жанры играют большую роль в создании этих рекомендаций. В этой истории мы построим модель классификации музыкальных треков по соответствующим жанрам. В этом руководстве мы будем использовать librosa, библиотеку для анализа музыки и звука. Мы также будем использовать GTZAN Dataset от Kaggle для обучения нашего классификатора.
Импорт библиотек
import os import pandas as pd import numpy as np import IPython import librosa import librosa.display import seaborn as sns import matplotlib.pyplot as plt from sklearn import preprocessing from sklearn.preprocessing import minmax_scale from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score
Разные жанры
Давайте посмотрим весь список жанров, присутствующих в наборе данных.
general_path = './Data' print(list(os.listdir('Data/genres_original/')))
Запись одного аудио
Мы возьмем один аудиофайл для исследования.
file = './Data/genres_original/classical/classical.00050.wav' signal , sr = librosa.load(file , sr = 22050)
Визуализация сигналов
Давайте используем волновой график для визуализации аудиофайла или сигнала.
plt.figure(figsize=(15,5)) librosa.display.waveplot(signal , sr = sr) plt.xlabel('Time') plt.ylabel('Amplitude') plt.title("Classical music signal") plt.show()
Воспроизведение аудио
Чтобы воспроизвести звук в Jupyter Notebook, мы будем использовать следующий код.
IPython.display.Audio(signal, rate=sr)
Преобразование Фурье
Преобразование Фурье — это функция, которая принимает сигнал во временной области в качестве входных данных и выводит его разложение на частоты. Давайте построим с его помощью график, чтобы увидеть распределение частот.
n_fft = 2048 hop_length = 512 D = np.abs(librosa.stft(signal, n_fft = n_fft, hop_length = hop_length)) plt.figure(figsize = (15, 5)) plt.plot(D) plt.title('Fourier Transform') plt.show()
Спектрограмма
Спектрограмма представляет собой представление громкости сигнала во времени на различных частотах, присутствующих в определенной волновой форме. Давайте построим спектрограмму для нашего аудиофайла.
DB = librosa.amplitude_to_db(D, ref = np.max) plt.figure(figsize = (15, 5)) librosa.display.specshow(DB, sr = sr, hop_length = hop_length, x_axis = 'time', y_axis = 'log', cmap = 'cool') plt.colorbar() plt.title('Spectrogram') plt.show()
Гармоники и восприятие
Гармоники — это нежелательные более высокие частоты, наложенные на основную форму волны, создающие искаженную волновую картину. Перцептив представляет собой звуковой ритм и эмоцию. Давайте изобразим их обоих на графике.
a,b = librosa.effects.hpss(signal) plt.figure(figsize = (15, 5)) plt.plot(a, color = '#FF5E33'); plt.plot(b, color = '#FFD433'); plt.title('Harmonics and Perceptrual') plt.show()
Спектральный центроид
Спектральный центроид указывает, где расположен центр масс спектра.
spectral_centroids = librosa.feature.spectral_centroid(signal, sr=sr)[0] plt.figure(figsize=(15, 5)) frames = range(len(spectral_centroids)) t = librosa.frames_to_time(frames) librosa.display.waveplot(signal, sr=sr, alpha=0.4) plt.plot(t, minmax_scale(spectral_centroids,axis=0), color='r') plt.title('Spectral Centroid') plt.show()
Хромограмма
Мы создадим хромограмму, в которой весь спектр будет спроецирован на 12 бинов, представляющих 12 различных полутонов музыкальной октавы.
hop_length = 5000 chromagram = librosa.feature.chroma_stft(signal, 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='YlGnBu') plt.title('Chromogram') plt.show()
30-секундные функции
Файл features_30_sec.csv содержит звуковые характеристики продолжительностью 30 секунд. Мы будем использовать его для изучения ударов в минуту.
data = pd.read_csv('./Data/features_30_sec.csv') data.head()
Ударов в минуту
Давайте посмотрим количество ударов в минуту для разных жанров.
x = data[["label", "tempo"]] f, ax = plt.subplots(figsize=(15, 5)); sns.boxplot(x = "label", y = "tempo", data = x, palette = 'husl'); plt.title('BPM for Genres', fontsize = 20) plt.xticks(fontsize = 14) plt.yticks(fontsize = 10); plt.xlabel("Genre", fontsize = 15) plt.ylabel("BPM", fontsize = 15) plt.show()
Загрузка данных
Файл features_3_sec.csvсодержит звуковые характеристики продолжительностью 3 секунды. Мы будем использовать его для обучения нашей модели.
data = pd.read_csv('./Data/features_3_sec.csv') data = data.iloc[0:, 1:]
Предварительная обработка данных
Мы предварительно обработаем данные, чтобы сделать их подходящими для нашей модели. Для этой цели мы будем использовать MinMaxScaler.
y = data['label'] X = data.loc[:, data.columns != 'label'] cols = X.columns min_max_scaler = preprocessing.MinMaxScaler() np_scaled = min_max_scaler.fit_transform(X) X = pd.DataFrame(np_scaled, columns = cols)
Разделение данных
Давайте разделим данные для обучения и тестирования.
X_train, X_test, y_train, y_test = train_test_split(X, y)
Создание модели и прогнозирование
Пришло время создать нашу модель. Мы будем использовать классификатор случайного леса для построения модели. Мы подгоним модель, используя данные обучения, и предскажем данные тестирования. Точность нашей модели оказалась 81,38 %, и это здорово!
model = RandomForestClassifier(n_estimators=1000, max_depth=10, random_state=0) model.fit(X_train, y_train) preds = model.predict(X_test) print('Accuracy:', round(accuracy_score(y_test, preds)))
Мы успешно построили модель классификации музыкальных жанров. Если вы нашли это руководство полезным, нажмите «Подписаться», чтобы присоединиться к сообществу.