人体活动识别:时序加速度数据的训练测试划分与建模咨询
跨受试者时序加速度数据分类建模方案
一、数据集说明
你已将41位受试者的100Hz加速度数据读取为subjects列表,单份数据集结构如下:
test = subjects[0] print(test.head()) print(test.info())
输出:
x y z label 0 0.000964 -0.001134 0.006626 0 1 0.001184 -0.001213 0.009387 0 2 0.000443 -0.001731 0.008007 0 3 -0.000256 -0.000379 0.006897 0 4 0.000328 0.000040 0.005098 0 <class 'pandas.core.frame.DataFrame'> RangeIndex: 1229597 entries, 0 to 1229596 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 x 1229597 non-null float64 1 y 1229597 non-null float64 2 z 1229597 non-null float64 3 label 1229597 non-null int64 dtypes: float64(3), int64(1) memory usage: 37.5 MB None
二、数据集划分:按受试者拆分(推荐)
你的初步划分方案完全合理,跨受试者拆分是时序行为数据的标准做法,能避免数据泄露(若打乱时序拆分,模型会接触到同一受试者的未来数据,泛化能力严重下降)。
# 41 subjects in total train_data = subjects[:29] # ~70% 训练集 validation_data = subjects[29:33] # ~10% 验证集 test_data = subjects[33:] # ~20% 测试集
若想更严谨,可先按label的分布分层挑选受试者,确保各集合的类别比例与整体一致。
三、特征工程:滑动窗口提取时序特征
原始加速度点无法直接用于分类,需通过滑动窗口提取时域、频域特征,捕捉运动模式:
- 窗口大小:100Hz采样率下,选1秒窗口(100个点),足够覆盖基本动作周期
- 滑动步长:50个点(50%重叠),平衡特征数量与计算成本
特征提取函数示例
import pandas as pd import numpy as np from scipy.stats import kurtosis, skew from scipy.fftpack import fft def extract_window_features(window, labels): # 时域特征:均值、标准差、极值、峰度、偏度 mean = np.mean(window, axis=0) std = np.std(window, axis=0) max_val = np.max(window, axis=0) min_val = np.min(window, axis=0) kurt = kurtosis(window, axis=0) skewness = skew(window, axis=0) # 频域特征:FFT正频率部分能量 fft_vals = fft(window, axis=0) freq_energy = np.sum(np.abs(fft_vals[:len(fft_vals)//2]), axis=0) # 合并所有特征 features = np.concatenate([mean, std, max_val, min_val, kurt, skewness, freq_energy]) # 窗口标签:取窗口内出现次数最多的标签(适配逐帧标注场景) window_label = pd.Series(labels).mode()[0] return features, window_label def process_subject(subject_df, window_size=100, step_size=50): features = [] labels = [] n_samples = len(subject_df) # 滑动窗口遍历数据 for start in range(0, n_samples - window_size + 1, step_size): end = start + window_size # 提取x/y/z三轴窗口数据 window_data = subject_df[['x','y','z']].values[start:end] window_labels = subject_df['label'].values[start:end] feat, lbl = extract_window_features(window_data, window_labels) features.append(feat) labels.append(lbl) return np.array(features), np.array(labels)
批量处理所有数据集
# 处理训练集 X_train, y_train = [], [] for subj in train_data: X_sub, y_sub = process_subject(subj) X_train.append(X_sub) y_train.append(y_sub) X_train = np.concatenate(X_train, axis=0) y_train = np.concatenate(y_train, axis=0) # 处理验证集 X_val, y_val = [], [] for subj in validation_data: X_sub, y_sub = process_subject(subj) X_val.append(X_sub) y_val.append(y_sub) X_val = np.concatenate(X_val, axis=0) y_val = np.concatenate(y_val, axis=0) # 处理测试集 X_test, y_test = [], [] for subj in test_data: X_sub, y_sub = process_subject(subj) X_test.append(X_sub) y_test.append(y_sub) X_test = np.concatenate(X_test, axis=0) y_test = np.concatenate(y_test, axis=0)
四、模型训练与调参
以Random Forest为例,完成训练、调参与验证:
from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix from sklearn.model_selection import GridSearchCV # 初始化基础模型 rf_model = RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1) # 训练模型 rf_model.fit(X_train, y_train) # 验证集初步评估 y_val_pred = rf_model.predict(X_val) print("=== 验证集初步评估 ===") print(classification_report(y_val, y_val_pred)) print(confusion_matrix(y_val, y_val_pred)) # 网格搜索调参(优化模型性能) param_grid = { 'n_estimators': [100, 200], 'max_depth': [None, 10, 20], 'min_samples_split': [2, 5] } grid_search = GridSearchCV(estimator=rf_model, param_grid=param_grid, cv=3, n_jobs=-1, verbose=2) grid_search.fit(X_val, y_val) best_rf = grid_search.best_estimator_
五、测试集最终评估
用从未见过的测试集验证模型泛化能力:
y_test_pred = best_rf.predict(X_test) print("=== 测试集最终评估 ===") print(classification_report(y_test, y_test_pred)) print(confusion_matrix(y_test, y_test_pred))
关键注意事项
- 窗口大小可根据任务调整:若动作周期短,可缩小窗口(如50个点=0.5秒)
- 特征扩展:可添加三轴相关性、时域峰值计数、频域特定频段能量等特征
- 标签处理:若窗口内标签不一致,可根据任务选择取最后一个标签、加权平均标签等方式
内容的提问来源于stack exchange,提问作者Maxl Gemeinderat
相关产品推荐
相关产品推荐

