2013-07-25 24 views
8

Tôi đang cố gắng tối ưu hóa hàm mục tiêu có nhiều biến đầu vào (từ 24 đến 30). Các biến này là các mẫu của ba biến thống kê khác nhau, và các giá trị hàm đích là các giá trị xác suất t-test. Hàm lỗi biểu thị lỗi (tổng các bình phương của sự khác biệt) giữa xác suất t và test thực tế mong muốn. Tôi chỉ có thể chấp nhận các giải pháp mà lỗi nhỏ hơn 1e-8, cho tất cả ba bài kiểm tra t.cách giảm thiểu một hàm có giá trị biến riêng biệt trong scipy

Tôi đã sử dụng scipy.optimize.fmin và nó hoạt động tốt. Có rất nhiều giải pháp mà hàm đích đã trở thành 0.

Vấn đề là tôi cần tìm giải pháp trong đó các biến nằm trong khoảng từ 0 đến 10,0, và là số nguyên hoặc không có nhiều hơn một phần phân số. Ví dụ về các giá trị hợp lệ là 0 10 3 5.5 6.8. Ví dụ về các giá trị không hợp lệ: -3 2.23 30 hoặc 0.16666667.

Tôi tình cờ biết rằng có ít nhất một giải pháp, vì giá trị đích đến từ dữ liệu đo thực tế. Dữ liệu gốc đã bị mất và nhiệm vụ của tôi là tìm chúng. Nhưng tôi không biết làm thế nào. Sử dụng thử/lỗi không phải là một lựa chọn, bởi vì có khoảng 100 giá trị có thể cho mỗi biến, và với số lượng biến, số lượng trường hợp có thể là 100 ** 30 là quá nhiều. Sử dụng fmin là tuyệt vời, tuy nhiên nó không hoạt động với các giá trị kín đáo.

Có cách nào để giải quyết vấn đề này không? Nó không phải là một vấn đề nếu tôi cần phải chạy một chương trình trong nhiều giờ để tìm một giải pháp. Nhưng tôi cần phải tìm các giải pháp cho khoảng 10 giá trị mục tiêu trong vòng một vài ngày và tôi không có ý tưởng mới.

Dưới đây là một ví dụ MWe:

import math 
import numpy 
import scipy.optimize 
import scipy.stats 
import sys 

def log(s): 
    sys.stdout.write(str(s)) 
    sys.stdout.flush() 

# List of target T values: TAB, TCA, TCB 
TARGETS = numpy.array([ 
    [0.05456834, 0.01510358, 0.15223353 ], # task 1 to solve 
    [0.15891875, 0.0083665,  0.00040262 ], # task 2 to solve 
]) 
MAX_ERR = 1e-10 # Maximum error in T values 
NMIN,NMAX = 8,10 # Number of samples for T probes. Inclusive. 

def fsq(x, t, n): 
    """Returns the differences between the target and the actual values.""" 
    a,b,c = x[0:n],x[n:2*n],x[2*n:3*n] 
    results = numpy.array([ 
     scipy.stats.ttest_rel(a,b)[1], # ab 
     scipy.stats.ttest_rel(c,a)[1], # ca 
     scipy.stats.ttest_rel(c,b)[1] # cb 
    ]) 
    # Sum of squares of diffs 
    return (results - t) 

def f(x, t, n): 
    """This is the target function that needs to be minimized.""" 
    return (fsq(x,t,n)**2).sum() 

def main(): 
    for tidx,t in enumerate(TARGETS): 
     print "=============================================" 
     print "Target %d/%d"%(tidx+1,len(TARGETS)) 
     for n in range(NMIN,NMAX+1): 
      log(" => n=%s "%n) 
      successful = False 
      tries = 0 
      factor = 0.1 
      while not successful: 
       x0 = numpy.random.random(3*n) * factor 
       x = scipy.optimize.fmin(f,x0, [t,n], xtol=MAX_ERR, ftol=MAX_ERR) 
       diffs = fsq(x,t,n) 
       successful = (numpy.abs(diffs)<MAX_ERR).all() 
       if successful: 
        log(" OK, error=[%s,%s,%s]\n"%(diffs[0],diffs[1],diffs[2])) 
        print " SOLUTION FOUND " 
        print x 
       else: 
        tries += 1 
        log(" FAILED, tries=%d\n"%tries) 
        print diffs 
        factor += 0.1 
        if tries>5: 
         print "!!!!!!!!!!!! GIVING UP !!!!!!!!!!!" 
         break 
if __name__ == "__main__": 
    main() 
+0

'scipy.optimize.fmin' sử dụng thuật toán Nelder-Mead, việc triển khai SciPy này nằm trong hàm' _minimize_neldermead' trong tệp 'optimize.py'. Bạn có thể lấy một bản sao của hàm này và viết lại nó, để làm tròn các thay đổi cho các biến ('x ...' từ việc kiểm tra nhanh hàm) tới các giá trị bạn muốn (từ 0 đến 10 với một số thập phân) bất cứ khi nào hàm thay đổi chúng. (Succes không được bảo đảm) –

+0

Với ý tưởng của bạn, tốt nhất tôi có thể làm là khoảng 1e-5 sự khác biệt cho mỗi giá trị t-test. Tôi cần một chút tốt hơn: 1e-8. Vẫn chạy chương trình ở chế độ dùng thử. Nó có thể tìm thấy một giải pháp tốt hơn. – nagylzs

Trả lời

2

gì bạn đang cố gắng để làm (nếu tôi hiểu thiết lập của bạn) được gọi là lập trình số nguyên và nó là NP-hard; http://en.wikipedia.org/wiki/Integer_programming. Tôi nhận ra rằng bạn không tìm kiếm các giải pháp số nguyên, nhưng nếu bạn nhân tất cả các đầu vào của mình bằng 10 và chia hàm mục tiêu của bạn thành 100, bạn sẽ có được một vấn đề tương đương trong đó các đầu vào là tất cả các số nguyên. Vấn đề là, đầu vào của bạn là rời rạc.

Chức năng đích mà bạn đang làm việc là hàm lồi, bậc hai và có các thuật toán tối ưu hóa hạn chế tốt sẽ giải quyết nhanh chóng cho các giá trị đầu vào thực trong khoảng [0, 10]. Từ đó bạn có thể thử làm tròn hoặc kiểm tra tất cả các điểm chấp nhận được ở gần, nhưng có 2^n trong số đó, trong đó n là số lượng đầu vào. Ngay cả khi bạn làm điều này, giải pháp tối ưu không được đảm bảo là một trong những điểm này.

Có các thuật toán xấp xỉ cho các vấn đề lập trình số nguyên và bạn có thể thấy rằng đôi khi một trong số chúng hoạt động đủ tốt để giúp bạn đạt được điểm tối ưu. Có một danh sách những điều bạn có thể thử trong bài viết Wikipedia tôi trích dẫn, nhưng tôi không biết rằng bạn sẽ rất vui khi cố gắng giải quyết vấn đề này.

+0

Chấp nhận giải pháp này bởi vì nó chứa một số lượng lớn các thuật toán có thể được sử dụng để tìm giải pháp. Ngoài ra nó mô tả rằng không có cách dễ dàng và chính xác để tìm thấy nó. – nagylzs

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