师兄,不好意思,写报告时考虑到,下午提到的方法不能解决当前的问题,我会先完成当前GPU实现,同时考虑其他的解决方法或其他聚类算法。
1.问题来源
对于masked_EM 算法,其实是GMM(高斯混合模型)算法的扩展版本,那么masked_EM 算法也同样分E步和M步进行迭代,具体过程如下:
M步:
E步:
我们可以看到在M步计算出sigma后,更新E步需要求sigma的逆矩阵,但直接经过M步得到的协方差矩阵并不能保证是可逆的,在目前的Python和C++的代码中,处理方法都是如果该cluster的cov不可逆,直接丢弃该cluster(代码中将该cluster的id标为0)。
因为目前的小数据跑的实验结果,经常有协方差矩阵不可逆,对小数据本来信息就不够,如果丢弃一部分cluster,性能可能会更差,所以我在网上找到一篇博客,关于如何处理GMM算法中协方差矩阵不可逆的问题:Click here~
这篇博客很清楚的讲解了如何处理计算出的协方差矩阵出现不可逆,但协方差矩阵为什么不可逆,我之前并没有深入思考,作者这样解释:
那么我们之前的关于协方差矩阵不可逆问题差不多可以解决了,但是如上面的作者提到的,当数据维度(目前32信道,每个信道3个主成分,即96 维)大于数据点数(spike的个数)时,很可能出现overfiting,我想效果也是不好的,我目前的Python的代码和C++代码跑了0.5s数据(10000个采样点*32信道)和2.5s数据,0.5s分类的效果很差,Python的结果只分出了噪声类和另外一个类,2.5s的效果好一点:
0.5秒的数据(10000个采样点*32信道) 2.5秒的数据(50000个采样点*32信道)2.解决方案
基于上面的GMM算法在小数据集上的表现不佳,我认为有两种思路可以考虑:
思路一:GMM算法的性能取决于数据集的大小(更严格的说取决于所选数据集里面检测到的spike的个数),那么只要使数据集尽可能大,那么就可以尽量保证在不更换或改进当前masked_EM算法的基础上,得到比较好的性能,而我们最大的数据集的大小取决于我们达到实时的目的下能处理的最大的数据量,但是现在由于GPU端的代码并没有完成,所以无法确定我们的数据块最大要多大,我会尽快完成后面的聚类算法的GPU实现,从而验证是否数据量过小。
思路二:由于这个问题的关键是由于cluster的协方差矩阵引起的,其中涉及的参数有spike的个数和数据的维度,也就是说只需要PCA之后提取的spike的特征,之前我们的思路是基于采样点的window_base,每个窗口(我们实时所能计算的最大的数据量)提取的spike进行处理,这样可以粗略保证窗口的大小(采样点的个数),但是每个window产生的spike的数量可能比较少,就容易出现上面的不可逆现象。
那么我们可以基于spike的个数的Window_base,即每个协方差的spike的个数可以大于维度,从而减小协方差矩阵的不可逆的概率。
后来又认真的考虑了一下,cov的计算是考量一个cluster内的所有spike的特征之间的相关性,那么随着EM算法的迭代,我们无法确定每一个cluster中的spike的个数,所以上面的不可逆及overfiting问题基于spike的个数的Window_base的方法行不通。
更新于9.28讨论之后。。。
师兄:
我看了这个这个报告。在里面引用的文章里,作者也讲了,要么增加训练数据的量,要么降低模型复杂度,也就是要减少我们模型里的参数。但是我们模型里的参数其实就是已经被算法固定好了。但是我们的基于window来实现real time想法里,要么就是改变window的大小增加包含的spike的数,从而使每一个窗口的取逆操作都可行,要么就是考虑上一个窗口的数据(中间或者结果数据)在一定程度上在下一个窗口得到复用,这样既能保证实时,也不需要所有数据ready了才能进行处理。换句话说,我们有两层的window,第一层的窗口都比较小,包含的spike也较小,所以分出来的类也比较粗。第二层“隐含”的窗口的较大,但是它里面的数据是前面已经粗略分过类的spike加当前的第一层小窗口的数据。这些数据包含的spike数较多,从而能保证每一个这样的大窗口所得到的cluster都有足够的spike,从而可以直接套用他们的算法,而且计算量也不会太多(因为已经有前面的粗略分类结果)。
我:
①我们的代码中,默认参数初始cluster的个数为500,当然我们可以改小一点,但即使改为50,那么对于一个window,假设我们检测到了500个spike,那么最坏的情况就是每个cluster只有50个spike,那么对于当前的cluster,50个点96维,并不可逆,同时随着EM迭代,其实我们无法确定每个簇的spike的个数,但是对于大量spike的数据,那些有大量spike的簇肯定会逐渐趋于稳定,所以他的代码中直接丢弃不可逆的簇也是可以理解的,但是我们当前的窗口的数据,得到的簇以及簇中的spike的数目远达不到稳定的状态。换句话说,取逆操作是基于cluster,是否可逆基于cluster中的spike的数,并不基于window中的总spike数目(虽然总spike越大,某些主要簇越可能越稳定)
②我们肯定要考虑前一个窗口的数据复用,但是目前还没有思路,师兄说的两层窗口,感觉有点像RNN(LSTM),当前节点的数据(当前第一层window)加上之前处理出来的信息流(之前所有window的特征),这个我再仔细考虑一下,毕竟之前得到的信息流用什么表征,之后怎么复用没有考虑过。
网友评论