音乐编码的螺旋损失函数

时间:2017-12-05 04:42:26

标签: deep-learning pytorch autoencoder music-notation

我正在尝试开发一种用于音乐生成的自动编码器;为了达到这个目的,我试图开发一种能够捕捉音乐关系的损失函数。

我目前的想法是' Spiral'损失函数,也就是说,如果系统在不同的八度音程中预测相同音符,则损失应小于音符错误时的损失。另外,接近正确音符的音符,例如B和D到C也应该有小的损失。人们可以在概念上将其视为找到线圈或螺旋上的两个点之间的距离,使得不同八度音中的相同音符位于与线圈相切的线上,但是被一些环距离隔开。

我在PyTorch工作,我的输入表示是36乘36 Tensor,其中行代表音符(MIDI范围48:84,钢琴的中间三个八度音程),列代表时间步长(1列= 1/100秒。矩阵中的值为0或1,表示在特定时间打开了一个音符。

这是我目前实施的损失:

def SpiralLoss():
    def spiral_loss(input, output):
        loss = Variable(torch.FloatTensor([0]))
        d = 5
        r = 10
        for i in xrange(input.size()[0]):
            for j in xrange(input.size()[3]):
                # take along the 1 axis because it's a column vector
                inval, inind = torch.max(input[i, :, :, j], 1)
                outval, outind = torch.max(output[i, :, :, j], 1)
                note_loss = (r*30*(inind%12 - outind%12)).float()
                octave_loss = (d*(inind/12 - outind/12)).float()
                loss += torch.sqrt(torch.pow(note_loss, 2) + torch.pow(octave_loss, 2))
        return loss
    return spiral_loss

这种损失的问题是最大功能不可区分。我想不出让这种损失可以区分的方法,并且想知道是否有人可能有任何想法或建议?

我不确定这个帖子是否适合这样的帖子,所以如果不是这样的话,我真的很感激任何指向更好位置的指示。

1 个答案:

答案 0 :(得分:1)

在这里采取最大值不仅因为可分性而存在问题:如果你只取最大输出值,而且它位于正确的位置,那么错误位置的略低值就不会受到惩罚。

一个粗略的想法是在输入和修改的输出矢量的差异上使用正常的L1或L2损失:输出可以乘以一些惩罚八度的重量掩模并且不同地记录差异,例如:< / p>

def create_mask(input_column):
    r = 10
    d = 5
    mask = torch.FloatTensor(input_column.size())
    _, max_ind = torch.max(input_column, 0)
    max_ind = int(max_ind[0])
    for i in range(mask.size(0)):
        mask[i] = r*abs(i-max_ind)%12 + d*abs(i-max_ind)/12
    return mask

这只是大致写的,不是准备好的东西,但理论上它应该完成这项工作。掩码矢量应设置为requires_grad=False,因为它是我们为每个输入计算的精确常量。因此,您可以在输入上使用最大值,但不要在输出上使用max

我希望它有所帮助!