EunGyeongKim

지도학습 : 회귀_2차원 모델(평면) 본문

ML & DL/딥러닝

지도학습 : 회귀_2차원 모델(평면)

EunGyeongKim 2023. 2. 22. 15:44

입력이 2차원일 경우 x=(x0, x1)에 확장

1차원일경우 xn은 나이만 의미했지만, 이번에는 몸무게 정보도 사용하여 키를 예측함

사람 체질량 지수가 23이라고 가정하여 데이터를 만듬

$$weight = 23 * \frac{height^2}{100}* noise$$

나이를 x0으로, 몸무게 데이터를 x1로 추가함.

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

#create data
x_n = 16

np.random.seed(seed=1)
x = 5+25 * np.random.rand(x_n)
x0 = x
x0_min = 5
x0_max = 30

prm_c = [170, 108, 0.2] # 생성 매개변수
t = prm_c[0] - prm_c[1] * np.exp(-prm_c[2]*x) + 4 *np.random.randn(x_n)

x1 = 23 * (t/100)**2*np.random.randn(x_n)
x1_min = 40
x1_max = 75

# show 2D data
def show_data2(ax, x0, x1, t):
    for i in range(len(x0)):
        ax.plot([x0[i],x0[i]], [x1[i], x1[i]], [120, t[i]], color='gray')
        ax.plot(x0, x1, t, 'o', color='cornflowerblue', markeredgecolor='black', markersize =6, markeredgewidth=0.5)
        #elev = elevation angle(양각), azim = azimuth angle(x,y plane angle)
        ax.view_init(elev=35, azim=-75)
    
#main
plt.figure(figsize=(6,5))
ax = plt.subplot(1,1,1, projection='3d')
show_data2(ax, x0, x1, t)
plt.show()

 

tip. 데이터 표시 방법

n = 데이터 번호
m = 벡터의 요소(0=나이, 1=몸무게 등)
n, m은 x의 아래첨자로 씀.
$$x_n = [x_{n,0}, x_{n,1}]$$

 

N개의 2차원 벡터 xn에 대해 각각 tn이 할당됨. 2d은 1d보다 1차원이 늘어났으므로 선이 아니라 면을 적용하면 새로운 x=[x0, x1]에 대해 t(키)가 예측이 가능함

임의의 w에 대해 면을 그리는 함수

# show plane
def show_plane(ax, w):
    px0 = np.linspace(x0_min, x0_max, 5)
    px1 = np.linspace(x1_min, x1_max, 5)
    px0, px1 = np.meshgrid(px0, px1)
    y = w[0]*px0 + w[1]*px1 + w[2]
    ax.plot_surface(px0, px1, y, rstride = 1, cstride = 1, alpha=0.3, color = 'blue', edgecolor='black')

# plane mse
def mse_plane(x0, x1, t, w):
    y = w[0]*x0 + w[1]*x1 + w[2]
    mse = np.mean((y-t)**2)
    return mse

#main
plt.figure(figsize=(6,5))
ax = plt.subplot(1,1,1,projection='3d')
w = [1.5, 1, 90]
show_plane(ax, w)
show_data2(ax, x0, x1, t)
mse = mse_plane(x0, x1, t, w)
print("SD={0:.3f}cm".format(np.sqrt(mse)))
plt.show()

매개변수의 해석해

데이터에 가장 적합한 w = [w0, w1, w2]를 구하자. 2차원 면 모델의 경우에도 1차원과 마찬가지로 평균제곱오차를 다음과 같이 정의 가능

$$J = \frac{1}{N}\sum_{n=0}^{N-1}(y(x_n) - t_n)^2 = \frac{1}{N}\sum_{n=0}^{N-1}(w_0x_{n,0} + w_1x_{n,1} + w_2 - t_n)^2$$

w를 움식이면 면이 여러방향을 향하며, 그에따라 J가 변화함. 목표는 J가 가장 작아지는 w = [w0, w1, w2]를 구하는것임. J를 최소화하는 최적의 w는 기울기가 0임. 따라서 아주 작은 w의 변화에 대해서 J의 변화는 0이기 때문에 J를 w0, w1, w2으로 편미분한것은 0인 관계가 성립됨

