TensorFlow'da düzenlilik nasıl eklenir?


95

TensorFlow kullanılarak uygulanan birçok kullanılabilir sinir ağı kodunda, düzenleme terimlerinin genellikle kayıp değerine manuel olarak ek bir terim ekleyerek uygulandığını gördüm.

Sorularım:

  1. Manuel olarak yapmaktan daha zarif veya önerilen bir düzenleme yöntemi var mı?

  2. Bunun get_variablebir argümanı olduğunu da görüyorum regularizer. Nasıl kullanılmalıdır? Biz gibi (buna bir regularizer geçirirseniz benim gözlemlere göre tf.contrib.layers.l2_regularizer, regularize terimini temsil eden bir tensör bilgisayarlı edilecek ve adında bir grafik koleksiyonuna eklendi tf.GraphKeys.REGULARIZATOIN_LOSSES. Bu koleksiyon otomatik optimize eğitimi)? Ya kullandığı örn TensorFlow (tarafından kullanılacak Will bu koleksiyonu kendi başıma kullanmam bekleniyor mu?


1
süper açık olmak gerekirse, bunu yapmanın yolu bu S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer )mu?
Pinocchio

@Pinocchio bunu çözdün mü?
Euler_Salter

2
@Euler_Salter Artık hatırlamıyorum, üzgünüm! Artık tensör akışını kullanmamak!
Pinokyo

Yanıtlar:


70

İkinci noktada söylediğiniz gibi, regularizerargümanı kullanmak önerilen yoldur. Bunu içinde kullanabilir get_variableveya bir kez ayarlayabilir variable_scopeve tüm değişkenlerinizi düzenleyebilirsiniz.

Kayıplar grafikte toplanır ve bunları maliyet fonksiyonunuza manuel olarak bu şekilde eklemeniz gerekir.

  reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
  reg_constant = 0.01  # Choose an appropriate one.
  loss = my_normal_loss + reg_constant * sum(reg_losses)

Umarım yardımcı olur!


2
Teşekkürler dostum. TensorFlow'un reg terimlerini manuel olarak kullanmaktan daha akıllıca işleyebileceğini düşünüyordum, öyle görünüyor: P
Lifu Huang

14
BTW, iki öneri, yanılıyorsam düzeltin. (1), sanırım reg_constantTensorFlow'daki düzenleyicilerin kurucularında bir argümanı scaleolduğundan, reg terimlerinin etkisinin daha ince bir şekilde kontrol edilebilmesi için gerekli olmayabilir. Ve (2) kullanmak tf.add_nbiraz daha iyi olabilir sum, sanırım toplam kullanmak ara sonucu saklamak için grafikte birçok tensör oluşturabilir.
Lifu Huang

1
Yani, sadece çok netleştirmek için, düzenleyiciyi değişkene koyduktan sonra S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer ), önerdiğiniz kodu mu yapacağım? Gibi sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))mi?
Pinocchio

1
Tf.get_collection (tf.GraphKeys.REGULARIZATION_LOSSES) ile ağırlık değişkenlerinin koleksiyonun bir parçası olmasını nasıl sağlayacağınızı gösterebilir misiniz?
Yu Shen

3
Bunun tf.reduce_sumyerine kullanılmalı gibi görünüyor sum?
ComputerScientist

46

Mevcut cevabın birkaç yönü benim için hemen anlaşılamadı, bu yüzden işte adım adım bir kılavuz:

  1. Düzenleyici tanımlayın. Düzenleme sabitinin ayarlanabileceği yer burasıdır, örneğin:

    regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
    
  2. Şu yolla değişkenler oluşturun:

        weights = tf.get_variable(
            name="weights",
            regularizer=regularizer,
            ...
        )
    

    Aynı şekilde, değişkenler normal weights = tf.Variable(...)kurucu aracılığıyla ve ardından tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights).

  3. Bir lossterim tanımlayın ve düzenleme terimini ekleyin:

    reg_variables = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
    reg_term = tf.contrib.layers.apply_regularization(regularizer, reg_variables)
    loss += reg_term
    

    Not: Görünüşe tf.contrib.layers.apply_regularizationbir şekilde uygulanmaktadır AddNkadar az ya da çok eşdeğeri sum(reg_variables).


