Perbedaan antara Variabel dan get_variable di TensorFlow

125

Sejauh yang saya tahu, Variableadalah operasi default untuk membuat variabel, dan get_variableterutama digunakan untuk berbagi bobot.

Di satu sisi, ada beberapa orang yang menyarankan untuk menggunakan get_variablealih-alih Variableoperasi primitif setiap kali Anda membutuhkan variabel. Di sisi lain, saya hanya melihat penggunaan get_variabledalam dokumen dan demo resmi TensorFlow.

Oleh karena itu, saya ingin mengetahui beberapa aturan praktis tentang cara menggunakan kedua mekanisme ini dengan benar. Apakah ada prinsip "standar"?

Lifu Huang
sumber
6
get_variable adalah cara baru, Variabel adalah cara lama (yang mungkin akan didukung selamanya) seperti yang dikatakan Lukasz (PS: dia menulis banyak cakupan nama variabel di TF)
Yaroslav Bulatov

Jawaban:

90

Saya akan merekomendasikan untuk selalu menggunakan tf.get_variable(...)- ini akan mempermudah refactor kode Anda jika Anda perlu berbagi variabel kapan saja, misalnya dalam pengaturan multi-gpu (lihat contoh CIFAR multi-gpu). Tidak ada sisi negatifnya.

Murni tf.Variableadalah tingkat yang lebih rendah; di beberapa titik tf.get_variable()tidak ada sehingga beberapa kode masih menggunakan cara tingkat rendah.

Lukasz Kaiser
sumber
5
Terima kasih banyak atas jawaban Anda. Tapi saya masih punya satu pertanyaan tentang bagaimana mengganti tf.Variabledengan tf.get_variablemana - mana. Saat itulah saya ingin menginisialisasi variabel dengan array numpy, saya tidak dapat menemukan cara yang bersih dan efisien untuk melakukannya seperti yang saya lakukan tf.Variable. Bagaimana Anda mengatasinya? Terima kasih.
Lifu Huang
69

tf.Variable adalah kelas, dan ada beberapa cara untuk membuat tf.Variable termasuk tf.Variable.__init__dan tf.get_variable.

tf.Variable.__init__: Membuat variabel baru dengan nilai_awal .

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

tf.get_variable: Mendapat variabel yang ada dengan parameter ini atau membuat yang baru. Anda juga bisa menggunakan penginisialisasi.

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

Sangat berguna untuk menggunakan penginisialisasi seperti xavier_initializer:

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

Informasi lebih lanjut di sini .

Sung Kim
sumber
Ya, Variablesebenarnya maksud saya menggunakan itu __init__. Karena get_variablesangat nyaman, saya bertanya-tanya mengapa sebagian besar kode TensorFlow yang saya lihat digunakan, Variablebukan get_variable. Apakah ada konvensi atau faktor yang perlu dipertimbangkan saat memilih di antara keduanya. Terima kasih!
Lifu Huang
Jika Anda ingin memiliki nilai tertentu, menggunakan Variabel sederhana: x = tf.Variable (3).
Sung Kim
@SungKim biasanya ketika kita menggunakan tf.Variable()kita dapat menginisialisasi sebagai nilai acak dari distribusi normal yang terpotong. Inilah contoh saya w1 = tf.Variable(tf.truncated_normal([5, 50], stddev = 0.01), name = 'w1'). Apa yang setara dengan ini? bagaimana cara saya mengatakan bahwa saya ingin normal yang terpotong? Haruskah saya lakukan w1 = tf.get_variable(name = 'w1', shape = [5,50], initializer = tf.truncated_normal, regularizer = tf.nn.l2_loss)?
Euler_Salter
@Euler_Salter: Anda dapat menggunakan tf.truncated_normal_initializer()untuk mendapatkan hasil yang diinginkan.
Beta
46

Saya dapat menemukan dua perbedaan utama antara yang satu dan yang lainnya:

  1. Pertama adalah tf.Variableselalu membuat variabel baru, sedangkan tf.get_variablemendapatkan variabel yang sudah ada dengan parameter tertentu dari grafik, dan jika tidak ada, membuat variabel baru.

  2. tf.Variable membutuhkan nilai awal yang ditentukan.

Penting untuk mengklarifikasi bahwa fungsi tersebut tf.get_variablemengawali nama dengan cakupan variabel saat ini untuk melakukan pemeriksaan penggunaan kembali. Sebagai contoh:

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

Kesalahan pernyataan terakhir menarik: Dua variabel dengan nama yang sama di bawah lingkup yang sama seharusnya merupakan variabel yang sama. Tetapi jika Anda menguji nama variabel ddan eAnda akan menyadari bahwa Tensorflow mengubah nama variabel e:

d.name   #d.name == "two/v:0"
e.name   #e.name == "two/v_1:0"
Jadiel de Armas
sumber
Contoh yang bagus! Mengenai d.namedan e.name, saya baru saja menemukan dokumen TensorFlow tentang operasi penamaan grafik tensor yang menjelaskannya: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.
Atlas7
2

Perbedaan lainnya terletak pada yang satu dalam hal ('variable_store',)koleksi tetapi yang lainnya tidak.

Silakan lihat kode sumbernya :

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

Izinkan saya mengilustrasikan bahwa:

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('')

Hasil:

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

Lerner Zhang
sumber