Python SciPy

SciPy.optimize를 활용한 최소화 문제 해결 (minimize)

PyExplorer 2025. 3. 7. 10:03
728x90

SciPy.optimize를 활용한 최소화 문제 해결 (minimize)

1. 개요

최적화(Optimization)는 과학, 공학, 데이터 분석 및 머신러닝에서 핵심적인 역할을 합니다. 최적화 문제란 주어진 목적 함수(objective function)를 최소화하거나 최대화하는 문제를 의미합니다. SciPy의 optimize 모듈은 다양한 최적화 알고리즘을 제공하며, 특히 minimize 함수는 함수의 최소값을 찾는 데 유용하게 활용됩니다.

본 포스팅에서는 scipy.optimize.minimize 함수를 활용하여 다양한 종류의 최소화 문제를 해결하는 방법을 설명하겠습니다.


2. 최소화 문제란?

최소화 문제는 일반적으로 다음과 같이 정의됩니다.

$$
\min_{x} f(x)
$$

여기서:

  • $ f(x) $는 최소화할 함수 (목적 함수)
  • $ x $는 최적화 변수

추가적으로, 제약 조건과 경계 조건을 포함할 수도 있습니다:

$$
\min_{x} f(x), \quad \text{subject to} \quad g_i(x) \leq 0, \quad h_j(x) = 0, \quad x_{\text{lower}} \leq x \leq x_{\text{upper}}
$$

SciPy의 minimize 함수는 여러 가지 알고리즘을 제공하여 이러한 최소화 문제를 해결할 수 있습니다.


3. scipy.optimize.minimize 기본 사용법

3.1 기본 구조

import numpy as np
from scipy.optimize import minimize

# 최소화할 함수 정의
def objective_function(x):
    return x**2 + 3*x + 2

# 초기 추정값
x0 = 0.0

# 최적화 수행
result = minimize(objective_function, x0)

# 결과 출력
print("최적화 결과:", result)
print("최적해 x:", result.x)

위의 코드는 함수 $ f(x) = x^2 + 3x + 2 $ 를 최소화하는 문제를 해결합니다. minimize 함수는 기본적으로 BFGS 알고리즘을 사용하며, 최적해 $ x $ 값과 최적화 결과를 출력합니다.


4. 다양한 최적화 알고리즘

4.1 Nelder-Mead 방법 (비구배 기반)

Nelder-Mead 방법은 미분을 사용하지 않고 단순체 기법(Simplex method)을 이용하여 최적화하는 방법입니다.

result = minimize(objective_function, x0, method='Nelder-Mead')
print("Nelder-Mead 결과:", result.x)

이 방법은 목적 함수가 미분 불가능한 경우에도 사용할 수 있습니다.


4.2 BFGS (구배 기반)

BFGS(Broyden-Fletcher-Goldfarb-Shanno) 방법은 함수의 미분(Gradient)을 사용하여 최적화하는 방법입니다.

result = minimize(objective_function, x0, method='BFGS')
print("BFGS 결과:", result.x)

이 방법은 목적 함수가 미분 가능할 때 매우 효율적입니다.


4.3 경계 조건이 있는 최소화 (Bounded Minimization)

최적화 변수에 제한된 범위가 있는 경우 bounds를 설정할 수 있습니다.

from scipy.optimize import Bounds

bounds = Bounds([-2], [2])  # x의 값이 -2 이상 2 이하로 제한됨
result = minimize(objective_function, x0, method='L-BFGS-B', bounds=bounds)

print("경계 조건 적용 결과:", result.x)

위의 예제에서는 변수 $ x $ 가 -2 이상 2 이하의 범위를 가지도록 제한하였습니다.


5. 제약 조건이 있는 최소화

최적화 문제에서 종종 특정 조건을 만족하는 해를 찾아야 합니다. SciPy의 minimize 함수에서는 constraints 인자를 사용하여 제약 조건을 추가할 수 있습니다.

5.1 등식 제약 조건 (Equality Constraint)

등식 제약 조건은 다음과 같이 설정할 수 있습니다:

$$
g(x) = 0
$$

from scipy.optimize import NonlinearConstraint

# 목적 함수
def objective_function(x):
    return x[0]**2 + x[1]**2

# 제약 함수
def constraint_eq(x):
    return x[0] + x[1] - 1  # x1 + x2 = 1

# 제약 조건 정의
constraint = {'type': 'eq', 'fun': constraint_eq}

# 초기값
x0 = np.array([0.5, 0.5])

# 최적화 수행
result = minimize(objective_function, x0, constraints=constraint)

print("등식 제약 조건 적용 결과:", result.x)

이 코드에서는 $ x_1 + x_2 = 1 $ 이라는 제약 조건을 적용하였습니다.


5.2 부등식 제약 조건 (Inequality Constraint)

부등식 제약 조건은 다음과 같습니다:

$$
h(x) \leq 0
$$

예제 코드:

# 부등식 제약 조건 (x1 + x2 <= 1)
def constraint_ineq(x):
    return 1 - (x[0] + x[1])  # 1 - (x1 + x2) >= 0

constraint = {'type': 'ineq', 'fun': constraint_ineq}

result = minimize(objective_function, x0, constraints=constraint)

print("부등식 제약 조건 적용 결과:", result.x)

위의 코드는 $ x_1 + x_2 \leq 1 $ 이라는 제약 조건을 추가한 최소화 문제를 해결합니다.


6. 실전 예제: 2차원 최적화 문제

다음은 2차원 공간에서 특정 함수의 최소값을 찾는 예제입니다.

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize

# 목적 함수
def objective_function(x):
    return np.sin(x[0]) + np.cos(x[1])

# 초기 추정값
x0 = np.array([0, 0])

# 최적화 수행
result = minimize(objective_function, x0, method='BFGS')

# 결과 출력
print("최적해:", result.x)

# 시각화
x = np.linspace(-2*np.pi, 2*np.pi, 100)
y = np.linspace(-2*np.pi, 2*np.pi, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)

plt.contourf(X, Y, Z, levels=50, cmap='viridis')
plt.colorbar(label='Function Value')
plt.scatter(result.x[0], result.x[1], color='red', label='최적해')
plt.legend()
plt.xlabel("x")
plt.ylabel("y")
plt.title("최소화 결과")
plt.show()

이 코드는 $ f(x, y) = \sin(x) + \cos(y) $ 의 최소값을 찾고, 결과를 시각적으로 표현합니다.


7. 결론

scipy.optimize.minimize 함수는 다양한 종류의 최소화 문제를 해결하는 데 강력한 도구입니다. 본 포스팅에서는 기본 사용법과 다양한 알고리즘을 소개하고, 경계 및 제약 조건을 활용하는 방법을 살펴보았습니다.

SciPy의 최적화 기능을 활용하면 복잡한 수학적 최적화 문제를 간단하게 해결할 수 있습니다. 이를 기반으로 실제 데이터 분석, 머신러닝 모델 튜닝 등 다양한 분야에 응용할 수 있습니다.

728x90