2013-04-05 46 views
0

如何解決這個練習4.5第2頁與Python Numpy矢量化?如何用python numpy向量化解決這個練習?

鏈接下載:

https://dl.dropbox.com/u/92795325/Python%20Scripting%20for%20Computational%20Scien%20-%20H.P.%20%20Langtangen.pdf

我試圖與Python的循環,但我需要矢量版本。

from numpy import * 
import time 

def fun1(x): 
     return 2*x+1 

def integ(a,b,n): 
     t0 = time.time() 
     h = (b-a)/n 
     a1 = (h/2)*fun1(a) 
     b1 = (h/2)*fun1(b) 
     c1 = 0 
     for i in range(1,n,1): 
       c1 = fun1((a+i*h))+c1 
     t1 = time.time() 
     return a1+b1+h*c1, t1-t0 
+0

嗨Ardeshir,你知道什麼意思是「矢量化」的問題? – askewchan 2013-04-05 14:50:05

+0

你可以閱讀前面的頁面,這有助於你理解。 – 2013-04-05 15:34:11

+0

我明白了,我問你是否確實如果你明白,你有沒有試圖實現它? – askewchan 2013-04-05 15:43:31

回答

0

「矢量化」使用numpy,這一切都意味着,而不是做一個明確的循環一樣,

for i in range(1, n): 
    c = c + f(i) 

然後,而不是你應該做i成numpy的數組,隨便拿其總和:

i = np.arange(1,n) 
c = i.sum() 

numpy自動爲您做矢量化。這個速度更快的原因是因爲numpy循環比普通的python循環更好的優化方式,出於各種原因。一般來說,迴路/陣列越長,優勢越好。這裏是你的梯形積分來實現:

import numpy as np 

def f1(x): 
    return 2*x + 1 

# Here's your original function modified just a little bit: 
def integ(f,a,b,n): 
    h = (b-a)/n 
    a1 = (h/2)*f(a) 
    b1 = (h/2)*f(b) 
    c1 = 0 
    for i in range(1,n,1): 
     c1 = f((a+i*h))+c1 
    return a1 + b1 + h*c1 

# Here's the 'vectorized' function: 
def vinteg(f, a, b, n): 
    h = (b-a)/n 
    ab = 0.5 * h * (f(a)+f(b)) #only divide h/2 once 

    # use numpy to make `i` a 1d array: 
    i = np.arange(1, n) 
    # then, passing a numpy array to `f()` means that `f` returns an array 
    c = f(a + h*i) # now c is a numpy array 

    return ab + c.sum() # ab + np.sum(c) is equivalent 

在這裏,我將導入我叫tmp.pyipython會議的時機更容易比使用time.time:快

import trap 
f = trap.f1 
a = 0 
b = 100 
n = 1000 

timeit trap.integ(f, a, b, n) 
#1000 loops, best of 3: 378 us per loop 

timeit trap.vinteg(f, a, b, n) 
#10000 loops, best of 3: 51.6 us per loop 

哇,七次。

看它是否有助於多的小n

n = 10 

timeit trap.integ(f, a, b, n) 
#100000 loops, best of 3: 6 us per loop 

timeit trap.vinteg(f, a, b, n) 
#10000 loops, best of 3: 43.4 us per loop 

不,小環形慢得多!那麼非常大的n

n = 10000 

timeit trap.integ(f, a, b, n) 
#100 loops, best of 3: 3.69 ms per loop 

timeit trap.vinteg(f, a, b, n) 
#10000 loops, best of 3: 111 us per loop 

快三十倍!

+0

感謝您的幫助。我明白了......但是如果你不介意的話,我還有更多的問題。首先,「矢量化版本」總是比循環更有效 - 我應該儘可能避免使用循環嗎?其次,循環和向量之間有什麼區別,使得這些差異變得更大?爲什麼在(例如)FORTRAN和C編程中沒有這種東西? – 2013-04-08 16:47:45

+0

@ArdeshirDVD第一:通常更快,但並非總是如此。它也比循環更可讀,這更重要。第二:區別不在於它們是循環,而是數據存儲和迭代的方式。 Numpy內建函數主要是用C語言編寫和編譯的,速度更快。它們不存在於Fortran或C中,因爲F.而C不需要它們:那些是編譯語言,而事實上python是一種「解釋性」語言,可以減緩其循環。 – askewchan 2013-04-08 19:46:17

+0

@ArdeshirDVD由於python被解釋並且未被編譯,並且因爲它的變量都是動態類型的,所以循環的每次迭代都必須檢查變量的類型,這對於超過10000個相同類型的浮點而言是浪費的。看到像http://stackoverflow.com/a/8097669/1730674和http://stackoverflow.com/q/3033329/1730674這樣的問題,關於爲什麼python如此緩慢地運行某些事情的小討論 – askewchan 2013-04-08 19:55:04