2013-07-25 6 views
8

여러 입력 변수 (24에서 30 사이)가있는 대상 함수를 최적화하려고합니다. 이 변수는 세 가지 다른 통계 변수의 샘플이며 대상 함수 값은 t- 검정 확률 값입니다. 에러 함수는 원하는 t- 테스트 확률과 실제 t- 테스트 확률 사이의 오차 (차이의 제곱의 합)를 나타냅니다. 오류가 1e-8 미만인 경우에만 세 가지 t- 테스트 모두에 대한 해결책을 수락 할 수 있습니다.scipy에서 개별 변수 값을 사용하여 함수를 최소화하는 방법

나는 scipy.optimize.fmin을 사용하고 있었는데 잘 동작했습니다. 대상 함수가 0이 된 많은 솔루션이 있습니다.

문제는 변수가 0에서 10.0 사이에 있고 정수이거나 소수점 이하 자릿수가 하나 이상없는 해결책을 찾아야한다는 것입니다. 유효한 값의 예는 0 10 3 5.5 6.8입니다. 잘못된 값의 예 : -3 2.23 30 또는 0.16666667

목표 값이 실제 측정 데이터에서 나오기 때문에 적어도 하나의 솔루션이 있다는 것을 알고 있습니다. 원래 데이터가 손실되었으며, 내 작업은 데이터를 찾는 것입니다. 하지만 어떻게해야할지 모르겠다. 시행 착오를 사용하는 것은 선택 사항이 아닙니다. 왜냐하면 각 변수에 대해 약 100 개의 가능한 값이 있고 변수의 수를 고려할 때 가능한 경우의 수가 100 ** 30이 될 것이기 때문에 너무 많습니다. fmin 사용은 훌륭하지만, 신중한 값에서는 작동하지 않습니다.

해결 방법이 있습니까? 해결책을 찾기 위해 여러 시간 동안 프로그램을 실행해야하는 경우에는 문제가되지 않습니다. 그러나 며칠 내에 약 10 개의 목표 값에 대한 솔루션을 찾아야하며 새로운 아이디어가 없습니다. 여기

는 예 MWE입니다 :

정수 프로그래밍이라고하고 NP-하드입니다 당신이 (내가 당신의 설정을 이해하는 경우) 할 시도
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'은 Nelder-Mead 알고리즘을 사용합니다. SciPy 구현은'optimize.py' 파일의'_minimize_neldermead' 함수에 있습니다. 이 함수의 복사본을 가져 와서 함수의 빠른 검사에서 변수에 대한 변경 사항 ('x ...')을 원하는 값 (10 진수로 0에서 10 사이)으로 바꿀 수 있습니다. 변경합니다. (Succes 보장되지 않음) –

+0

당신의 아이디어로, 내가 할 수있는 최선의 방법은 약 t- 테스트 값마다 약 1e-5 차이입니다. 나는 조금 더 나아야한다 : 1e-8. 아직 평가판 모드로 프로그램을 실행 중입니다. 더 나은 해결책을 찾을 수 있습니다. – nagylzs

답변

2

; http://en.wikipedia.org/wiki/Integer_programming. 정수 솔루션을 찾고 있지 않다는 것을 알고 있습니다 만, 모든 입력을 10으로 곱하고 목표 함수를 100으로 나눈다면, 입력이 모두 정수 인 동일한 문제를 얻을 수 있습니다. 요점은, 당신의 입력은 분리되어 있다는 것입니다.

대상 함수는 convex, 2 차 함수이며 [0, 10] 간격의 실수 입력에 대해 신속하게이를 해결할 수있는 우수한 제약 최적화 알고리즘이 있습니다. 이것으로부터 반올림하거나 근처의 모든 수용 가능한 점을 검사 할 수 있지만 그 중 2^n이 있습니다. 여기서 n은 입력의 수입니다. 이렇게해도 최적의 솔루션은 이러한 점 중 하나가 될 수 있습니다.

정수 프로그래밍 문제에 대한 근사 알고리즘이 있으며 그 중 하나가 최적의 지점으로 이동하기에 충분할 때가 있습니다. 내가 인용 한 Wikipedia 기사에서 시도해 볼 수있는 것들의 목록이 있지만,이 문제를 해결하기 위해 당신이 행복하게 노력할 것이라는 것을 나는 모른다.

+0

솔루션을 찾기 위해 사용할 수있는 많은 알고리즘을 포함하므로이 솔루션을 수락하십시오. 또한 그것을 찾을 수있는 쉽고 정확한 방법이 없다고 설명합니다. – nagylzs