gpt4 book ai didi

python - 如何知道算法是否可以更快

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:40:25 27 4
gpt4 key购买 nike

我正在做一个实验来计算信号的近似熵。详细信息(和实际代码)可以在其 Wikipedia page 上找到。 .不幸的是,虽然算法本身有效,但对于大型数据集来说它非常慢(例如,在 2000 长信号上大约需要 25 秒)。由于我要对许多更长的信号进行计算,以这种速度,我希望我的实验至少持续 1 个月。我想知道是否有任何方法可以加快算法的速度。

import numpy as np

def ApEn(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)]
C = [len([1 for x_j in x if _maxdist(x_i, x_j) <= r]) / (N - m + 1.0) for x_i in x]
return (N - m + 1.0)**(-1) * sum(np.log(C))

N = len(U)

return abs(_phi(m + 1) - _phi(m))

最佳答案

如果您愿意将该函数移至 cython 并添加一些类型注释,则可以显着提高性能。这是我对该算法的版本:

apen.pyx:

cimport cython
from libc.math cimport fabs, log
import numpy as np

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.initializedcheck(False)
@cython.cdivision(True)
cdef double max_dist(double[:] x_i, double[:] x_j, int m) nogil:
#Performs the max function described in step 4 of ApEn algorithm
cdef double out
cdef double dist
out = fabs(x_i[0] - x_j[0])
for k in range(1, m - 1):
dist = fabs(x_i[k] - x_j[k])
if dist > out:
out = dist
return out

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.initializedcheck(False)
@cython.cdivision(True)
cdef double phi(double[:] Sn, int m, int r):
cdef int N = len(Sn)
cdef int i
cdef int j
cdef int k

cdef int c_val
cdef int counter
cdef double phi_sum = 0
cdef double phi
cdef double m_dist

#Performs step 3 of the ApEn algorithm
cdef double[:, :] x = np.empty((N - m + 1, m), dtype=np.float64)
with nogil:
for i in range(N - m + 1):
for j in range(0, m):
x[i, j] = Sn[j + i]

#Performs a combined steps 4 & 5 of the ApEn algorithm
for i in range(N - m + 1):
counter = 0
for j in range(N - m + 1):
m_dist = max_dist(x[i], x[j], m)
c_val = 1 if m_dist <= r else 0
counter += c_val
phi_sum += log(counter / (N - m + 1.0))
phi = phi_sum / (N - m + 1.0)
return phi

cpdef double approx_entropy(double[:] Sn, int m, int r):#Passing in steps 1 & 2 of the ApEn algorithm
cdef double ApEn = abs(phi(Sn, m, r) - phi(Sn, m + 1, r))#Performs step 6 of the ApEn algorithm
return ApEn

apen.pxd:

cdef double max_dist(double[:] x_i, double[:] x_j, int m) nogil
cdef double phi(double[:] Sn, int m, int r)
cpdef double approx_entropy(double[:] Sn, int m, int r)

设置.pxd:

from distutils.core import setup
from Cython.Build import cythonize
from distutils.core import Extension
import numpy as np

extensions = [
Extension("apen", sources=["apen.pyx"], include_dirs=[np.get_include()], extra_compile_args=["-w"]),
]

setup(
ext_modules = cythonize(extensions)
)

主要.py:

import time
import apen
import numpy as np

start = time.time()
data = np.random.rand(2000)
#data = np.array([85, 80, 89] * 17, dtype=np.float64)
answer = apen.approx_entropy(Sn=data, m=2, r=3)
print(answer)
end = time.time()
print(end - start)

在我的笔记本电脑上使用此代码获取 2000 个随机数据点,cython 代码在 0.36 秒内计算出 ApEn。相比之下,维基百科代码需要 14.75 秒。这相当于 40 倍的速度提升。希望你觉得这有帮助!

关于python - 如何知道算法是否可以更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46996831/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com