Main Content

스칼라 목적 함수 작성하기

함수 파일

스칼라 목적 함수 파일은 하나의 입력값, x를 받으며 하나의 실수형 스칼라 출력값, f를 반환합니다. 입력값 x는 스칼라, 벡터 또는 행렬일 수 있습니다. 하나의 함수 파일에서 더 많은 출력값을 반환할 수 있습니다(기울기와 헤세 행렬 포함시키기 참조).

예를 들어, 목적 함수가 다음과 같이 세 가지 변수 x, y, z로 구성된 함수라고 가정하겠습니다.

f(x) = 3*(x – y)4 + 4*(x + z)2 / (1 + x2 + y2 + z2) + cosh(x – 1) + tanh(y + z).

  1. 이 함수를 벡터 xin = [x;y;z]를 받고 f를 반환하는 파일로 작성합니다.

    function f = myObjective(xin)
    f = 3*(xin(1)-xin(2))^4 + 4*(xin(1)+xin(3))^2/(1+norm(xin)^2) ...
        + cosh(xin(1)-1) + tanh(xin(2)+xin(3));
  2. 이 파일을 myObjective.m이라는 이름으로 MATLAB® 경로에 있는 폴더에 저장합니다.

  3. 다음과 같이 함수가 올바르게 실행되는지 확인합니다.

    myObjective([1;2;3])
    
    ans =
        9.2666

추가 파라미터를 포함시키는 방법에 대한 자세한 내용은 추가 파라미터 전달하기 항목을 참조하십시오. 함수 파일에 대한 더 복잡한 예제는 Minimization with Gradient and Hessian Sparsity Pattern 항목 또는 Minimization with Bound Constraints and Banded Preconditioner 항목을 참조하십시오.

로컬 함수와 중첩 함수

함수는 로컬 함수 또는 중첩 함수의 형태로 다른 파일 내에 존재할 수 있습니다. 로컬 함수 또는 중첩 함수를 사용하면 저장해야 하는 개별 파일의 개수가 적어질 수 있습니다. 중첩 함수를 사용하면 중첩 함수에서 보여지는 것처럼 추가 파라미터를 이용할 수도 있습니다.

예를 들어, 비선형 제약 조건에 설명된 제약 조건 ellipseparabola.m을 따르는 함수 파일에서 다룬 myObjective.m 목적 함수를 최소화하고자 한다고 가정하겠습니다. 두 파일 myObjective.mellipseparabola.m을 작성하는 대신 다음과 같이 두 함수를 로컬 함수로 포함하는 파일 하나를 작성합니다.

function [x fval] = callObjConstr(x0,options)
% Using a local function for just one file

if nargin < 2
    options = optimoptions('fmincon','Algorithm','interior-point');
end

[x fval] = fmincon(@myObjective,x0,[],[],[],[],[],[], ...
    @ellipseparabola,options);

function f = myObjective(xin)
f = 3*(xin(1)-xin(2))^4 + 4*(xin(1)+xin(3))^2/(1+sum(xin.^2)) ...
    + cosh(xin(1)-1) + tanh(xin(2)+xin(3));

function [c,ceq] = ellipseparabola(x)
c(1) = (x(1)^2)/9 + (x(2)^2)/4 - 1;
c(2) = x(1)^2 - x(2) - 1;
ceq = [];

다음과 같이 점 [1;1;1]부터 시작하여 제약 조건이 있는 최소화를 풉니다.

[x fval] = callObjConstr(ones(3,1))

Local minimum found that satisfies the constraints.

Optimization completed because the objective function is 
non-decreasing in feasible directions, to within the default 
value of the function tolerance, and constraints are satisfied 
to within the default value of the constraint tolerance.

x =
    1.1835
    0.8345
   -1.6439

fval =
    0.5383

익명 목적 함수

익명 함수를 사용하여 간단한 목적 함수를 작성합니다. 익명 함수에 대한 자세한 내용은 익명 함수란? 항목을 참조하십시오. 로젠브록 함수는 익명 함수로 작성할 만큼 충분히 단순합니다.

anonrosen = @(x)(100*(x(2) - x(1)^2)^2 + (1-x(1))^2);
다음과 같이 anonrosen[-1 2]에서 올바르게 실행되는지 확인합니다.
anonrosen([-1 2])

