Нормализация Счета i-вектора

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

Чтобы обратиться к этим трудностям, исследователи разработали нормализацию счета и калибровочные методы счета.

  • В нормализации счета необработанные баллы нормированы относительно 'когорты самозванца'. Выиграйте нормализация происходит прежде, чем оценить ошибочный компромисс обнаружения и может улучшить точность системы и ее способности адаптироваться к новым данным.

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

В этом примере вы применяете нормализацию счета к системе i-вектора. Чтобы узнать о калибровке счета, смотрите Калибровку Счета i-вектора.

Например, цели, вы используете выигрыш подобия косинуса (CSS) в этом примере. Выигрыш вероятностного линейного дискриминантного анализа (PLDA) также улучшен нормализацией, несмотря на то, что менее существенно.

Загрузите Систему i-вектора и Набор данных

Чтобы загрузить предварительно обученную систему i-вектора, подходящую для распознавания динамика, вызовите speakerRecognition. ivectorSystem возвращенный был обучен на наборе данных LibriSpeech, который состоит из англоязычных записей на 16 кГц.

ivs = speakerRecognition();

Предварительно обученная система i-вектора достигает равного коэффициента ошибок (EER) использование на приблизительно 6,73% CSS на наборе тестов LibriSpeech. EER достиг использования, PLDA значительно лучше. Однако, потому что CSS более прост, в целях этого примера, вы исследуете CSS только.

detectionErrorTradeoff(ivs)

Коэффициент ошибок набора тестов LibriSpeech и сопроводительный порог решения по умолчанию для верификации динамика, не расширяют хорошо к невидимым данным. Чтобы подтвердить это, загрузите набор данных PTDB-TUG [3]. Функция поддержки, loadDataset, загружает набор данных и затем передискретизирует его от 48 кГц до 16 кГц, который является частотой дискретизации, на которой была обучена система i-вектора. loadDataset функция возвращает четыре audioDatastore объекты:

  • adsEnroll - Содержит файлы, чтобы зарегистрировать докладчиков в систему i-вектора.

  • adsTest - Содержит файлы к эффективности выборочной проверки системы i-вектора.

  • adsDET - Содержит большой набор файлов, чтобы анализировать ошибочный компромисс обнаружения системы i-вектора.

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

targetSampleRate = ivs.SampleRate;
[adsEnroll,adsTest,adsDET,adsImposter] = loadDataset(targetSampleRate);

Зарегистрируйте докладчиков от набора данных приема. Когда вы enroll динамики, шаблон i-вектора создается для каждой уникальной марки докладчика.

enroll(ivs,adsEnroll,adsEnroll.Labels)
Extracting i-vectors ...done.
Enrolling i-vectors ...................done.
Enrollment complete.
enrolledLabels = categorical(ivs.EnrolledLabels.Properties.RowNames);

Выборочная проверка ложный уровень отклонения (FRR) и ложная пропускная способность (FAR) с помощью verify объектная функция. verify возразите функциональным баллам i-вектор, выведенный из аудиовхода против шаблона i-вектора, соответствующего заданной метке. Функция затем сравнивает счет с порогом решения и или принимает или отклоняет суждение, что аудиовход принадлежит заданной марке докладчика. Порог решения по умолчанию соответствует равному коэффициенту ошибок (EER), определил в прошлый раз, когда ошибочный компромисс обнаружения был оценен.

FA = 0;
FR = 0;
reset(adsTest)
numToSpotCheck = 50;
for ii = 1:numToSpotCheck
    [audioIn,fileInfo] = read(adsTest);
    targetLabel = fileInfo.Label;

    FR = FR + ~verify(ivs,audioIn,targetLabel,"css");

    nontargetIdx = find(~ismember(enrolledLabels,targetLabel));
    nontargetLabel = enrolledLabels(nontargetIdx(randperm(numel(nontargetIdx),1)));

    FA = FA + verify(ivs,audioIn,nontargetLabel,"css");
