I implemented a sequence generator object according to guidelines from link.
import tensorflow as tf
from cv2 import imread, resize
from sklearn.utils import shuffle
from cv2 import imread, resize
import numpy as np
from tensorflow.keras import utils
import math
import keras as ks
class reader(tf.keras.utils.Sequence):
def __init__(self, x, y, batch_size, n_class):
self.x, self.y = x, y
self.batch_size = batch_size
self.n_class = n_class
def __len__(self):
return math.ceil(len(self.x) / self.batch_size)
def __getitem__(self, idx):
print('getitem', idx)
batch_x = self.x[idx * self.batch_size:(idx + 1) *
self.batch_size]
batch_y = self.y[idx * self.batch_size:(idx + 1) *
self.batch_size]
data_x = list()
for batch in batch_x:
tmp = list()
for img_path in batch:
try:
img = imread(img_path)
tmp.append(img)
except Exception as e:
print(e)
print('failed to find path {}'.format(img_path))
data_x.append(tmp)
#
data_x = np.array(data_x, dtype='object')
data_y = np.array(batch_y)
data_y = utils.to_categorical(data_y, self.n_class)
print('return item')
print(data_x.shape)
return (data_x, data_y)
def on_epoch_end(self):
# option method to run some logic at the end of each epoch: e.g. reshuffling
print('on epoch end')
seed = np.random.randint()
self.x = shuffle(self.x, random_state=seed)
self.y = shuffle(self.y, random_state=seed)
However, it doesn't work with tensorflow model's fit api. Below is the simple model architecture I used to replicate this issue.
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv3D(10, input_shape=(TEMPORAL_LENGTH,HEIGHT,WIDTH,CHANNEL), kernel_size=(2,2,2), strides=2))
model.add(tf.keras.layers.Conv3D(10, kernel_size=(2,3,3), strides=2))
model.add(tf.keras.layers.Conv3D(10, kernel_size=(2,3,3), strides=2))
model.add(tf.keras.layers.Conv3D(10, kernel_size=(2,3,3), strides=2))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(10))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy', tf.keras.metrics.Precision(), tf.keras.metrics.Recall()])
model.summary()
Let me create a reader
r1 = reader(x_train, y_train, 20, 10)
Then I call the model.fit api.
train_history = model.fit(r1, epochs=3, steps_per_epoch=5, verbose=1)
### output ###
getitem 0
return item
(20, 16, 192, 256, 3)
WARNING:tensorflow:sample_weight modes were coerced from
...
to
['...']
Train for 5 steps
Epoch 1/3
It will stay like this forever if I don't interrupt. Out of curiosity, I tried this approach with model created from Keras api and to my surprise it just work!
model = ks.models.Sequential()
model.add(ks.layers.Conv3D(10, input_shape=(TEMPORAL_LENGTH,HEIGHT,WIDTH,CHANNEL), kernel_size=(2,2,2), strides=2))
model.add(ks.layers.Conv3D(10, kernel_size=(2,3,3), strides=2))
model.add(ks.layers.Conv3D(10, kernel_size=(2,3,3), strides=2))
model.add(ks.layers.Conv3D(10, kernel_size=(2,3,3), strides=2))
model.add(ks.layers.Flatten())
model.add(ks.layers.Dense(10))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
train_history = model.fit(r1, epochs=3, steps_per_epoch=5, verbose=1)
### output ###
Epoch 1/3
getitem 586
return item
(20, 16, 192, 256, 3)
getitem 169
1/5 [=====>........................] - ETA: 22s - loss: 11.0373 - accuracy: 0.0000e+00return item
(20, 16, 192, 256, 3)
getitem 601
2/5 [===========>..................] - ETA: 12s - loss: 7.9983 - accuracy: 0.0250 return item
(20, 16, 192, 256, 3)
getitem 426
3/5 [=================>............] - ETA: 8s - loss: 10.7049 - accuracy: 0.2500return item
(20, 16, 192, 256, 3)
getitem 243
4/5 [=======================>......] - ETA: 3s - loss: 8.5093 - accuracy: 0.1875
Dependencies
- tensorflow-gpu: 2.1
- keras-gpu: 2.3.1