对于初学者的一些观察:
- 您的样本可能太少,无法有效使用神经网络。使用一个简单的算法作为初学者很好地了解您的模型是如何进行预测的。
- 确保您有足够的(30% 或更多)来自不同扬声器的样本用于最终测试。您只能使用此测试集一次,因此请考虑构建一个管道来生成训练集、验证集和测试集。确保不要将同一个扬声器放入 1 套以上。
-
librosa 的第一个系数为您提供了 AFAIK 偏移量。我建议绘制您的特征与标签的相关性以及它们重叠的距离,我猜有些可能很容易混淆。查找是否有任何功能可以区分您的课程。不要通过运行模型来做到这一点,先进行目视检查。
到实际功能!您认为音高应该发挥至关重要的作用是正确的。我建议您查看aubio - 它具有 Python 绑定。
Yaafe 还提供出色的功能选择。
您可能很容易就拥有 150 多个功能。您可能希望减少问题的维度,甚至可能将其压缩为 2d 并查看是否可以以某种方式分离这些类。 Here 是我自己的 Dash 示例。
最后但同样重要的是,一些从音频中提取频率的基本代码。在这种情况下,我还试图找到三个峰值频率。
import numpy as np
def spectral_statistics(y: np.ndarray, fs: int, lowcut: int = 0) -> dict:
"""
Compute selected statistical properties of spectrum
:param y: 1-d signsl
:param fs: sampling frequency [Hz]
:param lowcut: lowest frequency [Hz]
:return: spectral features (dict)
"""
spec = np.abs(np.fft.rfft(y))
freq = np.fft.rfftfreq(len(y), d=1 / fs)
idx = int(lowcut / fs * len(freq) * 2)
spec = np.abs(spec[idx:])
freq = freq[idx:]
amp = spec / spec.sum()
mean = (freq * amp).sum()
sd = np.sqrt(np.sum(amp * ((freq - mean) ** 2)))
amp_cumsum = np.cumsum(amp)
median = freq[len(amp_cumsum[amp_cumsum <= 0.5]) + 1]
mode = freq[amp.argmax()]
Q25 = freq[len(amp_cumsum[amp_cumsum <= 0.25]) + 1]
Q75 = freq[len(amp_cumsum[amp_cumsum <= 0.75]) + 1]
IQR = Q75 - Q25
z = amp - amp.mean()
w = amp.std()
skew = ((z ** 3).sum() / (len(spec) - 1)) / w ** 3
kurt = ((z ** 4).sum() / (len(spec) - 1)) / w ** 4
top_peaks_ordered_by_power = {'stat_freq_peak_by_power_1': 0, 'stat_freq_peak_by_power_2': 0, 'stat_freq_peak_by_power_3': 0}
top_peaks_ordered_by_order = {'stat_freq_peak_by_order_1': 0, 'stat_freq_peak_by_order_2': 0, 'stat_freq_peak_by_order_3': 0}
amp_smooth = signal.medfilt(amp, kernel_size=15)
peaks, height_d = signal.find_peaks(amp_smooth, distance=100, height=0.002)
if peaks.size != 0:
peak_f = freq[peaks]
for peak, peak_name in zip(peak_f, top_peaks_ordered_by_order.keys()):
top_peaks_ordered_by_order[peak_name] = peak
idx_three_top_peaks = height_d['peak_heights'].argsort()[-3:][::-1]
top_3_freq = peak_f[idx_three_top_peaks]
for peak, peak_name in zip(top_3_freq, top_peaks_ordered_by_power.keys()):
top_peaks_ordered_by_power[peak_name] = peak
specprops = {
'stat_mean': mean,
'stat_sd': sd,
'stat_median': median,
'stat_mode': mode,
'stat_Q25': Q25,
'stat_Q75': Q75,
'stat_IQR': IQR,
'stat_skew': skew,
'stat_kurt': kurt
}
specprops.update(top_peaks_ordered_by_power)
specprops.update(top_peaks_ordered_by_order)
return specprops