Contenido principal

Clasificar series de tiempo utilizando análisis de wavelets y deep learning

En este ejemplo se muestra cómo clasificar señales de electrocardiogramas (ECG) humanos utilizando la transformada wavelet continua (CWT) y una red neuronal convolucional (CNN) profunda.

Entrenar una CNN profunda desde cero demanda una alta carga computacional y requiere una gran cantidad de datos de entrenamiento. En distintas aplicaciones, no hay disponible una cantidad suficiente de datos de entrenamiento y sintetizar nuevos ejemplos de entrenamiento realistas no es factible. En estos casos, conviene aprovechar las redes neuronales existentes que se han entrenado con conjuntos grandes de datos para tareas similares desde el punto de vista conceptual. Este aprovechamiento de las redes neuronales existentes se conoce como transferencia del aprendizaje. En este ejemplo, adaptamos dos CNN, GoogLeNet y SqueezeNet, preentrenadas para el reconocimiento de imágenes para clasificar formas de onda de ECG según una representación de tiempo-frecuencia.

GoogLeNet y SqueezeNet son CNN profundas diseñadas originalmente para clasificar imágenes en 1000 categorías. Reutilizamos la arquitectura de red de la CNN para clasificar señales de ECG en función de las imágenes de la CWT de los datos de series de tiempo. Los datos usados en este ejemplo están disponibles públicamente en PhysioNet.

Descripción de los datos

En este ejemplo, se utilizan datos de ECG obtenidos de tres grupos de personas: personas con arritmia cardíaca (ARR), personas con insuficiencia cardíaca congestiva (CHF) y personas con un ritmo sinusal normal (NSR). En total se utilizan 162 grabaciones de ECG de tres bases de datos de PhysioNet: MIT-BIH Arrhythmia Database [3][7], MIT-BIH Normal Sinus Rhythm Database [3] y The BIDMC Congestive Heart Failure Database [1][3]. Más concretamente, 96 grabaciones de personas con arritmia, 30 grabaciones de personas con insuficiencia cardíaca congestiva y 36 grabaciones de personas con ritmo sinusal normal. El objetivo es entrenar un clasificador para diferenciar entre ARR, CHF y NSR.

Descargar datos

El primer paso es descargar los datos del repositorio GitHub®. Para descargar los datos del sitio web, haga clic en Code y seleccione Download ZIP. Guarde el archivo physionet_ECG_data-main.zip en una carpeta en la que tenga permiso de escritura. Las instrucciones para este ejemplo asumen que ha descargado el archivo en el directorio temporal, tempdir, de MATLAB®. Modifique las instrucciones posteriores para descomprimir y cargar los datos si elige descargar los datos en una carpeta distinta de tempdir.

Después de descargar los datos de GitHub, descomprima el archivo en el directorio temporal.

unzip(fullfile(tempdir,"physionet_ECG_data-main.zip"),tempdir)

Cuando se descomprime, se crea la carpeta physionet-ECG_data-main en el directorio temporal. Esta carpeta contiene el archivo de texto README.md y ECGData.zip. El archivo ECGData.zip contiene

  • ECGData.mat

  • Modified_physionet_data.txt

  • License.txt

ECGData.mat alberga los datos usados en este ejemplo. El archivo de texto, Modified_physionet_data.txt, es necesario para la política de reproducción de PhysioNet y proporciona las atribuciones de las fuentes de los datos, además de una descripción de los pasos de preprocesamiento aplicados a cada grabación de ECG.

Descomprima ECGData.zip en physionet-ECG_data-main. Cargue los datos en el área de trabajo de MATLAB.

unzip(fullfile(tempdir,"physionet_ECG_data-main","ECGData.zip"), ...
    fullfile(tempdir,"physionet_ECG_data-main"))
load(fullfile(tempdir,"physionet_ECG_data-main","ECGData.mat"))

ECGData es un arreglo de estructura con dos campos: Data y Labels. El campo Data es una matriz de 162 por 65536, donde cada fila es una grabación de ECG muestreada a 128 hercios. Labels es un arreglo de celdas de 162 por 1 de etiquetas de diagnóstico, una para cada fila de Data. Las tres categorías de diagnóstico son: 'ARR', 'CHF' y 'NSR'.

