Невозможно воспроизвести результаты тензорного потока даже после установки случайного начального числа - PullRequest
0 голосов
/ 20 ноября 2018

Чтобы иметь возможность выполнять оптимизацию гиперпараметров, я думаю, что лучше установить случайное начальное число, чтобы мы лучше сравнивали модели.Таким образом, я установил случайное начальное число в тензорном потоке через: tf.set_random_seed(mseed), и я создал инициализатор как: kernel_initializer = tf.glorot_normal_initializer(seed=mseed), где я передал последний в ячейку LSTM.Таким образом, модель будет выглядеть следующим образом:

import tensorflow as tf
import numpy as np


def lstm_model(lstm_model(inputs, cell_size1, kernel_initializer, m_dtype, dropout, is_training, use_peepholes, mseed, num_classes):

    with tf.variable_scope('lstm_model'):

        cell = tf.nn.rnn_cell.LSTMCell(cell_size1, initializer=kernel_initializer)
        initial_state = cell.zero_state(34 if is_training else 14, dtype=tf.float32)

        output, new_state = tf.nn.dynamic_rnn(cell, inputs, dtype=m_dtype, initial_state=initial_state)


    with tf.variable_scope("output"):
        output = tf.reshape(output, shape=[-1, cell_size1])
        output = tf.layers.dense(output, units=num_classes,
                                 kernel_initializer=kernel_initializer)

        if is_training:
            output = tf.reshape(output, shape=[34, -1, num_classes])
        else:
            output = tf.reshape(output, shape=[14, -1, num_classes])

        return output, new_state, initial_state, model_summary


def model(inputs..., mseed, kernel_initializer, reuse=False):
    with tf.variable_scope('model', reuse=reuse):

        output, new_state, initial_state, model_summary = lstm_model(inputs, num_units,
                                                                     kernel_initializer,
                                                                     tf.float32, dropout, not reuse, True,
                                                                     mseed, num_classes=num_classes)

    # Now I calculate the loss and used an optimizer in case of training...
    return output, new_state, initial_state, model_summary

mseed = 123
seed(mseed)
tf.set_random_seed(mseed)
kernel_initializer = tf.glorot_normal_initializer(seed=mseed)

# here I loaded the data as numpy arrays...
# Here I created the placeholders...

# t for train, and d for development
output_t, new_state_t, init_state_t = model(inputs_t..., mseed, kernel_initializer, reuse=False)
output_d, new_state_d, init_state_d = model(inputs_d..., mseed, kernel_initializer, reuse=True)

train_model()...

Таким образом, код суммирован, чтобы включить только важную его часть.

Теперь даже после установки случайного начального числа и использования mseedпри создании ядер, но я не могу воспроизвести те же результаты.

Вот снимок экрана для точности и потерь во времени.Мы видим, что значения почти одинаковы почти в начале, а затем они становятся разными.

enter image description here

enter image description here

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

new_state_train_py = sess.run(initiale_state_train)
    for i in range(num_iterations):
        _, summary_t, new_state_train_py = sess.run([train_step, summary_train, new_state_train],
                                feed_dict={train_x_ph: train_x[:, i*time_steps: (i + 1) * time_steps, :],
                                           train_y_ph: train_y[:, i*time_steps: (i + 1) * time_steps, :],
                                           initiale_state_train: new_state_train_py})

        train_writer.add_summary(summary_t, epoch * num_iterations + i)

Что я знаю до сих пор, так это то, что основная проблема должна заключаться в определении модели, поскольку именно она определяет любую случайность во всей модели, и именно это делает прогнозирование различным в разных прогонах.той же модели.Пожалуйста, поправьте меня, если я ошибаюсь.

После отладки я заметил, что когда я изменил dtype для каждой операции на графике на tf.float64, я обнаружил, что обе кривые полностью пересекаются, за исключением того, что в конце я получаю еще одно небольшое изменение вкривые.Что может быть причиной такого поведения?

enter image description here enter image description here

Любая помощь очень ценится !!

1 Ответ

0 голосов
/ 20 ноября 2018

Если вы выполняете код на графическом процессоре, это, вероятно, связано с недетерминированным поведением cuDNN (см. этот поток для получения дополнительной информации).Порядок, в котором некоторые операции выполняются на графическом процессоре, может быть случайным из-за оптимизации производительности.Это означает, что ошибки округления также происходят в другом порядке, что приводит к небольшим различиям в результате этих операций.В вашем случае эти небольшие различия накапливаются в процессе обучения, что приводит к значительному изменению поведения уже после нескольких этапов обучения.

Порядок величины ошибок округления зависит от точности с плавающей запятой, используемой графическим процессором.При float64 ошибки округления занимают намного больше времени, чем при float32.

В CPU это недетерминированное поведение не должно происходить, когда фиксированные случайные начальные числа Python, numpy и tensorflow.Поэтому, если вы запускаете свой код на ЦП, вы должны получать одинаковые результаты при каждом запуске (но это, конечно, занимает гораздо больше времени).

...