Cannot get reproducible results with ImageDataGenerator in keras - tensorflow

I am trying to get reproducible results between multiple runs of the same script in keras, but I get different ones at each iteration. My code looks like this:
import numpy as np
from numpy.random import seed
import random as rn
import os
seed_num = 1
os.environ['TF_CUDNN_DETERMINISTIC'] = '1'
os.environ['PYTHONHASHSEED'] = '1'
os.environ['TF_DETERMINISTIC_OPS'] = '1'
np.random.seed(seed_num)
rn.seed(seed_num)
import tensorflow as tf
tf.random.set_seed(seed_num)
import tensorflow.keras as ks
from tensorflow.python.keras import backend as K
...some imports...
from tensorflow.keras.preprocessing.image import ImageDataGenerator
.... data loading etc ....
generator = ImageDataGenerator(
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True)
generator.fit(X_train, seed=seed_num)
my_model.fit(generator.flow(X_train, y_train, batch_size=batch_size, shuffle=False, seed=seed_num), validation_data=(X_val, y_val), callbacks=callbacks , epochs=epochs, shuffle=False)
I identified the problem to be in ImageDataGenerator, i.e., when setting generator = ImageDataGenerator() without any augmentation the results are reproducible. I am also running on CPU and TensorFlow version is 2.4.1. What am I missing here?

Using GPU while creating augmented images can produce nondeterministic results.
To get reproducible results using ImageDataGenerator and GPU, one way is the following:
import random, os
import numpy as np
import tensorflow as tf
def set_seed(seed=0):
np.random.seed(seed)
tf.random.set_seed(seed)
random.seed(seed)
os.environ['TF_DETERMINISTIC_OPS'] = "1"
os.environ['TF_CUDNN_DETERMINISM'] = "1"
os.environ['PYTHONHASHSEED'] = str(seed)
set_seed()
Before model.fit() call again set_seed():
set_seed()
model.fit(...)
Otherwise, you can install the package tensorflow-determinism:
pip install tensorflow-determinism
If you're using Google Colab, restart your runtime or it won't probably work
The package will interact with GPU to produce deterministic results.
import random, os
import numpy as np
import tensorflow as tf
def set_seed(seed=0):
os.environ['TF_DETERMINISTIC_OPS'] = '1'
random.seed(seed)
np.random.seed(seed)
tf.random.set_seed(seed)
set_seed()
# code
Also in this case, before model.fit() call again set_seed():
set_seed()
model.fit(...)

Related

Feature extraction in pretrained model: different result from keras-gpu&tensorflow-gpu and keras&tensorflow base

I'm extracting features from a pretrained keras model (VGG16).The task is simple but I obtain different features (nx4096) when I run the code on GPU (tensorflow-gpu and keras-gpu installed) or CPU (tensorflow and keras installed).
The differences in the features are huge and when I use the different extracted features in a classifier, I obtain very much better results with those obtained on GPU.
Could someone explain me why?
I write the code in case it is useful:
from keras.preprocessing import image
from keras.applications.vgg16 import VGG16
import tensorflow.keras
from keras.applications.vgg16 import preprocess_input
import numpy as np
from sklearn.cluster import KMeans
# %matplotlib inline
import matplotlib.pyplot as plt
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.applications.vgg16 import decode_predictions
from keras.models import Model
from pickle import dump
model = VGG16(weights='imagenet')#, include_top=False
# remove the output layer
model = Model(inputs=model.inputs, outputs=model.layers[-2].output)
model.summary()
trainstack=np.load('.../All_imgs.npy')
trainstack=np.transpose(trainstack,[2,0,1,3])
trainstack=preprocess_input(trainstack)
trainstacklabel=np.load('.../All_labels.npy')
img_data = preprocess_input(trainstack)
vgg16_feature_list=[]
for i in range(trainstack.shape[0]):
v =img_data[i,:,:,:]
v=v[np.newaxis,...]
vgg16_feature = model.predict(v)
print (vgg16_feature.shape)
vgg16_feature_np = np.array(vgg16_feature)
vgg16_feature_list.append(vgg16_feature_np.flatten())
np.save('.../features.npy',vgg16_feature_list)
Thank you very much in advance!!
I try to extract features from a pretrained model for combining them with other variables in a binary classifier.
I obtain very different extracted features when I run my code on GPU and CPU.

