import numpy as np
import matplotlib.pyplot as plt
from numpy import (exp, multiply, eye, linspace, spacing, sqrt)
from numpy.linalg import cholesky, solve
from scipy.spatial.distance import squareform, pdist, cdist
from scipy.optimize import minimize # Für die Optimierung
class KrigingRegressor:
"""Ein Kriging-Regressionsmodell mit Hyperparameter-Optimierung.
Attributes:
initial_theta (float): Startwert für den Aktivitätsparameter Theta.
bounds (list): Liste von Tupeln für die Grenzen der Hyperparameter-Optimierung.
opt_theta_ (float): Optimierter Theta-Wert nach dem Fitting.
X_train_ (array): Trainings-Eingabedaten.
y_train_ (array): Trainings-Zielwerte.
U_ (array): Cholesky-Zerlegung der Korrelationsmatrix.
mu_hat_ (float): Geschätzter Mittelwert.
"""
def __init__(self, initial_theta=1.0, bounds=[(0.001, 100.0)]):
self.initial_theta = initial_theta
self.bounds = bounds
def _build_Psi(self, X, theta, eps=sqrt(spacing(1))):
"""Berechnet die Korrelationsmatrix Psi."""
if not isinstance(theta, np.ndarray) or theta.ndim == 0:
= np.array([theta])
theta
= squareform(pdist(X, metric='sqeuclidean', w=theta))
D = exp(-D)
Psi += multiply(eye(X.shape[0]), eps)
Psi return Psi
def _build_psi(self, X_train, x_predict, theta):
"""Berechnet den Korrelationsvektor psi."""
if not isinstance(theta, np.ndarray) or theta.ndim == 0:
= np.array([theta])
theta
= cdist(x_predict, X_train, metric='sqeuclidean', w=theta)
D = exp(-D)
psi return psi.T
def _neg_log_likelihood(self, params, X_train, y_train):
"""Berechnet die negative konzentrierte Log-Likelihood."""
= params
theta = X_train.shape[0]
n
try:
= self._build_Psi(X_train, theta)
Psi = cholesky(Psi).T
U except np.linalg.LinAlgError:
return 1e15
= np.ones(n).reshape(-1, 1)
one
# Berechne mu_hat (MLE des Mittelwerts)
= solve(U, solve(U.T, y_train))
Psi_inv_y = solve(U, solve(U.T, one))
Psi_inv_one = (one.T @ Psi_inv_y) / (one.T @ Psi_inv_one)
mu_hat = mu_hat.item()
mu_hat
# Berechne sigma_hat_sq (MLE der Prozessvarianz)
= y_train - one * mu_hat
y_minus_mu_one = (y_minus_mu_one.T @ Psi_inv_y) / n
sigma_hat_sq = sigma_hat_sq.item()
sigma_hat_sq
if sigma_hat_sq < 1e-10:
return 1e15
# Berechne negative konzentrierte Log-Likelihood
= 2 * np.sum(np.log(np.diag(U.T)))
log_det_Psi = 0.5 * (n * np.log(sigma_hat_sq) + log_det_Psi)
nll
return nll
def fit(self, X, y):
"""Fit das Kriging-Modell an die Trainingsdaten.
// ...existing docstring...
"""
self.X_train_ = X
self.y_train_ = y.reshape(-1, 1)
# Optimierung der Hyperparameter
= np.array([self.initial_theta])
initial_theta = minimize(self._neg_log_likelihood,
result
initial_theta,=(self.X_train_, self.y_train_),
args='L-BFGS-B',
method=self.bounds)
bounds
self.opt_theta_ = result.x
# Berechne optimale Parameter für Vorhersagen
= self._build_Psi(self.X_train_, self.opt_theta_)
Psi_opt self.U_ = cholesky(Psi_opt).T
= self.X_train_.shape[0]
n_train = np.ones(n_train).reshape(-1, 1)
one
self.mu_hat_ = (one.T @ solve(self.U_, solve(self.U_.T, self.y_train_))) / \
@ solve(self.U_, solve(self.U_.T, one)))
(one.T self.mu_hat_ = self.mu_hat_.item()
return self
def predict(self, X):
"""Vorhersage für neue Datenpunkte.
Args:
X (array-like): Eingabedaten für Vorhersage der Form (n_samples, n_features)
Returns:
array: Vorhergesagte Werte
"""
= self.X_train_.shape[0]
n_train = np.ones(n_train).reshape(-1, 1)
one # Fix: Use self._build_psi instead of build_psi
= self._build_psi(self.X_train_, X, self.opt_theta_)
psi
return self.mu_hat_ * np.ones(X.shape[0]).reshape(-1, 1) + \
@ solve(self.U_, solve(self.U_.T,
psi.T self.y_train_ - one * self.mu_hat_))
62 Lernmodul: Erweiterung des Kriging-Modells zu einer Klasse (Python Code)
def plot_kriging_results(X_train, y_train, X_test, y_test, y_pred, theta, figsize=(10, 6)):
"""Visualisiert die Kriging-Vorhersage im Vergleich zur wahren Funktion.
Args:
X_train (array-like): Trainings-Eingabedaten
y_train (array-like): Trainings-Zielwerte
X_test (array-like): Test-Eingabedaten
y_test (array-like): Wahre Werte zum Vergleich
y_pred (array-like): Vorhersagewerte des Modells
theta (float): Optimierter Theta-Parameter
figsize (tuple, optional): Größe der Abbildung. Default ist (10, 6).
"""
=figsize)
plt.figure(figsize
# Sortiere Test-Daten nach X-Werten für eine glatte Linie
= np.argsort(X_test.ravel())
sort_idx_test = X_test[sort_idx_test]
X_test_sorted = y_test[sort_idx_test]
y_test_sorted = y_pred[sort_idx_test]
y_pred_sorted
# Wahre Funktion
="grey", linestyle='--',
plt.plot(X_test_sorted, y_test_sorted, color="Wahre Sinusfunktion")
label
# Trainingspunkte
= len(X_train)
n_train "bo", markersize=8,
plt.plot(X_train, y_train, =f"Messpunkte ({n_train} Punkte)")
label
# Vorhersage
="orange",
plt.plot(X_test_sorted, y_pred_sorted, color=f"Kriging-Vorhersage (Theta={theta:.2f})")
label
# Plot-Eigenschaften
f"Kriging-Vorhersage mit {n_train} Trainings-Punkten\n" +
plt.title(f"Optimierter Aktivitätsparameter Theta={theta:.2f}")
"x")
plt.xlabel("y")
plt.ylabel(='upper right')
plt.legend(locTrue)
plt.grid( plt.show()
62.1 Ein erste Beispielverwendung:
# Generiere Trainingsdaten
= 4
n_train = np.linspace(0, 2 * np.pi, n_train, endpoint=False).reshape(-1, 1)
X_train = np.sin(X_train)
y_train
# Erstelle und trainiere das Modell
= KrigingRegressor(initial_theta=1.0)
model
model.fit(X_train, y_train)
# Generiere Testdaten
= np.linspace(0, 2 * np.pi, 100, endpoint=True).reshape(-1, 1)
X_test = np.sin(X_test)
y_test
# Mache Vorhersagen
= model.predict(X_test)
y_pred
# Visualisiere die Ergebnisse
plot_kriging_results(=X_train,
X_train=y_train,
y_train=X_test,
X_test=y_test,
y_test=y_pred,
y_pred=model.opt_theta_[0]
theta )
62.2 Ein zweites Beispiel mit train_test_split:
from sklearn.model_selection import train_test_split
import numpy as np
# Generate sample data
= 100
n_samples = np.linspace(0, 2 * np.pi, n_samples).reshape(-1, 1)
X = np.sin(X)
y
# Split data
= train_test_split(X, y, test_size=96, random_state=42)
X_train, X_test, y_train, y_test
# Fit model
= KrigingRegressor(initial_theta=1)
model
model.fit(X_train, y_train)
# Make predictions
= model.predict(X_test)
y_pred
# Visualize results
plot_kriging_results(=X_train,
X_train=y_train,
y_train=X_test,
X_test=y_test,
y_test=y_pred,
y_pred=model.opt_theta_[0]
theta )