Làm cách nào để thêm các quy định trong TensorFlow?


94

Tôi nhận thấy trong nhiều mã mạng nơ-ron có sẵn được triển khai bằng TensorFlow rằng các điều khoản quy định thường được triển khai bằng cách thêm một thuật ngữ bổ sung vào giá trị mất mát theo cách thủ công.

Câu hỏi của tôi là:

  1. Có cách nào thanh lịch hơn hoặc được khuyến nghị để quy định hơn là làm theo cách thủ công không?

  2. Tôi cũng thấy rằng get_variablecó một lập luận regularizer. Nó nên được sử dụng như thế nào? Theo quan sát của tôi, nếu chúng ta chuyển một bộ điều chỉnh cho nó (chẳng hạn như tf.contrib.layers.l2_regularizertensor đại diện cho thuật ngữ chính quy sẽ được tính toán và thêm vào một bộ sưu tập đồ thị có tên tf.GraphKeys.REGULARIZATOIN_LOSSES. Liệu bộ sưu tập đó có được tự động sử dụng bởi TensorFlow (ví dụ: được sử dụng bởi trình tối ưu hóa khi đào tạo) không? Hoặc Tôi có nên sử dụng bộ sưu tập đó một mình không?


1
chỉ để được siêu rõ ràng, là cách để làm điều đó S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer )?
Pinocchio

@Pinocchio bạn đã tìm ra chưa?
Euler_Salter

2
@Euler_Salter Tôi không nhớ nữa, xin lỗi! Không sử dụng dòng tensor nữa!
Pinocchio

Câu trả lời:


70

Như bạn nói ở điểm thứ hai, sử dụng regularizerlập luận là cách được khuyến khích. Bạn có thể sử dụng nó trong get_variablehoặc đặt nó một lần trong của bạn variable_scopevà có tất cả các biến của bạn được chính thức hóa.

Các khoản lỗ được thu thập trong biểu đồ và bạn cần phải thêm chúng theo cách thủ công vào hàm chi phí của mình như thế này.

  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)

Hy vọng rằng sẽ giúp!


2
Cảm ơn anh bạn. Tôi đã nghĩ rằng TensorFlow sẽ có một số cách xử lý điều khoản đăng ký thông minh hơn là làm chúng theo cách thủ công, có vẻ như không: P
Lifu Huang

14
BTW, hai gợi ý, hãy sửa cho tôi nếu tôi sai. (1), tôi đoán reg_constantcó thể không cần thiết, vì các nhà điều chỉnh trong TensorFlow có một đối số scaletrong các hàm tạo của họ để tác động của các điều khoản đăng ký có thể được kiểm soát theo cách chi tiết hơn. Và (2) sử dụng tf.add_ncó thể tốt hơn một chút so với sum, tôi đoán sử dụng sum có thể tạo ra nhiều tenxơ trong biểu đồ để lưu trữ kết quả trung gian.
Lifu Huang,

1
vì vậy chỉ để làm cho nó siêu rõ ràng, sau khi tôi đặt bộ điều chỉnh vào biến S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer ), sau đó tôi có mã mà bạn đề xuất không? Như trong sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))?
Pinocchio

1
Có thể chỉ ra cách làm cho các biến trọng số trở thành một phần của tập hợp có thể truy xuất bằng tf.get_collection (tf.GraphKeys.REGULARIZATION_LOSSES) không?
Yu Shen

3
Nó có vẻ như tf.reduce_sumnên được sử dụng thay vì sum?
ComputerScientist

45

Một số khía cạnh của câu trả lời hiện tại không rõ ràng ngay lập tức đối với tôi, vì vậy đây là hướng dẫn từng bước:

  1. Xác định một bộ điều chỉnh. Đây là nơi mà hằng số chính quy có thể được đặt, ví dụ:

    regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
  2. Tạo biến thông qua:

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

    Tương tự, các biến có thể được tạo thông qua hàm tạo thông thường weights = tf.Variable(...), theo sau là tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights).

  3. Xác định một số lossthuật ngữ và thêm thuật ngữ chính quy:

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

    Lưu ý: Có vẻ như tf.contrib.layers.apply_regularizationđược triển khai dưới dạng một AddN, vì vậy ít nhiều tương đương với sum(reg_variables).