10
Düzenleyiciyi iki kez uyguladığınızı düşünüyorum - hem adım hem de 3. adımda apply_regularization, değişkeni oluştururken düzenleyiciyi zaten belirttiyseniz gerekli olmamalıdır.
interjay

2
@interjay lütfen bir örnek verin, tüm bu cevaplar çok net değil! Bunun nedeni, her zaman altında yukarıdaki cevabın yanlış bir şey olduğunu söyleyen bir yorum yazan en az bir kişinin olmasıdır.
Euler_Salter

1
@interjay Bunu en son test ettiğimde her ikisini de yapmanın gerekli olduğuna eminim. Yine de bunun değişip değişmediğinden emin değilim.
bluenote10

1
Hayır, bu mantıklı değil çünkü o zaman aynı düzenleyiciyi iki işleve aktarmanıza gerek kalmaz. Dokümantasyon (ve isim) REGULARIZATION_LOSSES, düzenleyicilerden geri dönen toplam kayıp olduğunu açıkça ortaya koyuyor , bu yüzden esasen çağırıyorsunuz regularizer(regularizer(weight)).
interjay

1
Sanırım buradaki kafa karışıklığı "eşdeğer" kısmından kaynaklanıyor. O iki farklı yöntem tanımlıyor ve siz birini seçiyorsunuz, bu iki kez normalleştirmeyi içeren bir yöntem değil.
gcp

28

Bulamadığım için basit bir doğru cevap vereceğim. İki basit adıma ihtiyacınız var, gerisi tensorflow büyüsü ile yapılır:

  1. Değişkenler veya katmanlar oluştururken düzenleyiciler ekleyin:

    tf.layers.dense(x, kernel_regularizer=tf.contrib.layers.l2_regularizer(0.001))
    # or
    tf.get_variable('a', regularizer=tf.contrib.layers.l2_regularizer(0.001))
    
  2. Kaybı tanımlarken düzenleme terimini ekleyin:

    loss = ordinary_loss + tf.losses.get_regularization_loss()
    

Düzenleyici = tf.contrib.layers.l2_regularizer (0.001) ile bir düzenleyici op oluşturuyorsam, bunu birden çok katman başlatmasına aktarabilir miyim? veya her katman için ayrı bir düzenleyici oluşturmam gerekiyor mu likeregularizer1 = tf.contrib.layers.l2_regularizer (0.001), normalizer2 = ................. regulizer3 = .... .. ve bunun gibi?
MiloMinderbinder

@Nitin Aynı düzenleyiciyi kullanabilirsiniz. Bu sadece argümanı olarak ağırlıklara kayıp uygulayan bir python işlevidir.
alyaxey

1
Bu en zarif çözüm gibi görünüyor ama bu gerçekten işe yarıyor mu? Bunun reg_variables = tf.get_collection (tf.GraphKeys.REGULARIZATION_LOSSES) reg_term = tf.contrib.layers.apply_regularization (düzenleyici, reg_variables) loss + = reg_term
GeorgeOfTheRF'den farkı

1
Tf.contrib.layers.fully_connected'ın tf.layers.dense'in yerini alabileceğini ve ayrıca daha fazla işlev ekleyebileceğini belirtmek istiyorum. Şunlara bakın: bu , bu ve bu .
Usame Salah

16

Bunu contrib.learnkitaplıkla yapmanın başka bir seçeneği , Tensorflow web sitesindeki Deep MNIST öğreticisine göre aşağıdaki gibidir . İlk olarak, ilgili kitaplıkları (gibi import tensorflow.contrib.layers as layers) içe aktardığınızı varsayarak , ayrı bir yöntemde bir ağ tanımlayabilirsiniz:

