Итерационный подход для создания помеченных наборов сигнала с уменьшаемым человеческим усилием

Этот пример представляет итеративный основанный на глубоком обучении рабочий процесс, чтобы пометить сигналы с уменьшаемым человеческим усилием по маркировке.

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

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

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

Этот пример выполняет процедуру, представленную в Сегментации Формы волны Используя Глубокое обучение, чтобы обучить сеть долгой краткосрочной памяти (LSTM), которая может классифицировать выборки сигнала ECG как принадлежащий одной из этих трех необходимых областей.

Данные

Этот пример рассматривает маркировку областей сигнала ECG с помощью данных, общедоступных в Базе данных QT 1[] 2[]. Данные состоят примерно из 15 минут записей ECG от в общей сложности 105 пациентов. Чтобы получить каждую запись, ревизоры поместили два электрода в другие места на груди пациента, приводящей к двухканальному сигналу. База данных обеспечивает метки области сигнала, сгенерированные автоматизированной экспертной системой [3]. Метки соответствуют местоположениям волны P, T волна и области комплекса QRS в измерениях ECG. Каждый канал 105 двухканальных сигналов ECG был помечен независимо автоматизированной экспертной системой и обработан независимо для в общей сложности 210 сигналов ECG, которые хранились вместе с метками области в 210 MAT-файлах. Файлы доступны в следующем местоположении: https://www.mathworks.com/supportfiles/SPT/data/QTDatabaseECGData1.zip.

Загрузите набор данных с помощью downloadSupportFile функция.

% Download the data
datasetZipFile = matlab.internal.examples.downloadSupportFile('SPT','data/QTDatabaseECGData1.zip');
datasetFolder = fullfile(fileparts(datasetZipFile),'QTDataset');
if ~exist(datasetFolder,'dir')     
     unzip(datasetZipFile,fileparts(datasetZipFile));
end

unzip операция создает datasetFolder папка с 210 MAT-файлами в нем. Каждый файл содержит сигнал ECG в переменной ecgSignal и таблица области помечает в переменной signalRegionLabels. Каждый файл также содержит частоту дискретизации сигнала в переменной Fs. В этом примере все сигналы имеют частоту дискретизации 250 Гц.

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

sds = signalDatastore(datasetFolder,'SignalVariableNames',["ecgSignal","signalRegionLabels"])
sds = 
  signalDatastore with properties:

                       Files:{
                             ' .../MATLAB/Examples/R2021b/supportfiles/SPT/data/QTDataset/ecg1.mat';
                             ' .../MATLAB/Examples/R2021b/supportfiles/SPT/data/QTDataset/ecg10.mat';
                             ' .../MATLAB/Examples/R2021b/supportfiles/SPT/data/QTDataset/ecg100.mat'
                              ... and 207 more
                             }
                     Folders: {'/home/fboucher/Documents/MATLAB/Examples/R2021b/supportfiles/SPT/data/QTDataset'}
    AlternateFileSystemRoots: [0×0 string]
                    ReadSize: 1
         SignalVariableNames: ["ecgSignal"    "signalRegionLabels"]
       ReadOutputOrientation: "column"

Datastore возвращает двухэлементный массив ячеек с сигналом ECG, и таблица области помечает каждый раз, когда вы вызываете read функция. Используйте preview функция datastore, чтобы видеть, что содержимое первого файла является 225,000 выборки длинный сигнал ECG и таблица, содержащая 3 385 меток области.

data = preview(sds)
data=2×1 cell array
    {225000×1 double}
    {  3385×2 table }

Посмотрите на первые несколько строк таблицы меток области и заметьте, что каждая строка содержит предельные индексы области и значение класса области (P, T, или QRS).

head(data{2})
ans=8×2 table
    ROILimits     Value
    __________    _____

     83    117     P   
    130    153     QRS 
    201    246     T   
    285    319     P   
    332    357     QRS 
    412    457     T   
    477    507     P   
    524    547     QRS 

Визуализируйте метки для первых 1 000 выборок с помощью signalMask объект.

MGroundTruth = signalMask(data{2});
plotsigroi(MGroundTruth,data{1}(1:1000))

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

numFiles = numel(sds.Files);
sds = transform(sds,@getmask);

Измените размер (разделяет) сигналы и метки, чтобы получить несколько сегментов длины 5 000 выборок и преобразовать каждый сегмент ECG в частотный диапазон времени с помощью synchrosqueezed преобразования Фурье (FSST).

sds = transform(sds,@resizeData);
sdsFSST = transform(sds,@(x,fs)extractFSSTFeatures(x,250));

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

rng default
[trainIdx,~,testIdx] = dividerand(numFiles,0.7,0,0.3);

trainDs = subset(sds,trainIdx); % resized 5000 sample signals and labels
trainDsFSST = subset(sdsFSST,trainIdx); % FSST-transformed signals and labels

