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

如何用3个Keras生成器构建mini batch?训练CNN内核崩溃求助

解决Keras多生成器训练时内核崩溃的问题

看起来你在构建三输入图像生成器时遇到了内核崩溃的问题,我来帮你拆解问题并给出可行的解决方案:

先排查核心问题点

你的代码里有几个容易触发错误的地方,也是导致内核崩溃的常见原因:

1. flow_from_directory的使用可能不符合要求

flow_from_directory的规则是:传入的目录下必须有子文件夹作为类别(比如Anchor文件夹里要放class1、class2这类子目录,再在子目录里放图片)。如果你的Anchor/Positive/Negative文件夹里直接存图片,没有子类别目录,这个函数会无法正确读取数据,甚至悄悄抛出内存相关的异常,最终导致内核崩溃。

2. 三个生成器的同步逻辑缺失

每个flow_from_directory生成器的内部索引是独立维护的,当某个文件夹的图片数量比其他两个少,调用next()时会触发遍历结束的异常,而你的while True循环没有处理这种情况,会导致生成器逻辑混乱,进而拖垮内核。

3. 输入维度与模型的匹配问题

你生成的input_imgs是(3,224,224,3),如果你的模型输入层定义的是固定批量(比如Input(shape=(3,224,224,3)))而不是(224,224,3),会导致张量运算维度不匹配,触发内存溢出或计算错误。


具体解决方案

方案一:改用手动加载图片(更灵活可控)

如果你的文件夹里直接存图片,没有子类别目录,建议放弃flow_from_directory,手动构建路径列表并加载图片:

import os
import numpy as np
from tensorflow.keras.preprocessing.image import load_img, img_to_array

# 先获取所有图片路径
def get_img_paths(folder):
    return [os.path.join(folder, fname) 
            for fname in os.listdir(folder) 
            if fname.lower().endswith(('.png', '.jpg', '.jpeg'))]

# 替换成你的实际路径
anchor_paths = get_img_paths(r'C:\Users\sinthes\Desktop\AI_anaconda\face_recognition\dataset\train\E\Anchor')
positive_paths = get_img_paths(r'C:\Users\sinthes\Desktop\AI_anaconda\face_recognition\dataset\train\E\Positive')
negative_paths = get_img_paths(r'C:\Users\sinthes\Desktop\AI_anaconda\face_recognition\dataset\train\E\Negative')

def generator_three_imgs(batch_size=1):
    max_samples = min(len(anchor_paths), len(positive_paths), len(negative_paths))
    while True:
        # 随机选batch_size个样本索引
        indices = np.random.choice(max_samples, batch_size, replace=False)
        
        anchor_batch = []
        positive_batch = []
        negative_batch = []
        labels = []
        
        for idx in indices:
            # 加载并预处理图片(归一化到0-1)
            anchor = img_to_array(load_img(anchor_paths[idx], target_size=(224,224))) / 255.0
            positive = img_to_array(load_img(positive_paths[idx], target_size=(224,224))) / 255.0
            negative = img_to_array(load_img(negative_paths[idx], target_size=(224,224))) / 255.0
            
            anchor_batch.append(anchor)
            positive_batch.append(positive)
            negative_batch.append(negative)
            # 根据你的需求自定义标签,这里示例为anchor:0, positive:1, negative:2
            labels.extend([0, 1, 2])
        
        # 拼接成最终的批量输入
        input_imgs = np.concatenate([anchor_batch, positive_batch, negative_batch], axis=0)
        yield input_imgs, np.array(labels)

方案二:修复flow_from_directory的同步逻辑

如果你坚持用flow_from_directory,需要添加生成器重置逻辑,确保三个生成器同步:

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

def generator_three_imgs(index, batch_size=1):
    anchor_dir = anchor_paths[index]
    positive_dir = positive_paths[index]
    negative_dir = negative_paths[index]
    
    # 共用一个数据增强生成器即可
    data_gen = ImageDataGenerator()
    
    # 注意class_mode设为None,因为我们不需要自动生成的类别标签
    anchor_gen = data_gen.flow_from_directory(
        anchor_dir,
        target_size=(224,224),
        batch_size=batch_size,
        class_mode=None,
        shuffle=True
    )
    positive_gen = data_gen.flow_from_directory(
        positive_dir,
        target_size=(224,224),
        batch_size=batch_size,
        class_mode=None,
        shuffle=True
    )
    negative_gen = data_gen.flow_from_directory(
        negative_dir,
        target_size=(224,224),
        batch_size=batch_size,
        class_mode=None,
        shuffle=True
    )
    
    # 获取三个生成器的最小步数,避免某个生成器提前耗尽
    min_steps = min(len(anchor_gen), len(positive_gen), len(negative_gen))
    step_count = 0
    
    while True:
        if step_count >= min_steps:
            # 重置所有生成器,重新开始遍历
            anchor_gen.reset()
            positive_gen.reset()
            negative_gen.reset()
            step_count = 0
        
        # 获取批量数据
        anchor_imgs = anchor_gen.next()
        positive_imgs = positive_gen.next()
        negative_imgs = negative_gen.next()
        
        input_imgs = np.concatenate([anchor_imgs, positive_imgs, negative_imgs], axis=0)
        # 自定义标签
        labels = np.array([0]*batch_size + [1]*batch_size + [2]*batch_size)
        
        yield input_imgs, labels
        step_count += 1

额外排查步骤

  1. 测试生成器是否正常工作
    先单独运行生成器,看能不能正常输出数据:

    gen = generator_three_imgs(0)
    imgs, labels = next(gen)
    print(imgs.shape, labels.shape)  # 应该输出(3,224,224,3)和(3,)
    

    如果这一步就崩溃,说明生成器的图片读取逻辑有问题。

  2. 检查模型输入层
    确保模型输入层接受单张图片的形状,而不是固定批量:

    from tensorflow.keras.layers import Input
    input_layer = Input(shape=(224,224,3))  # 正确,批量维度自动适配
    
  3. 缓解内存压力
    如果是内存不足导致的崩溃,可以尝试:

    • 开启TensorFlow的GPU内存增长模式:
      import tensorflow as tf
      gpus = tf.config.experimental.list_physical_devices('GPU')
      if gpus:
          try:
              for gpu in gpus:
                  tf.config.experimental.set_memory_growth(gpu, True)
          except RuntimeError as e:
              print(e)
      
    • 训练前手动清理内存:
      import gc
      gc.collect()
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:35:53