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

ResNet18兄弟姐妹检测:如何调整数据集标签匹配图片对需求

问题根源分析

你现在遇到的核心问题是**flow_from_directory的默认逻辑和你的任务需求不匹配**:这个API是为「单张图片对应一个样本/标签」的场景设计的,但你的任务是「两张图片组成一个样本,对应一个是否为兄弟姐妹的标签」。

你当前的文件夹结构是按类别(false/siblings)存放单张图片,所以flow_from_directory会给每张单独的图片打上所在文件夹的标签,最终classes数组的长度等于图片总数,而不是你需要的图片对数量。

解决方案

下面提供两种可行的方案,你可以根据自己的实际情况选择:

方案一:自定义图片对数据生成器(推荐)

这种方式最灵活,完全贴合你的「双输入图片对」任务需求,步骤如下:

1. 重新组织数据集结构

创建这样的文件夹层级:

dataset/
├─ train/
│  ├─ sample_0/  # 标签0:非兄弟姐妹
│  │  ├─ img1.jpg
│  │  └─ img2.jpg
│  ├─ sample_1/  # 标签1:兄弟姐妹
│  │  ├─ img1.jpg
│  │  └─ img2.jpg
│  ├─ sample_2/  # 标签0:非兄弟姐妹
│  │  ├─ img1.jpg
│  │  └─ img2.jpg
│  └─ sample_3/  # 标签1:兄弟姐妹
│     ├─ img1.jpg
│     └─ img2.jpg
└─ train_labels.csv  # 记录每个样本的标签

train_labels.csv的内容示例:

sample_name,label
sample_0,0
sample_1,1
sample_2,0
sample_3,1

2. 实现自定义数据生成器

继承Keras的Sequence类,读取每个样本文件夹下的两张图片,返回双输入和对应标签:

import numpy as np
import pandas as pd
import os
from tensorflow.keras.utils import Sequence
from tensorflow.keras.preprocessing.image import load_img, img_to_array

class SiblingPairGenerator(Sequence):
    def __init__(self, data_dir, labels_csv, target_size=(28,28), batch_size=32, shuffle=True):
        self.data_dir = data_dir
        self.labels_df = pd.read_csv(labels_csv)
        self.target_size = target_size
        self.batch_size = batch_size
        self.shuffle = shuffle
        self.indexes = np.arange(len(self.labels_df))
        if self.shuffle:
            np.random.shuffle(self.indexes)

    def __len__(self):
        # 计算每个epoch的批次数
        return int(np.ceil(len(self.labels_df) / self.batch_size))

    def __getitem__(self, index):
        # 获取当前批次的样本索引
        batch_indexes = self.indexes[index*self.batch_size : (index+1)*self.batch_size]
        batch_imgs1, batch_imgs2, batch_labels = [], [], []

        for idx in batch_indexes:
            sample_row = self.labels_df.iloc[idx]
            sample_path = os.path.join(self.data_dir, sample_row['sample_name'])
            # 读取两张图片并预处理
            img1 = load_img(os.path.join(sample_path, 'img1.jpg'), target_size=self.target_size)
            img2 = load_img(os.path.join(sample_path, 'img2.jpg'), target_size=self.target_size)
            img1 = img_to_array(img1) / 255.0  # 归一化到0-1区间
            img2 = img_to_array(img2) / 255.0
            # 添加到批次
            batch_imgs1.append(img1)
            batch_imgs2.append(img2)
            batch_labels.append(sample_row['label'])

        # 转换为numpy数组返回
        return [np.array(batch_imgs1), np.array(batch_imgs2)], np.array(batch_labels)

    def on_epoch_end(self):
        # 每个epoch结束后打乱样本顺序
        if self.shuffle:
            np.random.shuffle(self.indexes)

3. 用生成器训练模型

假设你的ResNet18是双输入结构,训练代码示例:

from tensorflow.keras.layers import Input, GlobalAveragePooling2D, concatenate, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.applications import ResNet18  # 注意:如果是自定义ResNet18,替换成你的实现

# 构建双输入模型
input1 = Input(shape=(28,28,3))
input2 = Input(shape=(28,28,3))
# 共享ResNet18特征提取层
base_model = ResNet18(include_top=False, input_shape=(28,28,3))
x1 = GlobalAveragePooling2D()(base_model(input1))
x2 = GlobalAveragePooling2D()(base_model(input2))
# 合并特征并输出分类结果
merged = concatenate([x1, x2])
output = Dense(1, activation='sigmoid')(merged)
model = Model(inputs=[input1, input2], outputs=output)

# 编译并训练
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
train_generator = SiblingPairGenerator(
    data_dir='dataset/train',
    labels_csv='dataset/train_labels.csv',
    target_size=(28,28),
    batch_size=32
)
model.fit(train_generator, epochs=10)

方案二:拼接图片对后使用flow_from_directory(简易版)

如果想继续用flow_from_directory,可以把每张图片对拼接成一张图片(比如左右拼接),再按类别存放:

  1. 提前将所有非兄弟姐妹的图片对拼接成单张图,放到training/false文件夹
  2. 将所有兄弟姐妹的图片对拼接成单张图,放到training/siblings文件夹
  3. 此时flow_from_directory读取的每个文件就是一个完整的图片对样本,classes数组就会和你需要的一致(比如false里2张拼接图,siblings里2张,classes就是[0,0,1,1])

这种方式优点是简单,但灵活性差,后续调整图片对的输入方式会很麻烦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:37:57