视频异常监测(TensorFlow)

该数据集包含从UCF犯罪数据集中的每个视频中提取的图像。,用于监控视频中的真实世界—异常检测。提取每10帧长度的视频,并将其合并到该分类中。所有图片尺寸为64*64,格式为.png。该数据集共有14个类别(1. Abuse 、2. Arrest、3. Arson、4. Assault、5. Burglary、6. Explosion、7. Fighting、8. Normal Videos、9. RoadAccidents、10. Robbery、11. Shooting、12. Shoplifting、13. Stealing、14. Vandalism)。

包和参数配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import os
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import roc_curve, auc, roc_auc_score
from IPython.display import clear_output
import warnings
warnings.filterwarnings('ignore')

train_dir = "../input/ucf-crime-dataset/Train"
test_dir = "../input/ucf-crime-dataset/Test"

SEED = 12
IMG_HEIGHT = 64
IMG_WIDTH = 64
BATCH_SIZE = 64
EPOCHS = 1
LR = 0.00003
NUM_CLASSES = 14
CLASS_LABELS = ['Abuse','Arrest','Arson','Assault','Burglary','Explosion','Fighting',"Normal",'RoadAccidents','Robbery','Shooting','Shoplifting','Stealing','Vandalism']

数据加载和预处理

为训练数据和测试数据创建两个不同的生成器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
preprocess_fun = tf.keras.applications.densenet.preprocess_input

train_datagen = ImageDataGenerator(horizontal_flip=True,
width_shift_range=0.1,
height_shift_range=0.05,
rescale = 1./255,
preprocessing_function=preprocess_fun
)
test_datagen = ImageDataGenerator(rescale = 1./255, preprocessing_function=preprocess_fun)


train_generator = train_datagen.flow_from_directory(directory = train_dir,
target_size = (IMG_HEIGHT ,IMG_WIDTH),
batch_size = BATCH_SIZE,
shuffle = True ,
color_mode = "rgb",
class_mode = "categorical",
seed = SEED
)
test_generator = test_datagen.flow_from_directory(directory = test_dir,
target_size = (IMG_HEIGHT ,IMG_WIDTH),
batch_size = BATCH_SIZE,
shuffle = False ,
color_mode = "rgb",
class_mode = "categorical",
seed = SEED
)
# Found 1266345 images belonging to 14 classes.
# Found 111308 images belonging to 14 classes.

所有类别之间的数据分布(计数),训练数据分布:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fig = px.bar(x = CLASS_LABELS,
y = [list(train_generator.classes).count(i) for i in np.unique(train_generator.classes)] ,
color = np.unique(train_generator.classes) ,
color_continuous_scale="Emrld")
fig.update_xaxes(title="Classes")
fig.update_yaxes(title = "Number of Images")
fig.update_layout(showlegend = True,
title = {
'text': 'Train Data Distribution ',
'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'})
fig.show()

所有类别之间的数据分布(计数),测试数据分布:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fig = px.bar(x = CLASS_LABELS,
y = [list(test_generator.classes).count(i) for i in np.unique(test_generator.classes)] ,
color = np.unique(train_generator.classes) ,
color_continuous_scale="Emrld")
fig.update_xaxes(title="Classes")
fig.update_yaxes(title = "Number of Images")
fig.update_layout(showlegend = True,
title = {
'text': 'Test Data Distribution ',
'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'})
fig.show()

DenseNet121 迁移学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def feature_extractor(inputs):
feature_extractor = tf.keras.applications.DenseNet121(input_shape=(IMG_HEIGHT,IMG_WIDTH, 3),
include_top=False,
weights="imagenet")(inputs)
return feature_extractor

def classifier(inputs):
x = tf.keras.layers.GlobalAveragePooling2D()(inputs)
x = tf.keras.layers.Dense(256, activation="relu")(x)
x = tf.keras.layers.Dropout(0.3)(x)
x = tf.keras.layers.Dense(1024, activation="relu")(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(512, activation="relu")(x)
x = tf.keras.layers.Dropout(0.4) (x)
x = tf.keras.layers.Dense(NUM_CLASSES, activation="softmax", name="classification")(x)

return x

def final_model(inputs):
densenet_feature_extractor = feature_extractor(inputs)
classification_output = classifier(densenet_feature_extractor)

return classification_output

def define_compile_model():

inputs = tf.keras.layers.Input(shape=(IMG_HEIGHT ,IMG_WIDTH,3))
classification_output = final_model(inputs)
model = tf.keras.Model(inputs=inputs, outputs = classification_output)

model.compile(optimizer=tf.keras.optimizers.SGD(LR),
loss='categorical_crossentropy',
metrics = [tf.keras.metrics.AUC()])

return model

model = define_compile_model()
clear_output()
model.summary()

结果输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 64, 64, 3)] 0
_________________________________________________________________
densenet121 (Functional) (None, 2, 2, 1024) 7037504
_________________________________________________________________
global_average_pooling2d (Gl (None, 1024) 0
_________________________________________________________________
dense (Dense) (None, 256) 262400
_________________________________________________________________
dropout (Dropout) (None, 256) 0
_________________________________________________________________
dense_1 (Dense) (None, 1024) 263168
_________________________________________________________________
dropout_1 (Dropout) (None, 1024) 0
_________________________________________________________________
dense_2 (Dense) (None, 512) 524800
_________________________________________________________________
dropout_2 (Dropout) (None, 512) 0
_________________________________________________________________
classification (Dense) (None, 14) 7182
=================================================================
Total params: 8,095,054
Trainable params: 8,011,406
Non-trainable params: 83,648
_________________________________________________________________

训练

1
2
3
history = model.fit(x = train_generator,validation_data=test_generator,epochs = EPOCHS)

# 19787/19787 [==============================] - 12791s 646ms/step - loss: 1.2359 - auc: 0.9094 - val_loss: 1.7220 - val_auc: 0.8329

绘制多类别AUC曲线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
preds = model.predict(test_generator)
y_test = test_generator.classes
fig, c_ax = plt.subplots(1,1, figsize = (15,8))

def multiclass_roc_auc_score(y_test, y_pred, average="macro"):
lb = LabelBinarizer()
lb.fit(y_test)
y_test = lb.transform(y_test)
for (idx, c_label) in enumerate(CLASS_LABELS):
fpr, tpr, thresholds = roc_curve(y_test[:,idx].astype(int), y_pred[:,idx])
c_ax.plot(fpr, tpr,lw=2, label = '%s (AUC:%0.2f)' % (c_label, auc(fpr, tpr)))
c_ax.plot(fpr, fpr, 'black',linestyle='dashed', lw=4, label = 'Random Guessing')
return roc_auc_score(y_test, y_pred, average=average)

print('ROC AUC score:', multiclass_roc_auc_score(y_test , preds , average = "micro"))
plt.xlabel('FALSE POSITIVE RATE', fontsize=16)
plt.ylabel('TRUE POSITIVE RATE', fontsize=16)
plt.legend(fontsize = 11.5)
plt.show()

# ROC AUC score: 0.8333164153895329