Esporre la potenza del filtro di Kalman |  di Jimmy Weaver |  Novembre 2023

 | Intelligenza-Artificiale

Come data scientist ci troviamo occasionalmente di fronte a situazioni in cui dobbiamo modellare una tendenza per prevedere i valori futuri. Anche se c’è la tentazione di concentrarsi su algoritmi statistici o basati sull’apprendimento automatico, sono qui per presentare un’opzione diversa: il filtro di Kalman (KF).

All’inizio degli anni ’60 Rudolf E. Kalman rivoluzionò il modo in cui i sistemi complessi potevano essere modellati con la KF. Dal guidare aerei o navicelle spaziali verso la loro destinazione al consentire allo smartphone di trovare il suo posto in questo mondo, questo algoritmo unisce dati e matematica per fornire stime degli stati futuri con incredibile precisione.

In questo blog approfondiremo il funzionamento del filtro Kalman, mostrando esempi in Python che metteranno in risalto la vera potenza di questa tecnica. Partendo da un semplice esempio 2D, vedremo come modificare il codice per adattarlo a spazi 4D più avanzati e finiremo coprendo l’Extended Kalman Filter (il sofisticato predecessore). Unisciti a me in questo viaggio mentre ci imbarchiamo nel mondo degli algoritmi e dei filtri predittivi.

Il KF fornisce una stima dello stato di un sistema costruendo e aggiornando continuamente una serie di matrici di covarianza (che rappresentano la distribuzione statistica del rumore e degli stati passati) raccolte da osservazioni e altre misurazioni nel tempo. A differenza di altri algoritmi pronti all’uso, è possibile espandere e perfezionare direttamente la soluzione definendo le relazioni matematiche tra il sistema e le fonti esterne. Sebbene possa sembrare piuttosto complesso e intricato, il processo può essere riassunto in due fasi: previsione e aggiornamento. Queste fasi lavorano insieme per correggere e perfezionare iterativamente le stime dello stato del sistema.

Passo di previsione:

Questa fase riguarda la previsione del prossimo stato futuro del sistema sulla base delle stime a posteriori note del modello e del passo nel tempo di Δk. Matematicamente rappresentiamo le stime dello spazio degli stati come:

dove, F, la nostra matrice di transizione degli stati modella il modo in cui gli stati evolvono da un passo all’altro indipendentemente dall’input di controllo e dal rumore del processo. La nostra matrice B modella l’impatto dell’input di controllo, uₖ, sullo stato.

Oltre alle nostre stime dello stato successivo, l’algoritmo calcola anche l’incertezza della stima rappresentata dalla matrice di covarianza P:

La matrice di covarianza dello stato previsto rappresenta la confidenza e l’accuratezza delle nostre previsioni, influenzate da Q la matrice di covarianza del rumore di processo dal sistema stesso. Applichiamo questa matrice alle equazioni successive nella fase di aggiornamento per correggere le informazioni che il filtro di Kalman conserva sul sistema, migliorando conseguentemente le stime dello stato futuro.

Passaggio di aggiornamento:

Nella fase di aggiornamento l’algoritmo esegue aggiornamenti al guadagno di Kalman, alle stime di stato e alla matrice di covarianza. Il guadagno di Kalman determina quanta influenza dovrebbe avere una nuova misurazione sulle stime dello stato. Il calcolo include la matrice del modello di osservazione, Hche mette in relazione lo stato con la misurazione che ci aspettiamo di ricevere, e R la matrice di covarianza del rumore di misura degli errori nelle misurazioni:

In sostanza, K tenta di bilanciare l’incertezza nelle previsioni con quella presente nelle misurazioni. Come accennato in precedenza, il guadagno di Kalman viene applicato per correggere le stime di stato e la covarianza, come presentato rispettivamente dalle seguenti equazioni:

dove il calcolo tra parentesi per la stima statale è il residuo, la differenza tra la misurazione effettiva e quella prevista dal modello.

La vera bellezza del funzionamento di un filtro di Kalman risiede nella sua natura ricorsiva, aggiornando continuamente sia lo stato che la covarianza man mano che vengono ricevute nuove informazioni. Ciò consente al modello di affinarsi in modo statisticamente ottimale nel tempo, il che costituisce un approccio particolarmente potente ai sistemi di modellazione che ricevono un flusso di osservazioni rumorose.

È possibile sentirsi sopraffatti dalle equazioni che sono alla base del filtro di Kalman e per apprezzare appieno il suo funzionamento basandosi solo sulla matematica sarebbe necessaria una comprensione dello spazio degli stati (fuori dallo scopo di questo blog), ma cercherò di portare prende vita con alcuni esempi Python. Nella sua forma più semplice, possiamo definire un oggetto Filtro Kalman come:

