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/