Para almacenar los datos preprocesados de cada categoría, cree en primer lugar un directorio de datos de ECG dataDir dentro de tempdir. Después, cree tres subdirectorios en 'data' llamados de acuerdo con cada categoría de ECG. La función de ayuda helperCreateECGDirectories lo hace. helperCreateECGDirectories acepta ECGData, el nombre de un directorio de datos de ECG y el nombre de un directorio principal como argumentos de entrada. Puede reemplazar tempdir con otro directorio donde tenga permiso de escritura. Puede encontrar el código fuente para esta función de ayuda en la sección Funciones de apoyo al final de este ejemplo.

parentDir = tempdir;
dataDir = "data";
helperCreateECGDirectories(ECGData,parentDir,dataDir)

Cree una gráfica con un representante de cada categoría de ECG. La función de ayuda helperPlotReps lo hace. helperPlotReps acepta ECGData como entrada. Puede encontrar el código fuente para esta función de ayuda en la sección Funciones de apoyo al final de este ejemplo.

helperPlotReps(ECGData)

Crear representaciones de tiempo-frecuencia

Después de crear las carpetas, cree representaciones de tiempo-frecuencia de las señales de ECG. Estas representaciones se conocen como escalogramas. Un escalograma es el valor absoluto de los coeficientes de la CWT de una señal.

Para crear los escalogramas, realice el cálculo previo de un banco de filtros de CWT. Realizar el cálculo previo de un banco de filtros de CWT es el método preferido para obtener la CWT de muchas señales que utilizan los mismos parámetros.

Antes de generar los escalogramas, examine uno de ellos. Cree un banco de filtros de CWT utilizando cwtfilterbank (Wavelet Toolbox) para una señal con 1000 muestras. Utilice el banco de filtros para tomar la CWT de las primeras 1000 muestras de la señal y obtener el escalograma a partir de los coeficientes.

Fs = 128;
fb = cwtfilterbank(SignalLength=1000, ...
    SamplingFrequency=Fs, ...
    VoicesPerOctave=12);
sig = ECGData.Data(1,1:1000);
[cfs,frq] = wt(fb,sig);
t = (0:999)/Fs;
figure
pcolor(t,frq,abs(cfs))
set(gca,"yscale","log")
shading interp
axis tight
title("Scalogram")
xlabel("Time (s)")
ylabel("Frequency (Hz)")

Utilice la función de ayuda helperCreateRGBfromTF para crear los escalogramas como imágenes RGB y escríbalos en el subdirectorio adecuado de dataDir. El código fuente para esta función de ayuda está en la sección Funciones de apoyo al final de este ejemplo. Para ser compatible con la arquitectura de GoogLeNet, cada imagen RGB es un arreglo de tamaño 224 por 224 por 3.

helperCreateRGBfromTF(ECGData,parentDir,dataDir)

Dividir en datos de entrenamiento y de validación

Cargue las imágenes de escalograma como un almacén de datos de imágenes. La función imageDatastore etiqueta automáticamente las imágenes según los nombres de carpeta y almacena los datos como un objeto ImageDatastore. Un almacén de datos de imágenes permite almacenar un gran volumen de datos de imágenes, incluidos los que no caben en la memoria, y leer eficazmente lotes de imágenes durante el entrenamiento de una CNN.

allImages = imageDatastore(fullfile(parentDir,dataDir), ...
    "IncludeSubfolders",true, ...
    "LabelSource","foldernames");

Divida de manera aleatoria las imágenes en dos grupos, uno para el entrenamiento y otro para la validación. Utilice el 80% de las imágenes para el entrenamiento y el resto para la validación.

[imgsTrain,imgsValidation] = splitEachLabel(allImages,0.8,"randomized");
disp("Number of training images: "+num2str(numel(imgsTrain.Files)))
Number of training images: 130
disp("Number of validation images: "+num2str(numel(imgsValidation.Files)))
Number of validation images: 32

GoogLeNet

Cargar

Cargue la red neuronal GoogLeNet preentrenada. Si el paquete de soporte Deep Learning Toolbox™ Model for GoogLeNet Network no está instalado, el software proporciona un enlace al paquete de soporte correspondiente en Add-On Explorer. Para instalar el paquete de soporte, haga clic en el enlace y, después, en Install.

net = imagePretrainedNetwork("googlenet");

Extraiga y muestre la gráfica de capas de la red.

numberOfLayers = numel(net.Layers);
figure("Units","normalized","Position",[0.1 0.1 0.8 0.8])
plot(net)
title("GoogLeNet Layer Graph: "+num2str(numberOfLayers)+" Layers")

Inspeccione el primer elemento de la propiedad Layers de la red. Confirme que GoogLeNet requiere imágenes RGB de tamaño 224 por 224 por 3.

net.Layers(1)
ans = 
  ImageInputLayer with properties:

                      Name: 'data'
                 InputSize: [224 224 3]
        SplitComplexInputs: 0

   Hyperparameters
          DataAugmentation: 'none'
             Normalization: 'zerocenter'
    NormalizationDimension: 'auto'
                      Mean: [224×224×3 single]

Modificar parámetros de red GoogLeNet

Cada capa de la arquitectura de la red se puede considerar un filtro. Las primeras capas identifican más características comunes de imágenes, como manchas, bordes y colores. Las siguientes capas se centran en características más específicas para diferenciar categorías. GoogLeNet está preentrenada para clasificar imágenes en 1000 categorías de objetos. Debe volver a entrenar GoogLeNet para nuestro problema de clasificación de ECG.

Inspeccione las últimas cuatro capas de la red.

net.Layers(end-3:end)
ans = 
  4×1 Layer array with layers:

     1   'pool5-7x7_s1'        2-D Global Average Pooling   2-D global average pooling
     2   'pool5-drop_7x7_s1'   Dropout                      40% dropout
     3   'loss3-classifier'    Fully Connected              1000 fully connected layer
     4   'prob'                Softmax                      softmax

Para evitar un sobreajuste, se utiliza una capa de abandono. Una capa de abandono establece aleatoriamente elementos de entrada en cero con una probabilidad dada. Consulte dropoutLayer para obtener más información. La probabilidad predeterminada es 0.5. Reemplace la capa final de abandono de la red, pool5-drop_7x7_s1, con una capa de abandono de probabilidad 0.6.

newDropoutLayer = dropoutLayer(0.6,"Name","new_Dropout");
net = replaceLayer(net,"pool5-drop_7x7_s1",newDropoutLayer);

Las capas convolucionales de la red extraen características de imágenes. Después, la última capa de aprendizaje, loss3-classifier, en GoogLeNet, contiene información sobre cómo combinar las características que la red extrae en probabilidades de clase. Para volver a entrenar GoogLeNet para clasificar imágenes RGB, reemplácela con la nueva capa adaptada a los datos.

Reemplace la capa totalmente conectada loss3-classifier con una nueva capa totalmente conectada con el mismo número de filtros que de clases. Para aprender más rápido en las nuevas capas que en las capas transferidas, aumente los factores de tasa de aprendizaje de la capa totalmente conectada.

numClasses = numel(categories(imgsTrain.Labels));
newConnectedLayer = fullyConnectedLayer(numClasses,"Name","new_fc", ...
    "WeightLearnRateFactor",5,"BiasLearnRateFactor",5);
net = replaceLayer(net,"loss3-classifier",newConnectedLayer);

Inspeccione las últimas cinco capas. Confirme que ha reemplazado las capas de abandono, convolucionales y totalmente conectadas.

net.Layers(end-3:end)
ans = 
  4×1 Layer array with layers:

     1   'pool5-7x7_s1'   2-D Global Average Pooling   2-D global average pooling
     2   'new_Dropout'    Dropout                      60% dropout
     3   'new_fc'         Fully Connected              3 fully connected layer
     4   'prob'           Softmax                      softmax

Establecer opciones de entrenamiento y entrenar GoogLeNet

Entrenar una red neuronal es un proceso iterativo que conlleva minimizar una función de pérdida. Para minimizar la función de pérdida, se utiliza un algoritmo de gradiente descendente. En cada iteración, el gradiente de la función de pérdida se evalúa y los pesos del algoritmo descendente se actualizan.

El entrenamiento se puede ajustar estableciendo distintas opciones. InitialLearnRate especifica el tamaño de paso inicial en la dirección del gradiente negativo de la función de pérdida. MiniBatchSize especifica el tamaño de un subconjunto del conjunto de entrenamiento que se desea usar en cada iteración. Una época es una pasada completa del algoritmo de entrenamiento por todo el conjunto de entrenamiento. MaxEpochs especifica el número máximo de épocas que se desea usar para el entrenamiento. Elegir el número correcto de épocas no es una tarea trivial. Reducir el número de épocas tiene el efecto de provocar un subajuste del modelo, mientras que aumentar el número de épocas provoca un sobreajuste.