end
FRR = FR./numToSpotCheck;
FAR = FA./numToSpotCheck;
fprintf('False Rejection Rate = %0.2f (%%)\nFalse Acceptance Rate = %0.2f (%%)\n',100*FRR,100*FAR)
False Rejection Rate = 0.00 (%)
False Acceptance Rate = 44.00 (%)

Эффективность на этом новом наборе данных не совпадает с эффективностью, о которой сообщают когда обучение и оценка системы i-вектора на наборе данных LibriSpeech. Кроме того, порог решения по умолчанию на наборе данных LibriSpeech не соответствует равному коэффициенту ошибок набора данных PTDB-TUG.

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

detectionErrorTradeoff(ivs,adsDET,adsDET.Labels,'Scorer',"css")
Extracting i-vectors ...done.
Scoring i-vector pairs ...done.
Detection error tradeoff evaluation complete.

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

FA = 0;
FR = 0;
reset(adsTest)
for ii = 1:numToSpotCheck
    [audioIn,fileInfo] = read(adsTest);
    trueLabel = fileInfo.Label;

    FR = FR + ~verify(ivs,audioIn,trueLabel,"css");

    imposterIdx = find(~ismember(enrolledLabels,trueLabel));
    imposter = enrolledLabels(imposterIdx(randperm(numel(imposterIdx),1)));

    FA = FA + verify(ivs,audioIn,imposter,"css");
end
FRR = FR./numToSpotCheck;
FAR = FA./numToSpotCheck;
fprintf('False Rejection Rate = %0.2f (%%)\nFalse Acceptance Rate = %0.2f (%%)\n',100*FRR,100*FAR)
False Rejection Rate = 6.00 (%)
False Acceptance Rate = 4.00 (%)

Выиграйте нормализацию

Выиграйте нормализация является общим подходом, чтобы сделать целевые и нецелевые распределения счета через динамики более подобными. Это позволяет системе установить порог решения, который ближе к оптимальному для большего количества динамиков. В этом примере вы исследуете адаптивный симметричный вариант нормализации 1 (S-norm1) [1].

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

Изолируйте два i-вектора шаблона, соответствующие двум динамикам.

enrolledIvecs = cat(2,ivs.EnrolledLabels.ivector{1},ivs.EnrolledLabels.ivector{9});
label_e = categorical([ivs.EnrolledLabels.Properties.RowNames(1),ivs.EnrolledLabels.Properties.RowNames(9)]);

Извлеките i-векторы из набора тестов. Набор тестов помечает перекрытие зарегистрированными метками.

testIvecs = ivector(ivs,adsTest);
label_t = adsTest.Labels;

Создайте векторы индексации, чтобы отслеживать, из которых тестируют i-векторы, соответствуют, который зарегистрировал метку. В targets матрица, столбцы соответствуют зарегистрированным докладчикам, и строки соответствуют тестовым файлам. Если тестовая метка соответствует зарегистрированной метке, значением в матрице является true, в противном случае значением является false.

targets = [ismember(label_t,label_e(1)),ismember(label_t,label_e(2))];

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

[targetScores,nontargetScores] = scoreTargets(enrolledIvecs,testIvecs,targets);

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

plotScoreDistributions(targetScores,nontargetScores,'Analyze','label')

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

plotEER(targetScores,nontargetScores,'Analyze','label')

Анализируйте нормализацию счета на двух динамиках

В этом примере вы используете адаптивный симметричный вариант нормализации 1 (S-norm1) [1]. S-norm1 вычисляет в среднем нормированные баллы из Z-нормы (нулевая нормализация счета) и T-нормы (нормализация экзаменационной отметки).

s(e,t)s-norm1=12(s(e,t)-μ(Se(ξetop))σ(Se(ξetop))+s(e,t)-μ(St(ξttop))σ(St(ξttop)))

