Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Refactors and fixes sample entropy (last M values must be ignored) #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

CSchoel
Copy link

@CSchoel CSchoel commented Jan 24, 2020

@DominiqueMakowski called my attention to a discrepancy between this implementation of the sample entropy and my implementation in nolds in this issue: neuropsychology/NeuroKit#75 .

I think there is a small issue in MultiscaleEntropy that causes this inconsistence: The sample entropy is the conditional probability that two pieces of the input sequence that are similar for M time steps will remain similar for M+1 time steps. If we count the number of similar template vector pairs of length M we therefore must ignore the last template vector, since it cannot be followed for another time step. If we would include it in the calculation, this would introduce a bias that underestimates the number of template vectors that remain similar for a length of M+1.

Reference: Richman and Moorman (2000), page H2042

At Dominique's hint I found similar issues with entro-py (ixjlyons/entro-py#2), pyeeg (forrestbao/pyeeg#29) and pyEntropy (nikdon/pyEntropy#15). With the suggested fix in this pull request, MultiscaleEntropy produces the same output as nolds and the R-package pracma (which I used as reference for the implementation of nolds), as well as the fixed versions of pyeeg, entro-py and pyEntropy,

import nolds
import entropy as e
import pyentrp.entropy as pent
import pyeeg.entropy as peeg
import numpy as np
import MultiscaleEntropy as mse

num = 100
dim = 2
tol = 0.2
signal = np.cos(np.linspace(start=0, stop=30, num=num))
print("entro-py", e.sampen(signal, dim, tol, False))
print(" pyentrp", pent.sample_entropy(signal, dim + 1, tol)[-1])
print("   pyeeg", peeg.samp_entropy(signal, dim, tol))
print(" MSEntr.", mse.sample_entropy(signal, [dim], [tol], sd=1, return_type="list")[0][0])
print("   nolds", nolds.sampen(signal, emb_dim=dim, tolerance=tol))
entro-py 0.27672305866206137
 pyentrp 0.2767230586620615
   pyeeg 0.27672305866206137
 MSEntr. 0.2767230586620615
   nolds 0.2767230586620615

Since I found the code in MultiscaleEntropy hard to understand, I took the liberty to refactor it. After I was done with that I could also identify the actual culprit in the original code. So if you would like to incorporate the fix but not my refactored version, you can alternatively pull the branch bugfix in my fork.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant