2012-11-13 28 views
14

Tôi có một hàm có nhiều tham số. Thay vì đặt tất cả các tham số theo cách thủ công, tôi muốn thực hiện tìm kiếm lưới. Tôi có một danh sách các giá trị có thể cho mỗi tham số. Đối với mọi kết hợp các thông số có thể, tôi muốn chạy hàm của mình báo cáo hiệu suất của thuật toán của tôi trên các tham số đó. Tôi muốn lưu trữ các kết quả của điều này trong một ma trận nhiều chiều, vì vậy mà từ sau tôi chỉ có thể tìm thấy chỉ số của hiệu suất tối đa, mà lần lượt sẽ cho tôi những thông số tốt nhất. Sau đây là cách mã được viết tại:Tìm kiếm lưới thanh lịch trong 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! 

Tôi muốn giữ lại phần đầu tiên, nơi tôi xác định danh sách như nó vốn có, vì tôi muốn một cách dễ dàng có thể thao tác các giá trị trên mà tôi tìm kiếm.

Tôi cũng muốn kết thúc với ma trận kết quả như vậy, vì tôi sẽ hình dung cách thay đổi các thông số khác nhau ảnh hưởng đến hiệu suất của thuật toán. Một chút ở giữa, mặc dù, là khá lặp đi lặp lại và cồng kềnh (đặc biệt là bởi vì tôi có rất nhiều tham số, và tôi có thể muốn thêm hoặc loại bỏ các thông số), và tôi cảm thấy cần phải có một cách gọn gàng hơn/thanh lịch hơn để khởi tạo ma trận kết quả, lặp lại tất cả các chỉ mục và thiết lập các tham số thích hợp.

Vì vậy, có?

+2

có vẻ như bạn đang tìm kiếm 'itertools.product' –

+0

Ahh, thật vậy! Điều này sẽ đơn giản hóa mọi thứ một chút! – dlants

+0

về cơ bản, đây là bản sao gần: http://stackoverflow.com/questions/1316068/pythonic-way-of-iterating-over-3d-array –

Trả lời

8

Tôi nghĩ rằng scipy.optimize.brute là những gì bạn đang theo dõi.

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

Lưu ý rằng nếu đối số full_outputTrue, lưới đánh giá sẽ được trả lại.

+0

Tôi đã đơn giản hóa tình huống trên một chút. Tôi thực sự báo cáo nhiều giá trị dưới dạng đầu ra (một số hàm đánh giá), vì vậy kết quả của tôi là kết quả [p1idx, p2idx, ...,:,:,:] = ma trận 3d của các giá trị đầu ra. Tôi không nghĩ rằng tôi có thể sử dụng tìm kiếm bruteforce từ scipy vì điều này. Giải pháp của bạn hoàn toàn đúng với vấn đề tôi đã đăng ở trên, nhưng tôi đang tìm cách đơn giản hóa mã đó để tạo ma trận kết quả mà không cần sử dụng chức năng tìm kiếm lưới hiện có. – dlants

+0

Có phải trường hợp bạn đang cố gắng tìm các tham số đầu vào tốt nhất cho một trong nhiều đầu ra vô hướng, ví dụ: "Cung cấp cho tôi đầu vào giảm thiểu kết quả [i]" hoặc bạn có một số cách đánh giá "tốt" của tất cả các kết quả cùng một lúc, như tổng hợp, hoặc l1 hoặc l2 tiêu chuẩn? –

+1

Các giá trị là chính xác, chính xác và thu hồi đối với các đối tượng khác nhau. Tôi sẽ lấy độ chính xác tối thiểu trong độ chính xác của từng loại đối tượng, và trên các đối tượng, và kết hợp các phép đo chính xác và thu hồi theo nhiều cách khác nhau. – dlants

6

John Vinyard 's giải pháp có vẻ đúng; nhưng nếu bạn đang tìm kiếm sự linh hoạt hơn, bạn có thể sử dụng phát sóng + vectorize. Sử dụng ix_ để sản xuất một bộ broadcastable các thông số, và sau đó vượt qua những sang một phiên bản vectorized của hàm (nhưng xem caveat dưới đây):

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 

Với kết quả như sau cho 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]]]) 

Lưu ý rằng đây có thể không phải là cách tiếp cận nhanh nhất. vectorize là tiện dụng, nhưng nó bị giới hạn bởi tốc độ của hàm được truyền cho nó và các hàm python chậm. Nếu bạn có thể viết lại my_func để sử dụng numpy ufuncs, bạn có thể nhận được lưới của mình nhanh hơn, nếu bạn quan tâm.Một cái gì đó như thế này:

>>> 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

Bạn có thể sử dụng ParameterGrid từ các module sklearn

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

Ví dụ

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

Phiên bản mới của mô-đun: 'from sklearn.model_selection import ParameterGrid' – Abramodj

1

Bạn có thể sử dụng NumPy meshgrid cho việc này:

import numpy as np 

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

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

lưu ý rằng chức năng của bạn phải có thể hoạt động với numpy.array s.

Các vấn đề liên quan