主要内容

手势识别使用视频和深度学习

这个例子首先展示了如何使用pretrained执行手势识别SlowFast[1]视频分类器,然后展示了如何使用转移学习训练一个分类器自定义手势识别数据集。

概述

人类建立手势识别涉及到预测一个手势,如打招呼、手语手势,或鼓掌,使用一组视频帧。手势识别的吸引人的特点之一是,他们可以让人类与计算机和通信设备不需要外部输入设备如鼠标或远程控制。手势识别的视频有很多应用,如消费电子和机械的控制系统,机器人学习,和电脑游戏。例如,在线预测的多个操作来自多个摄像头的视频可以为机器人的学习是很重要的。图像分类相比,人类使用视频手势识别是挑战模式由于不准确的地面实况视频数据的数据集,演员的各种手势视频可以执行,大量类不平衡数据集,和大量的数据需要从头开始训练一个健壮的分类器。深度学习技术,如SlowFast卷积网络两种途径[1],表明改进的性能在较小的数据集使用转移学习与网络pretrained大型视频活动识别数据集。

注意:这个例子需要计算机视觉工具箱™模型SlowFast视频分类。你可以安装的计算机视觉工具箱模型SlowFast视频分类插件探险家。关于安装插件的更多信息,请参阅获取和管理插件

使用Pretrained视频执行手势识别分类器

下载pretrained SlowFast视频分类器以及一个视频文件,执行手势识别。下载zip文件的大小大约是245 MB。

