Правильное использование sequence_length в dynamic_rnn

Я пытаюсь разработать RNN для целей классификации последовательностей, используя dynamic_rnn tensorflow. Мои примеры могут различаться по длине, и благодаря своим исследованиям я узнал, что могу передавать «sequence_length» в качестве параметра, определяющего длину моих примеров. Однако, когда я пытаюсь это сделать, я получаю некоторые странные результаты. Короче говоря, включение переменной не позволяет моей системе обучаться, спасибо, что я все еще могу тренироваться, когда я буферизирую свои последовательности с нулями до максимальной длины, но мне бы очень хотелось знать, что идет не так для моей будущей работы.

Паттерн, который я пытаюсь изучить, прост: если мы видим 1 саму по себе, мы присваиваем ей класс 1, если мы видим 2 где-либо в последовательности, ей присваивается класс 2, и если мы видим 1 как в первый, так и во второй раз. фрагменту мы должны присвоить класс 3.

Вот мой тестовый код:

from __future__ import print_function
import tensorflow as tf
import numpy as np

import random

dataset = [[1, 0], [2, 0], [1,2], [1,1]]
labels = [[1,0,0], [0,1,0], [0,1,0], [0,0,1]]

#---------------------------------------------
#define model

# placeholders
data_ph = tf.placeholder("float", [1, None, 1], name="data_placeholder")
len_ph = tf.placeholder("int32", [1], name="seq_len_placeholder")
y_ph = tf.placeholder("float", [1, None, 3], name="y_placeholder")

n_hidden = 10
n_out = len(labels[0])

# variable definition
out_weights=tf.Variable(tf.random_normal([n_hidden,n_out]))
out_bias=tf.Variable(tf.random_normal([n_out]))

# lstm definition
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden, state_is_tuple=True)
state_series, final_state = tf.nn.dynamic_rnn(
                                        cell=lstm_cell, 
                                        inputs=data_ph, 
                                        dtype=tf.float32,
                                        sequence_length=len_ph,
                                        time_major=False
                                        )
out = state_series[:, -1, :]

prediction=tf.nn.softmax(tf.matmul(out,out_weights)+out_bias)

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y_ph))
optimizer=tf.train.AdamOptimizer(learning_rate=1e-3).minimize(loss)

#---------------------------------------------
#run model
sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())

#TRAIN
for iteration in range(5000):
    if (iteration%100 == 0):
        print(iteration)
    ind = random.randint(0, len(dataset)-1)

    example = np.reshape(dataset[ind], (1,-1,1))
    label = np.reshape(labels[ind], (1,-1,3))

    vals={data_ph: example,
        len_ph: [len(example)],
        y_ph: label,
    }
    #print(sess.run(state_series, feed_dict=vals))
    sess.run(optimizer, feed_dict=vals)


#TEST
for x in range(len(dataset)):

    example = np.reshape(dataset[x], (1,-1,1))
    label = np.reshape(labels[x], (1,-1,3))
    vals = {data_ph: example,
        len_ph: [len(example)],
        y_ph: label,
    }

    classification = sess.run([prediction, loss], feed_dict=vals)
    print("predicted values: "+str(np.matrix.round(classification[0][0], decimals=2)), "loss: "+str(classification[1]))

Когда я оцениваю систему, когда я определяю sequence_length, все мои тестовые примеры возвращают один и тот же прогноз:

predicted values: [ 0.25999999  0.58999997  0.15000001] loss: 1.19235
predicted values: [ 0.25999999  0.58999997  0.15000001] loss: 0.855842
predicted values: [ 0.25999999  0.58999997  0.15000001] loss: 0.855842
predicted values: [ 0.25999999  0.58999997  0.15000001] loss: 1.30355

Сравните эти результаты с тем, когда я не определяю длину последовательности или когда я фиксирую длину на уровне 2:

predicted values: [ 0.99000001  0.          0.01      ] loss: 0.559447
predicted values: [ 0.  1.  0.] loss: 0.554004
predicted values: [ 0.          0.92000002  0.08      ] loss: 0.603042
predicted values: [ 0.02        0.02        0.95999998] loss: 0.579448

Мы будем признательны за любой вклад. Спасибо


person The_Chicken_Lord    schedule 29.05.2018    source источник


Ответы (1)


Параметр sequence_length, который вы передаете, на самом деле имеет значение 1, а не 2, поэтому сеть не может обучаться.

len(example) возвращает 1, поскольку имеет форму (1,2,1). Вы можете исправить это, используя len(example.flatten()), и вы должны увидеть правильный вывод.

person vijay m    schedule 29.05.2018
comment
Спасибо! Это определенно объясняет проблему - person The_Chicken_Lord; 31.05.2018