Utilice la función trainingOptions para especificar las opciones de entrenamiento. Establezca MiniBatchSize en 15, MaxEpochs en 20 y InitialLearnRate en 0.0001. Visualice el progreso del entrenamiento estableciendo Plots en training-progress. Utilice el optimizador de gradiente descendente estocástico con momento. De forma predeterminada, el entrenamiento se hace en una GPU, si se dispone de ella. Utilizar una GPU requiere Parallel Computing Toolbox™. Para ver las GPU compatibles, consulte GPU Computing Requirements (Parallel Computing Toolbox).

options = trainingOptions("sgdm", ...
    MiniBatchSize=15, ...
    MaxEpochs=20, ...
    InitialLearnRate=1e-4, ...
    ValidationData=imgsValidation, ...
    ValidationFrequency=10, ...
    Verbose=true, ...
    Plots="training-progress", ...
    Metrics="accuracy");

Entrene la red. El proceso de entrenamiento tarda normalmente entre 1 y 5 minutos en una CPU de sobremesa. Los tiempos de ejecución serán más rápidos si se puede utilizar una GPU. La ventana de comandos muestra información de entrenamiento durante la ejecución. Los resultados incluyen número de épocas, número de iteraciones, tiempo transcurrido, precisión de minilotes, precisión de validación y valor de la función de pérdida para los datos de validación.

trainedGN = trainnet(imgsTrain,net,"crossentropy",options);
    Iteration    Epoch    TimeElapsed    LearnRate    TrainingLoss    ValidationLoss    TrainingAccuracy    ValidationAccuracy
    _________    _____    ___________    _________    ____________    ______________    ________________    __________________
            0        0       00:00:07       0.0001                            1.3444                                    46.875
            1        1       00:00:07       0.0001          1.7438                                    40                      
           10        2       00:00:37       0.0001          1.7555            1.1047                  40                  62.5
           20        3       00:01:03       0.0001         0.75169           0.68252              66.667                 68.75
           30        4       00:01:27       0.0001         0.74739           0.52126              73.333                78.125
           40        5       00:01:50       0.0001         0.49647           0.43025                  80                84.375
           50        7       00:02:13       0.0001         0.27949           0.36374              93.333                  87.5
           60        8       00:02:33       0.0001         0.15129           0.36825              93.333                84.375
           70        9       00:02:50       0.0001         0.15792           0.29109                 100                  87.5
           80       10       00:03:07       0.0001          0.3697           0.30388              93.333                90.625
           90       12       00:03:28       0.0001           0.159           0.25558                 100                90.625
          100       13       00:03:47       0.0001         0.02107           0.25558                 100                90.625
          110       14       00:04:06       0.0001         0.17743            0.2531              93.333                90.625
          120       15       00:04:27       0.0001        0.086914           0.23932                 100                90.625
          130       17       00:04:48       0.0001         0.13208           0.24259              93.333                90.625
          140       18       00:05:12       0.0001        0.025648           0.20339                 100                 93.75
          150       19       00:05:36       0.0001         0.17878           0.19556              93.333                 93.75
          160       20       00:06:01       0.0001        0.050998           0.21189                 100                 93.75
Training stopped: Max epochs completed

Evaluar la precisión de GoogLeNet

Evalúe la red usando los datos de validación.

classNames = categories(imgsTrain.Labels);
scores = minibatchpredict(trainedGN,imgsValidation);
YPred = scores2label(scores,classNames);
accuracy = mean(YPred==imgsValidation.Labels);
disp("GoogLeNet Accuracy: "+num2str(100*accuracy)+"%")
GoogLeNet Accuracy: 93.75%

La precisión es idéntica a la precisión de validación indicada en la figura de visualización de entrenamiento. Los escalogramas se han dividido en colecciones de entrenamiento y validación. Se han utilizado ambas colecciones para entrenar GoogLeNet. La forma ideal de evaluar el resultado del entrenamiento es que la red clasifique datos que no haya visto. Dado que hay una cantidad insuficiente de datos para dividirlos en entrenamiento, validación y prueba, tratamos la precisión de validación calculada como la precisión de la red.

