【问题标题】:TensorFlow - expected global_average_pooling2d_1_input to have shape (1, 1, 2048) but got array with shape (7, 7, 2048)TensorFlow - 预期 global_average_pooling2d_1_input 的形状为 (1, 1, 2048) 但得到的数组形状为 (7, 7, 2048)
【发布时间】:2018-07-17 20:36:55
【问题描述】:

我对 TensorFlow 和图像分类还很陌生,所以我可能缺少关键知识,这可能就是我面临这个问题的原因。

我在 TensorFlow 中构建了一个 ResNet50 模型,用于犬种的图像分类,使用 ImageNet 库,我已经成功训练了一个可以检测各种犬种的神经网络。

我现在想将一张狗的随机图像传递给我的模型,让它输出它认为的狗品种的输出。但是,当我运行这个函数dog_breed_predictor("dogImages/dogImages/valid/016.Beagle/Beagle_01126.jpg") 时,当它尝试执行Resnet50_model.predict(bottleneck_feature) 行时,我得到了错误expected global_average_pooling2d_1_input to have shape (1, 1, 2048) but got array with shape (7, 7, 2048),我不知道如何解决这个问题。

这是代码。我已经提供了我认为与问题相关的所有内容。

#import tensorflow as tf, etc.

from sklearn.datasets import load_files
np_utils = tf.keras.utils

# define function to load train, test, and validation datasets
def load_dataset(path):
    data = load_files(path)
    dog_files = np.array(data['filenames'])
    dog_targets = np_utils.to_categorical(np.array(data['target']), 133)
    return dog_files, dog_targets

# load train, test, and validation datasets
train_files, train_targets = load_dataset('dogImages/dogImages/train')
valid_files, valid_targets = load_dataset('dogImages/dogImages/valid')
test_files, test_targets = load_dataset('dogImages/dogImages/test')

#define Resnet50 model
Resnet50_model = ResNet50(weights="imagenet")

def path_to_tensor(img_path):
    #loads RGB image as PIL.Image.Image type
    img = image.load_img(img_path, target_size=(224, 224))
    #convert PIL.Image.Image type to 3D tensor with shape (224, 224, 3)
    x = image.img_to_array(img)
    #convert 3D tensor into 4D tensor with shape (1, 224, 224, 3)
    return np.expand_dims(x, axis=0)

from keras.applications.resnet50 import preprocess_input, decode_predictions

def ResNet50_predict_labels(img_path):
    #returns prediction vector for image located at img_path
    img = preprocess_input(path_to_tensor(img_path))
    return np.argmax(Resnet50_model.predict(img))

###returns True if a dog is detected in the image stored at img_path
def dog_detector(img_path):
    prediction = ResNet50_predict_labels(img_path)
    return ((prediction <= 268) & (prediction >= 151))

###Obtain bottleneck features from another pre-trained CNN
bottleneck_features = np.load("bottleneck_features/DogResnet50Data.npz")
train_DogResnet50 = bottleneck_features["train"]
valid_DogResnet50 = bottleneck_features["valid"]
test_DogResnet50 = bottleneck_features["test"]

###Define your architecture
Resnet50_model = tf.keras.Sequential()
Resnet50_model.add(tf.keras.layers.GlobalAveragePooling2D(input_shape=train_DogResnet50.shape[1:]))
Resnet50_model.add(tf.contrib.keras.layers.Dense(133, activation="softmax"))

Resnet50_model.summary()

###Compile the model
Resnet50_model.compile(loss="categorical_crossentropy", optimizer="rmsprop", metrics=["accuracy"])
###Train the model
checkpointer = tf.keras.callbacks.ModelCheckpoint(filepath="saved_models/weights.best.ResNet50.hdf5",
                                                 verbose=1, save_best_only=True)

Resnet50_model.fit(train_DogResnet50, train_targets,
                  validation_data=(valid_DogResnet50, valid_targets),
                  epochs=20, batch_size=20, callbacks=[checkpointer])

###Load the model weights with the best validation loss.
Resnet50_model.load_weights("saved_models/weights.best.ResNet50.hdf5")

###Calculate classification accuracy on the test dataset
Resnet50_predictions = [np.argmax(Resnet50_model.predict(np.expand_dims(feature, axis=0))) for feature in test_DogResnet50]

#Report test accuracy
test_accuracy = 100*np.sum(np.array(Resnet50_predictions)==np.argmax(test_targets, axis=1))/len(Resnet50_predictions)
print("Test accuracy: %.4f%%" % test_accuracy)

from extract_bottleneck_features import * #separate .py file

