Keras多标签分类:sigmoid+binary_crossentropy能否用flow_from_directory?
关于Keras多标签分类中flow_from_directory的使用问题
其实不用非要写自定义批量生成器!flow_from_directory确实是为单标签分类设计的(一个文件夹对应一个类别,每张图片只能属于一个文件夹),但对于多标签分类场景,Keras已经提供了更合适的工具——flow_from_dataframe,用它就能轻松配合sigmoid+binary_crossentropy实现多标签分类,比自己写生成器省心多了。
为什么flow_from_directory不适合直接用?
因为它的核心逻辑是**“图片所在的文件夹就是它的唯一标签”**,而多标签分类中一张图片对应多个标签,显然没法把一张图片同时放到N个文件夹里(硬要这么做会浪费存储空间,还容易出错),所以直接用flow_from_directory确实走不通。
替代方案:用flow_from_dataframe实现多标签分类
步骤很简单:
- 准备一个CSV文件,记录每张图片的文件名和对应的所有标签。比如格式可以是这样:
filename,labels img_001.jpg,cat;dog img_002.jpg,bird;cat img_003.jpg,dog - 把CSV里的标签转换成模型需要的二进制格式(每个标签对应一列,1表示存在该标签,0表示不存在)。
- 用
ImageDataGenerator的flow_from_dataframe方法生成批量数据,配合你的多标签模型。
举个具体的代码示例:
import pandas as pd from tensorflow.keras.preprocessing.image import ImageDataGenerator # 读取标签CSV df = pd.read_csv("image_labels.csv") # 拆分标签列,生成每个标签的二进制列 all_labels = ["cat", "dog", "bird"] df["labels"] = df["labels"].str.split(";") for label in all_labels: df[label] = df["labels"].apply(lambda x: 1 if label in x else 0) # 初始化数据生成器(带数据增强和验证集拆分) datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2) # 训练集生成器 train_generator = datagen.flow_from_dataframe( dataframe=df, directory="./images", # 图片存放的根目录 x_col="filename", # 图片文件名所在的列 y_col=all_labels, # 多标签对应的列 target_size=(224, 224), batch_size=32, class_mode="raw", # 因为y_col是多个数值列,用raw返回数组格式的标签 subset="training", shuffle=True ) # 验证集生成器同理 val_generator = datagen.flow_from_dataframe( dataframe=df, directory="./images", x_col="filename", y_col=all_labels, target_size=(224, 224), batch_size=32, class_mode="raw", subset="validation", shuffle=False )
然后你的模型输出层就可以设置为:
model.add(Dense(len(all_labels), activation="sigmoid")) model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
什么时候需要自定义生成器?
如果你的数据集有非常特殊的读取逻辑(比如需要实时处理复杂的标签格式、或者图片存储在非本地路径等),这时候才需要考虑写自定义生成器。但绝大多数多标签分类场景,flow_from_dataframe完全能搞定,没必要重复造轮子。
内容的提问来源于stack exchange,提问作者mrgloom
相关产品推荐
相关产品推荐

