TensorFlowで正則化を追加するにはどうすればよいですか?


94

TensorFlowを使用して実装された多くの利用可能なニューラルネットワークコードで、正則化用語はしばしば損失値に手動で追加の用語を追加することによって実装されることがわかりました。

私の質問は:

  1. 手動で行うよりも洗練された、または推奨される正則化の方法はありますか?

  2. 私はそれにもget_variable議論があると思いますregularizer。それはどのように使用すべきですか?私の観察によると、レギュラライザーをそれに渡すと(など)tf.contrib.layers.l2_regularizer、正則化された項を表すテンソルが計算され、という名前のグラフコレクションに追加されtf.GraphKeys.REGULARIZATOIN_LOSSESます。そのコレクションはTensorFlowによって自動的に使用されますか(たとえば、トレーニング時にオプティマイザーによって使用されます)?またはそのコレクションを自分で使用する必要があると思いますか?


1
超明示的にするために、それを行う方法はありS = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer )ますか?
ピノキオ

@Pinocchioわかった?
Euler_Salter 2017年

2
@Euler_Salterすみません、もう覚えていません!テンソルフローを使用しなくなりました。
ピノキオ

回答:


70

2番目のポイントで言ったregularizerように、引数を使用することをお勧めします。で使用するか、get_variable一度設定しvariable_scopeてすべての変数を正規化することができます。

損失は​​グラフに収集され、このようなコスト関数に手動で追加する必要があります。

  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)

お役に立てば幸いです。


2
ありがとう。私はいないようだ、それらを手動で行うよりもTensorFlowはREG用語を扱ういくつかのよりインテリジェントな方法を持っているだろうと考えました:P
Lifu黄

14
ところで、私が間違っている場合は、2つの提案で修正してください。(1)、reg_constantTensorFlowのレギュラライザーはscaleコンストラクターに引数を持っているため、必要ないかもしれません。これにより、reg用語の影響をより詳細に制御できます。(2)を使用tf.add_nする方がよりも少し良いsumかもしれません。合計を使用すると、中間結果を格納するためにグラフに多くのテンソルが作成される可能性があります。
Lifu Huang 2016

1
わかりやすくするために、変数S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer )にレギュラライザーを配置した後、提案したコードを使用しますか?のようにsum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))
ピノキオ

1
重み変数を、tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)によって取得可能なコレクションの一部にする方法を示すことができますか?
Yu Shen

3
tf.reduce_sum代わりに使用する必要があるようsumです?
ComputerScientist

45

既存の回答のいくつかの側面はすぐにはわかりませんでした。そのため、ステップバイステップガイドは次のとおりです。

  1. 正則化器を定義します。これは、正則化定数を設定できる場所です。例:

    regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
  2. 変数を作成するには:

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

    同様に、通常のweights = tf.Variable(...)コンストラクタとそれに続くを介して変数を作成できますtf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights)

  3. いくつかのloss用語を定義し、正則化用語を追加します。

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

    注:tf.contrib.layers.apply_regularizationはとして実装されているように見えるAddNため、多かれ少なかれと同等sum(reg_variables)です。


10
正規化処理を2回適用していると思います。ステップとステップ3の両方でapply_regularization、変数の作成時に既に正規化処理を指定している場合は必要ありません。
インタージェイ2017

2
@interjayは例を挙げてください、これらの答えはすべて非常に不明確です!これは、上記の回答に問題があるとコメントを書いている人が常に少なくとも1人はいるためです。
Euler_Salter 2017年

1
@interjay前回これをテストしたとき、両方を実行する必要があったと確信しています。これが変わったかどうかはわかりません。
bluenote10 2017年

1
いいえ、その場合は同じ正規化子を2つの関数に渡す必要がないため、意味がありません。ドキュメンテーション(および名前)はREGULARIZATION_LOSSES、それがレギュラライザーから返される損失の合計であることを明確にしているため、基本的にを呼び出していregularizer(regularizer(weight))ます。
interjay 2017年

1
ここでの混乱は、「同等」の部分に起因すると思います。彼は2つの異なる方法を説明し、あなたは1つを選びます。これは、正則化を2回適用することを含む1つの方法ではありません。
gcp '31年

28

