介紹
循環(huán)在我們身邊自然而然地出現(xiàn),我們幾乎在所有編程語言中都學過循環(huán)。因此,默認情況下,每當有重復操作時,我們就開始實現(xiàn)循環(huán)。但是當我們處理大量迭代(數(shù)百萬/數(shù)十億行)時,使用循環(huán)就是一種罪行。我們可能會卡住好幾個小時,最后意識到它行不通。這就是在Python中實現(xiàn)向量化變得非常關鍵的地方。
什么是向量化?
向量化是在數(shù)據(jù)集上實現(xiàn)(NumPy)數(shù)組操作的技術。在后臺,它將操作應用于數(shù)組或系列的所有元素,一次性完成(不像“for”循環(huán)一次操作一行)。在這篇文章中中,我們可以輕松地用向量化替代Python循環(huán)。這將幫助我們節(jié)省時間,并在編碼方面變得更加熟練。
用例1:找到數(shù)字的和
首先,我們將看一個使用循環(huán)和Python中的向量化找到數(shù)字和的基本示例。
使用循環(huán)
import time
start = time.time()
# iterative sum
total = 0
# iterating through 1.5 Million numbers
for item in range(0, 1500000):
total = total + item
print('sum is:' + str(total))
end = time.time()
print(end - start)
#1124999250000
#0.14 Seconds
使用向量化
import numpy as np
start = time.time()
# vectorized sum - using numpy for vectorization
# np.arange create the sequence of numbers from 0 to 1499999
print(np.sum(np.arange(1500000)))
end = time.time()
print(end - start)
##1124999250000
##0.008 Seconds
相比于使用range函數(shù)進行迭代,向量化執(zhí)行時間約為循環(huán)的18倍。在使用Pandas DataFrame時,這種差異將變得更為顯著。
用例2:數(shù)學運算(在DataFrame上)
在數(shù)據(jù)科學中,開發(fā)人員在使用Pandas DataFrame時,使用循環(huán)進行數(shù)學運算以創(chuàng)建新的派生列。在以下示例中,我們可以看到如何輕松地將循環(huán)替換為這種情況下的向量化。
創(chuàng)建DataFrame
DataFrame是以行和列形式的表格數(shù)據(jù)。我們創(chuàng)建一個具有500萬行和4列,填充了0到50之間的隨機值的Pandas DataFrame。
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(0, 50, size=(5000000, 4)), columns=('a','b','c','d'))
df.shape
# (5000000, 5)
df.head()
前5行
我們將創(chuàng)建一個新列'ratio',以找到列'd'和'c'的比率。
使用循環(huán)
import time
start = time.time()
# Iterating through DataFrame using iterrows
for idx, row in df.iterrows():
# creating a new column
df.at[idx,'ratio'] = 100 * (row["d"] / row["c"])
end = time.time()
print(end - start)
### 109 Seconds
使用向量化
start = time.time()
df["ratio"] = 100 * (df["d"] / df["c"])
end = time.time()
print(end - start)
### 0.12 seconds
我們可以看到,在DataFrame中,與Python中的循環(huán)相比,向量化操作所需的時間幾乎快1000倍。
用例3:if-else語句(在DataFrame上)
我們實現(xiàn)了許多需要使用“If-else”類型邏輯的操作。我們可以輕松地用Python中的向量化操作替換這些邏輯。讓我們看下面的例子以更好地理解它(我們將使用在用例2中創(chuàng)建的DataFrame):
假設我們想基于對現(xiàn)有列‘a(chǎn)’的某些條件創(chuàng)建一個新列‘e’。
使用循環(huán)
import time
start = time.time()
# Iterating through DataFrame using iterrows
for idx, row in df.iterrows():
if row.a == 0:
df.at[idx,'e'] = row.d
elif (row.a <= row.a=""> 0):
df.at[idx,'e'] = (row.b)-(row.c)
else:
df.at[idx,'e'] = row.b + row.c
end = time.time()
print(end - start)
### Time taken: 177 seconds
使用向量化
# using vectorization
start = time.time()
df['e'] = df['b'] + df['c']
df.loc[df['a'] <= 25, 'e'] = df['b'] -df['c']
df.loc[df['a']==0, 'e'] = df['d']end = time.time()
print(end - start)
## 0.28007707595825195 sec
向量化操作所需的時間比帶有if-else語句的Python循環(huán)快600倍。
用例4(高級):解決機器學習/深度學習網(wǎng)絡
深度學習要求我們解決多個復雜的方程,而且還要為數(shù)百萬甚至數(shù)十億行運行。在Python中運行循環(huán)來解決這些方程非常慢,而向量化是最優(yōu)解。例如,為了計算多元線性回歸方程中數(shù)百萬行的y值:
多元線性回歸
我們可以用向量化替換循環(huán)。m1,m2,m3...的值是通過使用與x1,x2,x3...相對應的數(shù)百萬個值解上述方程得出的(為簡單起見,我們只看一個簡單的乘法步驟)
創(chuàng)建數(shù)據(jù)
import numpy as np
# setting initial values of m
m = np.random.rand(1,5)
# input values for 5 million rows
x = np.random.rand(5000000,5)
m的輸出
x的輸出
使用循環(huán)
import numpy as np
m = np.random.rand(1,5)
x = np.random.rand(5000000,5)
total = 0
tic = time.process_time()
for i in range(0,5000000):
total = 0
for j in range(0,5):
total = total + x[i][j]*m[j]
zer[i] = total
toc = time.process_time()
print ("Computation time = " + str((toc - tic)) + "seconds")
####Computation time = 28.228 seconds
使用向量化
兩個矩陣的點積
tic = time.process_time()
#dot product
np.dot(x,m.T)
toc = time.process_time()
print ("Computation time = " + str((toc - tic)) + "seconds")
####Computation time = 0.107 seconds
np.dot在后臺實現(xiàn)了向量化矩陣乘法。與Python中的循環(huán)相比,它快165倍。
結論
在Python中,向量化非常快,應該優(yōu)先使用,特別是在處理非常大的數(shù)據(jù)集時。
隨著時間的推移開始實施它,我們將逐漸習慣以向量化代碼的方式思考。