Чтобы обучить нейронную сеть, я изменил код, который нашел на YouTube. Это выглядит следующим образом:
def data_generator(samples, batch_size, shuffle_data = True, resize=224):
num_samples = len(samples)
while True:
random.shuffle(samples)
for offset in range(0, num_samples, batch_size):
batch_samples = samples[offset: offset + batch_size]
X_train = []
y_train = []
for batch_sample in batch_samples:
img_name = batch_sample[0]
label = batch_sample[1]
img = cv2.imread(os.path.join(root_dir, img_name))
#img, label = preprocessing(img, label, new_height=224, new_width=224, num_classes=37)
img = preprocessing(img, new_height=224, new_width=224)
label = my_onehot_encoded(label)
X_train.append(img)
y_train.append(label)
X_train = np.array(X_train)
y_train = np.array(y_train)
yield X_train, y_train
Теперь я попытался обучить нейронную сеть с помощью этого кода, размер выборки поезда составляет 105000 (файлы изображений, которые содержат 8 символов из 37 возможных, AZ, 0-9 и пустое пространство). Я использовал относительно небольшой размер партии (32, я думаю, что это уже слишком мало), чтобы сделать его более эффективным, но, тем не менее, тренировка четверти первой эпохи длилась вечно (у меня было 826 шагов за эпоху, а это заняло 90 минут. для 199 шагов ... steps_per_epoch = num_train_samples // batch_size
).
В генератор данных включены следующие функции:
def shuffle_data(data):
data=random.shuffle(data)
return data
Я не думаю, что мы можем сделать эту функцию более эффективной или исключить его из генератора.
def preprocessing(img, new_height, new_width):
img = cv2.resize(img,(new_height, new_width))
img = img/255
return img
Для предварительной обработки / изменения размера данных я использую этот код для получения изображений до уникального размера, например (224, 224, 3). Я думаю, что эта часть генератора занимает больше всего времени, но я не вижу возможности исключить ее из генератора (поскольку моя память будет заполнена, если мы изменим размер изображений вне пакетов).
#One Hot Encoding of the Labels
from numpy import argmax
# define input string
def my_onehot_encoded(label):
# define universe of possible input values
characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ '
# define a mapping of chars to integers
char_to_int = dict((c, i) for i, c in enumerate(characters))
int_to_char = dict((i, c) for i, c in enumerate(characters))
# integer encode input data
integer_encoded = [char_to_int[char] for char in label]
# one hot encode
onehot_encoded = list()
for value in integer_encoded:
character = [0 for _ in range(len(characters))]
character[value] = 1
onehot_encoded.append(character)
return onehot_encoded
Думаю, в этой части мог бы быть один подход, чтобы сделать его более эффективным. Я подумываю исключить этот код из генератора и создать массив y_train вне генератора, чтобы генератору не приходилось каждый раз горячо кодировать метки.
Как вы думаете? Или мне следует go для совершенно другого подхода?