Skip to content

Commit dd36775

Browse files
0.33.10
1 parent e521a3b commit dd36775

4 files changed

Lines changed: 95 additions & 129 deletions

File tree

notebooks/00_spotPython_tests.ipynb

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14446,20 +14446,46 @@
1444614446
"model = Kriging()\n",
1444714447
"model.fit(X_train, y_train)\n",
1444814448
"# get theta values of the fitted model\n",
14449-
"theta_values = model.get_model_params()[\"theta\"]\n",
14449+
"theta_values = model.get_params()[\"theta\"]\n",
1445014450
"print(\"Fitted theta values:\", theta_values)"
1445114451
]
1445214452
},
1445314453
{
1445414454
"cell_type": "code",
14455-
"execution_count": 6,
14455+
"execution_count": null,
14456+
"metadata": {},
14457+
"outputs": [],
14458+
"source": [
14459+
"from spotpython.surrogate.kriging import Kriging\n",
14460+
"import numpy as np\n",
14461+
"nat_X = np.array([[1, 2], [3, 4], [5, 6]])\n",
14462+
"nat_y = np.array([1, 2, 3])\n",
14463+
"var_type = [\"num\", \"int\", \"float\"]\n",
14464+
"n_theta=2\n",
14465+
"n_p=2\n",
14466+
"S=Kriging(var_type=var_type, seed=124, n_theta=n_theta, n_p=n_p, optim_p=True)\n",
14467+
"for param, value in S.get_params(deep=True).items():\n",
14468+
" print(f\"{param} -> {value}\")"
14469+
]
14470+
},
14471+
{
14472+
"cell_type": "code",
14473+
"execution_count": null,
14474+
"metadata": {},
14475+
"outputs": [],
14476+
"source": []
14477+
},
14478+
{
14479+
"cell_type": "code",
14480+
"execution_count": 1,
1445614481
"metadata": {},
1445714482
"outputs": [
1445814483
{
1445914484
"name": "stdout",
1446014485
"output_type": "stream",
1446114486
"text": [
14462-
"Lambda -> None\n",
14487+
"Anisotropic model: n_theta set to 2\n",
14488+
"Lambda -> [-8.98453674]\n",
1446314489
"counter -> None\n",
1446414490
"eps -> 1.4901161193847656e-08\n",
1446514491
"isotropic -> False\n",
@@ -14473,59 +14499,36 @@
1447314499
"min_p -> 1.0\n",
1447414500
"min_theta -> -3.0\n",
1447514501
"model_fun_evals -> 100\n",
14476-
"model_optimizer -> <function differential_evolution at 0x10e6e1bc0>\n",
14477-
"n_p -> 2\n",
14502+
"model_optimizer -> <function differential_evolution at 0x1173237e0>\n",
14503+
"n_p -> 1\n",
1447814504
"n_theta -> 2\n",
1447914505
"name -> Kriging\n",
14480-
"optim_p -> True\n",
14506+
"optim_p -> False\n",
1448114507
"p_val -> 2.0\n",
1448214508
"penalty -> 10000.0\n",
1448314509
"seed -> 124\n",
1448414510
"spot_writer -> None\n",
14485-
"theta -> None\n",
14511+
"theta -> [-2.73827427 -2.74539395]\n",
1448614512
"theta_init_zero -> False\n",
14487-
"var_type -> ['num', 'int', 'float']\n"
14513+
"var_type -> ['num', 'num']\n",
14514+
"Fitted theta values: [-2.73827427 -2.74539395]\n"
1448814515
]
1448914516
}
1449014517
],
1449114518
"source": [
14492-
"from spotpython.surrogate.kriging import Kriging\n",
1449314519
"import numpy as np\n",
14494-
"nat_X = np.array([[1, 2], [3, 4], [5, 6]])\n",
14495-
"nat_y = np.array([1, 2, 3])\n",
14496-
"var_type = [\"num\", \"int\", \"float\"]\n",
14497-
"n_theta=2\n",
14498-
"n_p=2\n",
14499-
"S=Kriging(var_type=var_type, seed=124, n_theta=n_theta, n_p=n_p, optim_p=True)\n",
14500-
"for param, value in S.get_params(deep=True).items():\n",
14501-
" print(f\"{param} -> {value}\")"
14520+
"from spotpython.surrogate.kriging import Kriging\n",
14521+
"# Training data\n",
14522+
"X_train = np.array([[0.0, 0.0], [0.5, 0.5], [1.0, 1.0]])\n",
14523+
"y_train = np.array([0.1, 0.2, 0.3])\n",
14524+
"# Initialize and fit the Kriging model\n",
14525+
"model = Kriging()\n",
14526+
"model.fit(X_train, y_train)\n",
14527+
"for param, value in model.get_params(deep=True).items():\n",
14528+
" print(f\"{param} -> {value}\")\n",
14529+
"theta_values = model.get_params()[\"theta\"]\n",
14530+
"print(\"Fitted theta values:\", theta_values)"
1450214531
]
14503-
},
14504-
{
14505-
"cell_type": "code",
14506-
"execution_count": null,
14507-
"metadata": {},
14508-
"outputs": [
14509-
{
14510-
"ename": "AttributeError",
14511-
"evalue": "'Kriging' object has no attribute 'get_params'",
14512-
"output_type": "error",
14513-
"traceback": [
14514-
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
14515-
"\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)",
14516-
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m param, value \u001b[38;5;129;01min\u001b[39;00m \u001b[43mS\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget_params\u001b[49m(deep=\u001b[38;5;28;01mTrue\u001b[39;00m).items():\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mparam\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m -> \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mvalue\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m\"\u001b[39m)\n",
14517-
"\u001b[31mAttributeError\u001b[39m: 'Kriging' object has no attribute 'get_params'"
14518-
]
14519-
}
14520-
],
14521-
"source": []
14522-
},
14523-
{
14524-
"cell_type": "code",
14525-
"execution_count": null,
14526-
"metadata": {},
14527-
"outputs": [],
14528-
"source": []
1452914532
}
1453014533
],
1453114534
"metadata": {

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
77

88
[project]
99
name = "spotpython"
10-
version = "0.33.9"
10+
version = "0.33.10"
1111
authors = [
1212
{ name="T. Bartz-Beielstein", email="tbb@bartzundbartz.de" }
1313
]

src/spotpython/surrogate/kriging.py

Lines changed: 42 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,9 @@ def __init__(
135135
If True, the model is isotropic, meaning all variables are treated equally (only one theta value is used).
136136
If False, the model can handle different theta values, one for each dimension. Defaults to False.
137137
theta (np.ndarray, optional):
138-
Currently ignored. Initial theta values for the model. If None, theta values are initialized during fitting.
139-
Defaults to None.
138+
Initial theta values for the model. If None, theta values are initialized during fitting. Note that theta is in log10 scale. Defaults to None.
140139
Lambda (float, optional):
141-
Currently ignored. Initial Lambda value for the model. If None, Lambda is initialized during fitting.
142-
Defaults to None.
140+
Currently ignored. Initial Lambda value for the model. If None, Lambda is initialized during fitting. Note that Lambda is in log10 scale. Defaults to None.
143141
**kwargs:
144142
Additional keyword arguments.
145143
"""
@@ -258,8 +256,7 @@ def _set_variable_types(self) -> None:
258256

259257
def get_model_params(self) -> Dict[str, float]:
260258
"""
261-
Get the model parameters (in addition to sklearn's get_params method).
262-
259+
Get the (internal) model parameters (in addition to sklearn's get_params method).
263260
This method is NOT required for scikit-learn compatibility.
264261
265262
Returns:
@@ -358,7 +355,10 @@ def fit(self, X: np.ndarray, y: np.ndarray, bounds: Optional[List[Tuple[float, f
358355
>>> # Initialize and fit the Kriging model
359356
>>> model = Kriging()
360357
>>> model.fit(X_train, y_train)
361-
>>> print("Fitted log(theta):", model.logtheta_lambda_)
358+
>>> for param, value in model.get_params(deep=True).items():
359+
>>> print(f"{param} -> {value}")
360+
>>> theta_values = model.get_params()["theta"]
361+
>>> print("Fitted theta values:", theta_values)
362362
"""
363363
X = np.asarray(X)
364364
y = np.asarray(y).flatten()
@@ -553,34 +553,6 @@ def build_Psi(self) -> None:
553553
print("Building Psi failed. Error: %s, Type: %s", err, type(err))
554554
raise
555555

556-
def _kernel(self, X: np.ndarray, theta: np.ndarray, p: float) -> np.ndarray:
557-
"""
558-
Computes the correlation matrix Psi using vectorized operations.
559-
560-
Args:
561-
X (np.ndarray): Input data of shape (n_samples, n_features).
562-
theta (np.ndarray): Theta parameters of shape (n_features,).
563-
p (float): Power exponent.
564-
565-
Returns:
566-
np.ndarray: The upper triangle of the correlation matrix Psi.
567-
"""
568-
n_samples, n_features = X.shape
569-
Psi = np.zeros((n_samples, n_samples), dtype=float)
570-
# Calculate all pairwise differences:
571-
# X_expanded_rows will have shape (n_samples, 1, n_features)
572-
# X_expanded_cols will have shape (1, n_samples, n_features)
573-
# diff will have shape (n_samples, n_samples, n_features)
574-
diff = np.abs(X[:, np.newaxis, :] - X[np.newaxis, :, :]) ** p
575-
# Apply theta and sum over features
576-
# dist_matrix will have shape (n_samples, n_samples)
577-
dist_matrix = np.sum(theta * diff, axis=2)
578-
# Compute Psi using the exponential kernel
579-
Psi = np.exp(-dist_matrix)
580-
# Return only the upper triangle, as the matrix is symmetric
581-
# and the diagonal will be handled later.
582-
return np.triu(Psi, k=1)
583-
584556
def likelihood(self, x: np.ndarray) -> Tuple[float, np.ndarray, np.ndarray]:
585557
"""
586558
Computes the negative of the concentrated log-likelihood for a given set
@@ -653,41 +625,41 @@ def likelihood(self, x: np.ndarray) -> Tuple[float, np.ndarray, np.ndarray]:
653625

654626
def build_psi_vec(self, x: np.ndarray) -> None:
655627
"""
656-
Build the psi vector required for predictive methods.
657-
658-
Args:
659-
x (ndarray): Point to calculate the psi vector for.
660-
661-
Returns:
662-
None
663-
664-
Modifies:
665-
self.psi (np.ndarray): Updates the psi vector.
666-
667-
Examples:
668-
>>> import numpy as np
669-
from spotpython.build.kriging import Kriging
670-
X_train = np.array([[1., 2.],
671-
[2., 4.],
672-
[3., 6.]])
673-
y_train = np.array([1., 2., 3.])
674-
S = Kriging(name='kriging',
675-
seed=123,
676-
log_level=50,
677-
n_theta=1,
678-
^ cod_type="norm")
679-
S.fit(X_train, y_train)
680-
# force theta to simple values:
681-
S.theta = np.array([0.0])
682-
nat_X = np.array([1., 0.])
683-
S.psi = np.zeros((S.n, 1))
684-
S.build_psi_vec(nat_X)
685-
res = np.array([[np.exp(-4)],
686-
[np.exp(-17)],
687-
[np.exp(-40)]])
688-
assert np.array_equal(S.psi, res)
689-
print(f"S.psi: {S.psi}")
690-
print(f"Control value res: {res}")
628+
Build the psi vector required for predictive methods.
629+
630+
Args:
631+
x (ndarray): Point to calculate the psi vector for.
632+
633+
Returns:
634+
None
635+
636+
Modifies:
637+
self.psi (np.ndarray): Updates the psi vector.
638+
639+
Examples:
640+
>>> import numpy as np
641+
from spotpython.build.kriging import Kriging
642+
X_train = np.array([[1., 2.],
643+
[2., 4.],
644+
[3., 6.]])
645+
y_train = np.array([1., 2., 3.])
646+
S = Kriging(name='kriging',
647+
seed=123,
648+
log_level=50,
649+
n_theta=1,
650+
cod_type="norm")
651+
S.fit(X_train, y_train)
652+
# force theta to simple values:
653+
S.theta = np.array([0.0])
654+
nat_X = np.array([1., 0.])
655+
S.psi = np.zeros((S.n, 1))
656+
S.build_psi_vec(nat_X)
657+
res = np.array([[np.exp(-4)],
658+
[np.exp(-17)],
659+
[np.exp(-40)]])
660+
assert np.array_equal(S.psi, res)
661+
print(f"S.psi: {S.psi}")
662+
print(f"Control value res: {res}")
691663
"""
692664
try:
693665
n = self.X_.shape[0]
@@ -764,17 +736,6 @@ def _pred(self, x: np.ndarray) -> float:
764736
resid_tilde = np.linalg.solve(U, resid)
765737
resid_tilde = np.linalg.solve(U.T, resid_tilde)
766738

767-
# Build psi (modified in 0.31.0)
768-
# X = self.X_
769-
# p = self.p_val
770-
# theta = self.theta
771-
# # theta is in log scale, so transform it back:
772-
# theta10 = 10.0**theta
773-
# psi = np.ones(n)
774-
# for i in range(n):
775-
# dist_vec = np.abs(X[i, :] - x) ** p
776-
# psi[i] = np.exp(-np.sum(theta10 * dist_vec))
777-
778739
psi = self.build_psi_vec(x)
779740

780741
# Compute SigmaSqr and SSqr

src/spotpython/utils/init.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -801,14 +801,16 @@ def surrogate_control_init(
801801
Note:
802802
* The surrogate_control dictionary is used in the Spot class. The following values
803803
are updated in the Spot class if they are None in the surrogate_control dictionary:
804-
* `method`: If the surrogate model dictionary is passed to the Spot class,
804+
* `method`:
805+
If the surrogate model dictionary is passed to the Spot class,
805806
and the `method` value is `None`, then the method value is set in the
806807
Spot class based on the value of `method` in the Spot class fun_control dictionary.
807-
* `var_type`: The `var_type` value is set in the Spot class based on the value
808-
of `var_type` in the Spot class fun_control dictionary and the dimension of the problem.
808+
* `var_type`:
809+
The `var_type` value is set in the Spot class based on the value of `var_type` in the Spot class fun_control dictionary and the dimension of the problem.
809810
If the Kriging model is used as a surrogate in the Spot class, the setting from
810811
surrogate_control_init() is overwritten.
811-
* `isotropic`: If the `isotropic` value is set to `True`, then the theta values are isotropic, i.e., the same value is used for all dimensions. If it is set to `False`, then the theta values are anisotropic, i.e., different values are used for each dimension.
812+
* `isotropic`:
813+
If `True`, then the theta values are isotropic (same value for all dimensions). If `False`, then they are anisotropic (different values for each dimension).
812814
* The value `model_fun_evals` will used for the optimization of the surrogate model, e.g., theta values.
813815
Differential evaluation uses `maxiter = 1000` and sets the number of function evaluations to
814816
(maxiter + 1) * popsize * N, which results in 1000 * 15 * k,

0 commit comments

Comments
 (0)