l8l技術メモ

機械学習・深層学習・組込みとかのメモ

TensorFlowで最適化(最小化)

値域つきの変数 0 < x1 < x2 < 1 からなる loss(x1,x2) を最小化したい。

lossが線形の時は線形計画法でよい。pythonのライブラリにpulpライブラリがあるらしい。非線形のとき、tensorflowなどで最適化できる。

 

変数の制約をつけたいとき

  • 値域をつけたい -> sigmoid(x)等で値を制限する
  • tf.Variable(val, constraint=lambda x: tf.clip(x, 0, 1)) みたいにclipする
  • 厳密な条件でない時 -> lossで値域をゆるやかに制限する。relu(x-超えたくない値)などをlossに足す。expなどを使うと微分もexpであることからgradientが突然大きくなってパラメタが発散したりする(一敗)

 以下が簡易コード

import tensorflow as tf

D = tf.constant(0.3) # min distance

low = tf.constant(0.0)
x1 = tf.Variable(0.3, trainable=True, name="x1")
x2 = tf.Variable(0.5, trainable=True, name="x2")
high = tf.constant(1.0)

eps = tf.constant(1e-2)
bnd_loss =    tf.nn.relu((low-x1)/eps) \
            + tf.nn.relu((x1-x2)/eps) \
            + tf.nn.relu((x2-high)/eps)
keep_loss = tf.math.pow( x1 - 0.3, 2 ) + tf.math.pow( x2 - 0.5, 2 )
diff_loss = tf.math.pow( ( x1 - x2 ) / D , -2 )

loss = bnd_loss + keep_loss + diff_loss
# opt = tf.train.GradientDescentOptimizer(0.001).minimize(loss)
opt = tf.train.AdamOptimizer().minimize(loss)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(4000):
        ret = sess.run([x1,x2,loss])
        if i % 100 == 0:
            print(i, ret)
        sess.run(opt)    

出力

0 [0.3, 0.5, 2.2500002]
100 [0.22975032, 0.5702493, 0.7861366]
200 [0.1915977, 0.6084021, 0.5415596]
300 [0.1637411, 0.63625854, 0.44022736]
(略)
3700 [0.04612662, 0.75386834, 0.308578]
3800 [0.046126585, 0.75386834, 0.30857804]
3900 [0.04612657, 0.75386834, 0.308578]

参考 https://m-alcu.github.io/blog/2018/01/16/tensorflow-minimize/