ans =
   104
fminunc를 사용하여 anonrosen을 최소화하면 다음 결과가 생성됩니다.
options = optimoptions(@fminunc,'Algorithm','quasi-newton');
[x fval] = fminunc(anonrosen,[-1;2],options)

Local minimum found.

Optimization completed because the size of the gradient
is less than the default value of the function tolerance.

x =
    1.0000
    1.0000

fval =
  1.2266e-10

기울기와 헤세 행렬 포함시키기

솔버에 도함수 제공하기

fminconfminunc의 경우 목적 함수에 기울기를 포함시킬 수 있습니다. 일반적으로, 기울기를 포함시키면 솔버가 더 견고해지고 약간 더 빨라질 수 있습니다. 도함수 포함 시 얻을 수 있는 이점 항목을 참조하십시오. 2계 도함수(헤세 행렬)도 포함시키려면 헤세 행렬 포함시키기 항목을 참조하십시오.

다음 표에서는 어떤 알고리즘이 기울기와 헤세 행렬을 사용할 수 있는지 보여줍니다.

솔버알고리즘기울기헤세 행렬
fminconactive-set선택적불가
interior-point선택적선택적(fmincon의 interior-point 알고리즘에 대한 헤세 행렬 참조)
sqp선택적불가
trust-region-reflective필수선택적(fminunc의 trust-region 알고리즘 또는 fmincon의 trust-region-reflective 알고리즘에 대한 헤세 행렬 참조)
fminuncquasi-newton선택적불가
trust-region필수선택적(fminunc의 trust-region 알고리즘 또는 fmincon의 trust-region-reflective 알고리즘에 대한 헤세 행렬 참조)

기울기를 포함시키는 방법

  1. 다음을 수행하는 코드를 작성합니다.

    • 첫 번째 출력값으로 목적 함수(스칼라)를 반환

    • 두 번째 출력값으로 기울기(벡터)를 반환

  2. optimoptions를 사용하여 SpecifyObjectiveGradient 옵션을 true로 설정합니다. 필요한 경우, SpecifyConstraintGradient 옵션도 true로 설정합니다.

  3. 선택적으로, 기울기 함수가 유한 차분 근사와 일치하는지 여부를 확인합니다. Checking Validity of Gradients or Jacobians 항목을 참조하십시오.

유연성을 극대화하려면 조건화된 코드를 작성합니다. 조건화되었다는 것은 다음 예제에 보여지는 것처럼 함수 출력값의 개수가 달라질 수 있음을 의미합니다. 조건화된 코드는 SpecifyObjectiveGradient 옵션의 값에 따라 오류를 발생시키지 않습니다. 조건화되지 않은 코드를 사용하려면 옵션을 적절하게 설정해야 합니다.

예를 들어, 다음과 같은 로젠브록 함수가 있다고 가정하겠습니다.

f(x)=100(x2x12)2+(1x1)2,

이 함수는 최적화 라이브 편집기 작업 또는 솔버를 사용한, 제약 조건이 있는 비선형 문제에 설명 및 플로팅되어 있습니다. f(x)의 기울기는 다음과 같습니다.

f(x)=[400(x2x12)x12(1x1)200(x2x12)],

rosentwo는 다음과 같이 솔버가 필요로 하는 모든 값을 반환하는 조건화된 함수입니다.

function [f,g] = rosentwo(x)
% Calculate objective f
f = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2;

if nargout > 1 % gradient required
    g = [-400*(x(2)-x(1)^2)*x(1)-2*(1-x(1));
        200*(x(2)-x(1)^2)];
    
end

nargout은 호출하는 함수가 지정하는 인수의 개수를 확인합니다. 함수 인수의 개수 구하기 항목을 참조하십시오.

제약 조건이 없는 최적화에 사용하도록 설계된 fminunc 솔버를 사용하면 로젠브록 함수를 최소화할 수 있습니다. 다음과 같이 options를 설정하여 기울기와 헤세 행렬을 사용하도록 fminunc에 지시합니다.

options = optimoptions(@fminunc,'Algorithm','trust-region',...
    'SpecifyObjectiveGradient',true);

다음과 같이 [-1;2]에서 시작하도록 fminunc를 실행합니다.