где

  • s(e,t) необработанный счет на основе приема e и тест t i-векторы.

  • ξetop набор выигрывающей верхнюю часть когорты самозванца с зарегистрированным i-вектором, e.

  • ξttop набор выигрывающей верхнюю часть когорты самозванца с тестовым i-вектором, t.

  • Se={s(e,εi)}i=1N, набор баллов когорты, сформированных путем выигрыша произнесения приема e с главными файлами от когорты самозванца ξ.

  • Se(ξetop)={s(e,ε)}εξetop, набор главных баллов между зарегистрированным i-вектором и i-векторами самозванца.

  • St(ξttop)={s(e,ε)}εξttop, набор главных баллов между тестовым i-вектором и i-векторами самозванца.

  • μ(S) и σ(S) среднее и стандартное отклонение S.

Чтобы начаться, извлеките i-векторы из когорты самозванца (ξ).

imposterIvecs = ivector(ivs,adsImposter);

Выиграйте зарегистрированные i-векторы против когорты самозванца (Se(ξe)) и затем изолируйте только K лучшие баллы (Se(ξetop)). [1] предлагает использовать главные 200-500 файлов выигрыша, чтобы создать зависящую от диктора когорту. Наконец, вычислите среднее значение (μ(Se(ξetop))) и стандартное отклонение (σ(Se(ξetop))).

topK = 400;

imposterScores = вид (cosineSimilarityScore (enrolledIvecs, imposterIvecs),'descend');
imposterScores = imposterScores (1:min (topK, размер (imposterScores, 1)), :);
mu_e = среднее значение (imposterScores, 1);
std_e = станд. (imposterScores, [], 1);

Вычислить μ(St(ξttop)) и σ(St(ξttop)) как выше.

imposterScores = sort(cosineSimilarityScore(testIvecs,imposterIvecs),'descend');
imposterScores = imposterScores(1:min(topK,size(imposterScores,1)),:);
mu_t = mean(imposterScores,1);
std_t = std(imposterScores,[],1);

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

normFactorsSe = struct('mu',mu_e,'std',std_e);
normFactorsSt = struct('mu',mu_t,'std',std_t);

[targetScores,nontargetScores] = scoreTargets(enrolledIvecs,testIvecs,targets, ...
    'NormFactorsSe',normFactorsSe,'NormFactorsSt',normFactorsSt);

Постройте распределения счета баллов после применения адаптивного s-norm1.

plotScoreDistributions(targetScores,nontargetScores,'Analyze','label')

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

plotEER(targetScores,nontargetScores,'Analyze','label')

Анализируйте нормализацию счета на ошибочном наборе компромисса обнаружения

Извлеките i-векторы из набора DET.

testIvecs = ivector(ivs,adsDET);

Поместите все зарегистрированные i-векторы в матрицу.

enrolledIvecs = cat(2,ivs.EnrolledLabels.ivector{:});

Вычислите статистику нормализации для каждого зарегистрированного и протестируйте i-вектор. Функция поддержки, getNormFactors, выполняет те же операции, как в Анализируют Нормализацию Счета на Двух Динамиках.

topK = 100;

normFactorsSe = getNormFactors (enrolledIvecs, imposterIvecs,'TopK', topK);
normFactorsSt = getNormFactors (testIvecs, imposterIvecs,'TopK', topK);

Создайте целевую матрицу указание, какие пары i-вектора имеют соответствующие метки.

targets = true(numel(adsDET.Labels),height(ivs.EnrolledLabels));
for ii = 1:height(ivs.EnrolledLabels)
    targets(:,ii) = ismember(adsDET.Labels,ivs.EnrolledLabels.Properties.RowNames(ii));
end

Выиграйте каждый i-вектор приема против каждого тестового i-вектора.

[targetScores,nontargetScores] = scoreTargets(enrolledIvecs,testIvecs,targets, ...
    'NormFactorsSe',normFactorsSe,'NormFactorsSt',normFactorsSt);

Постройте целевые и нецелевые распределения счета для группы.

plotScoreDistributions(targetScores,nontargetScores,'Analyze','group')

Постройте равный коэффициент ошибок этой новой системы. Равный коэффициент ошибок после применения адаптивного s-norm1 составляет приблизительно 5,49%. Равный коэффициент ошибок до адаптивного s-norm1 составляет приблизительно 8,4%.

plotEER(targetScores,nontargetScores,'Analyze','group')

Вспомогательные Функции

Загрузите набор данных

