Regression(1)

Residual sum of squares(RSS)

  • 실제 값과 회귀 모델의 차이의 제곱이다.
  • 최적의 회귀 모델을 위해서는 잔차의 합이 최소가 되어야 한다.



경사 하강법(Gradient Descent)

  • RSS를 최소화해주는 방법.
  • 점진적인 반복 계산을 통해 회귀 계수의 값을 업데이트하며 오류를 최소화 한다.



  • RSS를 각각의 회귀 계수에 대해서 편미분하고, 결과값을 반복적으로 보정한다.


[코드]

np.dot을 이용한 내적으로 식을 완성한다.

def get_weight_updates(w1, w0, x, y, learning_rate=0.01):
    N = len(y)
    w1_update = np.zeros_like(w1)
    w0_update = np.zeros_like(w0)
    y_pred = np.dot(x, w1.T) + w0
    diff = y-y_pred
    
    w0_factors = np.ones((N,1))
    w1_update = -(2/N)*learning_rate*(np.dot(x.T, diff))
    w0_update = -(2/N)*learning_rate*(np.dot(w0_factors.T, diff))
    
    return w1_update, w0_update

def gradient_descent_steps(x,y,iters=10000):
    w0 = np.zeros((1,1))
    w1 = np.zeros((1,1))
    
    for ind in range(iters):
        w1_update, w0_update = get_weight_updates(w1, w0, x, y, learning_rate=0.01)
        w1 = w1 - w1_update
        w0 = w0 - w0_update
        
    return w1, w0

[결과]

w1 : 4.022 w0 : 6.162
Gradient Descent Total Cost : 0.9935

단, 경사 하강법은 수행 시간이 매우 오래 걸린다.
따라서 일부 데이터만을 이용하는 확률적 경사 하강법(Stochastic Gradient Descent)를 이용한다.



[코드]

x,y 대신 따로 뽑은 sample_x, sample_y를 이용한다.

def stochastic_gradient_descent_steps(x,y,batch_size=10, iters=1000):
    w0 = np.zeros((1,1))
    w1 = np.zeros((1,1))
    prev_cost  = 100000
    iter_index = 0
    
    for ind in range(iters):
        np.random.seed(ind)
        stochastic_random_index = np.random.permutation(x.shape[0])
        sample_x = x[stochastic_random_index[0:batch_size]]
        sample_y = y[stochastic_random_index[0:batch_size]]
        w1_update, w0_update = get_weight_updates(w1,w0,sample_x, sample_y, learning_rate = 0.01)
        w1 = w1 - w1_update
        w0 = w0 - w0_update
    return w1 , w0

[결과]

w1 : 4.028 w0 : 6.156
Stochastic Gradient Descent Total Cost : 0.9937

일반 하강 경사법의 회귀 계수값과 예측 오류비용이 큰 차이가 없다.
따라서 큰 데이터를 처리할 경우 수행속도를 고려하여 확률적 하강 경사법을 사용한다.



LinearRegression

  • LinearRegression 클래스는 RSS를 최소하하는 OLS(Ordinary Least Squares) 추정 방식으로 구현했다.
  • 회귀 모델은 피처의 독립성에 많은 영향을 받는다.

  • 회귀 모델을 평가하는 평가지표.
MAE(Mean Absolute Error) : 실제 값과 예측값의 차이를 절대값으로 변환해 평균한 것.

MSE(Mean Squared Error) : 실제 값과 예측값의 차이를 제곱해 평균한 것.

RMSE(Root Mean Squared Error) : MSE에 루트를 씌운 값.

R^2 : 분산 기반으로 예측 성능 평가하는 지표. 1에 가까울수록 예측 정확도가 높다.


사이킷런 내장 데이터를 이용 선형회귀 모델 (보스턴 주택 가격 데이터)

  • 데이터를 먼저 로드하고 DataFrame으로 변경한다.
boston = load_boston()

bostonDF = pd.DataFrame(boston.data, columns = boston.feature_names)


  • 각각의 피처들이 ‘PRICE’에 미치는 영향을 알아본다.

  • ‘RM’과 ‘LSTAT’의 영향이 가장 큰 것을 볼 수 있다.
  • ‘RM’(방 개수)는 양 방향 선형성을 보여주고, ‘LSTAT’(하위 계층의 비율)은 음 방향 선형성을 보여준다.
  • LinearRegression 클래스를 이용해서 회귀 모델을 만든다.



[코드]

y_target = bostonDF['PRICE']
X_data = bostonDF.drop(['PRICE'], axis=1, inplace=False)

X_train, X_test, y_train, y_test = train_test_split(X_data, y_target, test_size = 0.3, random_state=156)

lr = LinearRegression()
lr.fit(X_train, y_train)
y_preds = lr.predict(X_test)
mse = mean_squared_error(y_test, y_preds)
rmse = np.sqrt(mse)

[결과]

MSE : 17.297, RSME : 4.159
Variance score : 0.757


#절편 값과 각 회귀 계수의 값

절편 값 :  40.995595172164336
회귀 계수 값 :  [ -0.1   0.1   0.    3.  -19.8   3.4   0.   -1.7   0.4  -0.   -0.9   0. -0.6]
  • 회귀 계수의 값을 순서대로 피처를 나열