[x fval] = fminunc(@rosentwo,[-1;2],options)
Local minimum found.

Optimization completed because the size of the gradient
is less than the default value of the function tolerance.

x =
    1.0000
    1.0000

fval =
  1.9886e-17

Symbolic Math Toolbox™ 라이선스가 있는 경우 Calculate Gradients and Hessians Using Symbolic Math Toolbox에 설명된 대로 기울기와 헤세 행렬을 자동으로 계산할 수 있습니다.

헤세 행렬 포함시키기

fmincon'trust-region-reflective' 알고리즘과 'interior-point' 알고리즘, 그리고 fminunc'trust-region' 알고리즘을 사용하여 2계 도함수를 포함시킬 수 있습니다. 헤세 행렬 정보를 포함시킬 수 있는 방법에는 정보 유형과 알고리즘에 따라 여러 가지가 있습니다.

헤세 행렬을 포함시키려면 기울기도 포함시켜야 합니다(SpecifyObjectiveGradienttrue로 설정하고, 해당되는 경우 SpecifyConstraintGradienttrue로 설정).

fminunc의 trust-region 알고리즘 또는 fmincon의 trust-region-reflective 알고리즘에 대한 헤세 행렬.  이러한 알고리즘에는 제약 조건이 전혀 없거나 범위 제약 조건 또는 선형 등식 제약 조건만 있습니다. 따라서 헤세 행렬은 목적 함수의 2계 도함수로 구성된 행렬입니다.

헤세 행렬을 목적 함수의 세 번째 출력값으로 포함시킵니다. 예를 들어, 로젠브록 함수의 헤세 행렬 H(x)는 다음과 같습니다(기울기를 포함시키는 방법 참조).

H(x)=[1200x12400x2+2400x1400x1200].

목적 함수에 이 헤세 행렬을 포함시킵니다.

function [f, g, H] = rosenboth(x)
% Calculate objective f
f = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2;

if nargout > 1 % gradient required
    g = [-400*(x(2)-x(1)^2)*x(1)-2*(1-x(1));
        200*(x(2)-x(1)^2)];
    
    if nargout > 2 % Hessian required
        H = [1200*x(1)^2-400*x(2)+2, -400*x(1);
            -400*x(1), 200];  
    end

end

HessianFcn'objective'로 설정합니다. 예를 들면 다음을 입력합니다.

options = optimoptions('fminunc','Algorithm','trust-region',...
    'SpecifyObjectiveGradient',true,'HessianFcn','objective');

fmincon의 interior-point 알고리즘에 대한 헤세 행렬.  헤세 행렬은 라그랑주 함수의 헤세 행렬이며, 여기서 라그랑주 함수 L(x,λ)는 다음과 같습니다.

L(x,λ)=f(x)+λg,igi(x)+λh,ihi(x).

g 및 h는 각각 모든 부등식 제약 조건과 등식 제약 조건(즉, 범위 제약 조건, 선형 제약 조건, 비선형 제약 조건)을 나타내는 벡터 함수이므로 최소화 문제는 다음과 같습니다.

minxf(x) subject to g(x)0, h(x)=0.

자세한 내용은 제약 조건이 있는 최적성 이론 항목을 참조하십시오. 라그랑주 함수의 헤세 행렬은 다음과 같습니다.

xx2L(x,λ)=2f(x)+λg,i2gi(x)+λh,i2hi(x).(1)

헤세 행렬을 포함시키려면 다음 구문을 사용하여 함수를 작성하십시오.

hessian = hessianfcn(x,lambda)

hessian은 n×n 희소 또는 조밀 행렬이며, 여기서 n은 변수의 개수입니다. hessian이 대규모이고 상대적으로 적은 수의 0이 아닌 요소를 가지는 경우 hessian을 희소 행렬로 나타내어 실행 시간과 메모리를 절약하십시오. lambda는 다음과 같이 비선형 제약 조건과 연결된 라그랑주 승수 벡터를 갖는 구조체입니다.

lambda.ineqnonlin
lambda.eqnonlin

fmincon은 구조체 lambda를 계산한 후 이를 헤세 행렬 함수에 전달합니다. hessianfcn수식 1의 합계를 계산해야 합니다. 다음 옵션을 설정하여 사용자가 헤세 행렬을 제공한다는 것을 나타냅니다.

