파이썬을 사용한 회귀 분석의 개념 해설 2 부

α와 β의 값 찾기



그래프로 이미지 잡기



이 기사의 그 1 에서는, $\alpha$ 와 $\beta$ 각각을 어떠한 값으로 고정했을 경우에 최소치를 찾아낼 수 있는 것을 보았습니다만, 실제로 이 데이터에 대해서 근사 직선 (회귀 직선 ) 매개 변수 $\alpha,\beta$를 찾으려면 $\alpha$와 $\beta$가 동시에 최소값을 취하는 경우를 찾아야합니다.

그 1 에서 다룬 함수 $S$를 $\alpha$와 $\beta$의 2변수 함수로 보고 정리하면 아래와 같이 됩니다.

S(\alpha, \beta) = 
\left( \sum_i^n x_i^2 \right) \alpha^2 + n\beta^2
+ 2 \left( \sum_i^n x_i \right)\alpha \beta
- 2 \left( \sum_i^n x_i y_i \right)\alpha 
- 2 \left( \sum_i^n y_i \right)\beta
+ \sum_i^n y_i^2

또, 각 계수는 데이터로부터 구해지므로 ( 그 1 로 계산하고 있습니다),
n=50
\left( \sum_i^n x_i^2 \right) =34288
\left( \sum_i^n y_i^2 \right)=11604
\left( \sum_i^n x_iy_i \right)=18884
\left( \sum_i^n x_i \right)=1240
\left( \sum_i^n y_i \right)=655

그리고 이것을 대입하면

S(\alpha, \beta) = 
34288 \alpha^2 + 50\beta^2
+ 2480\alpha \beta
- 37768\alpha 
- 1310 \beta
+ 11604

됩니다. 이 2 변수 2 차 곡선의 그래프를 작성해 보겠습니다.
세로축 $S$는 각 데이터의 점과 직선 사이의 거리(오차)의 제곱합이군요. 이것이 가장 작은 곳을 찾으십시오.

from mpl_toolkits.mplot3d.axes3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

# set field
X = np.linspace(0.2, 1.3, 100)
Y = np.linspace(-25, 15, 100)

# set data
#sum(x**2)
sum_x_2 = 34288.2988
#sum(y**2)
sum_y_2 = 11603.8684051
#dot(x,y)
sum_xy = 18884.194896
#sum(x)
sum_x = 1239.7
#sum(y)
sum_y = 655.0152
X, Y = np.meshgrid(X, Y)
#S(α,β)=34288α^2 + 50β^2 + 2480αβ − 37768α − 1310β + 11604
S = (sum_x_2 * (X**2)) + (50 * (Y**2)) + (2 * sum_x * X * Y) + (-2 * sum_xy  * X) + (-2 * sum_y * Y) + sum_y_2

# prepare plot
fig = plt.figure(figsize=(18,6))
ax = fig.add_subplot(121, projection='3d', azim=60)
ax.set_xlabel("alpha")
ax.set_ylabel("beta")
ax.set_zlabel("S")

# draw 3D graph
surf = ax.plot_surface(X, Y, S, rstride=1, cstride=1, cmap=cm.coolwarm,
        linewidth=0, antialiased=False)

# draw contour
ax = fig.add_subplot(122)
plt.contour(X,Y,S,50)
ax.set_xlabel("alpha")
ax.set_ylabel("beta")

plt.show()



왼쪽의 3D 그래프라면 조금 이해하기 어렵습니다만, 오른쪽의 등고선 그래프를 보면 어쩐지 타원의 중심에 있는 최소치는 전에 육안으로 예측한 $\alpha = 0.74,\beta = -5$에 가까운 느낌 네요!

계산으로 풀어보기



계산으로 풀기 위해서는 $S$를 각각 $\alpha$와 $\beta$로 편미분하여 0이 되는 값을 구합니다.
$S$를 각각 $\alpha$와 $\beta$의 함수로 기술하면 다음과 같이 됩니다.

S(\alpha) = \left( \sum_i^n x_i^2 \right) \alpha^2
 + 2\left( \sum_i^n (x_i\beta - x_i y_i ) \right) \alpha 
 + n\beta^2 - 2\beta\sum_i^n y_i + \sum_i^n y_i^2

S(\beta) = n\beta^2
+ 2 \left( \sum_i^n (x_i\alpha - y_i) \right) \beta
+ \alpha^2\sum_i^n x_i^2 - 2\alpha \sum_i^n x_iy_i + \sum_i^n y_i^2

이것을 각각 편미분하여 0으로 놓기 때문에,

\frac{\partial S}{\partial \alpha} = 0,

\frac{\partial S}{\partial \beta } = 0,

의 연립방정식을 풀게 됩니다. 즉,

\frac{\partial S}{\partial \alpha} =  2\left(\sum_i^n x_i^2 \right) \alpha +  2\left( \sum_i^n x_i \right) \beta - 2\sum_i^n x_i y_i = 0

\frac{\partial S}{\partial \beta} = 2n\beta + 2\left( \sum_i^n x_i\right) \alpha - 2\sum_i^ny_i = 0

풀어야합니다. 데이터로부터 구한 값을 대입하면,
\frac{1}{2}\frac{\partial S}{\partial \alpha} =  34288 \alpha +  1240 \beta - 18884 = 0
\frac{1}{2}\frac{\partial S}{\partial \beta} = 50 \beta + 1240 \alpha - 655 = 0

이것을 Python을 사용하여 연립 방정식을 풀면,
from sympy import *
a, b = symbols('a b')
init_printing()

# 34288α + 1240β − 18884 = 0
#    50β + 1240α −   655 = 0
solve([34288 * a + 1240 * b - 18884, 50* b + 1240 * a - 655], [a, b])

a --> 0.746606334842
b --> -5.41583710407

\alpha = 0.746606334842
\beta  = -5.41583710407

처럼 해를 얻을 수

다시 한번, 이 $\alpha,\beta$ 의 값을 대입해 산포도에 직선을 플롯해 보면, 아래와 같이 됩니다.
import numpy as np
import matplotlib.pyplot as plt

data= np.loadtxt('cars.csv',delimiter=',',skiprows=1)
data[:,1] = map(lambda x: x * 1.61, data[:,1])    # mph から km/h に変換
data[:,2] = map(lambda y: y * 0.3048, data[:,2])  # ft から  m に変換

fig = plt.figure(figsize=(10,6))
ax = fig.add_subplot(111)
ax.set_xlim(0,50)
ax.set_title("Stopping Distances of Cars with estimated regression line")
ax.set_xlabel("speed(km/h)")
ax.set_ylabel("distance(m)")
plt.scatter(data[:,1],data[:,2])

x = np.linspace(0,50,50)
y = 0.746606334842 * x -5.41583710407
plt.plot(x,y)



이것은 회귀 직선입니다

애니메이션으로 설명해 보는 기사에 계속 .

좋은 웹페이지 즐겨찾기