Почему стекирование CNN разрушает воспроизводимость (даже с использованием seed и CPU)? - PullRequest
2 голосов
/ 03 ноября 2019

Воспроизводится :

ipt = Input(batch_shape=batch_shape)
x   = Conv2D(6, (8, 8), strides=(2, 2), activation='relu')(ipt)
x   = Flatten()(x)
out = Dense(6, activation='softmax')(x)  

НЕ Воспроизводится :

ipt = Input(batch_shape=batch_shape)
x   = Conv2D(6, (8, 8), strides=(2, 2), activation='relu')(ipt)
x   = Conv2D(6, (8, 8), strides=(2, 2), activation='relu')(x)
x   = Flatten()(x)
out = Dense(6, activation='softmax')(x)

Разница значительно увеличивается при использовании модели большего размераи фактические данные вместо случайного шума - до 30% разница в точности (относительная) в течение одной маленькой эпохи. Настройка среды, рассматриваемые источники и полный минимальный воспроизводимый пример приведены ниже. Соответствующий Git

В чем проблема и как ее исправить?


ВОЗМОЖНЫЕ ИСТОЧНИКИ : ( [x] = исключено)

  • [x] TF2 против TF1;Keras 2.3.0+ против Keras 2.2.5 (проверено оба)
  • [x] Случайные семена (numpy, tf, random, PYTHONHASHSEED)
  • [x] Значения данных / перестановка (те же значения, без перестановки)
  • [x] Инициализация веса (те же значения)
  • [x] Использование графического процессора (используется процессор)
  • [x] Многопоточность процессора (используется один поток; см. Также далее «далее»)
  • [x] Числовая неточность (используется float64; более того, степень расхождения слишком велика для числового показателя)
  • [x] Плохая установка CUDA (все официальное руководство тесты пройдены, TF обнаруживает GPU и CUDA)

ОКРУЖАЮЩАЯ СРЕДА :

  • CUDA 10.0.130, cuDNN 7.6.0, Windows 10, GTX 1070
  • Python 3.7.4, Spyder 3.3.6, Anaconda 3.0 2019.10
  • Anaconda Powershell Prompt для установки терминала PYTHONHASHSEED и запуска Spyder

НАБЛЮДЕНИЯ :

  • float64 против float32 - без уведомленияВозможная разница
  • ЦП и ГП - нет заметной разницы
  • Невоспроизводимо также для Conv1D
  • Воспроизводимо для Dense Замена Conv;другие слои, которые не тестировались
  • Для более крупной модели , которая все еще «мала», дисперсия потерь в течение одной эпохи существенна:
one_epoch_loss = [1.6814, 1.6018, 1.6577, 1.6789, 1.6878, 1.7022, 1.6689]
one_epoch_acc  = [0.2630, 0.3213, 0.2991, 0.3185, 0.2583, 0.2463, 0.2815]

КОД :

batch_shape = (32, 64, 64, 3)
num_samples = 1152

ipt = Input(batch_shape=batch_shape)
x   = Conv2D(6, (8, 8), strides=(2, 2), activation='relu')(ipt)
x   = Conv2D(6, (8, 8), strides=(2, 2), activation='relu')(x)
x   = Flatten()(x)
out = Dense(6, activation='softmax')(x)
model = Model(ipt, out)
model.compile('adam', 'sparse_categorical_crossentropy')

X = np.random.randn(num_samples, *batch_shape[1:])
y = np.random.randint(0, 6, (num_samples, 1))

reset_seeds()
model.fit(x_train, y_train, epochs=5, shuffle=False)

Импорт / настройка :

import os
os.environ['PYTHONHASHSEED'] = '0'
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import numpy as np
np.random.seed(1)
import random
random.seed(2)

import tensorflow as tf
session_conf = tf.ConfigProto(
      intra_op_parallelism_threads=1,
      inter_op_parallelism_threads=1)
sess = tf.Session(config=session_conf) # single-threading; TF1-only

def reset_seeds():
    np.random.seed(1)
    random.seed(2)
    if tf.__version__[0] == '2':
        tf.random.set_seed(3)
    else:
        tf.set_random_seed(3)
    print("RANDOM SEEDS RESET")
reset_seeds()

from keras.layers import Input, Dense, Conv2D, Flatten
from keras.models import Model
import keras.backend as K

K.set_floatx('float64')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...