Notice
Recent Posts
Recent Comments
Link
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Tags
more
Archives
Today
Total
관리 메뉴

kang's study

7일차 : 로지스틱 회귀분석 (분류) 본문

[학습 공간]/[혼공머신러닝]

7일차 : 로지스틱 회귀분석 (분류)

보끔밥0302 2022. 3. 3. 06:19

로지스틱 회귀

럭키백의 확률
 
데이터 준비하기
In [1]:
import pandas as pd

fish = pd.read_csv('https://bit.ly/fish_csv_data')
fish.head()
Out[1]:
  Species Weight Length Diagonal Height Width
0 Bream 242.0 25.4 30.0 11.5200 4.0200
1 Bream 290.0 26.3 31.2 12.4800 4.3056
2 Bream 340.0 26.5 31.1 12.3778 4.6961
3 Bream 363.0 29.0 33.5 12.7300 4.4555
4 Bream 430.0 29.0 34.0 12.4440 5.1340
In [2]:
print(pd.unique(fish['Species']))
 
['Bream' 'Roach' 'Whitefish' 'Parkki' 'Perch' 'Pike' 'Smelt']
In [3]:
# 데이터 프레임에서 열 선택 : 원하는 열을 리스트로 나열
fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
In [4]:
print(fish_input[:5])
 
[[242.      25.4     30.      11.52     4.02  ]
 [290.      26.3     31.2     12.48     4.3056]
 [340.      26.5     31.1     12.3778   4.6961]
 [363.      29.      33.5     12.73     4.4555]
 [430.      29.      34.      12.444    5.134 ]]
In [5]:
fish_target = fish['Species'].to_numpy()
In [6]:
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)
In [7]:
from sklearn.preprocessing import StandardScaler # 특성마다 스케일이 다른걸 정규화

ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)
 

k-최근접 이웃 분류기의 확률 예측

In [8]:
from sklearn.neighbors import KNeighborsClassifier

kn = KNeighborsClassifier(n_neighbors=3)
kn.fit(train_scaled, train_target) # 문자열도 타겟으로 잘 받음

print(kn.score(train_scaled, train_target))
print(kn.score(test_scaled, test_target))
 
0.8907563025210085
0.85
In [9]:
print(kn.classes_) # 알파벳 순서로 나옴
 
['Bream' 'Parkki' 'Perch' 'Pike' 'Roach' 'Smelt' 'Whitefish']
In [10]:
print(kn.predict(test_scaled[:5]))
 
['Perch' 'Smelt' 'Pike' 'Perch' 'Perch']
In [11]:
import numpy as np

proba = kn.predict_proba(test_scaled[:5])
print(np.round(proba, decimals=4))
 
[[0.     0.     1.     0.     0.     0.     0.    ]
 [0.     0.     0.     0.     0.     1.     0.    ]
 [0.     0.     0.     1.     0.     0.     0.    ]
 [0.     0.     0.6667 0.     0.3333 0.     0.    ]
 [0.     0.     0.6667 0.     0.3333 0.     0.    ]]
In [12]:
distances, indexes = kn.kneighbors(test_scaled[3:4])
print(train_target[indexes])
 
[['Roach' 'Perch' 'Perch']]
 

최근접 이웃은 가능한 확률이 이웃의 개수에 제한되어있는 한계가 있다.
위처럼 3개의 최근접이웃은 0/3, 1/3, 2/3, 3/3이 전부이다.

 

로지스틱 회귀 (분류)

분류를 위해 츨력값의 범위를 0~1로 바꿈
시그모이드 함수를 이용해서 로지스틱을 구한다.

 
 

시그모이드 함수

In [13]:
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()
 
 

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

도미와 빙어만 분류해보기

In [14]:
char_arr = np.array(['A', 'B', 'C', 'D', 'E'])
print(char_arr[[True, False, True, False, False]])
 
['A' 'C']
In [15]:
bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt') # 불리언 인덱싱
train_bream_smelt = train_scaled[bream_smelt_indexes] # bream, smelt만 뽑힘
target_bream_smelt = train_target[bream_smelt_indexes]
In [16]:
from sklearn.linear_model import LogisticRegression

