You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Keras中构建含图像与数值双输入的神经网络?

结合图像与数值输入的Keras多分支模型实现

嘿,你的思路完全正确!当需要同时利用图像视觉特征结构化数值特征时,单靠CNN确实搞不定,把数值输入接入全连接层(或者和CNN提取的特征融合后再走全连接)是这类多模态任务的标准操作。Keras的Functional API正好能完美支持这种多输入架构,我给你一步步拆解实现:

1. 改造现有CNN为图像分支

你给出的代码是Sequential风格的,首先咱们把它转成Functional API的图像分支(Sequential只能处理单输入,多输入必须用Functional):

from keras.models import Model
from keras.layers import Input, Lambda, Conv2D, MaxPooling2D, Flatten, Dense, Concatenate
from keras.optimizers import Adam

# 图像分支:沿用你原来的归一化逻辑和后续CNN层
image_input = Input(shape=(66, 200, 3), name='image_input')
# 你原来的像素归一化Lambda层
x = Lambda(lambda x: x/127.5 - 1.0)(image_input)
# 这里补全你未写完的CNN层(示例参考常见的自动驾驶图像特征提取结构)
x = Conv2D(24, (5,5), activation='relu', strides=(2,2))(x)
x = Conv2D(36, (5,5), activation='relu', strides=(2,2))(x)
x = Conv2D(48, (5,5), activation='relu', strides=(2,2))(x)
x = Conv2D(64, (3,3), activation='relu')(x)
x = Conv2D(64, (3,3), activation='relu')(x)
# 把CNN的2D输出展平为一维特征向量(也可用GlobalAveragePooling2D替代,按需选择)
image_features = Flatten()(x)

2. 构建数值特征分支

假设你的数值输入是N个连续型特征(比如速度、角度、环境参数等),咱们单独做一个轻量分支:

# 数值输入:假设输入是5维的结构化数值
numeric_input = Input(shape=(5,), name='numeric_input')
# 可选:给数值特征加几层全连接做特征变换(如果数值维度高或需要非线性变换)
y = Dense(16, activation='relu')(numeric_input)
y = Dense(8, activation='relu')(y)
numeric_features = y

3. 融合分支并构建输出层

把图像特征和数值特征拼接后,接入全连接层,最后用tanh激活匹配你需要的-1到1输出范围:

# 拼接两个分支的特征向量
combined_features = Concatenate()([image_features, numeric_features])
# 后续全连接层,可根据任务复杂度调整层数和神经元数
z = Dense(100, activation='relu')(combined_features)
z = Dense(50, activation='relu')(z)
z = Dense(10, activation='relu')(z)
# 输出层:tanh激活刚好输出-1到1的数值
output = Dense(1, activation='tanh', name='output')(z)

# 定义完整模型:输入为图像+数值,输出为预测结果
model = Model(inputs=[image_input, numeric_input], outputs=output)

4. 编译与训练

编译和训练逻辑和普通模型一致,只是需要同时传入图像和数值两类输入:

# 编译模型,回归任务用MSE损失,搭配Adam优化器
model.compile(optimizer=Adam(learning_rate=0.0001), loss='mse')

# 假设你的训练数据结构如下:
# X_img:形状为(样本数, 66, 200, 3)的图像数组
# X_num:形状为(样本数, 5)的数值数组
# y:形状为(样本数, 1)的标签数组(取值-1到1)
model.fit([X_img, X_num], y, epochs=50, batch_size=32, validation_split=0.2)

额外小提示

  • 如果数值特征维度极小(比如1-2个),可以跳过数值分支的Dense层,直接把原始数值和图像特征拼接
  • 可以给两个分支分别加Dropout层,降低过拟合风险
  • 推理时需同时传入图像和数值输入,比如:model.predict([test_img_batch, test_num_batch])

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

火山引擎 最新活动