RM          3.4
CHAS        3.0
RAD         0.4
ZN          0.1
B           0.0
TAX        -0.0
AGE         0.0
INDUS       0.0
CRIM       -0.1
LSTAT      -0.6
PTRATIO    -0.9
DIS        -1.7
NOX       -19.8



다항 회귀(Polynomial Regression)

  • 독립변수가 단항식이 아닌, 2,3차 방정식과 같은 다항식으로 표현 되는 것.
  • 단순 선형 회귀보다 예측 성능이 높다.
  • 하지만 차수가 너무 높아지게 되면 학습 데이터에만 맞춘 학습이 이루어진다.(과적합)



과적합과 과소적합의 예시

  • 원래 데이터 세트는 피처 X 와 target y가 약간의 잡음이 포함된 다항식의 코사인 그래프 관계이다.
  • 이를 다항 회귀의 차수를 변화시키며 예측곡선의 모양과 정확도를 비교한다.
  • 먼저 조건에 맞는 학습 데이터를 생성한다.


[코드]

X는 0부터 1까지 30개의 임의의 값을 순서대로 샘플링.
y는 코사인 기반의 true_fun()에서 약간의 노이즈를 포함한 값.
(약간의 노이즈 –> np.random.randn(n_samples) * 0.1)

def true_fun(X):
    return np.cos(1.5 * np.pi * X)

np.random.seed(0)
n_samples = 30
X = np.sort(np.random.rand(n_samples))

y = true_fun(X) + np.random.randn(n_samples) * 0.1
  • 차수 1, 4, 15 로 변화시키면서 다항회귀 비교


[코드]

개별 차수별로 polynomial로 변환한다.(Pipeline 이용)
교차 검증으로 다항회귀를 평가
테스트 데이터를 0 부터 1까지 만든다.(linspace이용)
테스트 데이터에 회귀 예측을 수행하고 예측 곡선과 실제곡선을 비교한다.

for i in range(len(degrees)):
    ax = plt.subplot(1, len(degrees), i + 1)
    plt.setp(ax, xticks=(), yticks=())
    
    polynomial_features = PolynomialFeatures(degree = degrees[i], include_bias = False)
    linear_regression = LinearRegression()
    pipeline = Pipeline([('poly', polynomial_features), ('linear', linear_regression)])
    pipeline.fit(X.reshape(-1,1), y)
    
    
    scores = cross_val_score(pipeline, X.reshape(-1,1), y, scoring='neg_mean_squared_error', cv= 10)
    
    coefficients = pipeline.named_steps['linear'].coef_
    print('\n Degree {} 회귀 계수는 {} 입니다.'.format(degrees[i], np.round(coefficients, 2)))
    print('Degree {} MSE는 {} 입니다.'.format(degrees[i], -1*np.mean(scores)))
    
    
    X_test = np.linspace(0,1,100)
    plt.plot(X_test, pipeline.predict(X_test[:,np.newaxis]), label = "Model")
    plt.plot(X_test, true_fun(X_test), '--', label='True function')
    plt.scatter(X,y, edgecolor = 'b', s=20, label = "Samples")

[결과]

Degree 1 회귀 계수는 [-1.61] 입니다.
Degree 1 MSE는 0.40772896250986834 입니다.

Degree 4 회귀 계수는 [  0.47 -17.79  23.59  -7.26] 입니다.
Degree 4 MSE는 0.04320874987231747 입니다.

Degree 15 회귀 계수는 [-2.98295000e+03  1.03899930e+05 -1.87417069e+06  2.03717225e+07
 -1.44873988e+08  7.09318780e+08 -2.47066977e+09  6.24564048e+09
 -1.15677067e+10  1.56895696e+10 -1.54006776e+10  1.06457788e+10
 -4.91379977e+09  1.35920330e+09 -1.70381654e+08] 입니다.
Degree 15 MSE는 182815433.47648773 입니다


  • 차수가 1일 때는 단순 선형 회귀랑 같기 때문에, 예측 곡선이 학습 데이터의 패턴을 반영하지 못했다.
  • 따라서 과소적합 모델이다.


  • 차수가 4일 때는 실제 데이터 세트와 예측곡선이 유사한 모습을 보인다. 사소한 잡음을 제대로 예측하지는 못했지만, 잘 예측한 곡선이다.


  • 차수가 15일 때는 MSE의 값과 예측 곡선 둘 다 말도 안되는 모습을 보인다.
  • 예측 곡선은 잡음을 지나치게 반영하여, 학습 데이터에만 치중된 모습을 보인다.
  • 따라서 과적합 모델이다.



편향 - 분산 트레이드 오프 (Bias-Variance Trade Off)

  • 앞선 데이터에서 차수가 1일때의 모델은 고편향(high bias)성을 가진다.(과소적합)
  • 또 차수가 15일때의 모델은 고분산(high variance)성을 가진다.(과적합)
  • 따라서 편향과 분산이 서로 트레이드 오프를 이루면서 오류 비용이 최대로 낮아지는 모델을 구축하는 것이 효율적이다.