假设我正在搜索一个维度:
from skopt import space
search_space = [
space.Real(1, 10, name="my_scale")
]
我怎样才能用离散的步骤搜索这个实数?例如。 0.25。因为就我而言,可以缓存每个实际值的计算数据,并且我知道以 0.00001 等小步长微调值不会带来有意义的改进。但是,如果计算出的值是 1.25、1.50、1.75 等。我可以缓存结果并大大加快优化过程。
例如类似的东西
search_space = [
space.Real(1, 10, step=0.25, name="my_scale")
]
我对
skopt
没有太多经验,但我想知道这样的事情是否会对你有帮助:
def generate_discrete_values(start, end, step):
values = []
while start <= end:
values.append(round(start, 2))
start += step
return values
随后,我会将其输入
skopt
,尽管我正在检查如何做到这一点 - 我正在审查 API。
会更新...
生成这些离散值的列表并使用 space.Categorical 而不是 space.Real。
from skopt import space, gp_minimize
from skopt.utils import use_named_args
start, end, step = 1, 10, 0.25
discrete_values = [round(start + i * step, 2) for i in range(int((end - start) / step) + 1)]
search_space = [space.Categorical(discrete_values, name="my_scale")]
@use_named_args(search_space)
def objective_function(my_scale):
return (my_scale - 5) ** 2
result = gp_minimize(objective_function, search_space, n_calls=50, random_state=0)
print(result.x)
print(result.fun)
为了确保搜索行为呈线性,同时仍采取离散步骤,您可以创建一个继承自 space.Real 的自定义维度类。
这个自定义类将定义一个空间,其行为类似于真实维度,但采取离散步骤。
您可以按如下方式实现:
from skopt import space, gp_minimize
from skopt.utils import use_named_args
import numpy as np
class DiscreteReal(space.Real):
def __init__(self, low, high, step, name=None):
super().__init__(low, high, name=name)
self.step = step
self.values = np.arange(low, high + step, step)
def rvs(self, n_samples=1, random_state=None):
rng = random_state if random_state is not None else np.random.default_rng()
return rng.choice(self.values, size=n_samples)
def _transform(self, X):
return X
def _inverse_transform(self, Xt):
return Xt
def bounds(self):
return (self.low, self.high)
def __repr__(self):
return f"DiscreteReal(low={self.low}, high={self.high}, step={self.step}, name={self.name})"
# Usage example
search_space = [ DiscreteReal(1, 10, step=0.25, name="my_scale") ]
print(search_space)
@use_named_args(search_space)
def objective_function(my_scale):
return (my_scale - 5) ** 2
result = gp_minimize(objective_function, search_space, n_calls=50, random_state=0)
print(result.x)
print(result.fun)
rvs
方法从可能的值生成随机样本。
transform
和inverse_transform
方法保留为恒等函数,因为离散步骤不需要它们。
bounds
方法返回维度的边界。
__repr__
方法提供对象的字符串表示形式。
此自定义维度将在搜索空间中使用,并确保优化过程遵循离散步骤,同时仍然在指定范围内线性运行。
提供的代码输出:
[DiscreteReal(low=1, high=10, step=0.25, name=my_scale)]
/home/o/.local/lib/python3.10/site-packages/skopt/optimizer/optimizer.py:517: UserWarning: The objective has been evaluated at point [5.0] before, using random point [1.0]
warnings.warn(
[5.0]
0.0