머신러닝_로지스틱스회귀

김수경·2024년 1월 31일

머신러닝

목록 보기
2/5

로지스틱스 회귀

선형회귀 vs 로지스틱스 회귀

  • 선형회귀 : 숫자, 평균으로 예측
  • 로지스틱스 회귀 : 분류(사망/생존)를 예측
    -> 선형회귀를 이용하기 때문에 '회귀'가 붙음

타이타닉 예제로 보는 로지스틱스 회귀

  • Y가 범주(0, 1 사망/생존)인 경우 선형회귀로 표현하기 부적절
    ex) 성별과 생존, 요금과 생존 등
  • 가중치를 안다면 X값이 주어졌을 때 해당 사건이 일어날 수 있는 P의 확률 계산
    이때, 확률 0.5를 기준으로 그보다 높으면 사건이 일어남 (P(Y) = 1), 그렇지 않으면 사건이 일어나지 않음(P(Y) = 0)으로 판단하여 분류 예측에 사용함
  • 로지스틱함수 계산식
    Logit=log(P1P)Logit = \log(\frac{P}{1-P})

회귀분석에서 예측값을 평가(MSE, R2)한 것 처럼
로지스틱회귀도 분류예측을 평가하는 지표가 존재함.


로지스틱스회귀 분류 평가

혼동 행렬(confusion Matrix)

📌 실제 값과 예측 값에 대한 모든 경우의 수를 표현하기 위한 2x2 행렬입니다.

  • 표기법
    • 실제와 예측이 같으면 True / 다르면 False
    • 예측을 양성으로 했으면 Positive / 음성으로 했으면 Negative
  • 해석
    - TP: 실제로 양성(암 환자)이면서 양성(암 환자) 올바르게 분류된 수
    - FP: 실제로 음성(정상인)이지만 양성(암 환자)로 잘못 분류된 수
    - FN: 실제로 양성(암 환자)이지만 음성(정상인)로 잘못 분류된 수
    - TN: 실제로 음성(정상인)이면서 음성(정상인)로 올바르게 분류된 수

1. 정밀도

모델이 양성 1로 예측한 결과 중 실제 양성의 비율(모델의 관점)

정밀도(precision)=TPTP+FP정밀도(precision) = \frac{TP}{TP+FP}
  • 재현율
  • F1-Score(아래) sklearn.metrics.f1_socre
  • 정확도(아래) sklearn.metrics.accuracy

2. 재현율

실제 값이 양성인 데이터 중 모델이 양성으로 예측한 비율(데이터의 관점)

재현율(Recall)=TPTP+FN재현율(Recall) = \frac{TP}{TP+FN}

3. F1-Score - 분류평가 지표 1

정밀도와 재현율의 조화평균

f1score=2정밀도재현율정밀도+재현율f1-score = 2*\frac{정밀도*재현율}{정밀도+재현율}

4. 정확도 - 분류평가 지표 2

맞춘것 / 전체 데이터 갯수

정확도(Accuracy)=TP+TNTP+TN+FP+FN정확도(Accuracy) = \frac{TP+TN}{TP+TN+FP+FN}

로지스틱스회귀 실습

X 변수가 1개일 때

(캐글 타이타닉 데이터로 실습하기)
가설 : 비상상황 특성상 여성을 배려하여 여성이 많이 생존했을 것이다.
1. pivot table을 만들어 확인
2. 그래프를 통해 확인

# 데이터 불러오기
import pandas as pd

titanic_df = pd.read_csv("파일경로")
titanic_df.head()


피봇테이블로 성별과 생존 명수 확인

#size : 갯수를 더해줌
pd.pivot_table(titanic_df, index = 'Sex', columns = 'Survived', aggfunc = 'size')

#데이터 갯수
len(titanic_df) --891


수기로 정확도를 계산해보면(여성은 다 살았을 거고 남성은 다 죽었을 것이다.)
(233+468) / 891 * 100 = 78%
-> 제법 높은 정확도!
피봇을 시각화 해보면,

#갯수를 세는 그래프니까 y는 따로 지정 안함
#hue는 범례
import seaborn as sns
sns.countplot(data = titanic_df, x='Sex', hue = 'Survived')


성별과 생존 여무가 제법 뚜렷하게 나타남.
이제, y가 범주형인 로지스틱스회귀 분석을 통해 예측모델을 만들어보자.
(x = 요금, y = 생존여부)

X_1 = titanic_df[['Fare']]
Y_true = titanic_df[['Survived']]

데이터 확인을 위해 산점도를 먼저 그려본다.

sns.scatter.plot(data=titanic_df, x = 'Fare', y = 'Surveived')


이상적인 로지스틱스 회귀분석으로는 나오지 않음 : 이상치가 있기 때문(전처리 하지 않음)
그리고 각 점에 대한 밀도도 알 수 없음
산점도 보다는 분포를 먼저 확인해야 한다.

sns.histplot(data = tatanic_df, x = 'Fare')


앞쪽에 분포가 많음
500이상짜리는 뺄지 말지 고민해보아야 함
기술통계를 통해 확인도 해보기 (fare 특성 확인)

titanic_df.describe()


로지스틱회귀 모델 학습하기

#로지스틱회귀 모델 불러오기
import sklearn
from sklearn.linear_model import LogisticRegression

#모델변수 선언
model_lor = LogisticRegression() 
model_lor.fit(X_1, y_true)

로지스틱회귀 모델 속성 확인
sklearn.linear_model.LogisticRegression : 로지스틱회귀 모델 클래스