downloadFolder = fullfile (tempdir,“姿态”);如果~ isfolder (downloadFolder) mkdir (downloadFolder);结束zipFile =“slowFastPretrained_fourClasses.zip”;如果~ isfile (fullfile (downloadFolder zipFile) disp (“下载pretrained网络…”);downloadURL =“https://ssd.mathworks.com/金宝appsupportfiles/vision/data/”+ zipFile;zipFile = fullfile (downloadFolder zipFile);websave (zipFile downloadURL);解压缩(zipFile downloadFolder);disp (“下载”。)结束
下载pretrained网络……
下载。

加载pretrained SlowFast视频分类器。

pretrainedDataFile = fullfile (downloadFolder,“slowFastPretrained_fourClasses.mat”);pretrained =负载(pretrainedDataFile);slowFastClassifier = pretrained.data.slowFast;

显示的类标签名pretrained视频分类器。

类= slowFastClassifier.Classes
类=4×1分类换掉wavingHello再鼓掌

读取和显示视频waving-hello.avi使用VideoReadervision.VideoPlayer

videoFilename = fullfile (downloadFolder,“waving-hello.avi”);videoReader = videoReader (videoFilename);放像机= vision.VideoPlayer;放像机。Name =“打招呼”;hasFrame (videoReader)帧= readFrame (videoReader);步骤(放像机、框架);结束释放(放像机);

选择10个随机选择的视频序列分类视频,均匀覆盖整个文件的查找操作类中主要的视频。

numSequences = 10;

分类使用的视频文件classifyVideoFile函数。

[gestureLabel,分数]= classifyVideoFile (slowFastClassifier、videoFilename NumSequences = NumSequences)
gestureLabel =分类wavingHello
分数=0.4753

分类也可以应用于流媒体视频。学习如何分类流摄像头视频,明白了流媒体网络摄像头视频使用SlowFast视频分类器进行分类

火车视频手势识别的分类器

本节的例子显示了上面所示的视频分类器训练使用转移学习。设置doTraining变量来使用pretrained视频分类器,而不必等待培训完成。另外,如果你想训练视频分类器,设置doTraining变量来真正的

doTraining = false;

地面实况训练数据下载

这个例子列车SlowFast视频分类网络使用下载的姿态数据集,其中包含四个手势:“鼓掌”、“wavingHello”、“换掉”,“再”。标签使用的数据集包含视频视频贴标签机和相应的地面实况数据。

创建目录来存储训练数据的“真正的事实”。

groundTruthFolder = fullfile (downloadFolder,“groundTruthFolder”);如果~ isfolder (groundTruthFolder) mkdir (groundTruthFolder);结束

下载的数据集和提取的zip归档downloadFolder

zipFile =“videoClipsAndSceneLabels.zip”;如果~ isfile (fullfile (groundTruthFolder zipFile) disp (“地面实况训练数据的下载…”);downloadURL =“https://ssd.mathworks.com/金宝appsupportfiles/vision/data/”+ zipFile;zipFile = fullfile (groundTruthFolder zipFile);websave (zipFile downloadURL);解压缩(zipFile groundTruthFolder);结束

提取训练视频序列

培训视频分类器,你需要一组视频和其相应的场景标签的集合。使用helper函数extractVideoScenes,定义在这个例子中,从地面实况数据中提取标记视频场景并将他们写到磁盘上作为单独的视频文件。了解更多关于从视频中提取训练数据,看看提取视频分类训练数据

groundTruthFolder = fullfile (downloadFolder,“groundTruthFolder”);trainingFolder = fullfile (downloadFolder,“videoScenes”);extractVideoScenes (groundTruthFolder trainingFolder类);

共有40个视频场景从下载中提取地面实况数据。

加载数据集

这个示例使用一个数据存储读取视频场景和标签从地面实况中提取数据。

指定数据存储视频帧的数量应该配置为输出每次从数据库读取数据。

numFrames = 16;

这里使用值为16平衡内存使用和分类。共同的价值观考虑8、16、32、64或128。使用更多的框架有助于捕捉额外的时间信息,但需要更多的内存。实证分析需要确定最优的帧数。

接下来,指定高度和宽度的帧数据存储应该配置为输出。数据存储指定大小自动调整原始视频帧,启用批处理多个视频序列。

frameSize = [112112];

值(112 112)是用来捕捉视频场景帮助长时间关系分类的手势与长时间的持续时间。常见的值大小(112 112),(224 224),或(256 256)。小尺寸使更多的视频帧的使用内存使用的成本,处理时间和空间分辨率。与帧的数量,需要实证分析以确定最优值。

指定的通道数量3,RGB视频。

numChannels = 3;

使用helper函数,createFileDatastore配置一个FileDatastore加载数据。helper函数列的这个例子。

isDataForTraining = true;dsTrain = createFileDatastore (trainingFolder numFrames numChannels,类,isDataForTraining);

配置SlowFast视频转移学习分类器

创建一个SlowFast视频分类器转移学习使用slowFastVideoClassifier函数。的slowFastVideoClassifier函数创建一个SlowFast视频分类器对象pretrained动力学- 400数据集(2]。

指定ResNet-50作为基础网络卷积神经网络三维架构SlowFast分类器。

baseNetwork =“resnet50-3d”;

指定的输入大小SlowFast视频分类器。

inputSize = [frameSize、numChannels numFrames];

创建一个SlowFast视频手势数据集分类器通过指定类和网络输入的大小。

slowFast = slowFastVideoClassifier (baseNetwork字符串(类),InputSize = InputSize);

指定一个视频分类器模型的名字。

slowFast。ModelName =“使用深度学习手势识别器”;

增加和训练数据进行预处理

数据增强提供了一种方法使用有限的训练数据集。增加对视频数据必须相同的集合框架基于网络输入的大小。微小的变化,如翻译、裁剪或改变一个图像,提供新的,不同的,独特的图像,您可以用它来训练一个健壮的视频分类器。数据存储是一个便捷的途径,阅读和增强数据的集合。增加培训视频数据通过使用augmentVideo金宝app支持函数,定义在这个例子。

dsTrain =变换(dsTrain @augmentVideo);

预处理的培训视频数据调整到SlowFast视频分类器输入大小,通过使用preprocessVideoClips定义在这个例子。指定InputNormalizationStatistics的视频预处理函数分类器和输入大小作为一个结构体字段值,preprocessInfo。的InputNormalizationStatistics属性用于重新调节0和1之间的视频帧,然后正常使用平均值和标准偏差的新数据。输入用于调整视频帧大小使用imresize基于SizingOption的价值信息结构体。或者,您可以使用“randomcrop”“centercrop”的值SizingOption随机的作物或中心作物的输入数据输入大小视频分类器。

preprocessInfo。统计= slowFast.InputNormalizationStatistics;preprocessInfo。InputSize=我nputSize; preprocessInfo.SizingOption =“调整”;dsTrain =变换(dsTrain @(数据)preprocessVideoClips(数据、preprocessInfo));

定义模型梯度函数

modelGradients函数,列出在这个例子中,将作为输入SlowFast视频分类器slowFastmini-batch的输入数据dlRGB和地面真理mini-batch标签数据海底。函数返回训练价值损失,损失的梯度对可学的分类器的参数,和mini-batch分类器的精度。

损失计算通过计算熵损失预测的视频分类器。网络的输出预测概率在0和1之间的每个类。

p r e d c t o n 年代 = f o r w 一个 r d ( 年代 l o w F 一个 年代 t , d l R G B ) ;

l o 年代 年代 = c r o 年代 年代 e n t r o p y ( p r e d c t o n 年代 )

分类器计算的准确性通过比较分类器预测地面实况标签的输入,海底

指定培训选项

火车mini-batch大小为5 600次迭代。指定保存模型的迭代之后最好的利用mini-batch损失SaveBestAfterIteration参数。

指定cosine-annealing学习速率的时间表(3)参数:

  • 至少学习1的军医。

  • 1 e - 3的最大学习速率。

  • 余弦函数的迭代次数为200、300和400年,之后重启学习速率调度周期。的选项CosineNumIterations定义每一个余弦函数周期的宽度。

为个指定的参数优化。初始化个优化参数初的培训:

  • 0.9的动力。

  • 一个初始速度参数初始化[]

  • 0.0005的L2正则化因子。

指定数据在后台使用派遣一个平行的池。如果DispatchInBackground被设置为true,打开一个平行池并行的指定数量的工人,并创建一个DispatchInBackgroundDatastore提供这个例子中,将在后台数据加速训练使用异步数据加载和预处理。默认情况下,这个示例使用GPU如果一个是可用的。否则,它使用一个CPU。使用GPU需要并行计算工具箱™和CUDA NVIDIA GPU®®启用。关于支持计算能力的信息,看到金宝appGPU计算的需求(并行计算工具箱)

参数个数。类=类;参数个数。MiniBatchSize = 5;参数个数。NumIterations = 600;参数个数。CosineNumIterations = (100 200 300);参数个数。SaveBestAfterIteration = 400; params.MinLearningRate = 1e-4; params.MaxLearningRate = 1e-3; params.Momentum = 0.9; params.Velocity = []; params.L2Regularization = 0.0005; params.ProgressPlot = false; params.Verbose = true; params.DispatchInBackground = true; params.NumWorkers = 12;

火车视频分类器

火车SlowFast视频分类器使用的视频数据。

对于每个时代:

  • 洗牌的数据在循环mini-batches之前的数据。

  • 使用minibatchqueue在mini-batches循环。支持函数金宝appcreateMiniBatchQueue列出在本例中,使用给定的训练数据存储创建一个minibatchqueue

  • 显示每个时代的损失和准确性结果使用支持功能金宝appdisplayVerboseOutputEveryEpoch年底上市,这个例子。

为每个mini-batch:

  • 将视频数据和标签dlarray对象与底层类型单一。

  • 使加工的时间维度使用SlowFast视频分类器指定的视频数据时间序列维度,“T”。指定尺寸的标签“SSCTB”(空间、空间、通道、时间、批)视频数据,和“CB”标签的数据。

minibatchqueue使用支持函数对象金宝appbatchVideo列出在本例中,批RGB视频数据。

参数个数。ModelFilename =“slowFastPretrained_fourClasses.mat”;如果doTraining时代= 1;bestLoss =最大浮点数;accTrain = [];lossTrain = [];迭代= 1;开始=抽搐;火车离站时刻表=开始;打乱= shuffleTrainDs (dsTrain);%的输出是两个:一个用于RGB框架,和一个地面真理标签。numOutputs = 2;兆贝可= createMiniBatchQueue(重组、numOutputs params);%使用initializeTrainingProgressPlot和initializeVerboseOutput%支金宝app持功能,列出的例子,来初始化%的培训发展情节和详细输出显示培训%,训练精度,验证精度。策划者= initializeTrainingProgressPlot (params);initializeVerboseOutput (params);迭代< = params.NumIterations%遍历的数据集。[dlX1,海底]=下一个(兆贝可);%计算模型使用dlfeval梯度和损失。(渐变、失去、acc) =dlfeval (@modelGradients, slowFast dlX1,海底);%累积损失和精度。lossTrain = (lossTrain、损失);accTrain = (accTrain, acc);%更新网络状态。slowFast。=状态;%更新梯度和视频分类器的参数%使用个优化器。[slowFast,参数个数。速度,learnRate] =updateLearnables (slowFast、渐变参数、params.Velocity迭代);如果~ hasdata(兆贝可)| | = = params.NumIterations迭代%完成当前的时代。做验证和更新进展。火车离站时刻表= toc(火车离站时刻表);accTrain =意味着(accTrain);lossTrain =意味着(lossTrain);%更新培训的进展。displayVerboseOutputEveryEpoch(参数、启动、learnRate时代,迭代,accTrain lossTrain,火车离站时刻表);updateProgressPlot (params,策划者,时代,迭代,开始,lossTrain, accTrain);%保存训练视频分类器参数,这给了%到目前为止最好的训练损失。使用saveData支持函数,金宝app%的结尾部分,本文罗列了这个例子。bestLoss = saveData (slowFast bestLoss,迭代,lossTrain params);结束如果~ hasdata(兆贝可)& & < params.NumIterations迭代%完成当前的时代。初始化培训损失,准确性%值,minibatchqueue为下一个时代。accTrain = [];lossTrain = [];时代=时代+ 1;火车离站时刻表=抽搐;打乱= shuffleTrainDs (dsTrain);兆贝可= createMiniBatchQueue(重组、numOutputs params);结束迭代=迭代+ 1;结束%完成训练时显示一条消息。endVerboseOutput (params);disp (”模型保存到:“+ params.ModelFilename);结束

评估分类器训练视频

评估的准确性训练SlowFast视频分类器,设置isDataForTraining假,并创建一个变量fileDatastore。注意,数据增强不应用于评价数据。理想情况下,测试和评估的数据应该代表原始数据和修改的公正的评价。

isDataForTraining = false;dsEval = createFileDatastore (trainingFolder numFrames numChannels,类,isDataForTraining);dsEval =变换(dsEval @(数据)preprocessVideoClips(数据、preprocessInfo));

负载的最佳模型保存在训练或使用pretrained模型。

如果doTraining transferLearned =负载(params.ModelFilename);slowFastClassifier = transferLearned.data.slowFast;结束

创建一个minibatchqueue对象加载批次的测试数据。

numOutputs = 2;兆贝可= createMiniBatchQueue (dsEval、numOutputs params);

每一批的评估数据,使用SlowFast视频分类器作出预测,使用混淆矩阵计算出预测精度。

numClasses =元素个数(params.Classes);cmat =稀疏(numClasses numClasses);hasdata(兆贝可)[dlVideo,海底]=(兆贝可);%的计算机预测SlowFast训练%视频分类器。dlYPred =预测(slowFastClassifier dlVideo);dlYPred = squeezeIfNeeded (dlYPred、海底);通过使用最大%总混淆矩阵%值预测分数和地面真理的标签。[~,欧美]= max(海底,[],1);[~,YPred] = max (dlYPred [], 1);欧美,cmat = aggregateConfusionMetric (cmat YPred);结束

计算平均剪辑SlowFast视频训练分类器的分类精度。

evalClipAccuracy =总和(诊断接头(cmat)。/笔(cmat,“所有”)
evalClipAccuracy = 0.9847

显示混合矩阵。

图图= confusionchart (cmat、类);

SlowFast视频分类器上pretrained动力学- 400数据集(2),为人类提供强劲表现在转移学习手势识别。以上培训运行24 gb Titan-X GPU约60分钟。当从头训练小手势识别视频数据集,训练时间和收敛需要更长的时间比pretrained视频分类器。反式学习使用动力学- 400 pretrained SlowFast视频分类器时也避免过度拟合分类器跑了更多的时代如此小的手势识别视频数据集。了解更多关于视频识别使用深度学习,明白了开始使用视频分类使用深度学习

金宝app支持功能

createFileDatastore

createFileDatastore函数创建一个FileDatastore对象使用给定的文件夹名称。的FileDatastore对象读取数据“partialfile”模式,所以每读可以返回部分读从视频帧。该功能有助于在阅读了大量的视频文件,如果所有的帧不适合在内存中。

函数数据存储= createFileDatastore (trainingFolder numFrames numChannels,类,isDataForTraining) readFcn = @ (f, u) readVideo (f, u, numFrames numChannels,类,isDataForTraining);数据存储= fileDatastore (trainingFolder,“IncludeSubfolders”,真的,“FileExtensions”,“.avi”,“ReadFcn”readFcn,“ReadMode”,“partialfile”);结束

shuffleTrainDs

shuffleTrainDs函数打乱文件出现在训练数据存储,dsTrain

函数打乱= shuffleTrainDs (dsTrain)打乱= (dsTrain)复印件;改变= isa(打乱,“matlab.io.datastore.TransformedDatastore”);如果转换文件= shuffled.UnderlyingDatastores {1} .Files;其他的文件= shuffled.Files;结束n =元素个数(文件);shuffledIndices = randperm (n);如果改变shuffled.UnderlyingDatastores {1}。文件=文件(shuffledIndices);其他的重新洗了一遍。F我le年代=f我le年代(年代huffledIndices);结束重置(重组);结束

readVideo

readVideo函数读取视频帧,和相应的标签值对于一个给定的视频文件。在培训过程中,读函数读取特定数量的帧按照网络输入大小,随机选择起始帧。在测试期间,所有的框架都按顺序阅读。所需的视频帧大小到分类器网络输入大小训练、测试和验证。

函数(数据、用户数据做)= readVideo(文件名,用户数据、numFrames numChannels,类,isDataForTraining)如果isempty(用户数据)用户数据。re一个der=VideoReader(f我len一个me); userdata.batchesRead = 0; userdata.label = getLabel(filename,classes); totalFrames = floor(userdata.reader.Duration * userdata.reader.FrameRate); totalFrames = min(totalFrames, userdata.reader.NumFrames); userdata.totalFrames = totalFrames; userdata.datatype = class(read(userdata.reader,1));结束读者= userdata.reader;totalFrames = userdata.totalFrames;标签= userdata.label;batchesRead = userdata.batchesRead;如果isDataForTraining视频= readForTraining(读者,numFrames totalFrames);其他的视频= readForEvaluation(读者,userdata.datatype、numChannels numFrames, totalFrames);结束数据={视频标签};batchesRead = batchesRead + 1;用户数据。batchesRead = batchesRead;如果numFrames > totalFrames numBatches = 1;其他的numBatches =地板(totalFrames / numFrames);结束%完成标志设置为true,如果读者读过所有的帧或%如果是培训。做= batchesRead = = numBatches | | isDataForTraining;结束

readForTraining

readForTraining函数读取视频帧分类器训练视频。函数读取特定的帧数按照网络输入大小,随机选择起始帧。如果没有足够的帧,视频序列重复垫所需数量的帧。

函数视频= readForTraining(读者,numFrames totalFrames)如果numFrames > = totalFrames startIdx = 1;endIdx = totalFrames;其他的startIdx = randperm (totalFrames - numFrames + 1);startIdx = startIdx (1);endIdx = startIdx + numFrames - 1;结束视频=阅读(读者,[startIdx endIdx]);如果numFrames > totalFrames%添加更多的帧来填补在网络输入的大小。附加=装天花板(numFrames / totalFrames);视频= repmat(视频,1,1,1,额外的);视频=视频(:,:,:1:numFrames);结束结束

readForEvaluation

readForEvaluation函数读取视频帧来评估分类器训练视频。函数读取特定的帧数顺序按照网络输入的大小。如果没有足够的帧,视频序列重复垫所需数量的帧。

函数视频= readForEvaluation(读者,数据类型,numChannels numFrames, totalFrames) H = reader.Height;W = reader.Width;探路者= min ([numFrames totalFrames]);视频= 0 (H, W, numChannels,探路者,数据类型);frameIndex = 0;hasFrame(读者)& & frameIndex < numFrames帧= readFrame(读者);frameIndex = frameIndex + 1;视频(:,:,:,frameIndex) =框架;结束如果frameIndex < numFrames视频=视频(:,:,:,1:frameIndex);附加=装天花板(numFrames / frameIndex);视频= repmat(视频,1,1,1,额外的);视频=视频(:,:,:1:numFrames);结束结束

getLabel

getLabel函数获取标签名称的完整路径文件名。的标签文件的文件夹的存在。例如,对于一个文件路径等“/道路/ /数据集/鼓掌/ video_0001.avi”,标签的名字“鼓掌”

函数标签= getLabel(文件名、类)文件夹= fileparts (string(文件名));[~,标签]= fileparts(文件夹);标签=分类(字符串(标签),字符串(类));结束

augmentVideo

augmentVideo功能增强培训的视频帧视频分类器。函数增加一个视频序列相同的扩增技术提供的augmentTransform函数。

函数data = augmentVideo(数据)numClips =大小(数据,1);2 = 1:numClips视频= {ii, 1}数据;% HxWxC深圳=大小(视频中,[1,2,3]);%每夹一个增强fcnaugmentFcn = augmentTransform(深圳);{二世,1}= augmentFcn数据(视频);结束结束

augmentTransform

augmentTransform函数创建一个扩展方法与随机左右翻转和扩展的因素。

函数augmentFcn = augmentTransform(深圳)%随机图像翻转和规模。tform = randomAffine2d (“XReflection”,真的,“规模”1.1 [1]);tform溃败= affineOutputView(深圳,“BoundsStyle”,“CenterOutput”);augmentFcn = @(数据)augmentData(数据、tform溃败);函数data = augmentData(数据、tform溃败)数据= imwarp(数据、tform“OutputView”,溃败);结束结束

preprocessVideoClips

preprocessVideoClips函数进行预处理的培训视频数据调整到SlowFast视频分类器输入的大小。需要的InputNormalizationStatisticsInputSize视频的属性分类器结构,信息。的InputNormalizationStatistics属性用于重新调节0和1之间的视频帧,然后正常使用平均值和标准偏差的新数据。输入用于调整视频帧大小使用imresize基于SizingOption的价值信息结构体。或者,您可以使用“randomcrop”“centercrop”的值SizingOption随机的作物或中心作物的输入数据输入大小视频分类器。

函数data = preprocessVideoClips(数据、信息)inputSize = info.InputSize (1:2);sizingOption = info.SizingOption;开关sizingOption情况下“调整”sizingFcn = @ (x) imresize (x, inputSize);情况下“randomcrop”sizingFcn = @ (x) cropVideo (x, @randomCropWindow2d inputSize);情况下“centercrop”sizingFcn = @ (x) cropVideo (x, @centerCropWindow2d inputSize);结束numClips =大小(数据,1);minValue = info.Statistics.Min;maxValue = info.Statistics.Max;meanValue = info.Statistics.Mean;stdValue = info.Statistics.StandardDeviation;minValue =重塑(minValue, 1, 1, 3);maxValue =重塑(maxValue, 1, 1, 3);meanValue =重塑(meanValue, 1, 1, 3);stdValue =重塑(stdValue, 1, 1, 3);2 = 1:numClips视频= {ii, 1}数据;大小= sizingFcn(视频);%将单一的输入。大小=单(大小);%重新调节输入0和1之间。大小=重新调节(大小,0,1,InputMin = minValue InputMax = maxValue);%规范化使用平均值和标准偏差。大小=大小- meanValue;大小= resized. / stdValue;数据{ii, 1} =调整;结束函数outData = cropVideo(数据、cropFcn inputSize) imsz =大小(数据,[1,2]);cropWindow = cropFcn (imsz inputSize);numBatches =大小(数据,4);深圳= [inputSize、大小(数据,3),numBatches);outData = 0(深圳,“喜欢”、数据);b = 1: numBatches outData (:,:,:, b) = imcrop(数据(:,:,:,b), cropWindow);结束结束结束

createMiniBatchQueue

createMiniBatchQueue函数创建一个minibatchqueue对象,该对象提供miniBatchSize从给定的数据存储的数据量。它还创建了一个DispatchInBackgroundDatastore如果一个平行池是开放的。

函数兆贝可= createMiniBatchQueue(数据存储、numOutputs params)如果参数个数。DispatchInBackground & & isempty (gcp (“nocreate”))%开始平行池,如果DispatchInBackground是真的,调度%在后台数据使用并行池。c = parcluster (“本地”);c。NumWorkers = params.NumWorkers;parpool (“本地”,params.NumWorkers);结束gcp (p =“nocreate”);如果~ isempty (p)数据存储= DispatchInBackgroundDatastore(数据存储,p.NumWorkers);结束inputFormat (1: numOutputs-1) =“SSCTB”;outputFormat =“CB”;numOutputs兆贝可= minibatchqueue(数据存储,“MiniBatchSize”params.MiniBatchSize,“MiniBatchFcn”@batchVideo,“MiniBatchFormat”inputFormat, outputFormat]);结束

batchVideo

batchVideo函数批量视频,从细胞和标签数据数组。它使用onehotencode函数地面实况分类标签编码到一个炎热的数组。在一个炎热的编码包含一个数组1在相对应的位置的类标签,和0在其他位置。

函数(视频、标签)= batchVideo(视频、标签)%批尺寸:5视频=猫(5、视频{:});%批尺寸:2标签=猫({}):2、标签;%功能维度:1= onehotencode标签(标签,1);结束

modelGradients

modelGradients函数作为输入mini-batch RGB数据dlRGB,和相应的目标海底,并返回相应的损失,损失的梯度对可学的参数,和训练精度。计算梯度,评估modelGradients函数使用dlfeval功能训练循环。

函数[gradientsRGB损失,acc, stateRGB] = modelGradients (slowFast dlRGB,海底)[dlYPredRGB stateRGB] =前进(slowFast dlRGB);dlYPred = squeezeIfNeeded (dlYPredRGB、海底);损失= crossentropy (dlYPred、海底);gradientsRGB = dlgradient(损失、slowFast.Learnables);%计算预测的准确性。[~,欧美]= max(海底,[],1);[~,YPred] = max (dlYPred [], 1);acc =收集(extractdata (sum(欧美= = YPred)。/元素个数(欧美)));结束

squeezeIfNeeded

squeezeIfNeeded函数的预测分数,dlYPred和相应的目标Y,并返回预测分数dlYPred挤压单维度后,如果有任何。

函数dlYPred = squeezeIfNeeded (dlYPred, Y)如果~ isequal(大小(Y),大小(dlYPred)) dlYPred =挤压(dlYPred);dlYPred = dlarray (dlYPred退去(Y));结束结束

updateLearnables

updateLearnables功能更新的可学的参数SlowFast视频分类器与梯度和其他参数使用个优化功能sgdmupdate

函数[slowFast、速度,learnRate] = updateLearnables (slowFast、渐变参数、速度迭代)%确定学习速率使用cosine-annealing学习速率的时间表。learnRate = cosineAnnealingLearnRate(迭代、params);%对权重应用L2正规化。可学的= slowFast.Learnables;idx =可学的。参数= =“重量”;梯度(idx:) = dlupdate (@ (g, w) g + params.L2Regularization * w梯度(idx:),可学的(idx:));%更新使用个优化网络参数。[slowFast,速度]= sgdmupdate (slowFast、渐变速度,learnRate params.Momentum);结束

cosineAnnealingLearnRate

cosineAnnealingLearnRate函数计算基于当前迭代数,学习速率最低学习速率、最大学习速率,对退火的迭代次数3]。

函数lr = cosineAnnealingLearnRate(迭代参数)如果迭代= =参数。NumIterations lr = params.MinLearningRate;返回;结束cosineNumIter = [0, params.CosineNumIterations];csum = cumsum (cosineNumIter);块=找到(迭代csum > = 1“第一”);cosineIter =迭代- csum (block - 1);annealingIteration =国防部(cosineIter cosineNumIter(块));cosineIteration = cosineNumIter(块);minR = params.MinLearningRate;maxR = params.MaxLearningRate;cosMult = 1 + cos(π* annealingIteration / cosineIteration);lr = minR + ((maxR - minR) * cosMult / 2);结束

aggregateConfusionMetric

aggregateConfusionMetric功能逐步填补了混淆矩阵的基础上,预测结果YPred和预期结果欧美

函数欧美,cmat = aggregateConfusionMetric (cmat YPred)欧美=收集(extractdata(欧美));YPred =收集(extractdata (YPred));[m, n] =大小(cmat);cmat = cmat +满(稀疏(欧美YPred 1, m, n));结束

saveData

saveData函数保存给定SlowFast视频分类器,MAT-file损失和其他训练参数。

函数bestLoss = saveData (slowFast bestLoss,迭代,lossTrain params)如果迭代> =参数。SaveBestAfterIteration trainingLoss = extractdata(收集(lossTrain));如果trainingLoss < bestLoss bestLoss = trainingLoss;slowFast = gatherFromGPUToSave (slowFast);数据。Be年代tLoss = bestLoss; data.slowFast = slowFast; data.Params = params; save(params.ModelFilename,“数据”);结束结束结束

gatherFromGPUToSave

gatherFromGPUToSave函数从GPU为了收集数据模型保存到磁盘。

函数slowfast = gatherFromGPUToSave (slowfast)如果~ canUseGPU返回;结束slowfast。可学的= gatherValues (slowfast.Learnables);slowfast。状态= gatherValues (slowfast.State);函数台= gatherValues(台)2 = 1:高度(台)台。{二}=收集价值(tbl.Value {2});结束结束结束

extractVideoScenes

extractVideoScenes函数从集合中提取培训视频数据的视频和其相应的场景标签的集合,通过使用功能sceneTimeRangeswriteVideoScenes

函数extractVideoScenes (groundTruthFolder、trainingFolder类)%如果视频场景已经提取,不需要下载%的数据集和提取视频场景。如果isfolder (trainingFolder) classFolders = fullfile (trainingFolder字符串(类));allClassFoldersFound = true;2 = 1:元素个数(classFolders)如果~ isfolder (classFolders (ii) allClassFoldersFound = false;打破;结束结束如果allClassFoldersFound返回;结束结束如果~ isfolder (groundTruthFolder) mkdir (groundTruthFolder);结束downloadURL =“https://ssd.mathworks.com/金宝appsupportfiles/vision/data/videoClipsAndSceneLabels.zip”;文件名= fullfile (groundTruthFolder,“videoClipsAndSceneLabels.zip”);如果~存在(文件名,“文件”)disp (“下载视频剪辑和相应的标签”+ groundTruthFolder);websave(文件名,downloadURL);结束%解压缩下载文件夹的内容。解压缩(文件名,groundTruthFolder);labelDataFiles = dir (fullfile (groundTruthFolder“* _labelData.mat”));labelDataFiles = fullfile (groundTruthFolder, {labelDataFiles.name}”);numGtruth =元素个数(labelDataFiles);%加载标签数据信息和创建地面实况对象。gTruth = groundTruth.empty (numGtruth 0);2 = 1:numGtruth ld =加载(labelDataFiles {2});videoFilename = fullfile (groundTruthFolder ld.videoFilename);gds = groundTruthDataSource (videoFilename);gTruth (ii) = groundTruth (gds, ld.labelDefs ld.labelData);结束%收集所有现场时间范围和相应的标签%使用sceneTimeRanges函数。[timeRanges, sceneLabels] = sceneTimeRanges (gTruth);%每个时间的子文件夹名称指定为现场标签的名字。foldernames = sceneLabels;%删除文件夹如果它已经存在。如果isfolder (trainingFolder)删除文件夹(trainingFolder,“年代”);结束%的视频文件被写入到指定的文件夹folderNames输入。writeVideoScenes (gTruth timeRanges、trainingFolder foldernames);结束

initializeTrainingProgressPlot

initializeTrainingProgressPlot功能配置两个情节显示培训损失,和训练精度。

函数策划者= initializeTrainingProgressPlot (params)如果params.ProgressPlot%画出损失,训练精度,验证精度。%损失情节次要情节(2,1,1)策划者。LossPlotter = animatedline;包含(“迭代”)ylabel (“损失”)%精度图次要情节(2,1,2)策划者。TrainAccPlotter = animatedline (“颜色”,“b”);传奇(“训练的准确性”,“位置”,“西北”);包含(“迭代”)ylabel (“准确性”)其他的策划者= [];结束结束

updateProgressPlot

updateProgressPlot功能更新进展情节与损失和在训练精度信息。

函数updateProgressPlot (params,策划者,时代,迭代,开始,lossTrain, accuracyTrain)如果params.ProgressPlot%更新培训的进展。D =持续时间(0,0,toc(开始),“格式”,“hh: mm: ss”);标题(plotters.LossPlotter.Parent,”时代:“+时代+”,过去:“+字符串(D));addpoints (plotters.LossPlotter、迭代、双(收集(extractdata (lossTrain))));addpoints (plotters.TrainAccPlotter迭代,accuracyTrain);drawnow结束结束

initializeVerboseOutput

initializeVerboseOutput函数显示表的列标题的训练价值,这显示了时代,mini-batch准确性,和其他训练价值。

函数initializeVerboseOutput (params)如果参数个数。详细disp (”“)如果canUseGPU disp (“训练在GPU上。”)其他的disp (“训练在CPU上。”)结束gcp (p =“nocreate”);如果~ isempty (p) disp (并行集群上的“培训”+ p.Cluster。概要文件+“”。”)结束disp (”NumIterations:“+字符串(params.NumIterations));disp (”MiniBatchSize:“+字符串(params.MiniBatchSize));disp (“类:”+加入(字符串(params.Classes),”、“));disp (“| = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |”)disp (| | |时代迭代时间| Mini-Batch | Mini-Batch学习| |基地训练时间|”)disp (“| | | (hh: mm: ss) | | | |率损失精度(hh: mm: ss) |”)disp (“| = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |”)结束结束

displayVerboseOutputEveryEpoch

displayVerboseOutputEveryEpoch函数显示培训的详细输出值,如时代、mini-batch准确性,mini-batch损失。

函数displayVerboseOutputEveryEpoch(参数、启动、learnRate时代,迭代,火车离站时刻表accTrain, lossTrain)如果参数个数。冗长的D =持续时间(0,0,toc(开始),“格式”,“hh: mm: ss”);火车离站时刻表=持续时间(0,0,火车离站时刻表,“格式”,“hh: mm: ss”);lossTrain =收集(extractdata (lossTrain));lossTrain =组成(“% .4f”,lossTrain);accTrain = composePadAccuracy (accTrain);learnRate =组成(“% .13f”,learnRate);disp (“|”+垫(string(时代),5,“两个”)+“|”+垫(字符串(迭代)9“两个”)+“|”+垫(string (D) 12“两个”)+“|”+垫(string (accTrain) 10“两个”)+“|”+垫(string (lossTrain) 10“两个”)+“|”+垫(string (learnRate), 13日“两个”)+“|”+垫(string(火车离站时刻表)10“两个”)+“|”)结束函数acc = composePadAccuracy (acc) acc =组成(“% .2f”,100年acc *) +“%”;acc =垫(字符串(acc) 6“左”);结束结束

endVerboseOutput

endVerboseOutput函数显示详细输出在训练结束。

函数endVerboseOutput (params)如果参数个数。详细disp (“| = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |”)结束结束

引用

[1]Christoph Feichtenhofer浩气粉丝,Jitendra Malik,他和开明。“SlowFast网络视频识别。”《IEEE计算机视觉与模式识别会议(CVPR), 2019年。

[2]将凯,若昂Carreira Karen Simonyan布莱恩,克洛伊希利尔,Sudheendra Vijayanarasimhan,法比奥Viola,蒂姆•格林特,保罗Natsev,安德鲁Zisserman Mustafa苏莱曼。“人类行为动力学的视频数据集。”arXiv预印本arXiv: 1705.06950,2017年。

[3]Loshchilov, Ilya和弗兰克Hutter。“SGDR:随机梯度下降法与温暖重启。”2017年国际Conferencee学习表示。法国土伦:ICLR, 2017。