Python:没有机器学习的网格搜索?

7
我希望优化一个具有多个可变参数作为输入的算法。
对于机器学习任务,Sklearn提供了使用gridsearch功能来优化超参数的方法。
是否有一种标准化的方式/Python库,允许优化超参数,而不仅限于机器学习主题?
4个回答

4

3

您可以考虑使用scipy的optimize.brute,它本质上与之相同,但在API使用方面没有那么受限制。 您只需定义一个返回标量的函数。

通过暴力枚举方法,在给定范围内最小化函数。

使用“暴力枚举”方法,即计算多维点阵中每个点的函数值,以找到函数的全局最小值。

文档的无耻示例复制:

代码

import numpy as np
from scipy import optimize


params = (2, 3, 7, 8, 9, 10, 44, -1, 2, 26, 1, -2, 0.5)
def f1(z, *params):
    x, y = z
    a, b, c, d, e, f, g, h, i, j, k, l, scale = params
    return (a * x**2 + b * x * y + c * y**2 + d*x + e*y + f)

def f2(z, *params):
    x, y = z
    a, b, c, d, e, f, g, h, i, j, k, l, scale = params
    return (-g*np.exp(-((x-h)**2 + (y-i)**2) / scale))


def f3(z, *params):
    x, y = z
    a, b, c, d, e, f, g, h, i, j, k, l, scale = params
    return (-j*np.exp(-((x-k)**2 + (y-l)**2) / scale))


def f(z, *params):
    return f1(z, *params) + f2(z, *params) + f3(z, *params)

rranges = (slice(-4, 4, 0.25), slice(-4, 4, 0.25))
resbrute = optimize.brute(f, rranges, args=params, full_output=True,
                          finish=optimize.fmin)
print(resbrute[:2])  # x0, feval

输出

(array([-1.05665192,  1.80834843]), -3.4085818767996527)

暴力函数并不是什么黑魔法,通常我们可以考虑自己实现。上面的scipy示例有一个更有趣的特性:

finish:可选的可调用优化函数,使用暴力力量最小化的结果作为初始猜测进行调用。finish应该将func和初始猜测作为位置参数,并将args作为关键字参数。它还可以将full_output和/或disp作为关键字参数。如果不使用“polishing”功能,则使用None。有关详情,请参见注释。

我建议在大多数情况下(在连续空间中)使用它。但请确保对此有一些基本的了解,以了解您不希望执行此操作的用例(需要离散空间结果;函数评估缓慢)。
如果您正在使用sklearn,则已经安装了scipy(它是一个依赖项)。
编辑:这里是我创建的一个小图(code),展示了finish在一个1d示例中的局部优化效果(不是最好的示例,但更容易绘制)。

enter image description here


2
您也可以看一下贝叶斯优化。在这个Github存储库中,您可以找到简单的实现。
区别在于,贝叶斯优化不会查看您输入范围内的具体值,而是寻找范围内的值。
以下示例来自他们的存储库,以便您可以看到实现有多么简单!
def black_box_function(x, y):
    """Function with unknown internals we wish to maximize.

    This is just serving as an example, for all intents and
    purposes think of the internals of this function, i.e.: the process
    which generates its output values, as unknown.
    """
    return -x ** 2 - (y - 1) ** 2 + 1

from bayes_opt import BayesianOptimization

# Bounded region of parameter space
pbounds = {'x': (2, 4), 'y': (-3, 3)}

optimizer = BayesianOptimization(
    f=black_box_function,
    pbounds=pbounds,
    random_state=1,
)

optimizer.maximize(
    init_points=2,
    n_iter=3,
)

print(optimizer.max)
>>> {'target': -4.441293113411222, 'params': {'y': -0.005822117636089974, 'x': 2.104665051994087}}

感谢分享这个仓库,但是我想使用pbounds作为整数值,例如'x':(11,20),以便在优化过程中只选择11到20之间的整数值,这种做法可行吗?因为我在代码中出现了错误。 - Pianistprogrammer
请参考以下链接:https://github.com/fmfn/BayesianOptimization/issues/292#issuecomment-1020076915。 - Alex L

1
Sklearn也可以独立于机器学习主题使用,因此为了完整起见,我建议:
from sklearn.model_selection import ParameterGrid
param_grid = {'value_1': [1, 2, 3], 'value_2': [0, 1, 2, 3, 5]}
for params in ParameterGrid(param_grid):
    function(params['value_1'], params['value_2'])

在此处找到详细的文档这里

1
我认为您忘记使用从sklearn.model_selection导入的ParameterGrid类。就目前而言,这个答案没有多少意义。 - Alberto Schiabel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接