请教一下,肌电的手势分类的应该用啥 CNN 模型?

2022-04-10 19:31:10 +08:00
 ALLROBOT

我不知道用什么 CNN 分类器能很好预测值

16 个电极模拟的值,每列代表某个电极在人体表面读取的生物信号强度数值,等数据缩放完了,数据格式大概如下:

[[-0.00001221  0.00001285  0.00000142 -0.00000145  0.00000089  0.00000128
  -0.00000432 -0.0000021  -0.00001083 -0.00000186 -0.000001   -0.00000192
   0.00000232  0.00000245 -0.00000036  0.00000399]
 [-0.00001103  0.00001196 -0.00000081 -0.00000296  0.00000162  0.00000013
  -0.00000231 -0.0000021  -0.00000726 -0.00000127  0.00000254 -0.00000042
   0.00000163  0.00000758 -0.00000008  0.00000972]
   ...
   ]

若使用 PIL 的 Image.fromarray(200 条 16 列的数值矩阵),输出为:

假若手打出 6 的手势,那么 16 个电极的一些电极贴近弯曲 3 个手指向后的手臂肌肉层能读取比较大的数值

可是,我用以下的代码训练几百轮,结果预测效果不太好,好几次预测,总是把实际值为 1 的手势预测输出 6

    def CNN(input_shape=(100,16,1), classes=9):
        X_input = Input(input_shape)

        X = Conv2D(filters=64, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='tanh', name='conv1')(
            X_input)
        X = MaxPooling2D(pool_size=(10, 1), strides=(10, 1), name='pool1')(X)

        X = Conv2D(filters=64, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='tanh', name='conv2')(X)
        X = MaxPooling2D(pool_size=(2, 1), strides=(2, 1), name='pool2')(X)

        X = Conv2D(filters=128, kernel_size=(3, 1), strides=(1, 1), padding='same', activation='tanh', name='conv3')(X)
        X = MaxPooling2D(pool_size=(2, 1), strides=(2, 1), name='pool3')(X)

        X = Flatten(name='flatten')(X)
        X = Dropout(0.5)(X)
        X = Dense(64, activation='tanh', name='fc1')(X)
        X = Dropout(0.4)(X)
        X = Dense(64, activation='tanh', name='fc2')(X)
        X = Dropout(0.3)(X)
        X = Dense(classes, activation='softmax')(X)

        model = Model(inputs=X_input, outputs=X, name='MultipleCNN')
        return model
        
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train, Y_train, epochs=500, batch_size=64, verbose=1,validation_data=(X_test, Y_test), callbacks=callbacks_list)

输出

......
Epoch 00999: val_accuracy did not improve from 0.82502
Epoch 1000/1000
138/138 [==============================] - 1s 8ms/step - loss: 0.0639 - accuracy: 0.9790 - val_loss: 1.0930 - val_accuracy: 0.8060

Epoch 01000: val_accuracy did not improve from 0.82502
276/276 [==============================] - 1s 3ms/step - loss: 0.0034 - accuracy: 0.9990
Train Loss = 0.003447444410994649
Train Accuracy = 0.9989800453186035
69/69 [==============================] - 0s 3ms/step - loss: 1.0930 - accuracy: 0.8060
Test Loss = 1.0929756164550781
Test Accuracy = 0.8059836626052856
time: 1228.2580664157867

我迷糊了,测试集有 80%准确率,我实际测了十几下,怎么都是预测错的😂

兄弟萌,这种数据应该用啥模型的比较好?

1748 次点击
所在节点    程序员
23 条回复
airqj
2022-04-10 19:48:38 +08:00
从 vgg 枚举到最新模型不就知道了 :)
ALLROBOT
2022-04-10 20:23:37 +08:00
@airqj #1 VGG 枚举到最新模型?原谅我,我是深度学习野路子的,你说的 VGG 怎么枚举到最新模型我真不知道😂

(网上有 VGG 模型,我姑且试试看吧)
ALLROBOT
2022-04-10 20:59:25 +08:00
问了导师结果被喷了😢,说我 CNN 模型和别人的太重复了,写不出来新什么东西

我问能用 VGG 模型,导师一顿狂喷为啥非要用别人的模型,你就不能改一改网络结构吗,至少把精度提高到 90%