function [adsEnroll,adsTest,adsDET,adsImposter] = loadDataset(targetSampleRate)
%LOADDATASET Load PTDB-TUG data set
% [adsEnroll,adsTest,adsDET,adsImposter] = loadDataset(targetSampleteRate)
% downloads the PTDB-TUG data set, resamples it to the specified target
% sample rate and save the results in your current folder. The function
% then creates and returns four audioDatastore objects. The enrollment set
% includes two utterances per speaker. The imposter set does not overlap
% with the other data sets.

% Copyright 2021 The MathWorks, Inc.

arguments
    targetSampleRate (1,1) {mustBeNumeric,mustBePositive}
end

url = 'https://www2.spsc.tugraz.at/databases/PTDB-TUG/SPEECH_DATA_ZIPPED.zip';
downloadFolder = tempdir;
datasetFolder = fullfile(downloadFolder,'PTDB-TUG');

% Download and unzip the dataset if it doesn't exist
if ~isfolder(datasetFolder)
    disp('Downloading PTDB-TUG (3.9 G) ...')
    unzip(url,datasetFolder)
end

% Resample the dataset and save to current folder if it doesn't already
% exist.
if ~isfolder(fullfile(pwd,'MIC'))
    ads = audioDatastore([fullfile(datasetFolder,"SPEECH DATA","FEMALE","MIC"),fullfile(datasetFolder,"SPEECH DATA","MALE","MIC")], ...
        'IncludeSubfolders',true, ...
        'FileExtensions','.wav', ...
        'LabelSource','foldernames');
    reduceDataset = false;
    if reduceDataset
        ads = splitEachLabel(ads,55);
    end
    adsTransform = transform(ads,@(x,y)fileResampler(x,y,targetSampleRate),'IncludeInfo',true);

    writeall(adsTransform,pwd,'OutputFormat','flac','UseParallel',~isempty(ver('parallel')))

end

% Create a datastore that points to the resampled dataset. Use the folder
% names as the labels.
ads = audioDatastore(fullfile(pwd,'MIC'),'IncludeSubfolders',true,'LabelSource',"foldernames");

% Split the data set into enrollment, test, DET, and imposter sets.
imposterLabels = categorical(["M05","M10","F05","F10"]);
adsImposter = subset(ads,ismember(ads.Labels,imposterLabels));

adsDev = subset(ads,~ismember(ads.Labels,imposterLabels));
rng default
numToEnroll = 2;
[adsEnroll,adsDev] = splitEachLabel(adsDev,numToEnroll);

numToTest = 50;
[adsTest,adsDET] = splitEachLabel(adsDev,numToTest);
end

Файл Resampler

function [audioOut,adsInfo] = fileResampler(audioIn,adsInfo,targetSampleRate)
%FILERESAMPLER Resample audio files
% [audioOut,adsInfo] = fileResampler(audioIn,adsInfo,targetSampleRate)
% resamples the input audio to the target sample rate and updates the info
% passed through the datastore.

% Copyright 2021 The MathWorks, Inc.

arguments
    audioIn (:,1) {mustBeA(audioIn,{'single','double'})}
    adsInfo (1,1) {mustBeA(adsInfo,'struct')}
    targetSampleRate (1,1) {mustBeNumeric,mustBePositive}
end

% Isolate the original sample rate
originalSampleRate = adsInfo.SampleRate;

% Resample if necessary
if originalSampleRate ~= targetSampleRate
    audioOut = resample(audioIn,targetSampleRate,originalSampleRate);
    amax = max(abs(audioOut));
    if max(amax>1)
        audioOut = audioOut./amax;
    end
end

% Update the info passed through the datastore
adsInfo.SampleRate = targetSampleRate;

end

Выиграйте цели и нецели