tensorflow.keras.fit uses more and more memory until crash

I am trying to solve an exercise from a machine learning book, where a classifier should be trained on the cifar10 dataset using tensorflow and keras. I have attached a code example. The code is running in a Jupyter notebook inside PyCharm.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import time
import os
import tensorflow as tf
from tensorflow import keras
tf.random.set_seed(42)
np.random.seed(42)
def build_model():
# Build a model as instructed
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=[32, 32, 3]))
for i in range(20):
model.add(keras.layers.Dense(100,
activation=keras.activations.elu,
kernel_initializer=tf.keras.initializers.HeNormal))
model.add(keras.layers.Dense(10, activation=keras.activations.softmax))
return model
model = build_model()
# Load the CIFAR10 image dataset
cifar10 = keras.datasets.cifar10.load_data()
X_train = cifar10[0][0] / 255.
X_test = cifar10[1][0] / 255.
y_train = cifar10[0][1]
y_test = cifar10[1][1]
print(X_train.max())
from sklearn.model_selection import train_test_split
# Split the data
X_train, X_valid, y_train, y_valid = train_test_split(X_train, y_train, test_size=0.1, shuffle= True)
model = build_model()
root_logdir = os.path.join(os.curdir, "my_logs_11-8")
def get_run_logdir():
run_id = time.strftime("run_%Y_%m_%d_%H_%M_%S")
return os.path.join(root_logdir, run_id)
run_logdir = get_run_logdir()
tensorboard_cb = keras.callbacks.TensorBoard(run_logdir)
model.compile(optimizer=keras.optimizers.Nadam(lr=5e-5), loss="sparse_categorical_crossentropy")
history = model.fit(X_train, y_train, epochs=100,
validation_data=(X_valid, y_valid),
callbacks=[tensorboard_cb],
batch_size=32)
I am already running into problems here:
I do not get past a few epochs (10-20), because with each epoch, the python process takes up more and more memory. My machine has 16 GB, of which 12 GB are usually free. When memory is full, my IDE (PyCharm) crashes and the python process is killed. Is that due to a memory leak? What can I do to fix it?
For each epoch, keras measures an estimated time of how long that epoch took. However, the time measured is much smaller than walltime (24s/epoch vs. ~60s/epoch). The book I am following seems to reach much faster training on a much weaker machine. How can this be?

Reproducible results with Keras with Tensorflow background

I have my own network. But it is giving me different outputs each time I run the code. I'm using keras (with Tensorflow backend), write the following code for reproducibility. My training sample: 280, validation sample # 27, test sample # 21.
# The following lines are for reproducibility
import os
import random as rn
os.environ['PYTHONHASHSEED'] = '0'
# random seed for NP genreator of ranodm numbers
np.random.seed(37)
rn.seed(1254) # specifying the seed for python-generated random numbers:
import tensorflow as tf
tf.compat.v1.set_random_seed(89) #tf.set_random_seed(89)
import keras.backend.tensorflow_backend as K
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)

How to get reproducible result when running Keras with Tensorflow backend

