Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
197 views
in Technique[技术] by (71.8m points)

python - Can I use numpy to speed this loop?

Good evening,

I am trying to speed up the loop in this code. I have read through the numpy docs but to no avail. np.accumulate looks like it is almost what I need, but not quite.

What could I do to speed up the loop?

import numpy as np

N       = 1000
AR_part = np.random.randn(N+1)
s2      = np.ndarray(N+1)
s2[0]   = 1.0

beta = 1.3

old_s2  = s2[0]
for t in range( 1, N+1 ):               
    s2_t    = AR_part[ t-1 ] + beta * old_s2
    s2[t]   = s2_t        
    old_s2  = s2_t

In response to Warren, I updated my code:

import numpy as np
from scipy.signal import lfilter, lfiltic

N       = 1000
AR_part = np.random.randn(N+1)

beta = 1.3

def method1( AR_part):
    s2      = np.empty_like(AR_part)
    s2[0]   = 1.0
    old_s2  = s2[0]
    for t in range( 1, N+1 ):               
        s2_t    = AR_part[ t-1 ] + beta * old_s2
        s2[t]   = s2_t        
        old_s2  = s2_t
    return s2

def method2( AR_part):
    y = np.empty_like(AR_part)
    b = np.array([0, 1])
    a = np.array([1, -beta])

    # Initial condition for the linear filter.
    zi = lfiltic(b, a, [1.0], AR_part[:1])

    y[:1] = 1.0
    y[1:], zo = lfilter(b, a, AR_part[1:], zi=zi)

    return y    

s2 = method1( AR_part )
y = method2( AR_part )
np.alltrue( s2==y )

Timing the code:

%timeit method1( AR_part )
100 loops, best of 3: 1.63 ms per loop
%timeit method2( AR_part )
10000 loops, best of 3: 129 us per loop

That shows that Warren's method is over 10 times faster! Very impressive!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your recurrence relation is linear, so it can be viewed as a linear filter. You can use scipy.signal.lfilter to compute s2. I recently answered a similar question here: python recursive vectorization with timeseries

Here's a script that shows how to use lfilter to compute your series:

import numpy as np
from scipy.signal import lfilter, lfiltic


np.random.seed(123)

N       = 4
AR_part = np.random.randn(N+1)
s2      = np.ndarray(N+1)
s2[0]   = 1.0

beta = 1.3

old_s2  = s2[0]
for t in range( 1, N+1 ):               
    s2_t    = AR_part[ t-1 ] + beta * old_s2
    s2[t]   = s2_t        
    old_s2  = s2_t


# Compute the result using scipy.signal.lfilter.

# Transfer function coefficients.
# `b` is the numerator, `a` is the denominator.
b = np.array([0, 1])
a = np.array([1, -beta])

# Initial condition for the linear filter.
zi = lfiltic(b, a, s2[:1], AR_part[:1])

# Apply lfilter to AR_part.
y = np.empty_like(AR_part)
y[:1] = s2[:1]
y[1:], zo = lfilter(b, a, AR_part[1:], zi=zi)

# Compare the results
print "s2 =", s2
print "y  =", y

Output:

s2 = [ 1.          0.2143694   1.27602566  1.94181186  1.0180607 ]
y  = [ 1.          0.2143694   1.27602566  1.94181186  1.0180607 ]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...