$$\frac{\partial J}{\partial w_0} = 0, \frac{\partial J}{\partial w_1} = 0, \frac{\partial J}{\partial w_2} = 0$$

w0에 대한 편미분 식은 다음과 같음.

 $$\frac{\partial J}{\partial w_0} = \frac{2}{N}\sum_{n=0}^{N-1}(w_0x_{n,0} + w_1x_{n, 1}+w_2 - t_n)x_{n, 0}$$

$$ = 2\left\{ w_0 <x_0^2> + w_1<x_0x_1> + w_2<x_0> - <{tx_0}> \right\} = 0$$

 

w1에 대한 편미분 식은 다음과 같음.

$$\frac{\partial J}{\partial w_1} = \frac{2}{N}\sum_{n=0}^{N-1}(w_0x_{n,0} + w_1x_{n, 1}+w_2 - t_n)x_{n, 1}$$

$$= 2\left\{ w_0 <x_0x_1> + w_1<x_1^2> + w_2<x_1> - <{tx_1}> \right\} = 0$$

 

w2에 대한 편미분 식은 다음과 같음.

$$\frac{\partial J}{\partial w_2} = \frac{2}{N}\sum_{n=0}^{N-1}(w_0x_{n,0} + w_1x_{n, 1}+w_2 - t_n)$$

$$= 2\left\{ w_0 <x_0> + w_1<x_1> + w_2 - <t> \right\} = 0$$

 

w0, w1, w2의 연립 방적식을 풀면 다음과 같은 식을 얻을 수 있음.

$$w_0 = \frac{cov(t, x_1) cov(x_0, x_1) - var(x_1)cov(t, x_0)}{cov(x_0, x_1)^2 - var(x_0)var(x_1)}$$

$$w_1 = \frac{cov(t, x_0) cov(x_0, x_1) - var(x_0)cov(t, x_1)}{cov(x_0, x_1)^2 - var(x_0)var(x_1)}$$

$$w_2 = -w_0 <x_0> - w_1<x_1>+<t>$$

'var(a) = <a^2> - <a>^2' 은 a의 분산, 'cov(a, b) = <ab>-<a><b>'는 a와 b의 공분산이라고 불리는 통계량

a의 분산은 a와 얼마나 차이가 있는지를 나타내고, a와 b의 공분산은 a와 b가 서로 얼마나 영향을 끼치고 있는지를 나타냄

 

위 식에 실제 데이터 x0, x1와 목표데이터 t값을 넣어 w0, w1, w2값을 구하고, 그 면을 그려봄

# analytic
def fit_plane(x0, x1, t):
    c_tx0 = np.mean(t*x0) - np.mean(t) * np.mean(x0)
    c_tx1 = np.mean(t*x1) - np.mean(t) * np.mean(x1)
    c_x0x1 = np.mean(x0 * x1) - np.mean(x0) * np.mean(x1)
    v_x0 = np.var(x0)
    v_x1 = np.var(x1)
    w0 = (c_tx1*c_x0x1 - v_x1*c_tx0) / (c_x0x1**2 - v_x0*v_x1)
    w1 = (c_tx0*c_x0x1 - v_x0*c_tx1) / (c_x0x1**2 - v_x0*v_x1)
    w2 = -w0 * np.mean(x0) - w1 * np.mean(x1) + np.mean(t)
    return np.array([w0,w1,w2])

# main
plt.figure(figsize = (6,5))
ax = plt.subplot(1,1,1,projection = '3d')
w = fit_plane(x0, x1, t)
print("w0={0:.1f}, w1={1:.1f}, w2={2:.1f},".format(w[0], w[1], w[2]))
show_plane(ax, w)
show_data2(ax, x0, x1, t)
mse = mse_plane(x0, x1, t, w)
print("SD={0:.3f}cm".format(np.sqrt(mse)))
plt.show()
Comments