lr = LogisticRegression()
lr.fit(train_bream_smelt, target_bream_smelt) 
Out[16]:
LogisticRegression()
In [17]:
print(lr.predict(train_bream_smelt[:5]))
 
['Bream' 'Smelt' 'Bream' 'Bream' 'Bream']
In [18]:
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]]
In [19]:
print(lr.classes_)
# 알파벳 순서로 레이블 됨 0 bream 1 smelt
# 음성클래스(0): 도미, 양성클래스(1) : 빙어
 
['Bream' 'Smelt']
In [20]:
# 모델이 학습한 계수 확인
print(lr.coef_, lr.intercept_) # 무게, 길이 , 대각선, 높이, 두께
 
[[-0.4037798  -0.57620209 -0.66280298 -1.01290277 -0.73168947]] [-2.16155132]
 

로지스틱 회귀 모델이 학습한 방정식
z = -0.404 × (weight) -0.576 × (length) -0.663 × (diagonal) -1.013 × (height) -0.732 × (width) -2.161

In [21]:
# 처음5개 샘플의 z값을 출력
# decision_function()메서드는 양성 클래스에 대한 z값을 반환
decisions = lr.decision_function(train_bream_smelt[:5])
print(decisions)
 
[-6.02927744  3.57123907 -5.26568906 -4.24321775 -6.0607117 ]
In [22]:
from scipy.special import expit # 시그모이드 함수 제공
print(expit(decisions)) 
# 결과적으로 양성 클래스만 나옴
# 앞선 prob 값이랑 동일, 이진분류는 하나의 함수만 학습해도 나머지는 1에서 빼면됨
 
[0.00240145 0.97264817 0.00513928 0.01415798 0.00232731]
 

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

In [23]:
lr = LogisticRegression(C=20, max_iter=1000) 
# 반복적인 알고리즘을 사용하며 반복횟수 기본 100, 
# 릿지 회귀와 같이 계수의 제곱을 규제한다 (L2규제)
# 규제를 제어하는 매개변수 C는 alpha와 반대로 작을수록 규제가 큼 default=1
lr.fit(train_scaled, train_target)

print(lr.score(train_scaled, train_target))
print(lr.score(test_scaled, test_target))
 
0.9327731092436975
0.925
In [24]:
print(lr.predict(test_scaled[:5]))
 
['Perch' 'Smelt' 'Pike' 'Roach' 'Perch']
In [25]:
proba = lr.predict_proba(test_scaled[:5]) # softmax함수가 이용된다.
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]]
In [26]:
print(lr.classes_)
 
['Bream' 'Parkki' 'Perch' 'Pike' 'Roach' 'Smelt' 'Whitefish']
In [27]:
print(lr.coef_.shape, lr.intercept_.shape) 
# 다중 분류는 클래스마다 z값을 하나씩 계산한다.
# 7개의 클래스 마다 선형함수가 1개씩 만들어짐 (이진분류 하나 양성 나머지 음성)
 
(7, 5) (7,)
In [28]:
decision = lr.decision_function(test_scaled[:5])
# 이진 분류 여러 번 실행 z값 7개 출력
print(np.round(decision, decimals=2)) 
# 7개의 시그모이드의 합이 1이 되게 출력하려면 새로운 함수가 필요하다
 
[[ -6.5    1.03   5.16  -2.73   3.34   0.33  -0.63]
 [-10.86   1.93   4.77  -2.4    2.98   7.84  -4.26]
 [ -4.34  -6.23   3.17   6.49   2.36   2.42  -3.87]
 [ -0.68   0.45   2.65  -1.19   3.26  -5.75   1.26]
 [ -6.4   -1.99   5.82  -0.11   3.5   -0.11  -0.71]]
In [29]:
from scipy.special import softmax # 다중분류의 z값 확률을 표현

proba = softmax(decision, 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]]

출처 : 박해선, 『혼자공부하는머신러닝+딥러닝』, 한빛미디어(2021), p176-196

Comments