5.2 제한조건이 있는 최적화 문제#
이 절에서는 제한조건(constraint)을 가지는 최적화 문제를 풀어본다. 제한조건은 연립방정식 또는 연립부등식이다. 연립방정식 제한조건이 있는 경우에는 라그랑주 승수법을 사용하여 새로운 최적화 문제를 풀어야 한다. 연립부등식 제한조건의 경우에는 KKT 조건이라는 것을 만족하도록 하는 복잡한 과정을 거쳐야 한다.
등식 제한조건이 있는 최적화 문제#
현실의 최적화 문제에서는 여러가지 제한조건이 있는 최적화(constrained optimization) 문제가 많다. 가장 간단한 경우는 다음과 같이 연립방정식 제한조건이 있는 경우다. 등식(equality) 제한조건이라고도 한다.
첫 번째 식만 보면 단순히 목적함수
를 동시에 모두 만족시키면서 목적함수
예제#
목적 함수
이 문제는 다음 그림처럼
# 목적함수 f(x) = x1^2 + x2^2
def f1(x1, x2):
return x1 ** 2 + x2 ** 2
x1 = np.linspace(-5, 5, 100)
x2 = np.linspace(-3, 3, 100)
X1, X2 = np.meshgrid(x1, x2)
Y = f1(X1, X2)
# 등식 제한조건 방정식 g(x) = x1 + x2 - 1 = 0
x2_g = 1 - x1
plt.contour(X1, X2, Y, colors="gray", levels=[0.5, 2, 8, 32])
plt.plot(x1, x2_g, 'g-')
plt.plot([0], [0], 'rP')
plt.plot([0.5], [0.5], 'ro', ms=10)
plt.xlim(-5, 5)
plt.ylim(-3, 3)
plt.xticks(np.linspace(-4, 4, 9))
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.title("등식 제한조건이 있는 최적화 문제")
plt.show()

