繁体   English   中英

数据集不适合 LSTM 训练的内存

[英]Dataset doesn't fit in memory for LSTM training

我正在尝试创建在大型音乐数据集上训练的模型。 midi 文件被转换成 numpy 数组。 由于 LSTM 需要顺序数据,因此在转换为 LSTM 的序列时,数据集的大小变得如此之大。

我根据基调和持续时间将 MIDI 音符转换为索引,因此我为 C4 键获得了 6 个类。 同样,我从 C3 到 B5,总共 288 节课以及休息时间的课。

单个 MIDI 的转换格式如下所示。

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

为了训练 LSTM,x 和 y 变为

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

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

x 和 y 中的值进一步转换为 one-hot 编码。 因此,对于 60 个小的中间文件,数据的大小变得很大,但我有 1700 个文件。 如何使用如此数量的文件训练模型。 我检查了 ImageGenerator 但它要求数据位于单独的类目录中。 如何实现这一目标?

您应该在训练过程中即时生成训练数据。 根据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团队本身不推荐的“旧”Keras(从 tensorflow 2.0 之前开始),则应改用fit_generator

model.fit_generator(generator, ...)

使用此解决方案,您只需将数据存储在内存中一次,不会因重叠序列而重复。

我为这个问题使用了一个生成器类,使用了以下代码。 发电机是为了我的目的而修改的。 内存使用量显着减少。

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM