Как я могу получить воспроизводимые результаты в кератах для сверточной нейронной сети, используя увеличение данных для классификации изображений? - PullRequest
0 голосов
/ 22 апреля 2020

Если я обучаю одну и ту же архитектуру модели сверточной нейронной сети (на одних и тех же данных) дважды, очищая сеанс между запусками, я получаю разные результаты.

tensorboard_plot

Я установил случайные начальные числа и конфигурацию потока следующим образом:

import numpy as np
from numpy.random import seed
import pandas as pd
import random as rn
import os

seed_num = 1
os.environ['PYTHONHASHSEED'] = '0'
np.random.seed(seed_num)
rn.seed(seed_num)

import tensorflow as tf
from tensorflow.keras.models import load_model
from tensorflow.compat.v1.keras import backend as K

session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
tf.random.set_seed(seed_num)
sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
K.set_session(sess)

... и я указал начальное число при запуске flow_from_directory:

train_data_gen_aug_rotate = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, 
                                                                 validation_split=0.1,
                                                                 rotation_range=45)

train_img = train_data_gen_aug_rotate.flow_from_directory(data_path, 
                                               subset='training',
                                               color_mode='rgb', 
                                               target_size=target_size,
                                               batch_size=batch_size, 
                                               class_mode='categorical',
                                               seed=seed_num)

Другая информация, полезная для ответа на вопрос:

Архитектура модели:

inputs = tf.keras.layers.Input(shape=num_pixels_and_channels)
conv = tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3), padding='SAME', activation='relu')(inputs)
pool = tf.keras.layers.AveragePooling2D(pool_size=(2,2), strides=(2,2), padding='SAME')(conv)
batnorm = tf.keras.layers.BatchNormalization()(pool)
flattened = tf.keras.layers.Flatten()(batnorm)
dense = tf.keras.layers.Dense(257)(flattened)
outputs = tf.keras.layers.Softmax()(dense)

my_model = tf.keras.Model(inputs, outputs)

I'm компилируем модель следующим образом:

model_name.compile(loss='categorical_crossentropy',  
                optimizer=tf.keras.optimizers.Adam(0.001),
                metrics=['accuracy']
               )

Я использую train_on_batch и test_on_batch:

# get next batch of images & labels
X_imgs, X_labels = next(train_img) 

#train model, get cross entropy & accuracy for batch
train_CE, train_acc = model_name.train_on_batch(X_imgs, X_labels)

# validation images - just predict
X_imgs_val, X_labels_val = next(val_img)
val_CE, val_acc = model_name.test_on_batch(X_imgs_val, X_labels_val)

Я очищаю сеанс между запуском каждой модели с помощью tf.keras.backend.clear_session()

Я работаю над ма c с одним процессором, в ноутбуке Jupyter, использую тензор потока версии 2.1.0.

Я спросил, есть ли glorot_uniform kernel_initializer в Conv2D использует тот же начальный номер, который установлен в tf.random.set_seed(), и единственный ответ, предоставленный до сих пор (на момент написания), говорит «да».

Что еще мне нужно сделать, чтобы получить тот же результат для той же модели архитектуры? Существует ли случайное начальное число, связанное с ImageDataGenerator, train_on_batch, test_on_batch или с оптимизатором Адама, который не использует заданное мной начальное число тензорного потока? Или другая часть кода, для которой нужно указать зерно отдельно?

1 Ответ

0 голосов
/ 23 апреля 2020

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

1) Очистка сеанса и установка случайных начальных чисел и конфигураций сеанса tf перед каждым экспериментом:

tf.keras.backend.clear_session()

seed_num = 1
os.environ['PYTHONHASHSEED'] = '0'
np.random.seed(seed_num)
rn.seed(seed_num)
tf.random.set_seed(seed_num)
session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
K.set_session(sess)

2) Повторное выполнение кода ImageDataGenerator и flow_from_directory перед каждым экспериментом (чтобы обеспечить начать с начала последовательности случайных чисел для начального числа после начала обучения для следующей модели)

Итак, мой код от начала записной книжки до 1-го эксперимента:

import numpy as np
from numpy.random import seed
import pandas as pd
import random as rn
import os

seed_num = 1
os.environ['PYTHONHASHSEED'] = '0'
np.random.seed(seed_num)
rn.seed(seed_num)

import tensorflow as tf
from tensorflow.keras.models import load_model
from tensorflow.compat.v1.keras import backend as K

session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
tf.random.set_seed(seed_num)
sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
K.set_session(sess)

... тогда для каждого эксперимента, до определения архитектуры модели и компиляции модели, это:

tf.keras.backend.clear_session()

seed_num = 1
os.environ['PYTHONHASHSEED'] = '0'
np.random.seed(seed_num)
rn.seed(seed_num)
tf.random.set_seed(seed_num)
session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
K.set_session(sess)


batch_size = 80  
target_size=(64,64) 
num_pixels_and_channels = (64,64,3) 

train_data_gen_aug_rotate = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, 
                                                                 validation_split=0.1,
                                                                 rotation_range=45)

train_img = train_data_gen_aug_rotate.flow_from_directory(data_path, 
                                               subset='training',
                                               color_mode='rgb', 
                                               target_size=target_size,
                                               batch_size=batch_size, 
                                               class_mode='categorical',
                                               seed=seed_num)

val_data_gen_aug_rotate = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, 
                                                               validation_split=0.1)


val_img = val_data_gen_aug_rotate.flow_from_directory(data_path, 
                                           subset='validation',
                                           color_mode='rgb',
                                           target_size=target_size,
                                           batch_size=batch_size,
                                           class_mode='categorical',
                                           seed=seed_num)

Я не знаю, является ли это излишним, и есть более эффективный способ сделать это, но это у меня работает на ноутбуке с одним процессором. (Работа на GPU вносит дополнительную изменчивость)

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