[Python] 단변수 함수 최적화하기 (Univariate Function Optimization)


[Python] 단변수 볼록함수 최적화하기 (Univariate Convex Function Optimization)

파이썬과 scipy 라이브러리를 사용해서 단변수 스칼라 함수를 최적화할 수 있습니다.

Matplotlib 라이브러리를 사용해서 이 과정을 시각화하는 방법도 함께 소개합니다.




1. minimize_scalar() 함수 사용하기


scipy.optimize 모듈은 목적함수 (Objective funtion)를 최소화하는 함수들을 제공합니다.

이 모듈의 minimize_scalar() 함수는 하나의 변수를 갖는 스칼라 함수를 최소화합니다.


예제

from scipy.optimize import minimize_scalar


def func(x):
  return (x - 1.5) ** 2 + 0.5


res = minimize_scalar(func)
opt_x, opt_y = res.x, res.fun

print('x: {}, y: {}'.format(opt_x, opt_y))
x: 1.5, y: 0.5

함수 func(x)는 x=1.5에서 최소값을 갖는 2차함수입니다.

minimize_scalar()에 목적함수의 이름 func를 입력하면 최적화를 수행하고 결과 (res)를 반환합니다.

속성 x, fun은 각각 최적화 변수값과 목적함수의 값입니다.




2. Convex Function 최적화하기


볼록함수 (Convex function)는 임의의 두 점을 이은 할선이 두 점을 이은 곡선보다 위에 있는 함수입니다.

minimize_scalar() 함수를 사용해서 볼록함수를 최소화하는 값을 찾고

Matplotlib 라이브러리를 사용해서 시각화하는 과정을 소개합니다.


예제1

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

# Matplotlib 기본 스타일 설정
plt.style.use('default')
plt.rcParams['figure.figsize'] = (6, 4)
plt.rcParams['font.size'] = 12


def objective(x):
  return (x - 1.5)**2 + 0.5


x_arr = np.linspace(0, 5, 100)

plt.plot(x_arr, objective(x_arr), '--')
plt.show()

단변수 스칼라 함수 objective()를 Matplotlib 라이브러리를 사용해서 시각화했습니다.

Matplotlib 라이브러리의 기본적인 사용법은 이 링크를 참고하세요.

결과는 아래와 같습니다.


[Python] 단변수 볼록함수 최적화하기 (Univariate Convex Function Optimization)



예제2

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

# Matplotlib 기본 스타일 설정
plt.style.use('default')
plt.rcParams['figure.figsize'] = (6, 4)
plt.rcParams['font.size'] = 12


def objective(x):
    return (x - 1.5)**2 + 0.5


res = minimize_scalar(objective)
opt_x, opt_y = res.x, res.fun

x_arr = np.linspace(0, 5, 100)

plt.plot(x_arr, objective(x_arr), '--')
plt.scatter(opt_x, opt_y, s=100)
plt.show()

minimize_scalar() 함수는 objective 함수를 최소화하는 x 값과 그 때의 함수값을 반환합니다.

x, fun 속성을 사용해서 두 값을 얻고, plt.scatter() 함수를 사용해서 그래프에 표시했습니다.

아래와 같은 그래프가 표시됩니다.


[Python] 단변수 볼록함수 최적화하기 (Univariate Convex Function Optimization)




3. Non-convex Function 최적화하기


이번에는 비볼록함수 (Non-convex function)의 최소값을 찾아보겠습니다.

두 개 이상의 극소점을 갖는 함수의 특정 범위 안에서 극소점을 찾는 방법을 소개합니다.


예제1

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

# Matplotlib 기본 스타일 설정
plt.style.use('default')
plt.rcParams['figure.figsize'] = (6, 4)
plt.rcParams['font.size'] = 12


def objective(x):
    return (x - 2.0) * (x + 0.3) ** 2 * (x + 1.5)


res = minimize_scalar(objective, method='Brent')
opt_x, opt_y = res.x, res.fun
print(opt_x, opt_y)

x_arr = np.linspace(-2, 2, 100)

plt.plot(x_arr, objective(x_arr), '--')
plt.scatter(opt_x, opt_y, s=100)
plt.show()
1.3575527185778797 -5.043899761957515

앞의 예제에서와 같이 함수 objective()의 최소값을 얻었습니다.

