我正在尝试创建在大型音乐数据集上经过训练的模型。 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中的值进一步转换为一热编码。 因此,仅60个中小型文件的数据大小就变得很大,但我有1700个文件。如何使用这么多的文件训练模型。我检查了ImageGenerator,但它要求数据位于单独的类目录中。如何实现呢?
答案 0 :(得分:3)
您应该在训练本身过程中即时生成训练数据。 基于tf documentation,您可以编写自己的生成器以用作训练数据,或从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(从tensorflow 2.0之前的版本开始) Keras团队本身不建议使用,则应改用fit_generator
:
model.fit_generator(generator, ...)
使用此解决方案,您只需将数据存储在内存中一次,就不会由于序列重叠而造成重复。
答案 1 :(得分:0)
我使用以下代码针对此问题使用了生成器类。发电机已针对我的目的进行了修改。内存使用量大大减少。
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)