Sensor Fusion¶
[1]:
import os
import gpflow as gpf
import numpy as np
import tensorflow as tf
from tsipy.correction import SignalGenerator
from tsipy.fusion import SVGPModel, LocalGPModel
from tsipy.fusion.kernels import MultiWhiteKernel
from tsipy.fusion.utils import (
build_and_concat_label_mask,
build_and_concat_label_mask_output,
)
from tsipy.utils import (
make_dir,
plot_signals,
plot_signals_and_confidence,
pprint,
pprint_block,
sort_inputs,
)
Parameters¶
[2]:
random_seed = 0
fusion_model = "localgp"
normalization = True
clipping = True
num_inducing_pts = 100
max_iter = 1000
pred_window_width = 0.2
fit_window_width = 0.6
Generate Dataset¶
[3]:
np.random.seed(random_seed)
tf.random.set_seed(random_seed)
# Generate Brownian motion signal
signal_generator = SignalGenerator(add_degradation=False)
t_a, a = signal_generator["a"]
t_b, b = signal_generator["b"]
pprint("Signal", level=0)
pprint("- t_a", t_a.shape, level=1)
pprint("- a", a.shape, level=1)
pprint("Signal", level=0)
pprint("- t_b", t_b.shape, level=1)
pprint("- b", b.shape, level=1)
Signal
- t_a (90002,)
- a (90002,)
Signal
- t_b (20127,)
- b (20127,)
[4]:
_ = plot_signals(
[
(t_a, a, "$a$", {}),
(t_b, b, "$b$", {}),
(signal_generator.x, signal_generator.y, "$s$", {}),
],
legend="upper right",
)
Sensor Fusion¶
[5]:
gpf.config.set_default_float(np.float64)
np.random.seed(random_seed)
tf.random.set_seed(random_seed)
t_a = build_and_concat_label_mask(t_a, label=1)
t_b = build_and_concat_label_mask(t_b, label=2)
t_out = build_and_concat_label_mask_output(signal_generator.x)
# Concatenate signals and sort by x[:, 0]
t = np.vstack((t_a, t_b))
s = np.reshape(np.hstack((a, b)), newshape=(-1, 1))
t, s = sort_inputs(t, s, sort_axis=0)
pprint("Signals", level=0)
pprint("- t", t.shape, level=1)
pprint("- s", s.shape, level=1)
Signals
- t (110129, 2)
- s (110129, 1)
Covariance Function¶
[6]:
# Signal kernel
matern_kernel = gpf.kernels.Matern12(active_dims=[0]) # Kernel for time dimension
# Noise kernel
white_kernel = MultiWhiteKernel(
labels=(1, 2), active_dims=[1]
) # Kernel for sensor dimension
# Kernel composite
kernel = matern_kernel + white_kernel
[7]:
if fusion_model == "localgp":
local_model = SVGPModel(
kernel=kernel,
num_inducing_pts=num_inducing_pts,
)
model = LocalGPModel(
model=local_model,
pred_window_width=pred_window_width,
fit_window_width=fit_window_width,
normalization=normalization,
clipping=clipping,
)
else:
model = SVGPModel( # type: ignore
kernel=kernel,
num_inducing_pts=num_inducing_pts,
normalization=normalization,
clipping=clipping,
)
# Train
model.fit(t, s, max_iter=max_iter, x_val=t_out, n_evals=5, verbose=True)
# Predict
s_out_mean, s_out_std = model(t_out)
pprint("\nOutput Signals", level=0)
pprint("- t_out", t_out.shape, level=1)
pprint("- s_out_mean", s_out_mean.shape, level=1)
pprint("- s_out_std", s_out_std.shape, level=1)
Window
- Prediction: -inf, 0.200
- Training: 0.000, 0.400
- Data indices: 0, 44123
- x, y: (44124, 2), (44124, 1)
- n_ind_pts/time_unit 167.500
- Step 1/1000: -103866.746
- Step 200/1000: -60010.142
- Step 400/1000: -48683.046
- Step 600/1000: -36832.851
- Step 800/1000: -23925.447
- Step 1000/1000: -19596.609
Window
- Prediction: 0.200, 0.400
- Training: 0.000, 0.600
- Data indices: 0, 66134
- x, y: (66135, 2), (66135, 1)
- n_ind_pts/time_unit 168.333
- Step 1/1000: -149145.480
- Step 200/1000: -92874.614
- Step 400/1000: -76923.542
- Step 600/1000: -58122.908
- Step 800/1000: -44142.680
- Step 1000/1000: -31588.207
Window
- Prediction: 0.400, 0.600
- Training: 0.200, 0.800
- Data indices: 21993, 88103
- x, y: (66111, 2), (66111, 1)
- n_ind_pts/time_unit 166.667
- Step 1/1000: -155923.508
- Step 200/1000: -87845.159
- Step 400/1000: -66874.528
- Step 600/1000: -44976.776
- Step 800/1000: -24288.666
- Step 1000/1000: -11041.589
Window
- Prediction: 0.600, 0.800
- Training: 0.400, 1.000
- Data indices: 44123, 110128
- x, y: (66006, 2), (66006, 1)
- n_ind_pts/time_unit 166.669
- Step 1/1000: -156447.908
- Step 200/1000: -84106.167
- Step 400/1000: -61901.960
- Step 600/1000: -35648.582
- Step 800/1000: -13297.355
- Step 1000/1000: 2251.993
Window
- Prediction: 0.800, inf
- Training: 0.600, 1.000
- Data indices: 66134, 110128
- x, y: (43995, 2), (43995, 1)
- n_ind_pts/time_unit 167.504
- Step 1/1000: -105286.991
- Step 200/1000: -55338.623
- Step 400/1000: -40155.449
- Step 600/1000: -22377.848
- Step 800/1000: -5512.004
- Step 1000/1000: 6260.036
Output Signals
- t_out (100000, 2)
- s_out_mean (100000,)
- s_out_std (100000,)
Results¶
[8]:
fig, ax = plot_signals_and_confidence(
[(t_out[:, 0], s_out_mean, s_out_std, fusion_model)],
)
ax.scatter(
t_a[:, 0],
a,
label="$a$",
s=3,
)
_ = ax.scatter(
t_b[:, 0],
b,
label="$b$",
s=3,
)
[9]:
fig, ax = plot_signals_and_confidence(
[(t_out[:, 0], s_out_mean, s_out_std, fusion_model)],
)
_ = ax.plot(signal_generator.x, signal_generator.y, label="$s$")
Training¶
[10]:
if fusion_model == "localgp":
for i, window in enumerate(model.windows):
elbo = window.model.iter_elbo
plot_signals(
[(np.arange(elbo.size), elbo, r"ELBO", {})],
legend="lower right",
)
else:
elbo = model.iter_elbo # type: ignore
plot_signals(
[(np.arange(elbo.size), elbo, r"ELBO", {})],
legend="lower right",
)
[ ]: