Как загружать порции данных в память «заранее», чтобы избежать чтения с диска? - PullRequest
0 голосов
/ 17 июня 2019

Я обучаю ConvNet ( Keras, python ) для некоторых пользовательских наборов данных изображений непосредственно с помощью графического процессора моего ноутбука ( GeForce GTX 1050 ). Контролируя мой GPU во время тренировок, я заметил, что он использовался только на 10% от его емкости или даже меньше. Дальнейшие исследования позволили мне понять, что обучение было узким местом при доступе к данным с моего диска хранения (я использую генератор данных).

Я также заметил, что, хотя диск использовался на 100%, моя Память не использовалась (около 65%). Я подумал: давайте загрузим в память «заранее» следующую партию данных (или несколько следующих партий), пока графический процессор обучается текущей партии, , а затем получим прямой доступ к загруженной партии из Память, избегая дорогостоящих операций чтения с диска . Я искал документацию или код для переполнения стека и других платформ, но не нашел ничего подходящего.

Одним из временных решений, которое я нашел, чтобы избежать этого узкого места чтения диска, было вставка моих данных на диск с операционной системой, который является SSD. Он работал довольно хорошо, сокращая время обучения в 10-15 раз , Но поскольку у меня ограниченная емкость хранилища на диске SSD (100 Гб), это решение не будет работать, когда я перейду к более тяжелым данным (обычно я сейчас использую пересчитанный образ (64, 64), но я планирую увеличить его масштабирование). до (128, 128) или даже больше).

Введите код моего генератора, чтобы вы могли лучше понять ситуацию:

    def generator(self, passes=np.inf):

        # initialize the epoch count
        db = self.db
        epochs = 0

        # keep looping infinitely -- the model will stop once we have
        # reach the desired number of epochs
        while epochs < passes:
            # shuffle dataset_indices for stochasticity
            if self.shuffle == True: np.random.shuffle(self.dataset_indices)
            # loop over the HDF5 dataset_indices
            for i in np.arange(0, self.numImages, self.batchSize):
                X, Y = [], []

                if self.gaussian_test == True:  # TODO : Add gaussian testing
                    for j in self.dataset_indices[i:i + self.batchSize]:
                        y = db[db[self.gen_type + "_indices"][j]]["label"][()]
                        X.append(np.random.normal(loc=y, scale=0.2, size=(1, 64, 64)))
                        Y.append(y)

                else:
                    for j in self.dataset_indices[i:i + self.batchSize]:
                        X.append(db[db[self.gen_type + "_indices"][j]]["array"][()])
                        Y.append(db[db[self.gen_type + "_indices"][j]]["label"][()])

                X = np.array(X)
                Y = np.array(Y)
                Y = to_categorical(Y, num_classes=6)
                # yield a tuple of images and labels
                yield (X, Y)
            # increment the total number of epochs
            epochs += 1


Я не уверен, как поступить, но я почти уверен, что это должно быть возможно ...

1 Ответ

0 голосов
/ 24 июня 2019

Поскольку я пока не получил никакого ответа, я делюсь своими выводами для всех, кому будет интересна эта тема.На самом деле, идея, которую я искал, состояла в том, чтобы использовать мульти-обработку ...

(I): После некоторых исследований я обнаружил, что Keras fit_generator () допускает такую ​​ мультиобработку с помощью аргументов use_multiprocessing = True и working = n .Но этот метод имеет свои ограничения:

  • Во-первых, ваш генератор должен быть потокобезопасным .Если ваш генератор наследует от класса Keras.utils.Sequence, он уже поточно-ориентирован.Иначе, обратитесь к этому учебнику , где вы узнаете, как создать декоратор, который сделает ваш поток генератора безопасным.
  • Во-вторых, если вы используете компьютер с Windows, то вы можете 't use_multiprocessing = True , поскольку это не реализовано.Хотя я понял, что вы все равно можете установить working = n> 1 , но тогда я думаю, что ваш генератор не будет поточно-ориентированным, что является проблемой.

(II): Поскольку я использую компьютер Windows, это не сработало для меня.Затем я нашел другие ресурсы ( TensorFlow doc , Пост блога ), предлагающие использовать TensorFlow QueueRunner class .Это кажется наиболее эффективным и надежным решением, но вам нужно использовать TensorFlow, который может занять много времени, если вам придется погрузиться в него в первый раз.Я еще не пробовал это решение, так как в ближайшие дни ожидаю перехода на облако AWS, что позволит мне использовать первое решение.

...