分类使用深度学习视频
这个例子展示了如何创建一个网络视频分类结合pretrained图像分类模型和一个LSTM网络。
创建一个深度学习网络视频分类:
转换视频序列的特征向量使用pretrained卷积神经网络,如GoogLeNet,从每一帧中提取特征。
火车一个LSTM网络在视频序列来预测标签。
组装一个网络,直接将视频通过结合网络层。
下图说明了网络体系结构。
向网络输入图像序列,使用序列输入层。
利用卷积层提取特征,也就是说,应用卷积操作独立视频的每一帧,使用序列折叠层卷积层紧随其后。
恢复序列结构和重塑输出向量序列,使用序列展开层和一个平层。
分类结果向量序列,包括LSTM层输出层紧随其后。
负载Pretrained卷积网络
帧的视频转换成特征向量,利用pretrained网络的激活。
加载一个pretrained GoogLeNet模型使用googlenet
函数。这个函数需要深度学习工具箱™模型GoogLeNet网络万博1manbetx支持包。如果这种支持包没万博1manbetx有安装,那么函数提供一个下载链接。
netCNN = googlenet;
加载数据
下载HBMD51数据集HMDB:一个巨大的人类运动数据库RAR文件提取到一个文件夹命名“hmdb51_org”
。数据集包含了约7000年的2 GB的视频数据片段51类,如“喝”
,“运行”
,“shake_hands”
。
提取的RAR文件后,使用支持功能万博1manbetxhmdb51Files
获取文件名称和标签的视频。
dataFolder =“hmdb51_org”;(文件、标签)= hmdb51Files (dataFolder);
阅读第一个视频使用readVideo
helper函数,在这个例子中,定义并查看视频的大小。这个视频是一个H——- - - - - -W——- - - - - -C——- - - - - -年代数组,H,W,C,年代高度,宽度,渠道,和视频的帧数。
idx = 1;文件名=文件(idx);视频= readVideo(文件名);大小(视频)
ans =1×4240 320 409
查看相应的标签。
标签(idx)
ans =分类brush_hair
查看视频,使用implay
函数(需要图像处理工具箱™)。这个函数将数据范围[0,1],所以首先必须的数据除以255。或者,您可以遍历各个框架和使用imshow
函数。
numFrames =大小(视频、4);图为i = 1: numFrames帧=视频(::,:,我);imshow(帧/ 255);drawnow结束
帧转换为特征向量
利用卷积网络特征提取器的输入视频帧到网络时激活。将视频序列的特征向量,特征向量的输出激活
函数的最后池层GoogLeNet网络(“pool5-7x7_s1”
)。
这个图表说明了通过网络数据流。
读取视频数据和调整它来匹配输入的大小GoogLeNet网络使用readVideo
和centerCrop
辅助函数,定义在这个例子。这一步需要花很长时间。转换后的视频序列,保存在MAT-file序列tempdir
文件夹中。如果垫文件已经存在,然后从MAT-file加载序列没有改造。
inputSize = netCNN.Layers (1) .InputSize (1:2);layerName =“pool5-7x7_s1”;tempFile = fullfile (tempdir,“hmdb51_org.mat”);如果存在(tempFile“文件”)负载(tempFile“序列”)其他的numFiles =元素个数(文件);序列=细胞(numFiles, 1);为i = 1: numFiles流(“阅读文件% d % d…\ n”,我,numFiles)视频= readVideo(文件(i));视频= centerCrop(视频、inputSize);序列{我1}=激活(layerName netCNN、视频,“OutputAs”,“列”);结束保存(tempFile,“序列”,“-v7.3”);结束
视图的大小头几个序列。每个序列都是一个D——- - - - - -年代数组,D是功能的数量(池层的输出大小)和年代是视频的帧数。
序列(1:10)
ans =10×1单元阵列{1024×409单}{1024×395单}{1024×323单}{1024×246单}{1024×159单}{1024×137单}{1024×359单}{1024×191单}{1024×439单}{1024×528单}
准备训练数据
准备培训的数据分区的数据为训练和验证的分区和删除任何长序列。
创建分区训练和验证
分区的数据。90%的数据分配给培训验证分区分区和10%。
numObservations =元素个数(序列);idx = randperm (numObservations);地板(N = 0.9 * numObservations);idxTrain = idx (1: N);sequencesTrain =序列(idxTrain);labelsTrain =标签(idxTrain);idxValidation = idx (N + 1:结束);sequencesValidation =序列(idxValidation);labelsValidation =标签(idxValidation);
删除长序列
序列中比典型的长序列的网络可以在训练中引入大量填充过程。填充太多负面影响分类精度。
得到的序列长度的训练数据和可视化在训练数据的直方图。
numObservationsTrain =元素个数(sequencesTrain);numObservationsTrain sequenceLengths = 0 (1);为i = 1: numObservationsTrain = sequencesTrain序列{};sequenceLengths (i) =(序列,2)大小;结束图直方图(sequenceLengths)标题(“序列长度”)包含(“序列长度”)ylabel (“频率”)
只有几个序列有超过400的时间步骤。提高分类精度,删除超过400时间步的训练序列及其对应的标签。
最大长度= 400;idx = sequenceLengths >最大长度;sequencesTrain (idx) = [];labelsTrain (idx) = [];
创建LSTM网络
接下来,创建一个LSTM网络可以表示视频序列的特征向量进行分类。
定义LSTM网络体系结构。指定以下网络层。
序列输入层的大小对应于特征维的特征向量
BiLSTM层与2000隐藏单位辍学层之后。输出只有一个标签为每个序列通过设置
“OutputMode”
选择BiLSTM层“最后一次”
完全连接层和一个输出尺寸对应类的数量,softmax层和一层分类。
numFeatures =大小(sequencesTrain {1}, 1);numClasses =元素个数(类别(labelsTrain));层= [sequenceInputLayer numFeatures,“名字”,“序列”)bilstmLayer (2000,“OutputMode”,“最后一次”,“名字”,“bilstm”)dropoutLayer (0.5,“名字”,“下降”)fullyConnectedLayer (numClasses“名字”,“俱乐部”)softmaxLayer (“名字”,“softmax”)classificationLayer (“名字”,“分类”));
指定培训选项
使用指定的培训选项trainingOptions
函数。
设置一个mini-batch尺寸16,0.0001的初始学习速率,梯度阈值的2(防止梯度爆炸)。
截断在每个mini-batch序列有相同的长度最短的序列。
混乱的数据每一时代。
验证每个时代网络一次。
显示在一块训练进展和抑制详细输出。
miniBatchSize = 16;numObservations =元素个数(sequencesTrain);numIterationsPerEpoch =地板(numObservations / miniBatchSize);选择= trainingOptions (“亚当”,…“MiniBatchSize”miniBatchSize,…“InitialLearnRate”1的军医,…“GradientThreshold”2,…“洗牌”,“every-epoch”,…“ValidationData”{sequencesValidation, labelsValidation},…“ValidationFrequency”numIterationsPerEpoch,…“阴谋”,“训练进步”,…“详细”、假);
火车LSTM网络
列车网络使用trainNetwork
函数。这可能需要很长时间才能运行。
[netLSTM,信息]= trainNetwork (sequencesTrain、labelsTrain层,选择);
计算网络的分类精度验证设置。使用相同的培训mini-batch大小选项。
YPred =分类(netLSTM sequencesValidation,“MiniBatchSize”,miniBatchSize);YValidation = labelsValidation;精度=意味着(YPred = = YValidation)
精度= 0.6647
组装视频分类网络
直接创建一个分类的网络视频,网络组装使用创建的网络层。使用层从卷积网络将视频转换成向量序列和层次从LSTM网络分类向量序列。
下图说明了网络体系结构。
向网络输入图像序列,使用序列输入层。
利用卷积层提取特征,也就是说,应用卷积操作独立视频的每一帧,使用序列折叠层卷积层紧随其后。
恢复序列结构和重塑输出向量序列,使用序列展开层和一个平层。
分类结果向量序列,包括LSTM层输出层紧随其后。
添加回旋的层
首先,创建一个层GoogLeNet网络的图。
cnnLayers = layerGraph (netCNN);
删除输入层(“数据”
)和层后池层用于激活(“pool5-drop_7x7_s1”
,“loss3-classifier”
,“概率”
,“输出”
)。
layerNames = [“数据”“pool5-drop_7x7_s1”“loss3-classifier”“概率”“输出”];cnnLayers = removeLayers (cnnLayers layerNames);
添加顺序输入层
创建一个序列输入层,接受图像序列包含的图像大小相同的输入GoogLeNet网络。规范化的图像使用相同的平均形象GoogLeNet网络设置“归一化”
选择的顺序输入层“zerocenter”
和“的意思是”
选择平均GoogLeNet的输入层的形象。
inputSize = netCNN.Layers (1) .InputSize (1:2);averageImage = netCNN.Layers (1) .AverageImage;inputLayer = sequenceInputLayer (inputSize [3],…“归一化”,“zerocenter”,…“的意思是”averageImage,…“名字”,“输入”);
添加序列输入层到层图。应用卷积层独立的图像序列,去除图像序列的序列结构,包括一个序列折叠层之间的序列输入层和卷积层。的输出序列折叠层连接到输入的第一个回旋的层(“conv1-7x7_s2”
)。
层= [inputLayer sequenceFoldingLayer (“名字”,“折”));lgraph = addLayers (cnnLayers层);lgraph = connectLayers (lgraph,“折/”,“conv1-7x7_s2”);
添加LSTM层
LSTM层添加到层图通过移除序列LSTM网络的输入层。恢复序列结构被序列折叠层,包括序列卷积后展开层层。LSTM层期望向量序列。重塑的输出序列展开层向量序列,包括平层后序列展开层。
从LSTM网络层和删除序列输入层。
lstmLayers = netLSTM.Layers;lstmLayers (1) = [];
添加序列折叠层、平层和LSTM层到层图。连接最后卷积层(“pool5-7x7_s1”
)的输入序列展开层(“展开/”)
。
层= [sequenceUnfoldingLayer (“名字”,“展开”)flattenLayer (“名字”,“平”)lstmLayers);lgraph = addLayers (lgraph层);lgraph = connectLayers (lgraph,“pool5-7x7_s1”,“展开/”);
使展开层恢复序列结构,连接“miniBatchSize”
的输出序列折叠层的相应输入序列展开层。
lgraph = connectLayers (lgraph,“折/ miniBatchSize”,“展开/ miniBatchSize”);
组装网络
检查网络是否有效使用analyzeNetwork
函数。
analyzeNetwork (lgraph)
组装网络预测准备使用assembleNetwork
函数。
净= assembleNetwork (lgraph)
网= DAGNetwork属性:层:[148×1 nnet.cnn.layer.Layer]连接:(175×2表)
使用新数据进行分类
阅读和center-crop视频“pushup.mp4”
使用相同的步骤。
文件名=“pushup.mp4”;视频= readVideo(文件名);
查看视频,使用implay
函数(需要图像处理工具箱)。这个函数将数据范围[0,1],所以首先必须的数据除以255。或者,您可以遍历各个框架和使用imshow
函数。
numFrames =大小(视频、4);图为i = 1: numFrames帧=视频(::,:,我);imshow(帧/ 255);drawnow结束
使用组装网络视频进行分类。的分类
函数将一个单元阵列包含输入视频,所以你必须输入一个1×1单元阵列包含视频。
视频= centerCrop(视频、inputSize);{视频}YPred =分类(净)
YPred =分类俯卧撑
辅助函数
的readVideo
函数读取视频文件名
并返回一个H
——- - - - - -W
——- - - - - -C -
由- - - - - -年代
数组,H
,W
,C
,年代
高度,宽度,渠道,和视频的帧数。
函数视频= readVideo(文件名)vr = VideoReader(文件名);H = vr.Height;W = vr.Width;C = 3;% Preallocate视频数组numFrames =地板(虚拟现实。Duration * vr.FrameRate); video = zeros(H,W,C,numFrames);%阅读框架我= 0;而hasFrame (vr)我= + 1;视频(::,:,我)= readFrame (vr);结束%去除未分配的框架如果大小(视频,4)>我视频(:,:,:,i + 1:结束)= [];结束结束
的centerCrop
函数作物的最长边视频和尺寸大小inputSize
。
函数videoResized = centerCrop(视频、inputSize)深圳=大小(视频);如果深圳(1)<深圳(2)%视频讲的是风景地板idx =((深圳(2)-深圳(1)/ 2);视频(:,1:(idx-1):,:) = [];视频(:,(深圳(1)+ 1):,:,:)= [];elseif深圳(2)<深圳(1)%视频画像地板idx =((深圳(1)-深圳(2))/ 2);视频(1:(idx-1)::,:) = [];视频((深圳(2)+ 1):,:,:,:)= [];结束videoResized = imresize(视频、inputSize (1:2));结束