Explorar las activaciones de GoogLeNet

Cada capa de una CNN produce una respuesta, o activación, a una imagen de entrada. Sin embargo, solo hay unas pocas capas dentro de una CNN que son adecuadas para la extracción de características de imagen. Inspeccione las cinco primeras capas de la red entrenada.

trainedGN.Layers(1:5)
ans = 
  5×1 Layer array with layers:

     1   'data'             Image Input                   224×224×3 images with 'zerocenter' normalization
     2   'conv1-7x7_s2'     2-D Convolution               64 7×7×3 convolutions with stride [2  2] and padding [3  3  3  3]
     3   'conv1-relu_7x7'   ReLU                          ReLU
     4   'pool1-3x3_s2'     2-D Max Pooling               3×3 max pooling with stride [2  2] and padding [0  1  0  1]
     5   'pool1-norm1'      Cross Channel Normalization   cross channel normalization with 5 channels per element

Las capas al principio de la red capturan características de imagen básicas, como bordes y manchas. Para verlo, visualice los pesos del filtro de la red desde la primera capa convolucional. Existen 64 conjuntos individuales de pesos en la primera capa.

wghts = trainedGN.Layers(2).Weights;
wghts = rescale(wghts);
wghts = imresize(wghts,8);
figure
I = imtile(wghts,GridSize=[8 8]);
imshow(I)
title("First Convolutional Layer Weights")

Puede examinar las activaciones y descubrir qué características aprende GoogLeNet comparando áreas de activación con la imagen original. Para obtener más información, consulte Visualize Activations of a Convolutional Neural Network y Visualize Features of a Convolutional Neural Network.

Examine qué áreas de las capas convolucionales activan una imagen de la clase ARR. Compárelas con las áreas correspondientes de la imagen original. Cada capa de una red neuronal convolucional consta de muchos arreglos 2D llamados canales. Pase la imagen a través de la red y examine las activaciones de salida de la primera capa convolucional, conv1-7x7_s2.

convLayer = "conv1-7x7_s2";

imgClass = "ARR";
imgName = "ARR_10.jpg";
imarr = imread(fullfile(parentDir,dataDir,imgClass,imgName));

trainingFeaturesARR = predict(trainedGN,single(imarr),Outputs=convLayer);
sz = size(trainingFeaturesARR);
trainingFeaturesARR = reshape(trainingFeaturesARR,[sz(1) sz(2) 1 sz(3)]);
figure
I = imtile(rescale(trainingFeaturesARR),GridSize=[8 8]);
imshow(I)
title(imgClass+" Activations")

Encuentre el canal más fuerte para esta imagen. Compare el canal más fuerte con la imagen original.

imgSize = size(imarr);
imgSize = imgSize(1:2);
[~,maxValueIndex] = max(max(max(trainingFeaturesARR)));
arrMax = trainingFeaturesARR(:,:,:,maxValueIndex);
arrMax = rescale(arrMax);
arrMax = imresize(arrMax,imgSize);
figure
I = imtile({imarr,arrMax});
imshow(I)
title("Strongest "+imgClass+" Channel: "+num2str(maxValueIndex))

SqueezeNet

SqueezeNet es una CNN profunda cuya arquitectura admite imágenes de tamaño 227 por 227 por 3. Aunque las dimensiones de la imagen son diferentes para GoogLeNet, no es necesario que genere nuevas imágenes RGB con las dimensiones de SqueezeNet. Puede utilizar las imágenes RGB originales.

Cargar

Cargue la red neuronal SqueezeNet preentrenada.

netsqz = imagePretrainedNetwork("squeezenet");

Extraiga la gráfica de capas de la red. Confirme que SqueezeNet tiene menos capas que GoogLeNet. Confirme también que SqueezeNet está configurada para imágenes de tamaño 227 por 227 por 3.

disp("Number of Layers: "+num2str(numel(netsqz.Layers)))
Number of Layers: 68
netsqz.Layers(1)
ans = 
  ImageInputLayer with properties:

                      Name: 'data'
                 InputSize: [227 227 3]
        SplitComplexInputs: 0

   Hyperparameters
          DataAugmentation: 'none'
             Normalization: 'zerocenter'
    NormalizationDimension: 'auto'
                      Mean: [1×1×3 single]

