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

如何读取预处理分类文件夹文本以训练NLP/图文多模态模型?

同分类文件夹结构下多模态数据(文本+图像)的读取与预处理方案

1. 基于Keras Sequence实现稳定的自定义多模态生成器

Keras的Sequence类比手动写生成器更可靠,能直接和model.fit()配合,完美适配分类文件夹的存储结构。

核心流程:

  • 遍历所有类别文件夹,批量收集文本、图像的文件路径,同时映射对应的类别标签(文件夹名转索引)
  • 在初始化阶段完成文本Tokenizer的全局拟合(避免批量拟合导致词汇表不一致)
  • 在__getitem__方法中批量读取文本/图像,完成各自的预处理(文本分词、padding;图像resize、归一化等)
  • 同时返回图像、文本数据和对应标签,供多模态模型训练

示例代码框架:

import os
import numpy as np
from tensorflow.keras.utils import Sequence
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.preprocessing.image import load_img, img_to_array

class MultimodalGenerator(Sequence):
    def __init__(self, root_dir, img_size=(224,224), max_seq_len=128, batch_size=32, shuffle=True):
        self.root_dir = root_dir
        self.img_size = img_size
        self.max_seq_len = max_seq_len
        self.batch_size = batch_size
        self.shuffle = shuffle

        # 收集所有成对样本路径与标签
        self.samples = []
        self.labels = []
        self.classes = sorted(os.listdir(root_dir))
        self.class_map = {cls: idx for idx, cls in enumerate(self.classes)}

        for cls_name in self.classes:
            cls_dir = os.path.join(root_dir, cls_name)
            # 假设文本为.txt,图像为.jpg,文件名前缀一致(如sample_001.txt对应sample_001.jpg)
            for txt_file in os.listdir(cls_dir):
                if txt_file.endswith(".txt"):
                    base_name = os.path.splitext(txt_file)[0]
                    img_file = f"{base_name}.jpg"
                    img_path = os.path.join(cls_dir, img_file)
                    if os.path.exists(img_path):
                        self.samples.append((os.path.join(cls_dir, txt_file), img_path))
                        self.labels.append(self.class_map[cls_name])

        # 全局拟合文本Tokenizer
        self.tokenizer = Tokenizer()
        all_texts = []
        for txt_path, _ in self.samples:
            with open(txt_path, "r", encoding="utf-8") as f:
                all_texts.append(f.read().strip())
        self.tokenizer.fit_on_texts(all_texts)
        self.vocab_size = len(self.tokenizer.word_index) + 1

        self.on_epoch_end()

    def __len__(self):
        return int(np.ceil(len(self.samples) / self.batch_size))

    def __getitem__(self, idx):
        batch_start = idx * self.batch_size
        batch_end = min((idx + 1) * self.batch_size, len(self.samples))
        batch_samples = self.samples[batch_start:batch_end]
        batch_labels = self.labels[batch_start:batch_end]

        # 批量处理文本
        batch_texts = []
        for txt_path, _ in batch_samples:
            with open(txt_path, "r", encoding="utf-8") as f:
                batch_texts.append(f.read().strip())
        text_seqs = self.tokenizer.texts_to_sequences(batch_texts)
        text_data = pad_sequences(text_seqs, maxlen=self.max_seq_len)

        # 批量处理图像
        img_data = []
        for _, img_path in batch_samples:
            img = load_img(img_path, target_size=self.img_size)
            img = img_to_array(img) / 255.0  # 归一化
            img_data.append(img)
        img_data = np.array(img_data)

        return [img_data, text_data], np.array(batch_labels)

    def on_epoch_end(self):
        if self.shuffle:
            combined = list(zip(self.samples, self.labels))
            np.random.shuffle(combined)
            self.samples, self.labels = zip(*combined)

2. 用tf.data.Dataset构建高效多模态数据管道

适合大规模数据集,支持并行预处理、预取等性能优化,和TensorFlow生态无缝兼容。

核心流程:

  • 用tf.data.Dataset.list_files匹配所有文本文件路径
  • 通过路径解析提取类别标签和对应图像路径
  • 定义预处理函数,完成文本向量转换、图像解码resize
  • 配置批量、打乱、预取等操作提升加载效率

示例代码框架:

import tensorflow as tf
import os

def parse_paths(txt_path):
    # 从路径提取类别标签
    parts = tf.strings.split(txt_path, os.sep)
    cls_name = parts[-2]
    # 提前定义类别映射(需先遍历根目录获取所有类别)
    class_list = sorted(os.listdir(root_dir))
    class_map = {cls: idx for idx, cls in enumerate(class_list)}
    label = tf.convert_to_tensor(class_map[cls_name.numpy().decode("utf-8")], dtype=tf.int32)
    # 生成对应图像路径
    base_name = tf.strings.split(tf.strings.split(txt_path, ".")[0], os.sep)[-1]
    img_path = tf.strings.join([parts[0], parts[1], base_name + ".jpg"], separator=os.sep)
    return txt_path, img_path, label

def preprocess_sample(txt_path, img_path, label):
    # 处理文本:用TextVectorization做向量转换(需提前适配全局文本)
    txt_content = tf.io.read_file(txt_path)
    txt_content = tf.strings.strip(txt_content)
    # 提前初始化并适配vectorize_layer:vectorize_layer.adapt(all_texts_list)
    txt_seq = vectorize_layer(txt_content)

    # 处理图像
    img_content = tf.io.read_file(img_path)
    img = tf.image.decode_jpeg(img_content, channels=3)
    img = tf.image.resize(img, (224, 224)) / 255.0

    return (img, txt_seq), label

# 构建数据集
root_dir = "path/to/your/data"
txt_files_ds = tf.data.Dataset.list_files(os.path.join(root_dir, "*", "*.txt"))

# 解析路径+预处理
dataset = txt_files_ds.map(
    lambda x: tf.py_function(parse_paths, [x], [tf.string, tf.string, tf.int32]),
    num_parallel_calls=tf.data.AUTOTUNE
)
dataset = dataset.map(preprocess_sample, num_parallel_calls=tf.data.AUTOTUNE)

# 配置训练参数
dataset = dataset.shuffle(1000).batch(32).prefetch(tf.data.AUTOTUNE)

3. 关键注意事项

  • 文本预处理全局拟合:Tokenizer或TextVectorization必须在所有训练文本上完成适配,不能仅在批量数据上拟合,避免词汇表不一致
  • 样本配对校验:确保图像与文本文件名严格对应,可在初始化阶段加入校验逻辑,过滤缺失配对的样本
  • 性能优化:Sequence类中避免重复读取文本;tf.data开启并行映射和预取,减少数据加载瓶颈
  • 标签一致性:图像与文本的类别标签必须从同一文件夹名转换,避免标签错位

内容的提问来源于stack exchange,提问作者Ibrahima S Wade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:20:22