로지스틱 회귀분석 (Logistic Regression)
선형 모형을 이용한 감성 분석
y=wx+b
- x: 문서 내 특정 단어의 빈도
- y: 문서의 긍/부정(긍정 = 1, 부정 = 0)
- w: 가중치 또는 계수
- w>0: x가 증가할수록 y도 증가 → 긍정 단어
- w<0: x가 증가하면 y는 감소 → 부정 단어
- b: 절편 또는 편향
로지스틱 모형
- 선형 모형의 경우 y가 −∞ ~ +∞의 범위를 가짐
- 실제로 y는 긍정(1) 또는 부정(0)
- 선형 모형에 로지스틱 함수를 결합하여 y가 0~1 범위를 가지게 함
y=σ(wx+b)
로지스틱 함수 (Logistic Function)
σ(x)=1/(1+e−x)
- 벨기에 수학자 P. F. 베르헐스트가 고안
- S자 형태의 곡선이라 '시그모이드'라고도 함
- sigma: 그리스어의 S
- -oid: ~를 닮은 (안드로이드: 인간을 닮은)
로지스틱 모형의 출력값에 대한 해석
- 로지스틱 모형은 0~1 사이의 실수를 출력 → 확률로 해석
- 예시:
- 0.8인 경우 → 긍정일 확률이 80% (부정일 확률 20%)
- 0.4인 경우 → 긍정일 확률이 40% (부정일 확률 60%)
- 보통 0.5를 기준으로 그보다 높으면 긍정, 낮으면 부정으로 예측
로지스틱 모형의 학습 방법
- **'학습'**이란 모형의 파라미터(w, b)를 추정하는 것
- 모형의 예측과 문장의 실제 긍/부정의 차이를 손실 함수로 측정하여, 손실 함수의 값을 가장 작게 만드는 파라미터를 찾음
- 주로 **경사하강법(Gradient Descent)**이라는 알고리즘을 사용
- 데이터의 일부(batch)를 모형에 입력한다
- 모형의 예측과 실제값을 비교하여 손실을 구한다
- 손실이 작아지는 방향으로 파라미터를 약간 수정한다
- 위의 과정을 반복한다
교차 엔트로피 (Cross Entropy)
- 두 확률 분포의 차이를 계산
- 범주형 변수의 예측에 사용
H(p,q)=−∑p(x)logq(x)
- p와 q 두 확률 분포가 비슷할수록 작아짐
- 높은 확률로 예측했을 때 맞고, 낮은 확률로 예측했을 때 틀려야 교차 엔트로피가 감소
우도 (Likelihood)
- 어떤 모형을 가정했을 때, 우리가 가진 샘플의 데이터가 관찰될 가능성
- 우도가 높으면, 우리의 가정이 맞다고 생각할 수 있다 (최대우도법)
- 우도에 로그를 씌운 것이 로그 우도
- 마이너스 로그 우도 = 교차 엔트로피
- 교차 엔트로피의 최소화는 최대우도법과 동일
정칙화 (Regularization)
- 과대적합을 막기 위한 방법들
- w와 과대적합
- 기본적인 로지스틱 회귀분석은 교차 엔트로피를 가장 작게 만드는 파라미터 w를 추정
- w가 너무 커지면서 함수의 형태가 불규칙 → 과대적합
- 정칙화
- 손실함수 J(w)에 파라미터의 크기(norm)를 추가
- 가능한 작은 파라미터로 손실을 낮추도록 학습
- 함수형의 형태를 규칙적으로(=regular) 만들어 과대적합을 억제
- 종류:
- 라쏘 (Lasso, L1)
- 릿지 (Ridge, L2)
- 엘라스틱넷 (Elastic Net): 라쏘 + 릿지
엘라스틱 넷 (Elastic Net)
J(w)+C∑(λ∣w∣+(1−λ)w2/2)
- λ: L1과 L2 norm 중 L1의 반영 비율 (0≤λ≤1)
- C: 정칙화의 강도를 결정
- L1은 일부 파라미터를 0으로 만드는 경향이 있음
사이킷런에서 로지스틱 회귀분석
from sklearn.linear_model import LogisticRegressionCV
- 엘라스틱넷으로 C는 0.001, 0.01, 0.1 세 가지, L1의 비율은 0, 0.5, 1 세 가지를 시도
- 총 9가지 조합을 시도하여 성능이 가장 좋은 조합을 찾음
model = LogisticRegressionCV(
penalty='elasticnet', solver='saga', random_state=42,
Cs=[0.1, 1, 10], l1_ratios=[0, 0.5, 1], max_iter=4000
)
model.fit(x_train, y_train)
결과
model.C_
model.l1_ratio_
테스트
model.score(x_train, y_train)
model.score(x_test, y_test)
단어별 가중치
word_coef = pd.DataFrame({
'단어': cv.get_feature_names_out(),
'가중치': model.coef_.flat
})
긍부정 단어 보기
word_coef.sort_values('가중치').tail(10)
word_coef.sort_values('가중치').head(10)
예측
y_pred = model.predict(x_test)
probs = model.predict_proba(x_test)
prob = probs[:, 1]
threshold = 0.5
y_pred = np.where(prob > threshold, 1, 0)