options = optimoptions('fmincon','Algorithm','interior-point',...
    'SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true,...
    'HessianFcn',@hessianfcn);

예를 들어, 단위 원판 x12+x221로 제한된 로젠브록 함수의 헤세 행렬을 포함시키려면 제약 조건 함수 g(x)=x12+x2210가 다음과 같은 기울기와 2계 도함수 행렬을 포함한다는 것을 상기하십시오.

g(x)=[2x12x2]Hg(x)=[2002].

다음과 같이 헤세 행렬 함수를 작성합니다.

function Hout = hessianfcn(x,lambda)
% Hessian of objective
H = [1200*x(1)^2-400*x(2)+2, -400*x(1);
            -400*x(1), 200];
% Hessian of nonlinear inequality constraint
Hg = 2*eye(2);
Hout = H + lambda.ineqnonlin*Hg;

hessianfcn을 MATLAB 경로에 저장합니다. 예제를 완료하기 위해 기울기를 포함하는 제약 조건 함수를 설명하면 다음과 같습니다.

function [c,ceq,gc,gceq] = unitdisk2(x)
c = x(1)^2 + x(2)^2 - 1;
ceq = [ ];

if nargout > 2
    gc = [2*x(1);2*x(2)];
    gceq = [];
end

기울기와 헤세 행렬을 포함하는 문제를 풉니다.

fun = @rosenboth;
nonlcon = @unitdisk2;
x0 = [-1;2];
options = optimoptions('fmincon','Algorithm','interior-point',...
    'SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true,...
    'HessianFcn',@hessianfcn);
[x,fval,exitflag,output] = fmincon(fun,x0,[],[],[],[],[],[],@unitdisk2,options);

interior-point 헤세 행렬을 사용하는 다른 예제는 해석적 헤세 행렬을 사용하는 fmincon Interior-Point 알고리즘 항목과 Calculate Gradients and Hessians Using Symbolic Math Toolbox 항목을 참조하십시오.

헤세 행렬의 곱셈 함수.  전체 헤세 행렬 함수 대신 fminconinterior-point 알고리즘과 trust-region-reflective 알고리즘을 사용하면 헤세 행렬의 곱셈 함수를 제공할 수 있습니다. 이 함수는 헤세 행렬을 직접 계산하지 않고 헤세 행렬과 벡터의 곱에 대한 결과를 구해줍니다. 따라서 메모리를 절약할 수 있습니다. 헤세 행렬의 곱셈 함수가 작동하려면 SubproblemAlgorithm 옵션이 'cg'여야 하며, 이는 trust-region-reflective의 디폴트 값입니다.

두 알고리즘의 구문은 서로 다릅니다.

  • interior-point 알고리즘의 경우 구문은 다음과 같습니다.

    W = HessMultFcn(x,lambda,v);

    결과 W는 곱 H*v여야 하며, 여기서 Hx에서 계산된 라그랑주 함수의 헤세 행렬이고(수식 1 참조), lambda는 라그랑주 승수이며(fmincon으로 계산됨), v는 n×1 크기의 벡터입니다. 옵션을 다음과 같이 설정합니다.

    options = optimoptions('fmincon','Algorithm','interior-point','SpecifyObjectiveGradient',true,... 
        'SpecifyConstraintGradient',true,'SubproblemAlgorithm','cg','HessianMultiplyFcn',@HessMultFcn);

    n×1 벡터를 반환하는 함수 HessMultFcn을 제공하십시오. 여기서 n은 x의 차원 수입니다. HessianMultiplyFcn 옵션을 사용하면 헤세 행렬을 계산하지 않고도 헤세 행렬과 벡터를 곱한 결과를 전달할 수 있습니다.

  • trust-region-reflective 알고리즘은 lambda를 사용하지 않습니다.

    W = HessMultFcn(H,v);

    결과를 나타내는 식은 W = H*v입니다. fmincon은 목적 함수의 세 번째 출력값에 반환되는 값으로 H를 전달합니다(fminunc의 trust-region 알고리즘 또는 fmincon의 trust-region-reflective 알고리즘에 대한 헤세 행렬 참조). fmincon은 n개 행을 가지는 벡터 또는 행렬인 v도 전달합니다. v에 포함된 열의 개수는 달라질 수 있으므로 임의 개수의 열을 받을 수 있도록 HessMultFcn을 작성하십시오. H는 반드시 헤세 행렬일 필요가 없으며 W = H*v를 계산할 수 있는 어떤 것이든 가능합니다.

    옵션을 다음과 같이 설정합니다.

    options = optimoptions('fmincon','Algorithm','trust-region-reflective',... 
        'SpecifyObjectiveGradient',true,'HessianMultiplyFcn',@HessMultFcn);

    trust-region-reflective 알고리즘에 헤세 행렬의 곱셈 함수를 사용하는 예제를 보려면 Minimization with Dense Structured Hessian, Linear Equalities 항목을 참조하십시오.