def get_att(x) : 
	print('클래스 종류', x.classes_)
    print('독립변수 갯수', x.n_features_in)
    print('들어간 독립변수(x) 이름', x.feature_name_in_)
    print('가중치', x.coef_)
    print('바이어스', x.intercept)

get_att(model_lor)

---
클래스 종류 [0 1]
독립변수 갯수 1
들어간 독립변수(x) 이름 ['Fare']
가중치 [[0.01519666]]
바이어스 [-0.94131796]

로지스틱회귀 분류평가 지표
1) f1-Score, 정확도

#함수 불러오기
from sklearn.metrics import accuracy_score, f1_score

#함수만들기
def get_metrics(true, pred) : 
	print('정확도', accuracy_score(true, pred)
    print('f1-score', f1_score(true, pred)

#예측값 생성
y_pred_1 = model.lor.pridict(X_1)

#함수에 모델 적용시켜 평가하기
get_metrics(y_true, y_pred_1)
---
정확도 0.6655443322109988
f1-score 0.35497835497835495
---

정확도 66%로 제법 높지만 f-1스코어가 35%를 넘지 않아 좋은 모델이라 하긴 어렵다.
-> 변수를 추가하거나 데이터 전처리를 통해 모델 평가 지표를 높일 수 있다.


X변수가 여러개일 때

Y = Survived
X = Plass, Sex, Fare

# pclass는 1, 2, 3이기 때문에 전처리 할 필요가 없음 
# 성별을 전처리 하자면
def get_sex(x) : 
	if x == 'female' :
    	return 0
    else : 
    	return 1

#열 추가해줌
titanic_df['Sex_en'] = titanic_df['Sex'].apply(get_sex)
titanic_df.head()

x의 세가지 변수에 대한 모델 학습

#변수 설정, 모델 학습
X_2 = titanic_df[['Pclass', 'Sex_en', 'Fare']]
y_true = titanic_df[['Survived']]

model_lor_2 = LogisticRegression() 
model_lor_2.fit(X_2, y_true)

위에서 넣었던 get_att로 모델 속성 확인

get_att(model_lor_2)
---
클래스 종류 [0 1]
독립변수 갯수 3
들어간 독립변수(x) 이름 ['Pclass' 'Sex_en' 'Fare']
가중치 [[-8.88331324e-01 -2.53993425e+00  1.64019087e-03]]
바이어스 [3.02004403]
---

y 예측값 구하기

y_pred_2 = model_lor_2.predict(X_2)
y_pred_2[:10]
---
array([0, 1, 1, 1, 0, 0, 0, 0, 1, 1])
---

예측값 넣은 모델 평가하기
위에서 사용했던 get_metrics함수 사용

# X변수가 1개 Fare
get_metrics(y_true, y_pred_1)

# X변수가 3개 Fare, Sex_en, Pclass
get_metrics(y_true, y_pred_2)
---
정확도 0.6655443322109988
f1-score 0.35497835497835495
정확도 0.7867564534231201
f1-score 0.7121212121212122
---

변수가 fare 하나일때보다 정확도와 f1-score모두 올라감
그렇다면 0, 1말고 실제로 y예측값에 대한 확률은 어떻게 될까?
각 데이터별 Y=1일 확률 뽑아보기

model_lor_2.predict_proba(X_2) 
---
array([[0.8977979 , 0.1022021 ],
       [0.09546762, 0.90453238],
       [0.40901264, 0.59098736],
       ...,
       [0.40287202, 0.59712798],
       [0.58880217, 0.41119783],
       [0.89772263, 0.10227737]])
---

이중리스트, 첫번째는 죽을 확률 두번째는 생존할 확률
[0.8977979 , 0.1022021 ] -> 죽을 확률 89%, 생존할 확률 10% -> 0.5 기준으로 분할하면 0
[0.09546762, 0.90453238] -> 죽을확률 9% 생존할 확률 90%

y 예측값을 다시 확인해보면

y_pred_2[:10]
---
array([0, 1, 1, 1, 0, 0, 0, 0, 1, 1])

확인해보면 첫번째 사람은 0
두번째 사람은 1

정리해보자면, 회귀분석은 다음과 같은 순서로 이루어진다.

  1. x, y 변수 설정
    • X 변수 설정
    • y_true 설정
  2. 회귀모델 설정 및 학습(fit)
    • 모델변수 회귀모델 설정
      model = LinearRegresstion() or LogisticRegression()
    • 모델학습
      model.fit(X, y_true)
  3. 모델 속성 함수(확인용)
    • 선형회귀
      coef_: 가중치
      intercept_ : 바이어스
    • 로지스틱회귀
      x.classes_ : 클래스(Y)의 종류
      n_features_in_ : 독립변수(X)의 갯수
      feature_name_in : 독립변수(X)의 이름
      coef_: 가중치
      intercept_ : 바이어스
  4. y 예측값 구하기
    y_pred = model.predict(X)
  5. 모델 평가(선형회귀 : MSE, R2 / 로지스틱회귀 : 정확도, f1-Score)
    • MSE: mean_squared_error(y_true, y_pred)
    • R2 : r2_score(y_true, y_pred)
    • 정확도 : accuracy_score(y_true, y_pred)
    • f1-Score : f1_score(y_true, y_pred)

선형회귀 vs 로지스틱스회귀

공통점

  • 모델 생성이 쉬움
  • 가중치(회귀계수)를 통한 해석이 쉬움
  • X변수에 범주형, 수치형 둘다 사용 가능함

차이점

profile
잘 하고 있는겨?

0개의 댓글