import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplotsEffect of Measurement Noise on Differentiation¶
Let’'s see what happens when we introduce error into our data.
# Setup baseline rocket signal and central difference stencil
def v(t):
return 2000 * np.log((14 * 10**4) / (14 * 10**4 - 2100 * t)) - 9.8 * t
def central_difference(f, x, h):
return (f(x + h) - f(x - h)) / (2 * h)
t = np.linspace(0, 30, 100)
a_cd_h2 = central_difference(v, t, h=2)
np.random.seed(42)
noise = np.random.normal(0, 1, len(t))
vt = v(t)
vt_err = vt + noise
def v_err(t_eval):
return v(t_eval) + np.random.normal(0, 1, np.shape(t_eval))
a_cd_h2_error = central_difference(v_err, t, h=2)
fig = make_subplots(rows=2, cols=1, subplot_titles=["v(t) vs v_err(t)", "a_cd_h2_error vs a_cd_h2"])
fig.add_trace(go.Scatter(x=t, y=vt, name="v(t)"), row=1, col=1)
fig.add_trace(go.Scatter(x=t, y=vt_err, name="v_err(t)"), row=1, col=1)
fig.add_trace(go.Scatter(x=t, y=a_cd_h2_error, name="a_cd_h2_error"), row=2, col=1)
fig.add_trace(go.Scatter(x=t, y=a_cd_h2, name="a_cd_h2"), row=2, col=1)
fig.update_xaxes(title_text="t")
fig.update_yaxes(title_text="v(t)", row=1, col=1)
fig.update_yaxes(title_text="a(t)", row=2, col=1)
fig.update_layout(height=420, margin=dict(l=40, r=40, t=40, b=40))
fig.show()Loading...
Uncertainty Amplification and mitigation¶
Because noise typically is very high frequency compared to the signal, differentiation will typically amplify the error.
With this in mind, there are several options:
Prefilter the data: Apply a moving average, or low-pass filter to reduce high-frequency noise.
Regularization: Incorporate a penalty term to smooth the derivatives.
Fit an analytical function: Use regression (e.g. least squares) to fit a smooth function, then differentiate analytically.
Choose a robust method: Use differentiation methods that are less sensitive to noise, like total variation regularization.