import numpy as np

class KalmanFilter:
"""
An implementation of the classic Kalman Filter for linear dynamic systems.
The Kalman Filter is an optimal recursive data processing algorithm which
aims to estimate the state of a system from noisy observations.

Attributes:
F (np.ndarray): The state transition matrix.
B (np.ndarray): The control input marix.
H (np.ndarray): The observation matrix.
u (np.ndarray): the control input.
Q (np.ndarray): The process noise covariance matrix.
R (np.ndarray): The measurement noise covariance matrix.
x (np.ndarray): The mean state estimate of the previous step (k-1).
P (np.ndarray): The state covariance of previous step (k-1).
"""
def __init__(self, F, B, u, H, Q, R, x0, P0):
"""
Initializes the Kalman Filter with the necessary matrices and initial state.

Parameters:
F (np.ndarray): The state transition matrix.
B (np.ndarray): The control input marix.
H (np.ndarray): The observation matrix.
u (np.ndarray): the control input.
Q (np.ndarray): The process noise covariance matrix.
R (np.ndarray): The measurement noise covariance matrix.
x0 (np.ndarray): The initial state estimate.
P0 (np.ndarray): The initial state covariance matrix.
"""
self.F = F # State transition matrix
self.B = B # Control input matrix
self.u = u # Control vector
self.H = H # Observation matrix
self.Q = Q # Process noise covariance
self.R = R # Measurement noise covariance
self.x = x0 # Initial state estimate
self.P = P0 # Initial estimate covariance

def predict(self):
"""
Predicts the state and the state covariance for the next time step.
"""
self.x = self.F @ self.x + self.B @ self.u
self.P = self.F @ self.P @ self.F.T + self.Q
return self.x

def update(self, z):
"""
Updates the state estimate with the latest measurement.

Parameters:
z (np.ndarray): The measurement at the current step.
"""
y = z - self.H @ self.x
S = self.H @ self.P @ self.H.T + self.R
K = self.P @ self.H.T @ np.linalg.inv(S)
self.x = self.x + K @ y
I = np.eye(self.P.shape(0))
self.P = (I - K @ self.H) @ self.P

return self.xChallenges with Non-linear Systems

Utilizzeremo il predict() E update() funzioni per ripetere i passaggi descritti in precedenza. La struttura del filtro di cui sopra funzionerà per qualsiasi serie temporale e per mostrare come le nostre stime si confrontano con i valori effettivi costruiamo un semplice esempio:

import numpy as np
import matplotlib.pyplot as plt

# Set the random seed for reproducibility
np.random.seed(42)

# Simulate the ground truth position of the object
true_velocity = 0.5 # units per time step
num_steps = 50
time_steps = np.linspace(0, num_steps, num_steps)
true_positions = true_velocity * time_steps

# Simulate the measurements with noise
measurement_noise = 10 # increase this value to make measurements noisier
noisy_measurements = true_positions + np.random.normal(0, measurement_noise, num_steps)

# Plot the true positions and the noisy measurements
plt.figure(figsize=(10, 6))
plt.plot(time_steps, true_positions, label='True Position', color='green')
plt.scatter(time_steps, noisy_measurements, label='Noisy Measurements', color='red', marker='o')

plt.xlabel('Time Step')
plt.ylabel('Position')
plt.title('True Position and Noisy Measurements Over Time')
plt.legend()
plt.show()

In realtà la “Posizione reale” sarebbe sconosciuta ma la tracceremo qui come riferimento, le “Misurazioni rumorose” sono i punti di osservazione che vengono immessi nel nostro filtro di Kalman. Effettueremo un’istanziazione molto semplice delle matrici e in una certa misura non ha importanza poiché il modello di Kalman convergerà rapidamente attraverso l’applicazione del guadagno di Kalman, ma in determinate circostanze potrebbe essere ragionevole eseguire un avvio a caldo del modello.

# Kalman Filter Initialization
F = np.array(((1, 1), (0, 1))) # State transition matrix
B = np.array(((0), (0))) # No control input
u = np.array(((0))) # No control input
H = np.array(((1, 0))) # Measurement function
Q = np.array(((1, 0), (0, 3))) # Process noise covariance
R = np.array(((measurement_noise**2))) # Measurement noise covariance
x0 = np.array(((0), (0))) # Initial state estimate
P0 = np.array(((1, 0), (0, 1))) # Initial estimate covariance

kf = KalmanFilter(F, B, u, H, Q, R, x0, P0)

# Allocate space for estimated positions and velocities
estimated_positions = np.zeros(num_steps)
estimated_velocities = np.zeros(num_steps)

# Kalman Filter Loop
for t in range(num_steps):
# Predict
kf.predict()

# Update
measurement = np.array(((noisy_measurements

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *