【问题标题】:keras: how to aggregate over frame-level predictions to song-level predictionkeras:如何将帧级预测聚合到歌曲级预测
【发布时间】:2019-05-20 14:50:00
【问题描述】:

我正在做歌曲流派分类。对于每首歌曲,我将它们切成小帧(5 秒)以生成频谱图作为神经网络的输入特征,并且每一帧都有一个相关的歌曲流派标签。

数据如下所示:

   name         label   feature
   ....
   song_i_frame1 label   feature_vector_frame1
   song_i_frame2 label   feature_vector_frame2
   ...
   song_i_framek label   feature_vector_framek
   ...

我可以毫无问题地从 Keras 获得每一帧的预测精度。但目前,我不知道如何通过多数投票将预测结果从帧级别聚合到歌曲级别,因为数据输入 when keras 模型时,它们的名称会丢失。

如何在 keras 输出中保留每个标签的名称(例如,song_i_frame1),以通过多数投票形成对歌曲的聚合预测。或者,有没有其他方法可以聚合到歌曲级别的预测???

我在 Google 上四处搜索,但找不到答案,如果有任何见解,我将不胜感激。

【问题讨论】:

  • 每首歌都是你的原创标签吗?然后每一帧都从它所属的歌曲中获取标签?
  • 是的。每个帧都从它所属的歌曲中获取标签,我想找到一种方法将这些预测聚合到歌曲级别

标签: python tensorflow keras deep-learning audio-processing


【解决方案1】:

在数据集中,每个标签都可能被命名(例如:'rock')。要将其与神经网络一起使用,需要将其转换为整数(例如:2),然后转换为单热编码(例如:[0,0,1])。所以'rock' == 2 == [0,0,1]。您的输出预测将采用这种单热编码形式。 [ 0.1, 0.1, 0.9 ] 表示预测了第 2 类,[ 0.9, 0.1, 0.1 ] 表示第 0 类等。 要以可逆方式执行此操作,请使用sklearn.preprocessing.LabelBinarizer

有几种方法可以将帧预测组合成整体预测。最常见的是,按照复杂性递增的顺序:

  • 对概率的多数投票
  • 对概率的平均/平均投票
  • 对概率的对数赔率进行平均
  • 概率对数概率的序列模型
  • 多实例学习

以下是前三个的示例。

import numpy
from sklearn.preprocessing import LabelBinarizer

labels = [ 'rock', 'jazz', 'blues', 'metal' ] 

binarizer = LabelBinarizer()
y = binarizer.fit_transform(labels)

print('labels\n', '\n'.join(labels))
print('y\n', y)

# Outputs from frame-based classifier. 
# input would be all the frames in one song
# frame_predictions = model.predict(frames)
frame_predictions = numpy.array([
    [ 0.5, 0.2, 0.3, 0.9 ],
    [ 0.9, 0.2, 0.3, 0.3 ],
    [ 0.5, 0.2, 0.3, 0.7 ],
    [ 0.1, 0.2, 0.3, 0.5 ],
    [ 0.9, 0.2, 0.3, 0.4 ],
])

def vote_majority(p):
    voted = numpy.bincount(numpy.argmax(p, axis=1))
    normalized = voted / p.shape[0]
    return normalized

def vote_average(p):
    return numpy.mean(p, axis=0)

def vote_average_logits(p):
    logits = numpy.log(p / (1 - p))
    avg = numpy.mean(logits, axis=1)
    p = 1/(1+ numpy.exp(-avg))
    return p


maj = vote_majority(frame_predictions)
mean = vote_average(frame_predictions)
mean_logits = vote_average_logits(frame_predictions)

genre_maj = binarizer.inverse_transform(numpy.array([maj]))
genre_mean = binarizer.inverse_transform(numpy.array([mean]))
genre_mean_logits = binarizer.inverse_transform(numpy.array([mean_logits]))
print('majority voting', maj, genre_maj)
print('mean voting', mean, genre_mean)
print('mean logits voting', mean_logits, genre_mean_logits)

输出

labels:
 rock
 jazz
 blues
 metal
y:
 [[0 0 0 1]
 [0 1 0 0]
 [1 0 0 0]
 [0 0 1 0]]
majority voting: [0.4 0.  0.  0.6] ['rock']
mean voting: [0.58 0.2  0.3  0.56] ['blues']
mean logits voting [0.49772704 0.44499443 0.41421356 0.24829914 0.4724135 ] ['blues']

对平均概率的一个简单改进是计算概率的 logits(log-odds)并将其平均。这更恰当地解释了很可能或不太可能发生的事情。它可以看作是一个朴素贝叶斯,在帧是独立的假设下计算后验概率。

也可以通过使用在逐帧预测上训练的分类器来执行投票,尽管这并不常见,并且当输入长度变化时会很复杂。可以使用简单的序列模型,即循环神经网络 (RNN) 或隐马尔可夫模型 (HMM)。

另一种选择是在基于帧的分类上使用Multiple-Instance-Learning with GlobalAveragePooling,一次性学习整首歌曲。

【讨论】:

  • 谢谢!但我仍然有一个困惑,我想让损失函数最小化每首歌的聚合预测(例如,通过多数投票),而不是帧级别的损失。这是多实例学习的案例吗?
  • 是的,这将是多实例学习!打开一个关于它的新问题,在这里链接,我会回答它:)
  • 谢谢!另一个问题在那边:stackoverflow.com/questions/55272508/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
  • 2017-01-01
  • 1970-01-01
  • 2023-03-26
  • 2021-12-13
  • 2021-10-06
  • 1970-01-01
相关资源
最近更新 更多