function [targetScores,nontargetScores] = scoreTargets(e,t,targetMap,nvargs)
%SCORETARGETS Score i-vector pairs
% [targetScores,nontargetScores] = scoreTargets(e,t,targetMap) exhaustively
% scores i-vectors in e against i-vectors in t. Specify e as an M-by-N
% matrix, where M corresponds to the i-vector dimension, and N corresponds
% to the number of i-vectors in e. Specify t as an M-by-P matrix, where P
% corresponds to the number of i-vectors in t. Specify targetMap as a
% P-by-N logical matrix that maps which i-vectors in e and t are target
% pairs (derived from the same speaker) and which i-vectors in e and t
% are non-target pairs (derived from different speakers). The
% outputs, targetScores and nontargetScores, are N-element cell arrays.
% Each cell contains a vector of scores between the i-vector in e and
% either all the targets or nontargets in t.
%
% [targetScores,nontargetScores] =
% scoreTargets(e,t,targetMap,'NormFactorsSe',NFSe,'NormFactorsSt',NFSt)
% normalizes the scores by the specified normalization statistics contained
% in structs NFSe and NFSt. If unspecified, no normalization is applied.

% Copyright 2021 The MathWorks, Inc.

arguments
    e (:,:) {mustBeA(e,{'single','double'})}
    t (:,:) {mustBeA(t,{'single','double'})}
    targetMap (:,:) {mustBeA(targetMap,{'logical'})}
    nvargs.NormFactorsSe = [];
    nvargs.NormFactorsSt = [];
end

% Score the i-vector pairs
scores = cosineSimilarityScore(e,t);

