我有一个包含2513张图片的8个类别的数据集,我想在这个数据集上对ResNet50进行微调。这是我的代码:
import kerasfrom keras.preprocessing.image import ImageDataGeneratorfrom sklearn.model_selection import train_test_splitimport matplotlib.pyplot as pltfrom tensorflow.keras.applications.resnet50 import ResNet50from tensorflow.keras.layers import Dense, Activation, Reshape, Conv2D, Flatten, GlobalAveragePooling2D, Dropoutimport numpy as npfrom tensorflow.keras.models import Modelfrom tensorflow.keras.optimizers import SGD, Adam, NadamDATA_DIR = 'data/'train_datagen = ImageDataGenerator( #rescale=1./255, #shear_range=0.2, #zoom_range=0.2, #horizontal_flip=True, validation_split=0.3 )train_generator = train_datagen.flow_from_directory(DATA_DIR, batch_size=50, class_mode='categorical', subset='training')validation_generator = train_datagen.flow_from_directory( DATA_DIR, # same directory as training data batch_size=50, class_mode='categorical', subset='validation') # set as validation data#X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=33)base_model = ResNet50(weights='imagenet', include_top=True)head_model = base_model.get_layer("conv5_block1_1_conv").output head_model = Dense(512, activation="relu")(head_model)head_model = Dropout(0.5)(head_model)head_model = Flatten()(head_model)#base_out = Reshape((25088,))(base_out)head_model = Dense(1, activation="sigmoid")(head_model)# place the head FC model on top of the base model (this will become# the actual model we will train)model = Model(inputs=base_model.input, outputs=head_model)model.summary()# loop over all layers in the base model and freeze them so they will# *not* be updated during the first training processfor layer in base_model.layers: layer.trainable = False # sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)adam = Adam(lr=0.001)model.compile(optimizer= adam, loss='categorical_crossentropy', metrics=['accuracy'])model.fit_generator( train_generator, steps_per_epoch = train_generator.samples // 32, validation_data = validation_generator, validation_steps = validation_generator.samples // 32, epochs = 100)model.save("asd.h5")
但运行这个代码时抛出了以下错误:
InvalidArgumentError: 输入到重塑的张量值为1638400,但请求的形状需要25088的倍数[[node model_8/flatten_7/Reshape (defined at ..)
我该怎么做来修复它?
回答:
有几件事似乎你需要考虑或确保。首先,你加载了ResNet50
并设置了它的weight
和include_top
参数,但没有定义input_shape
,因此它使用了默认值(224, 224, 3
),与此同时,你在flow_from_directory
中定义生成器时,也没有设置image_size
,默认设置为(256, 256)
,color_mode = rgb
。所以,看起来可能存在输入形状不匹配的问题,你需要检查一下。也请参考这个。
其次,正如你提到的,你有8个类别要分类,并为模型设置了损失函数categorical_crossentropy
,那么你的最后一层应该更像是这样:
# head_model = Dense(1, activation="sigmoid")(head_model) # 否head_model = Dense(8, activation="softmax")(head_model) # 是
在我们确保这些细节后,模型应该能够按预期运行。
from tensorflow.keras.applications import ResNet50from tensorflow.keras.layers import Dense, Dropout, Flattenfrom tensorflow.keras import Model base_model = ResNet50(weights='imagenet', include_top=True)head_model = base_model.get_layer("conv5_block1_1_conv").outputhead_model = Dense(512, activation="relu")(head_model)head_model = Dropout(0.5)(head_model)head_model = Flatten()(head_model)head_model = Dense(8, activation="softmax")(head_model)model = Model(inputs=base_model.input, outputs=head_model)import numpy as np img = np.random.randint(0, 255, size=(2, 224, 224, 3))model.compile(optimizer= 'adam', loss='categorical_crossentropy', metrics=['accuracy'])pred = model.predict(img)pred.shape(2, 8)