[핸즈온 머신러닝] 4강 모델학습 2편

2018. 7. 15. 04:54Python-이론/python-인공지능2

4.5 규제가 있는 선형 모델 


우리는 과대적합을 하기 위해 좋은 방법은 좋은 모델을 규제하는 것 입니다. 자유도를 줄이면 과대적합되기 더 어려워집니다. 예를 들어 다항회귀에서는 차수를 줄임으로써 모델을 규제할 수 있습니다. 이제 부터 각기 다른 규제 방법에 대해 알아 봅시다. 


4.5.1 릿지 회귀 


릿지 회귀는 규제가 추가된 선형 회귀 버전입니다. 따라서 일반 비용함수 MSE에다가 규제항

 

을 더해주어야 합니다. 


규제항은 훈련되는 동안에만 비용함수에 추가됩니다. 훈련이 끝나면 모델의 성능을 규제가 없는 성능 지표로 평가합니다. 


파라미터 alpha는 얼마나 규제를 할지 조절합니다. alpha = 0이면 선형회귀와 같고 아주 크면 거의 0에 가까워 집니다. 


릿지 회귀 비용함수 



선형 회귀와 마찬가지로 릿지 회귀를 계산하기 위해 정규 방정식을 사용할 수 도 있고 경사하강법을 사용할 수 도 있습니다. 




1. 정규방정식 활용 

from sklearn.linear_model import Ridge 

ridge_reg = Ridge(alpha=1, solver="cholesky")#쇼레스키 분해 용법 사용


ridge_reg.fit(X, Y)
ridge_reg.predict([[1.5]])


2. 확률적 경사 하강법

sdg_reg = SGDRegressor(max_iter=5, penalty="l2") #페널티에 l2 norm 사용
sgd_reg.fit(X, Y.ravel())
sgd_reg.predict([[1.5]])



라쏘회귀 


라쏘회귀는 선형회귀의 또 다른 규제된 버전입니다. 라쏘회귀는 릿지 회귀와 달리 l2 노름의 제곱을 2로 나눈 것 대신 가중치 l1 노름을 사용합니다. 


라쏘 회귀의 종요한 특징은 덜 중요한 특성의 가중치를 완전히 제거하려는 점입니다. 다시 말해 자동으로 특성을 선택하고 희소 모델을 만듭니다. 



from sklearn.linear_model import Lasso 
lasso_reg = Lasso(alpha=0.1)
lasso_reg.fit(X, Y)
lasso_reg.predict([[1.5]])

라쏘도 레지와 같이 정규 방정식이나 경사하강법에 적용할 수 있습니다.  SGDRegressor에 penalty에="l1"으로 적용해도 같습니다. 



4.5.3 엘라스틱넷 


엘라스틱 넷은 리지 회귀와 라쏘 회귀를 절충한 모델입니다. 규제항은 릿지와 회귀의 규제항을 단순히 더해서 사용하며 혼합 정도는 r로 비율을 결정합니다. r = 0 이면 리지 회귀와 같고 r =1 이면 라쏘 회귀와 같습니다. 


규제가 약간 있는 것이 대부분의 경우에 좋으므로 일반적으로 평범한 선형 회귀는 피해야합니다. 

실제로 쓰이는 특성이 몇 개뿐이라고 의심되면 라쏘나 엘라스틱 넷이 좋습니다. 

특성 수가 훈련 샘플 수보다 많거나 특성 몇 개가 강하게 연관 되어 있을 때는 보통 라쏘 문제를 일으키므로 라쏘보다는 엘라스틱을 선호합니다. 


from sklearn.linear_model import ElasticNet
elastic_net = ElasticNet(alpha=0.1, l1_ratio=0.5)
elastic_net.fit(X,Y)
elastic_net.predict([[1.5]])


4.5.4 조기 종료


