pyFDN.train.losses package#
Submodules#
pyFDN.train.losses.base module#
The two loss families, and how they compose.
A training objective is a weighted sum of losses, built with + and *:
loss = pyFDN.FlatMagnitude() + 0.2 * pyFDN.Sparsity(A)
Losses come in two families, distinguished by what they read:
ResponseLoss– a function of the model’s impulse response (Response).ParameterLoss– a function of one model parameter, referenced by aParamRefit holds.
Both are called with the response, so the trainer needs no special case; a parameter loss simply ignores it.
- class pyFDN.train.losses.base.Loss[source]#
Bases:
ABCBase class for training losses. Combine with
+and scale with*.- check(model)[source]#
Preflight against the model it will train, before the first step.
Override to reject or warn about a model this loss cannot be fit on – raising here beats a silently useless optimization run. Most losses place no demands on the model, hence the no-op default.
- Return type:
- property name: str#
Short label, used as the key in
pyFDN.TrainLog.loss_log.
- class pyFDN.train.losses.base.ParameterLoss(ref)[source]#
Bases:
LossA loss on one model parameter, referenced by
ref.Implement
penalty(); the response argument is ignored.- property name: str#
Short label, used as the key in
pyFDN.TrainLog.loss_log.
- class pyFDN.train.losses.base.ResponseLoss[source]#
Bases:
LossA loss on the impulse response. Implement
__call__().
- class pyFDN.train.losses.base.Scaled(weight, loss)[source]#
Bases:
Lossweight * loss. Built byLoss.__mul__(), rarely by hand.- check(model)[source]#
Preflight against the model it will train, before the first step.
Override to reject or warn about a model this loss cannot be fit on – raising here beats a silently useless optimization run. Most losses place no demands on the model, hence the no-op default.
- Return type:
- property name: str#
Short label, used as the key in
pyFDN.TrainLog.loss_log.
- class pyFDN.train.losses.base.Sum(losses)[source]#
Bases:
LossA sum of losses. Built by
Loss.__add__(), rarely by hand.- check(model)[source]#
Preflight against the model it will train, before the first step.
Override to reject or warn about a model this loss cannot be fit on – raising here beats a silently useless optimization run. Most losses place no demands on the model, hence the no-op default.
- Return type:
- property name: str#
Short label, used as the key in
pyFDN.TrainLog.loss_log.
pyFDN.train.losses.distances module#
- class pyFDN.train.losses.distances.AbsoluteError[source]#
Bases:
DistanceL1: Elementwise absolute difference: |pred - target|.
- class pyFDN.train.losses.distances.CircularDistance[source]#
Bases:
DistanceCircular angular metric: 1 - cos(pred - target) bounded in [0, 2].
- class pyFDN.train.losses.distances.CompressedEnergyDistance(power=0.5, floor_db=-100.0)[source]#
Bases:
DistanceReference-normalized, compressed squared error per cumulation direction.
Each
(direction, channel, freq, frame)surface is normalized by the reference’s total energy (one constant per direction, so relative levels between paths survive) and compressed withpowerabove afloor_dbfloor before comparing.
- class pyFDN.train.losses.distances.ConstantTargetDistance(target_value)[source]#
Bases:
DistanceSquared error of
predagainst a constant (ignores the reference).For the targetless losses that fit to a constant rather than a reference IR, e.g.
FlatMagnitude(|H| = target) andFlatSpectrogram(normalized spectra equal to 1).
- class pyFDN.train.losses.distances.Distance[source]#
Bases:
ABCBase class for pairwise element comparison metrics.
- class pyFDN.train.losses.distances.FlatnessRatioDistance(target_flatness=None)[source]#
Bases:
DistanceSquared error of the spectral flatness, per channel.
The flatness of a magnitude spectrum \(|H|\) over its frequency axis (dim 0) is the ratio of its geometric to its arithmetic mean,
\[F = \frac{\exp\big(\overline{\log |H|}\big)}{\overline{|H|}},\]1 for a perfectly flat spectrum and towards 0 for a peaky one. A silent spectrum (arithmetic mean at the numerical floor) has flatness 0, so it is never mistaken for a flat one.
- class pyFDN.train.losses.distances.MaskedSquaredError(floor_db=-45.0)[source]#
Bases:
DistanceSquared error over the entries where the reference is above
floor_db.The mask follows the reference, so only the part of the curve carrying signal counts; entries below the floor (noise) are ignored. Returns the masked entries only, as a 1-D tensor, so any plain reduction (e.g.
Rms) averages over them alone.
- class pyFDN.train.losses.distances.RelativeError(p=1.0)[source]#
Bases:
DistanceElementwise \(|pred - target|^p\) over the reference’s mean \(|target|^p\).
Followed by
Meanthis is the normalized \(L^p\) error \(\overline{|pred - target|^p} / \overline{|target|^p}\), a scale-free number whatever the feature’s units.
pyFDN.train.losses.features module#
- class pyFDN.train.losses.features.CumulativeEnergySurface(window=1024, hop=None, directions=('descending',))[source]#
Bases:
FeatureDoubly-cumulated short-time power, one surface per direction.
Power is integrated backwards in time, then along frequency in each of
directions("descending"and/or"ascending"). Returns a(n_directions, n_channels, n_freq, n_frames)tensor.
- class pyFDN.train.losses.features.EchoDensityProfile(win_duration=0.02, hop=None, kappa=(100.0, 100000.0))[source]#
Bases:
FeatureDifferentiable normalized echo density profile (Abel & Huang).
In a Hann window of
win_durationseconds around each analysis point, the fraction of samples whose magnitude exceeds the window’s weighted RMS \(\sigma\), normalized by \(\operatorname{erfc}(1/\sqrt{2})\), the fraction expected of Gaussian noise – so the profile reaches about 1 once the reverberation is diffuse. The hard threshold is replaced by \(\operatorname{sigmoid}(\kappa(|h| - \sigma))\) so gradients flow; \(\kappa\) rises linearly fromkappa[0]tokappa[1]over the response, to stay sharp as the decaying signal gets smaller.\(\kappa\) acts on absolute amplitude, so the profile depends on level: below about -60 dB the sigmoid softens and the profile reads high (noise at -80 dB gives about 1.16). Compare responses normalized to the same level.
Returns a
(n_channels, n_frames)tensor, one point everyhopsamples.
- class pyFDN.train.losses.features.EnergyDecayCurve(window=4096, hop=None, bands=None)[source]#
Bases:
FeatureOctave-band normalized Schroeder decay curves in dB.
Short-time power per octave band, backward-integrated (Schroeder) and normalized to each band’s own value at
t=0.
- class pyFDN.train.losses.features.Feature[source]#
Bases:
ABCBase class for extracting a representation from an impulse response.
- class pyFDN.train.losses.features.Magnitude(channels='none')[source]#
Bases:
FeatureFrequency-domain magnitude spectrum via rfft.
- class pyFDN.train.losses.features.MelEnergyDecayRelief(n_fft=512, win_length=256, hop_length=128, n_mels=64, top_db=80.0)[source]#
Bases:
FeatureMel-band energy decay relief in dB, one relief per channel.
The mel power spectrogram (
torchaudio’sMelSpectrogram, power 2), backward-integrated over frames (Schroeder) and converted to dB with a floortop_dbbelow the maximum over all channels (astorchaudio’sAmplitudeToDB). Returns a(n_channels, n_mels, n_frames)tensor.
- class pyFDN.train.losses.features.MelMagnitude(n_mels=128, f_min=0.0, f_max=None, channels='none')[source]#
Bases:
FeatureMel-scaled magnitude spectrum via rfft + triangular filterbank.
Both the time-domain waveform and frequency-domain magnitude are computed via FFT and reduced to
n_melsmel bands usingtorchaudio’s triangular mel filterbank, weighting the fit towards low frequencies where mel spacing is finer.- Parameters:
n_mels (
int) – Number of mel bands.f_min (
float) – Mel filterbank frequency range in Hz.f_maxdefaults to Nyquist.f_max (
float|None) – Mel filterbank frequency range in Hz.f_maxdefaults to Nyquist.channels (
str) – How the output channels are combined."none"(default) keeps each input/output pair separate.
- class pyFDN.train.losses.features.PeakEnvelope(release_time=0.00028)[source]#
Bases:
FeatureSmoothed peak envelope of the squared response, one per channel.
A peak follower on \(h^2\), \(a[n] = \max(h[n]^2, \alpha\, a[n-1])\) with \(\alpha = e^{-1/(f_s T)}\) for a release time \(T\), then zero-phase low-pass filtered (a least-squares FIR, passband to 3.2 kHz, stopband from 4.8 kHz, about 1 ms long at any rate) and floored at zero. Returns a
(n_channels, n_samples)tensor.
- class pyFDN.train.losses.features.Phase(channels='none')[source]#
Bases:
FeatureFrequency-domain phase spectrum via rfft, in \((-\pi, \pi]\).
With
channels="sum"or"mean"the complex spectra of the output channels are combined first and the phase is taken of the result, i.e. the phase of the summed response (the phase of the mean is the same). Summing the phase angles themselves would not be the phase of anything.The whole-response phase of a reverberant IR varies extremely fast with frequency and is undefined where the magnitude vanishes, yet every bin counts equally; a phase loss built on it is best reserved for short or early responses.
- class pyFDN.train.losses.features.PhaseSpectrogramFeature(nfft=(256, 512, 1024, 2048), overlap=0.75)[source]#
Bases:
FeatureMulti-resolution STFT phase (circular distance ready).
For each window size, extracts STFT phase and stacks across windows.
- class pyFDN.train.losses.features.SpectrogramFeature(nfft=(256, 512, 1024, 2048), overlap=0.75)[source]#
Bases:
FeatureMulti-resolution Welch spectrogram (smoothed magnitude across windows).
For each window size in
nfft, computes the STFT magnitude, averages over frames (Welch estimate), normalizes by per-frequency mean, and returns. This feature is resolution-independent (unlike single-FFT magnitude).
pyFDN.train.losses.match module#
- class pyFDN.train.losses.match.Match(target, feature, distance=<pyFDN.train.losses.distances.SquaredError object>, reduction=<pyFDN.train.losses.reductions.Mean object>)[source]#
Bases:
ResponseLossCompares a model’s impulse response to a target using three steps:
1. Feature: Extracts representations from both the model response and the target (e.g., raw waveform, magnitude spectrum, or phase). 2. Distance: Computes the differences between the extracted features (e.g., squared error or circular phase difference). 3. Reduction: Aggregates the elementwise differences into a scalar loss tensor (e.g., mean or sum).
The reference target is aligned in length, shape, device, and dtype using
_CachedTarget, and its feature is computed once and cached until the loss is called on a response of a different shape, device, dtype or sample rate.Without a target (
target=None) the distance is called with an all-zeros tensor in place of the reference feature; targetless losses use a distance that compares against a constant of its own and ignores it.- Parameters:
target (
Any|None) – Reference impulse response (NumPy array, PyTorch tensor, or list), or None.feature (
Feature|Callable[[Tensor,float],Tensor]) – Extracts the representation to compare:(h, fs) -> torch.Tensor.distance (
Distance|Callable[[Tensor,Tensor],Tensor]) – Calculates error between two features:(pred, target) -> torch.Tensor.reduction (
Reduction|Callable[[Tensor],Tensor]) – Turns the error tensor into a single scalar:(diff) -> torch.Tensor.
pyFDN.train.losses.parameter module#
Costs on a model parameter, rather than on its response.
Each takes a ParamRef naming the parameter it acts
on, so it works on any FDN structure:
A = pyFDN.param(model, "feedback")
loss = pyFDN.FlatMagnitude() + 0.2 * pyFDN.Sparsity(A)
- class pyFDN.train.losses.parameter.L1(ref)[source]#
Bases:
ParameterLossMean absolute value of a parameter – pushes it toward sparse.
- class pyFDN.train.losses.parameter.L2(ref)[source]#
Bases:
ParameterLossMean squared value of a parameter – plain weight decay.
- class pyFDN.train.losses.parameter.Sparsity(ref)[source]#
Bases:
ParameterLossDensity penalty on a square mixing matrix, after Optimizing Tiny Colorless FDNs (Dal Santo et al.).
Rewards a dense matrix – 0 when \(|A|\) is maximally dense (its entries all \(1/\sqrt{N}\), i.e. best mixing) and 1 when fully sparse. Registered with a positive weight it therefore pushes the feedback matrix away from the sparse, poorly-mixing corners of SO(N) that a magnitude-only objective is otherwise happy to sit in.
- Parameters:
ref (
ParamRef) – The matrix to penalize, e.g.pyFDN.param(model, "feedback"). Must be square.
pyFDN.train.losses.reductions module#
- class pyFDN.train.losses.reductions.MeanPerGroup(feature=None)[source]#
Bases:
ReductionMean averaged per first-dimension group, then across groups.
Each group is normalized by its actual element count, giving equal weight to each group regardless of its size (unlike
Mean()which weights by total element count).Multi-resolution features (
SpectrogramFeature,PhaseSpectrogramFeature) pad every resolution to a common shape and record each resolution’s number of real (unpadded) entries in_group_countson every call. Pass that feature here so each group is divided by its real count; the padding must then contribute zero distance (it does for the distances those features are used with). Without such a feature, each group is averaged over its full, padded size.
- class pyFDN.train.losses.reductions.MeanRmsOverGroups[source]#
Bases:
ReductionMean of per-group RMS values, groups split along dim 0.
- class pyFDN.train.losses.reductions.Reduction[source]#
Bases:
ABCBase class for aggregation strategies.
pyFDN.train.losses.spectral module#
Losses on the spectrum of the impulse response.
- class pyFDN.train.losses.spectral.AsymmetricFlatMagnitude(*, peak_power=4.0)[source]#
Bases:
ResponseLossFlatness that punishes peaks far harder than dips – colorless.
The asymmetric sibling of
FlatMagnitude: a resonant peak rings audibly at its own pitch while a dip of the same size is largely inaudible, so this measures \(|H|\) against the response’s own RMS and raises the two sides of the deviation to different powers,\[d[f] = \frac{|H[f]|}{\sqrt{\langle |H|^2 \rangle_f}} - 1, \qquad \mathcal{L} = \Big\langle \big(d^{+}\big)^{p} + \big(d^{-}\big)^{2} \Big\rangle_f,\]with
peak_power\(p \ge 2\). Flat stays the unique minimum at everypeak_powerand the loss is gain-invariant (addEnergyto pin the level). The exponent, not a weight, is what makes it bite, and the linear magnitude (not dB) is deliberate; see the design note for why, and for what a higher exponent costs in convergence.- Parameters:
peak_power (
float) – Exponent on the peak side; dips are always quadratic. Must be at least 2 (the symmetric-shape reference, still peak-biased since a peak is unbounded and a dip is not). 4 is the default; 6 is slower but steadier. The advantage overFlatMagnitudeis not unconditional – measure your own case. Loss values are not comparable acrosspeak_poweror withFlatMagnitude; compare the responses.
Notes
A lossless FDN has every pole exactly on the unit circle, where the frequency-domain evaluation breaks down;
check()warns if the model was built without thealias_decay_dbthat avoids it.
- class pyFDN.train.losses.spectral.FlatMagnitude(target=1.0, *, channels='sum')[source]#
Bases:
MatchMean squared error of \(|H|\) against a flat target – colorless.
Fits the magnitude spectrum of the (rectangularly truncated) impulse response to a constant, after Differentiable FDNs for Colorless Reverberation (Dal Santo et al.). Its frequency resolution is the model’s
nfft, which makes the fit sensitive to it; see the design note andFlatSpectrogramfor a resolution-independent alternative.- Parameters:
target (
float) – The flat magnitude to fit. The default of 1 matchespyFDN.build_fdn()’s normalized input/output gains, which put the initial \(|H|\) near unity.channels (
Literal['sum','mean','none']) – How the output channels are combined before the comparison."sum"(default) reproduces FLAMO’smse_lossconvention."none"fits each input/output pair to flat on its own, the well-posed choice for a multi-output FDN.
Notes
The optimization crosses long plateaus on this objective;
train_fdn’s defaultpatience=10stops inside one. Raise it (~100) for a converged fit. A lossless FDN has every pole exactly on the unit circle, where the frequency-domain evaluation breaks down;check()warns if the model was built without thealias_decay_dbthat avoids it.
- class pyFDN.train.losses.spectral.FlatSpectrogram(*, nfft=(256, 512, 1024, 2048), overlap=0.75)[source]#
Bases:
MatchFlatness measured on multi-resolution smoothed spectra – colorless.
The multi-scale sibling of
FlatMagnitude, and the one whose frequency resolution is its own business rather than the model’s. For each analysis window \(n\), the short-time magnitudes are averaged over frames into a smoothed (Welch) spectral estimate, which is then normalized by its own mean and fitted to flat:\[P_n[f] = \sqrt{\big\langle |S_n[t, f]|^2 \big\rangle_t}, \qquad \mathcal{L} = \frac{1}{|W|} \sum_{n \in W} \Big\langle \Big( \frac{P_n[f]}{\langle P_n \rangle_f} - 1 \Big)^2 \Big\rangle_f\]A short window smooths heavily and constrains the broad spectral tilt; a long one resolves individual modes. Because each scale is normalized by its own mean, the loss is invariant to overall gain – it fits spectral shape only, and needs no assumption that \(|H| \approx 1\). Averaging over frames before measuring flatness is the whole design (per-frame flatness rewards an impulsive, comb-filtered IR); see the design note.
- Parameters:
nfft (
tuple[int,...]) – STFT window sizes, each no longer than the model’snfft. The default spans a factor of eight, which is what makes the objective multi-scale; one window alone is just a smoothedFlatMagnitude.overlap (
float) – Fractional overlap between frames (0.75 -> hop of a quarter window).
Notes
The loss value is not comparable with
FlatMagnitude’s (the smoothing removes most of the mode-to-mode fluctuation), but it is far more stable against the model’snfft.
- class pyFDN.train.losses.spectral.MatchMagnitude(target, *, channels='none')[source]#
Bases:
MatchMean squared error of \(|H|\) against a reference impulse response.
The magnitude-only sibling of
MatchImpulseResponse: fits the spectral envelope while ignoring phase.- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.channels (
Literal['sum','mean','none']) – How the output channels are combined before the comparison."none"(default) fits each input/output pair on its own.
- class pyFDN.train.losses.spectral.MatchMelMagnitude(target, *, n_mels=128, f_min=0.0, f_max=None, channels='none')[source]#
Bases:
MatchMel-scaled mean squared error of \(|H|\) against a reference.
The mel sibling of
MatchMagnitude: both spectra are reduced ton_melsmel bands (viatorchaudio’s triangular filterbank) before comparing, weighting the fit towards the low frequencies where mel spacing resolves more finely, at the cost of resolution in the high ones.- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.n_mels (
int) – Number of mel bands. Default 128.f_min (
float) – Mel filterbank frequency range in Hz.f_maxdefaults to Nyquist.f_max (
float|None) – Mel filterbank frequency range in Hz.f_maxdefaults to Nyquist.channels (
Literal['sum','mean','none']) – How the output channels are combined before the comparison."none"(default) fits each input/output pair on its own, the well-posed choice for a multi-output FDN.
- class pyFDN.train.losses.spectral.MatchMelSpectrogram(target, *, nfft=(256, 512, 1024), device=None, **kwargs)[source]#
Bases:
_FlamoSpectrogramLossMel-scaled multi-resolution STFT distance (FLAMO’s
mel_mss_loss).
- class pyFDN.train.losses.spectral.MatchPhase(target, *, channels='none')[source]#
Bases:
MatchCircular distance of \(\angle H\) against a reference impulse response.
The per-bin distance is \(1 - \cos(\Delta\phi)\), circular so the \(\pm\pi\) wrap costs nothing extra.
- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.channels (
Literal['sum','mean','none']) –"none"(default) compares each input/output pair on its own;"sum"and"mean"compare the phase of the summed output channels (both give the same phase).
Notes
The whole-response phase of a reverberant IR varies extremely fast with frequency and is undefined where \(|H|\) vanishes, yet every bin counts equally, so the loss landscape is very rough for long responses. Prefer it for short filters or the early part of a response, or use
MatchPhaseSpectrogram.
- class pyFDN.train.losses.spectral.MatchPhaseSpectrogram(target, *, nfft=(256, 512, 1024, 2048), overlap=0.75)[source]#
Bases:
MatchCircular distance of the STFT phase against a reference, multi-resolution.
The windowed sibling of
MatchPhase: rather than a single FFT over the whole response, phase is compared frame by frame at each ofnfft’s window sizes and averaged across scales – whatMatchSpectrogramis toMatchMagnitude, but for phase. The per-bin distance is \(1 - \cos(\Delta\phi)\), circular so the \(\pm\pi\) wrap costs nothing extra.- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.nfft (
tuple[int,...]) – STFT window sizes, each no longer than the model’snfft.overlap (
float) – Fractional overlap between frames (0.75 -> hop of a quarter window).
- class pyFDN.train.losses.spectral.MatchSpectrogram(target, *, nfft=(256, 512, 1024), device=None, **kwargs)[source]#
Bases:
_FlamoSpectrogramLossMulti-resolution STFT distance to a reference impulse response.
Wraps FLAMO’s
mss_loss.nfftis the tuple of STFT window sizes; the loss’s own frequency resolution therefore comes from these, independent of the model’snfft.
- class pyFDN.train.losses.spectral.SpectralFlatness(target=1.0, *, channels='none')[source]#
Bases:
MatchSpectral flatness measure of \(|H|\) fit to flat – colorless.
The ratio of the geometric to the arithmetic mean of \(|H|\), the classic flatness measure: 1 for a perfectly flat spectrum, towards 0 for a peaky one. Unlike
FlatMagnitude, both means scale the same way with an overall gain, so the loss is gain-invariant without needing to assume \(|H| \approx 1\). A silent response has flatness 0, the opposite end from flat.- Parameters:
Notes
A lossless FDN has every pole exactly on the unit circle, where the frequency-domain evaluation breaks down;
check()warns if the model was built without thealias_decay_dbthat avoids it.
pyFDN.train.losses.temporal module#
Losses on the impulse response in the time domain.
- class pyFDN.train.losses.temporal.Energy(target=1.0)[source]#
Bases:
ResponseLossSquared deviation of the response’s total energy from
target.A blunt level anchor: useful next to a magnitude-only loss to stop an objective that is invariant to overall gain from drifting.
- class pyFDN.train.losses.temporal.MatchCumulativeEnergy(target, *, window=1024, hop=None, power=0.5, floor_db=-100.0, frequency='descending')[source]#
Bases:
MatchDoubly-cumulated energy against a reference – decay and colour, no bands.
Takes the short-time power spectrum of both signals and integrates it twice, backwards in time and downwards in frequency:
\[E[f, t] = \sum_{t' \ge t} \; \sum_{f' \ge f} \big| S[f', t'] \big|^2\]so \(E[f, t]\) is the energy still to come after time \(t\) in the band above \(f\), and \(E[0, 0]\) is the total energy. The loss is the RMS difference of the two surfaces after a compressive power.
Cumulating twice carries both things a fit needs: read down the \(t = 0\) edge and you have the integrated spectrum (the colour), read across the \(f = 0\) edge and you have the full-band decay, and the interior ties them together band by band – without the arbitrary quantization of octave bands. The compressive
power(rather than a logarithm) keeps the surface’s six-orders-of-magnitude dynamic range visible to the loss while staying bounded. See the design note for the reasoning behind the defaults.- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.window (
int) – STFT window and hop in samples. UnlikeMatchEnergyDecaythis loss needs no window long enough to resolve an octave – it never splits into octaves – so the default is short.hop (
int|None) – STFT window and hop in samples. UnlikeMatchEnergyDecaythis loss needs no window long enough to resolve an octave – it never splits into octaves – so the default is short.power (
float) – The compression exponent \(p \in (0, 1]\) applied to the normalized surface. 1 is no compression (raw energies), 0.5 the default, 0.25 stronger.floor_db (
float) – Hard floor on the normalized surface, in energy dB below the reference’s total energy. It bounds the gradient of the compression near zero and keeps the fit off the numerical floor of the render;clampmeans no gradient flows from anything below it.frequency (
str) – Which way the frequency cumulation runs, and with it the loss’s balance between the ends of the spectrum. The default"descending"(the plain reading of “energy above this frequency”) gives a low band little gradient;"both"scores both directions and averages, and is what to reach for when the fit has to find a decay it was not given. See the design note for the comparison.
Notes
The surface is normalized by the reference’s total energy, one constant – not each surface by its own – so a level error is a genuine error of the loss rather than something it is blind to. Fitting shape only, with the level left to another term, is the one thing this loss deliberately does not do.
- class pyFDN.train.losses.temporal.MatchEchoDensity(target, *, win_duration=0.02, hop=None, kappa=(100.0, 100000.0))[source]#
Bases:
MatchMean squared error of the differentiable echo density profile.
Scores how fast the response builds up to a diffuse, Gaussian-like tail – the one property of a reverberator that neither a spectrogram nor an energy decay sees. See
EchoDensityProfile.Contributed by Riccardo Giampiccolo.
- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.win_duration (
float) – Analysis window in seconds.hop (
int|None) – Samples between profile points; defaults to a quarter window. 1 is the textbook profile, at a memory cost ofnfft * windowper channel.kappa (
float|tuple[float,float]) – Sigmoid slope, or its linear ramp from start to end of the response.
- class pyFDN.train.losses.temporal.MatchEnergyDecay(target, *, window=4096, hop=None, bands=None, floor_db=-45.0)[source]#
Bases:
MatchRMS dB error of the octave-band energy decay curves against a reference.
The loss that sees the decay – and the one to add when the decay is a trained parameter (a
AttenuationFilterin thepost_delayhook). A magnitude spectrogram distance is not a substitute for fitting a decay; see the design note.Each band’s Schroeder curve is normalized to its own value at \(t=0\), so the loss reads the decay and nothing else – level is left to whatever else is in the objective.
The value is in dB, which puts it many orders of magnitude above a spectrogram distance: weight accordingly, and read
TrainLog.loss_log(which stores every term unweighted) to see what each term is worth.- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.window (
int) – STFT window and hop in samples for the band energies. The default 4096 (85 ms at 48 kHz) resolves the 63 Hz octave; shorter windows leave the low bands with too few bins to be worth reading.hop (
int|None) – STFT window and hop in samples for the band energies. The default 4096 (85 ms at 48 kHz) resolves the 63 Hz octave; shorter windows leave the low bands with too few bins to be worth reading.bands (
Any) – Band edges in Hz; defaults to the octave bands from 44 Hz to 11.3 kHz.floor_db (
float) – Only the part of each band’s curve where the target is still above this level is compared. Past it a measurement is reading its own noise floor, and fitting that would fit the microphone.
- class pyFDN.train.losses.temporal.MatchEnvelope(target, *, release_time=0.00028, p=2.0)[source]#
Bases:
MatchNormalized \(L^p\) error of the smoothed peak envelope.
\(\overline{|e - \hat e|^p} / \overline{|\hat e|^p}\) between the envelopes of prediction and reference, where the envelope is a fast peak follower on \(h^2\), zero-phase low-passed. Sees the arrival and level of individual reflections that an energy decay integrates away. See
PeakEnvelope.Contributed by Riccardo Giampiccolo.
- class pyFDN.train.losses.temporal.MatchImpulseResponse(target)[source]#
Bases:
MatchMean squared error against a reference impulse response, sample by sample.
The strictest of the matching losses – it fits phase as well as magnitude, which for a reverberator is usually more than you want. Reach for
MatchSpectrogramunless you are fitting an early part or a short filter.- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.
- class pyFDN.train.losses.temporal.MatchMelEnergyDecayRelief(target, *, fft_sizes=(1024, 2048, 512), win_lengths=(600, 1200, 240), hop_lengths=(120, 240, 50), n_mels=64, p=1.0)[source]#
Bases:
ResponseLossMulti-resolution mel energy decay relief (EDR) distance to a reference.
At each STFT resolution, the mel power spectrogram of both signals is backward-integrated over time and taken to dB (with an 80 dB floor), and the normalized \(L^p\) error \(\overline{|E - \hat E|^p} / \overline{|\hat E|^p}\) is averaged over the resolutions. Decay and colour at once, like
MatchCumulativeEnergy, but banded on the mel scale.Contributed by Riccardo Giampiccolo. The defaults are his, tuned at 16 kHz; at 48 kHz the same STFT sizes span a third of the time.
- Parameters:
target (
Any) – Reference IR, shape(n_samples,),(n_samples, n_out)or(n_samples, n_out, n_in). Zero-padded or truncated to the model’snfft.fft_sizes (
tuple[int,...]) – One STFT resolution per entry; all three the same length.win_lengths (
tuple[int,...]) – One STFT resolution per entry; all three the same length.hop_lengths (
tuple[int,...]) – One STFT resolution per entry; all three the same length.n_mels (
int) – Number of mel bands.p (
float) – Exponent of the error.
Module contents#
Training losses for FDNs – see pyFDN.train.losses.base for how they
compose into an objective.