Modificar parámetros de red de SqueezeNet

Para volver a entrenar SqueezeNet para clasificar nuevas imágenes, haga cambios similares a los que se hicieron para GoogLeNet.

Inspeccione las últimas cinco capas de la red.

netsqz.Layers(end-4:end)
ans = 
  5×1 Layer array with layers:

     1   'conv10'         2-D Convolution              1000 1×1×512 convolutions with stride [1  1] and padding [0  0  0  0]
     2   'relu_conv10'    ReLU                         ReLU
     3   'pool10'         2-D Global Average Pooling   2-D global average pooling
     4   'prob'           Softmax                      softmax
     5   'prob_flatten'   Flatten                      Flatten

Reemplace la última capa de abandono de la red con una capa de abandono de probabilidad 0.6.

tmpLayer = netsqz.Layers(end-5);
newDropoutLayer = dropoutLayer(0.6,"Name","new_dropout");
netsqz = replaceLayer(netsqz,tmpLayer.Name,newDropoutLayer);

A diferencia de GoogLeNet, la última capa de aprendizaje de SqueezeNet es una capa convolucional de 1 por 1, conv10, y no una capa totalmente conectada. Reemplace la capa con una nueva capa convolucional con el número de filtros igual al número de clases. Al igual que con GoogLeNet, aumente los factores de tasa de aprendizaje de la nueva capa.

numClasses = numel(categories(imgsTrain.Labels));
tmpLayer = netsqz.Layers(end-4);
newLearnableLayer = convolution2dLayer(1,numClasses, ...
        "Name","new_conv", ...
        "WeightLearnRateFactor",10, ...
        "BiasLearnRateFactor",10);
netsqz = replaceLayer(netsqz,tmpLayer.Name,newLearnableLayer);

Inspeccione las últimas cinco capas de la red. Confirme que la capa de abandono y la capa convolucional han cambiado.

netsqz.Layers(end-4:end)
ans = 
  5×1 Layer array with layers:

     1   'new_conv'       2-D Convolution              3 1×1 convolutions with stride [1  1] and padding [0  0  0  0]
     2   'relu_conv10'    ReLU                         ReLU
     3   'pool10'         2-D Global Average Pooling   2-D global average pooling
     4   'prob'           Softmax                      softmax
     5   'prob_flatten'   Flatten                      Flatten

Preparar los datos RGB para SqueezeNet

Las imágenes RGB tienen dimensiones adecuadas para la arquitectura de GoogLeNet. Cree almacenes de datos de imágenes aumentadas que cambien automáticamente el tamaño de las imágenes RGB existentes para la arquitectura de SqueezeNet. Para obtener más información, consulte augmentedImageDatastore.

augimgsTrain = augmentedImageDatastore([227 227],imgsTrain);
augimgsValidation = augmentedImageDatastore([227 227],imgsValidation);

Establecer opciones de entrenamiento y entrenar SqueezeNet

Cree un nuevo conjunto de opciones de entrenamiento que desee usar con SqueezeNet y entrene la red.

ilr = 3e-4;
miniBatchSize = 10;
maxEpochs = 15;
valFreq = floor(numel(augimgsTrain.Files)/miniBatchSize);
opts = trainingOptions("sgdm", ...
    MiniBatchSize=miniBatchSize, ...
    MaxEpochs=maxEpochs, ...
    InitialLearnRate=ilr, ...
    ValidationData=augimgsValidation, ...
    ValidationFrequency=valFreq, ...
    Verbose=1, ...
    Plots="training-progress", ...
    Metrics="accuracy");

