Набор данных не помещается в памяти для обучения LSTM - PullRequest
3 голосов
/ 02 марта 2020

Я пытаюсь создать модель для обучения на большом массиве данных c. Миди-файлы конвертируются в numpy массивы. Поскольку LSTM требует последовательных данных, размер набора данных становится таким огромным при преобразовании в последовательность для LSTM.

Я конвертирую ноты midi в индекс на основе ключевого слова и продолжительности, поэтому я получаю 6 классов для ключа C4. Точно так же я получаю C3-B5, так что всего 288 классов вместе с классами для периодов отдыха.

Преобразованный формат одного миди выглядит следующим образом.

midi = [0,23,54,180,23,45,34,.....];

Для Обучая LSTM, x и y становятся

x = [[0,23,54..45],[23,54,..,34],...];

y=[[34],[76],...]

Значения в x и y далее преобразуются в однократное кодирование. Следовательно, размер данных становится огромным только для 60 маленьких файлов среднего размера, но у меня 1700 файлов. Как я могу обучить модель с таким количеством файлов. Я проверил ImageGenerator, но он требует, чтобы данные были в отдельных каталогах классов. Как этого добиться?

Ответы [ 2 ]

2 голосов
/ 02 марта 2020

Вы должны генерировать свои тренировочные данные на лету, во время самой тренировки. На основе tf документации вы можете написать свой собственный генератор для использования в качестве обучающих данных или унаследовать от Sequence .

Первый вариант должен выглядеть следующим образом:

def create_data_generator(your_files):
    raw_midi_data = process_files(your_files)
    seq_size = 32

    def _my_generator():
        i = 0 
        while True:
            x = raw_midi_data[i:i + seq_size]
            y = raw_midi_data[i + seq_size]
            i = (i + 1) % (len(raw_midi_data) - seq_size)
            yield x, y

    return _my_generator()

И затем вызывать его с помощью (при условии, что tf> = 2.0)

generator = create_data_generator(your_files)
model.fit(x=generator, ...)

Если вы используете «старые» Keras (до версии tenorflow 2.0) , которую сама команда Keras не рекомендует , вместо нее следует использовать fit_generator:

model.fit_generator(generator, ...)

С этим решением вы сохраняете свои данные в памяти только один раз, нет дублирования из-за перекрывающихся последовательностей.

0 голосов
/ 03 марта 2020

Я использовал класс генератора для этой задачи, использовал следующий код. Генератор модифицирован для моей цели. Использование памяти резко сокращено.

class Generator(Sequence):

    def __init__(self, x_set, y_set, batch_size=4):
        self.x, self.y = x_set, y_set

        self.batch_size = batch_size
        self.indices = np.arange(len(self.x))

    def __len__(self):
        return int(np.ceil(len(self.x) / self.batch_size))

    def __getitem__(self, idx):
        inds = self.indices[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_x = []
        batch_y = []
        for ind in inds:
            ip = []

            for q in self.x[ind]:
                o = np.zeros(323)
                o[int(q)] = 1
                ip.append(o)
            batch_x.append(ip)
            hot_encoded = []
            for val in self.y[ind]:

                t = np.zeros(323)
                t[int(val)] = 1
                hot_encoded.append(t)
            batch_y.append(hot_encoded)

        return np.array(batch_x), np.array(batch_y)

    def on_epoch_end(self):
        # np.random.shuffle(self.indices)
        np.random.shuffle(self.indices)

...