转自:https://blog.csdn.net/cratial/article/details/79742363
建议查看原文
关于本博客的说明: 本次博客主要分享样本熵(Sample Entropy, SampEn, SE)的理论相关知识及其代码实现.
之前分享过一篇有关近似熵的博客“近似熵理论相关知识与代码实现”,有兴趣的博友欢迎前往观看,不足之处还请不吝赐教!https://blog.csdn.net/cratial/article/details/79707169
一、理论基础
样本熵(SampEn)是基于近似熵(ApEn)的一种用于度量时间序列复杂性的改进方法,在评估生理时间序列的复杂性和诊断病理状态等方面均有应用[1].
由于样本熵是近似熵的一种改进方法,因此可以将其与近似熵联系起来理解.
算法表述如下:
设存在一个以等时间间隔采样获得的NN维的时间序列u(1),u(2),...,u(N)u(1),u(2),...,u(N).
定义算法相关参数mm,rr,其中,mm为整数,表示比较向量的长度,rr为实数,表示“相似度”的度量值.
重构mm维向量X(1),X(2),...,X(N−m+1)X(1),X(2),...,X(N−m+1),其中X(i)=[u(i),u(i+1),...,u(i+m−1)]X(i)=[u(i),u(i+1),...,u(i+m−1)].
对于1≤i≤N−m+11≤i≤N−m+1,统计满足以下条件的向量个数
Bmi(r)=(number of X(j) such that d[X(i),X(j)]≤r)/(N−m), i≠j
Bim(r)=(number of X(j) such that d[X(i),X(j)]≤r)/(N−m), i≠j
其中,d[X,X∗]d[X,X∗]定义为d[X,X∗]=maxa|u(a)−u∗(a)|, X≠X∗d[X,X∗]=maxa|u(a)−u∗(a)|, X≠X∗
u(a)u(a)为向量XX的元素,dd表示向量X(i)X(i)与X(j)X(j)的距离,由对应元素的最大差值决定,jj的取值范围为[1,N−m+1][1,N−m+1],但是j≠ij≠i.
求Bmi(r)Bim(r)对所有ii值的平均值,记为Bm(r)Bm(r),即
Bm(r)=(N−m+1)−1∑i=1N−m+1Bmi(r)
Bm(r)=(N−m+1)−1∑i=1N−m+1Bim(r)
.
令k=m+1k=m+1,重复步骤3-4,得Ak(r)=(N−k+1)−1∑N−k+1i=1Aki(r)Ak(r)=(N−k+1)−1∑i=1N−k+1Aik(r),其中
Aki(r)=(number of X(j) such that d[X(i),X(j)]≤r)/(N−k), i≠j
Aik(r)=(number of X(j) such that d[X(i),X(j)]≤r)/(N−k), i≠j
则样本熵(SampEn)定义为
SampEn=limN→∞{−ln[Ak(r)/Bm(r)]}
SampEn=limN→∞{−ln[Ak(r)/Bm(r)]}
由于在实际计算应用过程中,NN不可能为∞∞,因此当NN取有限值时,样本熵估计为
SampEn=−ln[Ak(r)/Bm(r)]}
SampEn=−ln[Ak(r)/Bm(r)]}
其中, lnln表示自然对数,mm和rr由第2步定义.
参数选择:嵌入维数mm一般取1或2;相似容限rr的选择在很大程度上取决于实际应用场景,通常选择r=0.1∗std∼0.25∗stdr=0.1∗std∼0.25∗std,其中stdstd表示原时间序列的标准差.
近似熵与样本熵理论上的对比[2]
设BB为维数为mm时,时间序列的自相似概率;AA为维数为k=m+1k=m+1时,时间序列的自相似概率,得出CP=A/BCP=A/B。近似熵的计算是以−ln(CP)−ln(CP)为模型,并且计算出了所有模型的平均值。为了防止出现计算ln(0)ln(0)的情况,近似熵在算法的第4步中包含了与自身向量的比较,这种方式与新信息观点是不相容的,所以一定会存在偏差。不同的是,样本熵计算的是和的对数,且不包含与自身向量的比较,所以其优势在于包含更大的A、BA、B,以及更加准确的CPCP估计.
与近似熵相比,样本熵具有两个优势:样本熵的计算不依赖数据长度;样本熵具有更好的一致性,即参数mm和rr的变化对样本熵的影响程度是相同的.
二、代码实现
Python
(备注:示例程序是根据上文算法在Wikipedia关于Sample entropy的python实现代码上进行修改后得到的[1])
# SampEn calculation
import numpy as np
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))
# Usage example
U = np.array([85, 80, 89] *17)
print(SampEn(U,2,3))
令输入数据为一个以3为周期的周期时间序列,维度N=51N=51,即
SN={85,80,89,85,80,89,...}
SN={85,80,89,85,80,89,...}
设定参数:嵌入维度m=2m=2,相似容限r=3r=3
程序输出样本熵 SampEn=0.0008507018803128114SampEn=0.0008507018803128114
MATLAB
(备注:示例程序是根据上文算法在Kijoon Lee分享的样本熵代码“SampE”[3]的基础上修改得来的,在此表示感谢!)
% notification: this is a modification work based on that of Kijoon Lee.
function saen = SampEntropy( dim, r, data, tau )
% SAMPEN Sample Entropy
% calculates the sample entropy of a given time series data
% SampEn is conceptually similar to approximate entropy (ApEn), but has
% following differences:
% 1) SampEn does not count self-matching. The possible trouble of
% having log(0) is avoided by taking logarithm at the latest step.
% 2) SampEn does not depend on the datasize as much as ApEn does. The
% comparison is shown in the graph that is uploaded.
% dim : embedded dimension
% r : tolerance (typically 0.2 * std)
% data : time-series data
% tau : delay time for downsampling (user can omit this, in which case
% the default value is 1)
%
if nargin < 4, tau = 1; end
if tau > 1, data = downsample(data, tau); end
N = length(data);
result = zeros(1,2);
for m = dim:dim+1
Bi = zeros(1,N-m+1);
dataMat = zeros(m,N-m+1);
% setting up data matrix
for i = 1:m
dataMat(i,:) = data(i:N-m+i);
end
% counting similar patterns using distance calculation
for j = 1:N-m+1
% calculate Chebyshev distance, excluding self-matching case
dist = max(abs(dataMat - repmat(dataMat(:,j),1,N-m+1)));
% calculate Heaviside function of the distance
% User can change it to any other function
% for modified sample entropy (mSampEn) calculation
D = (dist <= r);
% excluding self-matching case
Bi(j) = (sum(D)-1)/(N-m);
end
% summing over the counts
result(m-dim+1) = sum(Bi)/(N-m+1);
end
saen = -log(result(2)/result(1));
end
采用与Python实现代码相同的计算数据与参数,得到样本熵为SampEn=8.507018803128114e−04SampEn=8.507018803128114e−04,此结果与Python计算结果一致.
参考文献:
[1]. https://en.wikipedia.org/wiki/Sample_entropy
[2]. 李立,曹锐,相洁.脑电数据近似熵与样本熵特征对比研究[J].计算机工程与设计,2014,35(03):1021-1026.
[3]. https://cn.mathworks.com/matlabcentral/fileexchange/35784-sample-entropy?s_tid=srchtitle