trainedSN = trainnet(augimgsTrain,netsqz,"crossentropy",opts);
    Iteration    Epoch    TimeElapsed    LearnRate    TrainingLoss    ValidationLoss    TrainingAccuracy    ValidationAccuracy
    _________    _____    ___________    _________    ____________    ______________    ________________    __________________
            0        0       00:00:01       0.0003                            2.7267                                        25
            1        1       00:00:01       0.0003          3.0502                                    30                      
           13        1       00:00:05       0.0003         0.93269           0.81717                  60                78.125
           26        2       00:00:10       0.0003          0.6929           0.62475                  70                 81.25
           39        3       00:00:15       0.0003         0.55664           0.54038                  70                84.375
           50        4       00:00:19       0.0003        0.075004                                   100                      
           52        4       00:00:20       0.0003         0.27402           0.51236                  90                 81.25
           65        5       00:00:25       0.0003         0.15558           0.72845                  90                 81.25
           78        6       00:00:27       0.0003         0.29531           0.58038                  90                 81.25
           91        7       00:00:30       0.0003        0.053372           0.53191                 100                 81.25
          100        8       00:00:32       0.0003        0.019003                                   100                      
          104        8       00:00:33       0.0003         0.23475           0.22768                  80                 93.75
          117        9       00:00:37       0.0003        0.059982           0.15849                 100                96.875
          130       10       00:00:43       0.0003        0.038729           0.20219                 100                90.625
          143       11       00:00:46       0.0003       0.0059834           0.26095                 100                90.625
          150       12       00:00:47       0.0003        0.002025                                   100                      
          156       12       00:00:48       0.0003       0.0067973           0.16036                 100                96.875
          169       13       00:00:50       0.0003       0.0086382           0.17935                 100                96.875
          182       14       00:00:52       0.0003       0.0020118           0.21593                 100                 93.75
          195       15       00:00:54       0.0003       0.0061499           0.22566                 100                 93.75
Training stopped: Max epochs completed

Evaluar la precisión de SqueezeNet

Evalúe la red usando los datos de validación.

scores = minibatchpredict(trainedSN,augimgsValidation);
YPred = scores2label(scores,classNames);
accuracy = mean(YPred==imgsValidation.Labels);
disp("SqueezeNet Accuracy: "+num2str(100*accuracy)+"%")
SqueezeNet Accuracy: 96.875%

Conclusión

En este ejemplo se muestra cómo usar la transferencia del aprendizaje y el análisis de wavelets continuas para clasificar tres clases de señales de ECG aprovechando las CNN preentrenadas GoogLeNet y SqueezeNet. Se utilizan representaciones de tiempo-frecuencia basadas en wavelets de señales de ECG para crear escalogramas. Se generan las imágenes RGB de los escalogramas. Las imágenes se utilizan para ajustar ambas CNN profundas. También se han explorado activaciones de diferentes capas de red.

En este ejemplo se ilustra un flujo de trabajo posible que puede utilizar para clasificar señales utilizando modelos de CNN preentrenados. Otros flujos de trabajo son posibles. Deploy Signal Classifier on NVIDIA Jetson Using Wavelet Analysis and Deep Learning (Wavelet Toolbox) y Deploy Signal Classifier Using Wavelets and Deep Learning on Raspberry Pi (Wavelet Toolbox) muestran cómo desplegar código en hardware para la clasificación de señales. GoogLeNet y SqueezeNet son modelos preentrenados con un subconjunto de la base de datos de ImageNet [10], que se utiliza en el ImageNet Large-Scale Visual Recognition Challenge (ILSVRC) [8]. La colección de ImageNet contiene imágenes de objetos reales como peces, pájaros, electrodomésticos y hongos. Los escalogramas quedan fuera de la clase de objetos reales. Para ajustarse a la arquitectura de GoogLeNet y SqueezeNet, los escalogramas también se han sometido a una reducción de datos. En lugar de ajustar las CNN preentrenadas para distinguir diferentes clases de escalogramas, entrenar una CNN desde cero en las dimensiones originales del escalograma es una opción.

