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()

거리가 멀어질수록 기울기가 커져 영향을 많이 받음

 

+ Recent posts