Bagaimana cara menambahkan regularisasi di TensorFlow?

94

Saya menemukan di banyak kode jaringan neural yang tersedia yang diimplementasikan menggunakan TensorFlow bahwa istilah regularisasi sering diterapkan dengan menambahkan istilah tambahan ke nilai kerugian secara manual.

Pertanyaan saya adalah:

  1. Apakah ada cara regularisasi yang lebih elegan atau disarankan daripada melakukannya secara manual?

  2. Saya juga menemukan bahwa get_variableada argumen regularizer. Bagaimana cara menggunakannya? Menurut pengamatan saya, jika kita meneruskan pengatur ke dalamnya (seperti tf.contrib.layers.l2_regularizer, tensor yang mewakili istilah yang diatur akan dihitung dan ditambahkan ke kumpulan grafik bernama tf.GraphKeys.REGULARIZATOIN_LOSSES. Apakah koleksi tersebut akan digunakan secara otomatis oleh TensorFlow (misalnya, digunakan oleh pengoptimal saat pelatihan)? Atau apakah saya diharapkan menggunakan koleksi itu sendiri?

Lifu Huang
sumber
1
hanya untuk menjadi sangat eksplisit, apakah cara melakukannya S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer )?
Pinokio
@ Pinokio sudahkah kamu mengetahuinya?
Euler_Salter
2
@Euler_Salter Saya tidak ingat lagi, maaf! Tidak menggunakan aliran tensor lagi!
Pinokio

Jawaban:

70

Seperti yang Anda katakan di poin kedua, menggunakan regularizerargumen adalah cara yang disarankan. Anda dapat menggunakannya di get_variable, atau mengaturnya sekali divariable_scope dan mengatur semua variabel Anda.

Kerugian dikumpulkan dalam grafik, dan Anda perlu menambahkannya secara manual ke fungsi biaya seperti ini.

  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)

Semoga membantu!

Lukasz Kaiser
sumber
2
Terima kasih sobat. Saya berpikir TensorFlow akan memiliki beberapa cara yang lebih cerdas dalam menangani istilah reg daripada melakukannya secara manual, tampaknya tidak: P
Lifu Huang
14
BTW, dua saran, koreksi saya jika saya salah. (1), saya kira reg_constantmungkin tidak diperlukan, karena regulator di TensorFlow memiliki argumen scaledalam konstruktornya sehingga dampak istilah reg dapat dikontrol dengan cara yang lebih terperinci. Dan (2) menggunakan tf.add_nmungkin sedikit lebih baik daripada sum, saya kira menggunakan jumlah mungkin membuat banyak tensor dalam grafik untuk menyimpan hasil antara.
Lifu Huang
1
jadi hanya untuk membuatnya sangat jelas, setelah saya meletakkan pengatur ke variabel S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer ), lalu apakah saya kode yang Anda sarankan? Seperti di sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))?
Pinocchio
1
Bisakah menunjukkan bagaimana membuat variabel bobot menjadi bagian dari koleksi yang dapat diambil oleh tf.get_collection (tf.GraphKeys.REGULARIZATION_LOSSES)?
Yu Shen
3
Sepertinya tf.reduce_sumharus digunakan, bukan sum?
ComputerScientist
45

Beberapa aspek dari jawaban yang ada tidak segera jelas bagi saya, jadi berikut adalah panduan langkah demi langkah:

  1. Tentukan regulator. Di sinilah konstanta regularisasi dapat disetel, misalnya:

    regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
  2. Buat variabel melalui:

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

    Dengan kata lain, variabel dapat dibuat melalui weights = tf.Variable(...)konstruktor reguler , diikuti oleh tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights).

  3. Definisikan beberapa lossistilah dan tambahkan istilah regularisasi:

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

    Catatan: Sepertinya tf.contrib.layers.apply_regularizationdiimplementasikan sebagai AddN, jadi kurang lebih sama dengan sum(reg_variables).

bluenote10
sumber
10
Saya pikir Anda menerapkan pengatur dua kali - baik di langkah dan langkah 3. apply_regularizationseharusnya tidak diperlukan jika Anda sudah menentukan pengatur saat membuat variabel.
interjay
2
@interjay tolong buat contoh, semua jawaban ini sangat tidak jelas! Ini karena selalu ada setidaknya satu orang yang menulis komentar di bawahnya yang mengatakan bahwa jawaban di atas ada yang salah.
Euler_Salter
1
@ Interjay Saya cukup yakin bahwa melakukan keduanya perlu dilakukan terakhir kali saya menguji ini. Saya tidak yakin apakah ini telah berubah.
bluenote10
1
Tidak, itu tidak masuk akal karena Anda tidak perlu meneruskan pengatur yang sama ke dua fungsi. Dokumentasi (dan namanya) memperjelas bahwa REGULARIZATION_LOSSESkerugian total yang dikembalikan dari regulator, jadi pada dasarnya Anda menelepon regularizer(regularizer(weight)).
interjay
1
Saya pikir kebingungan di sini berasal dari bagian "ekuivalen". Dia menjelaskan dua metode berbeda dan Anda memilih satu, itu bukan satu metode yang melibatkan penerapan regularisasi dua kali.
gcp
28

Saya akan memberikan jawaban yang benar sederhana karena saya tidak menemukannya. Anda membutuhkan dua langkah sederhana, sisanya dilakukan dengan sihir tensorflow:

  1. Tambahkan regulator saat membuat variabel atau lapisan:

    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. Tambahkan istilah regularisasi saat menentukan kerugian:

    loss = ordinary_loss + tf.losses.get_regularization_loss()
