符号说明:
x-输入信号矢量(如脑电信号或声音信号)
nSf-比例因子的数量
m-模板长度(历元长度);Costa使用m=2
r-匹配阈值;通常选择在
时间序列的样本偏差;当x经过z变换时:将公差定义为r乘以标准偏差
mse-多尺度熵
sf-与mse相对应的比例因子
解释:Costa解释了更高的熵值以反映更多在这个尺度上的信息(如果是随机的,则不太可预测)。在天平上相当稳定。
参考文献:
Costa等人。(2002)复杂生理学的多尺度熵分析时间序列。
Costa等人。(2005)生物信号的多尺度熵分析。
MSE_Costa2005
function [mse sf] = MSE_Costa2005(x,nSf,m,r)
% pre-allocate mse vector
mse = zeros([1 nSf]);
% coarse-grain and calculate sample entropy for each scale factor
for ii = 1 : nSf
% get filter weights
f = ones([1 ii]);
f = f/sum(f);
% get coarse-grained time series (i.e., average data within non-overlapping time windows)
y = filter(f,1,x);
y = y(length(f):end);
y = y(1:length(f):end);
% calculate sample entropy
mse(ii) = SampleEntropy(y,m,r,0);
end
% get sacle factors
sf = 1 : nSf;
colored_noise
function [y] = colored_noise(Sf,dur,b)
% [y] = colored_noise(Sf,dur,b)
%
% Sf - sampling frequency
% dur - duration
% b - exponent of the 1/f^b power law function
% b = 0 (white), 1 (pink), 2 (brown), -1 (blue), -2 (violet)
%
% y - noise time domain signal
% (y is normalized such that mean(y)==0 and std(y)==1)
%
% Description: The script calculates a colored noise.
% get number of samples
N = round(Sf * dur);
if mod(N,2)
M = N + 1;
else
M = N;
end
% get fourier spectrum and the corresponding frequency axis
F = fft(rand([M 1]));
xf = (0:M/2-1)*(Sf/M);
% power law function
p = 1./xf(2:end).^b;
% get scaled magnitudes and phase
R = sqrt((abs(F(2:length(xf))).^2).*p');
P = angle(F(2:length(xf)));
% get symmetrical spectrum
F(2:length(xf)) = R .* (cos(P) + 1i.*sin(P));
F(length(xf)+2:end) = real(F(length(xf):-1:2)) - 1i*imag(F(length(xf):-1:2));
% IFFT
y = ifft(F);
% get correct number of samples
y = real(y(1:N));
% ensure unity standard deviation and zero mean value
y = y - mean(y);
yrms = sqrt(mean(y.^2));
y = y / yrms;
SampleEntropy
function SampEn = SampleEntropy(x,m,r,sflag)
% check inputs
SampEn = [];
if nargin < 1 || isempty(x), fprintf('Error: x needs to be defined!\n'), return; end
if ~isvector(x), fprintf('Error: x needs to be a vector!\n'), return; end
if nargin < 2 || isempty(m), m = 2; end
if nargin < 3 || isempty(r), r = 0.2; end
if nargin < 4 || isempty(sflag), sflag = 1; end
% force x to be column vector
x = x(:);
N = length(x);
% normalize/standardize x vector
if sflag > 0, x = (x - mean(x)) / std(x); end
% obtain subsequences of the signal
Xam = zeros(N-m,m+1); Xbm = zeros(N-m,m);
for ii = 1 : N-m % although for N-m+1 subsequences could be extracted for m,
Xam(ii,:) = x(ii:ii+m); % in the Richman approach only N-m are considered as this gives the same length for m and m+1
Xbm(ii,:) = x(ii:ii+m-1);
end
% obtain number of matches
B = zeros(1,N-m); A = zeros(1,N-m);
for ii = 1 : N-m
% number of matches for m
d = abs(bsxfun(@minus,Xbm((1:N-m)~=ii,:),Xbm(ii,:)));
B(ii) = sum(max(d,[],2) <= r);
% number of matches for m+1
d = abs(bsxfun(@minus,Xam((1:N-m)~=ii,:),Xam(ii,:)));
A(ii) = sum(max(d,[],2) <= r);
end
% get probablities for two sequences to match
B = 1/(N-m-1) * B; % mean number of matches for each subsequence for m
Bm = 1/(N-m) * sum(B); % probability that two sequences will match for m points (mean of matches across subsequences)
A = 1/(N-m-1) * A; % mean number of matches for each subsequence for m+1
Am = 1/(N-m) * sum(A); % probability that two sequences will match for m+1 points (mean of matches across subsequences)
cp = Am/Bm; % conditional probability
SampEn = -log(cp); % sample entropy
spectra
function [F xf] = spectra(X, Sf, nfft, win)
% check inputs
if nargin < 2, error('Error: Wrong number of inputs!\n'); end;
if nargin < 3 || isempty(nfft), nfft = size(X,1); end;
if nargin < 4 || isempty(win), win = @hann; end;
if nfft < size(X,1); fprintf('Info: nfft < size(X,1)! Using nfft = size(X,1).\n'); nfft = size(X,1); end;
% reshape multidimensional data into 2-d matrix
siz = size(X);
n = siz(1); nrest = siz(2:end);
X = reshape(X,[n prod(nrest)]);
% get window function and multiply it with the data
xwin = window(win,n);
X = bsxfun(@times,X,xwin);
% compute FFT, F - complex numbers, fourier matrix
F = fft(X,nfft,1)*2/sum(xwin);
% get frequency axis
xf = (0:nfft/2)*(Sf/nfft);
% shorten matrix by half
F = F(1:length(xf),:);
% put data back into multi-d matrix
F = reshape(F,[size(F,1) nrest]);
main
clear all;
format compact
rand('seed',10)
% parameters
Sf = 1000;
dur = 30;
% colors and b parameter for 1/f^b
ccol = [0 151 204; 0 0 0; 204 8 118; 204 122 0] / 255;
b = [-1 0 1 2];
lab = {'Blue' 'White' 'Pink' 'Brown'};
% get signals, mse, spectrum
nsamps = round(10.^linspace(log10(50),log10(2000),60));
[y mse mspe mswpe SampEn pe wpe alpha] = deal([]);
for ii = 1 : length(b)
y(:,ii) = colored_noise(Sf,dur,b(ii));
[mse(:,ii) sf] = MSE_Costa2005(y(:,ii),20,2,std(y(:,ii))*0.15);
SampEn(ii) = SampleEntropy(y(:,ii),2,std(y(:,ii))*0.15,0);
end
% time vector
t = (0:length(y)-1)/Sf;
% spectrum
[F xf] = spectra(y, Sf, Sf*10, @hann);
% plot spectra
figure, set(gcf,'Color',[1 1 1]), hold on
for ii = 1 : length(b)
subplot(1,length(b),ii)
set(gca,'FontSize',12)
plot(xf,abs(F(:,ii)),'-','Color',ccol(ii,:))
xlim([0 400])
ylim([0 0.2])
xlabel('Frequency (Hz)')
if ii == 1
ylabel('Amplitude (a.u.)')
end
title([lab{ii} ' noise (1/f^{' num2str(b(ii)) '})'])
end
% plot time course
figure, set(gcf,'Color',[1 1 1]), hold on
for ii = 1 : length(b)
subplot(length(b),1,ii)
set(gca,'FontSize',12)
plot(t,y(:,ii),'-','Color',ccol(ii,:))
ylim([-3 3])
if ii == length(b)
xlabel('Time (s)')
end
ylabel('Amp. (a.u.)')
title([lab{ii} ' noise (1/f^{' num2str(b(ii)) '})'])
end
% plot mse
figure, set(gcf,'Color',[1 1 1]), hold on, pp = []; labfull = {};
set(gca,'FontSize',12)
for ii = 1 : length(b)
pp(ii) = plot(sf,mse(:,ii),'-','Color',ccol(ii,:),'LineWidth',2);
labfull{ii} = [lab{ii} ' noise (1/f^{' num2str(b(ii)) '})'];
end
ylim([0 3])
xlabel('Scale')
ylabel('SampEn')
title('Multi-scale entropy')
legend(pp,labfull)
legend('boxoff')
% plot sample entropy
figure, set(gcf,'Color',[1 1 1]), hold on, pp = []; labfull = {};
set(gca,'FontSize',12)
for ii = 1 : length(b)
rectangle('Position',[ii 0 1 SampEn(ii)],'FaceColor',ccol(ii,:))
end
set(gca,'XTick',1.5:length(b)+0.5,'XTickLabel',lab)
xlim([0.8 length(b)+1.2])
ylim([0 3])
xlabel('Noise type')
ylabel('SampEn')
title('Sample entropy')