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

各位同学,咱们今天聊聊多模态学习的“地基”——四种常见模态的特征表示和预处理。说实话,很多做多模态融合的项目最后效果不好,问题往往就出在这一步。我见过太多人直接把原始数据扔进模型,结果训练都收敛不了。

你想想看,图像是像素矩阵,文本是离散符号,语音是时序波形,表格是结构化字段。这四种东西怎么统一到一个空间里去?嗯,咱们一步步拆开看。

2.1 图像模态:从像素到语义向量

图像的本质是什么?说白了就是一个三维张量——高度 × 宽度 × 通道数。RGB 图像就是 3 个通道,每个像素值范围 0-255。

2.1.1 预处理流水线

我个人习惯的预处理流程是这样的:

  1. 尺寸归一化:把所有图缩放到统一尺寸,比如 224×224。别小看这一步,我遇到过因为数据集里混了一张 4K 大图,训练时直接 OOM 的情况。
  2. 像素值归一化:除以 255 缩放到 [0,1],或者用 ImageNet 的 mean/std 做标准化。
  3. 数据增强:随机翻转、旋转、裁剪、色彩抖动。这是防止过拟合的“免费午餐”。

关键指标:预处理后的图像张量形状为 [B, C, H, W],其中 B 为 batch size,C 为通道数,H/W 为高宽。

2.1.2 特征提取方法

方法 输出维度 特点 我的经验
CNN (ResNet/ViT) 2048 / 768 层次化特征,平移不变性 ResNet-50 是万金油,ViT 在大数据上更优
CLIP 视觉编码器 512 对齐文本空间,适合跨模态 做图文匹配时我首选这个
手工特征 (SIFT/HOG) 可变 可解释性强,但泛化差 现在基本不用了,除非做传统方法对比
# 图像预处理示例 (PyTorch)
from torchvision import transforms

transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225])
])

避坑指南:我曾经在医疗影像项目里直接用了 ImageNet 的标准化参数,结果模型死活不收敛。后来发现医学图像的像素分布和自然图像完全不同——一定要根据你的数据分布重新计算 mean/std。

2.2 文本模态:离散符号的连续化

文本和图像最大的区别是什么?图像是连续的,文本是离散的。你没法直接对“苹果”这个词做梯度下降。所以我们需要一个映射——把词变成向量。

2.2.1 Tokenization 策略

这一步决定了你的词表大小和语义粒度:

  • Word-level:按空格分词,词表大(5万+),OOV 问题严重
  • Character-level:按字符切分,词表小(几十个),但序列太长
  • Subword (BPE/WordPiece):折中方案,目前最主流。BPE 从字符开始逐步合并高频共现对

我个人习惯用 BPE,词表设 3 万左右。为什么?因为我在做中文多模态项目时发现,Word-level 对“未登录词”太不友好了,而 Character-level 又抓不住语义。

2.2.2 文本特征表示

模型 输出维度 上下文感知 适用场景
Word2Vec / GloVe 300 否(静态) 传统方法、轻量场景
BERT / RoBERTa 768 是(双向) 语义理解、分类、匹配
系列 768-4096 是(单向) 生成任务、对话
Sentence-BERT 384-768 是(句级) 语义相似度、检索
# 使用 BERT tokenizer 和模型
from transformers import BertTokenizer, BertModel

tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

text = "Multimodal learning is fascinating."
inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)
outputs = model(**inputs)
# outputs.last_hidden_state.shape: [1, seq_len, 768]

小技巧:做多模态对齐时,我通常取 BERT 的 [CLS] 作为整句表示,或者对所有 做 mean pooling。具体哪个好?建议你在验证集上试一下,不同任务差异很大。

2.3 语音模态:一维时序的挑战

语音和文本很像,都是序列数据。但语音是连续的,而且采样率很高——16kHz 就是一秒 16000 个点。直接建模这么长的序列?不现实。

2.3.1 预处理:从波形到频谱

我们通常把语音转成频谱图,当成“图像”来处理。流程如下:

  1. 预加重:增强高频信号,补偿口唇辐射损失
  2. 分帧加窗:每帧 25ms,帧移 10ms,用汉明窗平滑
  3. FFT 变换:得到频谱,再映射到 Mel 尺度(模拟人耳感知)
  4. 取对数:得到 Log-Mel 频谱,形状为 [T, F],T 是帧数,F 是 Mel 滤波器个数(通常 80)