minimize_scalar() 함수는 기본적으로 Brent’s method를 사용해서 전체 범위에서 최소값을 반환합니다.


[Python] 단변수 볼록함수 최적화하기 (Univariate Convex Function Optimization)



예제2

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

# Matplotlib 기본 스타일 설정
plt.style.use('default')
plt.rcParams['figure.figsize'] = (6, 4)
plt.rcParams['font.size'] = 12


def objective(x):
    return (x - 2.0) * (x + 0.3) ** 2 * (x + 1.5)


res = minimize_scalar(objective, bounds=(-2, 0), method='Bounded')
opt_x, opt_y = res.x, res.fun
print(opt_x, opt_y)

x_arr = np.linspace(-2, 2, 100)

plt.plot(x_arr, objective(x_arr), '--')
plt.scatter(opt_x, opt_y, s=100)
plt.axvline(-2, 0, 1, color='gray', linestyle='--', linewidth='1')
plt.axvline(-0, 0, 1, color='gray', linestyle='--', linewidth='1')
plt.show()
-1.132551083254979 -0.7978420349065158

minimize_scalar() 함수의 method를 ‘Bounded’로 하고, bounds를 사용해서 범위를 (-2, 0)으로 제한했습니다.

아래 그림과 같이 -2.0 ~ 0.0 사이의 범위에서 극소값을 얻을 수 있습니다.


[Python] 단변수 볼록함수 최적화하기 (Univariate Convex Function Optimization)




4. 데이터로부터 최적값 찾기


이번에는 특정 영역에서 분포하는 임의의 데이터에 대해서 다항식 피팅 (Polynomial curve fitting)을 수행하고,

피팅으로 얻은 함수에 대해 최소점을 찾는 과정을 소개합니다.


예제1

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

np.random.seed(0)

# Matplotlib 기본 스타일 설정
plt.style.use('default')
plt.rcParams['figure.figsize'] = (6, 4)
plt.rcParams['font.size'] = 12


def objective(x):
    return (x - 2.0) * (x + 0.3) ** 2 * (x + 1.5)


x_arr = np.linspace(-2, 2, 50)
y_arr = objective(x_arr)
y_arr_rand = objective(x_arr) + np.random.randn(50)


plt.plot(x_arr, y_arr, '--', label='Objective')
plt.scatter(x_arr, y_arr_rand, label='Random Data')
plt.legend()
plt.show()

임의의 데이터를 만들기 위해서 np.random.randn() 함수를 사용합니다.

y_arr_rand는 objective() 함수로부터 얻어진 임의의 데이터 어레이입니다.

objective() 함수로부터 아래와 같은 데이터가 만들어졌습니다.


[Python] 단변수 볼록함수 최적화하기 (Univariate Convex Function Optimization)



예제2

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

np.random.seed(0)

# Matplotlib 기본 스타일 설정
plt.style.use('default')
plt.rcParams['figure.figsize'] = (6, 4)
plt.rcParams['font.size'] = 12


def objective(x):
    return (x - 2.0) * (x + 0.3) ** 2 * (x + 1.5)


x_arr = np.linspace(-2, 2, 50)
y_arr = objective(x_arr)
y_arr_rand = objective(x_arr) + np.random.randn(50)

y_arr_fit = np.polyfit(x_arr, y_arr_rand, 4)
p = np.poly1d(y_arr_fit)

res = minimize_scalar(p)
opt_x, opt_y = res.x, res.fun
print(opt_x, opt_y)

plt.plot(x_arr, y_arr, '--', label='Objective')
plt.scatter(x_arr, y_arr_rand, label='Random Data')
plt.plot(x_arr, p(x_arr), label='Fitted Curve')
plt.scatter(opt_x, opt_y, s=100, label='Minimum')
plt.legend()
plt.show()
1.3865397876431753 -5.359015199730874

y_arr_fit은 np.polyfit() 함수를 사용해서 얻은 4차 다항식 계수입니다.

np.poly1d()는 이 계수를 사용하는 다항식 함수입니다.

이 다항식 함수 p에 대해서 minimize_scalar() 함수를 사용해서 최소점을 얻고, 그래프로 나타냈습니다.

Matplotlib 라이브러리의 기본적인 사용법은 이 링크를 참고하세요.

결과는 아래와 같습니다.


[Python] 단변수 볼록함수 최적화하기 (Univariate Convex Function Optimization)


이전글