多模态数据基础:图像、文本、语音的表示与预处理

做多模态模型,第一关就是数据。图像、文本、语音,这三类数据长得完全不一样——图像是像素矩阵,文本是离散符号,语音是一维时序信号。怎么把它们统一成模型能吃的「数字饲料」?这就是本章要解决的问题。

我个人习惯把数据预处理分成两步:表示(怎么用数字描述原始信息)和预处理(怎么清洗、对齐、标准化)。下面我们逐个模态拆开讲。

2.1 图像数据的表示与预处理

2.1.1 图像的数字化表示

一张彩色图片,在计算机眼里就是一个三维数组:[H, W, C]。H 是高度(像素行数),W 是宽度(像素列数),C 是通道数(RGB 就是 3)。每个像素的值范围是 0~255。

举个例子,一张 224x224 的 RGB 图片,形状就是 (224, 224, 3)。灰度图只有 1 个通道,形状是 (H, W) 或 (H, W, 1)。

关键点:深度学习框架(PyTorch/TensorFlow)默认的通道顺序是 [C, H, W],而 OpenCV 读出来是 [H, W, C]。这个坑我踩过不止一次——模型训练不收敛,查了半天发现是维度顺序搞反了。

2.1.2 图像预处理流水线

实际项目中,图像预处理通常包含以下步骤:

  1. 解码:从 JPEG/PNG 压缩格式还原为像素矩阵
  2. 缩放:统一到固定尺寸(如 224x224、384x384)
  3. 归一化:将像素值从 [0, 255] 映射到 [0, 1] 或 [-1, 1]
  4. 标准化:减去均值,除以标准差(通常使用 ImageNet 统计值)
  5. 数据增强:随机裁剪、翻转、颜色抖动等

我曾经在一个 OCR 项目里,因为忘了做归一化,模型 loss 一直降不下去。后来发现输入像素值还是 0~255,而权重初始化是假设输入在 0~1 之间的。嗯,这种低级错误,犯过一次就记住了。

经验值:标准化用的均值和标准差,建议从训练集统计,而不是直接套 ImageNet 的。尤其是医学影像、卫星图这类特殊数据,ImageNet 的统计值可能完全不适用。

2.1.3 常见图像增强操作

操作 说明 适用场景
随机水平翻转 以 50% 概率左右镜像 通用分类、检测
随机裁剪 从原图随机裁一块再缩放 提升平移不变性
颜色抖动 随机调整亮度、对比度、饱和度 光照变化大的场景
旋转 随机旋转 ±15° 文本检测、遥感
高斯噪声 添加随机噪声 抗噪鲁棒性训练
注意:增强不是越多越好。我见过有人对医学 CT 图做随机翻转——结果左右肺都反了,模型直接学废。增强策略必须符合数据的物理含义。

2.2 文本数据的表示与预处理

2.2.1 文本的数字化表示

文本不像图像那样天然是数值。我们需要先把文字变成数字。主流方式有两种:

  • 词袋模型(Bag of Words):统计每个词出现的次数,忽略顺序。简单但丢失语义。
  • 词嵌入(Word Embedding):把每个词映射到一个稠密向量(如 Word2Vec、GloVe)。
  • 子词分词(Subword Tokenization):BPE、WordPiece、SentencePiece,把词拆成更小的单元,解决 OOV(未登录词)问题。

现在的主流做法是子词分词 + 预训练嵌入。BERT 用的就是 WordPiece, 系列用 BPE。你想想看,如果遇到一个生僻词「饕餮」,词袋模型直接不认识,但 BPE 可以拆成「饕」「餮」两个子词,模型至少能猜个大概。

2.2.2 文本预处理流水线

  1. 清洗:去除 HTML 标签、特殊符号、多余空格
  2. 分词:按语言规则或模型词表切分
  3. 转 ID:将 映射为词表中的整数索引
  4. 填充/截断:统一序列长度(padding 到 max_len 或 truncate)
  5. 注意力掩码:标记哪些位置是真实 ,哪些是 padding
避坑指南:我曾经在处理中文文本时,直接用空格分词——结果「我爱北京天安门」被切成「我」「爱」「北京天安门」。中文分词必须用专门工具(jieba、LAC、HanLP),或者直接用字符级分词。

2.2.3 特殊 的处理

现代语言模型会引入一些特殊 :

  • [CLS]:分类任务用的起始标记
  • [SEP]:句子分隔符
  • [PAD]:填充符
  • [UNK]:未知词
  • [MASK]:掩码(用于 MLM 预训练)

