Sự khác biệt giữa Biến và get_variable trong TensorFlow


125

Theo như tôi biết, Variable là thao tác mặc định để tạo biến và get_variablechủ yếu được sử dụng để chia sẻ trọng lượng.

Một mặt, có một số người đề nghị sử dụng get_variablethay vì Variablethao tác nguyên thủy bất cứ khi nào bạn cần một biến. Mặt khác, tôi chỉ thấy bất kỳ việc sử dụngget_variable trong các tài liệu và bản demo chính thức của TensorFlow.

Vì vậy, tôi muốn biết một số quy tắc về cách sử dụng chính xác hai cơ chế này. Có bất kỳ nguyên tắc "tiêu chuẩn"?


6
get_variable là cách mới, Biến là cách cũ (có thể được hỗ trợ mãi mãi) như Lukasz nói (PS: anh ấy đã viết nhiều về phạm vi tên biến trong TF)
Yaroslav Bulatov

Câu trả lời:


90

Tôi khuyên bạn nên luôn luôn sử dụng tf.get_variable(...)- việc tái cấu trúc mã của bạn sẽ dễ dàng hơn nếu bạn cần chia sẻ các biến bất cứ lúc nào, ví dụ như trong cài đặt nhiều gpu (xem ví dụ CIFAR đa gpu). Không có nhược điểm của nó.

Tinh khiết tf.Variablelà cấp thấp hơn; tại một số điểm tf.get_variable()không tồn tại nên một số mã vẫn sử dụng cách thức cấp thấp.


5
Cảm ơn bạn rất nhiều cho câu trả lời của bạn. Nhưng tôi vẫn có một câu hỏi về cách thay thế tf.Variablebằng tf.get_variablemọi nơi. Đó là khi tôi muốn khởi tạo một biến với một mảng numpy, tôi không thể tìm thấy một cách làm sạch và hiệu quả như tôi làm với tf.Variable. Làm thế nào để bạn giải quyết nó? Cảm ơn.
Lifu Huang

68

tf.Variable là một lớp và có một số cách để tạo tf.Variable bao gồm tf.Variable.__init__tf.get_variable.

tf.Variable.__init__: Tạo một biến mới với init_value .

W = tf.Variable(<initial-value>, name=<optional-name>)

tf.get_variable: Nhận một biến hiện có với các tham số này hoặc tạo một biến mới. Bạn cũng có thể sử dụng trình khởi tạo.

W = tf.get_variable(name, shape=None, dtype=tf.float32, initializer=None,
       regularizer=None, trainable=True, collections=None)

Nó rất hữu ích để sử dụng các trình khởi tạo, chẳng hạn như xavier_initializer:

W = tf.get_variable("W", shape=[784, 256],
       initializer=tf.contrib.layers.xavier_initializer())

Thêm thông tin ở đây .


Vâng, Variablethực sự tôi có nghĩa là sử dụng nó __init__. Vì get_variablenó rất thuận tiện, tôi tự hỏi tại sao hầu hết mã TensorFlow tôi thấy sử dụng Variablethay vì get_variable. Có bất kỳ quy ước hoặc yếu tố để xem xét khi lựa chọn giữa chúng. Cảm ơn bạn!
Lifu Huang

Nếu bạn muốn có một giá trị nhất định, sử dụng Biến là đơn giản: x = tf.Variable (3).
Sung Kim

@SungKim bình thường khi chúng tôi sử dụng, tf.Variable()chúng tôi có thể khởi tạo nó dưới dạng giá trị ngẫu nhiên từ phân phối chuẩn bị cắt ngắn. Đây là ví dụ của tôi w1 = tf.Variable(tf.truncated_normal([5, 50], stddev = 0.01), name = 'w1'). Tương đương của điều này sẽ là gì? Làm thế nào để tôi nói với nó tôi muốn cắt ngắn bình thường? Tôi có nên làm w1 = tf.get_variable(name = 'w1', shape = [5,50], initializer = tf.truncated_normal, regularizer = tf.nn.l2_loss)không?
Euler_Salter

@Euler_Salter: Bạn có thể sử dụng tf.truncated_normal_initializer()để có được kết quả mong muốn.
Beta

46

Tôi có thể tìm thấy hai sự khác biệt chính giữa cái này và cái khác:

  1. Đầu tiên là tf.Variablesẽ luôn tạo một biến mới, trong khi đó tf.get_variablecó một biến hiện có với các tham số đã chỉ định từ biểu đồ và nếu nó không tồn tại, sẽ tạo một biến mới.

  2. tf.Variable đòi hỏi một giá trị ban đầu được chỉ định.

Điều quan trọng là phải làm rõ rằng hàm tf.get_variabletiền tố tên với phạm vi biến hiện tại để thực hiện kiểm tra tái sử dụng. Ví dụ:

with tf.variable_scope("one"):
    a = tf.get_variable("v", [1]) #a.name == "one/v:0"
with tf.variable_scope("one"):
    b = tf.get_variable("v", [1]) #ValueError: Variable one/v already exists
with tf.variable_scope("one", reuse = True):
    c = tf.get_variable("v", [1]) #c.name == "one/v:0"

with tf.variable_scope("two"):
    d = tf.get_variable("v", [1]) #d.name == "two/v:0"
    e = tf.Variable(1, name = "v", expected_shape = [1]) #e.name == "two/v_1:0"

assert(a is c)  #Assertion is true, they refer to the same object.
assert(a is d)  #AssertionError: they are different objects
assert(d is e)  #AssertionError: they are different objects

Lỗi xác nhận cuối cùng rất thú vị: Hai biến có cùng tên trong cùng phạm vi được cho là cùng một biến. Nhưng nếu bạn kiểm tra tên của các biến debạn sẽ nhận ra rằng Tensorflow đã thay đổi tên của biến e:

d.name   #d.name == "two/v:0"
e.name   #e.name == "two/v_1:0"

Ví dụ tuyệt vời! Về d.namee.name, tôi vừa bắt gặp một tài liệu TensorFlow này về hoạt động đặt tên biểu đồIf the default graph already contained an operation named "answer", the TensorFlow would append "_1", "_2", and so on to the name, in order to make it unique.
tenor

2

Một sự khác biệt khác nằm ở chỗ một trong ('variable_store',)bộ sưu tập nhưng cái khác thì không.

Xin vui lòng xem nguồn đang :

def _get_default_variable_store():
  store = ops.get_collection(_VARSTORE_KEY)
  if store:
    return store[0]
  store = _VariableStore()
  ops.add_to_collection(_VARSTORE_KEY, store)
  return store

Hãy để tôi minh họa rằng:

import tensorflow as tf
from tensorflow.python.framework import ops

embedding_1 = tf.Variable(tf.constant(1.0, shape=[30522, 1024]), name="word_embeddings_1", dtype=tf.float32) 
embedding_2 = tf.get_variable("word_embeddings_2", shape=[30522, 1024])

graph = tf.get_default_graph()
collections = graph.collections

for c in collections:
    stores = ops.get_collection(c)
    print('collection %s: ' % str(c))
    for k, store in enumerate(stores):
        try:
            print('\t%d: %s' % (k, str(store._vars)))
        except:
            print('\t%d: %s' % (k, str(store)))
    print('')

Đầu ra:

collection ('__variable_store',): 0: {'word_embeddings_2': <tf.Variable 'word_embeddings_2:0' shape=(30522, 1024) dtype=float32_ref>}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.