10
Tôi nghĩ rằng bạn đang áp dụng bộ điều chỉnh hai lần - cả trong bước và bước 3. apply_regularizationKhông cần thiết nếu bạn đã chỉ định bộ điều chỉnh khi tạo biến.
tục

2
@interjay xin làm một ví dụ, tất cả những câu trả lời này là siêu không rõ ràng! Điều này là do luôn có ít nhất một người viết bình luận bên dưới nói rằng câu trả lời trên có gì đó sai.
Euler_Salter

1
@interjay Tôi khá chắc rằng việc thực hiện cả hai là cần thiết vào lần cuối cùng tôi thử nghiệm điều này. Tôi không chắc liệu điều này có thay đổi hay không.
bluenote10

1
Không, điều đó không có ý nghĩa gì vì khi đó bạn sẽ không cần phải chuyển cùng một bộ điều chỉnh cho hai hàm. Tài liệu (và tên) nói rõ rằng đó REGULARIZATION_LOSSESlà tổng số lỗ được trả lại từ các cơ quan quản lý, vì vậy về cơ bản bạn đang gọi regularizer(regularizer(weight)).
tục

1
Tôi nghĩ rằng sự nhầm lẫn ở đây bắt nguồn từ phần "tương đương". Anh ấy mô tả hai phương pháp khác nhau và bạn chọn một phương pháp, đó không phải là một phương pháp liên quan đến việc áp dụng chính quy hóa hai lần.
gcp,

28

Tôi sẽ cung cấp một câu trả lời chính xác đơn giản vì tôi không tìm thấy câu trả lời nào. Bạn cần hai bước đơn giản, phần còn lại được thực hiện bằng phép thuật tensorflow:

  1. Thêm bộ điều chỉnh khi tạo biến hoặc lớp:

    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. Thêm thuật ngữ quy định khi xác định tổn thất:

    loss = ordinary_loss + tf.losses.get_regularization_loss()

Nếu tôi đang tạo op điều chỉnh bằng điều chỉnh = tf.contrib.layers.l2_regularizer (0,001), tôi có thể chuyển nó cho nhiều lần khởi tạo lớp không? hay tôi có cần tạo một bộ điều chỉnh riêng biệt cho mỗi lớp nhưregularizer1 = tf.contrib.layers.l2_regularizer (0,001), điều chỉnh2 = ................. điều chỉnh 3 = .... .. và như thế?
MiloMinderbinder

@Nitin Bạn có thể sử dụng cùng một bộ điều chỉnh. Nó chỉ là một hàm python áp dụng giảm trọng lượng như đối số của nó.
alyaxey

1
Đây có vẻ như là giải pháp thanh lịch nhất nhưng điều này có thực sự hiệu quả không? Làm thế nào là khác nhau này từ reg_variables nói = tf.get_collection (tf.GraphKeys.REGULARIZATION_LOSSES) reg_term = tf.contrib.layers.apply_regularization (regularizer, reg_variables) mất + = reg_term
GeorgeOfTheRF

1
Tôi chỉ muốn đề cập rằng tf.contrib.layers.ly_connected có thể thay thế tf.layers.dense và hơn nữa, thêm nhiều chức năng hơn. Tham khảo những cái này: cái này , cái này , và cái này .
Osama Salah,

16

Một tùy chọn khác để thực hiện việc này với contrib.learnthư viện như sau, dựa trên hướng dẫn Deep MNIST trên trang web Tensorflow. Đầu tiên, giả sử bạn đã nhập các thư viện có liên quan (chẳng hạn như import tensorflow.contrib.layers as layers), bạn có thể xác định mạng theo một phương pháp riêng:

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 