😢😢😢 @airqj #1 能指教一下怎么改模型吗

虽然自学了吴恩达、周志华的课程,对于这些模型结构我比较陌生,有什么改模型的诀窍吗,求指路😥
jdhao
2022-04-10 21:07:06 +08:00
vgg 肯定不行,都是处理二维图像的,你的数据是一维的,别听不懂的人在那瞎扯淡。

大概率你需要自己试试不同的模型,或者特征上下点功夫,对特征做一些特征工程变换?
ALLROBOT
2022-04-10 21:08:42 +08:00
@jdhao #4 VGG 应该可以的,因为我把肌电数据处理成二维图像,再输入到模型中
ALLROBOT
2022-04-10 21:10:08 +08:00
导师带过几个涉及深度学习的项目😂
@jdhao #4
jdhao
2022-04-10 21:14:59 +08:00
@ALLROBOT 你这数据就 16 维,你怎么转图像? vgg 输入都是 224*224*3 的图像
ALLROBOT
2022-04-10 21:18:51 +08:00
@jdhao 以时间窗滑动,每个时间窗内的 16 列数据处理成( 100 ,16 ,1 )
Cortez
2022-04-10 21:33:38 +08:00
@ALLROBOT 不是 1 行 16 列的信号对应一个动作嘛?
Calibans
2022-04-10 21:38:40 +08:00
试试 lstm 或者 transformer
nightwitch
2022-04-10 21:44:38 +08:00
刚好做过类似的,只是我是在骨架的数据上做的。 在测试集上准确度和现实场景中的准确度会差很多,因为在现实场景下做手势动作的情况太多变了,数据集覆盖不了真实情况。真实的数据流是没有明确的起始和结束的,数据会和你数据集里切好段的差很多。

你把在测试集上的准确度提上来以后,在真实场景下用还要调很久,不是简单套个模型就 ok 的
airqj
2022-04-10 21:55:53 +08:00
@jdhao 大把模型把一维数据转成二维数据然后用 cnn 来识别,比如有的语音识别就先把语音信号来个 fft 处理再输入 cnn
@ALLROBOT 怪我没审好题。你这数据才 16 维,感觉都用不到 cnn,xgboost 大法试试
ALLROBOT
2022-04-10 21:56:34 +08:00
@Cortez 各个电极的值加起来除以电极的个数得到均值,如果高于休息状态的均值视为活动段,此时时间窗开始滑动

@Calibans 好的,我正想用几个模型看看呢


@nightwitch 真实场景一般怎么调的正好提高精度哈?

我不是手动打标签的,给肌电设了阈值,某个电极的高于阈值可以视为活动段开始,低于的视为结束

关于数据集,我尽可能覆盖面广一点,不同动作或力度的同一手势都收集看看
ALLROBOT
2022-04-10 21:57:55 +08:00
@airqj 网上的数据集是 16 列的,现实的传感器仅有 6 个(#-.-)
ttgo
2022-04-10 21:58:54 +08:00
在一个展会上学生区里见过个类似的,512 还是 128 来着长度的信号识别手势,人家就用了两个 fc 。。
ALLROBOT
2022-04-10 21:59:45 +08:00
@Cortez 再补充一下,每行 16 列是传感器几百次采样频率中的一次
airqj
2022-04-10 22:05:34 +08:00
@ALLROBOT 说不定回归模型还靠谱一些 🐶
Gezqh
2022-04-10 22:11:27 +08:00
是时间序列的数据么?可以找一些专门用来对多维时间序列进行分类的模型吧?
Gezqh
2022-04-10 22:12:07 +08:00
或者是将时间序列数据转换成梅尔频谱试试(时域到频域)?
ALLROBOT
2022-04-10 22:39:16 +08:00
@ttgo #15 很惭愧,我比不上人家调的优秀

@Gezqh #18 大概不是?时间序列是随着时间流动收集数据的,模型按不同时间预测数据可能对应的状态,而肌电活动段按时间窗口分割的,单单提取一个时间窗口不分时间前后,模型只对一个时间窗内的不同电极的生物信号强度,负责对比各列的数值大小从而预测对应的状态,预测状态和上一个或下一个时间窗口关系不大(如果时间窗口包括休息状态的肌电,预测容易出错)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/846113

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX