主要内容

利用小波分析和深度学习在NVIDIA Jetson上部署信号分类器

该示例展示了如何生成和部署一个CUDA®可执行文件,该可执行文件使用连续小波变换(CWT)和预训练的卷积神经网络(CNN)提取的特征对人体心电图(ECG)信号进行分类。

SqueezeNet是一个深度CNN,最初设计用于将图像分类为1000个类别。我们重新利用CNN的网络结构,根据心电信号的尺度图对其进行分类。标量图是信号的CWT的绝对值。在训练SqueezeNet对心电信号进行分类之后,您可以创建一个CUDA可执行文件,生成心电信号的标量图,然后使用CNN对信号进行分类。可执行文件和CNN都部署到NVIDIA硬件上。

中使用的数据与本例相同基于小波分析和深度学习的时间序列分类(小波工具箱).在该示例中,使用GoogLeNet和SqueezeNet的迁移学习将ECG波形分类为三类之一。为了方便起见,这里重复对数据的描述以及如何获取数据。

心电数据描述和下载

心电图数据来自三组人:心律失常(ARR)、充血性心力衰竭(CHF)和窦性心律正常(NSR)的人。总共有162个ECG记录来自三个PhysioNet数据库:MIT-BIH心律失常数据库[2] [3],MIT-BIH正常窦性心律数据库[3]BIDMC充血性心力衰竭数据库[1][3]。更具体地说,来自心律失常患者的96次录音,来自充血性心力衰竭患者的30次录音,来自正常窦性心律患者的36次录音。目标是训练一个模型来区分ARR, CHF和NSR。

您可以从MathWorks中获取这些数据GitHub库.如需从网站下载数据,请单击代码并选择下载ZIP.保存文件physionet_ECG_data-main.zip在您有写权限的文件夹中。本例的说明假设您已经将文件下载到临时目录,tempdir,在MATLAB中。如果选择在不同的文件夹中下载数据,请修改解压缩和加载数据的后续说明tempdir

从GitHub下载数据后,在临时目录中解压缩文件。

解压缩(fullfile (tempdir,“physionet_ECG_data-main.zip”), tempdir)

解压缩将创建文件夹physionet-ECG_data-main在临时目录中。此文件夹包含文本文件README.md而且ECGData.zip.的ECGData.zip文件包含:

  • ECGData.mat

  • Modified_physionet_data.txt

  • License.txt

ECGData.mat保存本例中使用的数据。文本文件Modified_physionet_data.txt是PhysioNet的复制策略所要求的,并提供了数据的源属性以及应用于每个ECG记录的预处理步骤的描述。

解压缩ECGData.zipphysionet-ECG_data-main.将数据文件加载到MATLAB工作区中。

