[IMLP] Chapter 2. 지도 학습 (3) - 지도학습 알고리즘 (2): 선형 모델
연구에 대한 아이디어를 좀 얻게 된 챕터. 나중에 추가확인이 더 필요할듯해서 해시태그 #추가확인 도 달아놨음!
[선형 모델]
#. 선형 회귀(최소 제곱법]
- 선형 회귀(linear regression)혹은 최소제곱법 (OLS, ordinary least square)
- 예측과 훈련 세트에 있는 타깃 y 사이의 평균제곱오차를 최소화하는 파라미터 w와 b를 찾음
- 평균제곱오차는 예측값과 타깃값의 차이를 제곱하여 더한 후에 샘플의 개수로 나눈 것
- 기울기 파라미터(w)는 가중치(weight)혹은 계수(coefficient)라고 하며 lr(linear regression) 객체의 coef_ 속성에 저장되어 있음
- 편향(offset) 또는 절편(intercept) 파라미터(b)는 intercept_속성에 저장되어 있음
#. 릿지(Ridge) 회귀
- 회귀를 위한 선형 모델
- 가중치(w)선택은 훈련 데이터를 잘 예측하기 위해서 뿐만 아니라 추가 제약 조건을 만족시키기 ㅜ이ㅏㅎㄴ 목적
- 가중치의 절댓값을 가능한 한 작게 만드는 것 -> 규제(regularization)
- 규제란, 과대적합이 되지 않도록 모델을 강제로 제한
- 릿지 회귀에서 사용하는 규제 방식을 L2 규제라고 함
from sklearn.linear_model import Ridge
ridge = Ridge().fit(X_train,y_train)
- 덜 자유로운 모델.. 모델을 단순하게 해주고 훈련 세트에 대한 성능 사이를 절충할 수 있는 방법 제공
- alpha 매개변수로 훈련 세트의 성능 대비 모델을 얼마나 단순화할지 지정할 수 있음 (default값은 1.0)
- alpha 값을 높이면 계수를 0에 더 가깝게 만들어서 훈련 세트의 성능으 나빠지지만 일반화에 도움 줄 수 있음
==> [추가 확인]
- 선형 회귀로 분류는 할 수 있음! (뒤에서 다시 확인..)
- Ridge 회귀를 EEG oddball패러다임 데이터에도 적용해보려고 했는데, 내가 원하는 predict_proba 는 계산할 수 없음 (ㅠㅠ)
- RidgeClassifier가 존재하지만 이것도 probability는 계산할 수 없음.. target:nontarget 비율이 1:3라 target일 probability 중 가장 큰 probability를 뽑아내야 하는 내 데이터에는 적용 불가능
- 하지만! 이 글 참고해서 확인해서 시도해볼만 한듯!
>>> from sklearn.datasets import load_breast_cancer
>>> from sklearn.linear_model import RidgeClassifier
>>> X, y = load_breast_cancer(return_X_y=True)
>>> clf = RidgeClassifier().fit(X, y)
>>> clf.score(X, y)
0.9595...
#. 라쏘 (Lasso)
- 선형 회귀에 규제를 적용하는 데 Ridge의 대안으로 Lasso가 있음
- 릿지 회귀에서와 같이 라쏘도 계수를 0에 가깝게 만드려고 함
- L1 규제 (cf. 릿지에서는 L2): L1 규제 결과로 라쏘 사용할 때 어떤 계수가 실제로 0 이 되기도 하는데 완전히 제외되는 특성이 생긴다는 뜻.. 어떻게 보면 특성 선택이 자동으로 이뤄진다고 볼 수 있음
==> [추가확인 1]
==> [궁금증 1] 그럼 target-nontarget 구분이 잘 안 되는 내 데이터에 적용하면..? 하지만 문제는 lasso도 output 중 predict_proba을 지원하지 않음.. https://stackoverflow.com/questions/47995738/sklearn-predict-proba-equivalents 가 도움이 될 수도 ?
(추가) 다음 내용 확인해보니 기본적으로 많이 썼던 SVM에서는 L2규제를 기본적으로 사용함
==> [궁금증 2] 그렇다면 Lasso가 matlab으로도 전혀 구현 불가능한가? 하고 확인하던 중 "regularization"의 파라미터로 설정 가능하다는 내용을 봐서... "regularization lasso"에 대해 더 확인하게 됨
from sklearn.linear_model import Lasso
lasso = Lasso().fit(X_train,y_train)
#. 사용한 특성의 수 확인
print("사용한 특성의 수: {}".format(np.sum(lasso.coef_ != 0)))
- 릿지와 마찬가지로 alpha 매개변수 지원: 과소적합 줄이기 위해 alpha 값 줄여볼 수 있음.. 하지만! max_iter (반복 실행하는 최대 횟수)의 기본값을 늘려야 함
lasso001 = Lasso(alpha=0.01, max_iters = 100000).fit(X_train,y_train)
- alpha 값 낮추면 모델의 복잡도 증가할 수 있음
- scikit-learn은 Lasso와 Ridge의 페널티를 결합한 ElasticNet도 제공함!
#. 분류용 선형 모델
- 함수에서 계산한 값이 0보다 작으면 클래스를 -1, 0보다 크면 +1이라고 예측함
- 결정 경계가 입력의 선형 함수
- 예시: linear_model.LogisticRegression에 구현된 로지스틱 회귀 그리고 svm.LinearSVC에 구현된 선형 서포트 벡터 머신 .. 두 모델 모두 기본적으로 L2 규제 사용함
<Logistic Regression 과 SVM>
!!!!! 로지스틱 회귀 이름에 "회귀"가 들어가지만 회귀 알고리즘이 아니라 분류알고리즘이므로 linear regression과 혼동하면 안됨
- 기본적으로 L2 규제 사용
- 규제의 강도를 결정하는 매개변수는 C: C의 값이 높아지면 규젝 감소함
- 매개변수로 높은 C값을 지정하면 훈련 세트에 가능한 최대한 맞추려 하고, C값을 낮추면 모델은 계수 벡터(w)가 0에 가까워지도록 만듬
- C의 값이 낮아지면 데이터 포인트 중 다수에 맞추려 하고, C의 값을 높이면 개개의 데이터 포인트를 정확히 분류하려고 함
- 고차원에서는 분류에 대한 선형 모델이 강력해지며 특성이 많아지면 과대적합되지 않도록 하는 것이 매우 중요함
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=42)
logreg = LogisticRegression().fit(X_train,y_train)
- 이해가 쉬운 모델을 원한다면 L1 규제를 사용하는 것이 좋음
lr_l1 = LogisticRegression(C=1, penalty="l1").fit(X_train,y_train)
!!! [추가 확인] 하지만, 실제로 확인해보니 아래와 같은 에러가 떴고,
자세히 찾아보니 default로 설정되는 lbfgs는 l2, none만 지원
그래서 다시 수정해봄! 'saga' 로 한 이유는 왜냐면 elasticnet도 시도해보고 싶어서..
lr_l1 = LogisticRegression(C = 1, penalty="l1",solver="saga").fit(X_train,y_train)
lr_l1.predict_proba(X_test)
내 EEG 데이터에 넣어보니.. "The max_iter was reached which means the coef_ did not converge" 라는 에러가 떴음
이 에러가 잘 이해가 안돼서.. (하지만 희소식은 정확도 상승!) max_iter = 100,1000 넣어봤는데 여전히 같은 에러.
찾아보니 이런 문구가 있어서 max_iter를 확 10000으로 늘려보니 에러가 더이상 뜨지 않았음. 하지만 정확도는 낮아져!
이런 내용도 확인함!
[다중 클래스 분류용 선형 모델]
- 많은 선형 분류 모델은 이진 분류만을 지원함
- 이진 분류 알고리즘을 다중 클래스 분류 알고리즘으로 확장하는 보편적인 기법은 일대다 방법
- 각 클래스를 다른 모든 클래스와 구분하도록 이진 분류 모델을 학습시켜 클래스 수만큼 이진 분류 모델이 만들어짐
[장단점과 매개 변수]
- 선형 모델은 샘플에 비해 특성이 많을 때 잘 작동함
==> [궁금증 3]: Linear SVC에 norm1으로 EEG 데이터 적용.. 하지만 linearSVC에도 마찬가지로 predict_proba 기능이 없었는데.. 다음 글 찾고 CalibratedClassifierCV() 적용해봄! 위에 정리했던대로 LASSO 사용할때도 쓰면 될 듯
!! 메서드 연결
- 모든 scikit-learn의 fit 메서드는 self를 반환 (self는 호출된 메서드를 저의한 객체 자신을 나타냄)
logreg = LogisticRegression().fit(X_train,y_train)
- 위에서 fit 메서드의 반환값(self)은 학습된 모델로, 변수 logreg에 할당함..
- 메서드 호출을 잇는 것 (여기서는 __init__와 fit)을 메서드 연결(method chaining)이라고 함