Hello! I’m a total noob at machine-learning and have stumbled upon an issue with a model I’m training to recognize note-patterns in midifiles.
I managed to run the model on my notedata, but my turned back negative for all the epochs:
tensor(-0.6253, grad_fn=)
tensor(-0.6354, grad_fn=)
tensor(-0.6475, grad_fn=)
and my output from trying to generate a new melody from a seed of three values stagnates at one value:
[30.0, 63.0, 68.0, 82.4828075170517, 82.22588127851486, 82.24921894073486, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509, 82.24920380115509]
Why is my loss negative, and why does it stagnate at a prediction value so fast?
import os
from mido import MidiFile
import pandas as pd
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
class MidiFileCollection(object):
def __init__(self, path):
self.path = path
self.files = []
for filename in os.listdir(path):
self.files.append(MidiFile(path+filename))
def longestFile(self):
longest = 0
for index, file in enumerate(self.files):
if index == 0:
longest = file
else:
if file.getLength() > longest.getLength():
longest = file
return file
def shortestFile(self):
shortest = 1000000
for index, file in enumerate(self.files):
if index == 0:
shortest = file
else:
if file.getLength() < shortest.getLength():
shortest = file
return file
def mostEvents(self):
busiest = 0
tempCount = 0
for idx, file in enumerate(self.files):
if idx == 0:
busiest = file
else:
if len(file.notes()) > len(busiest.notes()):
busiest = file
return busiest
def get(self, index):
return self.files[index]
path = "pathToMidiFile"
collection = MidiFileCollection(path)
def interpolate(value, leftMin, leftMax, rightMin, rightMax):
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (float)
valueScaled = float(value - leftMin) / float(leftSpan)
# Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan)
class NotesDataSet(Dataset):
def __init__(self, midifile):
self.midifile = midifile
self.train = []
self.labels = []
notes = self.midifile.notes()
for index, note in enumerate(range(len(notes)-3)):
self.train.append([notes[index],notes[index+1],notes[index+2]])
self.labels.append(notes[index+3])
def __len__(self):
return len(self.train)
def __getitem__(self, idx):
current_sample = self.train[idx]
current_label = self.labels[idx]
return {
"sample": torch.tensor(current_sample),
"label": torch.tensor(interpolate(current_label, 0, 127, 0, 1))
}
notedata = NotesDataSet(collection.mostEvents())
trainset = DataLoader(notedata, batch_size=10, shuffle=False)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(3, 6)
self.fc2 = nn.Linear(6, 6)
self.fc3 = nn.Linear(6, 4)
self.fc4 = nn.Linear(4, 1)
def forward(self, x):
x = torch.sigmoid(self.fc1(x))
x = F.relu(self.fc2(x))
x = F.relu(self.fc3(x))
x = self.fc4(x)
return x
net = Net()
import torch.optim as optim
optimizer = optim.Adam(net.parameters(), lr=0.0001)
EPOCHS = 3
for epoch in range(EPOCHS):
for data in trainset:
sample = data["sample"]
label = data["label"].float()
net.zero_grad()
output = net(sample)
loss = F.nll_loss(output, label.long())
loss.backward()
optimizer.step()
print(loss)
seed = [46., 63., 53.]
for idx, i in enumerate(range(50)):
output = net(torch.tensor([seed[idx],seed[idx+1],seed[idx+2]]))
seed.append(interpolate(output[0].item(), 0, 1, 0, 127))
print(seed)