返回文章列表

NumPy陣列堆積疊拆分與向量化運算

本文深入探討 NumPy 陣列的堆積疊與拆分方法,並詳細介紹向量化運算的優勢與應用,包含通用函式(ufuncs)的型別、使用方法和效能比較。同時,文章也涵蓋了基礎數學運算、三角函式、指數與對數函式等相關內容,以及如何避免溢位和精確度問題,並提供使用 SciPy 特殊函式的範例。

資料科學 Python

NumPy 是 Python 資料科學領域的核心函式庫,其高效的陣列運算能力是處理大量資料的關鍵。理解陣列操作、向量化計算和通用函式的使用,能大幅提升程式碼效能。在資料處理流程中,我們經常需要合併或分割資料,NumPy 提供了 hstackvstackdstacksplithsplitvsplit 等函式來滿足這些需求,靈活運用這些函式能讓我們更有效率地組織和處理資料。此外,使用向量化運算取代傳統迴圈,能充分利用 NumPy 的底層最佳化,避免 Python 直譯器造成的效能瓶頸,尤其在處理大型陣列時,效能提升尤為顯著。通用函式(ufuncs)是向量化運算的基礎,提供豐富的數學運算功能,從基本算術運算到三角函式、指數和對數函式等,ufuncs 能直接作用於陣列元素,實作高效的批次運算。同時,瞭解如何指定輸出陣列和使用其他進階 ufunc 功能,可以進一步最佳化記憶體使用和計算效率。

陣列的堆積疊和拆分

在 NumPy 中,陣列的堆積疊和拆分是兩種重要的操作。堆積疊(stacking)是指將多個陣列合併成一個新的陣列,而拆分(splitting)則是指將一個陣列分割成多個小陣列。

堆積疊

NumPy 提供了三種堆積疊函式:np.hstacknp.vstacknp.dstack。這些函式可以將陣列堆積疊在水平、垂直或深度方向上。

例如,使用 np.hstack 可以將兩個陣列水平堆積疊:

import numpy as np

grid = np.arange(12).reshape((3, 4))
y = np.array([99, 99, 99, 99])

result = np.hstack([grid, y[:, None]])
print(result)

輸出:

[[ 0  1  2  3 99]
 [ 4  5  6  7 99]
 [ 8  9 10 11 99]]

拆分

NumPy 也提供了三種拆分函式:np.splitnp.hsplitnp.vsplit。這些函式可以將一個陣列拆分成多個小陣列。

例如,使用 np.split 可以將一個陣列拆分成多個小陣列:

x = np.array([1, 2, 3, 99, 99, 3, 2, 1])
x1, x2, x3 = np.split(x, [3, 5])
print(x1, x2, x3)

輸出:

[1 2 3] [99 99] [3 2 1]

注意,N 個拆分點會導致 N + 1 個小陣列。

垂直和水平拆分

np.hsplitnp.vsplit 可以用於垂直和水平拆分陣列。例如:

grid = np.arange(16).reshape((4, 4))
upper, lower = np.vsplit(grid, [2])
print(upper)
print(lower)

輸出:

[[0 1 2 3]
 [4 5 6 7]]
[[ 8  9 10 11]
 [12 13 14 15]]

這些函式可以用於各種資料操作和分析任務中。

資料科學計算的核心:NumPy陣列運算

NumPy陣列運算是資料科學計算的根本。透過使用NumPy提供的通用函式(ufuncs),我們可以對陣列元素進行快速且高效的計算。

陣列分割

在進行陣列運算之前,讓我們先了解一下如何分割陣列。NumPy提供了np.hsplitnp.dsplit兩個函式,用於分割陣列。np.hsplit可以沿著水平軸分割陣列,而np.dsplit可以沿著深度軸分割陣列。

import numpy as np

# 建立一個4x4的陣列
grid = np.arange(16).reshape(4, 4)

