【问题标题】:convert VGG16 shape output from 4096 features to 2048将 VGG16 形状输出从 4096 个特征转换为 2048 个
【发布时间】:2020-10-03 20:17:18
【问题描述】:

我正在尝试使用 VGG16 预训练模型进行图像分类并将特征转换为 csv 文件,但我面临特征数量的问题,我试图获得 2048 个特征而不是我拥有的 4096 个特征读到小东西说我可以从 vgg16 模型中删除一层,然后我可以得到 2048 功能,但我被这个东西卡住了,谁能纠正我

def read_images(folder_path, classlbl):
       # load all images into a list
        images = []
        img_width, img_height = 224, 224
        class1=[]
        for img in os.listdir(folder_path):
            img = os.path.join(folder_path, img)
            img = load_img(img, target_size=(img_width, img_height))
            class1.append(classlbl)# class one.
            images.append(img)
        return images, class1  
def computefeatures(model,image):
   # convert the image pixels to a numpy array
    image = img_to_array(image)
    # reshape data for the model
    image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
    # prepare the image for the VGG model
    image = preprocess_input(image)

    # get extracted features
    features = model.predict(image)
    return features

# load model
model = VGG16()

# remove the output layer
model.layers.pop()
model = Model(inputs=model.inputs, outputs=model.layers[-1].output)

# call the image read and 
folder_path = '/content/Images'
classlbl=5

images, class1 =read_images(folder_path, classlbl)
# call the fucntion to compute the features for each image. 
list_features1=[]
list_features1 = np.empty((0,4096), float)# create an empty array with 0 row and 4096 columns this number from fature
# extraction from vg16 
for img in range(len(images)):
    f2=computefeatures(model,images[img]) # compute features forea each image
    #list_features1=np.append(list_features1, f2, axis=1)
    #list_features=np.vstack((list_features, f2))
    list_features1 = np.append(list_features1, f2, axis=0)

classes1 = []
count = 0
for i in range(156):
    if count >= 0 and count <= 156:
        classes1.append(5)
    count = count + 1
print(len(classes1))
df1= pd.DataFrame(list_features1,columns=list(range(1,4097)))
df1.head()

df1.head() 中的当前输出:

1       2       3       4       4096
0.12    0.23    0.345   0.5372  0.21111
0.2313  0.321   0.214   0.3542  0.46756
.
.

想要的输出:

1       2       3       4       2048
0.12    0.23    0.345   0.5372  0.21111
0.2313  0.321   0.214   0.3542  0.46756
.
.

P.S : 如果我直接将其替换为 2048 list_features1 = np.empty((0,2048), float) 它将返回错误:

all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 2048 and the array at index 1 has size 409

这是我的模型架构:

Model: "vgg16"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_8 (InputLayer)         (None, 224, 224, 3)       0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544 
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
predictions (Dense)          (None, 1000)              4097000   
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0

【问题讨论】:

  • 可以根据数据重新训练吗?
  • 上面的代码工作正常,但问题是我得到了 4096 个功能而不是 2048,是的,我可以

标签: numpy keras deep-learning neural-network conv-neural-network


【解决方案1】:

最简单的方法是在 4096 之后添加一个密集层,它在输出层之前只有 2096 个特征。在此过程中,我将保持原始模型的权重不变。 为了实现这一点,您可以像以前一样计算您的特征,将它们用作具有以下结构的第二个模型的输入(假设一个两类问题)

Layer (type)                 Output Shape              Param #   
=================================================================
input_11 (InputLayer)        [(None, 4096)]            0         
_________________________________________________________________
dense_13 (Dense)             (None, 2096)              8587312   
_________________________________________________________________
dense_14 (Dense)             (None, 2)                 4194       #<-- here you need to set right number of classes   
=================================================================
Total params: 8,591,506
Trainable params: 8,591,506
Non-trainable params: 0
_________________________________________________________________

根据数据训练模型后,再次弹出最后一层。

如果您还想重新训练原始特征,您可以使用子模型作为新头。

【讨论】:

  • 谢谢,但我期待的是 2048,而不是 2096,你能告诉我我必须在代码中做什么样的改变
【解决方案2】:

我不确定我是否理解您的问题,您可以在model.layers 上使用pop(),然后使用model.layers[-1].output 创建新图层。

vgg16_model = keras.applications.vgg16.VGG16()

model = Sequential()

for layer in vgg16_model.layers[:-1]:
    model.add(layer)

model.layers.pop()


# Freeze the layers 
for layer in model.layers:
    layer.trainable = False


# Add 'softmax' instead of earlier 'prediction' layer.
model.add(Dense(2048, activation='softmax'))


# Check the summary, and yes new layer has been added. 
model.summary()

【讨论】:

    猜你喜欢
    • 2018-12-20
    • 1970-01-01
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多