벌점법
제약조건이 있는 최적화 문제를 위한 penalty method
- 1. 학습 목표
- 2. 제약조건이 있는 최적화
- 3. 벌점법의 기본 원리
- 4. 손으로 계산하는 예제
- 5. 경사하강법으로 풀기
- 6. 두 변수 예제
- 7. 부등식 제약조건
- 8. 벌점계수를 증가시키는 방법
- 9. 벌점법의 장점과 주의점
- 10. 정리
- 11. 연습 문제
1. 학습 목표
이번 강의가 끝나면 다음을 할 수 있어야 한다.
- 목적함수와 제약조건을 구분할 수 있다.
- 벌점법(penalty method)의 기본 생각을 설명할 수 있다.
- 등식 제약조건을 벌점항으로 바꿀 수 있다.
- 벌점계수의 크기가 해와 수치 계산에 미치는 영향을 설명할 수 있다.
- 간단한 벌점함수를 경사하강법으로 최소화할 수 있다.
2. 제약조건이 있는 최적화
경사하강법에서는 다음과 같이 목적함수 $f(\boldsymbol{x})$를 가장 작게 만드는 $\boldsymbol{x}$를 찾았다.
\[\min_{\boldsymbol{x}} f(\boldsymbol{x})\]이처럼 모든 $\boldsymbol{x}$를 후보로 허용하는 문제를 제약조건이 없는 최적화(unconstrained optimization)라고 한다.
그러나 실제 공학 문제에서는 설계변수가 반드시 만족해야 하는 조건이 자주 등장한다. 예를 들면 다음과 같다.
- 두 합금 원소의 조성 합이 정해진 값과 같아야 한다.
- 재료의 질량은 허용 질량보다 작아야 한다.
- 계산된 응력은 허용응력을 넘지 않아야 한다.
등식 제약조건이 있는 문제는
\[\begin{aligned} \min_{\boldsymbol{x}} \quad & f(\boldsymbol{x}) \\ \text{subject to} \quad & h(\boldsymbol{x})=0 \end{aligned}\]과 같이 쓴다. 여기서
- $f(\boldsymbol{x})$: 가장 작게 만들고 싶은 목적함수(objective function)
- $h(\boldsymbol{x})=0$: 반드시 만족해야 하는 등식 제약조건(constraint)
이다. 제약조건을 만족하는 점을 가능점(feasible point)이라고 한다.
3. 벌점법의 기본 원리
벌점법에서는 제약조건을 어긴 정도만큼 목적함수에 큰 값을 더한다. 그러면 제약조건을 많이 위반한 점은 최소화 과정에서 불리해진다.
제약조건을 지키면 벌점(penalty)이 작고, 제약조건을 어기면 벌점이 커진다.
이 방법을 사용하면 제약조건이 있는 문제를 앞에서 배운 경사하강법으로 풀 수 있는 제약조건 없는 문제로 바꿀 수 있다.
3.1. 등식 제약조건
등식 제약조건 $h(\boldsymbol{x})=0$에 대해 가장 간단한 이차(2nd order) 벌점항은
\[\frac{\rho}{2}\left[h(\boldsymbol{x})\right]^{\textcolor{red}{2}}\]이다. 원래 목적함수$f(x)$에 이 항을 더한 벌점함수(penalty function)를
\[\boxed{ P(\boldsymbol{x};\rho) =f(\boldsymbol{x}) +\frac{\rho}{2}\left[h(\boldsymbol{x})\right]^2 }\]로 정의한다. $\rho>0$는 벌점계수(penalty parameter)이다.
- $h(\boldsymbol{x})=0$이면 벌점항은 $0$이다.
- $h(\boldsymbol{x})\ne0$이면 벌점항은 양수이다.
- 제약조건의 위반량이 두 배가 되면 제곱된 위반량은 네 배가 된다.
따라서 원래 문제 ($\min_{\boldsymbol{x}} f(x) \text{, subject to } h(x)=0$) 대신
\[\min_{\boldsymbol{x}}P(\boldsymbol{x};\rho)\]를 푼다.
만약 여러 개의 등식 제약조건 $h_j(\boldsymbol{x})=0$이 있다면 개별 제약 조건에 의한 벌점항을 모두 더한다.
\[P(\boldsymbol{x};\rho) =f(\boldsymbol{x}) +\frac{\rho}{2}\sum_{j=1}^{m} \left[h_j(\boldsymbol{x})\right]^2\]3.2. 벌점계수의 역할
벌점계수 $\rho$가 작으면 상대적으로 목적함수를 줄이는 것이 더 중요해지고, 제약조건을 어느 정도 위반해도 허용될 수 있다. 반대로 $\rho$가 커지면 제약조건 위반에 더 큰 벌점을 부과하고 따라서 제약 조건이 더욱 엄밀하게 요구된다.
\[\rho\uparrow \quad\Longrightarrow\quad |h(\boldsymbol{x})|\downarrow\]그러나 유한한 $\rho$에서는 일반적으로 제약조건을 정확히 만족하지 않고 조금 위반할 수 있다. 또한 $\rho$를 처음부터 지나치게 크게 정하면 벌점함수의 기울기($\dfrac{dP}{dx}$)가 매우 커져 경사하강법의 학습률을 작게 설정해야 할 수 있다.
4. 손으로 계산하는 예제
다음 문제를 생각하자.
\[\begin{aligned} \min_x \quad & f(x)=(x-2)^2 \\ \text{subject to} \quad & h(x)=x-1=0 \end{aligned}\]목적함수만 생각하면 최솟점은 $x=2$이다. 그러나 제약조건을 만족하는 점은 $x=1$뿐이므로 원래 제약 최적화 문제의 해는 $x^*=1$이다.
이차 벌점함수는
\[P(x;\rho)=(x-2)^2+\frac{\rho}{2}(x-1)^2\]이다. 미분하여 $0$으로 놓으면
\[\frac{dP}{dx}=2(x-2)+\rho(x-1)=0\]이고, 아래와 같이 전개된다.
\[(2+\rho)x-4-\rho=0\]위 조건을 만족시키는 벌점함수의 최솟점은
\[\boxed{x_\rho=\frac{4+\rho}{2+\rho}}\]이다.
| $\rho$ | $x_\rho$ | 제약조건 위반량 $ | x_{\rho}-1 | $ |
|---|---|---|---|---|
| 1 | 1.6667 | 0.6667 | ||
| 10 | 1.1667 | 0.1667 | ||
| 100 | 1.0196 | 0.0196 | ||
| 1000 | 1.0020 | 0.0020 |
$\rho$가 커질수록 $x_\rho$가 제약조건의 해 $x=1$에 가까워지는 것을 확인할 수 있다. 수학적으로는
\[\lim_{\rho\rightarrow\infty}x_\rho=1\]이다.
5. 경사하강법으로 풀기
위 벌점함수를 경사하강법으로 최소화해 보자. 반복식은
\[x^{(k+1)} =x^{(k)}-\alpha\frac{dP}{dx}\left(x^{(k)};\rho\right)\]이다. 여기서
\[\frac{dP}{dx}=2(x-2)+\rho(x-1)\]이다.
def penalty_gradient(x, rho):
return 2.0*(x - 2.0) + rho*(x - 1.0)
def gradient_descent_penalty(x0, rho, alpha, tol=1e-10,
max_iter=10000):
x = float(x0)
for iteration in range(max_iter):
grad = penalty_gradient(x, rho)
if abs(grad) < tol:
return x, iteration
x = x - alpha*grad
raise RuntimeError("최대 반복 횟수 안에 수렴하지 않았습니다.")
for rho in [1.0, 10.0, 100.0]:
# rho가 커질수록 작은 학습률을 사용한다.
alpha = 1.0/(rho + 2.0)
x, n_iter = gradient_descent_penalty(
x0=0.0,
rho=rho,
alpha=alpha,
)
print(
f"rho={rho:5.1f}, x={x:.6f}, "
f"constraint error={abs(x - 1.0):.6f}"
)
예상되는 결과는 다음과 같다.
rho= 1.0, x=1.666667, constraint error=0.666667
rho= 10.0, x=1.166667, constraint error=0.166667
rho=100.0, x=1.019608, constraint error=0.019608
이 예제의 벌점함수는 이차함수이므로 적절한 학습률을 사용하면 쉽게 수렴한다. 일반적인 비선형 문제에서는 $\rho$와 학습률을 함께 조절해야 한다.
6. 두 변수 예제
두 설계변수 $x$, $y$의 합이 $4$가 되어야 하는 문제를 생각하자.
\[\begin{aligned} \min_{x,y} \quad & f(x,y)=(x-3)^2+(y-2)^2 \\ \text{subject to} \quad & h(x,y)=x+y-4=0 \end{aligned}\]벌점함수는
\[P(x,y;\rho) =(x-3)^2+(y-2)^2 +\frac{\rho}{2}(x+y-4)^2\]이다. 기울기는
\[\nabla P(x,y;\rho)= \begin{bmatrix} 2(x-3)+\rho(x+y-4)\\ 2(y-2)+\rho(x+y-4) \end{bmatrix}\]이다. 따라서 앞에서 배운 경사하강법의 반복식을 그대로 사용할 수 있다.
import numpy as np
def penalty_gradient_2d(point, rho):
x, y = point
constraint = x + y - 4.0
return np.array([
2.0*(x - 3.0) + rho*constraint,
2.0*(y - 2.0) + rho*constraint,
])
def solve_penalty_2d(x0, rho, alpha, tol=1e-8,
max_iter=10000):
point = np.asarray(x0, dtype=float).copy()
for iteration in range(max_iter):
grad = penalty_gradient_2d(point, rho)
if np.linalg.norm(grad) < tol:
return point, iteration
point = point - alpha*grad
raise RuntimeError("최대 반복 횟수 안에 수렴하지 않았습니다.")
for rho in [1.0, 10.0, 100.0]:
point, n_iter = solve_penalty_2d(
x0=[0.0, 0.0],
rho=rho,
alpha=0.4/(1.0 + rho),
)
violation = point[0] + point[1] - 4.0
print(
f"rho={rho:5.1f}, point={point}, "
f"h(x,y)={violation:.6f}"
)
원래 제약 최적화 문제의 정확한 해는 $(x,y)=(2.5,1.5)$이다. $\rho$를 증가시키면 벌점법으로 구한 점이 이 해에 가까워진다.
7. 부등식 제약조건
부등식 제약조건은 보통
\[g(\boldsymbol{x})\leq0\]의 형태로 통일하여 쓴다. 조건을 만족하면 $g(\boldsymbol{x})\leq0$이고, 위반하면 $g(\boldsymbol{x})>0$이다. 따라서 양수인 위반 부분에만 벌점을 주는
\[\boxed{ P(\boldsymbol{x};\rho) =f(\boldsymbol{x}) +\frac{\rho}{2} \left[\max\left(0,g(\boldsymbol{x})\right)\right]^2 }\]를 사용할 수 있다.
예를 들어 $x\geq1$이라는 조건은
\[g(x)=1-x\leq0\]으로 바꾼다. 이때 벌점항은
\[\frac{\rho}{2}[\max(0,1-x)]^2\]이다.
- $x=1.5$이면 조건을 만족하므로 벌점은 $0$이다.
- $x=0.8$이면 위반량은 $0.2$이고 벌점은 $\rho(0.2)^2/2$이다.
부등식 제약조건의 경계에서는 함수의 미분을 주의해서 다루어야 한다. 이번 강의에서는 제약조건을 위반한 부분에만 벌점을 준다는 생각까지만 익힌다.
8. 벌점계수를 증가시키는 방법
실제 계산에서는 매우 큰 $\rho$ 하나를 처음부터 사용하기보다, 작은 값에서 시작하여 점차 증가시키는 방법을 사용할 수 있다.
- 비교적 작은 $\rho$를 선택한다.
- 현재 벌점함수를 최소화한다.
-
제약조건 위반량 $ h(\boldsymbol{x}) $을 계산한다. - 위반량이 허용오차보다 크면 $\rho$를 증가시킨다.
- 이전 단계의 해를 새로운 초기값으로 사용하여 다시 최소화한다.
이를 간단히 나타내면 다음과 같다.
x = initial_value
for rho in [1.0, 10.0, 100.0, 1000.0]:
x = minimize_penalty(x, rho)
if abs(constraint(x)) < constraint_tolerance:
break
위 코드는 전체 흐름을 설명하기 위한 의사 코드이다. minimize_penalty에는 경사하강법과 같은 최소화 알고리듬을 사용할 수 있다.
9. 벌점법의 장점과 주의점
| 항목 | 내용 |
|---|---|
| 장점 | 제약조건이 있는 문제를 익숙한 제약조건 없는 최소화 문제로 바꿀 수 있다. |
| 장점 | 목적함수와 제약조건의 식만 알면 비교적 쉽게 구현할 수 있다. |
| 주의점 | 유한한 $\rho$에서는 제약조건을 정확히 만족하지 않을 수 있다. |
| 주의점 | $\rho$가 너무 작으면 제약조건 위반이 크다. |
| 주의점 | $\rho$가 너무 크면 함수가 가파르게 변하여 수치 계산이 어려워질 수 있다. |
| 주의점 | 목적함수와 제약조건의 단위나 크기가 크게 다르면 적절한 크기 조정이 필요하다. |
계산 결과를 판단할 때는 목적함수의 값만 확인해서는 안 된다. 반드시 제약조건의 위반량도 함께 확인해야 한다.
\[\text{목적함수값}: f(\boldsymbol{x}), \qquad \text{제약조건 위반량}: |h(\boldsymbol{x})|\]10. 정리
- 벌점법은 제약조건 위반량을 목적함수에 더하는 방법이다.
- 등식 제약조건 $h(\boldsymbol{x})=0$에는 $\rho[h(\boldsymbol{x})]^2/2$를 벌점항으로 사용할 수 있다.
- 벌점계수 $\rho$가 커질수록 일반적으로 제약조건 위반량이 감소한다.
- 유한한 $\rho$에서는 제약조건을 조금 위반할 수 있다.
- 지나치게 큰 $\rho$는 최소화 문제를 수치적으로 어렵게 만들 수 있다.
- 계산 결과에서는 목적함수값과 제약조건 위반량을 모두 확인해야 한다.
11. 연습 문제
문제 1. 목적함수와 제약조건
다음 문제에서 목적함수와 제약조건을 각각 쓰시오.
\[\begin{aligned} \min_{x,y}\quad &(x-1)^2+(y-3)^2\\ \text{subject to}\quad &x+y=5 \end{aligned}\]문제 2. 가능점 판단
제약조건이 $x+y-4=0$일 때 다음 중 가능점을 모두 고르시오.
\[(1,3),\qquad(2,1),\qquad(0,4)\]문제 3. 벌점항 계산
$h(x)=x-2$, $\rho=10$일 때 $x=2.5$에서 이차 벌점항 $\rho[h(x)]^2/2$를 계산하시오.
문제 4. 벌점함수 만들기
다음 제약 최적화 문제의 이차 벌점함수 $P(x;\rho)$를 쓰시오.
\[\begin{aligned} \min_x\quad &(x-3)^2\\ \text{subject to}\quad &x-1=0 \end{aligned}\]문제 5. 벌점계수 비교
같은 점에서 제약조건의 위반량이 $0.2$일 때 $\rho=10$과 $\rho=100$의 이차 벌점항을 각각 계산하시오.
문제 6. 손으로 최솟점 구하기
다음 벌점함수에서 $\rho=2$일 때 최솟점 $x$를 구하시오.
\[P(x;\rho)=(x-2)^2+\frac{\rho}{2}(x-1)^2\]문제 7. Python 실습
4절의 일변수 예제에서 $\rho=1$, $10$, $100$, $1000$에 대한 $x_\rho=(4+\rho)/(2+\rho)$와 제약조건 위반량 $|x_\rho-1|$을 Python으로 계산하시오.
문제 8. 결과 해석
벌점법으로 구한 두 후보의 결과가 다음과 같다.
| 후보 | $f(\boldsymbol{x})$ | $ | h(\boldsymbol{x}) | $ |
|---|---|---|---|---|
| A | 1.0 | 0.2 | ||
| B | 1.1 | 0.001 |
제약조건 허용오차가 $0.01$일 때 어느 후보를 선택해야 하는지 설명하시오.