Every time I run LSTM network with Keras in jupyter notebook, I got a different result, and I have googled a lot, and I have tried some different solutions, but none of they are work, here are some solutions I tried:
set numpy random seed
random_seed=2017
from numpy.random import seed
seed(random_seed)
set tensorflow random seed
from tensorflow import set_random_seed
set_random_seed(random_seed)
set build-in random seed
import random
random.seed(random_seed)
set PYTHONHASHSEED
import os
os.environ['PYTHONHASHSEED'] = '0'
add PYTHONHASHSEED in jupyter notebook kernel.json
{
"language": "python",
"display_name": "Python 3",
"env": {"PYTHONHASHSEED": "0"},
"argv": [
"python",
"-m",
"ipykernel_launcher",
"-f",
"{connection_file}"
]
}
and the version of my env is:
Keras: 2.0.6
Tensorflow: 1.2.1
CPU or GPU: CPU
and this is my code:
model = Sequential()
model.add(LSTM(16, input_shape=(time_steps,nb_features), return_sequences=True))
model.add(LSTM(16, input_shape=(time_steps,nb_features), return_sequences=False))
model.add(Dense(8,activation='relu'))
model.add(Dense(1,activation='linear'))
model.compile(loss='mse',optimizer='adam')
The seed is definitely missing from your model definition. A detailed documentation can be found here: https://keras.io/initializers/.
In essence your layers use random variables as their basis for their parameters. Therefore you get different outputs every time.
One example:
model.add(Dense(1, activation='linear',
kernel_initializer=keras.initializers.RandomNormal(seed=1337),
bias_initializer=keras.initializers.Constant(value=0.1))
Keras themselves have a section about getting reproduceable results in their FAQ section: (https://keras.io/getting-started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development). They have the following code snippet to produce reproducable results:
import numpy as np
import tensorflow as tf
import random as rn
# The below is necessary in Python 3.2.3 onwards to
# have reproducible behavior for certain hash-based operations.
# See these references for further details:
# https://docs.python.org/3.4/using/cmdline.html#envvar-PYTHONHASHSEED
# https://github.com/fchollet/keras/issues/2280#issuecomment-306959926
import os
os.environ['PYTHONHASHSEED'] = '0'
# The below is necessary for starting Numpy generated random numbers
# in a well-defined initial state.
np.random.seed(42)
# The below is necessary for starting core Python generated random numbers
# in a well-defined state.
rn.seed(12345)
# Force TensorFlow to use single thread.
# Multiple threads are a potential source of
# non-reproducible results.
# For further details, see: https://stackoverflow.com/questions/42022950/which-seeds-have-to-be-set-where-to-realize-100-reproducibility-of-training-res
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
from keras import backend as K
# The below tf.set_random_seed() will make random number generation
# in the TensorFlow backend have a well-defined initial state.
# For further details, see: https://www.tensorflow.org/api_docs/python/tf/set_random_seed
tf.set_random_seed(1234)
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)
Keras + Tensorflow.
Step 1, disable GPU.
import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = ""
Step 2, seed those libraries which are included in your code, say "tensorflow, numpy, random".
import tensorflow as tf
import numpy as np
import random as rn
sd = 1 # Here sd means seed.
np.random.seed(sd)
rn.seed(sd)
os.environ['PYTHONHASHSEED']=str(sd)
from keras import backend as K
config = tf.ConfigProto(intra_op_parallelism_threads=1,inter_op_parallelism_threads=1)
tf.set_random_seed(sd)
sess = tf.Session(graph=tf.get_default_graph(), config=config)
K.set_session(sess)
Make sure these two pieces of code are included at the start of your code, then the result will be reproducible.
I resolved this issue by adding os.environ['TF_DETERMINISTIC_OPS'] = '1'
Here an example:
import os
os.environ['TF_DETERMINISTIC_OPS'] = '1'
#rest of the code
#TensorFlow version 2.3.1

Getting Cuda code from Tensorflow or Keras

I have a code in Keras (or its TF version). I want to have a CUDA code which is equivalence to it. Is there a way to get it?
I know that from Keras I can look at the basic graph topology using the following code:
# LSTM for sequence classification in the IMDB dataset
import numpy
from keras.datasets import imdb
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers.embeddings import Embedding
from keras import backend as K
from keras.preprocessing import sequence
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset but only keep the top n words, zero the rest
top_words = 5000
max_review_length = 500
# create the model
embedding_vecor_length = 32
model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
g = K.get_session().graph
# GIVES THE GRAPH TOPOLOGY!:
graph_def = g.as_graph_def()
Is there a way to have the .cc file that represent this code?
Thanks!
There is no functionality in TensorFlow to generate C++ CUDA source code from a graph, but the XLA framework supports ahead-of-time compilation, which generates efficient bytecode from your TensorFlow graph, which you can then execute on your CUDA-capable GPU.