본문 바로가기

Python

Python 활용 #1: 선형 보간법 (linear interpolation) 을 구현해 보자. (야 너도 Python 코딩 할 수 있어! #1) (2020.12.25.)

Python 활용 #1: 선형 보간법 (linear interpolation) 을 구현해 보자.

 

결과 값

 

사용 Python platform: Python IDLE 3.8.3
사용 개념들: x=[], range(), len(), def, for ... loop, if ... else, and, in 

 

 

목차 

1. Motivation

2. 목표: x 가 1과 9 사이에 위치할 때, 즉 $  1 < x_0 < 9 $ 일 경우, 이 $x_0$에 해당되는 $(x_0, y_0)$ 의 근사값을 계산해 보자.

Step 3. Python 을 가동하여 list x, list y, list slope, list y_intercept 를 생성하자. 

Step 4. 목표 수정: 가정을 하나 더 추가하자. (0,0) 값을 추가하자. x 가 0(포함) 과 9(포함) 사이에 위치할 때, 이 x 값에 해당되는 $(x_0, y_0)$ 의 근사값을 계산하자. 

Step 5. slope_generator 라는 함수(function) 을 생성하자.

Step 6. slope_generator 함수를 이용하자. 주어진 x=(1, 4, 9), y=(3, 8, 14)을 사용한다.  
Step 7. y_intercept_generator 라는 함수를 생성하자. x 구간별로 y=mx+b 직선의 그래프에서 어떤 y절편 값 b을 사용할 것인지 수식화하자.  
Step 8. Interpolation 에 적용할 x1 값들이 x=[1,4,9] 중 어느 구간에 속하는지 계산하자. 함수 location_check를 만든다.  

Step 9. 테스팅할 x1 리스트와 x1 리스트에 해당되는 x1_in_x 리스트를 감안하여 x1 리스트에 해당되는 y_interpolated 리스트를 계산하자. 

 

 

본문

Step 1. Motivation

가정1: 위 table 과 같이 순서쌍 (x,y) 값들이 주어졌다고 가정하자. 

(order가 0에서부터 시작하는 이유: Python은 순서를 셀 때, 1이 아니라 0부터 센다고 한다.)

 

 

Step 2. 목표: x 가 1과 9 사이에 위치할 때, 즉 $  1 < x_0 < 9 $ 일 경우, 이 $x_0$에 해당되는 $(x_0, y_0)$ 의 근사값을 계산해 보자.

즉, 일종의 interpolation 계산이다. 

 

 

추가 가정들: 

가정2: x와 y간 함수가 존재한다고 가정하자. $ f(x) = y $

 

가정3: 함수 f(x)는 x의 구간별로 함수가 적용되고, 각 구간별 f(x)는 직선의 방정식(linear equation)으로 표현할 수 있다. 

