dynamic_rnn を使ってみる

dynamic_rnn は前回のinference相当の事をやってくれるらしいです。

In [47]: def inference(x, max_len):
    ...:     state = initial_state
    ...:     for i in range(max_len):
    ...:         (output, state) = rnn_cell(x[i], state)
    ...:     return tf.squeeze(output)

あと、前回reluを使いましたが変数の値がマイナスになった途端にoutputが0になっちゃうのでleaky reluとかを使ったほうが良さそうでした。

その辺を踏まえて、前回の足し合わせをdynamic_rnnを使って書き直してみました。

import random
import tensorflow as tf
sess = tf.Session()

size = 1
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=size, activation=tf.nn.leaky_relu)

n_batch = 1
max_len = 3

x = tf.placeholder(tf.float32, shape=[n_batch, max_len, size])

output, state = tf.nn.dynamic_rnn(rnn_cell, x, dtype=tf.float32)

y = tf.placeholder(tf.float32, shape=[])

loss = tf.reduce_mean(tf.square(y - output[-1, -1, -1]))

optimizer = tf.train.GradientDescentOptimizer(0.0001)
train_step = optimizer.minimize(loss)

init = tf.global_variables_initializer()
sess.run(init)
losses = []
for i in range(3000):
    xs = [random.random() * 10 for j in range(max_len)]
    yy = sum(xs)
    # TODO batch_size, max_timeに対応する
    xs = [ [ [xx] for xx in xs] ] # shape 1, 3, 1
    sess.run(train_step, feed_dict={x: xs, y: yy})
    if i % 100 == 0:
        losses.append(sess.run(loss, feed_dict={x: xs, y: yy}))

print('vars : ', sess.run(rnn_cell.variables[0])) # RNNのウェイトを表示してみる
print('losses : ', losses)

動かしてみた結果がこちらです

vars :  [[ 0.94803673]
 [ 1.00511789]]
losses :  [189.65527, 120.48457, 402.87241, 0.10081632, 0.23049662, 0.54468751, 0.041665234, 0.57337528, 0.0074442979, 0.010118874, 0.097668171, 0.047499236, 0.22022037, 0.11357728, 0.14063072, 0.081412017, 0.15039197, 0.30661905, 0.010041318, 0.30713466, 0.2246805, 0.12985943, 0.013962295, 0.0031880976, 0.0033751372, 0.35504347, 0.043138403, 0.034578215, 0.17706399, 0.043236308]


一応想定した通り、variablesは(1, 1)あたりになってlossもなんとなく減っているみたいです