You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于三轴加速度计数据的CNN人体活动分类模型输入维度错误问题

问题描述

基于智能手机三轴加速度计(x、y、z轴)数据对6种人体活动分类,已用Random Forest、KNN、MLP、LDA实现80-90%的准确率,现在尝试CNN但遇到维度不兼容问题。

数据集情况:共2086923行×4列,包含3列加速度数据(x-accel、y-accel、z-accel)和1列活动标签。

尝试的代码如下:

train,test = train_test_split(df,test_size=0.3,random_state=42)
X_train = train[train.columns[2:4]]
y_train = train['Activity']
X_test = test[test.columns[2:4]]
y_test = test['Activity']

model=Sequential()

model.add(Conv2D(32,(3,3),activation='relu',input_shape=(3,)))
model.add(MaxPool2D(2,2))
model.add(Flatten())
model.add(Dense(100,activation='relu'))
model.add(Dense(10,activation='softmax'))

model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
model.fit(X_train,y_train,epochs=10)
model.evaluate(X_test,y_test)

运行后报错:

ValueError: Input 0 of layer "conv2d_1" is incompatible with the layer: expected min_ndim=4, found ndim=2. Full shape received: (None, 3)


解决方案

核心问题分析

  • Conv2D不适用于时序加速度数据:Conv2D是为图像设计的二维卷积层,要求输入为4维张量(样本数×图像高度×图像宽度×通道数),但你的输入是2维(样本数×3个轴的加速度值),维度不匹配导致报错。
  • 未做时序窗口分割:加速度数据是时序数据,单个时间点的3个值无法体现运动的时序特征,CNN需要处理连续的时间窗口样本才能捕捉动作模式。

具体修正步骤

1. 生成时序窗口样本

先定义函数,将原始时序数据分割成连续时间窗口(窗口大小可根据数据采样率调整,示例用30):

import numpy as np

def create_sequence_data(X, y, window_size=30):
    sequences = []
    labels = []
    for i in range(len(X) - window_size):
        # 取连续window_size个时间步的加速度数据
        seq = X.iloc[i:i+window_size].values
        # 取窗口最后一个时间步的标签作为样本标签
        label = y.iloc[i+window_size]
        sequences.append(seq)
        labels.append(label)
    return np.array(sequences), np.array(labels)

2. 预处理训练/测试数据

修正列索引确保取到完整的x、y、z三列数据,同时生成时序样本并编码标签:

# 修正列索引:确保取到x、y、z三列加速度数据(根据实际列位置调整)
X_train = train[['x-accel', 'y-accel', 'z-accel']]
y_train = train['Activity']
X_test = test[['x-accel', 'y-accel', 'z-accel']]
y_test = test['Activity']

# 生成时序窗口样本
window_size = 30
X_train_seq, y_train_seq = create_sequence_data(X_train, y_train, window_size)
X_test_seq, y_test_seq = create_sequence_data(X_test, y_test, window_size)

# 标签整数编码(适配sparse_categorical_crossentropy损失函数)
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y_train_seq = le.fit_transform(y_train_seq)
y_test_seq = le.transform(y_test_seq)

3. 用Conv1D构建适配的模型

Conv1D专为一维时序数据设计,输入为3维张量(样本数×时间步长度×特征数),完全匹配时序窗口样本:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense

model = Sequential()
# 输入形状为(窗口长度, 特征数),对应(30,3)
model.add(Conv1D(filters=32, kernel_size=3, activation='relu', input_shape=(window_size, 3)))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
# 输出层神经元数等于活动类别数(6种)
model.add(Dense(6, activation='softmax'))

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
# 训练模型
model.fit(X_train_seq, y_train_seq, epochs=10, batch_size=32)
# 评估模型
test_loss, test_acc = model.evaluate(X_test_seq, y_test_seq)
print(f"测试准确率: {test_acc:.4f}")

额外优化建议

  • 调整窗口大小:根据数据采样率调整,比如50Hz采样率下,30个窗口对应0.6秒动作片段,可尝试20-50区间的数值。
  • 添加Dropout层:在Dense层之间加入Dropout(0.2)抑制过拟合。
  • 调整卷积参数:尝试增加filters数量(64、128)或调整kernel_size(5、7)提升性能。

内容的提问来源于stack exchange,提问作者Matheus Torres

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 18:42:47