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

Keras实现Inception模块拼接报Concatenate无compile属性错误

问题描述

参考IEEE收录的相关论文搭建卷积神经网络,尝试对Inception模块输出的特征图做拼接操作时,编写代码运行抛出属性错误。
原实现代码如下:

model_1 = Sequential()
model_1.add(Conv2D(3,kernel_size=(3,3), strides=(1),activation='relu',input_shape=(48,48,3),padding='same'))
model_1.add(Conv2D(3,kernel_size=(7,1), strides=(1), activation='relu',padding='same'))
model_1.add(Conv2D(3,kernel_size=(1,7), strides=(1), activation='relu',padding='same'))
model_1.add(BatchNormalization())
model_1.add(MaxPool2D(pool_size=(2, 2), strides=(2)))
model_1.add(Dropout(rate=0.2))

model_2 = Sequential()
model_2.add(Conv2D(64,kernel_size=(3,1), strides=(1), activation='relu',padding='same'))
model_2.add(Conv2D(64,kernel_size=(1,3), strides=(1), activation='relu',padding='same'))
model_2.add(Conv2D(64,kernel_size=(1,7), strides=(1), activation='relu',padding='same'))
model_2.add(Conv2D(64,kernel_size=(7,1), strides=(1), activation='relu',padding='same'))
model_2.add(BatchNormalization())

model_3 = Sequential()
model_3.add(BatchNormalization())
model_3.add(MaxPool2D(pool_size=(2, 2), strides=(2)))
model_3.add(Dropout(rate=0.2))
model_3.add(Conv2D(128,kernel_size=(3,3), strides=(1), activation='relu'))
model_3.add(Conv2D(128,kernel_size=(3,3), strides=(1), activation='relu'))
model_3.add(MaxPool2D(pool_size=(2, 2), strides=(2)))
model_3.add(Dropout(rate=0.3))
model_3.add(Dense(NUM_CLASS))
model_3.add(Dropout(rate=0.4))
model_3.add(Dense(NUM_CLASS, activation='softmax'))

#Concatenate
merged = Concatenate([model_1,model_2])
result =  Concatenate([merged,model_3])

result.compile(optimizer="adam",metrics=["accuracy"])
result.summary()

网络结构参考示意图:
网络结构示意图

运行代码抛出的错误信息:

AttributeError: 'Concatenate' object has no attribute 'compile'
错误产生原因
  • 核心错误是混淆了Keras中的层对象和模型对象:Concatenate是用于张量拼接的网络层类,实例化后得到的是层对象,仅负责完成张量拼接计算,不具备compile、summary、fit等仅模型对象才有的方法,直接对Concatenate实例调用编译方法必然报错。
  • 多分支Inception结构无法通过纯Sequential模型实现:Sequential是单输入单输出的线性堆叠结构,不支持多分支张量拼接的拓扑逻辑;且原代码直接将Sequential模型实例作为参数传入Concatenate,没有传递实际计算的张量,逻辑完全不成立。
  • 原代码存在多处维度不匹配隐患:分支1做了步长为2的最大池化,输出特征图尺寸为输入的1/2,分支2无池化操作,输出特征图尺寸和输入一致,二者空间维度不匹配无法直接拼接;卷积层输出为3维特征图,直接接全连接Dense层也会报维度错误。
修复方案

使用Keras函数式API构建多分支拓扑,修复所有维度匹配问题,最终通过Model类封装完整可编译的模型:

  1. 定义全局统一的输入张量,所有分支从该输入开始前向计算
  2. 调整各分支层参数,保证待拼接的特征图宽高维度完全一致,仅在通道维度做拼接
  3. 按正确语法调用Concatenate层完成张量拼接,拼接后继续堆叠后续卷积、分类层
  4. 在卷积层和全连接层之间补充Flatten层,完成特征维度展平
  5. 绑定输入张量和最终输出张量,实例化Model对象后再执行编译、summary操作

修复后的可运行代码如下:

from tensorflow.keras.models import Model
from tensorflow.keras.layers import (
    Input, Conv2D, BatchNormalization, MaxPool2D,
    Dropout, Dense, Concatenate, Flatten
)

# 定义全局输入,按任务设置类别数
input_tensor = Input(shape=(48, 48, 3))
NUM_CLASS = 10  # 替换为自身任务的实际类别数

# 分支1
b1 = Conv2D(3, kernel_size=(3,3), strides=1, activation='relu', padding='same')(input_tensor)
b1 = Conv2D(3, kernel_size=(7,1), strides=1, activation='relu', padding='same')(b1)
b1 = Conv2D(3, kernel_size=(1,7), strides=1, activation='relu', padding='same')(b1)
b1 = BatchNormalization()(b1)
b1 = MaxPool2D(pool_size=(2,2), strides=2, padding='same')(b1)
b1_out = Dropout(rate=0.2)(b1)

# 分支2
b2 = Conv2D(64, kernel_size=(3,1), strides=1, activation='relu', padding='same')(input_tensor)
b2 = Conv2D(64, kernel_size=(1,3), strides=1, activation='relu', padding='same')(b2)
b2 = Conv2D(64, kernel_size=(1,7), strides=1, activation='relu', padding='same')(b2)
b2 = Conv2D(64, kernel_size=(7,1), strides=1, activation='relu', padding='same')(b2)
b2 = BatchNormalization()(b2)
# 补充池化层,对齐和分支1的特征图尺寸
b2 = MaxPool2D(pool_size=(2,2), strides=2, padding='same')(b2)
b2_out = Dropout(rate=0.2)(b2)

# 第一次拼接两个Inception分支
merged = Concatenate()([b1_out, b2_out])

# 拼接后的后续分类网络
x = BatchNormalization()(merged)
x = MaxPool2D(pool_size=(2,2), strides=2)(x)
x = Dropout(rate=0.2)(x)
x = Conv2D(128, kernel_size=(3,3), strides=1, activation='relu')(x)
x = Conv2D(128, kernel_size=(3,3), strides=1, activation='relu')(x)
x = MaxPool2D(pool_size=(2,2), strides=2)(x)
x = Dropout(rate=0.3)(x)
# 补充Flatten层展平特征,适配全连接层输入要求
x = Flatten()(x)
x = Dense(NUM_CLASS)(x)
x = Dropout(rate=0.4)(x)
output_tensor = Dense(NUM_CLASS, activation='softmax')(x)

# 构建完整模型
result = Model(inputs=input_tensor, outputs=output_tensor)
result.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
result.summary()

注:如果你的标签是整数型而非独热编码,需要将loss参数替换为sparse_categorical_crossentropy。

内容的提问来源于stack exchange,提问作者LIM XIN ROY

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:24:34