혼공머

혼공머 4-1 로지스틱 회귀

박뮤트 2022. 1. 19. 12:52

로지스틱 회귀: 이름은 회귀이지만 분류 모델이다.

목표) 종속 변수와 독립 변수 간의 관계를 구체적인 함수로 나타내어 예측 모델에 사용하는 것

독립 변수의 선형 결합으로 종속 변수를 설명한다는 점에서 선형 회귀 분석과 유사하다.

그러나 로지스틱 회귀는 선형 회귀분석과 다르게 종속 변수가 '범주형 데이터'를 대상으로 하고, 데이터 분석 결과가 특정 분류로 나뉘기 때문에 분류 기법으로 볼 수 있다.

 

선형 방정식

z = a * 무게 + b * 길이 + c * 대각선 + d * 높이 + e * 넓이 + f

여기서 a, b, c, d, e는 가중치 혹은 계수

z 값을 0~1 사이의 값으로 만들기 위해서(확률로 표현하기 위해서) 시그모이드 함수(혹은 로지스틱 함수)를 사용한다.

 

로지스틱 회귀로 이진 분류 수행하기

# 도미와 빙어 분류하기

# 불리언 인덱싱을 통해 도미, 빙어 데이터 골라내기
bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt')
train_bream_smelt = train_scaled[bream_smelt_indexes]
target_bream_smelt = train_target[bream_smelt_indexes]

# 로지스틱 회귀 모델 훈련
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_bream_smelt, target_bream_smelt)

# 처음 1개 샘플 확률 출력
print(lr.predict_proba(train_bream_smelt[:1]))
>>> [[0.99759855 0.00240145]]        # 알파벳 순으로 정렬하기 때문에 도미가0, 빙어가1

# 로지스틱 회귀가 학습한 계수 확인
print(lr.coef_, lr.intercept_)
>>> [[-0.4037798, -0.57620209, -0.66280298, -1.01290277, -0.73168947]][-2.16155132]

로지스틱 회귀 모델이 학습한 방정식

z = -0.404 * 무게 - 0.576 * 길이 - 0.663 * 대각선 - 1.013 * 높이 - 0.732 * 넓이 - 2.161

 

# LogisticRegression 모델로 z 값 계산하기
# decision_function() 메소드 사용
decision = lr.decision_function(train_bream_smelt[:1])
print(decision)
>>> [-6.02927744]

이 z 값을 시그모이드 함수에 통과시켜 확률을 얻을 수 있다.

사이파이 라이브러리의 expit() 함수가 시그모이드 함수이다.

from scipy.special import expit
print(expit(decision))
>>> [0.00240145]

decision_function()은 양성 클래스에 대한 z 값 반환

 

로지스틱 회귀로 다중 분류 수행하기

lr = LogisticRegression(C=20, max_iter=1000)

L2 규제(계수의 제곱을 규제한다)를 사용

로지스틱 회귀에서 규제를 제어하는 매개변수는 대문자 C이다. 기본값은 1이며, 작을수록 규제가 커진다.

(책에서는 규제를 완화하기 위해 20으로 늘렸다.)

 

max_iter 매개변수는 반복횟수를 지정하는 것으로 기본값은 100이다. 

(책에서는 충분히 훈련시키기 위해 1000으로 늘렸다.)

 

# 훈련 시키기
lr.fit(train_scaled, train_target)
print(lr.score(train_scaled, train_target))
print(lr.score(test_scaled, test_target))
>>>
0.9327731092436975		# 훈련 세트
0.925				# 테스트 세트
# 예측 확률 출력하기
proba = lr.predict_proba(test_scaled[:1])
print(np.round(proba, decimals=3))
>>> [[0.	0.014	0.841	0.	0.136	0.007	0.003]]

# 클래스 정보 확인
print(lr.classes_)
>>> ['Bream' 'Parkki' 'Perch' 'Pike' 'Roach' 'Smelt' 'Whitefish']

Perch일 확률이 84.1%로 가장 높다.

 

소프트맥스 함수

: 다중 분류는 클래스(여기서는 생선 종류 7개)마다 z값을 하나씩 계산한다. 시그모이드 함수는 하나의 선형 방정식의 출력값을 0~1 사이로 압축하는 반면, 소프트맥스 함수는 여러 개의 선형 방정식의 출력값을 0~1사이로 압축하고 전체 합이 1이 되도록한다.

 

계산방식

1) 7개의 z 값을 z1 ~ z7이라고 붙인다.

2) e_sum = e^z1 + e^z2 + ... + e^z7

3) e^z1 ~ e^z7을 각각 e_sum으로 나눈다.

s1 = e^z1 / e_sum

s2 = e^z2 / e_sum

.

.

.

s7  = e^z7 / e_sum

4) s1부터 s7까지 더하면 1이 된다.

decision_function()을 사용해보자

decision = lr.decision_function(test_scaled[:1])
print(np.round(decision, decimals=2))
>>> [[-6.5	1.03	5.16	-2.73	3.34	0.33	-0.63]]

softmax() 함수에 decision을 전달해보자

from scpy.special import softmax
proba = softmax(decision, axis=1)
print(np.round(proba, decimals=3))
>>> [[0.	0.014	0.841	0.	0.136	0.007	0.003]]