答えが見つからなかったので、簡単な正解を提供します。あなたは2つの簡単なステップを必要とします、残りはテンソルフローマジックによって行われます:

  1. 変数またはレイヤーを作成するときにレギュラライザーを追加します。

    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. 損失を定義するときに正則化項を追加します。

    loss = ordinary_loss + tf.losses.get_regularization_loss()

regularizer = tf.contrib.layers.l2_regularizer(0.001)でレギュラライザーオペレーションを作成している場合、それを複数のレイヤーの開始に渡すことができますか?または、regularizer1 = tf.contrib.layers.l2_regularizer(0.001)、regularizer2 = ................. regularizer3 = .... .. 等々?
MiloMinderbinder 2018

@Nitin同じ正規化子を使用できます。引数として重みに損失を適用するのは、単なるpython関数です。
alyaxey

1
これは最もエレガントなソリューションのように見えますが、これは本当に機能しますか?これは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
私はtf.contrib.layers.fully_connectedがtf.layers.denseを置き換え、さらに機能を追加できることを述べたいだけです。これらを参照してください:このこの、およびこれ
オサマサラ

16

contrib.learnライブラリでこれを行う別のオプションは、TensorflowウェブサイトのDeep MNISTチュートリアルに基づく次のとおりです。最初に、関連するライブラリ(などimport tensorflow.contrib.layers as layers)をインポートしたと想定して、別の方法でネットワークを定義できます。

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 

次に、メインメソッドで、次のコードスニペットを使用できます。

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)

これを機能させるには、前にリンクしたMNISTチュートリアルに従って関連ライブラリをインポートする必要がありますが、TensorFlowを学ぶのはいい練習であり、正規化が出力にどのように影響するかを簡単に確認できます。引数として正則化を適用すると、次のようになります。

- 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

正規化の部分では、利用可能なアイテムに基づいて3つのアイテムが表示されることに注意してください。

正規化が0、0.0001、0.01、および1.0の場合、それぞれ0.9468、0.9476、0.9183、および0.1135のテスト精度値が得られ、高い正規化項の危険性が示されます。


2
本当に詳細な例。
stackoverflowuser2010 2017年

5

誰かがまだ探している場合は、tf.kerasに追加して、レイヤーの引数としてそれらを渡すことで、重みの正規化を追加できます。Tensorflow Kerasチュートリアルサイトから卸売りされたL2正則化を追加する例:

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

私が知る限り、この方法を使用して正則化損失を手動で追加する必要はありません。

リファレンス:https : //www.tensorflow.org/tutorials/keras/overfit_and_underfit#add_weight_regularization


4

私がテストしたtf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)tf.losses.get_regularization_loss()1とl2_regularizerグラフに、彼らは同じ値を返すことがわかりました。値の量を観察することで、のパラメーターを設定することにより、reg_constantはすでに値を理解していると思いますtf.contrib.layers.l2_regularizer


3

CNNを使用している場合は、次の操作を実行できます。

モデル関数で:

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

あなたの損失関数では:

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

いくつかの答えは私をより混乱させます。ここでは、それを明確にするために2つの方法を示します。

#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 

次に、それを合計損失に追加できます


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
このコードスニペットをありがとうございます。このコードスニペットは、限られた、即時のヘルプを提供する場合があります。適切な説明は、なぜこれが問題の優れた解決策であるかを示すことにより、長期的な価値を大幅に改善し、他の同様の質問を持つ将来の読者にとってより有用になるでしょう。回答を編集して、仮定を含めて説明を追加してください。
Maximilian Peters

1

tf.GraphKeys.REGULARIZATION_LOSSES は自動的には追加されませんが、簡単に追加できます。

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

tf.losses.get_regularization_loss()を使用tf.add_nして、tf.GraphKeys.REGULARIZATION_LOSSES要素ごとのエントリを合計します。tf.GraphKeys.REGULARIZATION_LOSSES通常、正則化関数を使用して計算されたスカラーのリストになります。パラメータが指定されtf.get_variableているへの呼び出しからエントリを取得しますregularizer。そのコレクションに手動で追加することもできます。これは、tf.Variableアクティビティレギュラライザーや他のカスタムレギュラライザーを使用する場合や指定する場合にも役立ちます。例えば:

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

(この例では、xを正則化すると、yが本当に大きなxに対して平坦になるため、おそらくより効果的です。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.