W wielu dostępnych kodach sieci neuronowych zaimplementowanych przy użyciu TensorFlow zauważyłem, że warunki regularyzacyjne są często implementowane przez ręczne dodanie dodatkowego terminu do wartości straty.
Moje pytania to:
Czy istnieje bardziej elegancki lub zalecany sposób regularyzacji niż robienie tego ręcznie?
Uważam też, że
get_variable
ma to argumentregularizer
. Jak należy tego używać? Zgodnie z moimi obserwacjami, jeśli przekażemy do niego regulator (np.tf.contrib.layers.l2_regularizer
Tensor reprezentujący człon regularyzowany zostanie obliczony i dodany do zbioru wykresów o nazwietf.GraphKeys.REGULARIZATOIN_LOSSES
. Czy ta kolekcja będzie automatycznie używana przez TensorFlow (np. Używana przez optymalizatory podczas uczenia)? czy oczekuje się, że sam powinienem korzystać z tej kolekcji?
źródło
S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer )
?Odpowiedzi:
Jak powiesz w drugim punkcie, użycie
regularizer
argumentu jest zalecanym sposobem. Możesz go użyćget_variable
lub ustawić raz w swoimvariable_scope
i uregulować wszystkie zmienne.Straty są gromadzone na wykresie i musisz ręcznie dodać je do funkcji kosztu w ten sposób.
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)
Mam nadzieję, że to pomoże!
źródło
reg_constant
wydaje mi się, że może nie być konieczne, ponieważ regulatory w TensorFlow mają argumentscale
w swoich konstruktorach, dzięki czemu wpływ warunków reg można kontrolować w bardziej precyzyjny sposób. I (2) użycietf.add_n
może być nieco lepsze niżsum
, myślę, że użycie sumy może stworzyć wiele tensorów na wykresie do przechowywania pośrednich wyników.S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer )
mam kod, który zasugerowałeś? Jak wsum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))
?tf.reduce_sum
należy użyć zamiastsum
?Kilka aspektów istniejącej odpowiedzi nie było dla mnie od razu jasnych, więc oto przewodnik krok po kroku:
Zdefiniuj regularyzator. Tutaj można ustawić stałą regularyzacji, np .:
regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
Utwórz zmienne poprzez:
weights = tf.get_variable( name="weights", regularizer=regularizer, ... )
Równoważnie zmienne można tworzyć za pomocą zwykłego
weights = tf.Variable(...)
konstruktora, po którym następujetf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights)
.Zdefiniuj jakiś
loss
termin i dodaj termin regularyzacji:Uwaga: wygląda na to, że
tf.contrib.layers.apply_regularization
jest zaimplementowany jakoAddN
, więc mniej więcej równoważny zsum(reg_variables)
.źródło
apply_regularization
nie powinno być konieczne, jeśli już określiłeś regulatora podczas tworzenia zmiennej.REGULARIZATION_LOSSES
jest to całkowita strata zwrócona przez regulatory, więc zasadniczo dzwoniszregularizer(regularizer(weight))
.Dam prostą, poprawną odpowiedź, ponieważ jej nie znalazłem. Potrzebujesz dwóch prostych kroków, resztę zajmuje magia tensorflow:
Dodaj regulatory podczas tworzenia zmiennych lub warstw:
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))
Dodaj termin regularyzacji podczas definiowania straty:
źródło
Inna opcja zrobienia tego z
contrib.learn
biblioteką jest następująca, oparta na samouczku Deep MNIST na stronie internetowej Tensorflow. Po pierwsze, zakładając, że zaimportowałeś odpowiednie biblioteki (takie jakimport tensorflow.contrib.layers as layers
), możesz zdefiniować sieć w oddzielnej metodzie: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
Następnie w głównej metodzie możesz użyć następującego fragmentu kodu:
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)
Aby to zadziałało, musisz postępować zgodnie z samouczkiem MNIST, z którym łączyłem się wcześniej i zaimportować odpowiednie biblioteki, ale nauczenie się TensorFlow jest przyjemnym ćwiczeniem i łatwo jest zobaczyć, jak regularyzacja wpływa na wynik. Jeśli zastosujesz regularyzację jako argument, zobaczysz:
- 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
Zwróć uwagę, że część regularyzacji zawiera trzy elementy w oparciu o dostępne elementy.
Przy regularyzacjach 0, 0,0001, 0,01 i 1,0, otrzymuję wartości dokładności testu wynoszące odpowiednio 0,9468, 0,9476, 0,9183 i 0,1135, pokazujące niebezpieczeństwa związane z wysokimi składnikami regularyzacyjnymi.
źródło
Jeśli ktoś nadal szuka, chciałbym tylko dodać, że w tf.keras możesz dodać regulację wagi, przekazując je jako argumenty w swoich warstwach. Przykład dodania regularyzacji L2 pobranej hurtowo z witryny Tensorflow Keras Tutorials:
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) ])
O ile wiem, nie ma potrzeby ręcznego dodawania strat regularyzacyjnych tą metodą.
Źródła: https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#add_weight_regularization
źródło
Przetestowałem
tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
iztf.losses.get_regularization_loss()
jednyml2_regularizer
na wykresie i stwierdziłem, że zwracają tę samą wartość. Obserwując ilość wartości, domyślam się, że reg_constant ma już sens dla wartości, ustawiając parametrtf.contrib.layers.l2_regularizer
.źródło
Jeśli masz CNN, możesz wykonać następujące czynności:
W swojej funkcji modelu:
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) ...
W Twojej funkcji utraty:
źródło
Niektóre odpowiedzi wprawiają mnie w zakłopotanie, tutaj podaję dwie metody, aby to jasno wyrazić.
#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
Następnie można go dodać do całkowitej straty
źródło
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
źródło
tf.GraphKeys.REGULARIZATION_LOSSES
nie zostaną dodane automatycznie, ale istnieje prosty sposób na ich dodanie:tf.losses.get_regularization_loss()
używatf.add_n
do sumowania wpisówtf.GraphKeys.REGULARIZATION_LOSSES
elementarnych.tf.GraphKeys.REGULARIZATION_LOSSES
będzie zazwyczaj listą skalarów obliczoną za pomocą funkcji regulatora. Pobiera wpisy z wywołań,tf.get_variable
które mająregularizer
określony parametr. Możesz również dodać do tej kolekcji ręcznie. Byłoby to przydatne podczas używania,tf.Variable
a także podczas określania regulatorów aktywności lub innych niestandardowych regulatorów. Na przykład:#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)
(W tym przykładzie prawdopodobnie bardziej efektywne byłoby uregulowanie x, ponieważ y naprawdę spłaszcza się dla dużego x).
źródło