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

如何针对类别不平衡的二分类任务增强Class1数据优化CNN性能?

类别不平衡下的针对性数据增强解决方案

针对你遇到的Class2数据量是Class1 6倍的类别不平衡问题,通过针对Class1单独做数据增强来平衡数据分布,是解决模型偏向多数类的有效方法,以下是具体实现方案:

方法1:拆分数据集,为Class1配置专属增强策略

Keras原生的flow_from_directory会对所有类别应用相同的增强规则,没法单独提升少数类的增强频次或强度。所以可以手动拆分两类数据,分别处理后再合并:

  1. 遍历数据集文件夹,分别收集Class1和Class2的图像路径与标签,生成DataFrame
  2. 为Class1配置更强的增强策略(比如增加旋转、缩放范围),Class2用弱增强或仅归一化
  3. 用flow_from_dataframe分别创建两类的生成器,再自定义合并生成器,让Class1的输出频次匹配Class2的数量规模

示例代码:

import pandas as pd
import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# 生成单类别数据的DataFrame
def get_class_df(class_folder, label):
    img_paths = [os.path.join(class_folder, fname) 
                for fname in os.listdir(class_folder) 
                if fname.lower().endswith(('.png', '.jpg', '.jpeg'))]
    return pd.DataFrame({'image_path': img_paths, 'label': [label]*len(img_paths)})

# 指向训练集下的两类子文件夹
training_dir = "你的训练集路径"
class1_dir = os.path.join(training_dir, "class1")
class2_dir = os.path.join(training_dir, "class2")

# 生成两类的DataFrame
df_class1 = get_class_df(class1_dir, 0)  # Class1标记为0
df_class2 = get_class_df(class2_dir, 1)  # Class2标记为1

# 为Class1配置高强度数据增强
aug_class1 = ImageDataGenerator(
    rotation_range=15,
    height_shift_range=40,
    width_shift_range=40,
    zoom_range=0.15,
    horizontal_flip=True,
    vertical_flip=True,
    fill_mode='reflect',
    rescale=1/255.0
)

# Class2仅做归一化(数据量足够,无需额外增强)
aug_class2 = ImageDataGenerator(rescale=1/255.0)

# 创建两类的生成器
gen_class1 = aug_class1.flow_from_dataframe(
    df_class1,
    x_col='image_path',
    y_col='label',
    target_size=(96, 96),
    color_mode='rgb',
    class_mode='categorical',
    batch_size=64,
    shuffle=True
)

gen_class2 = aug_class2.flow_from_dataframe(
    df_class2,
    x_col='image_path',
    y_col='label',
    target_size=(96, 96),
    color_mode='rgb',
    class_mode='categorical',
    batch_size=64,
    shuffle=True
)

# 自定义合并生成器,让Class1的输出频次是原来的6倍(抵消数量差)
def balanced_generator(gen_minority, gen_majority, minority_mult=6):
    while True:
        # 每次输出6个Class1的batch,再输出1个Class2的batch
        for _ in range(minority_mult):
            x_min, y_min = next(gen_minority)
            yield x_min, y_min
        x_maj, y_maj = next(gen_majority)
        yield x_maj, y_maj

# 最终训练用的生成器
train_generator = balanced_generator(gen_class1, gen_class2)

# 计算训练步数:(Class1数量*6 + Class2数量) // batch_size
steps_per_epoch = (len(df_class1)*6 + len(df_class2)) // 64

方法2:结合类别权重与全局增强(快速补充方案)

如果不想拆分数据集,可以继续使用你原来的flow_from_directory,但在训练时加入类别权重,让模型对Class1的分类错误施加更重的惩罚,以此抵消数据量差异的影响。

示例代码:

# 计算类别权重:权重 = 总样本数 / (类别数 * 该类样本数)
total_samples = len(df_class1) + len(df_class2)
class_weight = {
    0: total_samples / (2 * len(df_class1)),  # Class1的权重
    1: total_samples / (2 * len(df_class2))   # Class2的权重
}

# 训练模型时传入class_weight参数
model.fit(
    aug_train_gen,
    steps_per_epoch=len(aug_train_gen),
    epochs=15,
    class_weight=class_weight
)

方法3:物理复制Class1图像(简易但不推荐)

最直接的方式是手动复制Class1的图像文件,让其数量接近Class2,再用原来的增强器训练。但这种方式容易导致模型过拟合(因为只是重复相同样本),仅适合快速验证思路,不推荐用于正式训练。

关键注意事项

  • 增强策略要适度,避免过度变换导致Class1图像失真,反而降低模型识别能力
  • 训练时务必开启shuffle=True,防止模型学习到样本顺序的无效信息
  • 优先结合针对性增强+类别权重的方案,能同时平衡数据分布和模型损失权重,效果更稳定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:45:56