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

训练EfficientNetB3遇维度不匹配ValueError,求排查代码问题

代码错误分析与修正方案

1. GLCM特征与图像拼接的维度不匹配错误

在compute_glcm_transformed_image函数中,img_resized是2维数组(300,300),而glcm_features是greycomatrix输出ravel后的1维数组(65536,)。你直接用np.concatenate((img_resized, glcm_features), axis=-1)拼接时,2维数组的axis=-1是列维度(长度300),1维数组的axis=-1是自身长度(65536),两者维度无法对齐,导致返回的transformed_image形状混乱,最终data_list中元素维度不一致,触发报错。

修正方案:
如果要将GLCM特征与图像结合,需把GLCM特征转换为和图像同维度的特征图,再进行通道拼接:

def compute_glcm_transformed_image(image_path, target_size=(300, 300)):
    img = io.imread(image_path)
    img_gray = color.rgb2gray(img)
    img_resized = resize(img_gray, target_size)
    # 把2维灰度图扩展为单通道:(300,300) → (300,300,1)
    img_resized = np.expand_dims(img_resized, axis=-1)
    
    glcm = feature.greycomatrix((img_resized * 255).astype(np.uint8)[...,0], [5], [0], 256, symmetric=True, normed=True)
    glcm_features = np.ravel(glcm)
    # 将GLCM特征转为同尺寸单通道特征图(示例用均值填充,也可按需设计)
    glcm_feature_map = np.full((target_size[0], target_size[1], 1), glcm_features.mean())
    
    # 拼接为(300,300,2)的多通道输入
    return np.concatenate((img_resized, glcm_feature_map), axis=-1)

2. 未定义变量提前使用的逻辑错误

遍历图像的循环中,你提前使用了img_height、img_width、channels、len(glcm_features)这些变量,但这些变量都是在循环结束、X生成之后才定义的,会直接触发NameError;即使你手动提前定义过,也会因形状不匹配导致后续数据维度混乱。

修正方案:
提前定义固定参数,直接使用处理后图像的形状:

# 提前定义目标尺寸
img_height, img_width = 300, 300
data_list = []
labels_list = []

for class_folder in os.listdir(main_directory):
    class_path = os.path.join(main_directory, class_folder)
    if os.path.isdir(class_path):
        for filename in os.listdir(class_path):
            if filename.endswith(".jpg") or filename.endswith(".png"):
                image_path = os.path.join(class_path, filename)
                transformed_image = compute_glcm_transformed_image(image_path)
                # 直接添加处理后的图像,无需额外reshape
                data_list.append(transformed_image)
                labels_list.append(class_folder)

3. 输入形状与EfficientNetB3不兼容的错误

EfficientNetB3要求输入为(height, width, channels)格式的多通道图像,而你当前拼接后的输入是(300, 300 + 65536)的2维数组,完全不符合CNN模型的输入规范,会导致模型输入层与数据不匹配。

推荐修正方案:使用多输入模型
分别传入灰度图像和GLCM特征,让模型同时学习视觉特征和纹理特征:

# 1. 图像输入分支(适配EfficientNetB3的3通道要求)
image_input = Input(shape=(img_height, img_width, 1), name='image_input')
# 将单通道转为3通道
image_input_3ch = tf.keras.layers.Conv2D(3, (1,1))(image_input)
base_model = EfficientNetB3(weights='imagenet', include_top=False, input_tensor=image_input_3ch)
x_image = base_model.output
x_image = GlobalAveragePooling2D()(x_image)

# 2. GLCM特征输入分支
glcm_input = Input(shape=(65536,), name='glcm_input')
x_glcm = Dense(256, activation='relu')(glcm_input)
x_glcm = Dropout(0.2)(x_glcm)

# 3. 拼接两个分支输出
x = tf.keras.layers.concatenate([x_image, x_glcm])
x = Dense(1024, activation='relu')(x)
x = Dense(512, activation='relu')(x)
# 替换为实际类别数量
num_classes = len([f for f in os.listdir(main_directory) if os.path.isdir(os.path.join(main_directory, f))])
preds = Dense(num_classes, activation='softmax')(x)

model = Model(inputs=[image_input, glcm_input], outputs=preds)

4. 其他潜在问题

  • 标签处理:labels_list是字符串类名,建议转换为整数编码,避免sparse_categorical_crossentropy的潜在问题:
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y = le.fit_transform(labels_list)
  • EfficientNetB3默认输入尺寸为224x224,若使用300x300需确保所有输入图像形状一致。

内容的提问来源于stack exchange,提问作者Arjun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:11:06