% Apply as-norm1 if normalization factors supplied
if ~isempty(nvargs.NormFactorsSe) && ~isempty(nvargs.NormFactorsSt)
    scores = 0.5*( (scores - nvargs.NormFactorsSe.mu)./nvargs.NormFactorsSe.std + (scores - nvargs.NormFactorsSt.mu')./nvargs.NormFactorsSt.std' );
end

% Separate the scores into targets and non-targets
targetScores = cell(size(targetMap,2),1);
nontargetScores = cell(size(targetMap,2),1);
for ii = 1:size(targetMap,2)
    targetScores{ii} = scores(targetMap(:,ii),ii);
    nontargetScores{ii} = scores(~targetMap(:,ii),ii);
end
end

Счет подобия косинуса (CSS)

function scores = cosineSimilarityScore(a,b)
%COSINESIMILARITYSCORE Cosine similarity score
% scores = cosineSimilarityScore(a,b) scores matrix of i-vectors, a,
% against matrix of i-vectors b. Specify a as an M-by-N matrix of
% i-vectors. Specify b as an M-by-P matrix of i-vectors. scores is returned
% as a P-by-N matrix, where columns corresponds the i-vectors in a
% and rows corresponds to the i-vectors in b and the elements of the array
% are the cosine similarity scores between them.

% Copyright 2021 The MathWorks, Inc.

arguments
    a (:,:) {mustBeA(a,{'single','double'})}
    b (:,:) {mustBeA(b,{'single','double'})}
end

scores = squeeze(sum(a.*reshape(b,size(b,1),1,[]),1)./(vecnorm(a).*reshape(vecnorm(b),1,1,[])));
scores = scores';
end

Постройте распределения счета

function plotScoreDistributions(targetScores,nontargetScores,nvargs)
%PLOTSCOREDISTRIBUTIONS Plot target and non-target score distributions
% plotScoreDistribution(targetScores,nontargetScores) plots empirical
% estimations of the distribution for target scores and nontarget scores.
% Specify targetScores and nontargetScores as cell arrays where each
% element contains a vector of speaker-specific scores.
%
% plotScoreDistrubtions(targetScores,nontargetScores,'Analyze',ANALYZE)
% specifies the scope for analysis as either 'label' or 'group'. If ANALYZE
% is set to 'label', then a score distribution plot is created for each
% label. If ANALYZE is set to 'group', then a score distribution plot is
% created for the entire group by combining scores across speakers. If
% unspecified, ANALYZE defaults to 'group'.

% Copyright 2021 The MathWorks, Inc.

arguments
    targetScores (1,:) cell
    nontargetScores (1,:) cell
    nvargs.Analyze (1,:) char {mustBeMember(nvargs.Analyze,{'label','group'})} = 'group'
end

% Combine all scores to determine good bins for analyzing both the target
% and non-target scores together.
allScores = cat(1,targetScores{:},nontargetScores{:});
[~,edges] = histcounts(allScores);

% Determine the center of each bin for plotting purposes.
centers = movmedian(edges(:),2,'Endpoints','discard');

if strcmpi(nvargs.Analyze,'group')
     % Plot the score distributions for the group.

    targetScoresBinCounts = histcounts(cat(1,targetScores{:}),edges);
    targetScoresBinProb = targetScoresBinCounts(:)./sum(targetScoresBinCounts);
    nontargetScoresBinCounts = histcounts(cat(1,nontargetScores{:}),edges);
    nontargetScoresBinProb = nontargetScoresBinCounts(:)./sum(nontargetScoresBinCounts);

    figure
    plot(centers,[targetScoresBinProb,nontargetScoresBinProb])
    title("Score Distributions")
    xlabel('Score')
    ylabel('Probability')
    legend(["target","non-target"],'Location','northwest')
    axis tight

else

    % Create a tiled layout and plot the score distributions for each speaker.
    N = numel(targetScores);
    tiledlayout(N,1)
    for ii = 1:N
        targetScoresBinCounts = histcounts(targetScores{ii},edges);
        targetScoresBinProb = targetScoresBinCounts(:)./sum(targetScoresBinCounts);
        nontargetScoresBinCounts = histcounts(nontargetScores{ii},edges);
        nontargetScoresBinProb = nontargetScoresBinCounts(:)./sum(nontargetScoresBinCounts);

        nexttile
        hold on
        plot(centers,[targetScoresBinProb,nontargetScoresBinProb])
        title("Score Distribution for Speaker " + string(ii))
        xlabel('Score')
        ylabel('Probability')
        legend(["target","non-target"],'Location','northwest')
        axis tight
    end
end
end

Постройте Равный коэффициент ошибок (EER)

function plotEER(targetScores,nontargetScores,nvargs)
%PLOTEER Plot equal error rate (EER)
% plotEER(targetScores,nontargetScores) creates an equal error rate plot
% using the target scores and the non-target scores. Specify targetScores
% and nontargetScores as cell arrays where each element contains a vector
% of speaker-specific scores.
%
% plotEER(targetScores,nontargetScores,'Analyze',ANALYZE) specifies the
% scope for analysis as either 'label' or 'group'. If ANALYZE is set to
% 'label', then an equal error rate plot is created for each label. If
% ANALYZE is set to 'group', then an equal error rate plot is created for
% the entire group by combining scores across speakers. If unspecified,
% ANALYZE defaults to 'group'.

% Copyright 2021 The MathWorks, Inc.

arguments
    targetScores (1,:) cell
    nontargetScores (1,:) cell
    nvargs.Analyze (1,:) char {mustBeMember(nvargs.Analyze,{'label','group'})} = 'group'
end

% Combine all scores to determine good bins for analyzing both the target
% and non-target scores together.
allScores = cat(1,targetScores{:},nontargetScores{:});
[~,edges] = histcounts(allScores,'BinWidth',0.002);

% Determine the center of each bin for plotting purposes.
centers = movmedian(edges(:),2,'Endpoints','discard');

if strcmpi(nvargs.Analyze,'group')
    % Plot the equal error rate for the group.

    targetScoresBinCounts = histcounts(cat(1,targetScores{:}),edges);
    targetScoresBinProb = targetScoresBinCounts(:)./sum(targetScoresBinCounts);
    nontargetScoresBinCounts = histcounts(cat(1,nontargetScores{:}),edges);
    nontargetScoresBinProb = nontargetScoresBinCounts(:)./sum(nontargetScoresBinCounts);

    targetScoresCDF = cumsum(targetScoresBinProb);
    nontargetScoresCDF = cumsum(nontargetScoresBinProb,'reverse');
    [~,idx] = min(abs(targetScoresCDF(:) - nontargetScoresCDF));

    figure
    plot(centers,[targetScoresCDF,nontargetScoresCDF])
    xline(centers(idx),'-',num2str(centers(idx),3),'LabelOrientation','horizontal')
    legend(["FRR","FAR"],'Location','best')
    xlabel('Threshold Score')
    ylabel('Error Rate')
    title(sprintf("Equal Error Plot, EER = %0.2f (%%)",100*mean([targetScoresCDF(idx);nontargetScoresCDF(idx)])))
    axis tight

else

    % Create a tiled layout and plot the equal error rate for each speaker.
    N = numel(targetScores);
    f = figure;
    tiledlayout(f,N,1,'Padding','tight','TileSpacing','tight')
    for ii = 1:N
        targetScoresBinCounts = histcounts(targetScores{ii},edges);
        targetScoresBinProb = targetScoresBinCounts(:)./sum(targetScoresBinCounts);
        nontargetScoresBinCounts = histcounts(nontargetScores{ii},edges);
        nontargetScoresBinProb = nontargetScoresBinCounts(:)./sum(nontargetScoresBinCounts);

        targetScoresCDF = cumsum(targetScoresBinProb);
        nontargetScoresCDF = cumsum(nontargetScoresBinProb,'reverse');
        [~,idx] = min(abs(targetScoresCDF(:) - nontargetScoresCDF));

        nexttile
        plot(centers,[targetScoresCDF,nontargetScoresCDF])
        xline(centers(idx),'-',num2str(centers(idx),3),'LabelOrientation','horizontal')
        legend(["FRR","FAR"],'Location','southwest')
        xlabel('Threshold Score')
        ylabel('Error Rate')
        title(sprintf("Equal Error Plot for Speaker " + string(ii) + ", EER = %0.2f (%%)", ...
            100*mean([targetScoresCDF(idx);nontargetScoresCDF(idx)])))
        axis tight
    end
end
end

Получите факторы нормы

function normFactors = getNormFactors(w,imposterCohort,nvargs)
%GETNORMFACTORS Get norm factors
% normFactors = getNormFactors(w,imposterCohort) returns the mean and
% standard deviation of the scores between the i-vectors in w and the i-vectors
% in the imposter cohort. Specify w as a matrix of i-vectors. Specify
% imposterCohort as a matrix of i-vectors. Each column corresponds to an
% i-vector the same length as w.
%
% normFactors = getNormFactors(w,imposterCohort,'TopK',TOPK) calculates the
% normalization statistics using only the top K highest scores. If
% unspecified, all scores are used.

% Copyright 2021 The MathWorks, Inc.

arguments
    w (:,:) {mustBeA(w,{'single','double'})}
    imposterCohort (:,:) {mustBeA(imposterCohort,{'single','double'})}
    nvargs.TopK (1,1) {mustBePositive} = inf
end
topK = min(ceil(nvargs.TopK),size(imposterCohort,2));

% Score the template i-vector against the imposter cohort.
imposterScores = cosineSimilarityScore(w,imposterCohort);

% Isolate the top K scores.
imposterScores = sort(imposterScores,'descend');
imposterScores = imposterScores(1:topK,:);

% Calculate the score normalization statistics
MU = mean(imposterScores,1);
STD = std(imposterScores,[],1);

% Return normalization statistics as a struct
normFactors = struct('mu',MU,'std',STD);
end

Ссылки

[1] Matejka, Павел, Ondrej Novotny, Oldrich Plchot, Лукаш Бургет, Миреия Диз Санчес и Ян Серноки. "Анализ Нормализации Счета в Многоязычном Распознавании Динамика". Межречь 2017, 2017. https://doi.org/10.21437/interspeech.2017-803.

[2] ван Лиувен, Дэвид А. и Нико Браммер. "Введение в Не зависящую от приложения Оценку Систем Распознавания Динамика". Читайте лекции Примечаниям в Информатике, 2007, 330–53. https://doi.org/10.1007/978-3-540-74200-5_19.

[3] Г. Пиркер, М. Уохлмэр, С. Петрик и Ф. Пернкопф, "Корпус Отслеживания Тангажа с Оценкой на Сценарии Отслеживания Мультитангажа", Межречь, стр 1509-1512, 2011.