深度学习在人体活动识别中的应用与实践
·
1. 人体活动识别问题概述
人体活动识别(Human Activity Recognition, HAR)是一项通过分析传感器数据来识别人体当前活动的技术。这项技术在健康监测、智能家居、运动分析等领域有着广泛应用。典型的应用场景包括:
- 老年人跌倒检测
- 健身动作识别与计数
- 工作场所安全监测
- 日常活动模式分析
传统方法依赖手工提取特征,需要领域专家设计复杂的特征工程。而现代深度学习方法能够自动学习特征表示,大大降低了技术门槛。本教程将基于一个标准数据集,展示如何应用深度学习处理这类时间序列分类问题。
2. 数据集详解与准备
2.1 数据集来源与特点
我们使用的是巴塞罗那大学Casale等人收集的"Activity Recognition from Single Chest-Mounted Accelerometer"数据集。该数据集包含15名受试者的胸部加速度计数据,采样频率为52Hz(每秒52个数据点)。
数据集特点:
- 数据格式:CSV文件(每个受试者一个文件)
- 数据列:时间戳、x轴加速度、y轴加速度、z轴加速度、活动标签
- 活动类别:7种明确活动+1类"无活动"
2.2 数据加载与预处理
加载数据时需要注意几个关键点:
- 文件排序问题:Python的listdir()返回的文件顺序可能与预期不同
- 内存管理:大数据集需要分块加载
- 数据标准化:不同受试者的数据尺度可能不同
import os
import numpy as np
import pandas as pd
def load_har_dataset(data_dir):
"""加载HAR数据集"""
subjects = []
for filename in sorted(os.listdir(data_dir), key=lambda x: int(x.split('.')[0])):
if not filename.endswith('.csv'):
continue
filepath = os.path.join(data_dir, filename)
# 使用chunksize处理大文件
df_chunks = pd.read_csv(filepath, header=None, chunksize=10000)
for chunk in df_chunks:
# 移除时间戳列,保留xyz和标签
values = chunk.values[:, 1:].astype(np.float32)
subjects.append(values)
return subjects
提示:在实际应用中,建议对每个受试者的数据单独进行标准化处理,消除个体差异带来的影响。
3. 数据探索与可视化
3.1 单受试者活动轨迹分析
通过可视化单个受试者的数据,我们可以直观理解不同活动对应的加速度模式:
import matplotlib.pyplot as plt
def plot_subject_activities(subject_data, subject_id):
plt.figure(figsize=(12, 8))
activities = ['无活动','电脑工作','站立行走','站立','行走','上下楼梯','边走边说','站立说话']
for i in range(4): # 3轴加速度+活动标签
plt.subplot(4, 1, i+1)
if i < 3:
plt.plot(subject_data[:, i], label=['X','Y','Z'][i])
plt.legend()
else:
# 绘制活动标签
for act in np.unique(subject_data[:, 3]):
mask = subject_data[:, 3] == act
plt.scatter(np.where(mask)[0], [act]*sum(mask),
label=activities[int(act)], s=1)
plt.yticks(range(8), activities)
plt.title(f"受试者{subject_id} - {['X轴','Y轴','Z轴','活动'][i]}加速度")
plt.tight_layout()
plt.show()
3.2 活动持续时间分布
分析不同活动的持续时间分布有助于理解数据平衡性:
def plot_activity_durations(subjects):
activities_duration = {i:[] for i in range(8)}
freq = 52 # 采样频率
for subject in subjects:
for act in range(8):
duration = np.sum(subject[:,-1]==act)/freq/60 # 转换为分钟
activities_duration[act].append(duration)
plt.figure(figsize=(10,6))
plt.boxplot(activities_duration.values(), labels=activities.values())
plt.ylabel('持续时间(分钟)')
plt.title('各活动持续时间分布')
plt.xticks(rotation=45)
plt.show()
从分析中我们发现:
- "站立说话"和"电脑工作"数据量最多
- "上下楼梯"和"边走边说"数据较少
- 需要考虑类别不平衡问题
4. 特征工程与数据准备
4.1 滑动窗口处理
时间序列分类通常采用滑动窗口方法:
def create_sliding_windows(data, window_size=52, overlap=0.5):
"""创建滑动窗口"""
windows = []
labels = []
step = int(window_size * (1 - overlap))
for i in range(0, len(data) - window_size, step):
window = data[i:i+window_size, :3] # 只取xyz数据
label = stats.mode(data[i:i+window_size, 3])[0][0] # 取窗口内众数
windows.append(window)
labels.append(label)
return np.array(windows), np.array(labels)
4.2 特征提取选项
除了原始时序数据,还可以提取多种特征:
-
时域特征:
- 均值、方差
- 过零率
- 峰值计数
-
频域特征:
- FFT系数
- 功率谱密度
-
统计特征:
- 偏度、峰度
- 四分位距
from scipy import stats
from scipy.fft import fft
def extract_features(window):
"""从窗口数据提取特征"""
features = []
for axis in range(3): # 对每个轴处理
x = window[:, axis]
# 时域特征
features.extend([np.mean(x), np.std(x), np.max(x), np.min(x)])
# 频域特征
fft_vals = np.abs(fft(x))[:len(x)//2]
features.extend([np.mean(fft_vals), np.max(fft_vals)])
# 统计特征
features.extend([stats.skew(x), stats.kurtosis(x)])
return np.array(features)
5. 建模方法比较
5.1 传统机器学习方法
传统方法需要手工设计特征:
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
# 特征工程
X = np.array([extract_features(w) for w in windows])
y = labels
# 随机森林模型
rf = RandomForestClassifier(n_estimators=100)
scores = cross_val_score(rf, X, y, cv=5)
print(f"交叉验证准确率: {np.mean(scores):.2f} (±{np.std(scores):.2f})")
5.2 深度学习方法
深度学习可以直接处理原始时序数据:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense
def build_cnn_model(input_shape, n_classes):
model = Sequential([
Conv1D(64, 3, activation='relu', input_shape=input_shape),
MaxPooling1D(2),
Conv1D(128, 3, activation='relu'),
MaxPooling1D(2),
Flatten(),
Dense(100, activation='relu'),
Dense(n_classes, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
# 数据准备
X = windows.reshape(windows.shape[0], windows.shape[1], 3) # (样本, 时间步, 特征)
y = labels
# 构建模型
model = build_cnn_model((52, 3), 8)
history = model.fit(X, y, validation_split=0.2, epochs=20, batch_size=32)
6. 实际应用建议
6.1 数据不平衡处理
针对数据不平衡问题,可以采取:
- 类别加权损失函数
- 过采样少数类
- 数据增强(添加噪声、时间扭曲)
from sklearn.utils.class_weight import compute_class_weight
class_weights = compute_class_weight('balanced', classes=np.unique(y), y=y)
class_weight_dict = dict(enumerate(class_weights))
model.fit(X, y, class_weight=class_weight_dict, ...)
6.2 模型优化方向
-
架构选择:
- CNN:适合捕捉局部模式
- LSTM:适合时序依赖
- CNN+LSTM:混合架构
-
超参数调优:
- 窗口大小
- 网络深度
- 学习率
-
正则化策略:
- Dropout
- BatchNorm
- 早停法
6.3 部署注意事项
实际部署时需要考虑:
- 实时性要求:选择适当轻量模型
- 传感器校准:确保数据一致性
- 个性化适应:增量学习或微调
- 能耗优化:边缘设备部署方案
7. 扩展与进阶
7.1 多模态数据融合
结合其他传感器数据提升性能:
- 陀螺仪数据
- 心率监测
- 环境传感器
7.2 迁移学习应用
利用预训练模型:
- 在大规模HAR数据集上预训练
- 在小规模目标数据上微调
7.3 自监督学习
减少标注依赖:
- 对比学习(SimCLR)
- 掩码预测(Masked Modeling)
- 时序一致性学习
在实际项目中,我发现数据质量往往比模型选择更重要。确保传感器正确佩戴、数据采集环境稳定,这些因素对最终性能的影响可能超过模型架构的改进。另外,针对特定应用场景设计适当的后处理逻辑(如活动平滑)也能显著提升用户体验。
更多推荐


所有评论(0)