TensorFlow LSTM预测相同的值 [英] TensorFlow LSTM predicting same value

查看:95
本文介绍了TensorFlow LSTM预测相同的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要做的是向我的LSTM模型输入数字列表,然后让我的LSTM模型输出自己的数字列表.我的项目是一个程序,它获取在线MIDI文件,将其转换为数字列表,从LSTM获取新的数字列表,将这些新数字更改为MIDI,然后收听文件.我遇到问题的地方是从LSTM模型中获得新的数字列表.

What I want to do is input a list of numbers to my LSTM model, and have my LSTM model output its own list of numbers. My project is a program that takes an online MIDI file, converts it into a list of numbers, gets a new list of numbers from the LSTM, change those new numbers into MIDI, and then listen to the file. The place where I am running into an issue is where I get a new list of numbers from the LSTM model.

这是我目前拥有的主要代码:

Here is the main code that I currently have:

from midi_to_text import data_parse
from split_sequence import split_sequence
import py_midicsv as pm
import math
from numpy import asarray
from tensorflow.keras import Sequential
from tensorflow.keras.layers import *
import tensorflow as tf


raw_midi = pm.midi_to_csv('OnlineMidi.mid')
data = data_parse(raw_midi)

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='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 = 10

for 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
    # Turns float from 0 to 1 back into integer
    notes.append(prediction[0][0])

print(notes)

这是我创建训练集和标签的功能:

Here is my function for creating the training set and labels:

from numpy import asarray


def 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)
    # Turns values into float between 0 and 1
    return asarray(new_data), asarray(expected_values)

这是n_steps = 1时的x个训练数据.

This is the x training data when n_steps = 1:

[[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时的标签

This is the labels when 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个预测的列表:

This is what my model is currently outputting, a list of 9 predictions starting with the seed 64:

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

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

What I do not understand is why these predictions are all basically the same. When I print the prediction in the last for loop in my main code, I get an output of a list with x lists inside where x is the number of input data. Here is an example of one of these predictions:

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

这就是为什么在for循环中,我只是将列表中第一个列表的值用作预测.回顾一下,我有一个程序,该程序需要一个数字列表,我想让一个LSTM模型输出一个以种子64开头的预测数字列表.我遇到的问题是由于某种原因,我的模型是每次输出基本上相同的预测,因此在此预测过程中我需要帮助.

This is why in that for loop I just take the first list's value in the list as the prediction. To recap, I have a program that takes a list of numbers, and I want to have an LSTM model output a list of prediction numbers starting with the seed 64. The issue I am running into is that my model is, for some reason, outputting basically the same prediction every time, so I need help on this prediction process.

**更新:**我尝试将model.fit()和model.predict()放入for循环中,然后循环10次以查看发生了什么.好消息:每个预测都与上一个不同,这很好.坏消息:这非常慢,我不确定这是否是实现此目标的最佳方法.有什么建议可以使这些值更接近预期值,或者该方法是否还不错?这似乎效率很低,因为我仅对10个输出音符进行了10次再训练(实际上是5个,其他5个值是每个音符的持续时间).

**UPDATE: ** I tried putting the model.fit() and model.predict() in a for loop and just loop over that 10 times to see what happened. Good news: each prediction was different than the last and that is good. Bad news: It is very slow and I am not sure if this is the best way to go about this. Any advice for getting these values closer to expected values or if this method is even good? It seems highly ineffecient because I am retraining the model 10 times just for 10 output notes (its actually 5, the other 5 values are the duration for each note).

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

Here is my new output using this for loop:

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

这是我的新代码,只是有一个大的for循环而已:

Here is my new code, it is the same things just with a big for loop:

from midi_to_text import data_parse
from split_sequence import split_sequence
import py_midicsv as pm
import math
from numpy import asarray
from tensorflow.keras import Sequential
from tensorflow.keras.layers import *
import tensorflow as tf


raw_midi = pm.midi_to_csv('OnlineMidi.mid')
data = data_parse(raw_midi)

n_steps = 1
X, 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数据解析器:

Custom midi_to_text data parser:

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和预测放入for循环中,以预测未来的1步或生成1一次提供信息.这意味着,是的,您确实需要多次拟合模型,并将其先前生成的数据提供给模型,但这是我可以牺牲的.这种方法确实有效,只需要一些时间,并且是我发现的唯一主要解决方案.感谢所有做出答复的人,所有步骤对我来说都很清楚,希望这个问题对其他人有所帮助!

My conclusion is that although highly inefficient, to just put the model.fit and predict into a for loop to predict 1 step into the future or generate 1 piece of information at a time. This means that yes, you do have to fit the model a bunch of times, feeding it your previous data that it generated, but that is something that I could sacrifice. This method does work, just takes some time, and is the only main solution that I have found. Thanks to everyone who responded, making all of the steps really clear to me, hopefully this question helps someone else out there!

这篇关于TensorFlow LSTM预测相同的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