복붙노트

[PYTHON] 범위와 파이썬 최적화에서 세계 최소를 찾는 방법?

PYTHON

범위와 파이썬 최적화에서 세계 최소를 찾는 방법?

64 개의 변수가있는 파이썬 함수가 있고 최소화 함수에서 L-BFGS-B 메서드를 사용하여 최적화하려고 시도했지만이 메서드는 초기 추측에 상당히 의존하고 전역 최소값을 찾지 못했습니다.

그러나 변수에 대한 경계를 설정하는 기능이 마음에 들었습니다. 변수의 경계를 가지면서 전역 최소값을 찾는 방법 / 함수가 있습니까?

해결법

  1. ==============================

    1.이것은 scipy.optimize.basinhopping으로 할 수 있습니다. Basinhopping은 목적 함수의 전역 최소값을 찾도록 설계된 함수입니다. scipy.optimize.minimize 함수를 사용하여 최소화 된 반복을 수행하고 각 최소화 후에 좌표 공간에서 임의의 단계를 취합니다. Basinhopping은 경계를 구현하는 최소화 기 중 하나 (예 : L-BFGS-B)를 사용하여 경계를 여전히 존중할 수 있습니다. 이 작업을 수행하는 방법을 보여주는 코드가 있습니다.

    이것은 scipy.optimize.basinhopping으로 할 수 있습니다. Basinhopping은 목적 함수의 전역 최소값을 찾도록 설계된 함수입니다. scipy.optimize.minimize 함수를 사용하여 최소화 된 반복을 수행하고 각 최소화 후에 좌표 공간에서 임의의 단계를 취합니다. Basinhopping은 경계를 구현하는 최소화 기 중 하나 (예 : L-BFGS-B)를 사용하여 경계를 여전히 존중할 수 있습니다. 이 작업을 수행하는 방법을 보여주는 코드가 있습니다.

    # an example function with multiple minima
    def f(x): return x.dot(x) + sin(np.linalg.norm(x) * np.pi)
    
    # the starting point
    x0 = [10., 10.]
    
    # the bounds
    xmin = [1., 1.]
    xmax = [11., 11.]
    
    # rewrite the bounds in the way required by L-BFGS-B
    bounds = [(low, high) for low, high in zip(xmin, xmax)]
    
    # use method L-BFGS-B because the problem is smooth and bounded
    minimizer_kwargs = dict(method="L-BFGS-B", bounds=bounds)
    res = basinhopping(f, x0, minimizer_kwargs=minimizer_kwargs)
    print res
    

    위의 코드는 단순한 경우에 효과적이지만 basinhopping 무작위 변위 루틴을 사용하면 금지 된 영역에서 끝날 수 있습니다. 다행히도 키워드 take_step을 사용하여 루틴을 가져 오는 맞춤 단계를 전달하면 재정의 할 수 있습니다.

    class RandomDisplacementBounds(object):
        """random displacement with bounds"""
        def __init__(self, xmin, xmax, stepsize=0.5):
            self.xmin = xmin
            self.xmax = xmax
            self.stepsize = stepsize
    
        def __call__(self, x):
            """take a random step but ensure the new position is within the bounds"""
            while True:
                # this could be done in a much more clever way, but it will work for example purposes
                xnew = x + np.random.uniform(-self.stepsize, self.stepsize, np.shape(x))
                if np.all(xnew < self.xmax) and np.all(xnew > self.xmin):
                    break
            return xnew
    
    # define the new step taking routine and pass it to basinhopping
    take_step = RandomDisplacementBounds(xmin, xmax)
    result = basinhopping(f, x0, niter=100, minimizer_kwargs=minimizer_kwargs,
                          take_step=take_step)
    print result
    
  2. ==============================

    2.최적화 도구를 디버깅하고 시각화하기위한 몇 가지 상식적인 제안 귀하의 기능 :

    최적화 도구를 디버깅하고 시각화하기위한 몇 가지 상식적인 제안 귀하의 기능 :

    목적 함수와 제약 조건이 합리적입니까? 목적 함수가 f () + g ()라고하는 합인 경우, "fx-opt.nptxt"(아래)에서 모든 x에 대해 개별적으로 인쇄하십시오. f ()가 합계의 99 %이고 g () 1 % 인 경우 조사하십시오.

    제약 조건 (Constraints) : xfinal에서 얼마나 많은 구성 요소 x_i가 경계에 갇혔는지, x_i <= lo_i 또는> = hi_i?

    세계적인 수준에서 당신의 기능이 얼마나 울퉁불퉁합니까? 여러 개의 임의 시작점을 사용하여 실행하고 결과를 분석 / 플롯에 저장합니다.

    title = "%s  n %d  ntermhess %d  nsample %d  seed %d" % (  # all params!
        __file__, n, ntermhess, nsample, seed )
    print title
    ...
    np.random.seed(seed)  # for reproducible runs
    np.set_printoptions( threshold=100, edgeitems=10, linewidth=100,
            formatter = dict( float = lambda x: "%.3g" % x ))  # float arrays %.3g
    
    lo, hi = bounds.T  # vecs of numbers or +- np.inf
    print "lo:", lo
    print "hi:", hi
    
    fx = []  # accumulate all the final f, x
    for jsample in range(nsample):
            # x0 uniformly random in box lo .. hi --
        x0 = lo + np.random.uniform( size=n ) * (hi - lo)
    
        x, f, d = fmin_l_bfgs_b( func, x0, approx_grad=1,
                    m=ntermhess, factr=factr, pgtol=pgtol )
        print "f: %g  x: %s  x0: %s" % (f, x, x0)
        fx.append( np.r_[ f, x ])
    
    fx = np.array(fx)  # nsample rows, 1 + dim cols
    np.savetxt( "fx-opt.nptxt", fx, fmt="%8.3g", header=title )  # to analyze / plot
    
    ffinal = fx[:,0]
    xfinal = fx[:,1:]
    print "final f values, sorted:", np.sort(ffinal)
    jbest = ffinal.argmin()
    print "best x:", xfinal[jbest]
    

    최종 가치 중 일부가 합리적으로 양호한 것으로 보이는 경우, 그 근처에서 더 무작위 시작점을 시도하십시오 - 분명히 순수 무작위보다 낫다.

    x s가 곡선이거나 실제 값이라면 x 0과 x final을 가장 잘 나타내야합니다. (엄지 손가락의 규칙은 d 차원에서 nsample ~ 5 * d 또는 10 * d입니다. 너무 천천히, 너무 많이? maxiter / maxeval 감소, ftol 감소 - 당신은 이것을 탐구하는데 ftol 1e-6이 필요 없다.)

    재현 가능한 결과를 원한다면, 그런 다음 제목에 관련된 모든 매개 변수를 나열해야합니다 파생 된 파일 및 플롯에서. 그렇지 않으면, 당신은 "이게 어디에서 온거야?"

    엡실론 규모에서 ~ 10 ^ -6 정도의 기능이 얼마나 울퉁불퉁합니까? 그라디언트를 근사하는 메소드는 때때로 마지막 추정치를 반환하지만, 하지만 그렇지 않은 경우 :

    from scipy.optimize._numdiff import approx_derivative  # 3-point, much better than
    ## from scipy.optimize import approx_fprime
    for eps in [1e-3, 1e-6]:
        grad = approx_fprime( x, func, epsilon=eps )
        print "approx_fprime eps %g: %s" % (eps, grad)
    

    그러나 옵티마이 저가 종료되기 전에 그래디언트 추정치가 좋지 않거나 울퉁불퉁 한 경우, 너는 그것을 보지 못할 것이다. 그런 다음 모든 중간 [f, x, approx_fprime]을 저장해야합니다. 그들을 보는 것도; 파이썬으로 쉽게 - 명확하지 않은지 물어보십시오.

    일부 문제 영역에서는 백업 된 것으로 간주되는 xmin에서 다시 시작하는 것이 일반적입니다. 예를 들어, 시골 길에서 길을 잃은 경우, 먼저 주요 도로를 찾은 다음 거기에서 다시 시작하십시오.

    개요: 블랙 박스 최적화 도구가 어떤 함수에서 작동하는지 기대하지 마십시오. 대형 울퉁 불퉁한, 또는 엡실론 - 스케일 울퉁불퉁, 또는 둘 다. 테스트 스 캐 폴딩에 투자하고 옵티마이 저가 수행하는 방법을 확인합니다.

  3. ==============================

    3.귀하의 상세한 답변을 많이 주셔서 감사합니다. 그러나 저는 Python을 처음 접했을 때, 프로그램에 코드를 구현하는 방법을 알지 못했지만 여기에 최적화를 시도했습니다.

    귀하의 상세한 답변을 많이 주셔서 감사합니다. 그러나 저는 Python을 처음 접했을 때, 프로그램에 코드를 구현하는 방법을 알지 못했지만 여기에 최적화를 시도했습니다.

    x0=np.array((10, 13, f*2.5, 0.08,    10, f*1.5,  0.06, 20, 
                 10, 14, f*2.5, 0.08,    10, f*1.75, 0.07, 20,
                 10, 15, f*2.5, 0.08,    10, f*2,    0.08, 20,
                 10, 16, f*2.5, 0.08,    10, f*2.25, 0.09, 20,
                 10, 17, f*2.5, -0.08,    10, f*2.5, -0.06, 20,
                 10, 18, f*2.5, -0.08,    10, f*2.75,-0.07, 20,
                 10, 19, f*2.5, -0.08,    10, f*3,   -0.08, 20,
                 10, 20, f*2.5, -0.08,    10, f*3.25,-0.09, 20))
    
    # boundary for each variable, each element in this restricts the corresponding element     above
    bnds=((1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), 
      (1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), 
      (1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), 
      (1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), 
      (1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), 
      (1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), 
      (1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), 
      (1,12), (1,35), (0,f*6.75), (-0.1, 0.1),(1,35), (0,f*6.75), (-0.1, 0.1),(13, 35), )
    
    from scipy.optimize import basinhopping
    from scipy.optimize import minimize
    
    merit=a*meritoflength + b*meritofROC + c*meritofproximity +d*(distancetoceiling+distancetofloor)+e*heightorder
    minimizer_kwargs = {"method": "L-BFGS-B", "bounds": bnds, "tol":1e0}
    ret = basinhopping(merit_function, x0, minimizer_kwargs=minimizer_kwargs, niter=10, T=0.01)
    
    zoom = ret['x']
    res = minimize(merit_function, zoom, method = 'L-BFGS-B', bounds=bnds, tol=1e-5)
    print res
    

    merit 함수는 x0을 다른 값과 결합하여 8 개의 곡선에 대한 6 개의 제어점을 형성 한 다음 길이, 곡률 반경 등을 계산합니다. 최종 가중치는 일부 매개 변수가있는 해당 매개 변수의 선형 조합으로 반환됩니다.

    나는 최소 정밀도로 basinhopping을 사용하여 최소값을 찾은 다음 최소값을 사용하여 최소값의 정밀도를 높입니다.

    추신. 내가 실행중인 플랫폼은 Enthoght canopy 1.3.0, numpy 1.8.0 scipy 0.13.2 mac 10.8.3

  4. from https://stackoverflow.com/questions/21670080/how-to-find-global-minimum-in-python-optimization-with-bounds by cc-by-sa and MIT license