视频分类之UCF-101上的CNN方法详解
Code at Github:https://github.com/sujiongming/UCF-101_video_classification
PDF版(排版更好)下载链接:链接:https://pan.baidu.com/s/1mjlZqjA密码:7ads
视频分类包括人类行为识别和通用的多标签视频分类等研究内容。用的多标签视频分类以2016年谷歌发布的youtube-8M数据集为代表,其中很多视频属于多个类别,并且在类别上不限于人类行为。人类行为识别主要研究分类视频中包含的人类行动,一般一个视频中只包含一类人类行为,UCF101数据集就是其中的典型代表。UCF-101(2012)包含13,320个视频(共27个小时),101个人类行为类别,如运动、乐器和人物交互等。[1] 国内外研究人员在UCF-101数据集上进行了深入研究,目前最好的准确率已经达到95%以上。
UCF-101上的CNN方法一般作为其他分类方法的比较基准,也是最简单和自然的视频分类方法[2]。CNN方法是将这些视频帧视为一张张静态图像,应用CNN识别每一帧,然后对预测结果进行平均处理来作为该视频的最终结果。然而,这个方法使用的是不完整的视频信息,因此使得分类器可能容易发生混乱而导致准确度不高。本文CNN方法在测试集上的最终准确度为top1:63.0%,top5:87.5%。
UCF-101中6类行为的样本图像帧
一、 基本过程和思想
基本思想是将数据集中视频及分类标签转换为图像(视频帧)和其对应的分类标签,再采用CNN网络对图像进行训练学习和测试,将视频分类问题转化为图形分类问题。具体步骤包括:
(1) 对每个视频(训练和测试视频)以一定的FPS截出视频帧(jpegs)保存为训练集和测试集,将对图像的分类性能作为所对应视频的分类性能:train set 有1, 788, 425帧图像,test set 有697, 865帧图像
(2) 选择一个预先训练好的CNN网络架构和初始权重,迁移学习至UCF-101,如inception v3 with pre-trained on ImageNet
(3) 用train set对CNN网络部分层进行重新训练,获得模型
(4) 训练完成后载入模型对test set内所有的视频帧进行检查验证,得出全测试集上的top1准确率和top5准确率输出
二、 运行环境简介
(1) 服务器硬件环境:40核至强cpu,GeForce GTX 1080 8G显存 X2,128G内存,512G
SSD,3TB机械硬盘
(2) 服务器软件环境:安装ubuntu16.04、conda(含python2.7),CUDA,cudnn、tensorflow GPU,keras等所需python包,SSH服务,screen包,vim工具,ffmpeg包
(3) 客户机:window7 64位,pycharm,xshell,xftp
(4) 使用模式:客户机远程SSH连接服务器进行操作
三、 运行过程和结果
(5) 准备数据(UCF提供了三种训练/测试划分方案,本实例采用1#划分方案)
i. 用xftp软件将开源项目程序和UCF101数据包上传至服务器谋和目录下
ii. 将UCF101数据包放在开源项目文件夹的data目录下,运行命令“unrar e UCF101.rar”
iii. 运行命令`python 1_move_files.py`
iv. 运行命令`python 2_extract_files.py`
6) 训练CNN,输出测试集性能
i. 运行python CNN_train_UCF101.py,命令行输出训练过程信息,在测试子集上的准确率和top5准确率,系统函数默认k=5。
ii.训练集:到41 epoch时训练自动停止,最好的结果在29 epoch时出现,val_loss 最小为1.19,采用该模型评价测试集。模型名称为:inception.0.29-1.19.hdf5,需要修改CNN_evaluate_testset.py文件加载该名称模型。
iii. 运行python CNN_evaluate_testset.py,命令行输出测试集结果 。
iv. 测试集:loss:1.33,accuracy:0.63,top5 accuracy:0.875
v. 运行python CNN_validate_images.py,命令行输出随机选择的5张图像的分类信息和结果。
需要注意的是,你的运行结果可能与本文有所差异,因此研究者可能需要不断修改调整模型超参,多次运行,找出最好的一组模型参数,取最好的准确度结果。
四、 将inception-v3网络迁移学习至UCF-101
假设有数据集D,不同于数据集ImageNet,D有1024个输入特征,200个输出类别。
from keras.applications.inception_v3 import InceptionV3
from keras.preprocessing import image
from keras.models import Model
from keras.layers import Dense,GlobalAveragePooling2D
from keras import backend as K
# create the base
pre-trained model
base_model=InceptionV3(weights='imagenet',include_top=False)
#
include_top=False因为我们想要重新在数据集D上训练top level,我们移除了最后三层,暴露的是mixed10层的输出。
#模型最后4层的 layer.name, layer.input_shape,
layer.output_shape
('mixed10',[(None,8,8,320),(None,8,8,768),(None,8,8,768),(None,8,8,192)
('avg_pool',(None,8,8,2048),(None,1,1,2048))
('flatten',(None,1,1,2048),(None,2048))
('predictions',(None,2048),(None,1000))
#因此,需要加三层
x=base_model.output
x=GlobalAveragePooling2D()(x)
x=Dense(1024,activation='relu')(x)#加入1024个特征层
predictions=Dense(200,activation='softmax')(x)#输出层,加入数据集类别
model=Model(input=base_model.input,output=predictions)
forlayerinbase_model.layers:#固定inceptionv3模型参数
layer.trainable=False
#编译模型
model.compile(optimizer='rmsprop',loss='categorical_crossentropy')
#模型训练新加的层
model.fit_generator(train_generator,steps_per_epoch=100,validation_data=validation_generator,validation_steps=10,epochs=nb_epoch,callbacks=callbacks)
#训练the top 2 inception blocks,因此固定前172层,训练后面的层
forlayerinmodel.layers[:172]:layer.trainable=False
forlayerinmodel.layers[172:]:layer.trainable=True
model.compile(
optimizer=SGD(lr=0.0001,momentum=0.9),
loss='categorical_crossentropy',
metrics=['accuracy','top_k_categorical_accuracy'])
model.fit_generator(
train_generator,
steps_per_epoch=100,
validation_data=validation_generator,
validation_steps=10,
epochs=nb_epoch,
callbacks=callbacks)
这样就在新的数据集上通过迁移学习训练好一个新的网络了。
需要注意的是
(1) InceptionV3模型的输入为299X299X3,因此数据集上的图片大小得修改为该大小格式:
train_generator = train_datagen.flow_from_directory(
'./data/train/',
target_size=(299, 299), batch_size=32,
classes=data.classes,
class_mode='categorical')
validation_generator = test_datagen.flow_from_directory(
'./data/test/',
target_size=(299, 299), batch_size=32,
classes=data.classes,
class_mode='categorical')
image_arr = process_image(image, (299, 299, 3)) #CNN_validate_images
(2) 验证测试数据集时
results=model.evaluate_generator(generator=test_generator,steps=test_data_num//batch_size)#参数steps为数据生成的批次,一般为数据总数除以每批产生的数据个数
(3) 参数设置
#每个epoch后存入val_loss最小的模型checkpointer=ModelCheckpoint(filepath='./data/checkpoints/inception.{epoch:03d}-{val_loss:.2f}.hdf5',verbose=1,save_best_only=True)# patience: number of epochs with no improvement after which training will be stopped. 10个epoch模型性能没有改进后训练停止early_stopper=EarlyStopping(patience=10)
其他代码和使用说明可以详见github项目 UCF-101_video_classification。