變數簡介

在 TensorFlow.org 上檢視 在 Google Colab 中執行 在 GitHub 上檢視原始碼 下載筆記本

TensorFlow 變數是表示程式操控的共用、持續狀態的建議方式。本指南涵蓋如何在 TensorFlow 中建立、更新和管理 tf.Variable 的執行個體。

變數是透過 tf.Variable 類別建立和追蹤的。tf.Variable 代表一個張量,其值可以透過對其執行運算來變更。透過特定的運算,您可以讀取和修改此張量的值。較高階的程式庫 (例如 tf.keras) 使用 tf.Variable 來儲存模型參數。

設定

這個筆記本討論變數放置。如果您想查看變數放置在什麼裝置上,請取消註解這行。

import tensorflow as tf

# Uncomment to see where your variables get placed (see below)
# tf.debugging.set_log_device_placement(True)

建立變數

若要建立變數,請提供初始值。tf.Variable 將會具有與初始值相同的 dtype

my_tensor = tf.constant([[1.0, 2.0], [3.0, 4.0]])
my_variable = tf.Variable(my_tensor)

# Variables can be all kinds of types, just like tensors
bool_variable = tf.Variable([False, False, False, True])
complex_variable = tf.Variable([5 + 4j, 6 + 1j])

變數的外觀和行為都像張量,而且實際上是由 tf.Tensor 支援的資料結構。就像張量一樣,它們具有 dtype 和形狀,而且可以匯出至 NumPy。

print("Shape: ", my_variable.shape)
print("DType: ", my_variable.dtype)
print("As NumPy: ", my_variable.numpy())

大部分的張量運算都可以在變數上如預期般運作,但變數無法重新塑形。

print("A variable:", my_variable)
print("\nViewed as a tensor:", tf.convert_to_tensor(my_variable))
print("\nIndex of highest value:", tf.math.argmax(my_variable))

# This creates a new tensor; it does not reshape the variable.
print("\nCopying and reshaping: ", tf.reshape(my_variable, [1,4]))

如上所述,變數是由張量支援的。您可以使用 tf.Variable.assign 重新指派張量。呼叫 assign (通常) 不會配置新的張量;而是重複使用現有張量的記憶體。

a = tf.Variable([2.0, 3.0])
# This will keep the same dtype, float32
a.assign([1, 2]) 
# Not allowed as it resizes the variable: 
try:
  a.assign([1.0, 2.0, 3.0])
except Exception as e:
  print(f"{type(e).__name__}: {e}")

如果您在運算中像張量一樣使用變數,通常會對支援張量執行運算。

從現有變數建立新的變數會複製支援張量。兩個變數不會共用相同的記憶體。

a = tf.Variable([2.0, 3.0])
# Create b based on the value of a
b = tf.Variable(a)
a.assign([5, 6])

# a and b are different
print(a.numpy())
print(b.numpy())

# There are other versions of assign
print(a.assign_add([2,3]).numpy())  # [7. 9.]
print(a.assign_sub([7,9]).numpy())  # [0. 0.]

生命週期、命名和監看

在以 Python 為基礎的 TensorFlow 中,tf.Variable 執行個體具有與其他 Python 物件相同的生命週期。

當沒有對變數的參照時,系統會自動解除配置變數。變數也可以命名,這有助於您追蹤和偵錯變數。您可以為兩個變數指定相同的名稱。

# Create a and b; they will have the same name but will be backed by
# different tensors.
a = tf.Variable(my_tensor, name="Mark")
# A new variable with the same name, but different value
# Note that the scalar add is broadcast
b = tf.Variable(my_tensor + 1, name="Mark")

# These are elementwise-unequal, despite having the same name
print(a == b)

儲存和載入模型時,會保留變數名稱。根據預設,模型中的變數會自動取得唯一的變數名稱,因此除非您想要自行指派,否則不需要指派。

雖然變數對於微分很重要,但有些變數不需要微分。您可以在建立時將 trainable 設定為 false,以關閉變數的梯度。不需要梯度的變數範例是訓練步驟計數器。

step_counter = tf.Variable(1, trainable=False)

放置變數和張量

為了獲得更佳效能,TensorFlow 會嘗試將張量和變數放置在與其 dtype 相容的最快裝置上。這表示如果 GPU 可用,大部分的變數都會放置在 GPU 上。

不過,您可以覆寫此設定。在此程式碼片段中,即使 GPU 可用,仍將浮點張量和變數放置在 CPU 上。透過開啟裝置放置記錄 (請參閱「設定」),您可以查看變數放置在哪裡。

如果您在有無 GPU 的不同後端執行此筆記本,您會看到不同的記錄。請注意,裝置放置記錄必須在工作階段開始時開啟。

with tf.device('CPU:0'):

  # Create some tensors
  a = tf.Variable([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
  b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
  c = tf.matmul(a, b)

print(c)

可以將變數或張量的位置設定在一個裝置上,並在另一個裝置上執行運算。這會造成延遲,因為資料需要在裝置之間複製。

不過,如果您有多個 GPU 工作站,但只想要一份變數副本,您可能會這麼做。

with tf.device('CPU:0'):
  a = tf.Variable([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
  b = tf.Variable([[1.0, 2.0, 3.0]])

with tf.device('GPU:0'):
  # Element-wise multiply
  k = a * b

print(k)

如需分散式訓練的詳細資訊,請參閱指南

後續步驟

若要瞭解變數的典型用法,請參閱我們的自動微分指南。