def easier_network(x, reg):
    """ A network based on tf.contrib.learn, with input `x`. """
    with tf.variable_scope('EasyNet'):
        out = layers.flatten(x)
        out = layers.fully_connected(out, 
                num_outputs=200,
                weights_initializer = layers.xavier_initializer(uniform=True),
                weights_regularizer = layers.l2_regularizer(scale=reg),
                activation_fn = tf.nn.tanh)
        out = layers.fully_connected(out, 
                num_outputs=200,
                weights_initializer = layers.xavier_initializer(uniform=True),
                weights_regularizer = layers.l2_regularizer(scale=reg),
                activation_fn = tf.nn.tanh)
        out = layers.fully_connected(out, 
                num_outputs=10, # Because there are ten digits!
                weights_initializer = layers.xavier_initializer(uniform=True),
                weights_regularizer = layers.l2_regularizer(scale=reg),
                activation_fn = None)
        return out 

Ardından, ana yöntemde aşağıdaki kod parçacığını kullanabilirsiniz:

def main(_):
    mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
    x = tf.placeholder(tf.float32, [None, 784])
    y_ = tf.placeholder(tf.float32, [None, 10])

    # Make a network with regularization
    y_conv = easier_network(x, FLAGS.regu)
    weights = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'EasyNet') 
    print("")
    for w in weights:
        shp = w.get_shape().as_list()
        print("- {} shape:{} size:{}".format(w.name, shp, np.prod(shp)))
    print("")
    reg_ws = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES, 'EasyNet')
    for w in reg_ws:
        shp = w.get_shape().as_list()
        print("- {} shape:{} size:{}".format(w.name, shp, np.prod(shp)))
    print("")

    # Make the loss function `loss_fn` with regularization.
    cross_entropy = tf.reduce_mean(
        tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
    loss_fn = cross_entropy + tf.reduce_sum(reg_ws)
    train_step = tf.train.AdamOptimizer(1e-4).minimize(loss_fn)

Bunun işe yaraması için, daha önce bağladığım MNIST öğreticisini izlemeniz ve ilgili kitaplıkları içe aktarmanız gerekir, ancak TensorFlow'u öğrenmek güzel bir alıştırmadır ve normalleştirmenin çıktıyı nasıl etkilediğini görmek kolaydır. Bağımsız değişken olarak bir normalleştirme uygularsanız, şunları görebilirsiniz:

- EasyNet/fully_connected/weights:0 shape:[784, 200] size:156800
- EasyNet/fully_connected/biases:0 shape:[200] size:200
- EasyNet/fully_connected_1/weights:0 shape:[200, 200] size:40000
- EasyNet/fully_connected_1/biases:0 shape:[200] size:200
- EasyNet/fully_connected_2/weights:0 shape:[200, 10] size:2000
- EasyNet/fully_connected_2/biases:0 shape:[10] size:10

- EasyNet/fully_connected/kernel/Regularizer/l2_regularizer:0 shape:[] size:1.0
- EasyNet/fully_connected_1/kernel/Regularizer/l2_regularizer:0 shape:[] size:1.0
- EasyNet/fully_connected_2/kernel/Regularizer/l2_regularizer:0 shape:[] size:1.0

Düzenli hale getirme bölümünün, mevcut öğelere bağlı olarak size üç öğe verdiğine dikkat edin.

0, 0,0001, 0,01 ve 1,0 düzenlemeleri ile, yüksek düzenlilik terimlerinin tehlikelerini gösteren sırasıyla 0,9468, 0,9476, 0,9183 ve 0,1135 test doğruluk değerleri elde ediyorum.


2
Gerçekten detaylı örnek.
stackoverflowuser2010

Düşürücü, açıklamak ister misin? :)
ComputerScientist

5

Hala arayan biri varsa, bunu tf.keras'a eklemek istiyorum, bunları katmanlarınızda argümanlar olarak geçirerek ağırlık düzenlenmesi ekleyebilirsiniz. Tensorflow Keras Tutorials sitesinden toptan alınan L2 regülasyonunu ekleme örneği:

model = keras.models.Sequential([
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation=tf.nn.relu),
    keras.layers.Dense(1, activation=tf.nn.sigmoid)
])

Bildiğim kadarıyla bu yöntemle regülasyon kayıplarını elle eklemeye gerek yok.

Referans: https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#add_weight_regularization


4