라그랑주 승수법#
이렇게 등식 제한조건이 있는 최적화 문제는 **라그랑주 승수법(Lagrange multiplier)**을 사용하여 최적화할 수 있다.
라그랑주 승수 방법에서는 목적함수를 원래의 목적함수
를 목적함수로 간주하여 최적화한다. 이때 제한조건 등식 하나마다 새로운
이
를 구할 수 있다. 구한 결과에서
이 우리가 찾는 최소값
예제#
위에서 제시한 예제를 라그랑주 승수법으로 풀어보자. 새로운 목적함수는 다음과 같다.
라그랑주 승수법을 적용하여 그레디언트 벡터가 영벡터인 위치를 구한다.
위 방정식을 풀면 해는 다음과 같다.
연습 문제 5.2.1#
제한조건이
일 때 목적 함수
을 최소화하는
연습 문제 5.2.2#
제한조건이
일 때 목적 함수
를 최소화하는
사이파이를 사용하여 등식 제한조건이 있는 최적화 문제 계산하기#
사이파이의 optimize 서브패키지는 제한조건이 있는 최적화 문제를 푸는 fmin_slsqp()
명령을 제공한다.
fmin_slsqp(func_objective, x0, eqcons=[func_constraint1, func_constraint2])
fmin_slsqp()
명령은 목적함수와 초깃값, 그리고 제한조건 함수의 리스트를 인수로 받는다. 목적함수는 배열인 인수를 받도록 구현되어야 하고 제한조건 함수의 경우에는 항상 eqcons
인수를 명시해야 한다.
예제#
다음은 위 예제를 fmin_slsqp()
명령으로 푸는 코드다.
def f1array(x):
return x[0] ** 2 + x[1] ** 2
def eq_constraint(x):
return x[0] + x[1] - 1
sp.optimize.fmin_slsqp(f1array, np.array([1, 1]), eqcons=[eq_constraint])
Optimization terminated successfully. (Exit mode 0)
Current function value: 0.5000000000000002
Iterations: 2
Function evaluations: 8
Gradient evaluations: 2
array([0.5, 0.5])
라그랑주 승수의 의미#
만약 최적화 문제에서 등식 제한조건
예제#
목적함수가
인 최소화 문제의 답은
이다.
여기에 다음 제한조건이 있다고 하자.
라그랑주 승수법에서 새로운 목적함수는
이고 최적화 조건은
이를 풀면
로 제한조건이 있으나 없으나 해는 같고 라그랑주 승수가 0이다.
부등식 제한조건이 있는 최적화 문제#
이번에는 다음과 같이 부등식(inequality) 제한조건이 있는 최적화 문제를 생각하자.
만약 부등식이
과 같다면 양변에 -1을 곱하여 부등호의 방향을 바꾼다.
이렇게 부등식 제한조건이 있는 최적화 문제도 라그랑주 승수 방법과 목적함수를 다음처럼 바꾸어 푼다.
다만 이 경우, 최적화 해의 필요조건은 방정식 제한조건이 있는 최적화 문제와 다르게 KKT(Karush-Kuhn-Tucker) 조건이라고 하며 다음처럼 3개의 조건으로 이루어진다.
(1) 모든 독립 변수
(2) 모든 라그랑주 승수
(3) 라그랑주 승수는 음수가 아니어야 한다.
첫 번째 조건은 방정식 제한조건의 경우와 같다. 다먄 변수
두 번째 조건을 보면 확장된 목적함수를 라그랑주 승수로 미분한 값은 변수
마지막 조건은 KKT 조건이 실제로 부등식 제한조건이 있는 최적화 문제와 같은 문제임을 보장하는 조건이다.
예제#
부등식 제한조건을 가지는 최적화의 예를 풀어보자.
목적 함수는
이다.
이 예제에서는 두가지 제한 조건을 고려해볼 텐데 하나는 다음 그림 중 왼쪽 그림처럼 부등식 제한조건이
이다. 다른 하나는 오른쪽 그림처럼 부등식 제한조건이
인 경우다. 이 그림에서는 제한조건을 만족하는 영역을 어둡게 표시했다.
최적점의 위치는 점으로 표시했다. 첫 번째 제한조건의 경우에는 부등식 제한조건이 있기는 하지만 원래의 최적화 문제의 해가 부등식 제한조건이 제시하는 영역 안에 있기 때문에 최적점의 위치가 달라지지 않는다. 두 번째 제한조건의 경우에는 원래의 최적화 문제의 해가 부등식 제한조건이 제시하는 영역 바깥에 있기 때문에 최적점의 위치가 달라졌다. 하지만 최적점의 위치가 영역의 경계선(boundary line)에 있다는 점에 주의하라.
plt.figure(figsize=(13, 7))
ax1 = plt.subplot(121)
plt.contour(X1, X2, Y, colors="gray", levels=[0.5, 2, 8])
plt.plot(x1, x2_g, 'g-')
ax1.fill_between(x1, -20, x2_g, alpha=0.5)
plt.plot([0], [0], 'ro', ms=10)
plt.xlim(-3, 3)
plt.ylim(-5, 5)
plt.xticks(np.linspace(-4, 4, 9))
plt.yticks(np.linspace(-5, 5, 11))
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.title("최적해가 부등식과 관계없는 경우")
ax2 = plt.subplot(122)
plt.contour(X1, X2, Y, colors="gray", levels=[0.5, 2, 8])
plt.plot(x1, x2_g, 'g-')
ax2.fill_between(x1, 20, x2_g, alpha=0.5)
plt.plot([0.5], [0.5], 'ro', ms=10)
plt.xlabel("x_1")
plt.xlim(-3, 3)
plt.ylim(-5, 5)
plt.xticks(np.linspace(-4, 4, 9))
plt.yticks(np.linspace(-5, 5, 11))
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.title("최적해가 부등식에 의해 결정되는 경우")
plt.suptitle("부등식 제한조건이 있는 최적화 문제")
plt.show()

