import math
import numpy as np
import matplotlib.pyplot as plt
1. 일차함수
- \(y\)\(=\)\(ax\)\(+\)\(b\)
- \(a\): 기울기, \(b\): y절편
- 그래프 상에서 직선인 그래프(linear)
def linear_function(x):
a = 0.5
b = 2
return a*x+b
print(linear_function(5))
# 0.5 * 5 + 2 = 4.5
# 출력 결과
4.5
# x에 -5부터 5까지 0.1단위로 증가시키며 리스트 생성
x = np.arange(-5, 5, 0.1)
# x의 모든 값을 linear_function에 넣어 각 값에 대한 y값을 생성시킴
y = linear_function(x)
# 각 x값에 대응하는 y값을 그린 그래프
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Linear Function')
2. 이차함수
- \(y=ax^2+bx+c\)
- 일반적으로 두 개의 실근을 가짐
def quadratic_function(x):
a = 1
b = -1
c = -2
return a*x**2 + b*x + c
print(quadratic_function(2))
# 1*2**2 + -1*2 -2 = 4 -2 -2 = 0
# 출력 결과
0
x = np.arange(-5, 5, 0.1)
y = quadratic_function(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Quadratic Function')
3. 삼차함수(다항함수)
- \(y=ax^3+bx^2+cx+d\)
def cubic_function(x):
a = 4
b = 0
c = -1
d = -8
return a*x**3 + b*x**2 + c*x + d
print(cubic_function(3))
# 4*3**3 + 0*3**2 + -1*3 + -8 = 108 + 0 + -3 + -8 = 97
# 출력 결과
97
x = np.arange(-5, 5, 0.1)
y = cubic_function(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Cubic Function')
4. 함수의 최소값 / 최대값
x = np.arange(-10, 10, 0.1)
y = my_func(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.scatter(1.5, my_func(1.5))
plt.text(1.5-1.5, my_func(1.5)+10, 'min value of f(x)\n({}, {})'.format(1.5, my_func(1.5)), fontdict={'size': 10})
plt.title('my_func')
plt.show()
min_val = min(y)
print(min_val)
# 출력 결과
7.75
5. 특정 구간 내에서 최소값 구하기
# x1과 x2 사이에서 최소값 구하기
def get_minimum(x1, x2, f):
x = np.arange(x1, x2, 0.1)
y = f(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('get_minimum')
plt.show()
return min(y)
print(get_minimum(1, 4, my_func))
# 출력 결과
7.75
6. 지수함수 / 로그함수
- 지수함수·로그함수는 역함수 관계(\(y\)\(=\)\(x\) 직선 대칭, 단, 밑이 같을 때)
- 파이썬으로 직접 구현 가능
- 지수 함수
- \(y=a^{x} (a\ne0)\)(기본형)
- \(y=e^{x} (e=2.71828)\)
def exponential_function(x):
a = 4
return a**x
print(exponential_function(4))
print(exponential_function(0))
# 출력 결과
256
1
x = np.arange(-3, 2, 0.1)
y = exponential_function(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.ylim(-1, 15)
plt.xlim(-4, 3)
plt.title('exponential_function')
plt.show()
def exponential_fnction2(x):
a = 4
return math.pow(a, x)
print(exponential_function(4))
print(exponential_function(0))
# 출력 결과
256
1
- 밑이 \(e\)인 지수 함수 표현
# math 라이브러리나 numpy 라이브러리에 있는 exp 사용
print(math.exp(4))
print(np.exp(4))
# 출력 결과
54.598150033144236
54.598150033144236
- 로그 함수
- \(y=log_{a}(x) (a\ne1)\) (기본형)
- \(y=log_{10}(x)\) (상용로그)
- \(y=ln(x)\) (밑이 \(e\)인 자연로그)
# 밑이 3, 진수가 2인 로그
print(math.log(2, 3))
# 밑이 2인 로그
print(np.log2(4))
# np.log에서 log 다음 숫자가 없다면 밑이 e인 자연로그
print(np.log(4))
# 출력 결과
0.6309297535714574
2.0
1.3862943611198906
- 역함수 관계
- \(y\)\(=\)\(x\) 대칭
# 지수 함수
x1 = np.arange(-1, 5, 0.01)
y1 = np.exp(x1)
# 로그 함수
x2 = np.arange(0.000001, 5, 0.01)
y2 = np.log(x2)
# y=x의 직선
y3 = x1
plt.plot(x1, y1, 'r-', x2, y2, 'b-', x1, y3, 'k--')
plt.ylim(-2, 6)
plt.axvline(x = 0, color = 'k')
plt.axhline(y = 0, color = 'k')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
7. 함수 조작
- \(y=-log_{a}(x)\)와 \(y=-log_{a}(1-x)\)
\(x=0.5\) 대칭 - Logistic Regression을 위한 함수
x = np.arange(-10, 10, 0.01)
y1 = -np.log(x)
y2 = -np.log(1-x)
plt.axvline(x = 0, color = 'k')
plt.axhline(y = 0, color = 'k')
plt.grid()
plt.plot(x, y1, 'b-', x, y2, 'r-')
plt.text(0.9, 2.0, 'y=-log(1-x)', fontdict={'size': 15})
plt.text(0.1, 3, 'y=-log(x)', fontdict={'size': 15})
plt.xlim(-0.3, 1.4)
plt.ylim(-0.5, 4)
plt.scatter(0.5, -np.log(0.5))
plt.show()
8. 극한
- x가 어떤 값 a에 가까이 다가갈 때 a에 '한없이 가까이 간다'일 뿐, a에 도달하지 않는다
- 극한을 표현할 때, 엡실론(epsilon)이라는 아주 작은 값(ex, 0.00001)등으로 표현
from sympy import *
init_printing()
x, y, z = symbols('x y z')
a, b, c, t = symbols('a b c t')
- \(\underset{x\to 1}{lim}(\frac{x^{3}-1}{x-1})=3\)
print("극한값:", limit((x**3-1) / (x-1), x, 1))
# 출력 결과
극한값: 3
plot( ((x**3-1) / (x-1)), xlim = (-5, 5), ylim = (-1, 10))
- \(\underset{x\to \infty }{lim}(\frac{1+x}{x})=3\)
print("극한값:", limit((1+x) / (x), x, oo))
# 출력 결과
극한값: 1
plot( ((1+x) / (x)), xlim = (-10, 10), ylim = (-5, 5))
- \(\underset{x\to 1 }{lim}(\frac{\sqrt{x+3}-2}{x-1})=\frac{1}{4}\)
print("극한값:", limit((sqrt(x+3)-2) / (x-1), x, 1))
# 출력 결과
극한값: 1/4
plot( ((sqrt(x+3)-2) / (x-1)), xlim = (-5, 12), ylim = (-0.5, 1))
- 삼각함수의 극한
- \(\underset{x\to \frac{\pi }{2}+0 }{lim} \tan x=-\infty\)
- \(\underset{x\to \frac{\pi }{2}-0 }{lim} \tan x=\infty\)
print("극한값:", limit(tan(x), x, pi/2, '+'))
print("극한값:", limit(tan(x), x, pi/2, '-'))
# 출력 결과
극한값: -oo
극한값: oo
plot(tan(x), xlim = (-3.14, 3.14), ylim = (-6, 6))
- \(\underset{x\to 0 }{lim}\begin{pmatrix}\frac{\sin x}{x}\end{pmatrix}\)
print("극한값:", limit(sin(x)/x, x, 0))
# 출력 결과
극한값: 1
plot(sin(x)/x, ylim = (-2, 2))
- \(\underset{x\to 0 }{lim} x\sin\begin{pmatrix}\frac{1}{x}\end{pmatrix}\)
print("극한값:", limit(x * sin(1/x), x, 0))
# 출력 결과
극한값: 0
plot(x * sin(1/x), xlim = (-2, 2), ylim = (-1, 1.5))
- 지수함수, 로그함수의 극한
- \(\underset{x\to \infty }{lim} \begin{pmatrix}\frac{2^{x}-2^{-x}}{2^{x}+2^{-x}}\end{pmatrix}\)
print("극한값:", limit((2**x - 2**(-x)) / (2**x + 2**(-x)), x, oo))
# 출력 결과
극한값: 1
plot((2**x - 2**(-x)) / (2**x + 2**(-x)), xlim = (-10, 10), ylim = (-3, 3))
- \(\underset{x\to \infty }{lim} (log_{2}(x+1)-log_{2}(x))=0\)
print("극한값:", limit(log(x+1, 2) - log(x, 2), x, oo))
# 출력 결과
극한값: 0
plot(log(x, 2), log(x+1, 2), xlim = (-4, 6), ylim = (-4, 4))
- 자연로그(\(e\))의 밑
- (1) \(\underset{x\to \infty }{lim} \begin{pmatrix}1+\frac{1}{x}\end{pmatrix}^{x}=e\)
- (2) \(\underset{x\to \infty }{lim} \begin{pmatrix}1+\frac{2}{x}\end{pmatrix}^{x}=e^{2}\)
- (3) \(\underset{x\to 0 }{lim} \frac{(e^{x}-1)}{x}=1\)
- (4) \(\underset{x\to 0 }{lim} \frac{ln(1+x)}{x}=1\)
print('(1):', limit( (1+1/x)**x, x, oo ))
print('(2):', limit( (1+2/x)**x, x, oo ))
print('(3):', limit( (exp(x) -1) / x, x, 0))
print('(4):', limit( (ln(1+x) / x), x, 0))
# 출력 결과
(1): E
(2): exp(2)
(3): 1
(4): 1
# 그래프는 (4)만 출력
plot( ln(1+x) / x, xlim = (-4, 6), ylim = (-2, 8))
9. 미분
- 어떤 한 순간의 변화량을 표시한
- 미분과 기울기
- 어떤 함수를 나타내는 그래프에서 한 점의 미분값(미분계수)를 구하는 것은 해당 점에서의 접선을 의미
- 기울기는 방향성을 가짐
- 이용할 미분 식(수치 미분)
\(\frac{df(x)}{dx}=\displaystyle \lim_{x \to \infty}\frac{f(x+h)-f(x-h))}{2h}\)
- 이용할 미분 식(수치 미분)
- \(h\)는 아주 작은 수를 뜻하는데, 예를 들어 10\(e\)-50 정도의 수를 하면 파이썬은 이를 0.0으로 인식
- 따라서, 딥러닝에서 아주 작은 수를 정할 때, 1\(e\)-4 정도로 설정해도 무방
# 미분 계산하는 함수 정의
def numerical_differential(f, x):
h = 1e-4
return (f(x+h)-f(x-h)) / (2*h)
- 함수 위의 점 \((a, b)\)에서의 접선의 방정식
- 예제: 점 (1, 7)에서의 기울기
# 직접 지정한 2차함수식
def my_func(x):
return 2*x**2 + 3*x + 2
# 1차 선형식
# a: 직선의 x좌표
# b: 직선의 y좌표
# c: 직선의 기울기
def linear_func(a, b, c, x):
return c*(x-a) + b
c = numerical_differential(my_func, 1)
x = np.arange(-5, 5, 0.01)
y = linear_func(1, my_func(1), c, x)
plt.xlabel('x')
plt.ylabel('y')
plt.scatter(1, my_func(1))
plt.plot(x, my_func(x), x, y, 'r-')
plt.title('f(x) & linear function')
plt.show()
- 미분 공식
- \(\frac{d}{dx}(c)=0\) (\(c\)는 상수)
- \(\frac{d}{dx}[cf(x)]=cf'(x)\)
- \(\frac{d}{dx}[f(x)+g(x)]=f'(x)+g'(x)\)
- \(\frac{d}{dx}[f(x)-g(x)]=f'(x)-g'(x)\)
- \(\frac{d}{dx}[f(x)g(x)]=f(x)g'(x)+f'(x)g(x)\) (곱셈 공식)
- \(\frac{d}{dx}[\frac{f(x)}{g(x)}]=\frac{g(x)f'(x)-f(x)g'(x)}{[g(x)]^{2}}\)
- \(\frac{d}{dx}[x^{n}]=nx^{n}-1\)
- 편미분
- 변수가 1개짜리인 위의 수치미분과 달리, 변수가 2개 이상일 때의 미분법을 편미분이라 함
- 다변수 함수에서 특정 변수를 제외한 나머지 변수는 상수로 처리하여 미분을 하는 것
- 각 변수에 대해 미분 표시를 \(\sigma \)를 통해 나타냄
- ex) \(f(x_{0}, x_{1})=x\tfrac{2}{0}+x\tfrac{2}{1}\)
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-4.0, 4.0, 0.4)
y = np.arange(-4.0, 4.0, 0.4)
X, Y = np.meshgrid(x, y)
Z = X**2 + Y**2
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, cmap = 'coolwarm')
ax.set_title('f(x, y) = x**2 + y**2')
plt.show()
- 편미분 예제1: \(x_{0}\)에 대한 편미분, \(\frac{\sigma f}{\sigma x_{0}}\)
x = np.array([1, 2])
def f0_function(x0):
return (x0**2) + (2**2)
print(numerical_differential(f0_function, x[0]))
# 출력 결과
1.9999999999997797
- 편미분 예제2: \(x_{1}\)에 대한 편미분, \(\frac{\sigma f}{\sigma x_{1}}\)
x = np.array([1, 2])
def f1_function(x1):
return (1**2) + (x1**2)
print(numerical_differential(f1_function, x[1]))
# 출력 결과
4.000000000004
- 기울기(gradient)
- 방향성을 가짐
# 기울기를 나타내는 함수
def numerical_diff(f, x):
h = 1e-5
# x와 모양은 같지만 전부 0으로 채워진 배열
grad = np.zeros_like(x)
for i in range(x.size):
tmp = x[i]
x[i] = tmp + h
fxh1 = f(x)
x[i] = tmp - h
fxh2 = f(x)
grad[i] = (fxh1 - fxh2) / (2*h)
x[i] = tmp
return grad
print(numerical_diff(my_func2, np.array([3.0, 4.0])))
print(numerical_diff(my_func2, np.array([1.0, 2.0])))
# 출력 결과
[6. 0.]
[2. 0.]
- 기울기의 의미를 그래프로 확인
- 기울기가 가장 낮은 장소(가운데)로부터 거리가 멀어질수록 기울기가 커짐
- 기울기가 커진다는 것은 영향을 많이 받는다는 의미
- 기울기가 작다는 것은 영향을 적게 받는다는 의미
X = np.arange(-20, 20, 2)
Y = np.arange(-20, 20, 2)
U, V = np.meshgrid(X, Y)
fig, ax = plt.subplots()
# 기울기 표시할 때 화살표로 표시할 수 있는 함수
q = ax.quiver(X, Y, U, V)
ax.quiverkey(q, X = 0.4, Y = 1.0, U = 20, label = 'Quiver Key', labelpos = 'E')
plt.grid()
plt.show()
'Python > Deep Learning' 카테고리의 다른 글
[딥러닝 기초] 신경망 학습 (0) | 2023.03.14 |
---|---|
[딥러닝 기초] 경사하강법 (0) | 2023.03.13 |
[딥러닝 기초] 모델 학습과 손실 함수 (1) | 2023.03.12 |
[딥러닝 기초] 신경망 구조 (0) | 2023.03.09 |
[딥러닝 기초] 신경망 데이터 표현 (0) | 2023.03.08 |