$ \left\{\begin{matrix}
1\leqslant x \leqslant 4, & f(x)=m_1*x+b_1\\ 
4\leqslant x \leqslant 9, & f(x)=m_2*x+b_2
\end{matrix}\right. $

 

조금 일반적으로 표현하자면, 

$ for \quad x \in (x_i, x_{i+1}) \quad and \quad i = 0, 1, 2 \quad \exists g(x) \quad where \quad g(x) = f(x) $

 

f(x) 함수는 선형 함수로 가정하고 $ f(x) = mx+b $

m은 $(x_i, y_i), (x_{i+1} , y_{i+1}) $를 이용해 정의한다: $ m=\frac{y_{i+1}-y_i}{x_{i+1}-x_i} $ 

 

직관적으로/시각적으로 표현하자면: 

순서쌍 (x,y) 간 아래와 같은 선형(linear) 관계가 성립한다고 가정하자. 

$ x_0 = 6 $ 으로 가정하자. f(6) 의 근사값을 계산해 보자. 

 

 

Step 3. Python 을 가동하여 list x, list y, list slope, list y_intercept 를 생성하자. 

 

이번 예제에서 나는 Python 3.8.3 IDLE 을 사용하였다. 

x=[1,4,9] # x 값들을 입력한다. 

y=[3,8,14] # y 값들을 입력한다. 

 

>> len(x) =3 

#즉, list x 의 길이는 3으로 출력된다. list y도 마찬가지. 

 

지금까지 입력된 값들을 matrix로 표현하면,

 

$ x = \begin{bmatrix} 1 \\ 4 \\ 9 \end{bmatrix} $

$ y = \begin{bmatrix} 3 \\ 8 \\ 14 \end{bmatrix} $

 

$matrix \quad A = \begin{bmatrix}
1 & 3\\ 
4 & 8\\ 
9 & 14
\end{bmatrix}$

 

 

기울기 list 와 y 절편 list를 위한 list를 생성하자. 

일단, list의 값들은 0으로 부여하자. 

x matrix 의 길이만큼 slope list 와 y 절편 (y-intercept) list를 생성하자. 

 

slope = [0 for n in (range(0, len(x)))]       # x matrix 길이만큼 slope matrix를 생성
y_intercept = [0 for n in (range(0, len(x)))]       # x matrix 길이만큼 y_intercept matrix를 생성

 

설명: range(0:3) 은 0부터 (0포함) 3까지의 숫자 범위에 속하는 정수(integer)들의 집합을 나타낸다.

즉,  $ [0, 3)$ 구간에 속하는 interger 이므로 range(0:3) = {0, 1, 2} 가 된다.

 

Python에서 표현해 보면, 

list(range(0,3))

>>> [0, 1, 2] 

 

내친김에 다른 예제도 시험해 보자. 

list(range(-1,4))

>>> [-1, 0, 1, 2, 3] 

 

list(0 for n in (range(0,3))) 을 설명해보자.

n in range(0,3)은 n in [0,1,2] 이라는 의미이며, 

0 for n in [0, 1, 2] 은 

n = 0 일때 list의 0번째 값을 0으로 설정하고,

n = 1 일때, list의 1번째 값을 0으로 설정하고,

n = 2 일때 list의 2번째 값을 0으로 설정하라는 의미이다.

 

즉, list(0 for n in (range(0,3))) = [0,0,0] 이 된다. 

y_intercept 도 마찬가지의 논리로, [0,0,0] 이 되겠다.

 

$ slope = \begin{bmatrix} 0 \\ 0 \\ 0 \end{bmatrix} $

$ y_ intercept = \begin{bmatrix} 0 \\ 0 \\ 0 \end{bmatrix} $

 

지금까지 입력된 값들을 matrix로 표현하면,

$\begin{bmatrix}
1 & 3 & 0 & 0 \\ 
4 & 8 & 0 & 0 \\ 
9 & 14 & 0 & 0 
\end{bmatrix}$

 

 

Step 4. 가정을 하나 더 추가하자. (0,0) 값을 추가하자. 

 

Step 5. slope_generator 라는 함수(function) 을 생성하자. x 구간별로 y=mx+b 직선의 그래프에서 어떤 기울기값 m을 사용할 것인지 수식화하자. 

 

f(x) 함수는 선형 함수로 가정하고 $ f(x) = mx+b $

m은 $(x_i, y_i), (x_{i+1} , y_{i+1}) $를 이용해 정의한다: $ m=\frac{y_{i+1}-y_i}{x_{i+1}-x_i} $ 

 

아래 그림을 참고하면 이해가 더 잘 될 것이다. 

 

 

 

def slope_generator(x,y,slope): 
    for i in (range(0, len(x))):
        if i==0:
            slope[i] = y[i]/x[i]
        else:
            slope[i] = (y[i]-y[i-1])/(x[i]-x[i-1])

 

 

Step 6. slope_generator 함수를 이용하자. 주어진 x=(1, 4, 9), y=(3, 8, 14)을 사용한다. 

 

slope_generator(x,y,slope)

slope
>>> [3.0, 1.6666666666666667, 1.2]

 

 

 

출력값 설명 

$ 0 \leq x \leq 1 $ 일 경우, linear interpolation $y=f(x)=mx+b$ 에 쓰일 기울기 m 의 값은 3

$ 1 < x \leq 1 $ m 값은 1.666...

$ 4 < x \leq 9 $ m 값은 1.2

 

 

Step 7. y_intercept_generator 라는 함수를 생성하자. x 구간별로 y=mx+b 직선의 그래프에서 어떤 y절편 값 b을 사용할 것인지 수식화하자. 

 

(x, y) 값과 m 값이 주어질 경우, y = mx + b 등식에서 y - mx = b가 계산된다. 이를 이용하자.

 

def y_intercept_generator(x,y,y_intercept):
    for i in (range(0, len(x))):
        if i==0:
            y_intercept[i] == 0
        else:
            y_intercept[i] = y[i]-x[i]*(y[i]-y[i-1])/(x[i]-x[i-1])

 

y_intercept_generator(x,y,y_intercept) #y 절편값들을 출력해보자 

 

 

 

출력값 설명 

$ 0 \leq x \leq 1 $ 일 경우, linear interpolation $ y=f(x)=mx+b $ 에 쓰일 y-intercept b 의 값은 0

$ 1 < x \leq 4 $ 일 경우, linear interpolation $ y=f(x)=mx+b $ 에 쓰일 y-intercept b 의 값은 1.3333....

$ 4 < x \leq 9 $ 일 경우, linear interpolation $ y=f(x)=mx+b $ 에 쓰일 y-intercept b 의 값은 3.1999...

 

 

Step 8. Interpolation 에 적용할 x1 값들이 x=[1,4,9] 중 어느 구간에 속하는지 계산하자. 함수 location_check를 만든다. 

 

테스트 할 x 값을 x1으로 지정하자.

x1=[0, 0, 0.5, 0.7, 0.3, 2, 1.3, 6, 7, 8, 8.3, 8.999]

 

x1의 값이 x=[1,4,9] 중 어느 구간에 속하는지 결과값을 저장할 x1_in_x 을 만든다. 

x1_in_x 의 길이 = x1의 길이가 되어야 한다. 

x1_in_x = [0 for n in (range(0, len(x1)))]   

 

결과값들을 확인해 보자 

>>> x1_in_x
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

 

>>> len(x1) == len(x1_in_x)
True

 

함수 location_check를 정의하자.

목표: x1의 값이 x=[1,4,9]의 구간 중 

$ x \leq 1 $ 에 속하는가? 속한다면 결과값으로 1을 부여한다. 

$ 1 < x \leq 4 $ 에 속하는가? 속한다면 결과값으로 4를 부여한다.

$ 4 < x \leq 9 $ 에 속하는가? 속한다면 결과값으로 9를 부여한다. 

 

 

def location_check(x,x1,result):
    for i in (range(0, len(x1))):
        if x1[i] <= x[0]:
            result[i] = x[0]
        else:
            for j in (range(0,len(x))):
                if (x[j] < x1[i]) and (x1[i] <= x[j+1]):
                    result[i] = x[j+1]

 

함수가 정의되었으니, 주어진 x 값들과 x1값들로  x1_in_x를 계산해보자. 

location_check(x,x1,x1_in_x)

 

값을 출력해 보자 

>>> x1_in_x
[1, 1, 1, 1, 1, 4, 4, 9, 9, 9, 9, 9]

 

 

적절하게 계산이 되는 것 같다. 

 

 

Step 9. 테스팅할 x1 리스트와 x1 리스트에 해당되는 x1_in_x 리스트를 감안하여 x1 리스트에 해당되는 y_interpolated 리스트를 계산하자. 

 

$ y_1 = m*x_1 + b $ 수식에서, x_1에 해당되는 x 구간을 찾고, 해당 x 구간의 m 과 b를 사용하여 y를 계산한다. 

$ x_1 \mapsto x \mapsto (m_x, b_x) \mapsto y = x*m_x + b_x $

 

직관적으로 구성해 보자. 

x = [1, 4, 9] 

slope = [3.0, 1.6666666666666667, 1.2] 

y_intercept = [0, 1.333333333333333, 3.1999999999999993]

x1 = [0, 0, 0.5, 0.7, 0.3, 2, 1.3, 6, 7, 8, 8.3, 8.999]

 

예1 : $ x_1 = 0 \mapsto x=0 \mapsto (3, 0) \mapsto y = 0*3 + 0 $

예2 : $ x_1 = 1.3 \mapsto x 4 \mapsto (1.66.. \quad , 1.33...) \mapsto y = 1.3*1.66... + 1.33.. $

 

 

def y_interpolation(x, y,  slope, y_intercept, x1, x1_in_x, y_interpolated):
    for i in (range(0, len(x1_in_x))):
        for j in (range(0, len(x))):
            if x1_in_x[i] == x[j]:
                y_interpolated[i]= slope[j] * x1[i] + y_intercept[j]


y_interpolation(x, y,  slope, y_intercept, x1, x1_in_x, y_interpolated)

 

 

x1 list의 값들에 해당되는 y의 근사값을 출력하자 

y_interpolated

[0.0, 0.0, 1.5, 2.0999999999999996, 0.8999999999999999, 4.666666666666666, 3.5, 10.399999999999999, 11.6, 12.799999999999999, 13.16, 13.9988]

 

 

 

끝 

 

제목: Python 활용 #1: 선형 보간법 (linear interpolation) 을 구현해 보자. (야 너도 Python 코딩 할 수 있어! #1) (2020.12.25.)  

사용 Python platform: Python IDLE 3.8.3
사용 개념들: x=[], range(), len(), def, for ... loop, if ... else, and, in 

 

참고자료:

LaTex editor online www.codecogs.com/latex/eqneditor.php

Tistory blog에서 LaTex 입력하는 방법 bskyvision.com/476