exponenta event banner

Классификация музыкального жанра с использованием вейвлет-рассеяния времени

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

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

Набор данных, используемый в этом примере, представляет собой коллекцию жанров GTZAN [7] [8]. Данные предоставляются в виде архивного зипированного дегтя, размер которого составляет приблизительно 1,2 ГБ. Для несжатого набора данных требуется около 3 ГБ дискового пространства. При извлечении сжатого tar-файла из ссылки, представленной в ссылках, создается папка с десятью подпапками. Каждая подпапка названа по жанру музыкальных образцов, которые она содержит. Жанры: блюз, классика, кантри, диско, хипхоп, джаз, метал, поп, регги, рок. Существует 100 примеров каждого жанра, и каждый аудиофайл состоит примерно из 30 секунд данных, дискретизированных на частоте 22050 Гц. В оригинальной статье авторы использовали ряд признаков временной и частотной областей, включая коэффициенты mel-frequency cepstral (MFC), извлеченные из каждого музыкального примера, и классификацию модели гауссовой смеси (GMM) для достижения точности 61 процент [7]. Впоследствии к этим данным были применены сети глубокого обучения. В большинстве случаев эти подходы глубокого обучения состоят из сверточных нейронных сетей (CNN) с коэффициентами MFC или спектрограммами в качестве входных данных для глубокого CNN. Эти подходы привели к производительности около 84% [4]. Подход LSTM с квантами времени спектрограмм приводил к 79% точности, а особенности временной и частотной областей в сочетании с подходом ансамблевого обучения (AdaBoost) приводили к 82% точности тестового набора [2] [3]. Недавно подход к машинному обучению с разреженным представлением достиг точности приблизительно 89% [6].

Загрузить данные

Первым шагом является загрузка коллекции жанров GTZAN [7] [8]. В данном примере предполагается, что набор данных загружается во временный каталог .tempdir, в MATLAB ®. Если вы решили загрузить данные в папку, отличную отtempdirизмените имя каталога в последующих инструкциях. Использовать gunzip для загрузки и распаковки набора данных. Затем использовать untar для извлечения содержимого файла дегтя. Папка genres создается в tempdir. Внутри genres десять подпапок, по одной для каждого музыкального жанра.

dataURL = 'http://opihi.cs.uvic.ca/sound/genres.tar.gz';
gunzip(dataURL,tempdir)                       % creates genres.tar in tempdir
untar(fullfile(tempdir,'genres.tar'),tempdir) % creates genres folder

Структура вейвлет-рассеяния

Единственными параметрами для задания в сети вейвлет-временного рассеяния являются длительность инвариантности времени, количество блоков вейвлет-фильтров и количество вейвлетов на октаву. Для большинства приложений достаточно каскадировать данные через два банка вейвлет-фильтров. В этом примере мы используем сеть рассеяния по умолчанию, которая использует два банка вейвлет-фильтров. Первый блок фильтров имеет 8 вейвлетов на октаву, а второй блок фильтров имеет 1 вейвлет на октаву. Для этого примера установите инвариантную шкалу равной 0,5 секунды, что соответствует чуть более 11000 выборок для заданной частоты дискретизации. Создайте сеть декомпозиции вейвлет-рассеяния.

sn = waveletScattering('SignalLength',2^19,'SamplingFrequency',22050,...
    'InvarianceScale',0.5);

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

[fb,f,filterparams] = filterbank(sn);
phi = ifftshift(ifft(fb{1}.phift));
psiL1 = ifftshift(ifft(fb{2}.psift(:,end)));
dt = 1/22050;
time = -2^18*dt:dt:2^18*dt-dt;
scalplt = plot(time,phi,'linewidth',1.5);
hold on
grid on
ylimits = [-3e-4 3e-4];
ylim(ylimits);
plot([-0.25 -0.25],ylimits,'k--');
plot([0.25 0.25],ylimits,'k--');
xlim([-0.6 0.6]);
xlabel('Seconds'); ylabel('Amplitude');
wavplt = plot(time,[real(psiL1) imag(psiL1)]);
legend([scalplt wavplt(1) wavplt(2)],...
    {'Scaling Function','Wavelet-Real Part','Wavelet-Imaginary Part'});
title({'Scaling Function';'Coarsest-Scale Wavelet First Filter Bank'})
hold off

