如何提高数据生成器的效率?

5
为了训练神经网络,我修改了在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

现在,我尝试使用这段代码来训练神经网络,训练样本大小为105,000(图像文件,其中包含37种可能性中的8个字符,包括A-Z、0-9和空格)。 我使用了相对较小的批次大小(32,我认为已经太小了),以使它更加高效,但即使如此,训练一个季度的第一轮(每轮有826个步骤)也要花费很长时间(199个步骤需要90分钟... 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数组,以便生成器不必每次对标签进行单热编码。

你认为呢?或者我应该选择完全不同的方法吗?

1个回答

3

我发现你的问题非常有趣,因为你只给了一些线索。因此,这是我的调查结果。

使用你的片段,我找到了GitHub存储库和三部分的YouTube视频教程,主要关注Python中使用生成器函数的好处。 数据基于这个kaggle(我建议检查该问题上的不同内核,以比较您已经尝试过的方法与另一个CNN网络和使用的API进行审查)。

你不需要从头开始编写数据生成器,虽然这并不难,但发明轮子并不生产效益。

尽管如此,为了解决kaggle的任务,模型只需要识别单个图像,因此该模型是一个简单的深度CNN。但是据我所知,你正在将8个随机字符(类别)组合成一张图片,以便同时识别多个类别。对于这个任务,您需要R-CNN或YOLO作为您的模型。我最近刚刚发现了YOLO v4,可以非常快速地使其适用于特定任务。

关于你的设计和代码的普遍建议。

  • 确保库使用GPU,这可以节省很多时间。(即使我在CPU上重复了存储库中的花卉实验非常快 - 约10分钟,但结果预测并不比随机猜测更好。因此完整的训练需要在CPU上花费大量时间。)
  • 比较不同版本以找到瓶颈。尝试使用包含48张图像(每类1张)的数据集,增加每类图像的数量,并进行比较。缩小图像尺寸,改变模型结构等。
  • 在小型人工数据上测试全新的模型,证明其想法或使用迭代过程,从可转换为您任务的项目开始(手写识别?handwriting recognition?)

非常感谢您详细的回答! :-) 特别是有关DataGenerator sequence类的回答非常有帮助!关于DataGenerator,我在Stack Overflow上又提了一个问题。也许您可以看一下这个问题。它与GPU的使用有关:https://stackoverflow.com/questions/62468830/filenotfounderror-no-such-file-error-occuring-only-on-gpu-not-on-cpu/62476334?noredirect=1#comment110491190_62476334 - Tobitor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接