경사하강법과 같은 반복적인 학습알고리즘을 규제하는 아주 색다른 방식은 검증 에러가 최솟 값에 도달하면 바로 훈련을 중지시키는 것 입니다. 이를 조기 종료라고 합니다. 계속 적으로 멈추지 않고 계속 훈련을 하다보면 전역 최솟값에 도착하고도 계속해서 상승하는 경우가 있습니다.  과대적합이 시작 된 것 입니다.  이 방법은 간단하고 매우 효율적입니다. 이를 훌륭한 공짜 점심이라고 도 불립니다. 


코드 

from sklearn.base import clone
from sklearn.preprocessing import StandardScaler
poly_scaler = Pipeline([
("poly_features", PolynomialFeatures(degree=90, include_bias=False)),
("std_scaler", StandardScaler())
])

X_train_poly_scaled = poly_scaler.fit_transform(X)
X_val_poly_scaled = poly_scaler.fit_transform(X_val)

sgd_reg = SGDRegressor(n_iter=1, warm_start=True, penalty=None,
learning_rate="constant", eta0=0.0005)
minimum_val_error = float("inf")#무한대
best_epoch = None
best_model = None

for epoch in range(1000):
sgd_reg.fit(X_train_poly_scaled, y_predict)
y_val_predict = sgd_reg.predict(X_val_poly_scaled)
val_error = mean_squared_error(y_predict, y_val_predict)
if val_error <minimum_val_error:
minimum_val_error = val_error
best_epoch =epoch
best_model = clone(sgd_reg)

warm_start=True이면 fit 메서드가 호출될 때 처음부터 다시시작하지 않고 이전 모델 파라미터에서 이어갑니다.

clone 모델만 복사해준다. 



4.6 로지스틱 회귀 


로지스틱회귀는 어떤 데이터가 특정 클래스에 속할 확률을 추정하는 데 널리 쓰입니다. 보통은 50%가 넘으면 속한다고 생각하고 넘지 않으면 속하지 않는다고 생각합니다. 


4.6.1 확률 추정


선형 회귀 모델과 같이 입력특성의 가중치의 합을 계산합니다. 대신 결과를 바로 출력하지 않고 로지스틱을 출력합니다. 


로지스틱은 0과 1사이의 값을 출력하는 시그모이드 함수 입니다. 


양성 클래스일 확률이 50%가 넘으면 양성이고 50% 적으면 음성이라고 예측합니다. 


4.6.2 훈련과 비용 함수 


이제 로지스틱 회귀 모델은 어떻게 훈련 시킬까요? 양성 샘플에 대해서는 높은 확률을 추정하고 음성 샘플에 대해서는 낮은 확률을 추정하는 벡터 theta값을 찾는 것 입니다. 


한개의 데이터에 대해서 비용함수 

y = 1일 때 0.5이하로 잘못 판단 해버리면 음성이 되기 때문에 비용함수에 넣어보면 값이 0에 가까워질 수 록 커짐을 알 수 있다. 

y = 0일 때 0.5 이상으로 잘못 판단 하면 양성이 되기 때문에 비용함수에 넣어보면 1에 가까워질 수 록 값이 커진다. 

이를 로그 손실이라고 부른다. 

최솟 값을 구해주는 식은 없지만 경사하강법을 통해서 전역최소값을 구할 수 있습니다. 

위와 같이 편도함수를 만들 수 있습니다. 경사하강법 때 봤던 편도함수와 모양이 비슷합니다. 


4.6.3 결정 경계 


로지스틱 회귀를 설명하기 위해 붓꽃 데이터셋을 사용하겠습니다. 


붓꽃 데이터 불러오기 


from sklearn import datasets
iris = datasets.load_iris()
list(iris.keys())
X = iris["data"][:, 3:]
y = (iris["target"] == 2).astype(np.int) #배열을 복사후 int타입으로 바꾸어 반환해준다.


Iris-Verginica인지 아닌지 구분하기



from sklearn.linear_model import LogisticRegression

log_reg = LogisticRegression()
log_reg.fit(X, y)

로지스틱 회기를 훈련시키고 있다.


