MSE模型是我在进行眼电信号处理时遇到的。
简单的说,人在睡眠分为五个时期,分别是S1,S2,S3,S4,REM时期,我们可以将人在一晚上的睡眠数据分段,每一段提取熵值,这个熵值可以作为每一个时期的特征值,这样,通过其他的分类算法就可以进行睡眠分期的预测。
样本熵是通过度量信号中产生新模式的概率大小来衡量时间序列复杂性,新模式产生的概率越大,序列的复杂性越大。
样本熵的值越低,序列自我相似性约到;样本熵的值越大,样本序列就越复杂。
1.粗粒化(数据预处理)
一般来说,粗粒化的过程有两种。
一是非重叠式,每次跳跃τ个数据,取τ个数据做平均以产生新的数据。
粗粒化公式
二是重叠式,每次跳跃1-τ个数据,取τ个数据做平均。
例:有原序列x(1),x(2),x(3)...x(n)令τ=2
非重叠式X(1)=1/2 * (x(1)+x(2)),X(2)=1/2 * (x(3)+x(4))...
重叠式 X(1)=1/2 * (x(1)+x(2)),X(2)=1/2 * (x(2)+x(3))...
参考文献:Multiscale entropy analysis of complex physiologic time series
2.算法流程
个人理解以及算法的可操作性:
1.第一步,读取文本数据即可。
2.第二步,一般定义m为1,2。r取0.15std~20.25std即可,具体参数可以通过实验结果进行调整。
3.第三步,对原向量进行重构,将相邻的点看做一个点。当m取1时,新向量的长度与原向量相同N;当m取2时,新向量的为N-1,但其后序步骤的算法复杂度会大大增加。(2W个数据,跑一个m=2的样本熵加一个长度为10的k-means要284.57656693458557秒,m=3跑了359.2703492641449秒,m=1跑了253.7522554397583秒)同时,在实验中发现,当m取值大于等于4的时候就会出现除0/ln(0)的错误,因为当m取值过高会降低数据之间的耦合,使算出来的距离过大。
4.第四步,定义了距离的概念,找每一个点作为中心,在整段序列中的聚集程度(在[0,1]之间)。当m=1时,直接用一个循环即可;m=2时,可以看代码(重叠式的运用)
5.第五步,求取平均值,找到一个总体的聚散程度。第六步,将m+1后进行再次运行。第六步,简单。
后记:可以从我们的步骤中推断,样本熵是反应信号的复杂程度,且与之呈正比。
Python代码:
def SampEn(U, m, r):
def _maxdist(x_i, x_j):
return max([abs(ua - va) for ua, va in zip(x_i, x_j)])
def _phi(m):
x = [[U[j] for j in range(i, i + m - 1 + 1)] for i in range(N - m + 1)]
B = [(len([1 for x_j in x if _maxdist(x_i, x_j) <= r]) - 1.0) / (N - m) for x_i in x]
return (N - m + 1.0) ** (-1) * sum(B)
N = len(U)
return -np.log(_phi(m + 1) / _phi(m))
def Coarse(nlist, tao):
Coarse_list = []
# 重叠式
# for i in range(0,len(nlist)-tao):
# sum = listSum(nlist[i:i + tao])
# Coarse_list.append(sum / tao * 1.0)
# 非重叠式
for i in range(0,len(nlist),tao):
sum = listSum(nlist[i:i + tao])
Coarse_list.append(sum/tao*1.0)
return Coarse_list
def uSamp(nlist,tao):
Coarse_list = Coarse(nlist, tao)
N = len(Coarse_list)
narray = np.array(Coarse_list)
#注释的是手工算方差
# sum1 = narray.sum()
# narray2 = narray * narray
# sum2 = narray2.sum()
# mean = sum1 / N
# var = sum2 / N - mean ** 2
var = np.var(narray)
std = math.sqrt(var)
return SampEn(Coarse_list, 2, 0.20 * std)
网友评论