卷二:数据篇——DAIC-WOZ数据集解析与特征提取
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; border-radius: 12px; margin-bottom: 30px;">
<h3 style="color: white; margin: 0;">🎯 学习目标</h3>
<p style="color: #f0f0f0; margin: 10px 0 0 0;">深入掌握多模态数据处理技术,为机器学习模型训练奠定坚实基础</p>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 30px;">
<div style="background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<strong style="color: #667eea;">📚 预计学习时长</strong><br>
<p style="margin: 10px 0 0 0;">2-3小时</p>
</div>
<div style="background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<strong style="color: #667eea;">🔧 前置知识</strong><br>
<p style="margin: 10px 0 0 0;">Python基础、pandas数据处理、基本机器学习概念</p>
</div>
</div>
🏗️ 章节导航
- [[#3.1 DAIC-WOZ数据集概述]]
- [[#3.2 数据集文件结构]]
- [[#3.3 数据读取与验证]]
- [[#4.1 音频特征提取]]
- [[#4.2 视频特征提取]]
- [[#4.3 数据保存与管理]]
📚 本章导读
本章节深入解析DAIC-WOZ数据集的处理流程和特征提取技术,这是多模态抑郁检测系统的核心基础。通过本章学习,您将:
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 20px 0;">
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #667eea;">
✅ 掌握DAIC-WOZ数据集的结构和内容
</div>
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #667eea;">
✅ 深入理解音频特征提取的原理和实现
</div>
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #667eea;">
✅ 掌握视频特征提取的方法和技巧
</div>
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #667eea;">
✅ 学会数据预处理的最佳实践
</div>
</div>
3.1 DAIC-WOZ数据集概述
3.1.1 数据集背景
DAIC-WOZ(Distress Analysis Interview Corpus – Wizard of Oz)是一个专门用于抑郁症检测的多模态数据集。该数据集包含:
- 189名参与者的访谈记录
- 音频和视频两种模态数据
- PHQ-8量表的抑郁程度标注
- 临床诊断作为金标准
数据来源深度解析:
- 创建机构:南加州大学和麻省理工学院联合创建
- 发表会议:IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP)
- 研究目的:专为研究自动抑郁检测算法设计
- 数据质量:经过专业医生评估,标注质量高
3.1.2 数据采集过程
# 数据集规模统计
import pandas as pd
# 读取元数据文件
metadata = pd.read_csv('dev_split_Depression_AVEC2017.csv')
# 统计基本信息
total_participants = len(metadata)
depressed_count = sum(metadata['PHQ8_Score'] >= 10)
normal_count = total_participants - depressed_count
print(f"总参与者数: {total_participants}")
print(f"抑郁患者数: {depressed_count} ({depressed_count/total_participants*100:.1f}%)")
print(f"正常人数: {normal_count} ({normal_count/total_participants*100:.1f}%)")
print(f"PHQ-8分数范围: {metadata['PHQ8_Score'].min()} - {metadata['PHQ8_Score'].max()}")
数据采集流程深度解析:
标准化访谈流程
- 参与者筛选:通过初步筛选确保参与者符合研究条件
- 标准化访谈:使用结构化的访谈脚本,时长约20-30分钟
- 多模态记录:同步录制音频和视频数据
- 临床评估:由专业医生进行PHQ-8量表评估
- 数据标注:根据PHQ-8分数进行抑郁/非抑郁标注
PHQ-8量表详解
PHQ-8是一个常用的抑郁筛查量表,包含8个问题,每个问题0-3分,总分0-24分:
| 分数范围 | 严重程度 | 判定标准 |
|---|---|---|
| 0-4 | 无抑郁 | PHQ8_Score < 5 |
| 5-9 | 轻度抑郁 | 5 ≤ PHQ8_Score ≤ 9 |
| 10-14 | 中度抑郁 | 10 ≤ PHQ8_Score ≤ 14 |
| 15-19 | 中重度抑郁 | 15 ≤ PHQ8_Score ≤ 19 |
| 20-24 | 重度抑郁 | PHQ8_Score ≥ 20 |
核心原理深度解析:
- 二分类标准:PHQ-8分数≥10被标记为抑郁(label=1)
- 类别不平衡:抑郁样本约占30%,正常样本约占70%
- 临床意义:该划分标准与临床诊断具有较高的一致性
3.2 数据集文件结构
3.2.1 文件组织架构
DAIC-WOZ数据集/
├── dev_split_Depression_AVEC2017.csv # 开发集元数据
├── train_split_Depression_AVEC2017.csv # 训练集元数据
├── 300_P/ # 参与者300的数据目录
│ ├── 300_AUDIO.wav # 音频文件
│ ├── 300_VIDEO.mp4 # 视频文件
│ ├── 300_CLNF_features.txt # OpenFace提取的特征
│ └── 300_TRANSCRIPT.csv # 访谈文本转录
├── 301_P/ # 参与者301的数据目录
│ ├── 301_AUDIO.wav
│ ├── 301_VIDEO.mp4
│ ├── 301_CLNF_features.txt
│ └── 301_TRANSCRIPT.csv
└── ... # 其他参与者数据
文件命名规范深度解析:
命名规则
- 音频文件:
{participant_id}_AUDIO.wav– 包含参与者的语音数据 - 视频文件:
{participant_id}_VIDEO.mp4– 包含参与者的面部表情和动作 - 特征文件:
{participant_id}_CLNF_features.txt– OpenFace提取的面部特征 - 转录文件:
{participant_id}_TRANSCRIPT.csv– 访谈的文本转录
目录结构设计原则
- 参与者独立:每个参与者的数据独立存储在单独目录中
- 命名统一:所有文件遵循统一的命名模式
- 内容完整:包含音频、视频、特征和文本等多种数据形式
3.2.2 元数据文件解析
# 元数据文件解析
metadata = pd.read_csv('dev_split_Depression_AVEC2017.csv')
# 查看列名和数据类型
print("列名:", list(metadata.columns))
print("\n数据类型:")
print(metadata.dtypes)
# 查看前几行数据
print("\n样本数据:")
print(metadata.head())
关键字段深度解析:
| 字段名 | 数据类型 | 描述 | 重要性 |
|---|---|---|---|
| Participant_ID | int | 参与者唯一标识符 | ⭐⭐⭐⭐⭐ |
| PHQ8_Score | int | PHQ-8抑郁量表得分 | ⭐⭐⭐⭐⭐ |
| Gender | int | 性别(1=男,2=女) | ⭐⭐⭐ |
| Age | int | 年龄 | ⭐⭐⭐ |
| Interview_Duration | float | 访谈时长(分钟) | ⭐⭐ |
数据验证策略:
- 范围验证:检查PHQ8_Score范围(0-27)
- 唯一性验证:验证Participant_ID的唯一性
- 合理性验证:确认性别(1-2)和年龄(0-120)的合理性
- 完整性验证:检查关键字段是否存在缺失值
3.3 数据读取与验证
3.3.1 数据加载函数
def load_metadata(root_dir):
"""
加载DAIC-WOZ数据集的元数据
参数:
root_dir: 数据集根目录
返回:
metadata: 包含所有参与者信息的DataFrame
"""
# 定义元数据文件优先级
metadata_files = [
"dev_split_Depression_AVEC2017.csv",
"train_split_Depression_AVEC2017.csv",
"train_split_Depression.csv",
"train_split.csv"
]
# 查找可用的元数据文件
metadata_path = None
for file in metadata_files:
path = os.path.join(root_dir, file)
if os.path.exists(path):
metadata_path = path
print(f"✅ 找到元数据文件: {file}")
break
if not metadata_path:
raise FileNotFoundError("未找到任何元数据文件")
# 读取元数据
metadata = pd.read_csv(metadata_path)
# 验证必要列
required_columns = ['PHQ8_Score', 'Participant_ID']
missing_columns = [col for col in required_columns if col not in metadata.columns]
if missing_columns:
raise ValueError(f"元数据文件缺少必要列: {missing_columns}")
return metadata
设计思路深度解析:
优先级机制
- 灵活查找:按优先级顺序查找元数据文件
- 向后兼容:支持不同版本的数据集文件命名
- 错误处理:明确的异常抛出和错误信息
数据验证策略
- 文件存在性检查:确保元数据文件存在
- 列完整性检查:验证必要字段是否存在
- 数据类型检查:确保数据类型正确
- 缺失值处理:处理可能的缺失值
3.3.2 数据完整性验证
def validate_data_integrity(metadata, data_dir):
"""
验证数据完整性
参数:
metadata: 元数据DataFrame
data_dir: 数据目录
返回:
valid_participants: 数据完整的参与者列表
"""
valid_participants = []
for idx, row in metadata.iterrows():
participant_id = str(row['Participant_ID'])
participant_folder = f"{participant_id}_P"
folder_path = os.path.join(data_dir, participant_folder)
# 检查目录是否存在
if not os.path.exists(folder_path):
print(f"⚠️ 参与者目录不存在: {folder_path}")
continue
# 检查音频文件
audio_file = os.path.join(folder_path, f"{participant_id}_AUDIO.wav")
if not os.path.exists(audio_file):
print(f"⚠️ 音频文件缺失: {audio_file}")
continue
# 检查视频特征文件
feature_file = os.path.join(folder_path, f"{participant_id}_CLNF_features.txt")
if not os.path.exists(feature_file):
print(f"⚠️ 视频特征文件缺失: {feature_file}")
continue
valid_participants.append(participant_id)
print(f"\n✅ 数据完整性检查完成")
print(f" 总参与者数: {len(metadata)}")
print(f" 数据完整的参与者数: {len(valid_participants)}")
print(f" 数据完整率: {len(valid_participants)/len(metadata)*100:.1f}%")
return valid_participants
验证流程深度解析:
多层次验证
- 目录检查:确认参与者目录存在
- 文件检查:验证音频文件和视频特征文件存在
- 内容检查:检查文件内容的有效性
- 统计报告:生成数据完整性报告
错误处理策略
- 优雅降级:单个文件缺失不影响整体处理
- 详细日志:记录每个缺失的文件信息
- 统计分析:计算数据完整率,评估数据集质量
常见问题处理
| 问题类型 | 处理策略 | 影响 |
|---|---|---|
| 目录不存在 | 跳过该参与者 | 数据量减少 |
| 音频文件缺失 | 跳过该参与者 | 数据量减少 |
| 特征文件缺失 | 跳过该参与者 | 数据量减少 |
| 文件格式错误 | 跳过该参与者 | 数据量减少 |
4.1 音频特征提取
4.1.1 MFCC特征原理
MFCC(Mel频率倒谱系数)是音频处理中常用的特征提取方法,特别适合语音分析。其核心原理包括:
- 预加重:增强高频部分,平衡频谱
- 分帧:将音频信号分成短帧(通常20-30ms)
- 加窗:应用汉明窗减少频谱泄漏
- FFT变换:将时域信号转换到频域
- Mel滤波器组:模拟人耳对频率的感知特性
- 对数能量:计算每个滤波器的能量并取对数
- DCT变换:获取倒谱系数
def extract_mfcc_features(audio_file, n_mfcc=35, sample_rate=16000):
"""
提取音频的MFCC特征
参数:
audio_file: 音频文件路径
n_mfcc: MFCC系数数量
sample_rate: 采样率
返回:
mfcc_features: 平均MFCC特征向量
"""
try:
# 读取音频文件
y, sr = librosa.load(audio_file, sr=sample_rate)
# 提取MFCC特征
mfccs = librosa.feature.mfcc(
y=y,
sr=sr,
n_mfcc=n_mfcc,
n_fft=512, # FFT窗口大小
hop_length=256, # 帧移
win_length=512, # 窗口长度
window='hann', # 窗函数
center=True, # 中心化
pad_mode='reflect' # 填充模式
)
# 计算时间维度上的均值作为特征向量
mfcc_features = np.mean(mfccs, axis=1)
return mfcc_features
except Exception as e:
print(f"⚠️ 音频特征提取错误 ({audio_file}): {str(e)}")
return None
参数深度解析:
关键参数说明
- n_mfcc:MFCC系数数量(通常20-40),本项目使用35维
- n_fft:FFT窗口大小(512,影响频率分辨率)
- hop_length:帧移(256,影响时间分辨率)
- window:窗函数类型(’hann’,减少频谱泄漏)
- sample_rate:采样率(16000Hz,语音处理标准采样率)
性能优化策略
- 预计算:避免重复读取音频文件
- 向量化:使用librosa的高效实现
- 内存管理:及时释放不必要的中间变量
- 并行处理:使用多线程加速特征提取
4.1.2 音频特征工程
def extract_comprehensive_audio_features(audio_file):
"""
提取综合音频特征
参数:
audio_file: 音频文件路径
返回:
features: 综合特征向量
"""
try:
y, sr = librosa.load(audio_file, sr=16000)
# 提取MFCC特征
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=35)
mfcc_mean = np.mean(mfccs, axis=1)
mfcc_std = np.std(mfccs, axis=1)
# 提取频谱特征
spectral_centroid = librosa.feature.spectral_centroid(y=y, sr=sr)
spectral_bandwidth = librosa.feature.spectral_bandwidth(y=y, sr=sr)
spectral_rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
# 提取能量特征
rms = librosa.feature.rms(y=y)
# 提取零交叉率
zcr = librosa.feature.zero_crossing_rate(y)
# 提取基频特征(使用parselmouth)
import parselmouth
sound = parselmouth.Sound(audio_file)
pitch = sound.to_pitch()
pitch_values = pitch.selected_array['frequency']
pitch_mean = np.mean(pitch_values[pitch_values > 0]) if any(pitch_values > 0) else 0
pitch_std = np.std(pitch_values[pitch_values > 0]) if any(pitch_values > 0) else 0
# 组合所有特征
features = np.concatenate([
mfcc_mean,
mfcc_std,
[np.mean(spectral_centroid)],
[np.mean(spectral_bandwidth)],
[np.mean(spectral_rolloff)],
[np.mean(rms)],
[np.mean(zcr)],
[pitch_mean],
[pitch_std]
])
return features
except Exception as e:
print(f"⚠️ 综合特征提取错误: {str(e)}")
return None
特征组合策略深度解析:
特征类型分类
-
时域特征:
- 能量特征(RMS):反映语音强度
- 零交叉率(ZCR):反映语音的清晰度和频率特性
-
频域特征:
- 频谱中心:反映能量集中的频率区域
- 频谱带宽:反映频率分布的宽度
- 频谱滚降:反映能量分布的倾斜程度
-
倒谱特征:
- MFCC均值:反映语音的静态特征
- MFCC标准差:反映语音的动态变化
-
韵律特征:
- 基频均值:反映说话者的音高
- 基频标准差:反映音高的变化程度
特征选择原理
- 相关性:选择与抑郁症状相关的声学特征
- 互补性:不同类型的特征相互补充
- 鲁棒性:选择对噪声不敏感的特征
- 计算效率:考虑特征提取的计算成本
抑郁相关特征分析
| 特征类型 | 抑郁表现 | 特征变化 |
|---|---|---|
| 基频 | 情绪低落 | 基频降低、变化减小 |
| 能量 | 声音微弱 | RMS能量降低 |
| 零交叉率 | 语音单调 | ZCR降低 |
| MFCC | 语音特征变化 | 特定MFCC系数变化 |
4.2 视频特征提取
4.2.1 OpenFace特征解析
OpenFace是一个开源的面部分析工具,能够提取多种面部特征:
- 面部动作单元(AU):如眉毛抬起、眼睛闭合等表情动作
- 头部姿态:俯仰角、偏航角、滚转角
- 面部标志点:68个面部关键点坐标
- 眼神特征:注视方向、眨眼频率
def extract_video_features(participant_id, data_dir):
"""
从CLNF_features.txt提取视频特征
参数:
participant_id: 参与者ID
data_dir: 数据目录
返回:
video_features: 140维视频特征向量
"""
# 构建特征文件路径
features_file = os.path.join(
data_dir,
f"{participant_id}_P",
f"{participant_id}_CLNF_features.txt"
)
# 检查文件是否存在
if not os.path.exists(features_file):
print(f"⚠️ 视频特征文件不存在: {features_file}")
return np.random.rand(140)
try:
# 读取文件并提取特征(跳过第一行标题)
with open(features_file, 'r') as f:
lines = f.readlines()[1:] # 跳过标题行
if not lines:
print(f"⚠️ 视频特征文件为空: {features_file}")
return np.random.rand(140)
# 提取所有时间点的特征
features = []
for line in lines:
if not line.strip():
continue
nums = [float(x) for x in line.split(',')]
if len(nums) >= 140:
features.append(nums[:140])
if not features:
print(f"⚠️ 无有效视频特征: {features_file}")
return np.random.rand(140)
# 计算时间维度上的平均值
features_avg = np.mean(features, axis=0)
return features_avg[:140]
except Exception as e:
print(f"⚠️ 视频特征提取错误 ({features_file}): {str(e)}")
return np.random.rand(140)
特征维度深度解析:
OpenFace特征维度
| 特征类型 | 维度 | 描述 | 抑郁相关性 |
|---|---|---|---|
| 面部标志点 | 204维 | 68个点 × 3坐标(x,y,z) | ⭐⭐⭐ |
| 头部姿态 | 3维 | 俯仰角、偏航角、滚转角 | ⭐⭐⭐ |
| 面部动作单元 | 约30维 | AU强度和存在性 | ⭐⭐⭐⭐ |
| 眼神特征 | 约10维 | 注视方向、眨眼频率等 | ⭐⭐⭐ |
关键动作单元(AUs)解析
| AU编号 | 名称 | 描述 | 抑郁表现 |
|---|---|---|---|
| AU01 | 眉毛内侧抬起 | 悲伤表情 | 抑郁时增强 |
| AU02 | 眉毛外侧抬起 | 惊讶表情 | 抑郁时减弱 |
| AU04 | 眉毛降低 | 悲伤/担忧 | 抑郁时增强 |
| AU07 | 眼睑闭合 | 疲惫/困倦 | 抑郁时增强 |
| AU12 | 嘴角上扬 | 微笑表情 | 抑郁时减弱 |
| AU15 | 嘴角下拉 | 悲伤表情 | 抑郁时增强 |
| AU23 | 嘴唇收紧 | 紧张表情 | 抑郁时增强 |
数据处理策略
- 时间平均:计算整个视频的平均特征,捕捉整体表现
- 缺失处理:提供随机特征作为回退方案
- 维度控制:确保返回固定维度的特征向量
- 异常值处理:处理可能的异常值
4.2.2 视频特征工程
def process_video_features(raw_features):
"""
处理原始视频特征,提取更有意义的统计特征
参数:
raw_features: 原始特征列表(每个时间点的特征)
返回:
processed_features: 处理后的统计特征
"""
if not raw_features:
return np.zeros(280)
# 转换为numpy数组
features_array = np.array(raw_features)
# 计算基本统计特征
mean_features = np.mean(features_array, axis=0)
std_features = np.std(features_array, axis=0)
max_features = np.max(features_array, axis=0)
min_features = np.min(features_array, axis=0)
# 计算动态特征(变化率)
if len(raw_features) > 1:
diff_features = np.diff(features_array, axis=0)
mean_diff = np.mean(diff_features, axis=0)
std_diff = np.std(diff_features, axis=0)
else:
mean_diff = np.zeros_like(mean_features)
std_diff = np.zeros_like(std_features)
# 组合所有特征
processed_features = np.concatenate([
mean_features,
std_features,
max_features,
min_features,
mean_diff,
std_diff
])
return processed_features
统计特征提取深度解析:
统计特征类型
-
静态特征:
- 均值:反映特征的中心趋势
- 标准差:反映特征的变化程度
- 最大值/最小值:反映特征的极值范围
-
动态特征:
- 变化率均值:反映特征变化的平均速度
- 变化率标准差:反映特征变化的稳定性
特征选择依据
- 抑郁表现模式:抑郁患者通常表现出面部表情减少
- 动态变化:抑郁患者的面部动作可能更加缓慢
- 情绪表达:抑郁患者的情绪表达能力下降
- 注意力:抑郁患者的眼神接触可能减少
特征工程优势
- 信息丰富:统计特征包含了时间维度的信息
- 维度扩展:从140维扩展到280维,增加特征表达能力
- 鲁棒性:统计特征对噪声和异常值具有一定的鲁棒性
- 计算效率:统计特征计算高效,适合实时处理
4.3 数据保存与管理
4.3.1 数据序列化
def save_processed_data(audio_features, video_features, labels, participant_ids, output_dir):
"""
保存处理后的数据
参数:
audio_features: 音频特征数组
video_features: 视频特征数组
labels: 标签数组
participant_ids: 参与者ID列表
output_dir: 输出目录
"""
# 确保输出目录存在
os.makedirs(output_dir, exist_ok=True)
# 保存特征和标签
np.save(os.path.join(output_dir, "audio_features.npy"), audio_features)
np.save(os.path.join(output_dir, "video_features.npy"), video_features)
np.save(os.path.join(output_dir, "labels.npy"), labels)
np.save(os.path.join(output_dir, "participant_ids.npy"), participant_ids)
# 保存元数据
metadata = {
'num_samples': len(audio_features),
'audio_feature_dim': audio_features.shape[1],
'video_feature_dim': video_features.shape[1],
'depression_count': int(np.sum(labels)),
'normal_count': int(len(labels) - np.sum(labels))
}
with open(os.path.join(output_dir, "metadata.json"), 'w', encoding='utf-8') as f:
json.dump(metadata, f, indent=2, ensure_ascii=False)
print(f"\n✅ 数据已保存到: {output_dir}")
print(f"音频特征: {audio_features.shape}")
print(f"视频特征: {video_features.shape}")
print(f"标签分布: 抑郁={metadata['depression_count']}, 正常={metadata['normal_count']}")
数据格式选择深度解析:
存储格式对比
| 格式 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| NumPy数组 | 高效的数值数据存储 | 仅支持数值数据 | 特征数据存储 |
| JSON | 结构化的文本存储 | 不适合大数组 | 元数据存储 |
| HDF5 | 支持大数据集和压缩 | 依赖额外库 | 大规模数据集 |
| Pickle | 支持Python对象 | 安全性问题 | 模型存储 |
存储策略设计
- 分离存储:音频特征和视频特征分开保存,便于单独使用
- 元数据跟踪:记录数据维度和分布信息,便于后续处理
- 版本控制:考虑添加版本信息,支持数据版本管理
- 备份机制:建议定期备份处理后的数据
性能优化考虑
- 压缩选项:考虑使用
np.savez_compressed进行压缩 - 分块存储:对于大规模数据,考虑分块存储
- 索引优化:为频繁访问的数据建立索引
- 缓存策略:实现数据缓存,避免重复读取
4.3.2 数据加载与验证
def load_processed_data(output_dir):
"""
加载处理后的数据
参数:
output_dir: 输出目录
返回:
audio_features, video_features, labels, participant_ids
"""
try:
# 加载特征和标签
audio_features = np.load(os.path.join(output_dir, "audio_features.npy"))
video_features = np.load(os.path.join(output_dir, "video_features.npy"))
labels = np.load(os.path.join(output_dir, "labels.npy"))
participant_ids = np.load(os.path.join(output_dir, "participant_ids.npy"))
# 加载元数据
with open(os.path.join(output_dir, "metadata.json"), 'r', encoding='utf-8') as f:
metadata = json.load(f)
# 验证数据一致性
assert len(audio_features) == len(video_features) == len(labels) == len(participant_ids)
assert audio_features.shape[1] == metadata['audio_feature_dim']
assert video_features.shape[1] == metadata['video_feature_dim']
print(f"✅ 数据加载成功")
print(f"样本数量: {len(audio_features)}")
print(f"音频特征维度: {audio_features.shape[1]}")
print(f"视频特征维度: {video_features.shape[1]}")
print(f"标签分布: 抑郁={metadata['depression_count']}, 正常={metadata['normal_count']}")
return audio_features, video_features, labels, participant_ids
except Exception as e:
print(f"❌ 数据加载失败: {str(e)}")
return None, None, None, None
数据验证深度解析:
验证步骤
- 文件存在性检查:确保所有文件存在
- 维度一致性检查:验证特征维度匹配元数据
- 样本数量检查:确保各数组长度一致
- 数据类型检查:验证数据类型正确
错误处理策略
- 详细错误信息:提供具体的错误原因
- 优雅降级:错误时返回None,便于上层处理
- 日志记录:记录详细的错误信息
- 验证日志:输出验证通过的详细信息
数据质量评估
- 完整性检查:验证数据是否完整
- 一致性检查:验证数据之间的一致性
- 合理性检查:验证数据值的合理性
- 分布检查:检查标签分布是否合理
🎯 本章总结
核心知识点回顾
-
DAIC-WOZ数据集
- ✅ 数据集结构和文件组织深度解析
- ✅ 元数据文件解析和验证策略
- ✅ 数据完整性检查方法和实现
-
音频特征提取
- ✅ MFCC特征原理和参数设置
- ✅ 综合音频特征提取方法
- ✅ 特征工程和选择策略
-
视频特征提取
- ✅ OpenFace特征解析和维度说明
- ✅ 视频特征工程和统计特征提取
- ✅ 面部动作单元与抑郁相关性分析
-
数据管理
- ✅ 数据序列化和存储格式选择
- ✅ 数据加载和验证策略
- ✅ 元数据管理和质量评估
重点/易错点总结
重点掌握:
- DAIC-WOZ数据集的文件结构和命名规范
- MFCC特征提取的原理和参数设置
- OpenFace特征文件的解析方法
- 数据序列化和验证的最佳实践
- 特征工程和选择策略
常见错误:
- ❌ 文件路径拼接错误:导致文件找不到,解决方案:使用os.path.join或Pathlib
- ❌ 忽略特征维度不一致问题:导致后续处理失败,解决方案:添加维度验证
- ❌ 缺少异常处理:导致程序崩溃,解决方案:添加完整的异常处理
- ❌ 数据验证不严格:导致后续处理失败,解决方案:添加全面的数据验证
- ❌ 特征选择不合理:影响模型性能,解决方案:基于领域知识选择特征
学习建议
- 实践操作:尝试提取真实音频和视频的特征
- 参数调整:探索不同参数对特征提取的影响
- 特征分析:分析提取的特征与抑郁症状的相关性
- 性能优化:优化特征提取的速度和内存使用
- 数据可视化:可视化特征分布,理解特征含义
📚 参考资源
- [[DAIC-WOZ数据集官方文档]]
- [[librosa音频处理库文档]]
- [[OpenFace官方文档]]
- [[PHQ-8抑郁量表说明]]
- [[面部动作编码系统(FACS)]]
下一章预告:[[毕设项目学习笔记/03_卷三_模型篇]] – 深入讲解机器学习模型训练和评估技术