-
[혼공머] 4-1. 로지스틱 회귀Data Science/딥러닝 & 머신러닝 2025. 1. 10. 23:55
1. 럭키백의 확률
1. 배경
- 기간 한정 럭키백을 런칭 : 7개의 생선이 들어간다.
- 럭키백에 포함된 생선의 확률을 알려줄 것이다.
- → 어떻게 생선의 확률을 구할 수 있을까?
- 사용할 데이터 : 생선의 길이, 높이, 두께, 대각선 길이, 무게
2. 데이터 불러오기
import pandas as pd fish = pd.read_csv('<https://bit.ly/fish_csv_data>') print(pd.unique(fish['Species'])) # ['Bream' 'Roach' 'Whitefish' 'Parkki' 'Perch' 'Pike' 'Smelt']
3. 훈련 데이터와 타겟 데이터
fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy() fish_target = fish['Species'].to_numpy() from sklearn.model_selection import train_test_split train_input, test_input, train_target, test_target = train_test_split(fish_input, fish_target, random_state=42) from sklearn.preprocessing import StandardScaler ss = StandardScaler() ss.fit(train_input) train_scaled = ss.transform(train_input) test_scaled = ss.transform(test_input)
4. K-NeighborsClassifier로 확률 예측
from sklearn.neighbors import KNeighborsClassifier kn = KNeighborsClassifier(n_neighbors=3) kn.fit(train_scaled, train_target) kn.score(train_scaled, train_target), kn.score(test_scaled, test_target) # (0.8907563025210085, 0.85)
- classes_ : 다중 분류에서의 타겟값 확인
- predict_proba : 클래스별 확률값 출력조금 더 구체적인 확률이 필요하다.
kn.classes_ # array(['Bream', 'Parkki', 'Perch', 'Pike', 'Roach', 'Smelt', 'Whitefish'], dtype=object) kn.predict_proba(test_scaled[:3]) # array([[0., 0., 1., 0., 0., 0., 0.], # [0., 0., 0., 0., 0., 1., 0.], # [0., 0., 0., 1., 0., 0., 0.]])
2. 로지스틱 회귀와 시그모이드 함수
1. 로지스틱 회귀
- 선형회귀와 동일하지만, 분류 모델
- 다중회귀(독립변수 여러개)의 선형 방정식과 동일a, b, c, d, e : 가중치 or 계수 / z : 어떤 값도 가능함
2. 시그모이드 함수 (로지스틱 함수)
- 배경 : 로지스틱 회귀에서 z가 [0, 1] 의 확률 값을 갖도록 변경할 필요가 있다.
- z 가 아주 큰 음수라면 0
- z가 아주 큰 양수라면 1
- 시그모이드 함수의 형태수식 = 시그모이드 함수 → 그래프 만들기
- 확률값의 범위 내에 있고, z가 무한하게 크면 1, 무한하게 작으면 0을 가진다.
import numpy as np import matplotlib.pyplot as plt z = np.arange(-5, 5, 0.1) phi = 1 / (1 + np.exp(-z)) plt.plot(z, phi) plt.xlabel('z') plt.ylabel('phi') plt.show()
3. 로지스틱 회귀로 이중 분류 수행하기
1. 클래스 구분
- 0.5 초과 시 양성 클래스 [1]
- 0.5 미만 시 음성 클래스 [0]
- → 도미와 빙어를 구분해보자.
2. 불리언 인덱싱
- True, False 값을 전달해 행을 선택하는 것
char_arr = np.array(['A', 'B', 'C', 'D', 'E']) print(char_arr[[True, False, True, False, False]]) # ['A' 'C']
3. 불리언 인덱싱을 이용한 Bream과 Smelt 구분
- 도미와 빙어만 True를 전달하면 된다.
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]
4. 로지스틱 회귀 모델
# 훈련 from sklearn.linear_model import LogisticRegression lr = LogisticRegression() lr.fit(train_bream_smelt, target_bream_smelt)
# 예측 print(lr.predict(train_bream_smelt[:5])) # ['Bream' 'Smelt' 'Bream' 'Bream' 'Bream'] # 음성 클래스와 양성 클래스의 확률 print(lr.predict_proba(train_bream_smelt[:5])) # [[0.99759855 0.00240145] # [0.02735183 0.97264817] # [0.99486072 0.00513928] # [0.98584202 0.01415798] # [0.99767269 0.00232731]]
5. 로지스틱 회귀 모델의 속성
- classes_ : 음성 클래스와 양성 클래스 확인
- 사이킷런에서는 타겟값을 알파벳 순으로 정렬, 0 1 순서
print(lr.classes_) # ['Bream' 'Smelt'] -> Smelt가 양성
- coef_, intercept_
print(lr.coef_, lr.intercept_) # [[-0.4037798 -0.57620209 -0.66280298 -1.01290277 -0.73168947]] [-2.16155132]
- decision_function : logisticRegression 모델로 z 값 계산하기
decisions = lr.decision_function(train_bream_smelt[:5]) print(decisions) # [-6.02927744 3.57123907 -5.26568906 -4.24321775 -6.0607117 ]
- z 값을 시그모이드 함수에 넣으면 확률을 얻을 수 있다.
from scipy.special import expit print(expit(decisions)) # [0.00240145 0.97264817 0.00513928 0.01415798 0.00232731]
- z 값을 시그모이드 함수에 넣으면 확률을 얻을 수 있다.
4. 로지스틱 회귀와 소프트맥스 함수
1. 소프트맥스 함수
- 여러 개의 선형 방정식의 출력값을 0 ~ 1 사이로 압축하고 전체 합이 1이 되도록 만든다.
- ↔ sigmoid 는 1개의 선형 방정식에 대해 압축한다.
- 계산 방식
- class 개수만큼 z 를 구하고, 지수함수에 넣어 더한다.
- e^zi를 e_sum으로 나눈다.모두 더하면 분자 = 분모 → 1
5. 로지스틱 회귀로 다중 분류 수행하기
1. LogisticRegression으로 다중 분류
- LogisticRegression 클래스로 7개의 생선을 분류하자.
- max_iter 매개변수 : 반복 횟수 지정 b/c LogisticRegression은 반복적인 알고리즘을 사용
- C 매개변수 : LogisticRegression에서 규제를 제어
- 작을수록 규제가 크다.
- 기본값은 1
2. LogisticRegression 모델
# 훈련 lr = LogisticRegression(C=20, max_iter=1000) lr.fit(train_scaled, train_target) print(lr.score(train_scaled, train_target) # 0.93 print(lr.score(test_scaled, test_target)) # 0.92
# 예측 print(lr.predict(test_scaled[:5])) # ['Perch' 'Smelt' 'Pike' 'Roach' 'Perch'] # 확률 proba = lr.predict_proba(test_scaled[:5]) print(np.round(proba, decimals=3)) # [[0. 0.014 **0.841** 0. 0.136 0.007 0.003] # [0. 0.003 0.044 0. 0.007 0.946 0. ] # [0. 0. 0.034 0.935 0.015 0.016 0. ] # [0.011 0.034 0.306 0.007 0.567 0. 0.076] # [0. 0. 0.904 0.002 0.089 0.002 0.001]]
가장 높은 확률을 예측 클래스로.
3. 로지스틱 회귀 모델의 속성
- classes_ 속성
- 다중 분류의 선형 방정식 - coef_ 와 intercept_coef 의 행이 7개, 열이 5개 → 열 = 특성가장 높은 z값을 출력하는 클래스가 예측 클래스
- → 행 7개 = z를 일곱 개 계산 : 클래스마다 z값을 하나씩 계산
- print(lr.coef_.shape, lr.intercept_.shape) # (7, 5) (7,)
- decision_function() 으로 z 각각 구하기
print(lr.classes_) # ['Bream' 'Parkki' 'Perch' 'Pike' 'Roach' 'Smelt' 'Whitefish']
decision = lr.decision_function(test_scaled[:5]) print(np.round(decisions, decimals=3)) # [[ -6.498 1.032 5.164 -2.729 3.339 0.327 -0.634] # [-10.859 1.927 4.771 -2.398 2.978 7.841 -4.26 ] # [ -4.335 -6.233 3.174 6.487 2.358 2.421 -3.872] # [ -0.683 0.453 2.647 -1.187 3.265 -5.753 1.259] # [ -6.397 -1.993 5.816 -0.11 3.503 -0.112 -0.707]]
- z 값을 소프트맥스 함수에 넣으면 확률을 얻을 수 있다.
- softmax 함수
- axis =1 : 각 샘플(행)에 대해 소프트맥스르 게산
from scipy.special import expit proba = softmax(decisions, axis=1) print(np.round(proba, decimals=3)) # [[0. 0.014 0.841 0. 0.136 0.007 0.003] # [0. 0.003 0.044 0. 0.007 0.946 0. ] # [0. 0. 0.034 0.935 0.015 0.016 0. ] # [0.011 0.034 0.306 0.007 0.567 0. 0.076] # [0. 0. 0.904 0.002 0.089 0.002 0.001]]
- softmax 함수
6. 로지스틱 회귀로 확률 예측 전체 소스 코드
# 사용할 전체 데이터 준비 import pandas as pd fish = pd.read_csv('<https://bit.ly/fish_csv_data>') # 훈련 데이터와 타겟 데이터 fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy() fish_target = fish['Species'].to_numpy() from sklearn.model_selection import train_test_split train_input, test_input, train_target, test_target = train_test_split(fish_input, fish_target, random_state=42) # 데이터 전처리 - 표준화 from sklearn.preprocessing import StandardScaler ss = StandardScaler() ss.fit(train_input) train_scaled = ss.transform(train_input) test_scaled = ss.transform(test_input) # K-Neighbors를 이용한 다중 분류 from sklearn.neighbors import KNeighborsClassifier kn = KNeighborsClassifier(n_neighbors=3) kn.fit(train_scaled, train_target) kn.score(train_scaled, train_target), kn.score(test_scaled, test_target) kn.predict(test_scaled[:5]) kn.predict_proba(test_scaled[:3]) # 로지스틱 회귀를 이용한 이중 분류 + sigmoid bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt') # boolean train_bream_smelt = train_scaled[bream_smelt_indexes] # boolean indexing target_bream_smelt = train_target[bream_smelt_indexes] # boolean indexing from sklearn.linear_model import LogisticRegression lr = LogisticRegression() lr.fit(train_bream_smelt, target_bream_smelt) lr.predict(train_bream_smelt[:5]) lr.predict_proba(train_bream_smelt[:5]) lr.coef_, lr.intercept_ decisions = lr.decision_function(train_bream_smelt[:5]) from scipy.special import expit print(expit(decisions)) # 로지스틱 회귀를 이용한 다중 분류 + softmax lr = LogisticRegression(C=20, max_iter=1000) lr.fit(train_scaled, train_target) lr.score(train_scaled, train_target), lr.score(test_scaled, test_target) lr.predict(test_scaled[:5]) lr.decision_function(test_scaled[:5]) import numpy as np decision = lr.decision_function(test_scaled[:5]) print(np.round(decision, decimals=2)) from scipy.special import softmax proba = softmax(decision, axis = 1) print(np.round(proba, decimals=3))
'Data Science > 딥러닝 & 머신러닝' 카테고리의 다른 글
[혼공머] 5-1. 결정 트리 (0) 2025.01.12 [혼공머] 4-2. 확률적 경사 하강법 (0) 2025.01.11 [혼공머] 3-3. 특성 공학과 규제 (0) 2025.01.10 [혼공머] 3-2. 선형 회귀 (0) 2025.01.10 [혼공머] 3-1. K-최근접 이웃 회귀 (0) 2025.01.10