# 沿著水平軸分割陣列
left, right = np.hsplit(grid, [2])

print("左半部分:")
print(left)
print("右半部分:")
print(right)

輸出結果:

左半部分:
[[ 0  1]
 [ 4  5]
 [ 8  9]
 [12 13]]
右半部分:
[[ 2  3]
 [ 6  7]
 [10 11]
 [14 15]]

通用函式(ufuncs)

NumPy的通用函式(ufuncs)是對陣列元素進行運算的核心。ufuncs可以對陣列元素進行元素級別的運算,從而大大提高計算效率。

為什麼需要ufuncs?

在進行資料科學計算時,往往需要對大量的資料進行運算。如果使用傳統的迴圈方式進行運算,效率將非常低下。ufuncs可以幫助我們避免這種低效率的運算方式,從而大大提高計算速度。

ufuncs的優點

ufuncs有以下幾個優點:

  • 高效率:ufuncs可以對陣列元素進行元素級別的運算,從而大大提高計算效率。
  • 簡單易用:ufuncs的使用方法非常簡單,只需要呼叫相應的函式即可。
  • 豐富的功能:NumPy提供了大量的ufuncs,涵蓋了各種常見的運算。

常見的ufuncs

NumPy提供了許多常見的ufuncs,包括:

  • 基本算術運算:np.addnp.subtractnp.multiplynp.divide等。
  • 統計運算:np.meannp.mediannp.std等。
  • 三角函式:np.sinnp.cosnp.tan等。
import numpy as np

# 建立一個陣列
arr = np.array([1, 2, 3, 4, 5])

# 使用ufuncs進行運算
print("加法:")
print(np.add(arr, 2))
print("減法:")
print(np.subtract(arr, 2))
print("乘法:")
print(np.multiply(arr, 2))
print("除法:")
print(np.divide(arr, 2))

輸出結果:

加法:
[3 4 5 6 7]
減法:
[-1  0  1  2  3]
乘法:
[2 4 6 8 10]
除法:
[0.5 1.  1.5 2.  2.5]

圖表解釋

以下是使用Plantuml語法繪製的流程圖,展示了ufuncs的運算過程:

圖表翻譯:

上述流程圖展示了使用ufuncs進行運算的過程。首先,輸入一個陣列;然後,選擇要使用的ufunc;接下來,進行相應的運算;最後,輸出結果。這個過程非常簡單和高效,能夠大大提高資料科學計算的速度和效率。

Python 的迴圈效能問題

Python 的預設實作(也就是 CPython)在某些操作上相當耗時。這主要是由於 Python 的動態、直譯性質所導致;變數型別是靈活的,因此無法像 C 或 Fortran 等語言一樣將一系列操作編譯成高效的機器碼。

近年來,出現了多個嘗試來解決這個問題,例如 PyPy 專案是一個即時編譯的 Python 實作、Cython 專案可以將 Python 程式碼轉換成可編譯的 C 程式碼、以及 Numba 專案可以將 Python 程式碼片段轉換成快速的 LLVM 位元碼。每個方法都有其優缺點,但可以肯定的是,這三種方法都未能超越標準 CPython 引擎的普遍性和受歡迎程度。

Python 相對較慢的效能通常表現為需要重複執行許多小型操作的情況,例如迴圈遍歷陣列以對每個元素進行操作。例如,如果我們有一個值的陣列,想要計算每個值的倒數,直觀的方法可能如下所示:

import numpy as np

def compute_reciprocals(values):
    output = np.empty(len(values))
    for i in range(len(values)):
        output[i] = 1.0 / values[i]
    return output

# 測試資料
rng = np.random.default_rng(seed=1701)
values = rng.integers(1, 10, size=5)
print(compute_reciprocals(values))

對於來自 C 或 Java 背景的人員,這種實作可能看起來相當自然。但是,如果我們測量這段程式碼對於大型輸入的執行時間,就會發現這個操作非常耗時!使用 IPython 的 %timeit 魔法(在「Profiling and Timing Code」中討論)進行Benchmarking:

big_array = rng.integers(1, 100, size=1000000)
%timeit compute_reciprocals(big_array)

結果顯示,即使是當代手機的處理速度也達到每秒數十億次運算,如此耗時的結果似乎有些荒誕。實際上,瓶頸並不是運算本身,而是 CPython 必須在迴圈的每個迴圈中進行的型別檢查和函式派遣。每次計算倒數時,Python 都會先檢查物件的型別並動態查詢正確的函式來使用該型別。如果是在編譯過的程式碼中工作,型別規格將在程式碼執行前就已知,結果可以更有效地計算。

介紹 Ufuncs

對於許多型別的操作,NumPy 提供了一個方便的介面到靜態型別、編譯過的例程中。這被稱為向量化操作。對於簡單的操作,如元素-wise 除法,只需直接在陣列物件上使用 Python 算術運算子即可實作向量化。這種向量化方法旨在將迴圈推入 NumPy 底層的編譯層,從而導致更快的執行。

比較以下兩個操作的結果:

import numpy as np

# 直接計算倒數
values = np.array([1, 2, 3, 4, 5])
reciprocals = 1.0 / values
print(reciprocals)

# 使用迴圈計算倒數
def compute_reciprocals(values):
    output = np.empty(len(values))
    for i in range(len(values)):
        output[i] = 1.0 / values[i]
    return output

print(compute_reciprocals(values))

內容解密:

  • compute_reciprocals 函式使用迴圈計算陣列中每個值的倒數。
  • 直接使用 / 運算子在 NumPy 陣列上進行元素-wise 除法,可以達到向量化,從而提高效能。

圖表翻譯:

這個流程圖展示了使用迴圈和直接向量化計算陣列倒數的兩種方法,並強調了向量化方法的效能優勢。

瞭解 NumPy 的向量化運算

NumPy 的向量化運算是透過 ufuncs(通用函式)來實作的,ufuncs 的主要目的是快速執行重複的運算在 NumPy 陣列中。這些運算可以大大提高效率,尤其是在處理大型陣列時。

向量化運算的優勢

使用向量化運算可以使程式執行速度大幅提高。例如,當我們使用 Python 迴圈來執行運算時,速度可能會相當慢。但是,當我們使用 NumPy 的向量化運算時,速度就會大大提高。

import numpy as np

# 建立一個大型陣列
big_array = np.random.rand(1000000)

# 使用 Python 迴圈來執行運算
def python_loop(array):
    result = []
    for value in array:
        result.append(1.0 / value)
    return result

# 使用 NumPy 的向量化運算來執行運算
def numpy_vectorized(array):
    return 1.0 / array

# 比較執行時間
import timeit

python_loop_time = timeit.timeit(lambda: python_loop(big_array), number=10)
numpy_vectorized_time = timeit.timeit(lambda: numpy_vectorized(big_array), number=10)

print(f"Python 迴圈執行時間:{python_loop_time:.2f} 秒")
print(f"NumPy 向量化運算執行時間:{numpy_vectorized_time:.2f} 秒")

ufuncs 的種類別

ufuncs 有兩種:單元 ufuncs(unary ufuncs)和二元 ufuncs(binary ufuncs)。單元 ufuncs 只需要一個輸入,而二元 ufuncs 需要兩個輸入。

陣列運算

NumPy 的 ufuncs 支援各種陣列運算,包括加法、減法、乘法和除法。這些運算可以使用 Python 的原生運算子號來實作。

x = np.arange(4)
print("x =", x)
print("x + 5 =", x + 5)
print("x - 5 =", x - 5)

多維陣列運算

ufuncs 也可以作用於多維陣列。

x = np.arange(9).reshape((3, 3))
print("x =", x)
print("2 ** x =", 2 ** x)

