exponenta event banner

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

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

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

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

Загрузить предварительно обученную систему X-Vector

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

  • afe один audioFeatureExtractor изобретение позволяет получить частотные кепстральные коэффициенты (МФЦК).

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

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

  • classifier - структура, содержащая обученную проекционную матрицу для уменьшения размерности 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(features,1)
    featuresSegmented = cat(3,featuresSegmented,features(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-векторов для группирования аналогичных областей звука с использованием либо агломерированной иерархической кластеризации (clusterdata (Statistics and Machine Learning Toolbox)) или k-означает кластеризацию (kmeans (Статистика и инструментарий машинного обучения). [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,classifier),'linkage','average','maxclust',maxclusters);
    case 'agglomerative - CSS scoring'
        T = clusterdata(x','Criterion','distance','distance','cosine','linkage','average','maxclust',maxclusters);
    case 'kmeans - CSS scoring'
        T = kmeans(x',maxclusters,'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));

figure(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
sound(audioToPlay,fs)

figure(11)
tiledlayout(2,1)

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

nexttile
plot(t,audioIn.*bmsk(:,speakerToInspect))
axis tight
xlabel('Time (s)')
ylabel('Amplitude')
title("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] Снайдер, Дэвид, и др. Международная конференция IEEE 2018 по акустике, обработке речи и сигналов (ICASSP), IEEE, 2018, стр. 5329-33. DOI.org (Crossref), doi:10.1109/ICASSP.2018.8461375.

[2] Продавать, Г., Снайдер, Д., Маккри, А., Гарсия-Ромеро, Д., Вильяльба, Дж., Мацеевский, М., Манохар, В., Дехак, Н., Повей, Д., Ватанабе, С., Худанпур, С. ( Proc. Interspeech 2018, 2808-2812, DOI: 10.21437/Interspeech.2018-1893.