728x90
04-1 로지스틱 회귀¶
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()
fish_target = fish['Species'].to_numpy()
In [4]:
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)
k-최근접 이웃 분류기의 확률 예측¶
In [5]:
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)
In [6]:
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 [7]:
print(kn.predict(test_scaled[:5]))
import numpy as np
proba = kn.predict_proba(test_scaled[:5])
print(np.round(proba, decimals=4))
['Perch' 'Smelt' 'Pike' 'Perch' 'Perch']
[[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. ]]
3개의 최근접 이웃을 사용하기 때문에 가능한 확률은 0/3, 1/3, 2/3, 1이 전부
이런 단점을 해결하고자 로지스틱 회귀 사용
로지스틱 회귀¶
로지스틱 회귀 : 선형 방정식을 사용한 분류 알고리즘으로 선형 회귀와 달리 시그모이드 함수나 소프트맥스 함수를 사용하여 클래스 확률을 출력
In [8]:
# 시그모이드 함수
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 [9]:
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]
In [10]:
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_bream_smelt, target_bream_smelt)
Out[10]:
LogisticRegression()
In [11]:
print(lr.predict(train_bream_smelt[:5]))
print(lr.predict_proba(train_bream_smelt[:5]))
['Bream' 'Smelt' 'Bream' 'Bream' 'Bream']
[[0.99759855 0.00240145]
[0.02735183 0.97264817]
[0.99486072 0.00513928]
[0.98584202 0.01415798]
[0.99767269 0.00232731]]
In [12]:
print(lr.coef_, lr.intercept_) #로지스틱 회귀 계수
[[-0.4037798 -0.57620209 -0.66280298 -1.01290277 -0.73168947]] [-2.16155132]
In [13]:
decisions = lr.decision_function(train_bream_smelt[:5]) # z 출력 값
print(decisions)
[-6.02927744 3.57123907 -5.26568906 -4.24321775 -6.0607117 ]
In [14]:
# 시그모이드 함수에 대입하면 확률 생성
from scipy.special import expit
print(expit(decisions))
[0.00240145 0.97264817 0.00513928 0.01415798 0.00232731]
로지스틱 회귀로 다중 분류 수행¶
In [15]:
# C는 alpha와 반대로 작을수록 규제가 커진다. 기본값 1
lr = LogisticRegression(C=20, max_iter=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
In [16]:
print(lr.predict(test_scaled[:5]))
proba = lr.predict_proba(test_scaled[:5])
print(np.round(proba, decimals=3))
['Perch' 'Smelt' 'Pike' 'Roach' 'Perch']
[[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 [17]:
decision = lr.decision_function(test_scaled[:5]) # z 출력 값
print(np.round(decision, decimals=2))
[[ -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 [18]:
# 다중 분류일때는 소프트맥스 함수 사용
from scipy.special import softmax
proba = softmax(decision, axis=1) # axis를 지정하지 않으면 배열 전체에 대해 소프트맥스 계산
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]]
04-2 확률적 경사 하강법¶
데이터를 조금씩 사용해 점진적으로 학습하는 방법
확률적 경사 하강법 : 훈련 세트에서 랜덤하게 "하나"의 샘플을 선택하여 손실 함수의 경사를 따라 최적의 모델을 찾는 알고리즘
에포크(epoch) : 확률적 경사 하강법에서 훈련 세트를 한 번 모두 사용하는 과정
배치 경사 하강법 : 여러 개의 샘플을 사용해 경사 하강법을 수행하는 방식
배치 경사 하강법 : 한 번에 전체 샘플을 사용하는 방법으로 전체 데이터를 사용
손실 함수 : 어떤 문제에서 머신러닝 알고리즘이 얼마나 엉터리인지를 측정하는 기준
로지스틱 손실 함수 : 타깃 = 1 일때 -> -log(예측확률), 타깃 = 0 일때 -> -log(1-예측확률) {이진 크로스엔트로피 손실 함수라고도 한다}
크로스엔트로피 손실 함수 : 다중 분류에서 사용하는 손실 함수
In [19]:
# 데이터 준비
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)
In [20]:
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)
In [21]:
from sklearn.linear_model import SGDClassifier
sc = SGDClassifier(loss='log', max_iter=10, random_state=42) # 로지스틱 손실 함수 사용
sc.fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
0.773109243697479
0.775
C:\work\envs\datascience\lib\site-packages\sklearn\linear_model\_stochastic_gradient.py:574: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
warnings.warn("Maximum number of iteration reached before "
In [22]:
# partial_fit을 사용하여 에포크를 한 번 더 실행
sc.partial_fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
0.8151260504201681
0.85
에포크가 적게 진행되면 모델이 훈련 세트를 덜 학습하는 단점
에포크가 많으면 과대 적합되는 단점
적절한 에포크 값을 찾는게 중요
In [23]:
import numpy as np
sc = SGDClassifier(loss='log', random_state=42)
train_score = []
test_score = []
classes = np.unique(train_target)
In [24]:
for _ in range(0, 300):
sc.partial_fit(train_scaled, train_target, classes=classes)
train_score.append(sc.score(train_scaled, train_target))
test_score.append(sc.score(test_scaled, test_target))
In [25]:
# 에포크에 따른 정확도
import matplotlib.pyplot as plt
plt.plot(train_score, label='train')
plt.plot(test_score, label='test')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend()
plt.show()
In [26]:
# 에포크 100일때 적합
sc = SGDClassifier(loss='log', max_iter=100, tol=None, random_state=42)
sc.fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
0.957983193277311
0.925
In [27]:
from IPython.core.display import display, HTML
display(HTML("<style>.container {width:80% !important;}</style>"))
728x90
'Book report > 혼자 공부하는 머신러닝 + 딥러닝' 카테고리의 다른 글
[혼자 공부하는 머신러닝 + 딥러닝] Chapter 7 딥러닝을 시작합니다 (0) | 2021.09.04 |
---|---|
[혼자 공부하는 머신러닝 + 딥러닝] Chapter 6 비지도 학습 (0) | 2021.09.03 |
[혼자 공부하는 머신러닝 + 딥러닝] Chapter 5 트리 알고리즘 (0) | 2021.09.01 |
[혼자 공부하는 머신러닝 + 딥러닝] Chapter 3 회귀 알고리즘과 모델 규제 (0) | 2021.08.31 |
[혼자 공부하는 머신러닝 + 딥러닝] Chapter 2 데이터 다루기 (0) | 2021.08.30 |