基礎數學運算

在進行數值計算時,瞭解基本的數學運算是非常重要的。這些運算包括加法、減法、乘法、除法等。以下將介紹這些運算的使用方法和範例。

基本運算

  • 加法:兩個數值相加,可以使用 + 運算子。
  • 減法:兩個數值相減,可以使用 - 運算子。
  • 乘法:兩個數值相乘,可以使用 * 運算子。
  • 除法:兩個數值相除,可以使用 / 運算子。
x = [0, 1, 2, 3]
print("x + 5 =", [i + 5 for i in x])
print("x - 5 =", [i - 5 for i in x])
print("x * 2 =", [i * 2 for i in x])
print("x / 2 =", [i / 2 for i in x])

地板除法

地板除法(floor division)是指在進行除法運算時,結果向下舍入到最接近的整數。可以使用 // 運算子。

x = [0, 1, 2, 3]
print("x // 2 =", [i // 2 for i in x])

單元運算

單元運算包括負號(-)和絕對值等。以下是負號的範例:

x = [0, 1, 2, 3]
print("-x =", [-i for i in x])

指數運算

指數運算可以使用 ** 運算子。

x = [0, 1, 2, 3]
print("x ** 2 =", [i ** 2 for i in x])

模數運算

模數運算可以使用 % 運算子,得到的是除法的餘數。

x = [0, 1, 2, 3]
print("x % 2 =", [i % 2 for i in x])

內容解密:

以上範例展示了基本的數學運算,包括加法、減法、乘法、除法、地板除法、單元運算、指數運算和模數運算。每個範例都使用了列表推導式來對列表中的每個元素進行運算,並列印預出結果。這些運算在資料分析和科學計算中非常常用。

圖表翻譯:

圖表翻譯:

此圖表展示了不同數學運算之間的關係,從基本的加法、減法、乘法、除法到地板除法、單元運算、指數運算和模數運算。每個運算都會產生一個結果,這些結果可以用於進一步的分析或計算。

數值運算與絕對值

在 NumPy 中,數值運算可以使用 Python 的內建運算子,例如加、減、乘、除等。這些運算子可以直接作用於 NumPy 陣列上,從而實作元素級別的運算。

基本運算

給定一個 NumPy 陣列 x,我們可以使用基本運算子進行加、減、乘、除等運算。例如:

import numpy as np

x = np.array([1, 2, 3, 4, 5])
y = x * 2  # 元素級別的乘法運算
print(y)  # Output: [2 4 6 8 10]

此外,NumPy 還支援更多高階的運算,例如指數運算、模數運算等。

絕對值

NumPy 也支援絕對值運算,可以使用 abs() 函式或 np.abs() 函式來計算陣列元素的絕對值。例如:

x = np.array([-2, -1, 0, 1, 2])
abs_x = abs(x)  # 或 np.abs(x)
print(abs_x)  # Output: [2 1 0 1 2]

內容解密:

在上面的例子中,我們使用 abs() 函式計算了陣列 x 的絕對值。這個函式會傳回一個新的陣列,其中每個元素都是原始陣列中對應元素的絕對值。

圖表翻譯:

在這個流程圖中,我們可以看到原始陣列 x 被輸入到絕對值運算中,然後產生結果陣列 abs_x,最終輸出結果。

布林/位元運算

除了基本運算和絕對值運算外,NumPy 還支援布林/位元運算。這些運算可以用於比較、邏輯運算等。例如:

x = np.array([1, 2, 3, 4, 5])
y = x > 3  # 布林比較運算
print(y)  # Output: [False False False True True]

內容解密:

在上面的例子中,我們使用 > 運算子進行布林比較運算,產生了一個布林陣列 y,其中每個元素表示原始陣列中對應元素是否大於 3。

圖表翻譯:

在這個流程圖中,我們可以看到原始陣列 x 被輸入到布林比較運算中,然後產生結果布林陣列 y,最終輸出結果。

瞭解NumPy的基本數學運算

NumPy是一個強大的Python函式庫,提供了多種數學運算功能。在這篇文章中,我們將探討NumPy的基本數學運算,包括絕對值運算、三角函式運算等。

絕對值運算

絕對值運算是指計算一個數字的絕對值。NumPy提供了np.absolutenp.abs兩個函式來實作絕對值運算。這兩個函式的作用相同,都可以計算一個數字的絕對值。

import numpy as np

x = np.array([2, 1, 0, 1, 2])
print(np.absolute(x))  # Output: [2 1 0 1 2]
print(np.abs(x))  # Output: [2 1 0 1 2]

三角函式運算

NumPy提供了多種三角函式運算,包括正弦、餘弦、正切等。這些函式可以用來計算三角函式的值。

import numpy as np

theta = np.linspace(0, np.pi, 3)
print("theta = ", theta)
print("sin(theta) = ", np.sin(theta))
print("cos(theta) = ", np.cos(theta))
print("tan(theta) = ", np.tan(theta))

逆三角函式運算

NumPy也提供了多種逆三角函式運算,包括反正弦、反餘弦、反正切等。這些函式可以用來計算逆三角函式的值。

import numpy as np

x = [-1, 0, 1]
print("arcsin(x) = ", np.arcsin(x))
print("arccos(x) = ", np.arccos(x))
print("arctan(x) = ", np.arctan(x))

內容解密:

  • np.linspace(0, np.pi, 3):這行程式碼用於生成一個從0到π的等差數列,共3個資料點。
  • np.sin(theta)np.cos(theta)np.tan(theta):這些函式用於計算三角函式的值。
  • np.arcsin(x)np.arccos(x)np.arctan(x):這些函式用於計算逆三角函式的值。

圖表翻譯:

這個流程圖描述了計算三角函式和逆三角函式的過程。首先,輸入資料;然後,計算三角函式;接下來,計算逆三角函式;最後,輸出結果。

圖表翻譯:

這個流程圖展示了計算三角函式和逆三角函式的步驟。透過這個流程圖,可以清楚地看到計算三角函式和逆三角函式的過程。

逆三角函式與指數函式

在進行數學運算時,瞭解各種函式的運用方法至關重要。在這個部分,我們將探討逆三角函式和指數函式的使用方式。

首先,讓我們來看看逆三角函式。這些函式包括反正弦(arcsin)、反餘弦(arccos)和反正切(arctan)。以下是這些函式的使用示例:

import numpy as np

x = np.array([-1, 0, 1])

print("x = ", x)
print("arcsin(x) = ", np.arcsin(x))
print("arccos(x) = ", np.arccos(x))
print("arctan(x) = ", np.arctan(x))

這段程式碼計算了陣列 x 中每個元素的反正弦、反餘弦和反正切。結果顯示了這些函式的輸出值。

接下來,我們來看一下指數函式。NumPy 提供了多種指數函式,包括 exp(計算 e 的指數)、exp2(計算 2 的指數)和 power(計算任意基數的指數)。以下是這些函式的使用示例:

x = np.array([1, 2, 3])

print("x =", x)
print("e^x =", np.exp(x))
print("2^x =", np.exp2(x))
print("3^x =", np.power(3., x))

這段程式碼計算了陣列 x 中每個元素的 e 指數、2 指數和 3 指數。結果顯示了這些函式的輸出值。

內容解密:

  • np.arcsin(x):計算陣列 x 中每個元素的反正弦。
  • np.arccos(x):計算陣列 x 中每個元素的反餘弦。
  • np.arctan(x):計算陣列 x 中每個元素的反正切。
  • np.exp(x):計算陣列 x 中每個元素的 e 指數。
  • np.exp2(x):計算陣列 x 中每個元素的 2 指數。
  • np.power(3., x):計算陣列 x 中每個元素的 3 指數。

圖表翻譯:

這個流程圖描述了計算逆三角函式和指數函式的過程。首先,輸入陣列 x,然後計算每個元素的反正弦、反餘弦和反正切,接著計算每個元素的 e 指數、2 指數和 3 指數,最後輸出結果。

指數函式與對數函式的應用

在數學運算中,指數函式和對數函式是兩個非常重要的概念。指數函式可以用來計算一個數字的冪,而對數函式則可以用來計算一個數字的對數。

指數函式

指數函式可以用來計算一個數字的冪。例如,e^x2^x3^x等。其中,e是一個常數,約等於2.71828。

import numpy as np

# 定義指數函式
def exponential(x, base):
    return base ** x

# 測試指數函式
x = np.array([1, 2, 3])
print("e^x =", np.exp(x))
print("2^x =", exponential(x, 2))
print("3^x =", exponential(x, 3))

對數函式

對數函式可以用來計算一個數字的對數。例如,自然對數(ln(x))、底2對數(log2(x))、底10對數(log10(x))等。

import numpy as np

# 定義對數函式
def logarithm(x, base):
    return np.log(x) / np.log(base)

# 測試對數函式
x = np.array([1, 2, 4, 10])
print("x =", x)
print("ln(x) =", np.log(x))
print("log2(x) =", np.log2(x))
print("log10(x) =", np.log10(x))

小數點下的精確度

在計算小於1的對數時,需要注意精確度問題。NumPy提供了一些特殊版本的對數函式,可以用來維持小於1的輸入的精確度。

import numpy as np

# 測試小於1的對數函式
x = np.array([0, 0.001, 0.01, 0.1])
print("x =", x)
print("ln(x) =", np.log(x))
print("log2(x) =", np.log2(x))
print("log10(x) =", np.log10(x))

圖表翻譯:

內容解密:

上述程式碼展示瞭如何使用NumPy計算指數函式和對數函式。其中,np.exp(x)計算了e^x,而np.log(x)計算了自然對數。另外,np.log2(x)np.log10(x)計算了底2對數和底10對數。這些函式可以用來解決各種實際問題,例如計算複利、人口增長率等。

專業數學函式與NumPy

在進行數學計算時,尤其是在科學計算和工程應用中,高精確度和效率是非常重要的。NumPy提供了一系列特殊的數學函式,可以幫助我們實作這些目標。

避免溢位和精確度問題

當計算涉及非常小或非常大的數值時,直接使用基本的數學函式可能會導致溢位或精確度問題。為了避免這些問題,NumPy提供了一些特殊的函式,例如np.expm1np.log1p

import numpy as np

x = np.array([0, 1e-6, 1e-4, 1e-2])

print("exp(x) - 1 =", np.expm1(x))
print("log(1 + x) =", np.log1p(x))

這些函式可以提供更高的精確度,尤其是在計算非常小的數值時。

超越函式和特殊函式

除了基本的數學函式外,NumPy還提供了一系列超越函式和特殊函式,包括雙曲線函式、位元運算、比較運算、度分轉換、四捨五入和餘數等。這些函式可以在各種科學計算和工程應用中發揮重要作用。

SciPy中的特殊函式

如果您需要計算一些不常見的數學函式,SciPy的special子模組可能是您的最佳選擇。這個子模組提供了大量的特殊函式,包括Gamma函式、Beta函式、誤差函式等。

from scipy import special
import numpy as np

x = np.array([1, 5, 10])

print("gamma(x) =", special.gamma(x))
print("ln|gamma(x)| =", special.gammaln(x))
print("beta(x, 2) =", special.beta(x, 2))

x = np.array([0, 0.3, 0.7, 1.0])

print("erf(x) =", special.erf(x))

這些特殊函式可以幫助您解決各種複雜的數學問題。

圖表翻譯:

內容解密:

上述程式碼展示瞭如何使用NumPy和SciPy中的特殊函式來計算各種數學問題。這些函式可以幫助您提高計算的精確度和效率,並解決各種複雜的數學問題。

進階ufunc功能

NumPy的ufunc(通用函式)提供了許多強大的功能,讓使用者可以高效地進行數值計算。除了基本的數學運算外,ufunc還有一些進階功能,可以幫助使用者最佳化計算過程。

指定輸出

在進行大規模計算時,能夠指定計算結果儲存的陣列可以節省記憶體空間。所有ufunc都可以使用out引數來指定輸出陣列。例如:

import numpy as np

x = np.arange(5)
y = np.empty(5)

np.multiply(x, 10, out=y)

print(y)

輸出結果為:

[ 0. 10. 20. 30. 40.]

這個功能甚至可以用於陣列檢視(array views)。例如,我們可以將計算結果寫入指定陣列的每其他元素:

y = np.zeros(10)
np.power(2, x, out=y[::2])

print(y)

輸出結果為:

[ 1. 0. 2. 0. 4. 0. 8. 0. 16. 0.]

其他進階功能

除了指定輸出外,ufunc還有其他進階功能,例如:

  • where引數:可以根據條件指定哪些元素應該被計算。
  • casting引數:可以指定資料型別轉換的方式。
  • order引數:可以指定計算的順序。

這些功能可以幫助使用者最佳化計算過程,提高效率。

內容解密:

上述程式碼示範瞭如何使用out引數來指定計算結果儲存的陣列。這個功能可以節省記憶體空間,尤其是在進行大規模計算時。另外,程式碼還示範瞭如何使用陣列檢視來將計算結果寫入指定陣列的每其他元素。

圖表翻譯:

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title NumPy陣列堆積疊拆分與向量化運算

package "NumPy 陣列操作" {
    package "陣列建立" {
        component [ndarray] as arr
        component [zeros/ones] as init
        component [arange/linspace] as range
    }

    package "陣列操作" {
        component [索引切片] as slice
        component [形狀變換 reshape] as reshape
        component [堆疊 stack/concat] as stack
        component [廣播 broadcasting] as broadcast
    }

    package "數學運算" {
        component [元素運算] as element
        component [矩陣運算] as matrix
        component [統計函數] as stats
        component [線性代數] as linalg
    }
}

arr --> slice : 存取元素
arr --> reshape : 改變形狀
arr --> broadcast : 自動擴展
arr --> element : +, -, *, /
arr --> matrix : dot, matmul
arr --> stats : mean, std, sum
arr --> linalg : inv, eig, svd

note right of broadcast
  不同形狀陣列
  自動對齊運算
end note

@enduml

這個流程圖示範瞭如何使用out引數來指定計算結果儲存的陣列。首先,指定輸出陣列,然後進行計算,最後儲存結果。

從效能最佳化視角來看,NumPy 的向量化運算和廣播機制是其效能優勢的關鍵。藉由通用函式(ufuncs)將迴圈操作下放到編譯層級的 C 語言,NumPy 有效地避免了 Python 直譯器在迴圈中頻繁的型別檢查和函式排程,從而顯著提升了陣列運算的效率。然而,過度依賴廣播機制處理高維度陣列,可能導致記憶體消耗激增,因此需謹慎評估效能與資源的平衡。對於需要複雜邏輯或條件判斷的運算,向量化方法的優勢相對有限,此時可以考慮使用 Numba 或 Cython 等工具將效能關鍵的程式碼片段編譯成機器碼,以進一步提升效能。展望未來,隨著硬體加速技術的發展,預期 NumPy 將整合更多硬體加速功能,例如 GPU 運算,以進一步釋放其運算潛力。對於追求極致效能的應用場景,建議技術團隊深入研究 NumPy 的底層機制,並結合硬體加速技術,才能最大程度地發揮其效能優勢。