You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

加载VGG19模型遇AttributeError:'list'无'shape'属性的解决求助

问题:VGG19二分类模型加载时出现AttributeError: 'list' object has no attribute 'shape'

问题背景

使用自有JPG图像和包含图像ID、二分类标签(0/1)的Pandas DataFrame训练VGG19二分类模型,训练及保存过程无异常,但加载模型时触发上述错误。尝试过保存为.json和.h5格式均未解决问题。

环境信息

Python: 3.10
keras: 3.1.1
tensorflow: 2.16.2
OS: Ubuntu 22.04

训练与保存代码

import os
import pandas as pd
import tensorflow as tf
from keras import losses
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.optimizers import Adam
from keras.metrics import Precision, Recall
from keras.applications.vgg19 import VGG19

IMG_HEIGHT = 224
IMG_WIDTH = 224
MODELS_INPUT_SHAPE = (IMG_HEIGHT, IMG_WIDTH, 3)
NUM_CLASSES = 2
EPOCHS = 1
BATCH_SIZE = 32

train_dataset = pd.read_csv('data/train-data.csv')
train_images_location = 'data/train-images/'

# 图像预处理辅助函数
def preprocess_image(image):
    image = tf.io.read_file(image)
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize(image, [224, 224])
    image = tf.cast(image, tf.float32) / 255.0  # 归一化像素值到[0,1]
    return image

train_image_paths = [os.path.join('data/train-images', img_path) for img_path in train_dataset['id']]
one_hot_labels = tf.one_hot(train_dataset['T1'], NUM_CLASSES)
train_dataset = tf.data.Dataset.from_tensor_slices((train_image_paths, one_hot_labels))
train_dataset = train_dataset.map(lambda x, y: (preprocess_image(x), y))
train_dataset = train_dataset.batch(BATCH_SIZE)

models = {
    'vgg19_binary.keras': VGG19(weights='imagenet', include_top=False, input_shape=MODELS_INPUT_SHAPE)
}

for model_name in models.keys():
    base_model = models[model_name]

    # 冻结预训练模型层
    for layer in base_model.layers:
        layer.trainable = False

    # 构建Sequential模型
    model = Sequential()
    model.add(base_model)
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dense(128, activation='relu'))
    model.add(Dense(64, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(16, activation='relu'))
    model.add(Dense(NUM_CLASSES, activation='sigmoid'))
    
    # 编译模型
    model.compile(loss=losses.BinaryCrossentropy(),
                  optimizer=Adam(learning_rate=0.0001),
                  metrics=['accuracy', Precision(), Recall()])

    # 训练模型
    model.fit(train_dataset, epochs=EPOCHS)

    # 保存模型
    model_location = 'models/'+model_name
    model.save(model_location)

模型加载代码

from keras.models import load_model

vgg19_model_location = 'models/vgg19_binary.keras'
vgg19_model = load_model(vgg19_model_location)

完整报错信息

Traceback (most recent call last):
  File "/home/javier/PycharmProjects/thesis/thesis/binary_early_fusion.py", line 15, in <module>
    loaded_model = model_from_json(loaded_model_json)
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/models/model.py", line 586, in model_from_json
    return serialization_lib.deserialize_keras_object(
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/saving/serialization_lib.py", line 711, in deserialize_keras_object
    instance = cls.from_config(inner_config)
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/models/sequential.py", line 335, in from_config
    model.add(layer)
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/models/sequential.py", line 116, in add
    self._maybe_rebuild()
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/models/sequential.py", line 135, in _maybe_rebuild
    self.build(input_shape)
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/layers/layer.py", line 223, in build_wrapper
    original_build_method(*args, **kwargs)
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/models/sequential.py", line 176, in build
    x = layer(x)
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/utils/traceback_utils.py", line 122, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/home/javier/PycharmProjects/thesis/venv/lib/python3.10/site-packages/keras/src/layers/reshaping/flatten.py", line 72, in compute_output_spec
    output_shape = self.compute_output_shape(inputs.shape)
AttributeError: Exception encountered when calling Flatten.call().

'list' object has no attribute 'shape'

Arguments received by Flatten.call():
  • args=(['<KerasTensor shape=(None, 7, 7, 512), dtype=float32, sparse=False, name=keras_tensor_70>'],)
  • kwargs=<class 'inspect._empty'>

解决方案

该问题源于Keras 3.x序列化包含预训练模型的Sequential模型时的兼容性问题:VGG19的输出被序列化为列表而非张量,导致Flatten层无法识别形状。以下是三种可行解决方法:

方法1:改用Functional API构建模型

替换原Sequential模型构建逻辑,使用Functional API可以避免序列化时的输出格式异常:

# 替换原Sequential模型构建代码
inputs = tf.keras.Input(shape=MODELS_INPUT_SHAPE)
x = base_model(inputs, training=False)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
x = Dense(128, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dense(32, activation='relu')(x)
x = Dense(16, activation='relu')(x)
outputs = Dense(NUM_CLASSES, activation='sigmoid')(x)
model = tf.keras.Model(inputs, outputs)

方法2:保存前显式设置模型输入形状

在保存模型前,手动调用build()方法指定输入形状,确保序列化时能正确识别张量结构:

# 在model.save()前添加以下代码
model.build((None,) + MODELS_INPUT_SHAPE)
model.save(model_location)

方法3:手动重建模型并加载权重

若不想重新训练,可先重建与原模型完全一致的结构,再单独加载权重:

# 1. 重建模型结构
base_model = VGG19(weights='imagenet', include_top=False, input_shape=MODELS_INPUT_SHAPE)
for layer in base_model.layers:
    layer.trainable = False

model = Sequential()
model.add(base_model)
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dense(NUM_CLASSES, activation='sigmoid'))

# 2. 加载已保存的权重
model.load_weights('models/vgg19_binary.keras')

内容的提问来源于stack exchange,提问作者Javier Romero.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:03:12