사이킷런의 와인 분류 데이터셋을 사용하여 로지스틱 회귀 분석을 한다.


1. 라이브러리 및 데이터 로드

# 필요한 라이브러리
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

import pandas as pd  

# 필요한 데이터
wine_data = load_wine()


2. 데이터 정보 확인하기

# 데이터 셋 정보 확인
print(wine_data.DESCR)

📍 위 코드에 대한 출력 결과(일부만 가져옴)

데이터셋의 설명 및 피처 설명


3. 입력변수, 출력변수 지정

# 입력 변수를 dataframe으로 변환하여 저장
x = pd.DataFrame(wine_data.data, columns=wine_data.feature_names)

# 출력 변수를 dataframe으로 변환하여 저장
y = pd.DataFrame(wine_data.target, columns=['class'])

📍 입력변수와 출력변수의 head 출력 결과

입력 변수(왼쪽), 출력 변수(오른쪽)


4. 학습, 테스트 데이터 나누기

# 학습, 테스트용 데이터셋 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)

학습 데이터셋은 80%, 테스트 데이터셋은 20%로 데이터를 나누고 random_state를 42로 설정하여 데이터 분배 결과를 고정할 수 있도록 한다.

# 잘 나누어졌는지 shape로 확인
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)
출력 결과
(142, 13) (36, 13) (142, 1) (36, 1)


3. 모델링 및 평가

# 로지스틱 회귀 함수 사용
model = LogisticRegression(solver='saga', max_iter=1000)

# 학습 데이터로 모델 학습
model.fit(x_train, y_train)

# 학습이 완료된 모델에 테스트 데이터를 입력하여 y값을 예측
y_predict = model.predict(x_test)

# 분류가 잘 이루어졌는지 평가
model.score(x_test, y_test)
max_iter를 1000으로 설정했을 때의 성능
0.8611111111111112

출력할 클래스가 3개라는 점에서 다항 로지스틱 회귀에 맞는 솔버인 ‘saga’를 선택하고 최적화를 찾기 위해 과정을 몇번을 반복할 것인가(max_iter)는 1000으로 설정하여 모델을 만들어보았다. 모델 결과 성능이 약 86% 정도가 나왔는데, 이는 10개 중 8.6개가 정답으로 맞춘다는 뜻이다.


4. 반복 횟수 조정

max_iter 값을 조정하였을 때 성능을 높일 수 있는지 확인하기 위해 max_iter 값을 이전의 2배로 설정하여 모델을 만들어보았다.

# max_iter 를 2000으로 설정한 모델
model2 = LogisticRegression(solver='saga', max_iter=2000)

# 학습 데이터로 모델 학습
model2.fit(x_train, y_train)

# 학습이 완료된 모델에 테스트 데이터를 입력하여 y값을 예측
y_predict = model2.predict(x_test)

# 분류가 잘 이루어졌는지 평가
model2.score(x_test, y_test)
max_iter를 2000으로 설정했을 때의 성능
0.8888888888888888

max_iter를 2배로 설정(1000 -> 2000)하니 성능이 약 89%로 이전 대비 성능이 3%가 올랐다. max_iter 값을 5000으로 설정한 결과도 확인해보니 성능이 100%가 나왔다. 사이킷런에서 로지스틱 회귀 모델을 만들 때, max_iter 값을 높게 설정해도 그 전에 최적화가 이루어지면 과정을 stop 하도록 설계했다고 한다.


5. 결과 해석

(1) 클래스별 확률

.predict()를 사용하면 입력변수에 대한 결과를 예측한 값을 확인할 수 있고 .predict_proba()를 사용하면 입력변수에 대한 결과를 클래스별 확률값으로 확인할 수 있다.

predict 결과(왼쪽), predict_proba 결과(오른쪽)


첫 번째 입력변수에 대해 예측된 결과를 보면, predict 결과 0으로 예측하였다. predict_proba 결과를 보면서 해석해 보면 리스트 내의 세가지 값(class 0일 확률, class 1일 확률, class 2일 확률)들 중 0번째 요소가 제일 큰 값을 가진다. 즉 다른 클래스들일 확률들과 비교했을 때 0일 확률이 가장 크기 때문에 0으로 예측하는 것이다.

(2) 피처들의 계수

.coef_를 사용하면 모델로부터 어떤 feature가 결과에 큰 영향을 주는지 확인할 수 있다. class 별로 어떤 피처에 크게 영향을 받았는지 결과는 아래와 같다.

model.coef_
출력 결과
array([[-0.01878431, -0.00677701, -0.00294959, -0.06715177, -0.04582759,
         0.00248559,  0.00965551, -0.00169579,  0.00160013, -0.01425674,
        -0.00055358,  0.00368465,  0.00816883],
       [ 0.00966877, -0.01763132,  0.0004303 ,  0.03637297,  0.03785306,
         0.0104504 ,  0.01808975, -0.00023449,  0.00866373, -0.05555264,
         0.00738715,  0.0199435 , -0.00607386],
       [ 0.00911553,  0.02440833,  0.00251929,  0.0307788 ,  0.00797453,
        -0.01293599, -0.02774526,  0.00193028, -0.01026386,  0.06980938,
        -0.00683356, -0.02362815, -0.00209496]])
  • 첫 번째 클래스는 -0.06715177472030232 값을 가지는 alcalinity_of_ash 변수에 가장 영향을 많이 받았다는 것을 알 수 있다.
    • 음수가 나왔기 때문에 해당 값이 클수록 해당 클래스가 나올 확률이 낮아진다는 의미로 해석 가능
  • 두 번째 클래스는 계수로 -0.055552643460647214 값이 나온 color_intensity 변수에 가장 영향을 많이 받았다는 것을 알 수 있다.
    • 음의 관계를 가지기 때문에 해당 값이 클수록 클래스가 나올 확률이 낮아진다는 의미로 해석 가능
  • 세 번째 클래스는 계수로 0.06980938213920487 값이 나온 color_intensity 변수에 가장 영향을 많이 받았다는 것을 알 수 있다.
    • 양의 관계를 가지기 때문에 해당 값이 클수록 클래스가 나올 확률이 높아진다는 의미로 해석 가능


6. Reference


👩🏻‍💻개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다.

댓글남기기