최적화
1) 1차원 최적화(Scalar Optimization)
함수 입력값이 일차원인 경우.
(1) 1차원 스칼라 함수 최적화(minimize_scalar)
from scipy.optimize import minimize_scalar
minimize_scalar(lambda x: (x-2)**2)
(2) 이분법을 이용한 근 탐색(bisect)
from scipy.optimize import bisect
bisect(lambda x: x**3 - 1, 0, 2)
(3) 뉴튼 랩슨(newton)
from scipy.optimize import newton
newton(lambda x: x**3 - 2, x0=1)
(4) Brenth(brenth)
from scipy.optimize import brenth
brenth(lambda x: x**3 - 2*x + 1, -2, 2)
(5) brentq(1차원 비선형 방정식의 해 찾기)
from scipy.optimize import brentq
# 방정식 정의
def f(x):
return x**3 - 6*x**2 + 11*x - 6
# 해 구하기 (구간 설정)
root = brentq(f, 0, 1.5) # 구간 [0, 1.5]
print("해:", root)
2) 다차원 최적화(Multidimensional Optimization)
최적화 대상이 2개 이상 변수로 이루어진 경우.
즉, 함수 입력값이 다차원인 경우.
(1) 최소값 찾기(minimize)
from scipy.optimize import minimize
minimize(lambda x: (x[0] - 3)**2 + (x[1] - 2)**2, x0=[0, 0])
(2) Gradient를 사용하지 않는 단순 최적화(fmin, 미분 기반이 아님)
from scipy.optimize import fmin
fmin(lambda x: (x-1)**2, x0=[0])
- Nelder-Mead simplex 알고리즘 기반 최적화 수행.
- 미분 불가능한 함수거나 비연속적인 함수에 주로 사용하게 된다.
3) 비선형 문제 최적화(Nonlinear Optimization)
(1) 비선형 최소제곱 문제(least_squares)
from scipy.optimize import least_squares
import numpy as np
# 비선형 모델 정의
def model(params, x):
a, b, c = params
return a * np.exp(b * x) + c
# 잔차(residual) 계산
def residuals(params, x, y):
return model(params, x) - y
# 데이터
x = np.linspace(0, 1, 10)
y = 2 * np.exp(1.5 * x) + 0.5
# 비선형 최적화
res = least_squares(residuals, x0=[1, 1, 1], args=(x, y))
print(res.x) # [2.0, 1.5, 0.5]
(2) 비선형 회귀 적합(curve_fit)
from scipy.optimize import curve_fit
import numpy as np
def func(x, a, b): return a * np.exp(b * x)
x = np.linspace(0, 4, 50)
y = func(x, 2, 0.5) + 0.1 * np.random.normal(size=len(x))
curve_fit(func, x, y)
(3) 비선형 방정식(일차원, 다차원)의 해 구하기(root, fsolve)
from scipy.optimize import root
import numpy as np
# 방정식 시스템 정의
def equations(vars):
x, y = vars
return [
x**2 + y**2 - 1, # 첫 번째 비선형 방정식
x**3 - y # 두 번째 비선형 방정식
]
# 초기 추정값
initial_guess = [0.5, 0.5]
# 해 구하기
solution = root(equations, initial_guess)
# 결과 출력
print("해:", solution.x) # 해의 좌표 [x, y]
print("성공 여부:", solution.success)
########################
from scipy.optimize import fsolve
import numpy as np
# 1. 방정식 시스템 정의
def equations(vars):
x, y = vars
eq1 = x**2 + y**2 - 4 # 원 방정식
eq2 = np.exp(x) + y - 1 # 비선형 함수
return [eq1, eq2]
# 2. 초기 추정값 설정
initial_guess = [1, 1] # 초기값 설정
# 3. 해 구하기
solution = fsolve(equations, initial_guess)
# 4. 결과 출력
print("해:", solution) # [x, y]
print("함수값 확인:", equations(solution)) # 0에 가까운지 확인
4) 선형계획법(Liner Programming)
(1) 선형 계획법(linprog)
선형 제약 조건과 선형 목적 함수를 최적화하는 방법.
ex)
objective function : Z = 40x1 + 30x2
constraints : (2x1 + x2 =< 100 , x1 + 2x2 =< 80), (x1, x2 > 0)
from scipy.optimize import linprog
# 목적 함수 계수 (최소화 문제로 변환: -Z)
c = [-40, -30] # -1을 곱해 최소화로 변경
# 부등식 제약 조건 (Ax <= b)
A = [[2, 1], [1, 2]]
b = [100, 80]
# 비음 조건 (x >= 0)
x_bounds = [(0, None), (0, None)]
# 선형 계획법 최적화
result = linprog(c, A_ub=A, b_ub=b, bounds=x_bounds)
# 결과 출력
print("최적해:", result.x)
print("최적값:", -result.fun) # 다시 부호 변경
5) 전역 최적화
(1) 유전알고리즘 기반
from scipy.optimize import differential_evolution
differential_evolution(lambda x: x**2, bounds=[(-10, 10)])
(2) Monte Carlo 방식
국소 최적화 + 무작위로 시작지점을 지정하여 탐색
from scipy.optimize import basinhopping
basinhopping(lambda x: x**2, x0=[2])
(3) Simplex 기반
from scipy.optimize import shgo
shgo(lambda x: (x-1)**4, bounds=[(0, 2)])
c.f.) simplex
- 최적화에서 simplex란, 탐색 시작 지점을 정할 때, 각 탐색지점을 연결하면 도형이 되도록 탐색지점을 결정하는 방식을 말한다고 보면 된다.
- 이를 기반으로 도형의 크기를 크게 혹은 작게하면서 해를 탐색하게 된다.
(4) Simulated Annealing 기반
from scipy.optimize import dual_annealing
dual_annealing(lambda x: (x-3)**2, bounds=[(-10, 10)])
'Data Science' 카테고리의 다른 글
SciPy) 자주 사용하는 기능들 - 거리 (0) | 2024.12.29 |
---|---|
SciPy) 자주 사용하는 기능들 - 선형대수 (0) | 2024.12.29 |