TensorFlow LSTM 长度输出

TensorFlow LSTM length output

所以基本上我有一个 LSTM 模型,它接收一堆数字(这些数字实际上是我变成数字的音符。如果你想知道的话,我的目标是创建计算机生成的音乐)。我 运行 遇到的问题是我不知道如何进行预测。我希望计算机输出的是一个数字列表(或字符串或任何可能的数字),这些数字遵循它在训练过程中提出的任何规则。在以前的项目中,我只知道如何输出 1 个预测数字,给计算机一些数据来预测,但我想要一个全新的列表而不给计算机一个起始值。最好电脑一次可以生成1个以上的号码。

这是我目前拥有的代码。它现在不起作用:

n_steps = 1
X, y = split_sequence(data, n_steps)
X = X.reshape((X.shape[0], X.shape[1], 1))
X = tf.cast(X, dtype='float32')

model = Sequential()
model.add(LSTM(256, activation='relu', return_sequences=True))
#model.add(Dropout(0.2)) # I am not sure what this is, but it doesn't break my code
model.add(LSTM(128, activation='relu', return_sequences=True))
#model.add(Dropout(0.2))
model.add(LSTM(128))
#model.add(Dropout(0.2))
model.add(Dense(1, activation='linear'))
model.compile(optimizer='adam', loss='mse', metrics=['mae'])

model.fit(X, y, epochs=10, batch_size=2, verbose=2)


prediction = model.predict(X) # I want to output a list of numbers
print(prediction)

现在,我的预测正在输出一个非常长的列表列表,其中包含我认为是唯一预测的相同值。它看起来像这样:

[[62.449333]
 [62.449333]
 [62.449333]
 ...
 [62.449333]
 [62.449333]
 [62.449333]]

我想要一个不是预测的列表,而更像是一个全新数字列表的 GAN 输出。另外,我不确定为什么这个预测会输出一个很长的列表列表。

数据看起来像这样,为简洁起见,它被缩短了:

[64, 76, 64, 75, 64, 76, 64, 75, 64, 76, 64, 71, 64, 74, 64, 72, 69, 64, 45, 64, 52]

当 n_steps = 1 时,x 列看起来像这样:

[[64], [76], [64], [75], [64], [76], [64], [75], [64], [76], [64], [71], [64], [74]]

y 看起来像这样,每个都是对应 x 序列的预期输出:

[76, 64, 75, 64, 76, 64, 75, 64, 76, 64, 71, 64, 74, 64]

任何帮助将不胜感激!!

我的理解是 1) 您想要输出不同预测的列表(即您担心每个预测都采用相同的值)。 2) 你想要一个浮点数列表而不是包含浮点数的列表列表。

向后工作:

2,当使用神经网络和 model.predict() 进行预测时,它会在输入多个 x_test 样本时输出一个列表数组 - 这可以通过使用 ndarray.flatten() 轻松解决,因此在您的案例:prediction = model.predict(X).flatten()

1,我首先会调查您是否正确地重塑了输入数据。 LSTM 模型将 3D 数据作为输入,因此需要一个 3D 数组,其形式为 (sequence, timestep, feature):

序列,是数据集中的序列总数(或observations/samples)

时间步长,对应于你序列的大小

特征,是一个时间步长的观测数(/变量数)

因此您只为每个时间步定义了一个特征。如果是这种情况,你正在喂它(x.shape[0] 个样本,序列中有 x.shape[1] 个时间步长,只有 1 个 feature/variable) - 是这个你的意图?获取有关正在使用的数据的更多信息会很有帮助,即特征数量和所需的 window 序列大小。

我认为你的模型结构很好,但数据需要一些工作。您的 LSTM 仅设置为输出 1 个值,您可以看到最后一个 LSTM 层没有 return_sequences=True。您的 y 标签有多个值这一事实一定会混淆模型。

我认为你应该保持这种行为,但按如下方式编辑你的 input/output 数据:

如果您的数据中有一个序列是:

[64, 76, 64, 75, 64, 76, 64, 75, 64, 76, 64, 71, 64, 74, 64, 72, 69, 64, 45, 64, 52]

那么你的训练样本和标签应该是:

x[0] = [64]
y[1] = [76]

x[1] = [64, 76]
y[1] = [64]

x[2] = [64, 76, 64]
y[2] = [75]

序列的每一步都可以是一个单独的训练示例,但每个 y 标签只能是一个输出。

您的线性输出可以工作,但我认为这可能更适合作为具有 softmax 输出的分类问题。最后的密集层应该有你的模型可以输出的可能音符的数量。您还必须用 0 值填充这些序列,以便所有 x 输入值的长度相同,因此 x 值实际上是:

x[0] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64]
x[1] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 75]

等数组的长度是你的最大序列长度。

在预测时,使用循环。您将给模型一个单值输入序列,然后将预测的音符附加到输入序列并再次将其反馈给模型:

seed_note = [64] # initial note to give the model
next_notes = 10 # how many notes to predict

for _ in range(next_notes):
    token_list = pad_sequences(seed_note, maxlen=max_sequence_len, padding='pre') # pad sequence with 0s
    predicted = np.argmax(model.predict(token_list), axis=-1) # get best prediction for next note
    seed_note += [predicted]
    
print(seed_text)