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

TensorFlow中融合图像与Landmark坐标两种不同形状输入的方法

多输入模型融合与训练解决方案

问题分析

你之前的尝试存在几个关键问题:

  • 关键点输入层的形状错误:landmarks_x_train的形状是(120,478,3),但你定义的Input(shape=(landmarks_x_train.shape[1],))只对应了478这个维度,漏掉了坐标的3个通道
  • 关键点输入未做维度压缩:ResNet的输出是二维向量(batch_size, features),而原始关键点输入是三维(batch_size,478,3),两者维度不匹配,无法直接拼接
  • 融合后缺少最终分类层:你把拼接后的结果直接作为输出,但原来的任务是7分类,需要在拼接后添加全连接层完成分类
  • 训练时输入格式错误:多输入模型需要传入对应输入列表,而不是单一输入

完整实现步骤

1. 调整ResNet模型,获取特征输出

首先修改ResNet50模型,去掉顶层的分类层,保留特征提取部分:

# 重新定义模型,只保留特征提取部分,输出特征向量
def get_resnet_feature_model():
    base_model = ResNet50(include_top=False, input_shape=(224,224,1), weights=None)
    x = base_model.output
    # 全局平均池化得到特征向量
    x = GlobalAveragePooling2D()(x)
    # 可选:加全连接层增强特征表达
    x = Dense(256, activation='relu')(x)
    return Model(inputs=base_model.input, outputs=x)

# 获取特征提取模型
image_model = get_resnet_feature_model()

2. 构建关键点输入分支

对关键点输入进行处理,将三维数据压缩为二维特征向量:

from tensorflow.keras.layers import Input, Flatten, Dense, concatenate
from tensorflow.keras.models import Model

# 关键点输入层,匹配(478,3)的形状
landmarks_input = Input(shape=(478,3), name='landmarks_input')
# 压平三维数据,也可以用GlobalAveragePooling1D替代
x = Flatten()(landmarks_input)
# 加全连接层提取关键点特征
x = Dense(128, activation='relu')(x)
landmarks_feature = Dense(64, activation='relu')(x)

3. 融合两个分支并构建完整模型

将图像特征和关键点特征拼接,添加最终分类层:

# 获取图像分支的输出
image_feature = image_model.output

# 拼接两个特征向量
combined = concatenate([image_feature, landmarks_feature], name='combined_features')

# 添加分类层
x = Dense(128, activation='relu')(combined)
output = Dense(7, activation='softmax', name='classification_output')(x)

# 构建多输入模型
final_model = Model(inputs=[image_model.input, landmarks_input], outputs=output)

4. 编译模型

final_model.compile(optimizer='adam',
                    loss='sparse_categorical_crossentropy', # 标签是整数用这个,one-hot编码用categorical_crossentropy
                    metrics=['accuracy'])

5. 训练模型(两种场景)

场景1:直接使用numpy数组训练

如果你的标签是y_train(形状(120,)或(120,7)),直接传入输入列表:

# 假设y_train是训练标签,y_val是验证标签
final_model.fit(
    [X_train, landmarks_x_train],
    y_train,
    validation_data=([X_val, landmarks_x_val], y_val),
    epochs=20,
    batch_size=8
)

场景2:结合ImageDataGenerator处理图像增强

如果需要用ImageDataGenerator做图像增强,需要自定义生成器来同时输出图像和关键点数据:

from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np

# 初始化图像生成器
datagen = ImageDataGenerator(rotation_range=10, width_shift_range=0.1, height_shift_range=0.1)

# 自定义生成器,结合图像增强和关键点数据
def multi_input_generator(image_generator, x_images, x_landmarks, y):
    gen = image_generator.flow(x_images, y, batch_size=8)
    while True:
        image_batch, y_batch = next(gen)
        # 获取当前batch的索引,取出对应的关键点数据
        idx = gen.batch_index
        if idx == 0:
            indices = np.arange(len(x_images))
            np.random.shuffle(indices)
        batch_indices = indices[idx*gen.batch_size : (idx+1)*gen.batch_size]
        landmarks_batch = x_landmarks[batch_indices]
        yield [image_batch, landmarks_batch], y_batch

# 创建训练和验证生成器
train_gen = multi_input_generator(datagen, X_train, landmarks_x_train, y_train)
val_gen = multi_input_generator(ImageDataGenerator(), X_val, landmarks_x_val, y_val)

# 训练
final_model.fit(
    train_gen,
    steps_per_epoch=len(X_train)//8,
    validation_data=val_gen,
    validation_steps=len(X_val)//8,
    epochs=20
)

注意事项

  • 如果你的原始ResNet模型已经包含顶层分类层,需要先移除,否则特征维度会是(None,7),拼接后特征表达能力不足
  • 关键点分支的结构可以根据任务调整,比如用LSTM、1D卷积代替Flatten,更适合序列类的关键点数据
  • 训练时要确保输入列表的顺序和模型定义的inputs顺序完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 10:26:03