Kann ich numpy benutzen, um diese Schleife zu beschleunigen?

Guten Abend,

Ich versuche, die Schleife in diesem Code zu beschleunigen. Ich habe die Numpy Docs gelesen, aber ohne Erfolg. Np.accumulate sieht aus wie es ist fast was ich brauche, aber nicht ganz.

  • Pythonische Makrosyntax
  • Minimalistische Real-Time Plotten in Python
  • Django Rest Framework (DRF) Wie paginiere Klasse je nach query_params?
  • Python Pandas SettingWithCopyWarning kopiert vs neue Objekte
  • Ändern von URL-Komponenten in Python 2
  • Wie man auf Nargs von optparse-add_action zugreifen kann?
  • Was könnte ich tun, um die Schleife zu beschleunigen?

    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 

    Als Antwort auf Warren habe ich meinen Code aktualisiert:

    Import numpy als np aus 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 ) 

    Zeitcode:

     %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 

    Das zeigt, dass Warrens Methode über 10 mal schneller ist! Sehr beeindruckend!

    3 Solutions collect form web for “Kann ich numpy benutzen, um diese Schleife zu beschleunigen?”

    Ihre Rekursionsrelation ist linear, so dass sie als Linearfilter betrachtet werden kann. Sie können scipy.signal.lfilter , um s2 zu berechnen. Ich habe vor kurzem eine ähnliche Frage hier beantwortet: python rekursive vektorisierung mit timeseries

    Hier ist ein Skript, das zeigt, wie man lfilter , um deine Serie zu berechnen:

     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 

    Ausgabe:

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

    Ich bin mir nicht sicher, ob es viel zu tun gibt, um die Schleife zu beschleunigen … Der einzige Weg, den ich sehe, wäre, die Rekursion zu vermeiden, dh s2 [t] "direkt" für jeden t zu berechnen. Aber das ist auch teuer …

    Du hast

     s2[t] = AR_part[t-1] + beta * s2[t-1] = AR_part[t-1] + beta * (AR_part[t-2] + beta * s2[t-2]) = AR_part[t-1] + beta * AR_part[t-2] + beta^2 * s2[t-2] = np.dot( AR[:t-1], beta_powers[-(t-1):] ) 

    Wo beta_powers enthält [beta ^ 1000, beta ^ 999, … 1.0]. Sie können Beta_powers auf diese Weise erstellen:

     np.power(beta, np,arange(1000))[::-1]. 

    Aber ich kann nicht sehen, einen Weg, um das Zeug schneller als das, was Ihre Schleife zu berechnen …

    Allerdings können Sie es umschreiben:

     for t in range(N): s2[t+1] = AR_part[t] + beta * s2[t] 

    Ich stimme mit GHL zu, dass du nicht viel mehr Leistung bekommst (wenn auch N wirklich groß war, und du warst nur einige Teile des Vektors s2 , definitiv seine Methode), aber hier ist ein anderer Weg, um zu tun was du bist anschauen:

     import numpy as np N = 1000 AR_part = np.random.randn(N+1) beta = 1.3 def seq_gen(beta, constants, first_element = 1.0): next_element = first_element yield next_element for j in constants: next_element = j + beta * next_element yield next_element s2 = np.array([j for j in seq_gen(beta, AR_part, 1.0)]) 
    Python ist die beste Programmiersprache der Welt.