<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 선형 회귀 분석의 기초
회귀 분석(regression analysis)은 입력 자료(독립 변수) $x$와 이에 대응하는 출력 자료(종속 변수) $y$간의 관계를 정량과 하기 위한 작업이다. 
회귀 분석에는 결정론적 모형(Deterministic Model)과 확률적 모형(Probabilistic Model)이 있다.
결정론적 모형은 단순히 독립 변수 $x$에 대해 대응하는 종속 변수 $y$를 계산하는 함수를 만드는 과정이다.
$$ \hat{y} = f \left( x; { x_1, y_1, x_2, y_2, \cdots, x_N, y_N } \right) = f (x; D) = f(x) $$
여기에서 $ { x_1, y_1, x_2, y_2, \cdots, x_N, y_N } $ 는 모형 계수 추정을 위한 과거 자료이다.
만약 함수가 선형 함수이면 선형 회귀 분석(linear regression analysis)이라고 한다.
$$ \hat{y} = w_0 + w_1 x_1 + w_2 x_2 + \cdots + w_D x_D $$
Augmentation
일반적으로 회귀 분석에 앞서 다음과 같이 상수항을 독립 변수에 포함하는 작업이 필요할 수 있다. 이를 feature augmentation이라고 한다.
$$
x_i =
\begin{bmatrix}
x_{i1} \ x_{i2} \ \vdots \ x_{iD}
\end{bmatrix}
\rightarrow 
x_{i,a} =
\begin{bmatrix}
1 \ x_{i1} \ x_{i2} \ \vdots \ x_{iD}
\end{bmatrix}
$$
augmentation을 하게 되면 모든 원소가 1인 벡터를 feature matrix 에 추가된다.
$$
X =
\begin{bmatrix}
x_{11} & x_{12} & \cdots & x_{1D} \
x_{21} & x_{22} & \cdots & x_{2D} \
\vdots & \vdots & \vdots & \vdots \
x_{N1} & x_{N2} & \cdots & x_{ND} \
\end{bmatrix}
\rightarrow 
X_a =
\begin{bmatrix}
1 & x_{11} & x_{12} & \cdots & x_{1D} \
1 & x_{21} & x_{22} & \cdots & x_{2D} \
\vdots & \vdots & \vdots & \vdots & \vdots \
1 & x_{N1} & x_{N2} & \cdots & x_{ND} \
\end{bmatrix}
$$
augmentation을 하면 가중치 벡터(weight vector)도 차원이 증가하여 전체 수식이 다음과 같이 단순화 된다.
$$ w_0 + w_1 x_1 + w_2 x_2
\begin{bmatrix}
1 & x_1 & x_2
\end{bmatrix}
\begin{bmatrix}
w_0 \ w_1 \ w_2
\end{bmatrix}
= x_a^T w
$$
Step1:  OLS (Ordinary Least Squares)
OLS는 가장 기본적인 결정론적 회귀 방법으로 Residual Sum of Squares(RSS)를 최소화하는 가중치 벡터 값을 미분을 통해 구한다.
Residual 잔차
$$ e_i = {y}_i - x_i^T w $$
Stacking (Vector Form)
$$ e = {y} - Xw $$
Residual Sum of Squares (RSS)
$$\begin{eqnarray}
\text{RSS} 
&=& \sum (y_i - \hat{y}_i)^2 \
&=& \sum e_i^2 = e^Te \
&=& (y - Xw)^T(y - Xw) \
&=& y^Ty - 2y^T X w + w^TX^TXw
\end{eqnarray}$$
Minimize using Gradient
$$ \dfrac{\partial \text{RSS}}{\partial w} = -2 X^T y + 2 X^TX w = 0 $$
$$ X^TX w = X^T y $$
$$  w = (X^TX)^{-1} X^T y $$
여기에서 그레디언트를 나타내는 다음 식을 Normal equation 이라고 한다.
$$ X^T y - X^TX w = 0 $$
Normal equation 에서 잔차에 대한 다음 특성을 알 수 있다.
$$ X^T (y - X w ) = X^T e = 0 $$
Step2:  scikit-learn 패키지를 사용한  선형 회귀 분석
sklearn 패키지를 사용하여 선형 회귀 분석을 하는 경우에는 linear_model 서브 패키지의 LinearRegression 클래스를 사용한다.
http
Step3:  Boston Housing Price
Step4:  statsmodels 를 사용한 선형 회귀 분석
statsmodels 패키지에서는 OLS 클래스를 사용하여 선형 회귀 분석을 실시한다.
http
Step5:  RegressionResults 클래스는 분석 결과를 다양한 속성에 저장해주므로 추후 사용자가 선택하여 활용할 수 있다.
Step6:  statsmodel는 다양한 회귀 분석 결과 플롯도 제공한다.
plot_fit(results, exog_idx)   Plot fit against one regressor.
abline_plot([intercept, ...]) Plots a line given an intercept and slope.
influence_plot(results[, ...])    Plot of influence in regression.
plot_leverage_resid2(results) Plots leverage statistics vs.
plot_partregress(endog, ...)  Plot partial regression for a single regressor.
plot_ccpr(results, exog_idx)  Plot CCPR against one regressor.
plot_regress_exog(results, ...)   Plot regression results against one regressor.
<ASSISTANT_TASK:>
Python Code:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
%matplotlib inline
from sklearn.datasets import make_regression
bias = 100
X0, y, coef = make_regression(n_samples=100, n_features=1, bias=bias, noise=10, coef=True, random_state=1)
X = np.hstack([np.ones_like(X0), X0])
np.ones_like(X0)[:5] # no.ones_like(X0) : X0 사이즈와 동일한데 내용물은 1인 행렬 생성
X[:5]
Explanation: 선형 회귀 분석의 기초
회귀 분석(regression analysis)은 입력 자료(독립 변수) $x$와 이에 대응하는 출력 자료(종속 변수) $y$간의 관계를 정량과 하기 위한 작업이다. 
회귀 분석에는 결정론적 모형(Deterministic Model)과 확률적 모형(Probabilistic Model)이 있다.
결정론적 모형은 단순히 독립 변수 $x$에 대해 대응하는 종속 변수 $y$를 계산하는 함수를 만드는 과정이다.
$$ \hat{y} = f \left( x; { x_1, y_1, x_2, y_2, \cdots, x_N, y_N } \right) = f (x; D) = f(x) $$
여기에서 $ { x_1, y_1, x_2, y_2, \cdots, x_N, y_N } $ 는 모형 계수 추정을 위한 과거 자료이다.
만약 함수가 선형 함수이면 선형 회귀 분석(linear regression analysis)이라고 한다.
$$ \hat{y} = w_0 + w_1 x_1 + w_2 x_2 + \cdots + w_D x_D $$
Augmentation
일반적으로 회귀 분석에 앞서 다음과 같이 상수항을 독립 변수에 포함하는 작업이 필요할 수 있다. 이를 feature augmentation이라고 한다.
$$
x_i =
\begin{bmatrix}
x_{i1} \ x_{i2} \ \vdots \ x_{iD}
\end{bmatrix}
\rightarrow 
x_{i,a} =
\begin{bmatrix}
1 \ x_{i1} \ x_{i2} \ \vdots \ x_{iD}
\end{bmatrix}
$$
augmentation을 하게 되면 모든 원소가 1인 벡터를 feature matrix 에 추가된다.
$$
X =
\begin{bmatrix}
x_{11} & x_{12} & \cdots & x_{1D} \
x_{21} & x_{22} & \cdots & x_{2D} \
\vdots & \vdots & \vdots & \vdots \
x_{N1} & x_{N2} & \cdots & x_{ND} \
\end{bmatrix}
\rightarrow 
X_a =
\begin{bmatrix}
1 & x_{11} & x_{12} & \cdots & x_{1D} \
1 & x_{21} & x_{22} & \cdots & x_{2D} \
\vdots & \vdots & \vdots & \vdots & \vdots \
1 & x_{N1} & x_{N2} & \cdots & x_{ND} \
\end{bmatrix}
$$
augmentation을 하면 가중치 벡터(weight vector)도 차원이 증가하여 전체 수식이 다음과 같이 단순화 된다.
$$ w_0 + w_1 x_1 + w_2 x_2
\begin{bmatrix}
1 & x_1 & x_2
\end{bmatrix}
\begin{bmatrix}
w_0 \ w_1 \ w_2
\end{bmatrix}
= x_a^T w
$$
End of explanation
y = y.reshape(len(y), 1)
w = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), y)
print("bias:", bias)
print("coef:", coef)
print("w:\n", w)
w = np.linalg.lstsq(X, y)[0]
w
xx = np.linspace(np.min(X0) - 1, np.max(X0) + 1, 1000)
XX = np.vstack([np.ones(xx.shape[0]), xx.T]).T
yy = np.dot(XX, w)
plt.scatter(X0, y)
plt.plot(xx, yy, 'r-')
plt.show()
Explanation: OLS (Ordinary Least Squares)
OLS는 가장 기본적인 결정론적 회귀 방법으로 Residual Sum of Squares(RSS)를 최소화하는 가중치 벡터 값을 미분을 통해 구한다.
Residual 잔차
$$ e_i = {y}_i - x_i^T w $$
Stacking (Vector Form)
$$ e = {y} - Xw $$
Residual Sum of Squares (RSS)
$$\begin{eqnarray}
\text{RSS} 
&=& \sum (y_i - \hat{y}_i)^2 \
&=& \sum e_i^2 = e^Te \
&=& (y - Xw)^T(y - Xw) \
&=& y^Ty - 2y^T X w + w^TX^TXw
\end{eqnarray}$$
Minimize using Gradient
$$ \dfrac{\partial \text{RSS}}{\partial w} = -2 X^T y + 2 X^TX w = 0 $$
$$ X^TX w = X^T y $$
$$  w = (X^TX)^{-1} X^T y $$
여기에서 그레디언트를 나타내는 다음 식을 Normal equation 이라고 한다.
$$ X^T y - X^TX w = 0 $$
Normal equation 에서 잔차에 대한 다음 특성을 알 수 있다.
$$ X^T (y - X w ) = X^T e = 0 $$
End of explanation
from sklearn.datasets import load_diabetes
diabetes = load_diabetes()
dfX_diabetes = pd.DataFrame(diabetes.data, columns=["X%d" % (i+1) for i in range(np.shape(diabetes.data)[1])])
dfy_diabetes = pd.DataFrame(diabetes.target, columns=["target"])
df_diabetes0 = pd.concat([dfX_diabetes, dfy_diabetes], axis=1)
df_diabetes0.tail()
from sklearn.linear_model import LinearRegression
model_diabetes = LinearRegression().fit(diabetes.data, diabetes.target)
print(model_diabetes.coef_)
print(model_diabetes.intercept_)
predictions = model_diabetes.predict(diabetes.data)
plt.scatter(diabetes.target, predictions)
plt.xlabel("target")
plt.ylabel("prediction")
plt.show()
mean_abs_error = (np.abs(((diabetes.target - predictions)/diabetes.target)*100)).mean()
print("MAE: %.2f%%" % (mean_abs_error))
import sklearn as sk
sk.metrics.median_absolute_error(diabetes.target, predictions)
sk.metrics.mean_squared_error(diabetes.target, predictions)
Explanation: scikit-learn 패키지를 사용한  선형 회귀 분석
sklearn 패키지를 사용하여 선형 회귀 분석을 하는 경우에는 linear_model 서브 패키지의 LinearRegression 클래스를 사용한다.
http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html
입력 인수 
fit_intercept : 불리언, 옵션
상수상 추가 여부
normalize : 불리언, 옵션
회귀 분석전에 정규화 여부
속성
coef_ : 추정된 가중치 벡터
intercept_ : 추정된 상수항 
Diabetes Regression
End of explanation
from sklearn.datasets import load_boston
boston = load_boston()
dfX_boston = pd.DataFrame(boston.data, columns=boston.feature_names)
dfy_boston = pd.DataFrame(boston.target, columns=["MEDV"])
df_boston0 = pd.concat([dfX_boston, dfy_boston], axis=1)
df_boston0.tail()
model_boston = LinearRegression().fit(boston.data, boston.target)
print(model_boston.coef_)
print(model_boston.intercept_)
predictions = model_boston.predict(boston.data)
plt.scatter(boston.target, predictions)
plt.xlabel("target")
plt.ylabel("prediction")
plt.show()
mean_abs_error = (np.abs(((boston.target - predictions)/boston.target)*100)).mean()
print("MAE: %.2f%%" % (mean_abs_error))
sk.metrics.median_absolute_error(boston.target, predictions)
sk.metrics.mean_squared_error(boston.target, predictions)
Explanation: Boston Housing Price
End of explanation
df_diabetes = sm.add_constant(df_diabetes0)
df_diabetes.tail()
model_diabetes2 = sm.OLS(df_diabetes.ix[:, -1], df_diabetes.ix[:, :-1])
result_diabetes2 = model_diabetes2.fit()
result_diabetes2
print(result_diabetes2.summary())
df_boston = sm.add_constant(df_boston0)
model_boston2 = sm.OLS(df_boston.ix[:, -1], df_boston.ix[:, :-1])
result_boston2 = model_boston2.fit()
print(result_boston2.summary())
Explanation: statsmodels 를 사용한 선형 회귀 분석
statsmodels 패키지에서는 OLS 클래스를 사용하여 선형 회귀 분석을 실시한다.
http://www.statsmodels.org/dev/generated/statsmodels.regression.linear_model.OLS.html
statsmodels.regression.linear_model.OLS(endog, exog=None)
입력 인수
endog : 종속 변수. 1차원 배열
exog : 독립 변수, 2차원 배열. 
statsmodels 의 OLS 클래스는 자동으로 상수항을 만들어주지 않기 때문에 사용자가 add_constant 명령으로 상수항을 추가해야 한다.
모형 객체가 생성되면 fit, predict 메서드를 사용하여 추정 및 예측을 실시한다.
예측 결과는 RegressionResults 클래스 객체로 출력되면 summary 메서드로 결과 보고서를 볼 수 있다.
End of explanation
dir(result_boston2)
Explanation: RegressionResults 클래스는 분석 결과를 다양한 속성에 저장해주므로 추후 사용자가 선택하여 활용할 수 있다.
End of explanation
sm.graphics.plot_fit(result_boston2, "CRIM")
plt.show()
Explanation: statsmodel는 다양한 회귀 분석 결과 플롯도 제공한다.
plot_fit(results, exog_idx)   Plot fit against one regressor.
abline_plot([intercept, ...]) Plots a line given an intercept and slope.
influence_plot(results[, ...])    Plot of influence in regression.
plot_leverage_resid2(results) Plots leverage statistics vs.
plot_partregress(endog, ...)  Plot partial regression for a single regressor.
plot_ccpr(results, exog_idx)  Plot CCPR against one regressor.
plot_regress_exog(results, ...)   Plot regression results against one regressor.
End of explanation
<END_TASK>