解压缩(fullfile (tempdir,“physionet_ECG_data-main”“ECGData.zip”),...fullfile (tempdir“physionet_ECG_data-main”)加载(fullfile (tempdir“physionet_ECG_data-main”“ECGData.mat”))

ECGData是一个有两个字段的结构数组:数据而且标签.的数据field是一个162 × 65536的矩阵,其中每一行都是一个以128赫兹采样的ECG记录。标签是一个162 × 1单元阵列的诊断标签,每行一个标签数据.这三个诊断类别是:“加勒比海盗”瑞士法郎的,“签约”

特征提取

下载数据后,必须生成信号的标量图。标量图是CNN的“输入”图像。

为了存储每个类别的标量图,首先创建一个ECG数据目录“数据”内部tempdir.然后在中创建三个子目录“数据”以每个ECG类别命名。辅助函数helperCreateECGDirectories为你做这个。helperCreateECGDirectories接受ECGData, ECG数据目录的名称,以及父目录的名称作为输入参数。你可以替换tempdir您有写权限的另一个目录。方法中可以找到此帮助函数的源代码金宝app支持功能节的末尾。

parentDir = tempdir;dataDir =“数据”;helperCreateECGDirectories (ECGData parentDir dataDir)

制作文件夹后,将心电信号的标量图创建为RGB图像,并将其写入相应的子目录中dataDir.要创建标量图,首先要预先计算CWT滤波器组。当使用相同参数获得多个信号的CWT时,预计算滤波器组是首选方法。辅助函数helperCreateRGBfromTF这是否。此帮助函数的源代码在金宝app支持功能节的末尾。为了与SqueezeNet体系结构兼容,每个RGB图像都是一个大小为227 × 227 × 3的数组。

helperCreateRGBfromTF (ECGData parentDir dataDir)

将数据集分为训练数据和验证数据

将标量图图像加载为图像数据存储。的imageDatastore函数根据文件夹名称自动标记图像,并将数据存储为ImageDatastore对象。图像数据存储使您能够存储大量图像数据,包括不适合内存的数据,并在训练CNN时有效地读取批量图像。

allImages = imageDatastore(fullfile(tempdir,dataDir),...“IncludeSubfolders”,真的,...“LabelSource”“foldernames”);

将图像随机分为两组,一组用于训练,另一组用于验证。使用80%的图像进行训练,其余图像用于验证。为了重现性,我们将随机种子设置为默认值。

rng默认的[imgsTrain,imgsValidation] = splitEachLabel(allImages,0.8,“随机”);disp (['训练图像数量:'num2str(元素个数(imgsTrain.Files))));
训练图像数量:130张
disp ([验证图像的数量:num2str(元素个数(imgsValidation.Files))));
验证图像数量:32

SqueezeNet

SqueezeNet是一个预先训练好的CNN,可以将图像分为1000个类别。你需要重新训练SqueezeNet来解决我们的心电分类问题。在重新培训之前,您需要修改几个网络层并设置各种培训选项。重新训练完成后,将CNN保存在.mat文件。CUDA可执行文件将使用.mat文件。

指定实验试验索引和结果目录。如有必要,请创建该目录。

试验= 1;ResultDir =“结果”如果~存在(ResultDir“dir”mkdir (ResultDir)结束MatFile = fullfile(ResultDir,sprintf(“SqueezeNet_Trial % d.mat”、试验));

负载SqeezeNet。提取层图并检查最后五个层。

SQZ =挤压板;lgraph = layerGraph(sqz);lgraph.Layers (end-4:结束)
ans = 5×1带有图层的层数组:1 'conv10' Convolution 1000 1×1×512 convolutions with stride[1 1]和padding [0 000 0] 2 'relu_conv10' ReLU ReLU 3 'pool10' 2- d Global Average Pooling 2- d Global Average Pooling 4 'prob' Softmax Softmax 5 'ClassificationLayer_predictions' Classification Output crossentropyex with 'tench'和999个其他类

为了重新训练SqueezeNet对三类心电信号进行分类,可以替换“conv10”层,使用新的卷积层,其中滤波器的数量等于ECG类的数量。用一个没有类标签的新层替换分类层。

numClasses = numel(categories(imgsTrain.Labels));new_conv10_weightlearnatefactor = 1;new_conv10_biaslearnatefactor = 1;newConvLayer = convolution2dLayer(1,numClasses,...“名字”“new_conv10”...“WeightLearnRateFactor”new_conv10_WeightLearnRateFactor,...“BiasLearnRateFactor”, new_conv10_BiasLearnRateFactor);lgraph =替换层(lgraph,“conv10”, newConvLayer);newClassLayer = classificationLayer(“名字”“new_classoutput”);lgraph =替换层(lgraph,“ClassificationLayer_predictions”, newClassLayer);lgraph.Layers (end-4:结束)
ans = 5×1带有图层的层数组:1 'new_conv10' Convolution 3 1×1 convolutions with stride[1 1]和padding [0 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 'new_classoutput' Classification Output crossentropyex . 2

创建一套训练选项来使用SqueezeNet。

OptimSolver =“个”;MiniBatchSize = 15;MaxEpochs = 20;InitialLearnRate = 1e-4;动量= 0.9;ExecutionEnvironment =“cpu”;选项= trainingOptions(OptimSolver,...“MiniBatchSize”MiniBatchSize,...“MaxEpochs”MaxEpochs,...“InitialLearnRate”InitialLearnRate,...“ValidationData”imgsValidation,...“ValidationFrequency”10...“ExecutionEnvironment”ExecutionEnvironment,...“动量”、动力);

保存结构中的所有参数。经过训练的网络和结构稍后将保存在.mat文件。

TrialParameter。new_conv10_weightlearnatefactor = new_conv10_weightlearnatefactor;TrialParameter。new_conv10_biaslearnatefactor = new_conv10_biaslearnatefactor;TrialParameter。OptimSolver =OptimSolver; TrialParameter.MiniBatchSize = MiniBatchSize; TrialParameter.MaxEpochs = MaxEpochs; TrialParameter.InitialLearnRate = InitialLearnRate; TrialParameter.Momentum = Momentum; TrialParameter.ExecutionEnvironment = ExecutionEnvironment;

将随机种子设置为默认值,训练网络。保存训练后的网络、试验参数、训练运行时间和包含验证图像的图像数据存储。在桌面CPU上,训练过程通常需要1 ~ 5分钟。如果你想使用一个训练有素的CNN从以前的试验,设置试验到那次试验的索引号LoadModel真正的

LoadModel = false;如果~ LoadModel rng默认的抽搐;trainedModel = trainNetwork(imgsTrain,lgraph,options);trainingTime = toc;流(’总训练时间:%。2 e秒\ n”, trainingTime);保存(MatFile,“TrialParameter”“trainedModel”“trainingTime”“imgsValidation”);其他的disp (从文件中加载ML模型)负载(MatFile“trainedModel”“imgsValidation”);结束
初始化输入数据规范化。|======================================================================================================================| | 时代| |迭代时间| Mini-batch | |验证Mini-batch | |验证基地学习  | | | | ( hh: mm: ss) | | | | |损失损失精度精度  | |======================================================================================================================| | 1 | 1 | 00:00:03 | | 26.67% 25.00% | 4.1769 | 2.9883 | 1.0000 e-04 | | 2 | 10 | 00:00:18 |73.33% | 59.38% | 0.9875 | 1.1554 | 1.0000e-04 | | 3 | 20 | 00:00:35 | 60.00% | 56.25% | 0.9157 | 0.9178 | 1.0000e-04 | | 4 | 30 | 00:00:52 | 86.67% | 68.75% | 0.6708 | 0.7883 | 1.0000e-04 | | 5 | 40 | 00:01:10 | 66.67% | 68.75% | 0.9026 | 0.7482 | 1.0000e-04 | | 7 | 50 | 00:01:29 | 80.00% | 78.12% | 0.5429 | 0.6788 | 1.0000e-04 | | 8 | 60 | 00:01:48 | 100.00% | 81.25% | 0.4165 | 0.6130 | 1.0000e-04 | | 9 | 70 | 00:02:06 | 93.33% | 84.38% | 0.3590 | 0.5480 | 1.0000e-04 | | 10 | 80 | 00:02:24 | 73.33% | 84.38% | 0.5113 | 0.4783 | 1.0000e-04 | | 12 | 90 | 00:02:42 | 86.67% | 84.38% | 0.4211 | 0.4065 | 1.0000e-04 | | 13 | 100 | 00:03:00 | 93.33% | 90.62% | 0.1935 | 0.3486 | 1.0000e-04 | | 14 | 110 | 00:03:18 | 100.00% | 90.62% | 0.1488 | 0.3119 | 1.0000e-04 | | 15 | 120 | 00:03:36 | 100.00% | 93.75% | 0.0788 | 0.2774 | 1.0000e-04 | | 17 | 130 | 00:03:55 | 86.67% | 93.75% | 0.2489 | 0.2822 | 1.0000e-04 | | 18 | 140 | 00:04:13 | 100.00% | 93.75% | 0.0393 | 0.2283 | 1.0000e-04 | | 19 | 150 | 00:04:32 | 100.00% | 93.75% | 0.0522 | 0.2364 | 1.0000e-04 | | 20 | 160 | 00:04:50 | 100.00% | 93.75% | 0.0227 | 0.2034 | 1.0000e-04 | |======================================================================================================================| Training finished: Max epochs completed.
总训练时间:3.03e+02秒

只保存一个单独的训练网络.mat文件。这个文件将被CUDA可执行文件使用。

ModelFile = fullfile(ResultDir,sprintf(“SqueezeNet_Trial % d.mat”、试验));OutMatFile = fullfile(“ecg_model.mat”);数据=加载(ModelFile,“trainedModel”);net = data.trainedModel;保存(OutMatFile,“净”);

使用训练过的网络来预测验证集的类。

[YPred, probs] = classid (trainedModel,imgsValidation);accuracy = mean(YPred==imgsValidation.Labels)
准确度= 0.9375

用混淆图总结经过训练的网络在验证集上的性能。通过使用列和行摘要显示每个类的精度和召回率。保存该图形。混淆图底部的表格显示了精度值。混淆图右侧的表格显示召回值。

figure confusionMat = confusionMat (imgsValidation.Labels,YPred);confusionchart (imgsValidation。标签,YPred,...“标题”sprintf (验证上的混淆矩阵(总体准确度:%.4f)、准确性),...“ColumnSummary”“column-normalized”“RowSummary”“row-normalized”);

AccFigFile = fullfile(ResultDir,sprintf(“SqueezeNet_ValidationAccuracy_Trial % d.fig”、试验));saveas (gcf AccFigFile);

显示训练网络的大小。

信息= whoos (“trainedModel”);ModelMemSize = info.bytes/1024;流('训练的网络大小:%g kB\n'ModelMemSize)
训练网络大小:2991.89 kB

确定网络对图像进行分类所需的平均时间。

NumTestForPredTime = 20;TrialParameter。NumTestForPredTime = NumTestForPredTime;流(“测试预测时间(测试次数:%d)…”NumTestForPredTime)
测试预测时间(测试次数:20)…
imageSize = trainedModel.Layers(1).InputSize;= 0 (NumTestForPredTime,1);i = 1:NumTestForPredTime x = randn(imageSize);抽搐;[YPred, probs] = category (trainedModel,x,“ExecutionEnvironment”, ExecutionEnvironment);PredTime(i) = toc;结束AvgPredTimePerImage = mean(PredTime);流('平均预测时间(执行环境:%s): %。2e SEC \n'...ExecutionEnvironment AvgPredTimePerImage);
平均预测时间(执行环境:cpu): 1.67 -01秒

保存结果。

如果~ LoadModel保存(MatFile“准确性”“confusionMat”“PredTime”“ModelMemSize”...“AvgPredTimePerImage”“添加”结束

GPU代码生成-定义函数

信号的标量图是深度CNN的输入“图像”。创建一个函数,cwt_ecg_jetson_ex,它计算输入信号的标量图,并返回用户指定尺寸的图像。图像使用飞机(128)colormap。的% # codegen指令指示该函数用于代码生成。当使用coder.gpu.kernelfun中,代码生成尝试映射计算cwt_ecg_jetson_ex函数。

类型cwt_ecg_jetson_ex.m
function im = cwt_ecg_jetson_ex(timeseriesssignal, ImgSize) %#codegen %此函数仅用于支持小波深度学习示例。金宝app它可能会在未来的版本中被更改或删除。。coder.gpu.kernelfun ();%%创建cfs = cwt(timeseriesssignal, 'morse', 1, 'VoicesPerOctave', 12);CFS = abs(CFS);%%图像生成cmapj128 = code .load('cmapj128');Imx = ind2rgb_custom_ecg_jetson_ex(round(255*rescale(cfs))+1,cmapj128.cmapj128);%调整大小到适当的大小,并转换为uint8数据类型im = im2uint8(imresize(imx, ImgSize));结束

创建入口点函数,model_predict_ecg.m,用于生成代码。函数以心电信号作为输入并调用cwt_ecg_jetson_ex函数创建标量图的图像。的model_predict_ecg函数中包含的网络ecg_model.mat文件对心电信号进行分类。

类型model_predict_ecg.m
function PredClassProb = model_predict_ecg(timeseriesssignal) %#codegen %此函数仅用于支持小波深度学习示例。金宝app它可能会在未来的版本中被更改或删除。。coder.gpu.kernelfun ();% parameters ModFile = 'ecg_model.mat';ImgSize = [227 227];%完整性检查信号是一个正确长度的行向量assert(isequal(size(timeseriesssignal), [1 65536])) %% cwt转换为信号im = cwt_ecg_jetson_ex(timeseriesssignal, ImgSize);%%模型预测持久模型;如果为空(模型)模型=编码器。loadDeepLearningNetwork (ModFile mynet);end PredClassProb = predict(model, im); end

若要生成可部署到NVIDIA目标的CUDA可执行文件,请创建一个自定义主文件(main_ecg_jetson_ex.cu)和头文件(main_ecg_jetson_ex.h).您可以生成一个示例主文件,并将其用作重写新的主文件和头文件的模板。有关更多信息,请参见GenerateExampleMain的属性编码器。代码Config(MATLAB编码器).主文件调用为MATLAB入口点函数生成的代码。主文件首先从文本文件中读取心电信号,将数据传递给入口点函数,并将预测结果写入文本文件(predClassProb.txt).为了使GPU的计算效率最大化,可执行文件处理单精度数据。

类型main_ecg_jetson_ex.cu
// //文件:main_ecg_jetson_ex。cu // //此文件仅用于支持小波深度学习示例。金宝app//它可能会在将来的版本中被更改或删除。//*********************************************************************** // 包含文件# Include“rt_nonfinite.h”#包括“model_predict_ecg.h”#包括“main_ecg_jetson_ex.h”#包括“model_predict_ecg_terminate.h”#包括“model_predict_ecg_initialize.h”# Include < stdio . h > # Include < stdlib.h > # Include < time.h > / /函数定义/ *从文件读取数据* / int readData_real32_T (const char * const file_in, real32_T数据[65536]){文件* fp1 = fopen (file_in,“r”);if (fp1 == 0) {printf("ERROR:无法读取数据从%s\n", file_in);退出(0);} for(int i=0;我< 65536;I ++) {fscanf(fp1, "%f", &data[I]);}文件关闭(fp1); return 0; } /* Write data to a file*/ int writeData_real32_T(const char * const file_out, real32_T data[3]) { FILE* fp1 = fopen(file_out, "w"); if (fp1 == 0) { printf("ERROR: Unable to write data to %s\n", file_out); exit(0); } for(int i=0; i<3; i++) { fprintf(fp1, "%f\n", data[i]); } fclose(fp1); return 0; } // model predict function static void main_model_predict_ecg(const char * const file_in, const char * const file_out) { real32_T PredClassProb[3]; // real_T b[65536]; real32_T b[65536]; // readData_real_T(file_in, b); readData_real32_T(file_in, b); model_predict_ecg(b, PredClassProb); writeData_real32_T(file_out, PredClassProb); } // main function int32_T main(int32_T argc, const char * const argv[]) { const char * const file_out = "predClassProb.txt"; // Initialize the application. model_predict_ecg_initialize(); // Run prediction function main_model_predict_ecg(argv[1], file_out); // argv[1] = file_in // Terminate the application. model_predict_ecg_terminate(); return 0; }
类型main_ecg_jetson_ex.h
// //文件:main_ecg_jetson_ex.h // //仅支持小波深度学习样例。金宝app//它可能会在将来的版本中被更改或删除。// //*********************************************************************** # 如果未定义MAIN_H # define MAIN_H / /包含文件# Include < stddef.h > # Include < stdlib.h > # Include“rtwtypes.h”# Include " model_predict_ecg_types.h " / /函数声明走读生int32_T主要(int32_T argc, const char * const argv []);#endif // // main_ecg_jetson_ex.h // // [EOF] //

GPU代码生成-指定目标

若要创建可部署到目标设备的可执行文件,请设置CodeGenMode等于1。如果要创建本地运行并远程连接到目标设备的可执行文件,请设置CodeGenMode等于2。

主要函数从指定的文本文件中读取数据signalFile并将分类结果写入resultFile.集ExampleIndex选择一个有代表性的心电信号。您将使用此信号对可执行文件进行测试分类函数。Jetson_BuildDir指定在目标上执行远程生成过程的目录。如果指定的构建目录在目标上不存在,那么软件将用给定的名称创建一个目录。

CodeGenMode =1;signalFile =“signalData.txt”;resultFile =“predClassProb.txt”% consistent with "main_ecg_jetson_ex.cu"Jetson_BuildDir =“~ / projectECG”;ExampleIndex = 1;% 1,4: ARR型;2,5: CHF型;3,6: NSR型Function_to_Gen =“model_predict_ecg”;ModFile =“ecg_model.mat”%文件,保存神经网络模型;与"main_ecg_jetson_ex.cu"一致ImgSize = [227 227];ML模型的输入图像大小开关ExampleIndex情况下1% arr 7SampleSignalIdx = 7;情况下2%瑞士法郎97SampleSignalIdx = 97;情况下3.% NSR 132SampleSignalIdx = 132;情况下4% arr 31SampleSignalIdx = 31;情况下5%瑞士法郎101SampleSignalIdx = 101;情况下6% NSR 131SampleSignalIdx = 131;结束signal_data = single(ECGData.Data(SampleSignalIdx,:));ECGtype = ECGData.Labels{SampleSignalIdx};

GPU代码生成-连接到硬件

属性创建活动硬件连接对象,以与NVIDIA硬件通信杰森函数。创建硬件活连接对象时,需要知道目标板的主机名或IP地址、用户名和密码。

为Jetson硬件创建一个活动硬件连接对象。在下面的代码中,替换:

  • NameOfJetsonDeviceJetson设备的名称或IP地址

  • 用户名用你的用户名

  • 密码用你的密码

在创建对象期间,软件执行硬件和软件检查,IO服务器安装,并收集连接到目标的外设的信息。显示在命令窗口中。

Hwobj = jetson(“NameOfJetsonDevice”“用户名”“密码”);
检查目标上的CUDA可用性…正在检查目标系统路径中的“nvcc”…检查目标上的cuDNN库可用性…在目标上检查TensorRT库的可用性…检查前提库已经完成。收集硬件细节…检查目标上的第三方库可用性…完成硬件详细信息收集。单板名称:NVIDIA Jetson Nano CUDA版本:10.0 cuDNN版本:7.3 TensorRT版本:5.0 GStreamer版本:1.14.5 V4L2版本:1.14.2-1 SDL版本:1.2 OpenCV版本:3.3.1可用网络摄像头:可用gpu: NVIDIA Tegra X1可用数字引脚:7 11 12 13 15 16 18 19 21 22 23 24 26 31 32 33 35 36 37 38 40

使用coder.checkGpuInstall(GPU编码器)函数并验证在硬件上正确设置了运行此示例所需的编译器和库。

envCfg = code . gpuenvconfig (“杰森”);envCfg。DeepLibTarget =“cudnn”;envCfg。DeepCodegen = 1;envCfg。HardwareObject = hwobj;envCfg。安静= 1;coder.checkGpuInstall (envCfg)
ans =带字段的结构:Gpu: 1 cuda: 1 cudnn: 1 tensorrt: 0 basiccodegen: 0 basiccodeexec: 0 deepcodegen: 1 deepcodeexec: 0 tensorrtdatatype: 0 profiling: 0

GPU代码生成-编译

创建编译所需的GPU代码配置对象。使用coder.hardware函数为Jetson平台创建配置对象并将其分配给硬件代码配置对象的属性cfg.使用英伟达杰森的用于Jetson TX1或TX2电路板。自定义主文件是一个包装器,它在生成的代码中调用入口点函数。定制文件是部署的可执行文件所必需的。

使用编码器。DeepLearningConfig(GPU编码器)函数创建CuDNN深度学习配置对象,并将其分配给DeepLearningConfigGPU代码配置对象的属性。代码生成器利用NVIDIA®CUDA®深度神经网络库(cuDNN)用于NVIDIA gpu。cuDNN是一个用于深度神经网络的gpu加速原语库。

如果CodeGenMode == 1 cfg = code . gpuconfig (exe”);cfg。硬件= code . Hardware (英伟达杰森的);cfg.Hardware.BuildDir = Jetson_BuildDir;cfg。DeepLearningConfig =编码器。DeepLearningConfig (“cudnn”);cfg。CustomSource = fullfile(“main_ecg_jetson_ex.cu”);elseifCodeGenMode == 2 cfg = code . gpuconfig (“自由”);cfg。VerificationMode =“公益诉讼”;cfg。硬件= code . Hardware (英伟达杰森的);cfg.Hardware.BuildDir = Jetson_BuildDir;cfg。DeepLearningConfig =编码器。DeepLearningConfig (“cudnn”);结束

要生成CUDA代码,请使用codegen函数并传递GPU代码配置以及输入的大小和类型model_predict_ecg入口点函数。在主机上完成代码生成后,将复制生成的文件并在目标上构建。

codegen (“配置”cfg Function_to_Gen,“参数”{signal_data},“报告”);
代码生成成功:查看报告

GPU代码生成-执行

如果编译了要部署到目标的可执行文件,请将示例ECG信号写入文本文件。使用putFile ()硬件对象将文本文件放在目标上的函数。的workspaceDir属性的路径codegen目标上的文件夹。

如果CodeGenMode == 1 fid = fopen(signalFile,' w ');I = 1:length(signal_data) fprintf(fid)“% f \ n”signal_data(我));结束文件关闭(fid);hwobj.putFile (signalFile hwobj.workspaceDir);结束

运行可执行文件。

当运行部署的可执行文件时,如果之前的结果文件存在,请删除它。使用runApplication ()函数在目标硬件上启动可执行文件,然后getFile ()函数检索结果。因为结果可能不存在后立即runApplication ()函数调用返回,为了考虑通信延迟,将获取结果的最大时间设置为90秒。使用evalc函数抑制命令行输出。

如果CodeGenMode == 1%运行已部署可执行文件maxFetchTime = 90;resultFile_hw = fullfile(hwobj.workspaceDir,resultFile);如果ispc resultFile_hw = strrep(resultFile_hw,“\”' / ');结束Ta = tic;hwobj.deleteFile resultFile_hw evalc (“hwobj.runApplication (Function_to_Gen signalFile)”);Tf = tic;成功=错误;toc(tf) < maxFetchTime . txt试一试evalc (“hwobj.getFile (resultFile_hw)”);成功=真实;结束如果成功打破结束结束流('获取时间= %。3 e秒\ n”toc (tf));断言(成功,“无法获取预测”) PredClassProb = readmatrix(resultFile);PredTime = toc(ta);elseifCodeGenMode == 2%运行PIL可执行文件Ta = tic;eval (sprintf ('PredClassProb = %s_pil(signal_data);'Function_to_Gen));PredTime = toc(ta);eval (sprintf (“清楚% s_pil;”Function_to_Gen));%终止PIL执行结束
取时间= 1.658e+01秒

使用分类函数预测示例信号的类标签。

ModData = load(ModFile,“净”);im = cwt_ecg_jetson_ex(signal_data,ImgSize);[ModPred, ModPredProb] = category (ModData.net,im);PredCat =类别(ModPred)';

比较结果。

= array2table(PredClassProb(:)',“VariableNames”matlab.lang.makeValidName (PredCat));流('tPred = %。3.e sec\nExample ECG Type: %s\n'、PredTime ECGtype)
tPred = 2.044e+01 sec心电图类型:ARR
disp (PredTableJetson)
由瑞士法郎NSR  _______ ________ ________ 0.99858 0.001252 0.000166
array2table(ModPredProb(:)',“VariableNames”matlab.lang.makeValidName (PredCat));disp (PredTableMATLAB)
由瑞士法郎NSR  _______ _________ __________ 0.99858 0.0012516 0.00016613

关闭硬件连接。

清晰的hwobj

总结

这个例子展示了如何创建和部署一个CUDA可执行文件,该可执行文件使用CNN对ECG信号进行分类。您还可以选择创建本地运行并连接到远程目标的可执行文件。本例中给出了一个完整的工作流程。下载数据后,使用CWT从心电信号中提取特征。然后,对SqueezeNet进行重新训练,根据其标量图对信号进行分类。在目标NVIDIA设备上创建和编译两个用户定义函数。将可执行程序的结果与MATLAB进行了比较。

参考文献

  1. 拜姆,D. S.科鲁奇,E. S.蒙拉德,H. S.史密斯,R. F.赖特,A.拉努,D. F.戈蒂耶,B. J.兰西尔,W.格罗斯曼和E.布劳恩瓦尔德。"口服米力农治疗严重充血性心力衰竭患者的存活率"美国心脏病学会杂志.第7卷,第3期,1986,第661-670页。

  2. 戈德伯格A. L, L. A. N.阿马拉尔,L.格拉斯,J. M.豪斯多夫,P. Ch.伊万诺夫,R. G.马克,J. E.米耶图斯,G. B.穆迪,c . k。彭先生和斯坦利先生。“PhysioBank, PhysioToolkit,和PhysioNet:复杂生理信号新研究资源的组成部分。”循环。卷101,第23号:e215-e220。[流通电子页;http://circ.ahajournals.org/content/101/23/e215.full];二年(六月十三日)。cir.101.23.e215 doi: 10.1161/01.。

  3. 穆迪,g。B。和r。g。马克。“MIT-BIH心律失常数据库的影响。”IEEE医学与生物工程杂志.20卷。第三期,2001年5月至6月,第45-50页。(PMID: 11446209)

金宝app支持功能

helperCreateECGDirectories

函数helperCreateECGDirectories (ECGData parentFolder dataFolder)此函数仅用于支持小波深度学习示例。金宝app它可能会在未来的版本中被更改或删除。。rootFolder = parentFolder;localFolder = dataFolder;mkdir(fullfile(rootFolder,localFolder)) folderLabels = unique(ECGData.Labels);i = 1:numel(folderLabels) mkdir(fullfile(rootFolder,localFolder,char(folderLabels(i))));结束结束

helperPlotReps

函数helperPlotReps (ECGData)此函数仅用于支持小波深度学习示例。金宝app它可能会在未来的版本中被更改或删除。。folderLabels =唯一的(ECGData.Labels);k=1:3 ecgType = folderLabels{k};ind = find(ismember(ECGData.Labels,ecgType));次要情节(3 1 k)情节(ECGData.Data(印第安纳州(1)1:1000));网格标题(ecgType)结束结束

helperCreateRGBfromTF

函数helperCreateRGBfromTF (ECGData parentFolder childFolder)此函数仅用于支持小波深度学习示例。金宝app它可能会在未来的版本中被更改或删除。。imageRoot = fullfile(parentFolder,childFolder);data = ECGData.Data;labels = ECGData.Labels;[~,signalLength] = size(data);Fb = cwtfilterbank(“SignalLength”signalLength,“VoicesPerOctave”12);R = size(data,1);Ii = 1:r CFS = abs(fb.wt(data(Ii,:)));Im = ind2rgb(im2uint8(rescale(cfs)),jet(128));imgLoc = fullfile(imageRoot,char(labels(ii)));imFileName = strcat(char(labels(ii)),“_”num2str (ii),“jpg”);imwrite (imresize (im, 227年[227]),fullfile (imgLoc imFileName));结束结束

另请参阅

(小波工具箱)|(GPU编码器)|(小波工具箱)

相关的话题