作为背景,我对机器学习的世界比较陌生,我正在尝试一个项目,目标是在NBA游戏中对游戏进行分类。我的输入是一个NBA比赛中每场比赛40帧的序列,我的标签是11个包含给定比赛的分类。
该计划是采取每个帧序列,并通过每个帧到CNN提取一组功能。然后将给定视频中的每个特征序列传递到RNN。
我目前正在使用Keras进行大部分的实现,我选择了为我的CNN使用一个vgg16模型。下面是一些相关代码:
video = keras.Input(shape = (None, 255, 255, 3), name = 'video')
cnn = keras.applications.VGG16(include_top=False, weights = None, input_shape=
(255,255,3), pooling = 'avg', classes=11)
cnn.trainable = True
我的问题是-如果我的目标是对NBA比赛的视频剪辑进行分类,那么将vg16 convnet的权重初始化为“imagenet”对我来说是否仍然有益?如果是,为什么?如果不是,如何训练vg16 convnet获得自己的一组权重,然后如何将它们插入此函数中?在使用vgg16模型时,我几乎没有找到任何教程,其中有人包含了自己的一组权重。
如果我的问题看起来很幼稚,我道歉,但我真的很感谢你帮我解决这个问题。
最佳答案
您是否应该为您的特定任务重新培训vg16?绝对不是!对如此庞大的网络进行再培训是很困难的,而且需要大量的直觉和知识来训练深层网络。让我们分析一下为什么您可以为您的任务使用在ImageNet上预先培训的权重:
ImageNet是一个巨大的数据集,包含数百万个图像。VGG16本身已经在3-4天左右的时间内接受了强大GPU的培训。在CPU上(假设你没有像Nvidia Geforce Titan X那样强大的GPU)需要几周时间。
ImageNet包含来自真实场景的图像。NBA比赛也可以被视为真实的场景。所以,很有可能预先训练过的ImageNet功能也可以用于NBA比赛。
实际上,您不需要使用预先培训过的vgg16的所有卷积层。让我们看一下visualization of internal VGG16 layers并看看它们检测到了什么(取自this article;图像太大,所以我只放了一个链接来表示紧凑性):
第一和第二卷积块查看低级特征,如角、边等。
第三和第四卷积块查看曲面特征、曲线、圆等。
第五层介绍高级功能
因此,您可以决定哪种特性对您的特定任务有利。你需要第五街区的高级功能吗?或者您可能想使用第3块的中级功能?也许你想把另一个神经网络叠加在VGG的底层之上?有关更多说明,请看一下我编写的以下教程;它曾经是关于so文档的。
使用vgg和keras进行传输学习和微调
在本例中,给出了三个简短而全面的子示例:
从Keras库中包含的可用预培训模型加载重量
在任何VGG层上堆叠另一个网络进行培训
在其他层的中间插入层
使用vgg进行微调和转移学习的提示和拇指的一般规则
装载预先训练的砝码
Keras提供了针对ImageNet型号的预先培训,包括VGG-16和VGG-19。在本例中以及之后,将使用VGG-16。有关更多信息,请访问Keras Applications documentation。
from keras import applications
# This will load the whole VGG16 network, including the top Dense layers.
# Note: by specifying the shape of top layers, input tensor shape is forced
# to be (224, 224, 3), therefore you can use it only on 224x224 images.
vgg_model = applications.VGG16(weights='imagenet', include_top=True)
# If you are only interested in convolution filters. Note that by not
# specifying the shape of top layers, the input tensor shape is (None, None, 3),
# so you can use them for any size of images.
vgg_model = applications.VGG16(weights='imagenet', include_top=False)
# If you want to specify input tensor
from keras.layers import Input
input_tensor = Input(shape=(160, 160, 3))
vgg_model = applications.VGG16(weights='imagenet',
include_top=False,
input_tensor=input_tensor)
# To see the models' architecture and layer names, run the following
vgg_model.summary()
创建一个底层取自vgg的新网络
假设对于某些特定任务,对于大小为
(160, 160, 3)
的图像,您希望使用预先培训过的vgg底层,直至名称为block2_pool
的层。vgg_model = applications.VGG16(weights='imagenet',
include_top=False,
input_shape=(160, 160, 3))
# Creating dictionary that maps layer names to the layers
layer_dict = dict([(layer.name, layer) for layer in vgg_model.layers])
# Getting output tensor of the last VGG layer that we want to include
x = layer_dict['block2_pool'].output
# Stacking a new simple convolutional network on top of it
x = Conv2D(filters=64, kernel_size=(3, 3), activation='relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(10, activation='softmax')(x)
# Creating new model. Please note that this is NOT a Sequential() model.
from keras.models import Model
custom_model = Model(input=vgg_model.input, output=x)
# Make sure that the pre-trained bottom layers are not trainable
for layer in custom_model.layers[:7]:
layer.trainable = False
# Do not forget to compile it
custom_model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
删除多个图层并在中间插入一个新图层
假设您需要通过用单个卷积层替换
block1_conv1
和block2_conv2
来加速vg16,这样就可以保存预先培训的权重。其思想是将整个网络分解成不同的层,然后重新组装。以下是专门针对您的任务的代码:
vgg_model = applications.VGG16(include_top=True, weights='imagenet')
# Disassemble layers
layers = [l for l in vgg_model.layers]
# Defining new convolutional layer.
# Important: the number of filters should be the same!
# Note: the receiptive field of two 3x3 convolutions is 5x5.
new_conv = Conv2D(filters=64,
kernel_size=(5, 5),
name='new_conv',
padding='same')(layers[0].output)
# Now stack everything back
# Note: If you are going to fine tune the model, do not forget to
# mark other layers as un-trainable
x = new_conv
for i in range(3, len(layers)):
layers[i].trainable = False
x = layers[i](x)
# Final touch
result_model = Model(input=layer[0].input, output=x)