alyaxey
sumber
Jika saya membuat operasi regularizer dengan regularizer = tf.contrib.layers.l2_regularizer (0,001), dapatkah saya meneruskannya ke inisiasi beberapa lapisan? atau apakah saya perlu membuat pengatur terpisah untuk setiap lapisan likeregularizer1 = tf.contrib.layers.l2_regularizer (0.001), regularizer2 = ................. regularizer3 = .... .. dan seterusnya?
MiloMinderbinder
@ Nitin Anda dapat menggunakan pengatur yang sama. Ini hanya fungsi python yang menerapkan kerugian pada bobot sebagai argumennya.
alyaxey
1
Ini terlihat seperti solusi yang paling elegan tetapi apakah ini benar-benar berfungsi? Apa bedanya dengan say reg_variables = tf.get_collection (tf.GraphKeys.REGULARIZATION_LOSSES) reg_term = tf.contrib.layers.apply_regularization (regularizer, reg_variables) loss + = reg_term
GeorgeOfTheRF
1
Saya hanya ingin menyebutkan bahwa tf.contrib.layers.fully_connected dapat menggantikan tf.layers.dense dan, selanjutnya, menambahkan lebih banyak fungsi. Lihat ini: ini , ini , dan ini .
Osama Salah
16

Opsi lain untuk melakukan ini dengan contrib.learnpustaka adalah sebagai berikut, berdasarkan tutorial Deep MNIST di situs web Tensorflow. Pertama, dengan asumsi Anda telah mengimpor pustaka yang relevan (seperti import tensorflow.contrib.layers as layers), Anda dapat menentukan jaringan dalam metode terpisah:

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 

Kemudian, dalam metode utama, Anda dapat menggunakan cuplikan kode berikut:

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)

Agar ini berfungsi, Anda harus mengikuti tutorial MNIST yang saya tautkan sebelumnya dan mengimpor library yang relevan, tetapi mempelajari TensorFlow adalah latihan yang bagus dan mudah untuk melihat bagaimana regularisasi memengaruhi output. Jika Anda menerapkan regularisasi sebagai argumen, Anda dapat melihat yang berikut ini:

- 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

Perhatikan bahwa bagian regularisasi memberi Anda tiga item, berdasarkan item yang tersedia.

Dengan regularisasi 0, 0,0001, 0,01, dan 1,0, saya mendapatkan nilai akurasi uji masing-masing 0,9468, 0,9476, 0,9183, dan 0,1135, yang menunjukkan bahaya istilah regularisasi tinggi.

Ilmuwan komputer
sumber
2
Contoh yang sangat detail.
stackoverflowuser2010
5

Jika ada yang masih melihat, saya hanya ingin menambahkannya di tf.keras Anda dapat menambahkan regularisasi bobot dengan meneruskannya sebagai argumen di lapisan Anda. Contoh menambahkan regularisasi L2 yang diambil secara grosir dari situs Tutorial Tensorflow Keras:

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)
])

Tidak perlu menambahkan secara manual kerugian regularisasi dengan metode ini sejauh yang saya tahu.

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

MoltenMuffins
sumber
4

Saya menguji tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)dan tf.losses.get_regularization_loss()dengan satu l2_regularizerdi grafik, dan menemukan bahwa mereka mengembalikan nilai yang sama. Dengan mengamati kuantitas nilai, saya kira reg_constant sudah memahami nilainya dengan menetapkan parameter tf.contrib.layers.l2_regularizer.

lautan
sumber
3

Jika Anda memiliki CNN, Anda dapat melakukan hal berikut:

Dalam fungsi model Anda:

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) 
...

Dalam fungsi kerugian Anda:

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)
tsveti_iko
sumber
1

Beberapa jawaban membuat saya semakin bingung. Disini saya berikan dua cara untuk membuatnya dengan jelas.

#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 

Kemudian, dapat ditambahkan ke dalam kerugian total

pengguna3201329
sumber
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
Alex-zhai
sumber
1
Terima kasih atas cuplikan kode ini, yang mungkin memberikan bantuan terbatas dan langsung. Penjelasan yang tepat akan sangat meningkatkan nilai jangka panjangnya dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah tersebut dan akan membuatnya lebih berguna bagi pembaca di masa mendatang dengan pertanyaan serupa lainnya. Harap edit jawaban Anda untuk menambahkan penjelasan, termasuk asumsi yang Anda buat.
Maximilian Peters
1

tf.GraphKeys.REGULARIZATION_LOSSES tidak akan ditambahkan secara otomatis, tetapi ada cara sederhana untuk menambahkannya:

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

tf.losses.get_regularization_loss()digunakan tf.add_nuntuk menjumlahkan entri dari tf.GraphKeys.REGULARIZATION_LOSSESelemen-bijaksana. tf.GraphKeys.REGULARIZATION_LOSSESbiasanya berupa daftar skalar, dihitung menggunakan fungsi pengatur. Ia mendapat entri dari panggilan ke tf.get_variableyang memiliki regularizerparameter yang ditentukan. Anda juga dapat menambahkan ke koleksi itu secara manual. Itu akan berguna saat menggunakan tf.Variabledan juga saat menentukan pengatur aktivitas atau pengatur kustom lainnya. Misalnya:

#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)

(Dalam contoh ini mungkin akan lebih efektif untuk mengatur x, karena y benar-benar mendatar untuk x besar.)

Elias Hasle
sumber