簡體   English   中英

我需要Keras VGG16的預訓練重量嗎?

[英]Do I Need Pretrained Weights For Keras VGG16?

作為背景,我對機器學習的世界相對較新,我正在嘗試一個目標是在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比賽的視頻片段進行分類,那么將VGG16 ConvNet的權重初始化為'imagenet'對我來說仍然有益嗎? 如果是這樣,為什么? 如果沒有,我如何訓練VGG16 ConvNet獲取我自己的權重集,然后如何將它們插入到此函數中? 在使用VGG16模型時,我沒有找到任何有人使用自己的權重集的教程。

如果我的問題看起來很幼稚,我會道歉但我真的很感激任何有助於清理它的人。

您是否應該為特定任務重新訓練VGG16? 絕對不! 重新訓練如此龐大的網絡很難,並且需要很多直覺和知識來培訓深層網絡。 讓我們分析一下為什么你可以使用在ImageNet上預訓練的權重來完成你的任務:

  • ImageNet是一個龐大的數據集,包含數百萬個圖像。 VGG16本身已在3-4天左右的強大GPU上接受過培訓。 在CPU上(假設您沒有像NVIDIA GeForce Titan X那樣強大的GPU)需要數周時間。

  • ImageNet包含來自真實場景的圖像。 NBA比賽也可以被視為現實世界的場景。 因此,ImageNet功能的預訓練很可能也可用於NBA比賽。

實際上,您不需要使用預先訓練過的VGG16的所有卷積層。 讓我們看一下內部VGG16層可視化,看看它們檢測到了什么(取自本文 ;圖像太大,所以我只提供了一個緊湊的鏈接):

  • 第一和第二卷積塊查看低級特征,例如角,邊等。
  • 第三和第四個卷積塊查看曲面特征,曲線,圓等。
  • 第五層着眼於高級功能

因此,您可以決定哪種功能對您的特定任務有益。 在第5街區你需要高水平的功能嗎? 或者您可能想要使用第3塊的中級功能? 也許你想在VGG底層疊加另一個神經網絡? 有關更多說明,請查看我編寫的以下教程; 它曾經是SO文檔。


使用VGG和Keras進行傳輸學習和微調

在這個例子中,提出了三個簡短而全面的子示例:

  • 從可用的預訓練模型加載重量,包括Keras
  • 在VGG的任何層之上堆疊另一個網絡進行培訓
  • 在其他圖層的中間插入圖層
  • 使用VGG進行微調和轉移學習的提示和一般經驗法則

加載預先訓練的重量

Keras預先訓練上ImageNet車型,其中包括VGG-16VGG-19,是可用的。 在此示例中,此處和之后將使用VGG-16 有關更多信息,請訪問Keras Applications文檔

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) block2_pool (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_conv1block2_conv2替換為單個卷積層來加速block1_conv1block2_conv2保存預先訓練的權重。 我們的想法是將整個網絡拆分為單獨的層,然后再組裝。 以下是專門針對您的任務的代碼:

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM