requirements:
Keras>=2.0.2
numpy>=1.12.1
pandas>=0.19.2
tqdm>=4.11.2
matplotlib>=2.0.0
Pillow>=2.1.0
h5py>=2.7.0
1)下载UCF101数据集压缩包并减压至data文件夹。
2)在data文件夹创建train、test 、sequences、checkpoints四个文件。
1、UCF101数据集是由101类视频组成的,首先通过运行1_move_files.py将101类视频按照ucfTrainTestlist文件夹下的数据标签将101视频分别移至train、test文件夹。
Lable:
这里有个坑!!
1_move_files.py 第58行:
if not os.path.exists(filename):
print("Can't find %s to move. Skipping." % (filename))
continue
# Move it.
dest = os.path.join(group, classname, filename)
print("Moving %s to %s" % (filename, dest))
os.rename(filename, dest)
print("Done.")
filename_input = os.path.join('UCF-101', classname, filename)
if not os.path.exists(filename_input):
print("Can't find %s to move. Skipping." % (filename))
continue
# Move it.
dest = os.path.join(group, classname, filename)
print("Moving %s to %s" % (filename, dest))
os.rename(filename_input, dest)
print("Done.")
2、现在通过运行2_extract_files.py提取train、test文件夹中视频的视频帧,并生成一个CSV文件 。该CSV文件为之后特征提取及网络训练时数据读取提供帮助:
def get_data():
"""Load our data from file."""
with open(os.path.join('data', 'data_file.csv'), 'r') as fin:
reader = csv.reader(fin)
data = list(reader)
return data
通过运行extract_features.py提取视频帧特征。
seq_length = 40
class_limit = 101
seq_length:每个视频段考虑的视频帧数目
class_limit:限制分类数
举个例子:一个视频段input_list有240帧,seq_length = 40,首先判断input_list是否大于seq_length即 assert len(input_list) >= seq_length
。然后将input_list与seq_length做地板除即: skip = len(input_list) // size
,本例中skip = 6,即每隔6帧从input_list中取一帧以列表的形式保存到output即:output = [input_list[i] for i in range(0, len(input_list), skip)]
,最终取得40帧。
def rescale_list(input_list, size):
assert len(input_list) >= size
skip = len(input_list) // size
output = [input_list[i] for i in range(0, len(input_list), skip)]
return output[:size]
在Imagenet上预训练好的InceptionV3卷积网络提取这40帧特征作为该视频段的特征。并将特征保存在sequences文件夹,numpy会自动在末尾添加 .npy。
path = os.path.join('data', 'sequences', video[2] + '-' + str(seq_length) + \
'-features')
将提取到的序列特征送入LSTM网络进行训练。通过运行 train.py生成 .hdf5文件,并将模型保存到checkpoints文件夹,并且会在logs文件夹生成一个 .log 训练日志文件,用来可视化训练过程中acc与loss的变化。
获取由CNN提取的序列特征:
def get_extracted_sequence(self, data_type, sample):
"""Get the saved extracted features."""
filename = sample[2]
path = os.path.join(self.sequence_path, filename + '-' + str(self.seq_length) + \'-' + data_type + '.npy')
if os.path.isfile(path):
return np.load(path)
else:
return None
LSTM网络模型:
def lstm(self):
model = Sequential()
model.add(LSTM(2048, return_sequences=False,
input_shape=self.input_shape,
dropout=0.5))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(self.nb_classes, activation='softmax'))
return model
用来可视化训练过程的plot_trainlog.py:
import csv
import matplotlib.pyplot as plt
def main(training_log):
with open(training_log) as fin:
reader = csv.reader(fin)
next(reader, None) # skip the header
accuracies = []
Val_acc = []
cnn_benchmark = [] # this is ridiculous
for epoch,acc,loss,val_acc,val_loss in reader:
accuracies.append(float(acc))
Val_acc.append(float(val_acc))
cnn_benchmark.append(0.65) # ridiculous
plt.plot(accuracies)
plt.plot(Val_acc)
plt.plot(cnn_benchmark)
plt.show()
if __name__ == '__main__':
training_log = 'data/logs/lstm-training-1617251893.3342032.log'
main(training_log)
绿线:cnn_benchmark
橘黄线:Val_acc
蓝线:accuracies
通过运行validate_rnn.py将保存在checkpoints文件夹的模型加载进来验证模型准确度。结果如图:
若要将一段视频进行分段处理,十帧作为一个序列,首先送入CNN提取基础特征,后送入LSTM提取时间-空间特征,会遇到什么问题?能否完成视频分段任务?是否过拟合?模型鲁棒性如何?