Sau đó, trong một phương pháp chính, bạn có thể sử dụng đoạn mã sau:

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)

Để làm được điều này, bạn cần làm theo hướng dẫn MNIST mà tôi đã liên kết trước đó và nhập các thư viện liên quan, nhưng đó là một bài tập hay để học TensorFlow và thật dễ dàng để xem việc chính quy ảnh hưởng đến đầu ra như thế nào. Nếu bạn áp dụng quy định làm đối số, bạn có thể thấy những điều sau:

- 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

Lưu ý rằng phần quy định cung cấp cho bạn ba mục, dựa trên các mục có sẵn.

Với các mức quy định 0, 0,0001, 0,01 và 1,0, tôi nhận được các giá trị độ chính xác thử nghiệm tương ứng là 0,9468, 0,9476, 0,9183 và 0,1135, cho thấy sự nguy hiểm của các điều khoản chính quy cao.


2
Ví dụ thực sự chi tiết.
stackoverflowuser2010

5

Nếu ai đó vẫn đang tìm kiếm, tôi chỉ muốn thêm vào điều đó trong tf.keras, bạn có thể thêm quy định trọng số bằng cách chuyển chúng dưới dạng đối số trong các lớp của bạn. Một ví dụ về việc thêm quy định L2 được lấy sỉ từ trang 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)
])

Theo như tôi biết, tôi không cần phải thêm các khoản lỗ quy định theo cách thủ công bằng phương pháp này.

Tham khảo: https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#add_weight_regulption


4

Tôi đã thử nghiệm tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)tf.losses.get_regularization_loss()với một l2_regularizertrong biểu đồ, và thấy rằng chúng trả về cùng một giá trị. Bằng cách quan sát số lượng của giá trị, tôi đoán reg_constant đã có ý nghĩa về giá trị bằng cách đặt tham số của tf.contrib.layers.l2_regularizer.


3

Nếu bạn có CNN, bạn có thể làm như sau:

Trong chức năng mô hình của bạn:

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

Trong hàm mất mát của bạn:

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

Một số câu trả lời làm cho tôi bối rối hơn. Ở đây tôi đưa ra hai phương pháp để làm cho nó rõ ràng.

#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 

Sau đó, nó có thể được cộng vào tổng tổn thất


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
Cảm ơn bạn về đoạn mã này, đoạn mã này có thể cung cấp một số trợ giúp hạn chế, tức thì. Một lời giải thích phù hợp sẽ cải thiện đáng kể giá trị lâu dài của nó bằng cách chỉ ra lý do tại sao đây là một giải pháp tốt cho vấn đề và sẽ hữu ích hơn cho những người đọc trong tương lai với những câu hỏi tương tự khác. Vui lòng chỉnh sửa câu trả lời của bạn để thêm một số giải thích, bao gồm cả những giả định bạn đã đưa ra.
Maximilian Peters

1

tf.GraphKeys.REGULARIZATION_LOSSES sẽ không được thêm tự động, nhưng có một cách đơn giản để thêm chúng:

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

tf.losses.get_regularization_loss()sử dụng tf.add_nđể tính tổng các mục của tf.GraphKeys.REGULARIZATION_LOSSESphần tử khôn ngoan. tf.GraphKeys.REGULARIZATION_LOSSESthường sẽ là một danh sách các đại lượng vô hướng, được tính toán bằng cách sử dụng các hàm điều chỉnh. Nó nhận các mục nhập từ các cuộc gọi đến tf.get_variableregularizertham số được chỉ định. Bạn cũng có thể thêm vào bộ sưu tập đó theo cách thủ công. Điều đó sẽ hữu ích khi sử dụng tf.Variablevà cả khi chỉ định bộ điều chỉnh hoạt động hoặc bộ điều chỉnh tùy chỉnh khác. Ví dụ:

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

(Trong ví dụ này, có lẽ sẽ hiệu quả hơn nếu điều chỉnh x, vì y thực sự làm phẳng cho x lớn.)

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.