testDsFSST = subset(sdsFSST,testIdx);

Считайте все данные в память с помощью readall метода хранилищ данных. Это действие считает каждый сигнал ECG и применит все преобразования, описанные выше, чтобы возвратить несколько Фурье synchrosqueeze-преобразованные сегменты ECG. Используйте UseParallel опция, чтобы преобразовать набор данных в параллель с помощью доступных процессоров в компьютере каждый раз, когда у вас есть Parallel Computing Toolbox™.

% Get FSST-transformed signals
ecgFSSTData = readall(trainDsFSST,UseParallel=true);
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 8).
testFSSTData = readall(testDsFSST,UseParallel=true);

ecgFSST = ecgFSSTData(:,1);
ecgLabels = ecgFSSTData(:,2);

testECGFSST = testFSSTData(:,1);
testLabels = testFSSTData(:,2);

% Get time domain signal segments so that we can plot some labeling results
ecgData = readall(trainDs);
ecgSignals = ecgData(:,1);

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

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

  2. Человеческая этикетировочная машина корректирует любые ошибки маркировки вручную.

  3. Откорректированная маркировка добавляется к ранее помеченным системам координат.

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

Чтобы сделать количественные сравнения, симулируйте два сценария:

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

  • Для второго сценария притворитесь что ecgFrames данные не помечены, и пометьте их с помощью итерационного метода

Эффективность предсказания Используя полностью пометила ECG Data Set

Создайте сеть BiLSTM и обучайтесь, она с полным пометила ecgFrames установите, чтобы получить верхнюю границу эффективности предсказания. Как упомянуто выше, этот подход требует маркировки "в лоб" целого набора данных и следовательно самого большого человеческого усилия по маркировке. Обучите сеть с помеченным ecgFrames установите и вычислите точность предсказания на набор тестовых данных.

Сетевая архитектура

Создайте сеть BiLSTM с помощью слоев глубокого обучения.

  • Задайте sequenceInputLayer с размером как количество функций в FSST сигналов, который является общим количеством выборок частотного диапазона (40 в этом примере).

  • Задайте bilstmLayer с 200 скрытыми узлами и набором OutputMode к sequence поскольку каждая выборка сигнала имеет метку.

  • Задайте fullyConnectedLayer с выходным размером 4 соответствий этим четырем категориям, P волна, комплекс QRS, T волна и N/A.

  • Добавьте softmaxLayer и classificationLayer выводить предполагаемые метки.

% Training with the full emulated unlabeled data set
layers = [ ...
    sequenceInputLayer(size(ecgFSST{1},1))
    bilstmLayer(200,'OutputMode','sequence')
    fullyConnectedLayer(4)
    softmaxLayer
    classificationLayer];

Используйте traningOptions задавать решатель оптимизации и гиперпараметры, чтобы обучить сеть. Этот пример использует оптимизатор ADAM и мини-пакетный размер 50. Обучите сеть с помощью или центрального процессора или графического процессора. Используя графический процессор требует Parallel Computing Toolbox™. Чтобы видеть, который поддерживаются графические процессоры, смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox). Для получения информации о других параметрах смотрите trainingOptions (Deep Learning Toolbox). Этот пример использует графический процессор для обучения с помощью 'ExecutionEnvironment'пара "имя-значение".

options = trainingOptions('adam', ...
    'MaxEpochs',10, ...
    'MiniBatchSize',50, ...
    'ExecutionEnvironment','gpu', ...
    'InitialLearnRate',0.01, ...
    'LearnRateDropPeriod',6, ...
    'LearnRateSchedule','piecewise', ...
    'GradientThreshold',1, ...
    'Shuffle','every-epoch',...
    'Plots','training-progress',...
    'Verbose',0,...
    'DispatchInBackground',true);

Обучите сеть с, полностью пометил ecgFrames набор данных.

baselineNet = trainNetwork(ecgFSST,ecgLabels,layers,options);

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

predictLabelsAll = classify(baselineNet,testECGFSST,'MiniBatchSize',50);
accuracyAll = mean(cellfun(@(x,y)mean(x==y),predictLabelsAll,testLabels));
fprintf('The baseline prediction accuracy is %2.1f%%.\n',accuracyAll*100);
The baseline prediction accuracy is 89.9%.

Итеративная маркировка человеком в цикле

Чтобы уменьшать усилие по маркировке, попробуйте итерационный подход: Притворитесь что ecgFrames набор данных первоначально не помечен и что данные помечены вручную. В действительности пример использует метки основной истины, обеспеченные по условию набор.

Обучите начальную сеть

Запустите путем выбора 25 систем координат из ecgFrames установите и маркировка их вручную. Обучите сеть BiLSTM с этой начальной буквой помеченный набор, чтобы служить начальным шагом итеративного процесса.

numInitFrames = 25;

currentTrainingSet = ecgFSST(1:numInitFrames,1);
currentTrainingLabels = ecgLabels(1:numInitFrames);

Установите опции обучения иметь больше учебных эпох и меньший мини-пакетный размер, потому что существует только 25 систем координат в наборе данных начальной подготовки.

options = trainingOptions('adam', ...
    'MaxEpochs',20, ...
    'MiniBatchSize',5, ...
    'ExecutionEnvironment','gpu', ...
    'InitialLearnRate',0.01, ...
    'LearnRateDropPeriod',6, ...
    'LearnRateSchedule','piecewise', ...
    'GradientThreshold',1, ...
    'Shuffle','every-epoch', ...
    'Plots','none',...
    'Verbose',0,...
    'DispatchInBackground',true);

Обучите сеть BiLSTM с набором данных начальной подготовки и предскажите, что метки с помощью того же набора тестовых данных раньше устанавливали базовую линию эффективности. Точность предсказания этой начальной сети составляет приблизительно 40%.

initNet = trainNetwork(currentTrainingSet,currentTrainingLabels,layers,options);
initPrediction = classify(initNet,testECGFSST,'MiniBatchSize',50); 
initAccuracy = mean(cellfun(@(x,y)mean(x==y),initPrediction,testLabels));
fprintf('The prediction accuracy is %2.1f%%.\n',initAccuracy*100);
The prediction accuracy is 43.7%.

Маркировка

На следующем шаге выберите 200 новых систем координат данных из ecgFrames установите и накормите ими предварительно обученную сеть, initNet, пометить сигналы автоматически.

iteration = 1;
% Number of frames to label at each iteration
numFrames = 200; 
% Select the next set of frames to label
indexNext = numInitFrames+1:numInitFrames+numFrames;
% Use classify to label the new frames
currentPrediction = classify(initNet,ecgFSST(indexNext),'MiniBatchSize',50);

Оцените результаты маркировки, сгенерированные сетью, и сравните их с основной истиной. Найдите, что индексы ECG сигнализируют, что получил лучшее - и эффективность худшего случая с этой сетью.

errs = cellfun(@(x,y)sum(x~=y),ecgLabels(indexNext),currentPrediction);
[~,bestIndex] = min(errs);
[~,worstIndex] = max(errs);

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

ecgSignalOfInterest = ecgSignals{indexNext(bestIndex)};
groundTruthLabels = ecgLabels{indexNext(bestIndex)};
predictedLabels = currentPrediction{bestIndex};

MGroundTruth = signalMask(groundTruthLabels);
figure
plotsigroi(MGroundTruth,ecgSignalOfInterest(1:750))
title('Ground Truth - best-case scenario')

MPredicted = signalMask(predictedLabels);
figure
plotsigroi(MPredicted,ecgSignalOfInterest(1:750))
title('Labeling by Network - best-case scenario')

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

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

ecgSignalOfInterest = ecgSignals{indexNext(worstIndex)};
groundTruthLabels = ecgLabels{indexNext(worstIndex)};
predictedLabels = currentPrediction{worstIndex};

MGroundTruth = signalMask(groundTruthLabels);
figure
plotsigroi(MGroundTruth,ecgSignalOfInterest(1:750))
title('Ground Truth - worst-case scenario')

MPredicted = signalMask(predictedLabels);
figure
plotsigroi(MPredicted,ecgSignalOfInterest(1:750))
title('Labeling by Network - worst-case scenario')

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

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

numSamplesPerFrame = 5000;
networkLabelingErrorRate(iteration) = 1-mean(cellfun(@(x,y)mean(x==y),currentPrediction,ecgLabels(indexNext)));
averageNumOfCorrectionsPerFrame(iteration) = networkLabelingErrorRate(iteration) * numSamplesPerFrame;
fprintf('The average number of corrections per frame is %2.1f.\n',averageNumOfCorrectionsPerFrame(iteration));
The average number of corrections per frame is 2211.3.

Для первой итерации существует в среднем приблизительно 2 200 выборок на систему координат, которая должна быть откорректирована человеком. Откорректированные выборки на систему координат являются удобной метрикой, чтобы показать человеческое усилие. Обратите внимание однако, что на практике, человеческая этикетировочная машина не должна корректировать метку каждой выборки. Вместо этого человеческая этикетировочная машина только должна расширить или сократить пределы области.

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

На следующей итерации 200 недавно помеченных систем координат могут быть добавлены к currentTrainingSet установите, чтобы переобучить сеть и повторить итерацию маркировки. Этот график иллюстрирует рабочий процесс в каждой итерации после первой итерации:

Повторите итерации маркировки

Расширьте набор обучающих данных путем добавления недавно откорректированных помеченных систем координат, выберите еще 200 систем координат данных, которые будут помечены и повторите итерацию маркировки, пока эффективность не будет удовлетворительной.

% Include the initial training set and the 200 newly labeled data frames
maxIter = 15;
indexTraining = 1:numInitFrames+numFrames;

networkAccuracy = zeros(1,15);
networkAccuracy(iteration) = initAccuracy;

options = trainingOptions('adam', ...
    'MaxEpochs',20, ...
    'MiniBatchSize',50, ...
    'ExecutionEnvironment','gpu', ...
    'InitialLearnRate',0.01, ...
    'LearnRateDropPeriod',6, ...
    'LearnRateSchedule','piecewise', ...
    'GradientThreshold',1, ...
    'Shuffle','every-epoch', ...
    'Plots','none', ...
    'Verbose',0);

for iteration = 2:maxIter
    % Extended training data set
    currentTrainingSet = ecgFSST(indexTraining,1);    
    % Emulate human correction by assigning ground-truth labels to the
    % extended training set
    currentTrainingLabels = ecgLabels(indexTraining);

    % Train network with extended training set
    currentNet = trainNetwork(currentTrainingSet,currentTrainingLabels,layers,options);
    
    % Predict labels for the test data set and calculate the accuracy to
    % compare to baseline performance
    currentTestSetPrediction = classify(currentNet,testECGFSST,'MiniBatchSize',50);
    networkAccuracy(iteration) = mean(cellfun(@(x,y)mean(x==y),currentTestSetPrediction,testLabels));
    
    % Get another numFrames data frames for human labeler
    indexNext = indexTraining(end)+1:indexTraining(end)+numFrames;
    
    % Measure average number of human corrections per frame in this iteration
    currentPrediction = classify(currentNet,ecgFSST(indexNext),'MiniBatchSize',50);
    networkLabelingErrorRate(iteration) = 1-mean(cellfun(@(x,y)mean(x==y),currentPrediction,ecgLabels(indexNext)));
    averageNumOfCorrectionsPerFrame(iteration) = networkLabelingErrorRate(iteration) * numSamplesPerFrame;
    
    indexTraining = 1:indexNext(end);
end

Маркировка эффективности

После 15 итераций маркировки в currentTrainingSet существует 2 825 систем координат данных, соответствие приблизительно половине 6 543 систем координат данных содержится в полном ecgDataset набор. Точность предсказания сети, обученной с 2 825 системами координат, уже очень близко к базовой точности.

accuDiff = accuracyAll-networkAccuracy(end);
fprintf('The accuracy difference is %2.1f%%.\n',accuDiff*100);
The accuracy difference is 2.1%.

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

figure
examinedDataSize = 25:200:2825;
plot(examinedDataSize,networkAccuracy,'*-')
hold on
% Prediction accuracy upper bound
plot(examinedDataSize,ones(1,15)*accuracyAll,'r--')
grid on
xlabel('Training set size')
title('Accuracy for the test data set')
xlim([25 2825])
legend('Labeling Network','Upper Bound','Location','southeast')

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

figure
plot(examinedDataSize,averageNumOfCorrectionsPerFrame,'*-')
grid on
xlabel('Training set size')
title('Average number of human corrections per frame')
xlim([25 2825])

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

fprintf('The average number of corrections per frame is %2.1f.\n',mean(averageNumOfCorrectionsPerFrame));
The average number of corrections per frame is 716.9.

Заключение

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

Ссылки

[1] Голдбергер, Ари Л., Луис А. Н. Амараль, Леон Гласс, Джеффри М. Гаусдорф, Plamen Ch. Иванов, Роджер Г. Марк, Джозеф Э. Митус, Джордж Б. Муди, Чанг-Канг Пенг и Х. Юджин Стэнли. "PhysioBank, PhysioToolkit и PhysioNet: Компоненты Нового Ресурса Исследования для Комплексных Физиологических Сигналов". Циркуляция. Издание 101, Номер 23, 2000, стр e215–e220. [Циркуляция Электронные Страницы; http://circ.ahajournals.org/content/101/23/e215.full].

[2] Laguna, Пабло, Роджер Г. Марк, Ари Л. Голдбергер и Джордж Б. Муди. "База данных для Оценки Алгоритмов для Измерения QT и Других Интервалов Формы волны в ECG". Компьютеры в Кардиологии. Vol.24, 1997, стр 673–676.

[3] Laguna, Пабло, Рэймон Джейне и Пере Каминаль. "Автоматическое обнаружение контуров волны в мультиведущих сигналах ECG: Валидация с базой данных CSE". Компьютеры и Биомедицинское Исследование. Издание 27, Номер 1, 1994, стр 45–60.

Смотрите также

|

Для просмотра документации необходимо авторизоваться на сайте