Grafikte bir tane ile test ettim tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)ve aynı değeri döndürdüklerini gördüm . Değerin miktarını gözlemleyerek, reg_constant'ın parametresini ayarlayarak değeri zaten anlamış olduğunu tahmin ediyorum .tf.losses.get_regularization_loss()l2_regularizertf.contrib.layers.l2_regularizer


3

CNN'niz varsa, aşağıdakileri yapabilirsiniz:

Model işlevinizde:

conv = tf.layers.conv2d(inputs=input_layer,
                        filters=32,
                        kernel_size=[3, 3],
                        kernel_initializer='xavier',
                        kernel_regularizer=tf.contrib.layers.l2_regularizer(1e-5),
                        padding="same",
                        activation=None) 
...

Kayıp fonksiyonunuzda:

onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=num_classes)
loss = tf.losses.softmax_cross_entropy(onehot_labels=onehot_labels, logits=logits)
regularization_losses = tf.losses.get_regularization_losses()
loss = tf.add_n([loss] + regularization_losses)

1

Bazı cevaplar kafamı karıştırıyor, burada bunu netleştirmek için iki yöntem veriyorum.

#1.adding all regs by hand
var1 = tf.get_variable(name='v1',shape=[1],dtype=tf.float32)
var2 = tf.Variable(name='v2',initial_value=1.0,dtype=tf.float32)
regularizer = tf.contrib.layers.l1_regularizer(0.1)
reg_term = tf.contrib.layers.apply_regularization(regularizer,[var1,var2])
#here reg_term is a scalar

#2.auto added and read,but using get_variable
with tf.variable_scope('x',
        regularizer=tf.contrib.layers.l2_regularizer(0.1)):
    var1 = tf.get_variable(name='v1',shape=[1],dtype=tf.float32)
    var2 = tf.get_variable(name='v2',shape=[1],dtype=tf.float32)
reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
#here reg_losses is a list,should be summed 

Daha sonra toplam zarara eklenebilir


1
cross_entropy = tf.losses.softmax_cross_entropy(
  logits=logits, onehot_labels=labels)

l2_loss = weight_decay * tf.add_n(
     [tf.nn.l2_loss(tf.cast(v, tf.float32)) for v in tf.trainable_variables()])

loss = cross_entropy + l2_loss

1
Sınırlı ve anında yardım sağlayabilecek bu kod parçacığı için teşekkür ederiz. Uygun bir açıklama, bunun neden soruna iyi bir çözüm olduğunu göstererek uzun vadeli değerini büyük ölçüde artıracak ve diğer benzer sorularla gelecekteki okuyucular için daha yararlı hale getirecektir. Yaptığınız varsayımlar da dahil olmak üzere bazı açıklamalar eklemek için lütfen yanıtınızı düzenleyin.
Maximilian Peters

1

tf.GraphKeys.REGULARIZATION_LOSSES otomatik olarak eklenmez, ancak bunları eklemenin basit bir yolu vardır:

reg_loss = tf.losses.get_regularization_loss()
total_loss = loss + reg_loss

tf.losses.get_regularization_loss()kullandığı tf.add_ngirişlerini toplamak tf.GraphKeys.REGULARIZATION_LOSSESeleman-bilge. tf.GraphKeys.REGULARIZATION_LOSSESdüzenleyici işlevleri kullanılarak hesaplanan, tipik olarak bir skaler listesi olacaktır. Belirtilen parametreye tf.get_variablesahip çağrılardan girişler alır regularizer. Bu koleksiyona manuel olarak da ekleyebilirsiniz. Bu, tf.Variableetkinlik düzenleyicileri veya diğer özel düzenleyicileri kullanırken ve ayrıca belirtirken yararlı olacaktır . Örneğin:

#This will add an activity regularizer on y to the regloss collection
regularizer = tf.contrib.layers.l2_regularizer(0.1)
y = tf.nn.sigmoid(x)
act_reg = regularizer(y)
tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, act_reg)

(Bu örnekte, y büyük x için gerçekten düzleştiğinden, x'i düzenli hale getirmek muhtemelen daha etkili olacaktır.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.