这些 在预处理阶段就要处理好。比如 BERT 的输入格式是:[CLS] 句子A [SEP] 句子B [SEP]。_type_ids 用来区分哪个 属于句子 A,哪个属于句子 B。

2.3 语音数据的表示与预处理

2.3.1 语音的数字化表示

语音本质是一维的声波信号,采样后得到离散的幅度值序列。常见采样率:16kHz(电话)、44.1kHz(CD 音质)。

但原始波形直接喂给模型效果不好。我们通常提取声学特征:

  • MFCC(梅尔频率倒谱系数):最经典的特征,模拟人耳听觉特性
  • Fbank(Filter Bank):MFCC 的前一步,保留更多信息
  • Spectrogram(语谱图):将语音转为二维时频图,可以用 CNN 处理

我个人偏好用 Fbank。MFCC 做了 DCT 变换,会丢掉一些非线性信息,而 Fbank 保留得更完整。在语音识别任务中,Fbank 通常比 MFCC 好 1~2 个点。

2.3.2 语音预处理流水线

  1. 预加重:提升高频分量,补偿口唇辐射损失
  2. 分帧:将长语音切成短帧(通常 25ms,帧移 10ms)
  3. 加窗:对每帧加汉明窗,减少频谱泄漏
  4. FFT:将时域信号转为频域
  5. 梅尔滤波:用梅尔滤波器组提取 Fbank 特征
  6. 归一化:全局均值方差归一化或 CMVN(倒谱均值方差归一化)
经验之谈:语音数据的归一化最好做 utterance-level(按句子统计),而不是 global-level(按整个数据集统计)。因为不同说话人的音量、信道差异很大,全局归一化会把这种差异抹掉,反而丢失了说话人信息。

2.3.3 语音增强与数据增强

语音领域的数据增强和图像不太一样:

增强方法 操作 效果
速度扰动 改变语速(0.9x ~ 1.1x) 提升语速鲁棒性
音量扰动 随机调整增益 提升音量鲁棒性
加噪 叠加背景噪声(白噪声、环境音) 提升抗噪能力
SpecAugment 在频谱图上随机掩码(时间/频率维度) 提升泛化性
房间冲击响应 模拟不同房间的混响效果 提升远场识别效果
注意:SpecAugment 的掩码参数要调。我刚开始用的时候,频率掩码设了 30 个 bin,结果把元音全盖住了,模型直接学成了「哑巴」。建议频率掩码不超过 10 个 bin,时间掩码不超过 40 帧。

2.4 多模态数据的对齐与融合

做多模态,最难的不是单个模态的处理,而是对齐。图像、文本、语音在时间和空间上的粒度完全不同:

  • 图像是空间密集的(每个像素都有信息)
  • 文本是离散稀疏的(一个词对应多个像素区域)
  • 语音是时间连续的(每秒 16000 个采样点)

怎么对齐?常见策略:

  1. 时间对齐:视频和语音用时间戳同步,图像和文本用位置信息关联
  2. 特征对齐:通过注意力机制让不同模态的特征互相「看」到对方
  3. 对比学习对齐:让匹配的图文对距离近,不匹配的距离远(CLIP 的做法)

我记得在一个视频理解项目里,视频帧率是 30fps,语音特征每 10ms 一帧。如果直接对齐,一帧图像对应 3 帧语音特征,但语义上并不完全对应。后来我们用了交叉注意力,让模型自己学对齐权重——效果比硬对齐好不少。

2.5 本章知识体系总览

下面这张图总结了三种模态从原始数据到模型输入的完整流程:

多模态数据表示与预处理流程 图像 (Image) 解码 → 缩放 → 归一化 标准化 → 数据增强 输出: [C, H, W] 张量 文本 (Text) 清洗 → 分词 → 转 ID 填充/截断 → 注意力掩码 输出: [seq_len] 索引序列 语音 (Audio) 预加重 → 分帧 → 加窗 FFT → 梅尔滤波 → 归一化 输出: [T, F] 频谱特征 多模态对齐与融合 统一特征表示 → 模型输入 关键:不同模态的采样率、维度、语义粒度不同,预处理阶段就要设计好对齐策略 否则模型训练时会出现「模态失配」问题,导致收敛慢甚至不收敛

图像、文本、语音经过各自的预处理流水线后,最终汇聚到多模态对齐层。这一步决定了模型能不能真正「理解」不同模态之间的关系。说白了,预处理做得好,模型训练就成功了一半。

核心要点回顾:
  • 图像:注意通道顺序和归一化参数
  • 文本:选对分词器,处理好特殊
  • 语音:Fbank 优于 MFCC,增强要谨慎
  • 对齐:时间对齐、特征对齐、对比学习对齐三种思路