2012-11-13 3 views
14

私は、たくさんのパラメータを持つ関数を持っています。すべてのパラメータを手動で設定するのではなく、グリッド検索を実行する必要があります。私は、各パラメータに可能な値のリストを持っています。すべての可能なパラメータの組み合わせについて、それらのパラメータに対する私のアルゴリズムの性能を報告する関数を実行したい。私はこの結果を多次元の行列に保存したいので、あとで最大のパフォーマンスのインデックスを見つけることができます。これにより、最高のパラメータが得られます。ここでは、コードは現在書かれている方法です。pythonでのエレガントなグリッド検索/ numpy

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! 

私は-であるように私は簡単に私が検索した上で値を操作できるようにしたいので、私は、リストを定義最初の部分を、維持したいです。

さまざまなパラメータの変更がアルゴリズムのパフォーマンスにどのように影響するかを視覚化するため、結果マトリックスをそのまま使用したいと考えています。

途中のビットはかなり反復して嵩張っています(特にパラメータがたくさんあるので、パラメータを追加したり削除したいかもしれません)、もっと簡潔でエレガントな方法が必要です結果行列を初期化し、すべてのインデックスを反復し、適切なパラメータを設定します。

だから、そこにはありますか?

+2

あなたが 'itertools.product'を探しているようです。 –

+0

ああ、確かに!これはかなり簡単になります! – dlants

+0

本質的に、ここにはほぼ同じです:http://stackoverflow.com/questions/1316068/pythonic-way-of-iterating-over-3d-array –

答えて

8

私はscipy.optimize.bruteがあなたの後であると思います。 full_output引数がTrueであれば、評価グリッドが返されること

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

は注意してください。

+0

私は少し上の状況を単純化しました。私は実際に出力として複数の値を報告しています(いくつかの評価関数)ので、私の結果行は結果です。[p1idx、p2idx、...、:、:、:] =出力値の3次元行列。私はこれのためにscipyからbruteforce検索を使用できるとは思わない。 あなたのソリューションは上記の問題に対して厳密に正しいですが、既存のgridsearch関数に頼らずに結果行列を作成するためのコードを簡略化する方法を探しています。 – dlants

+0

多くのスカラー出力のうちの1つに最適な入力パラメータを見つけようとしているのでしょうか?たとえば、「結果を最小限に抑える入力を与えてください」、または「良さ」を評価する何らかの方法がありますか?総計、またはl1またはl2ノルムのように、一度にすべての結果を表示しますか? –

+1

この値は、さまざまなオブジェクトの精度、精度、再呼び出しです。私は、各オブジェクトカテゴリ内、オブジェクト間の正確さの厳密な最小値をとり、精度とリコールの測定値をさまざまな方法で組み合わせます。 – dlants

6

John Vinyardの解決策は正しいようです。より柔軟性が求められる場合は、ブロードキャスト+ vectorizeを使用することができます。パラメータのbroadcastableセットを生成し、次に関数のベクトル化バージョンにそれらを渡す(ただし、警告下記参照)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関数は遅いです。数字のufuncsを使用するようにmy_funcを書き直すことができたら、あなたが気にしていれば、あなたのグリッドをより速く得ることができます。このような何か:

>>> 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.  ]]]) 
7

あなたは

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

sklearnモジュールからParameterGridを使用することができます例

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']) 
+0

モジュールの新しいバージョン: 'from sklearn.model_selection import ParameterGrid' – Abramodj

1

あなたはこのためにnumpyのmeshgridを使用することがあります。

import numpy as np 

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

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

あなたの関数はnumpy.arrayで動作する必要があります。

関連する問題