核心参数:一段 3 秒的语音,16kHz 采样率,分帧后得到约 300 帧,每帧 80 维 Mel 特征。最终输入形状为 [1, 300, 80]。

2.3.2 特征提取方法

  • 手工特征:MFCC(梅尔频率倒谱系数),13-40 维,传统 ASR 标配
  • 预训练模型:Wav2Vec 2.0、HuBERT、Whisper。这些模型直接在原始波形上做自监督学习,效果远超手工特征

我记得有一次做语音情感识别,用 MFCC 怎么调都只有 65% 的准确率。换成 Wav2Vec 2.0 的特征后,直接跳到 82%。嗯,从此我成了预训练模型的忠实用户。

# 提取 Log-Mel 频谱 (使用 librosa)
import librosa

audio, sr = librosa.load('speech.wav', sr=16000)
mel_spec = librosa.feature.melspectrogram(
    y=audio, sr=sr, n_fft=400, hop_length=160, n_mels=80
)
log_mel = librosa.power_to_db(mel_spec)
# log_mel.shape: [80, T]

2.4 表格模态:被低估的结构化数据

表格数据在工业界太常见了——用户画像、交易记录、传感器读数。但很多人做多模态时直接把它忽略了,或者简单拼接到特征向量里。这其实是个坑。

2.4.1 特征类型与预处理

特征类型 示例 预处理方法 注意事项
数值型 年龄、收入、温度 标准化 (Z-score) 或 Min-Max 归一化 对异常值敏感,建议先做截断
类别型 性别、城市、设备类型 One-hot / Label Encoding / Embedding 高基数类别用 Embedding,维度设为 min(50, n_categories//2)
时序型 注册时间、最后登录时间 提取年/月/日/星期,或计算时间差 不要直接用时间戳,模型学不到周期性
文本型 备注、评论摘要 用 NLP 方法提取特征后拼回表格 注意长度控制,避免维度爆炸

2.4.2 表格特征表示策略

我常用的三种方式:

  • 直接拼接:所有特征归一化后拼成一个大向量。简单,但忽略了特征间的关系
  • TabNet / FT-Transformer:用 Transformer 架构处理表格,能学到特征交互。效果好,但计算量大
  • 特征交叉:手动构造二阶或三阶交叉特征(如“年龄×收入”)。依赖业务理解,但可解释性强

避坑指南:我曾经在一个推荐系统项目里,把用户 ID 做了 One-hot 编码,结果特征维度直接到了 1000 万。模型训练了三天还没收敛。后来改成 Embedding,维度降到 64,效果反而更好。记住:高基数类别特征一定要用 Embedding。

2.5 四种模态的统一视角

好了,四种模态都讲完了。你可能会问:它们之间有什么共性?

其实,所有模态的预处理都在做同一件事——把原始信号映射到一个模型能“理解”的向量空间。图像是 [C,H,W] 的张量,文本是 [L,D] 的序列,语音是 [T,F] 的频谱,表格是 [N_feat] 的向量。

多模态融合的核心挑战,就是把这些不同形状、不同语义空间的东西对齐到一起。

四种模态特征表示与预处理流程 图像 (RGB) Resize → Normalize CNN / ViT 编码 输出: [B, C, H, W] 文本 (String) Tokenize (BPE) BERT / 编码 输出: [B, L, D] 语音 (Waveform) 分帧 → FFT → Mel Wav2Vec / HuBERT 输出: [B, T, F] 表格 (Tabular) 归一化 / Embedding TabNet / MLP 输出: [B, N_feat] 统一特征空间 (Shared Embedding Space) 核心挑战:不同模态的形状、语义、采样率各不相同,需要对齐到同一空间 图像 [C,H,W] → 文本 [L,D] → 语音 [T,F] → 表格 [N_feat] → 统一向量

我的建议:在实际项目中,不要一上来就追求最先进的模型。先用简单的预处理和特征提取把 baseline 跑通,再逐步替换复杂模块。我见过太多团队在预处理阶段就卡了两周——先动起来,再优化。