查阅了NinaPro的原始论文,ps:他们的官网是真的烂,图片没显示,害我找了好久。
XXXXXXXXXXXXXXXXXXXXXX/DB9_Instructions
另外使用了DB9论文中的角度换算
尝试使用这个转换DB8中的手套数据,并使用UE4进行可视化。
然而论文里的源码并不能运行,在连续改了两个bug跑出来以后,得到的角度数据没有参考系,等于无法复现。焯!
然后我就寻思了,手套传感器数据通过隐函数映射到手指姿态,虽然论文里的隐函数转换脚本没法用了,但是我可以直接输出传感器数据啊,四舍五入我也得到手指姿态了。绝对不是为了赶论文。
然后我就快乐的写了一大片代码开始跑上面得到的数据集。
考虑到论文最好不全公开,我就贴下网络结构。PS 目前没调好,不一定能收敛。
class MyNet(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_chan):
super(MyNet, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size,
hidden_size,
num_layers,
batch_first=True)
#input tensor of shape (sequence length, batch size, input_size)
self.fc=nn.Linear(hidden_size, output_chan)
""" self.fc = nn.Sequential(
nn.Dropout(droprate), #Dropout层
nn.LeakyReLU(),
nn.Linear(hidden_size, 64),
nn.LeakyReLU(),
nn.Linear(64, output_chan)) """
#把隐藏状态空间用全连接层映射到输出空间。
def forward(self, x):
#初始化hidden和cell的states 不赋予初值所以用zeros
#详情:https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html
h0 = torch.zeros(self.num_layers, x.size(0),
self.hidden_size).to(device)
c0 = torch.zeros(self.num_layers, x.size(0),
self.hidden_size).to(device)
#LSTM
output, (hn, cn) = self.lstm(x, (h0, c0))
#tensor of shape (batch size, sequence length, hidden_size)
output = self.fc(output[:, -1, :]) #取sequence的最后一个输出hn
#tensor of shape (batch size, sequence length, hidden_size)
return output
开始炼丹!
这400多w的Loss是怎么来的???
刚开始,我还以为是梯度爆炸了之类的,毕竟我的Loss从几十万到几百万都有,很是奇怪,所以我先从这方面入手
这Loss这么大是不是我网络有问题啊?
询问了大佬后突然发现了一个盲点,我的数据是EMG数据集,用的是LSTM,激活函数默认为tanh,然后EMG数据大概是e-6量级,感觉会有问题,所以做了归一化。
归一化脚本:
def data_scaler(input_list):
"""
@description :
---------
@param :
-------
@Returns :
-------
"""
scaler = MinMaxScaler(copy=False)
matData=input_list[0]
matFile=input_list[1]
norm_data={}
norm_data['emg'] = []
scaler.fit(matData['emg'])
norm_data['emg']=scaler.transform(matData['emg'])
matData['emg']=norm_data['emg']
sio.savemat(saveDir+matFile, matData)
pool = ThreadPool()
mat_list=[]
for matFile in findAllMat():
matData=sio.loadmat(dataDir+matFile)
mat_list.append([matData,matFile])
results = pool.map(data_scaler, mat_list)
pool.close()
pool.join()
抽空再试试标准化。
然后继续训练,中间又改小了batch_size,由于Loss是整个batch的Loss和,所以Loss确实小了点,但是也没小多少,归一化以后结果好像没啥变化···不管了,归一化做了是对的,先这样跑吧,只要能收敛就行。
然后我发现了Loss的一个规律
这玩意一会儿高一会儿低的怎么?
经过分析我发现
大概23680条数据为一个周期,一个文件大概有2292000条
有0-9个动作,其中0为复位
每个动作会重复10次
data_total=2292000
data_total/9(个动作)/10(10次重复)=25472 非常接近23680的数量级,也就是说动作改变的时候loss会突增突减
那行吧,好像也没啥问题,先跑着。
然后在我的3080跑了一小时之后
???我的Loss呢!!!
我那么大的Loss,几百万呢?怎么突然就没了?
俺跑了两遍,都是在这里Loss消失,又百度了下。高度怀疑是数据集本身有问题。
经过写脚本定位查找以后,从7个G的数据集里成功揪出来了丢失的数据
mad,这群*人不会做数据集能不能不要做,跑了俩小时直接给我干废了
又把他们截掉然后重新跑。
脚本贴一下吧,这个nan问题很是花了我一番功夫
import numpy as np
import scipy.io as sio
import matplotlib.pyplot as plt
import os
from torch.utils.data import Dataset
import torch
from math import isnan
dataDir = './EMG_data/linear/'
saveDir = './EMG_data/nan_deled/'
def findAllMat():
"""
@description :找到dataDir下所有的mat文件
---------
@param :
-------
@Returns :
-------
"""
for root,dirs,files in os.walk(dataDir):
for f in files:
if(f.split('.')[-1]=="mat"):
yield f
def readMat(mData, name, del_nan):
"""
@description :读取并处理mat文件,找到nan的数据
---------
@param :mData 数据 name文件名 del_nan是否处理
-------
@Returns :
-------
"""
h=-1
l=-1
mlist=['emg','glove','rerepetition','restimulus']
for i in range(0,4):
foo=mData[mlist[i]]
if(len(np.where(np.isnan(foo))[0])):
h=np.where(np.isnan(foo))[0][0] #行数-1(索引)
l=np.where(np.isnan(foo))[1][0] #列数-1
#print(name)
break
if(h!=-1 and del_nan):
for i in range(0,4):
mData[mlist[i]]=mData[mlist[i]][:h,]
sio.savemat(saveDir+name, mData)
for matFile in findAllMat():
matData = sio.loadmat(dataDir + matFile)
readMat(matData, matFile, True)
最后都整的差不多了,打算挂一晚上,看看能不能跑收敛。
明天更不更看心情了。
200字以内,仅用于支线交流,主线讨论请采用回复功能。