我不知道用什么 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%准确率,我实际测了十几下,怎么都是预测错的😂
兄弟萌,这种数据应该用啥模型的比较好?
1
airqj 2022-04-10 19:48:38 +08:00
从 vgg 枚举到最新模型不就知道了 :)
|
2
ALLROBOT OP |
3
ALLROBOT OP 问了导师结果被喷了😢,说我 CNN 模型和别人的太重复了,写不出来新什么东西
我问能用 VGG 模型,导师一顿狂喷为啥非要用别人的模型,你就不能改一改网络结构吗,至少把精度提高到 90% 😢😢😢 @airqj #1 能指教一下怎么改模型吗 虽然自学了吴恩达、周志华的课程,对于这些模型结构我比较陌生,有什么改模型的诀窍吗,求指路😥 |
4
jdhao 2022-04-10 21:07:06 +08:00 via Android
vgg 肯定不行,都是处理二维图像的,你的数据是一维的,别听不懂的人在那瞎扯淡。
大概率你需要自己试试不同的模型,或者特征上下点功夫,对特征做一些特征工程变换? |
10
Calibans 2022-04-10 21:38:40 +08:00 via iPhone
试试 lstm 或者 transformer
|
11
nightwitch 2022-04-10 21:44:38 +08:00
刚好做过类似的,只是我是在骨架的数据上做的。 在测试集上准确度和现实场景中的准确度会差很多,因为在现实场景下做手势动作的情况太多变了,数据集覆盖不了真实情况。真实的数据流是没有明确的起始和结束的,数据会和你数据集里切好段的差很多。
你把在测试集上的准确度提上来以后,在真实场景下用还要调很久,不是简单套个模型就 ok 的 |
12
airqj 2022-04-10 21:55:53 +08:00
|
13
ALLROBOT OP @Cortez 各个电极的值加起来除以电极的个数得到均值,如果高于休息状态的均值视为活动段,此时时间窗开始滑动
@Calibans 好的,我正想用几个模型看看呢 @nightwitch 真实场景一般怎么调的正好提高精度哈? 我不是手动打标签的,给肌电设了阈值,某个电极的高于阈值可以视为活动段开始,低于的视为结束 关于数据集,我尽可能覆盖面广一点,不同动作或力度的同一手势都收集看看 |
15
ttgo 2022-04-10 21:58:54 +08:00
在一个展会上学生区里见过个类似的,512 还是 128 来着长度的信号识别手势,人家就用了两个 fc 。。
|
18
Gezqh 2022-04-10 22:11:27 +08:00
是时间序列的数据么?可以找一些专门用来对多维时间序列进行分类的模型吧?
|
19
Gezqh 2022-04-10 22:12:07 +08:00
或者是将时间序列数据转换成梅尔频谱试试(时域到频域)?
|
20
ALLROBOT OP |
21
Cortez 2022-04-10 22:41:20 +08:00
@ALLROBOT 我怎么理解的是这个跟时间没关系啊,为什么用时间窗呢?如果每行 16 列是一个数据,各列的顺序又是固定的,哪怕是传感器几百次采样频率中的一次,那也就是一个姿势你可以采集很多组几乎相同的样本,这时候只要后期处理数据时注意 balance 就可以了。等训练好后,每次读出一组 16 列数据就可以进行一次分类。
|