TensorFlow LSTM 预测相同值

我想做的就是将一组数字输入到我的LSTM模型中,然后让LSTM模型输出它自己的数字列表。我的项目是一个程序,它从网上获取MIDI文件,将其转换成数字列表,从LSTM模型中获取新的数字列表,将这些新数字转换成MIDI,然后听这个文件。我遇到问题的地方是从LSTM模型中获取新的数字列表。

这是我目前的主要代码:

from midi_to_text import data_parsefrom split_sequence import split_sequenceimport py_midicsv as pmimport mathfrom numpy import asarrayfrom tensorflow.keras import Sequentialfrom tensorflow.keras.layers import *import tensorflow as tfraw_midi = pm.midi_to_csv('OnlineMidi.mid')data = data_parse(raw_midi)n_steps = 1X, 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='sigmoid', return_sequences=True))model.add(Dropout(0.2))model.add(LSTM(128, activation='sigmoid', 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=100, batch_size=32, verbose=2)notes = [64]song_length = 10for i in range(song_length):    prediction = model.predict(asarray(notes).reshape((-1, 1, 1)))    prediction[0][0] = (prediction[0][0] * 384) - (prediction[0][0] * 13) + 13    # 将0到1的浮点数转换回整数    notes.append(prediction[0][0])print(notes)

这是我用于创建训练集和标签的函数:

from numpy import asarraydef split_sequence(data, n_steps):    new_data, expected_values = list(), list()    for i in range(len(data)):        if n_steps + i <= len(data) - 1:            new_data.append(data[i:n_steps + i])            expected_values.append(data[n_steps + i])        else:            break    for i in new_data:        i[0] = (i[0] - 13) / (384 - 13)    for i in range(len(expected_values)):        expected_values[i] = (expected_values[i] - 13) / (384 - 13)    # 将值转换为0到1之间的浮点数    return asarray(new_data), asarray(expected_values)

当n_steps = 1时,这是x训练数据:

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

当n_steps = 1时,这是标签:

[76, 64, 75, 64, 76, 64, 75, 64, 76, 64, 71, 64, 74, 64, 72, 69, 64, 45, 64, 52, 64, 57, 64, 60, 64, 64, 64, 69, 71, 64, 40, 64, 52, 64, 56, 64, 64, 64,]

这是我的数据:

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

这是我的模型目前输出的,以64为种子的9个预测值的列表:

[64, 62.63686, 62.636864, 62.636864, 62.636864, 62.636864, 62.636864, 62.636864, 62.636864, 62.636864, 62.636864]

我不明白的是为什么这些预测值基本上都是相同的。当我在主代码的最后一个for循环中打印预测值时,我得到的输出是一个包含x个列表的列表,其中x是输入数据的数量。这是其中一个预测的例子:

[[62.500393] [62.500393] [62.500393] [62.500393] [62.500393] [62.500393] [62.500393] [62.500393] [62.500393] [62.500393]]

这就是为什么在那个for循环中,我只取第一个列表中的值作为预测。总结一下,我有一个程序,它接受一个数字列表,我希望LSTM模型输出一个以64为种子的预测数字列表。我遇到的问题是,我的模型不知为何每次都输出基本相同的预测值,所以我需要在这个预测过程中得到帮助。

**更新:**我尝试将model.fit()和model.predict()放在一个for循环中,并循环10次,看看会发生什么。好消息是:每次预测都与上次不同,这很好。坏消息是:这非常慢,我不确定这是不是最好的方法。有什么建议可以让这些值更接近预期值,或者这种方法是否可行?这似乎非常低效,因为我只是为了10个输出音符(实际上是5个,其余5个值是每个音符的持续时间)而重新训练模型10次。

这是使用这个for循环的新输出:

[64, 56.53626, 58.395187, 61.333992, 59.08212, 58.66997, 55.86058, 59.819744, 54.183216, 55.231224, 53.8824]

这是我的新代码,只是加了一个大for循环,其余部分相同:

from midi_to_text import data_parsefrom split_sequence import split_sequenceimport py_midicsv as pmimport mathfrom numpy import asarrayfrom tensorflow.keras import Sequentialfrom tensorflow.keras.layers import *import tensorflow as tfraw_midi = pm.midi_to_csv('OnlineMidi.mid')data = data_parse(raw_midi)n_steps = 1X, y = split_sequence(data, n_steps)print(X)print(y)X = X.reshape((X.shape[0], X.shape[1], 1))X = tf.cast(X, dtype='float32')notes = [64]model = Sequential()model.add(LSTM(256, activation='linear', return_sequences=True))model.add(Dropout(0.2))model.add(LSTM(128, activation='linear', return_sequences=True))model.add(LSTM(128))model.add(Dropout(0.2))model.add(Dense(1, activation='linear'))model.compile(optimizer='adam', loss='mse', metrics=['mae'])for i in range(10):    model.fit(X, y, epochs=5, batch_size=2, verbose=2)    prediction = model.predict(asarray(notes).reshape((-1, 1, 1)))    prediction[0][0] = (prediction[0][0] * 384) - (prediction[0][0] * 13) + 13    notes.append(prediction[0][0])print(notes)

自定义的midi_to_text数据解析器:

def data_parse(raw_midi):    temp = []    final = []    to_remove = []    shift_unit = 20    for i in range(len(raw_midi)):        temp.append(raw_midi[i].split(', '))    for i in range(len(temp)):        if temp[i][2] != 'Note_on_c':            to_remove.append(temp[i])        for i in to_remove:        temp.remove(i)        for i in temp:        i.remove(i[0])        i.remove(i[1])        i.remove(i[1])        i.remove(i[2])    for i in range(len(temp)):        if i == len(temp) - 1:            temp[i][0] = '64'        else:            temp[i][0] = str(int(temp[i + 1][0]) - int(temp[i][0]))                to_remove.clear()        for i in range(len(temp)):        if i == len(temp) - 1:            break        if temp[i + 1][0] == '0':            temp[i].append(temp[i + 1][1])            to_remove.append(temp[i + 1])        for i in to_remove:        temp.remove(i)    for i in temp:        for _ in i:            final.append(int(_))    return final

谢谢!!


回答:

我的结论是,尽管效率低下,但将model.fit和predict放入一个for循环中,以预测未来一步或一次生成一个信息是可行的。这意味着,是的,你确实需要多次拟合模型,输入它之前生成的数据,但我可以接受这种牺牲。这种方法确实有效,只是需要一些时间,这是我找到的主要解决方案。感谢所有回应的人,使所有步骤对我来说非常清晰,希望这个问题能帮助到其他人!

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注