그림에서 보듯이 부등식 제한조건이 있는 최적화 문제를 풀면 그 제한조건은 다음 두 가지 경우의 하나가 되어 버린다.
최적화 결과에 전혀 영향을 주지 않는 쓸모없는 제한조건
최적화 결과에 영향을 주는 등식(equality)인 제한조건
어느 경우이든 부등식 제한조건 문제로 시작했지만 결과는 제한조건이 없거나 등식 제한조건 문제를 푸는 것과 같아진다.
KKT조건 중 두 번째 조건이 뜻하는 바는 다음과 같다. 다음 식에서
만약
반대로
따라서 부등식 제한조건이 있는 최적화 문제는 각 제한조건에 대해 위의 두 가지 경우를 가정하여 각각 풀어보면서 최적의 답을 찾는다.
예제#
다음은 복수의 부등식 제한조건이 있는 또다른 2차원 최적화 문제의 예다.
이 4개의 제한조건은 다음과 같은 하나의 부등식으로 나타낼 수도 있다.
def f2plt(x1, x2):
return np.sqrt((x1 - 4) ** 2 + (x2 - 2) ** 2)
x1 = np.linspace(-2, 5, 100)
x2 = np.linspace(-1.5, 3, 100)
X1, X2 = np.meshgrid(x1, x2)
Y = f2plt(X1, X2)
plt.contour(X1, X2, Y, colors="gray",
levels=np.arange(0.5, 5, 0.5) * np.sqrt(2))
# 제한 조건의 상수
k = 1
ax = plt.gca()
x12 = np.linspace(-k, 0, 10)
x13 = np.linspace(0, k, 10)
ax.fill_between(x12, x12 + k, -k - x12, color='g', alpha=0.5)
ax.fill_between(x13, x13 - k, k - x13, color='g', alpha=0.5)
# 최적점 위치
x1_sol = 1
x2_sol = 0
plt.plot(x1_sol, x2_sol, 'ro', ms=20)
plt.xlim(-2, 5)
plt.ylim(-1.5, 3)
plt.xticks(np.linspace(-2, 5, 8))
plt.yticks(np.linspace(-1, 3, 5))
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.title("$|x_1| + |x_2| \leq {}$ 제한조건을 가지는 최적화 문제".format(k))
plt.show()

연습 문제 5.2.3#
위 예제에서 최적해가
이라는 사실을 이용하여
라그랑주 승수
사이파이를 사용하여 부등식 제한조건이 있는 최적화 문제 계산하기#
fmin_slsqp()
명령은 이렇게 부등식 제한조건이 있는 경우에도 사용할 수 있다. 제한조건 인수의 이름이 ieqcons
로 달라졌다.
fmin_slsqp(func_objective, x0, ieqcons=[func_constraint1, func_constraint2])
단 ieqcons
인수에 들어가는 부등호의 부호는 우리가 지금까지 사용한 방식과 달리 0 또는 양수이어야 한다.
사실 fmin_slsqp()
명령은 등식 제한조건과 부등식 제한조건을 동시에 사용할 수 있다.
def f2(x):
return np.sqrt((x[0] - 4) ** 2 + (x[1] - 2) ** 2)
# 제한 조건 상수
k = 1
def ieq_constraint(x):
return np.atleast_1d(k - np.sum(np.abs(x)))
sp.optimize.fmin_slsqp(f2, np.array([0, 0]), ieqcons=[ieq_constraint])
Optimization terminated successfully. (Exit mode 0)
Current function value: 3.6055512804550336
Iterations: 11
Function evaluations: 77
Gradient evaluations: 11
array([9.99999982e-01, 1.79954011e-08])
연습 문제 5.2.4#
위 문제에서 제한조건을 다음과 같이 바꾼다.
여기에서