associative_scan
函數keras.ops.associative_scan(f, elems, reverse=False, axis=0)
並行執行使用結合律二元運算的掃描。
此操作類似於 scan
,主要區別在於 associative_scan
是一個並行實作,可能具有顯著的效能優勢,尤其是在經過 JIT 編譯時。但限制是它只能在 f
是二元結合律運算時使用(即它必須驗證 f(a, f(b, c)) == f(f(a, b), c)
)。
關於結合律掃描的介紹,請參考這篇論文:Blelloch, Guy E. 1990. 前綴和及其應用。
參數
r = f(a, b)
。函數 f
必須是結合律的,即它必須滿足方程式 f(a, f(b, c)) == f(f(a, b), c)
。輸入和結果是(可能巢狀的 Python 樹狀結構)與 elems
相符的陣列。每個陣列都有一個維度代替 axis
維度。f
應在 axis
維度上逐元素應用。結果 r
具有與兩個輸入 a
和 b
相同的形狀(和結構)。axis
維度,大小為 num_elems
。axis
維度反向。回傳
一個(可能巢狀的 Python 樹狀結構)陣列,具有與 elems
相同的形狀和結構,其中 axis
的第 k
個元素是遞迴應用 f
以組合沿 axis
的 elems
的前 k
個元素的結果。例如,給定 elems = [a, b, c, ...]
,結果將是 [a, f(a, b), f(f(a, b), c), ...]
。
範例
>>> sum_fn = lambda x, y: x + y
>>> xs = keras.ops.arange(5)
>>> ys = keras.ops.associative_scan(sum_fn, xs, axis=0)
>>> ys
[0, 1, 3, 6, 10]
>>> sum_fn = lambda x, y: [x[0] + y[0], x[1] + y[1], x[2] + y[2]]
>>> xs = [keras.ops.array([[1, 2]]) for _ in range(3)]
>>> ys = keras.ops.associative_scan(sum_fn, xs, axis=0)
>>> ys
[[1, 3], [1, 3], [1, 3]]
cast
函數keras.ops.cast(x, dtype)
將張量轉換為所需的 dtype。
參數
回傳
一個指定 dtype
的張量。
範例
>>> x = keras.ops.arange(4)
>>> x = keras.ops.cast(x, dtype="float16")
cond
函數keras.ops.cond(pred, true_fn, false_fn)
有條件地應用 true_fn
或 false_fn
。
參數
pred == True
的情況下回傳輸出。pred == False
的情況下回傳輸出。回傳
根據 pred,true_fn
或 false_fn
的輸出。
convert_to_numpy
函數keras.ops.convert_to_numpy(x)
將張量轉換為 NumPy 陣列。
參數
回傳
一個 NumPy 陣列。
convert_to_tensor
函數keras.ops.convert_to_tensor(x, dtype=None, sparse=None, ragged=None)
將 NumPy 陣列或 Python 陣列轉換為張量。
當前後端的原生張量,或保持不變,除非設定了 dtype
、sparse
或 ragged
參數。
參數
None
,則使用 x
的類型。False
將導致稀疏張量被稠密化。預設值 None
表示僅在後端支援稀疏張量時才保留它們。False
將導致參差不齊的張量被稠密化。預設值 None
表示僅在後端支援參差不齊的張量時才保留它們。回傳
一個具有指定 dtype
和稀疏性的後端張量。
範例
>>> x = np.array([1, 2, 3])
>>> y = keras.ops.convert_to_tensor(x)
custom_gradient
函數keras.ops.custom_gradient(f)
用於定義具有自訂梯度的函數的裝飾器。
此裝飾器允許對操作序列的梯度進行細粒度控制。這可能由於多種原因而有用,包括為操作序列提供更有效率或數值穩定的梯度。
參數
f(*args)
,回傳一個元組 (output, grad_fn)
,其中args
是函數的(巢狀結構)張量輸入序列。output
是將 forward_fn
中的操作應用於 args
的(巢狀結構)張量輸出。grad_fn
是一個簽名為 grad_fn(*args, upstream)
的函數,它回傳一個與(扁平化)args
大小相同的張量元組:output
中張量相對於 args
中張量的導數。upstream
是一個張量或張量序列,持有 output
中每個張量的初始值梯度。回傳
一個函數 h(*args)
,它回傳與 f(*args)[0]
相同的值,並且其梯度由 f(*args)[1]
決定。
範例
@ops.custom_gradient
def log1pexp(x):
e = ops.exp(x)
def grad(*args, upstream=None):
if upstream is None:
(upstream,) = args
return ops.multiply(upstream, 1.0 - 1.0 / ops.add(1, e))
return ops.log(1 + e), grad
請注意,回傳梯度計算的 grad 函數需要 args
以及 upstream
關鍵字參數,具體取決於設定的後端。對於 JAX 和 TensorFlow 後端,它只需要一個參數,而在 PyTorch 後端的情況下,它可能會使用 upstream
參數。
當使用 TensorFlow/JAX 後端時,grad(upstream)
就足夠了。對於 PyTorch,grad
函數需要 *args
以及 upstream
,例如 def grad(*args, upstream)
。請按照前面的範例使用 @ops.custom_gradient
,使其與所有後端相容。
@ops.custom_gradient
def log1pexp(x):
e = ops.exp(x)
def grad(upstream):
return ops.multiply(upstream, 1.0 - 1.0 / ops.add(1, e))
return ops.log(1 + e), grad
*args
和 upstream
@ops.custom_gradient
def log1pexp(x):
e = ops.exp(x)
def grad(*args, upstream):
return ops.multiply(upstream, 1.0 - 1.0 / ops.add(1, e))
return ops.log(1 + e), grad
dtype
函數keras.ops.dtype(x)
以標準化字串形式回傳張量輸入的 dtype。
請注意,由於標準化,dtype 將不等於後端特定版本的 dtype。
參數
dtype
屬性。回傳
一個字串,指示輸入張量的 dtype,例如 "float32"
。
範例
>>> x = keras.ops.zeros((8, 12))
>>> keras.ops.dtype(x)
'float32'
erf
函數keras.ops.erf(x)
逐元素計算 x
的誤差函數。
參數
回傳
一個與 x
具有相同 dtype 的張量。
範例
>>> x = np.array([-3.0, -2.0, -1.0, 0.0, 1.0])
>>> keras.ops.erf(x)
array([-0.99998 , -0.99532, -0.842701, 0., 0.842701], dtype=float32)
erfinv
函數keras.ops.erfinv(x)
逐元素計算 x
的反誤差函數。
參數
回傳
一個與 x
具有相同 dtype 的張量。
範例
>>> x = np.array([-0.5, -0.2, -0.1, 0.0, 0.3])
>>> keras.ops.erfinv(x)
array([-0.47694, -0.17914, -0.08886, 0. , 0.27246], dtype=float32)
extract_sequences
函數keras.ops.extract_sequences(x, sequence_length, sequence_stride)
將最後一個軸的維度展開為長度為 sequence_length
的序列。
在輸入的最後一個軸上滑動大小為 sequence_length
的視窗,步幅為 sequence_stride
,並將最後一個軸替換為 [num_sequences, sequence_length]
序列。
如果沿最後一個軸的維度為 N,則序列數可以透過以下公式計算
num_sequences = 1 + (N - sequence_length) // sequence_stride
參數
回傳
一個形狀為 [..., num_sequences, sequence_length] 的序列張量。
範例
>>> x = keras.ops.convert_to_tensor([1, 2, 3, 4, 5, 6])
>>> extract_sequences(x, 3, 2)
array([[1, 2, 3],
[3, 4, 5]])
fori_loop
函數keras.ops.fori_loop(lower, upper, body_fun, init_val)
For 迴圈實作。
參數
回傳
迴圈後的最終狀態。
範例
>>> lower = 0
>>> upper = 10
>>> body_fun = lambda i, s: (i + 1, s + i)
>>> init_val = 0
>>> keras.ops.fori_loop(lower, upper, body_fun, init_val)
45
in_top_k
函數keras.ops.in_top_k(targets, predictions, k)
檢查目標是否在 top-k 預測中。
參數
回傳
一個與 targets
具有相同形狀的布林張量,其中每個元素指示相應目標是否在 top-k 預測中。
範例
>>> targets = keras.ops.convert_to_tensor([2, 5, 3])
>>> predictions = keras.ops.convert_to_tensor(
... [[0.1, 0.4, 0.6, 0.9, 0.5],
... [0.1, 0.7, 0.9, 0.8, 0.3],
... [0.1, 0.6, 0.9, 0.9, 0.5]])
>>> in_top_k(targets, predictions, k=3)
array([ True False True], shape=(3,), dtype=bool)
is_tensor
函數keras.ops.is_tensor(x)
檢查給定物件是否為張量。
注意:這會檢查後端特定的張量,因此如果您的後端是 PyTorch 或 JAX,則傳遞 TensorFlow 張量將回傳 False
。
參數
回傳
如果 x
是張量,則為 True
,否則為 False
。
logsumexp
函數keras.ops.logsumexp(x, axis=None, keepdims=False)
計算張量中元素指數和的對數。
參數
None
,則對所有元素計算總和。預設為 None
。False
。回傳
一個包含 x
中元素指數和的對數的張量。
範例
>>> x = keras.ops.convert_to_tensor([1., 2., 3.])
>>> logsumexp(x)
3.407606
map
函數keras.ops.map(f, xs)
將函數映射到前導陣列軸上。
類似於 Python 的內建 map,不同之處在於輸入和輸出採用堆疊陣列的形式。除非您需要逐元素應用函數以減少記憶體使用量或使用其他控制流程原語進行異質計算,否則請考慮使用 vectorized_map()
轉換。
當 xs
是陣列類型時,map()
的語義由這個 Python 實作給出
def map(f, xs):
return np.stack([f(x) for x in xs])
參數
xs
的第一個軸或多個軸的函數。回傳
映射的值。
範例
>>> f = lambda x: x**2
>>> xs = keras.ops.arange(10)
>>> ys = keras.ops.map(f, xs)
>>> ys
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> f = lambda x: {"y1": x**2, "y2": x * 10} # Can have nested outputs
>>> ys = keras.ops.map(f, xs)
>>> ys["y1"]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> ys["y2"]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
rsqrt
函數keras.ops.rsqrt(x)
逐元素計算 x 平方根的倒數。
參數
回傳
一個與 x
具有相同 dtype 的張量。
範例
>>> x = keras.ops.convert_to_tensor([1.0, 10.0, 100.0])
>>> keras.ops.rsqrt(x)
array([1.0, 0.31622776, 0.1], dtype=float32)
saturate_cast
函數keras.ops.saturate_cast(x, dtype)
執行安全的飽和轉換為所需的 dtype。
當轉換為具有較小值範圍的 dtype
時,飽和轉換可防止資料類型溢位。例如,ops.cast(ops.cast([-1, 256], "float32"), "uint8")
回傳 [255, 0]
,但 ops.saturate_cast(ops.cast([-1, 256], "float32"), "uint8")
回傳 [0, 255]
。
參數
回傳
一個安全轉換為指定 dtype
的張量。
範例
使用雙三次插值的影像調整大小可能會產生超出原始範圍的值。
>>> image2x2 = np.array([0, 1, 254, 255], dtype="uint8").reshape(1, 2, 2, 1)
>>> image4x4 = tf.image.resize(image2x2, (4, 4), method="bicubic")
>>> print(image4x4.numpy().squeeze())
>>> # [[-22.500004 -22.204624 -21.618908 -21.32353 ]
>>> # [ 52.526054 52.82143 53.407146 53.70253 ]
>>> # [201.29752 201.59288 202.17859 202.47395 ]
>>> # [276.32355 276.61893 277.20465 277.50006 ]]
將調整大小後的影像轉換回 uint8
將導致溢位。
>>> image4x4_casted = ops.cast(image4x4, "uint8")
>>> print(image4x4_casted.numpy().squeeze())
>>> # [[234 234 235 235]
>>> # [ 52 52 53 53]
>>> # [201 201 202 202]
>>> # [ 20 20 21 21]]
飽和轉換為 uint8
會在轉換前將值剪裁到 uint8
範圍,並且不會導致溢位。
>>> image4x4_saturate_casted = ops.saturate_cast(image4x4, "uint8")
>>> print(image4x4_saturate_casted.numpy().squeeze())
>>> # [[ 0 0 0 0]
>>> # [ 52 52 53 53]
>>> # [201 201 202 202]
>>> # [255 255 255 255]]
scan
函數keras.ops.scan(f, init, xs=None, length=None, reverse=False, unroll=1)
在掃描前導陣列軸上的函數時,同時攜帶狀態。
當 xs
的類型是陣列類型或 None
,且 ys
的類型是陣列類型時,scan()
的語義大致由這個 Python 實作給出
def scan(f, init, xs, length=None):
if xs is None:
xs = [None] * length
carry = init
ys = []
for x in xs:
carry, y = f(carry, x)
ys.append(y)
return carry, np.stack(ys)
迴圈攜帶的值 carry
(init
) 在所有迭代中都必須保持固定的形狀和 dtype。
在 TensorFlow 中,y
的形狀和 dtype 必須與 carry
相符。在其他後端中,這不是必需的。
參數
xs
切片。此可呼叫物件回傳一個配對,其中第一個表示迴圈攜帶的新值,第二個表示輸出的切片。f
回傳的第一個元素的結構相符。xs
,則必須指定 length
以定義迴圈迭代次數。預設為 None
。length
,則預設為 xs
中陣列的前導軸大小。預設為 None
。xs
和 ys
中陣列的前導軸。unroll=True
) 還是完全未展開 (unroll=False
)。請注意,展開僅受 JAX 和 TensorFlow 後端支援。回傳
一個配對,其中第一個元素表示最終迴圈攜帶值,第二個元素表示在掃描輸入的前導軸時,f
的堆疊輸出。
範例
>>> sum_fn = lambda c, x: (c + x, c + x)
>>> init = keras.ops.array(0)
>>> xs = keras.ops.array([1, 2, 3, 4, 5])
>>> carry, result = keras.ops.scan(sum_fn, init, xs)
>>> carry
15
>>> result
[1, 3, 6, 10, 15]
scatter
函數keras.ops.scatter(indices, values, shape)
回傳一個形狀為 shape
的張量,其中 indices
設定為 values
。
在高層次上,此操作執行 zeros[indices] = updates
並回傳輸出。它等效於
zeros = keras.ops.zeros(shape)
output = keras.ops.scatter_update(zeros, indices, values)
參數
values
中值的索引。indices
處設定的值。範例
>>> indices = [[0, 1], [1, 1]]
>>> values = np.array([1., 1.])
>>> keras.ops.scatter(indices, values, shape=(2, 2))
array([[0., 1.],
[0., 1.]])
scatter_update
函數keras.ops.scatter_update(inputs, indices, updates)
透過分散(稀疏)索引處的更新來更新輸入。
在高層次上,此操作執行 inputs[indices] = updates
。假設 inputs
是一個形狀為 (D0, D1, ..., Dn)
的張量,scatter_update
有 2 個主要用法。
indices
是一個形狀為 (num_updates, n)
的 2D 張量,其中 num_updates
是要執行的更新次數,updates
是一個形狀為 (num_updates,)
的 1D 張量。例如,如果 inputs
是 zeros((4, 4, 4))
,並且我們想要將 inputs[1, 2, 3]
和 inputs[0, 1, 3]
更新為 1,那麼我們可以使用inputs = np.zeros((4, 4, 4))
indices = [[1, 2, 3], [0, 1, 3]]
updates = np.array([1., 1.])
inputs = keras.ops.scatter_update(inputs, indices, updates)
2 indices
是一個形狀為 (num_updates, k)
的 2D 張量,其中 num_updates
是要執行的更新次數,k
(k < n
) 是 indices
中每個索引的大小。updates
是一個形狀為 (num_updates, inputs.shape[k:])
的 n - k
-D 張量。例如,如果 inputs = np.zeros((4, 4, 4))
,並且我們想要將 inputs[1, 2, :]
和 inputs[2, 3, :]
更新為 [1, 1, 1, 1]
,那麼 indices
的形狀將為 (num_updates, 2)
(k = 2
),而 updates
的形狀將為 (num_updates, 4)
(inputs.shape[2:] = 4
)。請參閱下面的程式碼
inputs = np.zeros((4, 4, 4))
indices = [[1, 2], [2, 3]]
updates = np.array([[1., 1., 1, 1,], [1., 1., 1, 1,])
inputs = keras.ops.scatter_update(inputs, indices, updates)
參數
(N, inputs.ndim)
的張量或列表/元組,指定要更新的索引。N
是要更新的索引數,必須等於 updates
的第一個維度。indices
處放入 inputs
的新值。回傳
一個張量,具有與 inputs
相同的形狀和 dtype。
segment_max
函數keras.ops.segment_max(data, segment_ids, num_segments=None, sorted=False)
計算張量中區段的最大值。
參數
data
中每個元素的區段索引。data.shape[:len(segment_ids.shape)] 應匹配。segment_ids
中的最大值推斷。segment_ids
是否已排序。預設為 False
。回傳
一個包含區段最大值的張量,其中每個元素表示 data
中相應區段的最大值。
範例
>>> data = keras.ops.convert_to_tensor([1, 2, 10, 20, 100, 200])
>>> segment_ids = keras.ops.convert_to_tensor([0, 0, 1, 1, 2, 2])
>>> num_segments = 3
>>> keras.ops.segment_max(data, segment_ids, num_segments)
array([2, 20, 200], dtype=int32)
segment_sum
函數keras.ops.segment_sum(data, segment_ids, num_segments=None, sorted=False)
計算張量中區段的總和。
參數
data
中每個元素的區段索引。區段 ID 的維度數應嚴格小於或等於資料中的維度數。segment_ids
中的最大值推斷。segment_ids
是否已排序。預設為 False
。回傳
一個包含區段總和的張量,其中每個元素表示 data
中相應區段的總和。
範例
>>> data = keras.ops.convert_to_tensor([1, 2, 10, 20, 100, 200])
>>> segment_ids = keras.ops.convert_to_tensor([0, 0, 1, 1, 2, 2])
>>> num_segments = 3
>>> keras.ops.segment_sum(data, segment_ids,num_segments)
array([3, 30, 300], dtype=int32)
shape
函數keras.ops.shape(x)
取得張量輸入的形狀。
注意:在 TensorFlow 後端上,當 x
是具有動態形狀的 tf.Tensor
時,在編譯函數上下文中為動態的維度將具有 tf.Tensor
值,而不是靜態整數值。
參數
shape
屬性。回傳
一個整數或 None 值元組,指示輸入張量的形狀。
範例
>>> x = keras.ops.zeros((8, 12))
>>> keras.ops.shape(x)
(8, 12)
slice
函數keras.ops.slice(inputs, start_indices, shape)
回傳輸入張量的切片。
在高層次上,此操作是陣列切片的顯式替換,例如 inputs[start_indices: start_indices + shape]
。與透過方括號切片不同,此操作將在所有後端上接受張量起始索引,這在透過其他張量操作動態計算索引時很有用。
inputs = np.zeros((5, 5))
start_indices = np.array([3, 3])
shape = np.array([2, 2])
inputs = keras.ops.slice(inputs, start_indices, shape)
參數
(inputs.ndim,)
的列表/元組,指定更新的起始索引。回傳
一個張量,具有與 inputs
相同的形狀和 dtype。
slice_update
函數keras.ops.slice_update(inputs, start_indices, updates)
透過在更新值張量中切片來更新輸入。
在高層次上,此操作執行 inputs[start_indices: start_indices + updates.shape] = updates
。假設 inputs 是一個形狀為 (D0, D1, ..., Dn)
的張量,start_indices
必須是一個包含 n 個整數的列表/元組,指定起始索引。updates
必須與 inputs
具有相同的秩,並且每個維度的大小不得超過 Di - start_indices[i]
。例如,如果我們有 2D 輸入 inputs = np.zeros((5, 5))
,並且我們想要將最後 2 行和最後 2 列的交集更新為 1,即 inputs[3:, 3:] = np.ones((2, 2))
,那麼我們可以使用下面的程式碼
inputs = np.zeros((5, 5))
start_indices = [3, 3]
updates = np.ones((2, 2))
inputs = keras.ops.slice_update(inputs, start_indices, updates)
參數
(inputs.ndim,)
的列表/元組,指定更新的起始索引。indices
處放入 inputs
的新值。updates
必須與 inputs
具有相同的秩。回傳
一個張量,具有與 inputs
相同的形狀和 dtype。
stop_gradient
函數keras.ops.stop_gradient(variable)
停止梯度計算。
參數
回傳
已停用梯度計算的變數。
範例
>>> var = keras.backend.convert_to_tensor(
... [1., 2., 3.],
... dtype="float32"
... )
>>> var = keras.ops.stop_gradient(var)
switch
函數keras.ops.switch(index, branches, *operands)
確切應用由 index
給出的 branches
之一。
如果 index
超出範圍,則會將其鉗制在範圍內。
switch
的語義大致由這個 Python 實作給出
def switch(index, branches, *operands):
index = clamp(0, index, len(branches) - 1)
return branches[index](*operands)
參數
index
應用的函數序列。回傳
根據 index
選擇的分支的 branch(*operands)
輸出。
範例
>>> add_fn = lambda x, y: x + y
>>> subtract_fn = lambda x, y: x - y
>>> x = keras.ops.array(2.0)
>>> y = keras.ops.array(0.5)
>>> branches = [add_fn, subtract_fn]
>>> keras.ops.switch(0, branches, x, y)
2.5
>>> keras.ops.switch(1, branches, x, y)
1.5
top_k
函數keras.ops.top_k(x, k, sorted=True)
在張量中尋找 top-k 值及其索引。
參數
True
。回傳
一個包含兩個張量的元組。第一個張量包含 top-k 值,第二個張量包含輸入張量中 top-k 值的索引。
範例
>>> x = keras.ops.convert_to_tensor([5, 2, 7, 1, 9, 3])
>>> values, indices = top_k(x, k=3)
>>> print(values)
array([9 7 5], shape=(3,), dtype=int32)
>>> print(indices)
array([4 2 0], shape=(3,), dtype=int32)
unstack
函數keras.ops.unstack(x, num=None, axis=0)
將秩為 R 的張量的給定維度解包為秩為 (R-1) 的張量。
參數
None
,則自動推斷。回傳
沿給定軸解包的張量列表。
範例
>>> x = keras.ops.array([[1, 2], [3, 4]])
>>> keras.ops.unstack(x, axis=0)
[array([1, 2]), array([3, 4])]
vectorized_map
函數keras.ops.vectorized_map(function, elements)
在張量 elements
的軸 0 上並行映射 function
。
示意上,vectorized_map
實作以下內容,在單個張量輸入 elements
的情況下
def vectorized_map(function, elements)
outputs = []
for e in elements:
outputs.append(function(e))
return stack(outputs)
在張量 elements
的可迭代物件的情況下,它實作以下內容
def vectorized_map(function, elements)
batch_size = elements[0].shape[0]
outputs = []
for index in range(batch_size):
outputs.append(function([e[index] for e in elements]))
return np.stack(outputs)
在這種情況下,function
預期將單個張量引數列表作為輸入。
while_loop
函數keras.ops.while_loop(cond, body, loop_vars, maximum_iterations=None)
While 迴圈實作。
參數
loop_vars
的結構作為引數。如果 loop_vars
是元組或列表,則 loop_vars
的每個元素將按位置傳遞給可呼叫物件。loop_vars
的結構作為引數,並回傳具有相同結構的更新值。如果 loop_vars
是元組或列表,則 loop_vars
的每個元素將按位置傳遞給可呼叫物件。cond
輸出與一個附加條件進行 AND 運算,以確保執行的迭代次數不超過 maximum_iterations
。回傳
一個張量列表/元組,具有與 inputs
相同的形狀和 dtype。
範例
>>> i = 0
>>> cond = lambda i: i < 10
>>> body = lambda i: i + 1
>>> keras.ops.while_loop(cond, body, i)
10
>>> x, y = 0, 1
>>> cond = lambda x, y: x < 10
>>> body = lambda x, y: (x + 1, y + 1)
>>> keras.ops.while_loop(cond, body, (x, y))
10, 11