Tensorflow 1.11.0 выдает ошибку при попытке повторного использования переменных cudnnGRU с помощью scope.reusevariables () - PullRequest
0 голосов
/ 21 октября 2018

Я реализую кодировщик-декодер rnn, используя tf.contrib.cudnn_rnn.CudnnGRU() в качестве кодировщика, и обнаружил проблему:

Я хочу повторно использовать переменные, чтобы создать ту же модель, но использовать еес другими данными и, проще говоря, это будет код для воспроизведения моей проблемы:

tf.reset_default_graph()

def create_model():
    return tf.contrib.cudnn_rnn.CudnnGRU(num_layers=1, num_units=100,
                         direction='unidirectional')

# (time, batch_size, num_inputs)
x = tf.random_normal((100, 16, 100))

with tf.variable_scope('model') as scope:
    model_1 = create_model()
    rnn_out_1, rnn_state_1 = model_1(x)
    scope.reuse_variables()
    model_2 = create_model()
    rnn_out_2, rnn_state_2 = model_2(x)

Это приводит к следующей ошибке:

Переменная модель / cudnn_gru_1 / opaque_kernel несуществует или не был создан с помощью tf.get_variable ().Вы имели в виду установить reuse = tf.AUTO_REUSE в VarScope?

Итак, вторая модель пытается найти переменную model/cudnn_gru_1/opaque_kernel, но не может ее найти, потому что она должна искать model/cudnn_gru/opaque_kernel:0.

Дело в том, что я не знаю, почему это происходит, поскольку, следуя ссылке на тензор потока переменных, кажется, что все в порядке.С другой стороны, я также попытался написать это по-другому, так как документ tenorflow утверждает, что моя вышеупомянутая реализация и та, которую я показываю далее, фактически делают то же самое:

tf.reset_default_graph()

def create_model():
    return tf.contrib.cudnn_rnn.CudnnGRU(num_layers=1, num_units=100,
                         direction='unidirectional')

# (time, batch_size, num_inputs)
x = tf.random_normal((100, 16, 100))

with tf.variable_scope('model'):
    model_1 = create_model()
    rnn_out_1, rnn_state_1 = model_1(x)
with tf.variable_scope('model', reuse=True):
    model_2 = create_model()
    rnn_out_2, rnn_state_2 = model_2(x)

Этот второй способ фактически работает (илипо крайней мере я так думаю).Так что я действительно не знаю, что я делаю неправильно в первой реализации, я также не уверен, что обе реализации должны делать то же самое (что, я думаю, они должны).Так может кто-нибудь помочь мне разобраться, что я делаю неправильно или что я не могу правильно понять?

Заранее спасибо

1 Ответ

0 голосов
/ 21 октября 2018

CudnnGRU выглядит как объект модели в стиле керас.Поэтому вы должны повторно использовать объект для совместного использования параметров между слоями, такими как

def create_model():
    return tf.contrib.cudnn_rnn.CudnnGRU(num_layers=1, num_units=100,
                                  direction='unidirectional')


# (time, batch_size, num_inputs)
x = tf.random_normal((100, 16, 100))

model = create_model()
rnn_out_1, rnn_state_1 = model(x)
rnn_out_2, rnn_state_2 = model(x)

Я не знаю, почему только второй способ работает правильно.

EDIT

Я обнаружил, что CudnnGRU делает имена переменных для своих переменных уникально в текущей области видимости переменных.

В первом случае model_2 создает новое имя, например cudnn_gru_1, чтобы сделать его уникальным.С другой стороны, вторым способом вы создали новую область видимости переменных, поэтому уникальные имена переменных для model_2 совпадают с именами переменных для model_1.

Вы можете узнать, почему CudnnGRU создает уникальное имя переменной в Layer._set_scope () (tensorflow \ питона \ слои \ base.py # L150).Класс слоя создает новую переменную область видимости для своей переменной с аргументом default_name (область действия в данном случае - None), поэтому его имя становится уникальным.

...