Диаризация динамика с использованием x-векторов

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

Диаризация динамика имеет много приложений, в том числе: улучшение транскрипции речи путем структурирования текста в соответствии с активным динамиком, подписывание видео, поиск содержимого (что сказала Джейн?) и подсчет диктора (сколько спикеров присутствовало на заседании?).

В этом примере вы выполняете диаризацию динамика с помощью предварительно обученной системы x-векторов [1], чтобы охарактеризовать области аудио и агломеративной иерархической кластеризации (AHC) для группировки аналогичных областей аудио [2]. Чтобы увидеть, как была определена и обучена система x-векторов, смотрите Распознавание динамика с использованием векторов x.

Загрузка аудиосигнала

Загрузите аудиосигнал и таблицу, содержащую аннотации основной истины. Сигнал состоит из пяти динамиков. Прослушайте аудиосигнал и постройте график его волны во временной области.

[audioIn,fs] = audioread('exampleconversation.flac');
load('exampleconversationlabels.mat')
audioIn = audioIn./max(abs(audioIn));
sound(audioIn,fs)

t = (0:size(audioIn,1)-1)/fs;

figure(1)
plot(t,audioIn)
xlabel('Time (s)')
ylabel('Amplitude')
axis tight

Figure contains an axes. The axes contains an object of type line.

Извлечение x-векторов

В этом примере вы использовали предварительно обученную систему x-векторов. Система x-векторов является облегченной версией исходной системы x-векторов, описанной в [1]. Чтобы увидеть, как была определена и обучена система x-векторов, смотрите Распознавание динамика с использованием векторов x.

Загрузка предварительно обученной системы x-Vector

Загрузите легкую предварительно обученную систему x-векторов. Система x-векторов состоит из:

  • afe - an audioFeatureExtractor объект для извлечения коэффициентов mel frequency cepstral (MFCC).

  • factors - struct, содержащая среднее и стандартное отклонение MFCC, определяемое из репрезентативного набора данных. Эти факторы используются для стандартизации MFCC.

  • extractor - struct, содержащая параметры и состояние нейронной сети, обученной извлекать x-векторы. The xvecModel функция выполняет фактическое выделение x-вектора. The xvecModel функция помещается в текущую папку, когда вы открываете этот пример.

  • classifier - struct, содержащая обученную проекционную матрицу для уменьшения размерности x-векторов и обученную модель PLDA для оценки x-векторов.

load('xvectorSystem.mat')

Извлечение стандартизированных акустических функций

Извлеките стандартизированные функции MFCC из аудио данных. Просмотрите распределения функции, чтобы подтвердить, что факторы стандартизации, полученные из отдельного набора данных, приблизительно стандартизируют функции, выведенные в этом примере. Стандартное распределение имеет среднее значение нуля и стандартное отклонение 1.

features = single((extract(afe,audioIn)-factors.Mean)./factors.STD);

figure(2)
histogram(features)
xlabel('Standardized MFCC')

Figure contains an axes. The axes contains an object of type histogram.

Извлечение x-векторов

Каждый вектор акустической функции представляет приблизительно 0,01 секунды аудио данных. Сгруппировать функции примерно в 2 вторых сегментов с 0,1 секундным хмелем между сегментами.

featureVectorHopDur = (numel(afe.Window) - afe.OverlapLength)/afe.SampleRate;

segmentDur = 2;
segmentHopDur = 0.1;

segmentLength = round (segmentDur/featureVectorHopDur);
segmentHop = round (segmentHopDur/featureVectorHopDur);

idx = 1:segmentLength;
featuresSegmented = [];
while idx (end) < size (функции, 1)
    featuresSegmented = cat функций (idx,:));
    idx = idx + segmentHop;
end

Извлеките x-векторы из каждого сегмента. x-векторы соответствуют выходу из 7-го слоя в модели x-вектора, обученной в Распознавании Динамика с Использованием x-векторов. 7-й слой является первым слоем уровня сегмента после вычисления статистики для расширенных во времени слоев уровня кадра. Визуализируйте векторы X с течением времени.

outputLayer = 7;
xvecs = zeros(numel(extractor.Parameters.("fc"+outputLayer).Bias),size(featuresSegmented,3));
for sample = 1:size(featuresSegmented,3)
    dlX = dlarray(featuresSegmented(:,:,sample),'SCB');
    xvecs(:,sample) = extractdata(xvecModel(dlX,extractor.Parameters,extractor.State,'DoTraining',false,'OutputLayer',outputLayer));
end

figure(3)
surf(xvecs','EdgeColor','none')
view([90,-90])
axis([1 size(xvecs,1) 1 size(xvecs,2)])
xlabel('Features')
ylabel('Segment')

Figure contains an axes. The axes contains an object of type surface.

Примените предварительно обученную проекционную матрицу линейного дискриминантного анализа (LDA), чтобы уменьшить размерность x-векторов и затем визуализировать x-векторы с течением времени.

x = classifier.projMat*xvecs;

figure(4)
surf(x','EdgeColor','none')
view([90,-90])
axis([1 size(x,1) 1 size(x,2)])
xlabel('Features')
ylabel('Segment')

Figure contains an axes. The axes contains an object of type surface.

Кластерные x-векторы

X-векторная система учится извлекать компактные представления (x-векторы) дикторов. Кластеризуйте векторы X, чтобы сгруппировать подобные области аудио с помощью агломеративной иерархической кластеризации (clusterdata (Statistics and Machine Learning Toolbox)) или k-означает кластеризацию (kmeans (Statistics and Machine Learning Toolbox). [2] предлагает использовать агломеративную наследственную кластеризацию с оценкой PLDA в качестве измерения расстояния. K-средних значений кластеризация с использованием косинусоидального счета подобия также обычно используется. Предположим, что ранее было известно количество динамиков в аудио. Установите максимальное количество кластеров в количестве известных динамиков + 1, чтобы фон был кластеризован независимо.

knownNumberOfSpeakers = numel(unique(groundTruth.Label));
maxclusters = knownNumberOfSpeakers + 1;
clusterMethod = 'agglomerative - PLDA scoring';
switch clusterMethod
    case 'agglomerative - PLDA scoring'
        T = clusterdata (x ','Criterion','distance','distance', @ (a, b) helperPLDAScorer (a, b, классификатор),'linkage','average','maxclust', максимальные кластеры);
    case 'agglomerative - CSS scoring'
        T = clusterdata (x ','Criterion','distance','distance','cosine','linkage','average','maxclust', максимальные кластеры);
    case 'kmeans - CSS scoring'
        T = kmeans (x ', максимальные кластеры,'Distance','cosine');
end

Постройте график кластерных решений с течением времени.

figure(5)
tiledlayout(2,1)

nexttile
plot(t,audioIn)
axis tight
ylabel('Amplitude')
xlabel('Time (s)')

nexttile
plot(T)
axis tight
ylabel('Cluster Index')
xlabel('Segment')

Figure contains 2 axes. Axes 1 contains an object of type line. Axes 2 contains an object of type line.

Чтобы изолировать сегменты речи, соответствующие кластерам, сопоставьте сегменты с аудио выборок. Постройте график результатов.

mask = zeros(size(audioIn,1),1);
start = round((segmentDur/2)*fs);

segmentHopSamples = round(segmentHopDur*fs);

mask(1:start) = T(1);
start = start + 1;
for ii = 1:numel(T)
    finish = start + segmentHopSamples;
    mask(start:start + segmentHopSamples) = T(ii);
    start = finish + 1;
end
mask(finish:end) = T(end);

figure(6)
tiledlayout(2,1)

nexttile
plot(t,audioIn)
axis tight

nexttile
plot(t,mask)
ylabel('Cluster Index')
axis tight
xlabel('Time (s)')

Figure contains 2 axes. Axes 1 contains an object of type line. Axes 2 contains an object of type line.

Использование detectSpeech для определения речевых областей. Использование sigroi2binmask для преобразования речевых областей в маску обнаружения двоичной голосовой активности (VAD). Функции detectSpeech второй раз без каких-либо аргументов для построения графика обнаруженных речевых областей.

mergeDuration = 0.5;
VADidx = detectSpeech (audioIn, fs,'MergeDistance', fs * mergeDuration);

VADmask = sigroi2binmask (VADidx, numel (audioIn));

рисунок (7)
detectSpeech (audioIn, fs,'MergeDistance', fs * mergeDuration)

Figure contains an axes. The axes with title Detected Speech contains 31 objects of type line, constantline, patch.

Примените маску VAD к маске динамика и постройте график результатов. Индекс кластера 0 указывает на область отсутствия речи.

mask = mask.*VADmask;

figure(8)
tiledlayout(2,1)

nexttile
plot(t,audioIn)
axis tight

nexttile
plot(t,mask)
ylabel('Cluster Index')
axis tight
xlabel('Time (s)')

Figure contains 2 axes. Axes 1 contains an object of type line. Axes 2 contains an object of type line.

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

maskLabels = zeros(size(VADidx,1),1);
for ii = 1:size(VADidx,1)
    maskLabels(ii) = mode(mask(VADidx(ii,1):VADidx(ii,2)),'all');
    mask(VADidx(ii,1):VADidx(ii,2)) = maskLabels(ii);
end

figure(9)
tiledlayout(2,1)

nexttile
plot(t,audioIn)
axis tight

nexttile
plot(t,mask)
ylabel('Cluster Index')
axis tight
xlabel('Time (s)')

Figure contains 2 axes. Axes 1 contains an object of type line. Axes 2 contains an object of type line.

Подсчитайте количество остальных кластеров динамиков.

uniqueSpeakerClusters = unique(maskLabels);
numSpeakers = numel(uniqueSpeakerClusters)
numSpeakers = 5

Визуализация результатов диаризации

Создайте signalMask объект, а затем постройте график кластеров динамиков. Пометьте график метками основной истины. Метки кластера закодированы клавишей справа от графика. Истинные метки напечатаны над графиком.

msk = signalMask(table(VADidx,categorical(maskLabels)));

figure(10)
plotsigroi(msk,audioIn,true)
axis([0 numel(audioIn) -1 1])

trueLabel = groundTruth.Label;
for ii = 1:numel(trueLabel)  
    text(VADidx(ii,1),1.1,trueLabel(ii),'FontWeight','bold')
end

Figure contains an axes. The axes contains 21 objects of type line, patch, text.

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

speakerToInspect = 2;
cutOutSilenceFromAudio = true;

bmsk = binmask (msk, numel (audioIn));

audioToPlay = audioIn;
if cutOutSilenceFromAudio
    audioToPlay (~ bmsk (:, speakerToInspect)) = [];
end
звук (audioToPlay, fs)

рисунок (11)
tiledlayout (2,1)

nexttile
график (t, audioIn)
ось tight
ylabel ('Amplitude')

nexttile
график (t, audioIn. * bmsk (:, speakerToInspect))
ось tight
xlabel ('Time (s)')
ylabel ('Amplitude')
заголовок ("Speaker Group "+ speakerToInspect)

Figure contains 2 axes. Axes 1 contains an object of type line. Axes 2 with title Speaker Group 2 contains an object of type line.

Оценка системы диаризации

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

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

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

uniqueLabels = unique(trueLabel);
guessLabels = maskLabels;
uniqueGuessLabels = unique(guessLabels);

totalNumErrors = 0;
for ii = 1:numel(uniqueLabels)
    isSpeaker = uniqueLabels(ii)==trueLabel;
    minNumErrors = inf;
    
    for jj = 1:numel(uniqueGuessLabels)
        groupCandidate = uniqueGuessLabels(jj) == guessLabels;
        numErrors = nnz(isSpeaker-groupCandidate);
        if numErrors < minNumErrors
            minNumErrors = numErrors;
            bestCandidate = jj;
        end
        minNumErrors = min(minNumErrors,numErrors);
    end
    uniqueGuessLabels(bestCandidate) = [];
    totalNumErrors = totalNumErrors + minNumErrors;
end
SpeakerErrorRate = totalNumErrors/numel(trueLabel)
SpeakerErrorRate = 0

Ссылки

[1] Snyder, David, et al. «X-Vectors: Robust DNN Embeddings for Speaker Recognition». 2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP), IEEE, 2018, pp. 5329-33. DOI.org (Crossref), doi:10.1109/ICASSP.2018.8461375.

[2] Sell, G., Snyder, D., McCree, A., Garcia-Romero, D., Villalba, J., Maciejewski, M., Manohar, V., Dehak, N., Povey, D., Watanabe, S. Proc. Interspeech 2018, 2808-2812, DOI: 10.21437/Interspeech.2018-1893.