X_new = np.linspace(0, 3, 1000).reshape(-1, 1)#0출발점  3 도착점 3 1000 분해해서  
y_proba = log_reg.predict_proba(X_new)
plt.plot(X_new, y_proba[:, 1], "g-", label="Iris-Virginica")
plt.plot(X_new, y_proba[:, 0], "b--", label="not Iris-Virginica")
plt.legend(loc='upper right')
plt.show()

위의 그래프는 iris_virginica인지 꽃의 너비를 기준으로 판단해줍니다. Iris-Verginica는 꽃의 너비는 1.4cm에서 2.5cm정도 합니다. 반단 다른 붓꽃들은 일반적으로 꽃잎 너비가 더 작아 0.1~1.8cm에 분포합니다. 따라서 조금 겹치는 부분이 있습니다. 이그래프에서는 1.6cm 이상이되면 iris Virginica이고 그것 보다 적으면 아닙니다. 2.0이상 부터는 확실히 맞다고 생각하고 1cm 아래이면 확실히 아니라고 생각하는 것 같습니다. 

log_reg.predict([[1.5], [1.7]])

0, 1이 출력됩니다. 


이번 예제를 통해서 우리는 새롭게 들어 오는 데이터를 iris_Virginica인지 아닌지 구분해줍니다. 그리고 서로가 교차되는지점을 결정경계라고합니다. 이경계는 선형입니다. 



4.6.4 소프트맥스 회귀


로지스틕 회귀는 여러 개의 이진 분류기을 훈련시켜 연결하지 않고 직접 다중 클래스를 지원하도록 일반화 되어 있습니다. 각 클래스는 자기만의 하이퍼파리미터를 갖고 있습니다. 


여러개의 pk값 중에 가장높은 클래스를 선택합니다. (argmax이용하면 좋음 가장 높은 클래스의 인덱스를 반환합니다.)


이모델은 알맞은 클래스에 높은 확률을 추정하게 만들어주고 다른 클래스에 낮은 확률을 부여하는 것이 주목표입니다. 크로스 엔트로피 비용 함수를 최소화 하는 것은 낮은 확률의 클래스를 예측하는 모델을 억제하므로 이목적에 부합합니다. 


이제부터 소프트맥스 회귀를 직접 훈련시켜보고 예측해보겠습니다. 


   소프트 맥스 회귀를 사용해 붓꽃을 세 개의 클래스로 분류하겠습니다. 사이킷런의 Logistic Regression은 다중클래스를 예측할 때는 AOA(1 대 다)방법을 사용합니다. 하지만 multi_class 파라미터를 multinomial로 바꾸면 softmax로 바꿀 수 있습니다. 그리고 solver 매개변수에 lbfgs와 같이 소프트 맥스 회귀를 지원하는 알고리즘을 선택해야합니다

X = iris["data"][:, (2, 3)]
Y = iris["target"]
softmax_reg = LogisticRegression(multi_class="multinomial", solver="lbfgs", C=10)
softmax_reg.fit(X, Y)

BFGS 알고리즘은 연구자들의 이름을 따서 만든 의사 뉴턴 메소드이다. LBFGS는 BFGS 알고리즘을 제한된 메모리 공간에서 구현한 것으로 머신러닝 분야에서 널리 사용됩니다. 또한 newton-cg와 확률적 경사하강법인 sag가 multimomial 매개변수를 지원합니다.  



꽃잎의 길이가 5cm, 너비가 2cm인 붓꽃을 발견했다고 가정하고 이 붓꽃의 품종이 무엇인지 알아보겠습니다. 

softmax_reg.predict([[5, 2]]) [2] 반환 2번째 인덱스의 값이 가장 높은 확률이라는 의미



지금까지 다양한 방법의 모델훈련에 대해 알아보았습니다. 뭐 선형회귀 부터, 경사하강법, 모델에 파라미터를 규제해서 더강력한 모델을 만들 수 있었는 시간이었습니다.