keras:如何将帧级预测聚合到歌曲级预测
keras: how to aggregate over frame-level predictions to song-level prediction
我正在做歌曲流派分类。对于每首歌曲,我将它们切成小帧 (5s) 以生成频谱图作为神经网络的输入特征,并且每个帧都有一个相关的歌曲流派标签。
数据如下所示:
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 获得每一帧的预测精度。但是目前,我不知道如何通过多数投票将帧级到歌曲级的预测结果聚合起来,因为当数据输入 keras 模型时,它们的名字丢失了。
如何在 keras 输出中保留每个标签的名称(例如,song_i_frame1)以通过多数投票形成对歌曲的聚合预测。或者,还有其他聚合到歌曲级预测的方法吗???
我四处搜索,但找不到答案,非常感谢任何见解。
在数据集中,每个标签都可能被命名(例如:'rock'
)。要将其用于神经网络,需要将其转换为整数(例如:2
),然后再转换为单热编码(例如:[0,0,1]
)。所以'rock' == 2 == [0,0,1]
。您的输出预测将采用这种单热编码形式。 [ 0.1, 0.1, 0.9 ] 表示 class 2 被预测, [ 0.9, 0.1, 0.1 ] 表示 class 0 等。
要以可逆的方式执行此操作,请使用 sklearn.preprocessing.LabelBinarizer.
有多种方法可以将帧预测组合成整体预测。最常见的是,按照复杂性递增的顺序:
- 多数投票概率
- Mean/average 投票概率
- 平均对数概率
- 概率对数概率的序列模型
- 多实例学习
下面是前三个的例子。
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']
对平均概率的一个简单改进是计算概率的对数(log-odds)并将其平均。这更恰当地说明了很可能或不太可能发生的事情。它可以看作是一个朴素贝叶斯,在假设帧是独立的情况下计算后验概率。
人们还可以使用在逐帧预测上训练的 classifier 来执行投票,尽管这并不常见,并且在输入长度变化时会很复杂。可以使用简单的序列模型,即递归神经网络(RNN)或隐马尔可夫模型(HMM)。
另一种选择是在基于帧的 class 化上使用 ,一次学习整首歌曲。
我正在做歌曲流派分类。对于每首歌曲,我将它们切成小帧 (5s) 以生成频谱图作为神经网络的输入特征,并且每个帧都有一个相关的歌曲流派标签。
数据如下所示:
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 获得每一帧的预测精度。但是目前,我不知道如何通过多数投票将帧级到歌曲级的预测结果聚合起来,因为当数据输入 keras 模型时,它们的名字丢失了。
如何在 keras 输出中保留每个标签的名称(例如,song_i_frame1)以通过多数投票形成对歌曲的聚合预测。或者,还有其他聚合到歌曲级预测的方法吗???
我四处搜索,但找不到答案,非常感谢任何见解。
在数据集中,每个标签都可能被命名(例如:'rock'
)。要将其用于神经网络,需要将其转换为整数(例如:2
),然后再转换为单热编码(例如:[0,0,1]
)。所以'rock' == 2 == [0,0,1]
。您的输出预测将采用这种单热编码形式。 [ 0.1, 0.1, 0.9 ] 表示 class 2 被预测, [ 0.9, 0.1, 0.1 ] 表示 class 0 等。
要以可逆的方式执行此操作,请使用 sklearn.preprocessing.LabelBinarizer.
有多种方法可以将帧预测组合成整体预测。最常见的是,按照复杂性递增的顺序:
- 多数投票概率
- Mean/average 投票概率
- 平均对数概率
- 概率对数概率的序列模型
- 多实例学习
下面是前三个的例子。
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']
对平均概率的一个简单改进是计算概率的对数(log-odds)并将其平均。这更恰当地说明了很可能或不太可能发生的事情。它可以看作是一个朴素贝叶斯,在假设帧是独立的情况下计算后验概率。
人们还可以使用在逐帧预测上训练的 classifier 来执行投票,尽管这并不常见,并且在输入长度变化时会很复杂。可以使用简单的序列模型,即递归神经网络(RNN)或隐马尔可夫模型(HMM)。
另一种选择是在基于帧的 class 化上使用