Это из тех вещей, которые не дают мне уснуть по ночам. Этот ответ правильный (и чрезвычайно полезный!), но не полный, потому что он не объясняет большого различия между двумя подходами. . Мой ответ добавляет существенные дополнительные детали, но все еще не дает точных совпадений.
То, что происходит, сложно и лучше всего объясняется с помощью длинного блока кода ниже, который сравнивает librosa
и python_speech_features
с еще одним пакетом, torchaudio
.
Во-первых, обратите внимание, что реализация torchaudio имеет аргумент log_mels
, который по умолчанию (False) имитирует реализацию librosa, но если установлено True, будет имитировать python_speech_features. В обоих случаях результаты все еще неточные, но сходство очевидно.
Во-вторых, если вы погрузитесь в код реализации torchaudio, вы увидите примечание, что по умолчанию НЕ используется «реализация из учебника» (слова torchaudio, но я им доверяю), а предоставляется для совместимости с Librosa; ключевая операция в torchaudio, которая переключается с одного на другое:
mel_specgram = self.MelSpectrogram(waveform)
if self.log_mels:
log_offset = 1e-6
mel_specgram = torch.log(mel_specgram + log_offset)
else:
mel_specgram = self.amplitude_to_DB(mel_specgram)
В-третьих, вы вполне разумно задаетесь вопросом, сможете ли вы заставить librosa действовать правильно. Ответ - да (или, по крайней мере, «похоже на это»), если взять спектрограмму mel напрямую, взять ее навигационный журнал и использовать его, а не необработанные образцы, в качестве входных данных для функции librosa mfcc. Подробнее см. В приведенном ниже коде.
Наконец, будьте осторожны и если вы используете этот код, проверьте, что происходит, когда вы смотрите на различные функции. У 0-го элемента все еще есть серьезные необъяснимые смещения, а более высокие элементы имеют тенденцию дрейфовать друг от друга. Это может быть что-то столь же простое, как различные реализации под капотом или немного разные числовые константы стабильности, или это может быть что-то, что можно исправить с помощью точной настройки, например, выбор заполнения или, возможно, ссылка в каком-либо преобразовании децибел. Я правда не знаю.
Вот пример кода:
import librosa
import python_speech_features
import matplotlib.pyplot as plt
from scipy.signal.windows import hann
import torchaudio.transforms
import torch
n_mfcc = 13
n_mels = 40
n_fft = 512
hop_length = 160
fmin = 0
fmax = None
sr = 16000
melkwargs={"n_fft" : n_fft, "n_mels" : n_mels, "hop_length":hop_length, "f_min" : fmin, "f_max" : fmax}
y, sr = librosa.load(librosa.util.example_audio_file(), sr=sr, duration=5,offset=30)
# Default librosa with db mel scale
mfcc_lib_db = librosa.feature.mfcc(y=y, sr=sr, n_fft=n_fft,
n_mfcc=n_mfcc, n_mels=n_mels,
hop_length=hop_length,
fmin=fmin, fmax=fmax, htk=False)
# Nearly identical to above
# mfcc_lib_db = librosa.feature.mfcc(S=librosa.power_to_db(S), n_mfcc=n_mfcc, htk=False)
# Modified librosa with log mel scale (helper)
S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=n_mels, fmin=fmin,
fmax=fmax, hop_length=hop_length)
# Modified librosa with log mel scale
mfcc_lib_log = librosa.feature.mfcc(S=np.log(S+1e-6), n_mfcc=n_mfcc, htk=False)
# Python_speech_features
mfcc_speech = python_speech_features.mfcc(signal=y, samplerate=sr, winlen=n_fft / sr, winstep=hop_length / sr,
numcep=n_mfcc, nfilt=n_mels, nfft=n_fft, lowfreq=fmin, highfreq=fmax,
preemph=0.0, ceplifter=0, appendEnergy=False, winfunc=hann)
# Torchaudio 'textbook' log mel scale
mfcc_torch_log = torchaudio.transforms.MFCC(sample_rate=sr, n_mfcc=n_mfcc,
dct_type=2, norm='ortho', log_mels=True,
melkwargs=melkwargs)(torch.from_numpy(y))
# Torchaudio 'librosa compatible' default dB mel scale
mfcc_torch_db = torchaudio.transforms.MFCC(sample_rate=sr, n_mfcc=n_mfcc,
dct_type=2, norm='ortho', log_mels=False,
melkwargs=melkwargs)(torch.from_numpy(y))
feature = 1 # <-------- Play with this!!
plt.subplot(2, 1, 1)
plt.plot(mfcc_lib_log.T[:,feature], 'k')
plt.plot(mfcc_lib_db.T[:,feature], 'b')
plt.plot(mfcc_speech[:,feature], 'r')
plt.plot(mfcc_torch_log.T[:,feature], 'c')
plt.plot(mfcc_torch_db.T[:,feature], 'g')
plt.grid()
plt.subplot(2, 2, 3)
plt.plot(mfcc_lib_log.T[:,feature], 'k')
plt.plot(mfcc_torch_log.T[:,feature], 'c')
plt.plot(mfcc_speech[:,feature], 'r')
plt.grid()
plt.subplot(2, 2, 4)
plt.plot(mfcc_lib_db.T[:,feature], 'b')
plt.plot(mfcc_torch_db.T[:,feature], 'g')
plt.grid()
Честно говоря, ни одна из этих реализаций не удовлетворяет:
Python_speech_features использует необъяснимо причудливый подход, заключающийся в замене 0-й функции энергией, а не ее дополнением, и не имеет обычно используемой дельта-реализации.
Librosa по умолчанию нестандартна, без предупреждений и не имеет очевидного способа увеличения энергии, но имеет очень компетентную дельта-функцию в другом месте библиотеки.
Torchaudio будет имитировать и то, и другое, также имеет универсальную дельта-функцию, но по-прежнему не имеет чистого, очевидного способа получения энергии.
![введите описание изображения здесь](https://i.stack.imgur.com/uW9d7.png)
person
Novak
schedule
31.03.2020
samplerate=sr
? Или поменятьdct_type
в версии librosa? - person Hendrik   schedule 02.03.2020sr
в качестве входных данных. Что касаетсяdct_type
, есть некоторые изменения, когда я установил значение 3, но все еще очень далеко от выходов psf (1 и 2 почти идентичны). - person TYZ   schedule 02.03.2020samplerate=sr
? - ›Я имел в виду, что вы передаете его как позиционный аргумент, но это аргумент ключевого слова. Не уверен, если передача его в качестве аргумента kwarg имеет значение здесь, но я бы придерживался (явного) API. - person Hendrik   schedule 02.03.2020