查阅了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字以内,仅用于支线交流,主线讨论请采用回复功能。