Хранилище аудиоданных

Хранилище аудиоданных позволяет управлять коллекциями файлов аудиоданных. Для машинного или глубокого обучения хранилище аудиоданных не только управляет потоком аудиоданных из файлов и папок, хранилище аудиоданных также управляет связями меток с данными и предоставляет возможность случайного разделения данных на различные наборы для обучения, проверки и тестирования. В этом примере используйте хранилище аудиоданных для управления коллекцией жанров музыки GTZAN. Вспомним, что каждая подпапка коллекции названа по жанру, который она представляет. Установите 'IncludeSubFolders' свойство для true инструктировать хранилище аудиоданных использовать подпапки и установить 'LabelSource' свойство для 'foldernames' для создания меток данных на основе имен подпапок. В этом примере предполагается, что каталог верхнего уровня находится внутри MATLAB. tempdir и называется «жанрами». Убедитесь, что location правильный путь к папке данных верхнего уровня на компьютере. Папка данных верхнего уровня на компьютере должна содержать десять подпапок, каждая из которых называется для десяти жанров, и должна содержать только аудиофайлы, соответствующие этим жанрам.

location = fullfile(tempdir,'genres');
ads = audioDatastore(location,'IncludeSubFolders',true,...
    'LabelSource','foldernames');

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

countEachLabel(ads)
ans=10×2 table
      Label      Count
    _________    _____

    blues         100 
    classical     100 
    country       100 
    disco         100 
    hiphop        100 
    jazz          100 
    metal         100 
    pop           100 
    reggae        100 
    rock          100 

Как говорилось ранее, существует 10 жанров по 100 файлов в каждом.

Обучающие и тестовые наборы

Создание обучающих и тестовых наборов для разработки и тестирования нашего классификатора. Мы используем 80% данных для обучения и продержим оставшиеся 20% для тестирования. shuffle функция хранилища аудиоданных произвольно тасует данные. Выполните это перед разделением данных по меткам для рандомизации данных. В этом примере мы задаем начальное число генератора случайных чисел для воспроизводимости. Использовать хранилище аудиоданных splitEachLabel для выполнения разделения 80-20. splitEachLabel обеспечивает равное представление всех классов.

rng(100)
ads = shuffle(ads);
[adsTrain,adsTest] = splitEachLabel(ads,0.8);
countEachLabel(adsTrain)
ans=10×2 table
      Label      Count
    _________    _____

    blues         80  
    classical     80  
    country       80  
    disco         80  
    hiphop        80  
    jazz          80  
    metal         80  
    pop           80  
    reggae        80  
    rock          80  

countEachLabel(adsTest)
ans=10×2 table
      Label      Count
    _________    _____

    blues         20  
    classical     20  
    country       20  
    disco         20  
    hiphop        20  
    jazz          20  
    metal         20  
    pop           20  
    reggae        20  
    rock          20  

В данных обучения, как и ожидалось, имеется 800 записей, а в данных тестирования - 200 записей. Кроме того, существует 80 примеров каждого жанра в обучающем наборе и 20 примеров каждого жанра в тестовом наборе.

Для получения характеристик рассеяния используйте вспомогательную функцию, helperbatchscatfeatures, который получает натуральный логарифм признаков рассеяния для 219 выборок каждого аудиофайла и поднабор числа окон рассеяния на 6. Исходный код для helperbatchscatfeatures перечислены в приложении. Характеристики вейвлет-рассеяния вычисляются с использованием размера партии 64 сигнала.

При наличии Toolbox™ параллельных вычислений и поддерживаемого графического процессора установите useGPU кому true в следующем коде и преобразование рассеяния будет вычислено с использованием GPU. При использовании графического процессора NVIDIA Titan V с размером партии 64 характеристики рассеяния в этом примере вычислялись приблизительно в 9 раз быстрее, чем при использовании ЦП.

N = 2^19;
batchsize = 64;
scTrain = [];
useGPU = false; % Set to true to use the GPU

while hasdata(adsTrain)
    sc = helperbatchscatfeatures(adsTrain,sn,N,batchsize,useGPU);
    scTrain = cat(3,scTrain,sc);
end

Запишите количество временных окон в преобразовании рассеяния для создания метки.

numTimeWindows = size(scTrain,2);

В этом примере имеется 43 временных окна или кадра для каждого пути рассеяния.

Повторите тот же процесс извлечения элементов для данных теста.

scTest = [];

while hasdata(adsTest)
   sc = helperbatchscatfeatures(adsTest,sn,N,batchsize,useGPU);
   scTest = cat(3,scTest,sc); 
end

Определите количество путей в сети рассеяния и преобразуйте обучающие и тестовые функции в 2-D матрицы.

[~,npaths] = sn.paths();
Npaths = sum(npaths);
TrainFeatures = permute(scTrain,[2 3 1]);
TrainFeatures = reshape(TrainFeatures,[],Npaths,1);
TestFeatures = permute(scTest,[2 3 1]);
TestFeatures = reshape(TestFeatures,[],Npaths,1);

Каждая строка TrainFeatures и TestFeatures представляет собой одно временное окно рассеяния по 334 путям в преобразовании рассеяния каждого звукового сигнала. Для каждого музыкального образца у нас 43 таких окна времени. Соответственно, матрица признаков для обучающих данных составляет 34400 на 334. Количество строк равно количеству обучающих примеров (800), умноженному на количество окон рассеяния в примере (43). Аналогично, матрица признаков рассеяния для тестовых данных составляет 8600 на 334. В каждом примере имеется 200 тестовых примеров и 43 окна. Создайте жанровую метку для каждого из 43 окон в матрице функций вейвлет-рассеяния для обучающих данных.