def dog_breed(img_path):
    #extract bottleneck features
    bottleneck_feature = extract_Resnet50(path_to_tensor(img_path))
    #obtain predicted vector
    predicted_vector = Resnet50_model.predict(bottleneck_feature)
    #return dog breed that is predicted by the model
    return dog_names[np.argmax(predicted_vector)]

def dog_breed_predictor(img_path):
    #determine the predicted dog breed
    breed = dog_breed(img_path)
    #display the image
    img = cv2.imread(img_path)
    cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.imshow(cv_rgb)
    plt.show()
    #display relevant predictor result
    if dog_detector(img_path):
        print("This is a dog and its breed is: " + str(breed))
    elif face_detector(img_path):
        print("This is a human but it looks like a: " + str(breed))
    else:
        print("I don't know what this is.")

dog_breed_predictor("dogImages/dogImages/valid/016.Beagle/Beagle_01126.jpg") #shape error occurs here

extract_bottleneck_features.py 中的函数:

def extract_Resnet50(tensor):
    from keras.applications.resnet50 import ResNet50, preprocess_input
    return ResNet50(weights='imagenet', include_top=False).predict(preprocess_input(tensor))

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:

    为什么不使用pooling == 'avg'pooling == 'max'include_top=False 作为调用ResNet 的参数。它将处理您的池化层。使用这些参数调用函数后,您可以删除池化层。 来自source code

    if include_top:
        x = Flatten()(x)
        x = Dense(classes, activation='softmax', name='fc1000')(x)
    else:
        if pooling == 'avg':
            x = GlobalAveragePooling2D()(x)
        elif pooling == 'max':
            x = GlobalMaxPooling2D()(x)
    

    【讨论】:

    • 我已将其更改为“include_top=True”,但现在错误已更改为expected global_average_pooling2d_1_input to have 4 dimensions, but got array with shape (1, 1000)。有什么想法吗?
    • 哦,我没有意识到您正在训练自己的分类器,我会更新我的答案,您应该将它与 include_top=False 一起使用
    • 所以我需要从我的模型定义中删除 Resnet50_model.add(tf.keras.layers.GlobalAveragePooling2D(input_shape=train_DogResnet50.shape[1:])),而是在我的 ResNet 调用中添加 pooling="avg"pooling="max"
    【解决方案2】:

    首先有两个模型命名为Resnet50_model。一个是ResNet50()把图片归类为狗,另一个你自己设置

    ###Define your architecture
    Resnet50_model = tf.keras.Sequential()
    Resnet50_model.add(tf.keras.layers.GlobalAveragePooling2D(input_shape=train_DogResnet50.shape[1:]))
    Resnet50_model.add(tf.contrib.keras.layers.Dense(133, activation="softmax"))
    

    正在从ResNet50() 调整为狗的种类,你应该重命名它。

    bottleneck_features/DogResnet50Data.npz 加载的数据,维度为 (1,1,2048),而您从 extract_Resnet50(path_to_tensor(img_path)) 获得的数据,维度为 (1,2048),您可以编辑为

    def Resnet50_predict_breed(img_path):
        # extract bottleneck features
        bottleneck_feature = np.expand_dims(np.expand_dims(
            extract_Resnet50(path_to_tensor(img_path)), axis=0), axis=0)
        ...
    

    或者你可以得到你自己的bottleneck_features

    def paths_to_tensor(img_paths):
        list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
        return np.vstack(list_of_tensors)
    
    def extract_Resnet50(tensor):
        from keras.applications.resnet50 import ResNet50, preprocess_input
        ResNet50(weights='imagenet', input_shape=(224,224,3), pooling='avg', include_top=False).predict(preprocess_input(tensor))
    
    train_Resnet50 = extract_Resnet50(paths_to_tensor(train_files))[:,np.newaxis,np.newaxis,:]
    valid_Resnet50 = extract_Resnet50(paths_to_tensor(valid_files))[:,np.newaxis,np.newaxis,:]
    test_Resnet50 = extract_Resnet50(paths_to_tensor(test_files))[:,np.newaxis,np.newaxis,:]
    
    def Resnet50_predict_breed(img_path):
        # extract bottleneck features
        bottleneck_feature = np.expand_dims(np.expand_dims(
            extract_Resnet50(path_to_tensor(img_path)), axis=0), axis=0)
        ...
    

    【讨论】:

      猜你喜欢
      • 2018-12-16
      • 1970-01-01
      • 2020-05-14
      • 2019-05-09
      • 2019-03-11
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      相关资源
      最近更新 更多