Докладчик Диэризэйшн Используя x-векторы

Динамик diarization является процессом разделения звукового сигнала в сегменты согласно идентичности динамика. Это отвечает на вопрос, "кто говорил когда" без предварительных знаний динамиков и, в зависимости от приложения без предварительных знаний количества динамиков.

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

В этом примере вы выполняете динамик diarization использование предварительно обученной системы 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 object. The axes object contains an object of type line.

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

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

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

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

  • afe - audioFeatureExtractor возразите, чтобы извлечь mel частоту cepstral коэффициенты (MFCCs).

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

  • extractor - struct, содержащий параметры и состояние нейронной сети, обученной, чтобы извлечь x-векторы. xvecModel функция выполняет фактическую экстракцию x-вектора. 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 object. The axes object 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 = вокруг (segmentDur/featureVectorHopDur);
segmentHop = вокруг (segmentHopDur/featureVectorHopDur);

idx = 1:segmentLength;
featuresSegmented = [];
while idx (конец) <размер (функции, 1)
    featuresSegmented = кошка (3, featuresSegmented, функции (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 object. The axes object 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 object. The axes object 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', 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 objects. Axes object 1 contains an object of type line. Axes object 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 objects. Axes object 1 contains an object of type line. Axes object 2 contains an object of type line.

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

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

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

фигура (7)
detectSpeech (audioIn, фс,'MergeDistance', fs*mergeDuration)

Figure contains an axes object. The axes object 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 objects. Axes object 1 contains an object of type line. Axes object 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 objects. Axes object 1 contains an object of type line. Axes object 2 contains an object of type line.

Считайте количество остающихся кластеров динамика.

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

Визуализируйте результаты Diarization

Создайте 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 object. The axes object 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, фс)

фигура (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 objects. Axes object 1 contains an object of type line. Axes object 2 with title Speaker Group 2 contains an object of type line.

Системная оценка Diarization

Общая метрика для динамика diarization системы является коэффициентом ошибок diarization (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] Снайдер, Дэвид, и др. “X-векторы: Устойчивые Вложения DNN для Распознавания Динамика”. 2 018 Международных конференций IEEE по вопросам Акустики, Речи и Обработки сигналов (ICASSP), IEEE, 2018, стр 5329–33. DOI.org (Crossref), doi:10.1109/ICASSP.2018.8461375.

[2] Продайте, G., Снайдер, D., Маккри, A., Гарсия-Ромеро, D., Вильяльба, J., Мациейевский, M., Manohar, V., Dehak, N., Povey, D., Ватанабе, S., Khudanpur, S. (2018) Diarization Тверд: Некоторые События и Уроки, Извлеченные для Команды JHU во Вступительной проблеме DIHARD. Proc. Межречь 2018, 2808-2812, DOI: 10.21437/Interspeech.2018-1893.