trainLabels = adsTrain.Labels;
numTrainSignals = numel(trainLabels);
trainLabels = repmat(trainLabels,1,numTimeWindows);
trainLabels = reshape(trainLabels',numTrainSignals*numTimeWindows,1);

Повторите процесс для тестовых данных.

testLabels = adsTest.Labels;
numTestSignals = numel(testLabels);
testLabels = repmat(testLabels,1,numTimeWindows);
testLabels = reshape(testLabels',numTestSignals*numTimeWindows,1);

В этом примере используйте мультиклассный классификатор вектора поддержки (SVM) с кубическим полиномиальным ядром. Подберите SVM к учебным данным.

template = templateSVM(...
    'KernelFunction', 'polynomial', ...
    'PolynomialOrder', 3, ...
    'KernelScale', 'auto', ...
    'BoxConstraint', 1, ...
    'Standardize', true);
Classes = {'blues','classical','country','disco','hiphop','jazz',...
    'metal','pop','reggae','rock'};
classificationSVM = fitcecoc(...
    TrainFeatures, ...
    trainLabels, ...
    'Learners', template, ...
    'Coding', 'onevsone','ClassNames',categorical(Classes));

Прогнозирование тестового набора

Используйте модель SVM, соответствующую преобразованиям рассеяния обучающих данных, чтобы предсказать музыкальные жанры для тестовых данных. Напомним, что для каждого сигнала в преобразовании рассеяния имеется 43 временных окна. Используйте простое большинство голосов, чтобы предсказать жанр. Вспомогательная функция helperMajorityVote получает режим жанровых меток по всем 43 окнам рассеяния. При отсутствии уникального режима helperMajorityVote возвращает ошибку классификации, указанную 'NoUniqueMode'. Это приводит к дополнительному столбцу в матрице путаницы. Исходный код для helperMajorityVote перечислены в приложении.

predLabels = predict(classificationSVM,TestFeatures);
[TestVotes,TestCounts] = helperMajorityVote(predLabels,adsTest.Labels,categorical(Classes));
testAccuracy = sum(eq(TestVotes,adsTest.Labels))/numTestSignals*100
testAccuracy = 87.5000

Точность испытания, testAccuracy, составляет приблизительно 88 процентов. Эта точность сопоставима с современным уровнем техники набора данных GTZAN.

Отображение матрицы путаницы для проверки коэффициентов точности по жанрам. Напомним, в каждом классе по 20 примеров.

confusionchart(TestVotes,adsTest.Labels)

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

cm = confusionmat(TestVotes,adsTest.Labels);
cm(:,end) = [];
genreAccuracy = diag(cm)./20*100;
figure;
bar(genreAccuracy)
set(gca,'XTickLabels',Classes);
xtickangle(gca,30);
title('Percentage Correct by Genre - Test Set');

Резюме

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

Ссылки

  1. Анден, Дж. и Маллат, С. 2014. Спектр глубокого рассеяния. Транзакции IEEE по обработке сигналов, том 62, 16, стр. 4114-4128.

  2. Bergstra, J., Casagrande, N., Erhan, D., Eck, D. и Kegl, B. Агрегатные особенности и AdaBoost для музыкальной классификации. Машинное обучение, том 65, выпуск 2-3, стр. 473-484.

  3. Ирвин, Дж., Чарток, Э., и Холландер, Н. 2016. Повторяющиеся нейронные сети с вниманием к жанровой классификации. https://www.semanticscholar.org/paper/Recurrent-Neural-Networks-with-Attention-for-Genre-Irvin/6da301817851f19107447e4c72e682e3f183ae8a

  4. Ли, Т., Чан, А.Б., и Чун, А. 2010. Автоматическое извлечение признаков музыкального узора с использованием сверточной нейронной сети. Международная конференция по анализу и применению данных.

  5. Маллат. S. 2012. Инвариантное рассеяние группы. Сообщения по чистой и прикладной математике, том 65, 10, стр. 1331-1398.

  6. Panagakis, Y., Kotropoulos, C.L., and Arce, G.R. 2014. Классификация музыкальных жанров посредством совместного разреженного низкорангового представления звуковых особенностей. Транзакции IEEE по обработке звука, речи и языка, 22, 12, стр. 1905-1917.

  7. Цанетакис, Г. и Кук, П. 2002. Классификация музыкальных жанров аудиосигналов. Транзакции IEEE по обработке речи и звука, том 10, № 5, стр. 293-302.

  8. Коллекция жанров GTZAN. http://marsyas.info/downloads/datasets.html

Приложение - Вспомогательные функции

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

type helperMajorityVote
function [ClassVotes,ClassCounts] = helperMajorityVote(predLabels,origLabels,classes)
% This function is in support of wavelet scattering examples only. It may
% change or be removed in a future release.

% Make categorical arrays if the labels are not already categorical
predLabels = categorical(predLabels);
origLabels = categorical(origLabels);
% Expects both predLabels and origLabels to be categorical vectors
Npred = numel(predLabels);
Norig = numel(origLabels);
Nwin = Npred/Norig;
predLabels = reshape(predLabels,Nwin,Norig);
ClassCounts = countcats(predLabels);
[mxcount,idx] = max(ClassCounts);
ClassVotes = classes(idx);
% Check for any ties in the maximum values and ensure they are marked as
% error if the mode occurs more than once
tmpsum = sum(ClassCounts == mxcount);
ClassVotes(tmpsum > 1) = categorical({'NoUniqueMode'});
ClassVotes = ClassVotes(:);

helperbatchscatfeatures - эта функция возвращает матрицу характеристик вейвлет-временного рассеяния для данного входного сигнала. В этом случае мы используем натуральный логарифм коэффициентов вейвлет-рассеяния. Матрица признаков рассеяния вычисляется на 219 выборках сигнала. Признаки рассеяния субдискретизируются с коэффициентом 6. Если useGPU имеет значение trueпреобразование рассеяния вычисляется на GPU.

function sc = helperbatchscatfeatures(ds,sn,N,batchsize,useGPU)
% This function is only intended to support examples in the Wavelet
% Toolbox. It may be changed or removed in a future release.

% Read batch of data from audio datastore
batch = helperReadBatch(ds,N,batchsize);
if useGPU
    batch = gpuArray(batch);
end

% Obtain scattering features
S = sn.featureMatrix(batch,'transform','log');
gather(batch);
S = gather(S);
    
% Subsample the features
sc = S(:,1:6:end,:);
end

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

function batchout = helperReadBatch(ds,N,batchsize)
% This function is only in support of Wavelet Toolbox examples. It may
% change or be removed in a future release.
%
% batchout = readReadBatch(ds,N,batchsize) where ds is the Datastore and
%   ds is the Datastore
%   batchsize is the batchsize

kk = 1;

while(hasdata(ds)) && kk <= batchsize
    tmpRead = read(ds);
    batchout(:,kk) = cast(tmpRead(1:N),'single'); %#ok<AGROW>
    kk = kk+1;
end

end

См. также

Связанные темы