31

我有一个有一堆参数的函数。我不想手动设置所有参数,而是执行网格搜索。我有每个参数的可能值列表。对于每个可能的参数组合,我想运行我的函数来报告我的算法在这些参数上的性能。我想将这个结果存储在一个多维矩阵中,这样我就可以找到最大性能的索引,这反过来又会给我最好的参数。下面是现在的代码编写方式:

param1_list = [p11, p12, p13,...]
param2_list = [p21, p22, p23,...] # not necessarily the same number of values
...

results_size = (len(param1_list), len(param2_list),...)
results = np.zeros(results_size, dtype = np.float)

for param1_idx in range(len(param1_list)):
  for param2_idx in range(len(param2_list)):
    ...
    param1 = param1_list[param1_idx]
    param2 = param2_list[param2_idx]
    ...
    results[param1_idx, param2_idx, ...] = my_func(param1, param2, ...)

max_index = np.argmax(results) # indices of best parameters!

我想保留第一部分,我按原样定义列表,因为我希望能够轻松地操纵我搜索的值。

我还想按原样得到结果矩阵,因为我将可视化更改不同参数如何影响算法的性能。

不过,中间的那部分是相当重复和庞大的(特别是因为我有很多参数,我可能想添加或删除参数),我觉得应该有一种更简洁/优雅的方式来初始化结果矩阵,遍历所有索引,并设置适当的参数。

那么,有吗?

4

4 回答 4

43

您可以使用 sklearn 模块中的 ParameterGrid

http://scikit-learn.org/stable/modules/generated/sklearn.grid_search.ParameterGrid.html

例子

from sklearn.grid_search import ParameterGrid
param_grid = {'param1': [value1, value2, value3], 'paramN' : [value1, value2, valueM]}

grid = ParameterGrid(param_grid)

for params in grid:
    your_function(params['param1'], params['param2'])
于 2015-01-22T15:16:52.163 回答
11

我想scipy.optimize.brute这就是你所追求的。

>>> from scipy.optimize import brute
>>> a,f,g,j = brute(my_func,[param1_list,param2_list,...],full_output = True)

请注意,如果full_output参数为True,则将返回评估网格。

于 2012-11-13T23:33:07.030 回答
10

John VinyardSibelius Seraphini的解决方案是很好的内置选项,但如果您正在寻找更大的灵活性,您可以使用广播 + vectorize。用于ix_生成一组可广播的参数,然后将它们传递给函数的矢量化版本(但请参阅下面的警告):

a, b, c = range(3), range(3), range(3)
def my_func(x, y, z):
    return (x + y + z) / 3.0, x * y * z, max(x, y, z)

grids = numpy.vectorize(my_func)(*numpy.ix_(a, b, c))
mean_grid, product_grid, max_grid = grids

具有以下结果mean_grid

array([[[ 0.        ,  0.33333333,  0.66666667],
        [ 0.33333333,  0.66666667,  1.        ],
        [ 0.66666667,  1.        ,  1.33333333]],

       [[ 0.33333333,  0.66666667,  1.        ],
        [ 0.66666667,  1.        ,  1.33333333],
        [ 1.        ,  1.33333333,  1.66666667]],

       [[ 0.66666667,  1.        ,  1.33333333],
        [ 1.        ,  1.33333333,  1.66666667],
        [ 1.33333333,  1.66666667,  2.        ]]])

product grid

array([[[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]],

       [[0, 0, 0],
        [0, 1, 2],
        [0, 2, 4]],

       [[0, 0, 0],
        [0, 2, 4],
        [0, 4, 8]]])

max grid

array([[[0, 1, 2],
        [1, 1, 2],
        [2, 2, 2]],

       [[1, 1, 2],
        [1, 1, 2],
        [2, 2, 2]],

       [[2, 2, 2],
        [2, 2, 2],
        [2, 2, 2]]])

请注意,这可能不是最快的方法。vectorize很方便,但是受限于传递给它的函数的速度,python函数很慢。如果您可以重写my_func以使用 numpy ufuncs,如果您愿意,您可以更快地获得网格。像这样的东西:

>>> def mean(a, b, c):
...     return (a + b + c) / 3.0
... 
>>> mean(*numpy.ix_(a, b, c))
array([[[ 0.        ,  0.33333333,  0.66666667],
        [ 0.33333333,  0.66666667,  1.        ],
        [ 0.66666667,  1.        ,  1.33333333]],

       [[ 0.33333333,  0.66666667,  1.        ],
        [ 0.66666667,  1.        ,  1.33333333],
        [ 1.        ,  1.33333333,  1.66666667]],

       [[ 0.66666667,  1.        ,  1.33333333],
        [ 1.        ,  1.33333333,  1.66666667],
        [ 1.33333333,  1.66666667,  2.        ]]])
于 2012-11-14T01:48:03.940 回答
1

meshgrid您可以为此使用 numpy :

import numpy as np

x = range(1, 5)
y = range(10)

xx, yy = np.meshgrid(x, y)
results = my_func(xx, yy)

请注意,您的函数必须能够与numpy.arrays 一起使用。

于 2015-01-22T15:31:15.787 回答