Referencias

  1. Baim, D. S., W. S. Colucci, E. S. Monrad, H. S. Smith, R. F. Wright, A. Lanoue, D. F. Gauthier, B. J. Ransil, W. Grossman y E. Braunwald. "Survival of patients with severe congestive heart failure treated with oral milrinone". Journal of the American College of Cardiology. Vol. 7, número 3, 1986, págs. 661–670.

  2. Engin, M. "ECG beat classification using neuro-fuzzy network". Pattern Recognition Letters. Vol. 25, número 15, 2004, págs. 1715–1722.

  3. Goldberger A. L., L. A. N. Amaral, L. Glass, J. M. Hausdorff, P. Ch. Ivanov, R. G. Mark, J. E. Mietus, G. B. Moody, C.-K. Peng y H. E. Stanley. "PhysioBank, PhysioToolkit, and PhysioNet: Components of a New Research Resource for Complex Physiologic Signals". Circulation. Vol. 101, número 23: e215–e220. [Circulation Electronic Pages; http://circ.ahajournals.org/content/101/23/e215.full]; 2000 (13 de junio). DOI: 10.1161/01.CIR.101.23.e215.

  4. Leonarduzzi, R. F., G. Schlotthauer y M. E. Torres. "Wavelet leader based multifractal analysis of heart rate variability during myocardial ischaemia". In Engineering in Medicine and Biology Society (EMBC), Annual International Conference of the IEEE, 110–113. Buenos Aires, Argentina: IEEE, 2010.

  5. Li, T. y M. Zhou. "ECG classification using wavelet packet entropy and random forests". Entropy. Vol. 18, número 8, 2016, pág. 285.

  6. Maharaj, E. A. y A. M. Alonso. "Discriminant analysis of multivariate time series: Application to diagnosis based on ECG signals". Computational Statistics and Data Analysis. Vol. 70, 2014, págs. 67–87.

  7. Moody, G. B. y R. G. Mark. "The impact of the MIT-BIH Arrhythmia Database". IEEE Engineering in Medicine and Biology Magazine. Vol. 20. Número 3, mayo-junio 2001, págs. 45–50. (PMID: 11446209)

  8. Russakovsky, O., J. Deng y H. Su et al. "ImageNet Large Scale Visual Recognition Challenge". International Journal of Computer Vision. Vol. 115, número 3, 2015, págs. 211–252.

  9. Zhao, Q. y L. Zhang. "ECG feature extraction and classification using wavelet transform and support vector machines". In IEEE International Conference on Neural Networks and Brain, 1089–1092. Pekín, China: IEEE, 2005.

  10. ImageNet. http://www.image-net.org

Funciones de apoyo

helperCreateECGDataDirectories crea un directorio de datos dentro de un directorio principal y, después, crea tres subdirectorios dentro del directorio de los datos. Los subdirectorios se denominan según cada clase de señal de ECG encontrada en ECGData.

function helperCreateECGDirectories(ECGData,parentFolder,dataFolder)
% This function is only intended to support the ECGAndDeepLearningExample.
% It may change or be removed in a future release.

rootFolder = parentFolder;
localFolder = dataFolder;
mkdir(fullfile(rootFolder,localFolder))

folderLabels = unique(ECGData.Labels);
for i = 1:numel(folderLabels)
    mkdir(fullfile(rootFolder,localFolder,char(folderLabels(i))));
end
end

helperPlotReps representa las primeras mil muestras de un representante de cada clase de señal de ECG encontrada en ECGData.

function helperPlotReps(ECGData)
% This function is only intended to support the ECGAndDeepLearningExample.
% It may change or be removed in a future release.

folderLabels = unique(ECGData.Labels);

for k=1:3
    ecgType = folderLabels{k};
    ind = find(ismember(ECGData.Labels,ecgType));
    subplot(3,1,k)
    plot(ECGData.Data(ind(1),1:1000));
    grid on
    title(ecgType)
end
end

helperCreateRGBfromTF utiliza cwtfilterbank (Wavelet Toolbox) para obtener la transformada wavelet continua de las señales de ECG y genera los escalogramas a partir de los coeficientes de wavelets. La función de ayuda cambia el tamaño de los escalogramas y los escribe en el disco como imágenes jpeg.

function helperCreateRGBfromTF(ECGData,parentFolder,childFolder)
% This function is only intended to support the ECGAndDeepLearningExample.
% It may change or be removed in a future release.

imageRoot = fullfile(parentFolder,childFolder);

data = ECGData.Data;
labels = ECGData.Labels;

[~,signalLength] = size(data);

fb = cwtfilterbank(SignalLength=signalLength,VoicesPerOctave=12);
r = size(data,1);

for ii = 1:r
    cfs = abs(fb.wt(data(ii,:)));
    im = ind2rgb(round(rescale(cfs,0,255)),jet(128));
    
    imgLoc = fullfile(imageRoot,char(labels(ii)));
    imFileName = char(labels(ii))+"_"+num2str(ii)+".jpg";
    imwrite(imresize(im,[224 224]),fullfile(imgLoc,imFileName));
end
end

Consulte también

(Wavelet Toolbox) | | | | | |

Temas