BLOG
인공지능

로지스틱 회귀(Logistic Regression) (2) 모델을 평가하고 규제를 통해 성능 높이기


Jan. 18, 2022, 10:37 p.m.



이전 포스트에서 로지스틱 회귀 모델에 대해서 알아보고 사이킷런을 이용해서 훈련 데이터를 받아와 로지스틱 회귀 모델을 훈련하는 것 까지 알아 보았습니다. 이제부터는 이 훈련된 모델을 테스트셋으로 테스트 해보며 여러 규제들을 통해 모델의 성능을 높여보도록 하겠습니다.

1. 모델 평가하는 이유


모델을 평가하는 이유는 이 모델이 훈련 데이터셋에서만 적용 되는지, 다른 데이터 셋에서도 잘 적용이 되는지 확인할 필요가 있기 때문입니다.

훈련 데이터 셋에서는 매우 높은 정확도를 보였지만 다른 데이터 셋을 입력하면 낮은 성능을 보일 수 있습니다.

이런 경우 이 모델은 훈련 데이터셋에 과대 적합 되었다고 말합니다. 즉, 훈련 데이터셋의 큰 그림을 보고 추세를 예측해야하는데 그 수준을 넘어 지엽적으로 훈련 데이터셋을 그대로 따라하는 모델이 만들어 지는 것이죠.

그렇기 때문에 훈련 데이터셋이 아닌 다른 테스트셋을 입력하게 되면 정확도가 낮아지는 것입니다.

그렇기 때문에 다양한 방법을 시도하여 모델이 과대적합 되는 것을 막아야 합니다. 모델을 학습하는데 있어서 비용함수를 바꾸거나, 모델을 평가하는 방법, 여러가지 파라미터들을 바꾸어가면서 말이죠. 이를 하이퍼파라미터 튜닝이라고 합니다.

2. 로지스틱 회귀 모델 평가하기


훈련이 완료된 모델은 다양한 방법으로 평가할 수 있습니다. 이번에는 제일 쉬운 방법인 정확도를 기반으로 모델을 평가하겠습니다. 예측을 많이 맞출수록 정확도가 높고 성능이 좋은 모델이 되는 것입니다. 정확도 외에도 F1 Score, 크로스 엔트로피등 다양한 방법들이 있답니다.

평가하는 방법은 사이킷런에 다 구현이 되어 있습니다. 사이킷런을 통해서 정확도를 평가해볼까요? 바로 이전 포스트에서 로지스틱 회귀 모델을 lr로 선언하고 lr.fit()함수를 통해 학습을 진행했습니다. 정확도는 score() 함수로 바로 구할 수 있습니다.

lr.score(X_test_std, y_test)

1.0 이와 같이 소수점으로 정확도가 나올 것입니다. 100% 예측을 하는 모델이네요! 그 이유는 학습하는데 사용했던 학습 데이터가 이진 분류가 가능한 아주 간단한 데이터이기 때문입니다.

조금 더 복잡한 데이터를 훈련한다면 어떻게 될까요?

또 하나의 유명한 데이터인 와인 데이터셋을 가져와보도록 하겠습니다. 와인에 들어있는 화학 성분을 보고 무슨 와인인지를 예측하는 모델을 만들어야 합니다.

df_wine = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',header=None)

데이터를 가져왔습니다.

이 와인 테스트 셋은 아래와 같이 13개의 화학 성분 정보와 와인 정보를 숫자로 담고 있습니다.

     0      1     2     3     4    5   ...    8     9      10    11    12    13
0     1  14.23  1.71  2.43  15.6  127  ...  0.28  2.29   5.64  1.04  3.92  1065
1     1  13.20  1.78  2.14  11.2  100  ...  0.26  1.28   4.38  1.05  3.40  1050
2     1  13.16  2.36  2.67  18.6  101  ...  0.30  2.81   5.68  1.03  3.17  1185
3     1  14.37  1.95  2.50  16.8  113  ...  0.24  2.18   7.80  0.86  3.45  1480
4     1  13.24  2.59  2.87  21.0  118  ...  0.39  1.82   4.32  1.04  2.93   735
..   ..    ...   ...   ...   ...  ...  ...   ...   ...    ...   ...   ...   ...
173   3  13.71  5.65  2.45  20.5   95  ...  0.52  1.06   7.70  0.64  1.74   740
174   3  13.40  3.91  2.48  23.0  102  ...  0.43  1.41   7.30  0.70  1.56   750
175   3  13.27  4.28  2.26  20.0  120  ...  0.43  1.35  10.20  0.59  1.56   835
176   3  13.17  2.59  2.37  20.0  120  ...  0.53  1.46   9.30  0.60  1.62   840
177   3  14.13  4.10  2.74  24.5   96  ...  0.56  1.35   9.20  0.61  1.60   560
from sklearn.model_selection import train_test_split
X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=0)

