Files
modeling_zhaocui/deep_learning/Q1/方法说明_零基础版.md
T

147 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Q1 特征提取方法说明(零基础版)
这份说明介绍本次已经完成的 100 条视频处理过程。目标是把文字、声音和画面变成电脑能处理的数字,并让这三种数字都能回到原视频的时间位置。
## 先用一句话理解
把每条视频想成一段带字幕的短片:
- 把字幕切成一个个词,为每个词生成一组数字;
- 把声音切成许多很短的小段,为每段记录音高、响度等声音特征;
- 每隔一小段时间取一帧画面,为每帧生成一组画面数字;
- 再估计每个字幕词在声音里出现的时间,把同一时间附近的声音和画面对到一起。
这些数字就是“特征”。它们不是视频本身,也不是情感结论,而是模型后续可以读取的数字表示。
## 整体流程
```mermaid
flowchart LR
A[100条原始视频 + 原始字幕] --> B[文字:每个词生成向量]
A --> C[声音:提取逐帧声学特征]
A --> D[画面:每秒抽取约5帧并生成特征]
B --> E[用字幕和声音估计词级时间戳]
C --> E
E --> F[按词的时间段汇总声音和画面特征]
D --> F
F --> G[100个样本文件 + 汇总表 + 对应关系图]
```
## 什么叫“对齐”
一段视频里,字幕、声音和画面各有自己的节奏。比如字幕中的词“happy”可能在 1.2 秒左右说出,那个时刻的视频画面里也可能出现说话人的表情变化。
“对齐”就是给不同模态的内容标上共同的时间位置,便于回答:
> 这个词出现时,声音有什么变化?同一时刻画面里有什么?
本次时间统一使用“从这条短视频开始算起的秒数”。例如 1.2 秒就是片段开始后 1.2 秒。电脑估出来的时间是模型估计值,不是人工逐帧标注的真值。
## 文字是怎么处理的
1. 直接读取题目提供的英文 transcript(字幕文本),保留原文顺序和内容,不用模型改写或纠错。
2. 按空格切成词。像 `unbelievable` 这样的词,文字模型内部可能会再拆成更小的片段。
3. 使用预训练的 BERT 英文模型,为这些更小的片段生成数字向量,再把同一个词的片段向量取平均,得到这个词的一组数字。
可以把 BERT 理解成一个读过大量英文材料的编码器:它把每个词放进一组 768 个数字里。词的向量不是情感分数,也不代表某一维就等于某种具体情绪。
## 声音是怎么处理的
声音分成两个用途不同的步骤。
### 1. 找每个词大约在什么时候说出
使用预训练的 Wav2Vec2 英语语音模型,并把题目提供的 transcript 当作已知文本。模型根据实际声音,为字幕里的字母和词寻找最可能的时间位置。这种做法叫“强制对齐”:文本固定,模型估计它在声音中的时间。
这一步不会验证字幕是不是完全正确,也不会把它当成精确的人工真值。若字幕和录音差异较大,时间估计可能不准。
### 2. 记录声音本身的变化
用 FFmpeg 把视频里的声音转成单声道、每秒 16,000 个采样点的音频,再使用 openSMILE 的 eGeMAPSv02 特征配置。它大约每 0.01 秒输出一行、每行 25 个数字,记录响度、音高、频谱形状等声音信息。
这些数值描述“声音怎么变化”,不等同于文字内容,也不是情感类别。
## 画面是怎么处理的
视频不会把每一帧都存成特征。本次每秒大约抽取 5 帧,也就是平均约每 0.2 秒取一帧。
- DeiT-Tiny 图像模型为每帧生成 192 个数字,作为通用画面特征。这组数字能表示画面信息,但单独一个数字通常没有容易读懂的名称。
- 另外,MediaPipe Face Landmarker 会尝试检测人脸,并输出 52 个脸部动作系数,例如眉毛、眼睑和嘴部的运动。这些系数描述可见的脸部动作,不是“高兴/悲伤”等情绪标签。
有 13 条视频在抽样帧中没有检测到人脸,所以这些样本没有有效的人脸动作系数;它们仍然保留了 DeiT 通用画面特征,视觉模态没有因此缺失。
## 三种特征怎样对应到词
对齐完成后,每个字幕词都有一个起止时间。例如(下面只是示意):
| 字幕词 | 估计时间 | 对应的声音 | 对应的画面 |
| --- | --- | --- | --- |
| happy | 1.20–1.55 秒 | 取这个时间段内的声学帧并求平均 | 取这个时间段内的视频帧特征并求平均 |
声音特征比较密,通常一个词时间段里会有多行;视频每秒只有约 5 帧,所以有些很短的词时间段里可能没有正好落入的画面帧。这种情况下,程序取时间最近的一帧,并把“使用了最近帧”的标记一并保存。
本次有 12 个词无法直接从 CTC 对齐路径中获得时间,分布在 9 条样本里。它们被放在相邻有效词之间的一个时间点上,区间长度为零,并标记 `word_alignment_valid=false`。程序没有把估计不出的词伪装成可靠的起止时间;下游对应特征通过最近的有效声音帧或画面帧取得,并保留回退标记。
## 文件里存了什么
每条视频有一个压缩的 `.npz` 文件,变长序列按原长存储,不在文件里填充到同一长度。主要数组包括:
| 内容 | 形状示例 | 含义 |
| --- | --- | --- |
| `text_features` | 词数 × 768 | 每个 transcript 词的 BERT 向量 |
| `audio_features` | 音频帧数 × 25 | 逐帧 eGeMAPS 声学特征 |
| `vision_features` | 画面帧数 × 192 | 逐帧 DeiT 通用画面特征 |
| `face_blendshape_features` | 画面帧数 × 52 | 人脸动作系数;是否有效由独立掩码表示 |
| `word_intervals_s` | 词数 × 2 | 每个词的起止时间,单位秒 |
| `audio_word_features` | 词数 × 25 | 按词的时间段汇总后的声音特征 |
| `vision_word_features` | 词数 × 192 | 按词的时间段汇总后的视频特征 |
时间戳以 32 位浮点数保存,特征值以 16 位浮点数保存以节省空间,掩码使用布尔值。掩码就是一张有效性清单:`true` 表示该位置有可用数据,`false` 表示缺失或使用了需要谨慎处理的回退结果。
## 本次处理得到的汇总
- 原始样本:100 条;标签表里的 100 个样本与视频文件一一对应,未删除或替换样本。
- 文本:1,932 个词,768 维词向量。
- 声音:77,261 个有效帧,25 维声学特征。
- 画面:3,948 帧,192 维通用视觉特征,覆盖 100/100 条样本。
- 人脸动作:87/100 条检测到有效人脸帧;其余 13 条仍有通用视觉特征。
- CTC 词级时间:1,920/1,932 个词直接对齐,12 个词带回退标记。
- 抽取错误:0 条;完整特征与报告约 10.5 MB。
审计还发现两段原始视频短于题面给出的 2.648 秒下限:`-mJ2ud6oKI8/6` 约 2.2356 秒,`-s9qJ7ATP7w/6` 约 2.4667 秒。它们按原样保留,时长差异记录在审计文件中。
## 如何复现
在 `deep_learning` 目录中运行:
```bash
cd Q1
uv sync
uv run python -m q1.audit
uv run python -m q1.extract_features --output-dir outputs/q1_features
```
`uv.lock` 固定了 Python 依赖版本;运行清单记录了模型名称与修订号、参数、工具版本、GPU 信息和输出文件哈希。特征文件、汇总表、运行清单及典型样本图位于 `Q1/outputs/q1_features/`。
## 这次结果的边界
本说明讲的是“怎么从原始视频得到三模态特征,以及如何按时间组织它们”。最初的 M3/M4 版本曾把注意力摊得很平均;后来的时间码实验使 M4 找到了较稳定的时间位置,但“找到了同一时刻”仍不能保证文字、声音、画面的具体内容相互对应。情绪 Probe 也只是 100 条小样本上的检查,不能当作一般情绪识别准确率。CTC 时间、模型生成的向量和人脸动作系数都应当视为算法输出;要确认某个词和某段声音、画面是否真的对应,仍需要人工标注一些时间片段做独立核验。
## 后续的 TSFA 实验:为什么还要再对齐一次
可以把一段视频想成一条从头到尾的路。M4 根据时间先告诉我们:“第 20 个位置大约在这条路的中段。”TSFA 在中段附近再比较文字与声音、画面的内容,选择更像当前文字的片段。实验把每条视频组织成 50 个位置;“附近”在主方案中指整段视频时长的前后各 10%。如果窗口里没有可用的声音或画面位置,就取最近的有效位置,并保留这项规则。
为了知道“附近”是否真的有用,还做了两种对照:一种把同样宽的窗口随机放置,另一种让模型看完整段视频。七种方法使用相同的 100 条视频、相同的 BERT 文字特征、音频特征和 DeiT 图像特征;同一原视频的片段在同一折里一起作为训练或留出数据。总共做 5 折,每条样本都轮到一次留出评价。
结果显示,TSFA 比只用 M4 时更容易把同一位置的**文字与声音**对应起来,但画面相关的改善很小。随机窗口和看完整段视频的方案在“内容相似度”指标上甚至更高,却经常把视频前后位置弄乱。TSFA 的局部时间窗口主要帮助模型保持先后顺序。这里的“同一位置”由时间槽定义,还不是人工确认的同一事件,因此目前不能说三种模态已经准确理解了彼此。详细数字与图见 [RESULTS.md](RESULTS.md) 的 TSFA 小节。
我们也把连续情感分数按正负号分成三类,做了一个单独的小测。TSFA 三模态预测的 Accuracy 为 `0.54`,略低于总是猜样本最多的 Positive 类所得到的 `0.57`;它的 Macro-F1 为 `0.431`,高于这个简单猜测的 `0.242`。这表示它能识别一部分少数类别,但在连续分数回归上的误差仍偏大,所以不能据此认为 TSFA 已经是成熟的情感识别模型。
## 新增检查:让声音与画面交流,并保留各自的原始线索
原来的 TSFA 像是让文字分别询问声音和画面:“你们哪些部分与我对应?”这可能漏掉声音和表情之间的直接关系,也可能在挑选“与文字对应的部分”时丢掉有用的语调或画面线索。我们分别试了两件事:让声音和画面在同一小段时间内直接交换信息;以及在挑选后的信息之外,额外保留各模态未经这次语义挑选的特征。于是得到“两个开关各开或关”的四种组合。
四种组合仍使用原来的 100 条视频、BERT/eGeMAPS/DeiT 特征、五折留出方式和同一个简单情感预测器。原版的连续情感分数平均误差为 `0.820`;只加声音与画面的直接联系后为 `0.803`,变化很小;只保留原模态线索后降至 `0.572`;两者都加则为 `0.579`。原版预测的正负类别 Macro-F1 为 `0.431`;四种组合里,原版仍最高。按来源视频成组比较后,保留原模态线索带来的回归改善比较明确,新增的声音—画面联系暂时没有显示稳定改善。
这项结果说明原版 TSFA 交给情感预测器的信息可能不够完整。额外保留的线索同时包含文字、声音和画面,所以目前还不能说改进一定来自语调或表情;新组合的输入数字也更多。详细四组结果、配对区间和图见 [RESULTS.md](RESULTS.md) 的“A–V 局部边 × 原模态残差消融”一节。