도함수 포함 시 얻을 수 있는 이점

기울기를 제공하지 않을 경우 솔버는 유한 차분을 통해 기울기를 추정합니다. 복잡한 도함수에는 유한 차분 추정이 더 빠를 수 있지만 기울기를 제공하면 솔버가 이 유한 차분 추정을 수행할 필요가 없으므로 시간을 절약할 수 있으며 정확도가 더 높을 수 있습니다. 또한, 솔버는 실제 헤세 행렬과 많이 차이가 날 수 있는 근사 헤세 행렬을 사용합니다. 헤세 행렬을 제공하면 더 적은 반복으로 해에 수렴할 수 있습니다. 예를 들어 Calculate Gradients and Hessians Using Symbolic Math Toolbox의 마지막 부분을 참조하십시오.

제약 조건이 있는 문제에 대해 기울기를 제공하면 또 다른 이점을 얻을 수 있습니다. 솔버는 x를 실현 가능하게 되는 점 x에 도달할 수 있지만, 이 x에 대해서 x 주위의 유한 차분은 항상 실현불가능점에 이르게 됩니다. 실현불가능점에서의 목적 함수가 복소수 출력값, Inf, NaN 또는 오류를 반환한다고 가정하겠습니다. 이 경우, 솔버가 실패하거나 도중에 중단될 수 있습니다. 기울기를 제공하면 솔버가 계속 진행할 수 있습니다. 이 이점을 얻으려면 비선형 제약 조건 함수의 기울기를 포함시키고 SpecifyConstraintGradient 옵션을 true로 설정해야 할 수도 있습니다. 비선형 제약 조건 항목을 참조하십시오.

fmincon의 interior-point에 대한 입력값으로 헤세 행렬 근삿값 선택하기

fminconinterior-point 알고리즘에는 입력값으로 헤세 행렬 근삿값을 선택할 수 있는 옵션이 많이 있습니다. 구문 세부 정보는 입력값 헤세 행렬 항목을 참조하십시오. 다음은 옵션과 각 옵션의 상대적인 특성에 대한 추정값을 보여줍니다.

헤세 행렬상대적인 메모리 사용량상대적인 효율성
'bfgs'(디폴트 값)높음(대규모 문제의 경우)높음
'lbfgs'낮음~중간중간
'fin-diff-grads'낮음중간
'HessianMultiplyFcn'낮음(코드에 따라 다를 수 있음)중간
'HessianFcn'?(코드에 따라 다름)높음(코드에 따라 다름)

다음 경우에 해당되지 않을 경우 디폴트 'bfgs' 헤세 행렬을 사용하십시오.

'lbfgs'의 효율성이 중간 수준인 이유는 두 가지가 있습니다. 셔먼-모리슨(Sherman-Morrison) 업데이트가 상대적으로 비용이 많이 듭니다. 그리고 결과로 생성되는 반복 스텝은 'lbfgs'의 제한된 메모리로 인해 다소 부정확할 수 있습니다.

'fin-diff-grads'HessianMultiplyFcn의 효율성이 중간 수준인 이유는 켤레 기울기 접근법을 사용하기 때문입니다. 이 옵션은 목적 함수의 헤세 행렬을 정확하게 추정하지만, 가장 정확한 반복 스텝을 생성하지는 않습니다. 자세한 내용은 fmincon의 Interior Point 알고리즘 항목과 수식 38 풀이를 위한 LDL 접근법 및 켤레 기울기 접근법에 대한 설명을 참조하십시오.

관련 항목