from sklearn.preprocessing import StandardScaler as SC
sc = SC()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.transform(X_test)

훈련 셋과 테스트 셋으로 나누고 표준화를 진행했습니다.

모델을 훈련해보겠습니다.

lrr = LogisticRegression(solver='liblinear', multi_class='auto', random_state=1)

lrr.fit(X_train, y_train)

원래 로지스틱 회귀는 이진 분류 모델이라고 했었는데 와인의 종류는 3개입니다. 이를 어떻게 처리할까요? 바로 OvR이라는 방법을 사용합니다. 모델을 여러가지를 사용하는 것입니다. 와인의 종류는 3개이므로 1번 와인과 1번와인이 아닌 것을 분류하는 모델 1개, 2번 와인과 2번와인이 아닌것을 분류하는 모델 1개, 3번 와인과 3번 와인이 아닌것을 분류하는 모델 1개, 총 3개의 모델을 훈련하여 이중에서 가장 높은 확률이 나오는 값을 예측 값으로 사용하는 방식입니다.

사이킷런에서는 단순히 multi_class='auto'를 통해 간단히 멀티 클래스 분류를 할 수 있습니다.

훈련이 잘 되었는지 테스트 셋을 통해 정확도 테스트를 해볼까요?

lrr.score(X_test, y_test)

0.9444444 로 나왔네요. 높지만 매우 정확하다고 볼 수는 없겠네요. 정확도를 더 높일 수 있는 방법이 있을까요?

3. 규제로 과대적합 피하기


바로 '규제' 라는 방법을 이용합니다.

일반적으로 모델이 훈련 데이터에 과대적합이 될 수록 모델이 복잡해져 분산이 커져 훈련 데이터가 아닌 다른 데이터를 넣었을 때 예측의 일관성이 떨어집니다. 반대로 과소적합이 될 수록 분산은 적어져서 일관성은 높아지지만 편향이 커져서 예측의 정확도는 낮아지죠. 이를 분산-편향 상관관계(Tradeoff)라고 합니다.

규제는 과도하게 모델이 복잡해지는 것을 방지하기 위해 가중치의 값이 커지지 않도록 하여 편향이 높아지게 해 예측의 정확도는 살짝 낮아질 수도 있지만 다른 데이터에 대해서도 일관적인 예측을 가능하게 합니다.

그렇다면 과연 어떻게 가중치의 값이 커지지 않도록 규제할까요?

방법은 비용함수에 가중치항을 추가하는 것에 있습니다. 이전에 알려드렸던 로지스틱 회귀의 비용함수에 가중치의 제곱의 합을 더합니다. 모델이 학습된다는 것은 비용함수를 최소로 만드는 것을 말한다고 했죠? 그렇기 때문에 가중치의 값들도 커지지 않게 됩니다. 그리고 이를 L2 규제라고 합니다.

규제 항을 더한 비용함수는 아래와 같습니다.

의 값을 조절해가면서 규제의 정도를 조절합니다. 이를 조절해가면서 가장 좋은 성능을 내는 모델을 찾으면 되는것입니다. 가 이 모델에서의 하이퍼파라미터이고 이를 튜닝하는 것이라고 볼 수 있습니다.

사이킷런에서는 어떻게 사용할까요? 여기서는 의 역수인 상수 C를 조절합니다. 즉 상수 C가 줄어들 수록 규제의 정도는 커진다고 보면 됩니다.

lrr = LogisticRegression(solver='liblinear', multi_class='auto', C=0.1, random_state=1)

lrr.fit(X_train, y_train)

lrr.score(X_test, y_test)

모델을 선언할때 상수 C가 추가된 모습을 볼 수 있습니다. C값을 바꾸어가면서 테스트를 해본 결과 저는 0.1로 두었을 때 0.96의 정확도를 얻었습니다. 미세한 차이지만 성능이 늘어났다는 것에서 큰 의의가 있죠? 다른 더 복잡한 데이터들을 다룰 때는 더욱 유의미한 차이를 볼 수 있답니다.

로지스틱 회귀가 아닌 다른 모델들은 규제 외에도 더욱 많은 하이퍼파라미터들이 존재하고 여러가지 전처리 모델과 분류모델을 연결하여 더욱 복잡하게 만들 수도 있습니다. 그리고 똑같이 하이퍼파라미터 튜닝을 통해 성능을 높입니다.

앞으로 더 다양한 모델과 튜닝 방법에 대해서 알아보도록 하겠습니다.

사이킷런 scikit-learn 로지스틱회귀



Search