판다스를 이용하여 csv파일을 읽어보자!
import pandas as pd
fish = pd.read_csv("https://bit.ly/fish_csv_data")
fish.head()
species에는 어떠한 종류의 생선들이 있는지 확인하기 위해 unique() 함수를 사용해보자.
pd.unique(fish["Species"])
도미,빙어를 비롯해 총 7가지 종류의 생선이 있다.
이제 Species 열을 타겟으로 만들고 나머지 5개 열을 입력 데이터로 사용해보자.
fish_input = fish[["Weight","Length","Diagonal","Height","Width"]].to_numpy()
잘 입력되었는지 처음 5개 행을 출력해보자!
print(fish_input[:5])
array([[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 ]])
이제 타겟 데이터를 준비하자. ( 종류 )
fish_target = fish["Species"].to_numpy()
이제 훈련,테스트 세트로 나눠보자.
from sklearn.model_selection import train_test_split()
train_input, train_target, test_input, test_target = train_test_split(fish_input,fish_target,random_state=42)
이제 데이터 전처리 (표준화)를 하고 훈련시켜보자 !
from sklearn.preprocessing import StandardScaler
ss = StandardSclaer()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)
K-최근접 이웃 분류기로 확률 예측
from sklearn.neighbors import KNeighborsClassifier
Kn = KNeighborsClassifier()
Kn.fit(train_scaled,train_target)
print(Kn.score(train_scaled,train_target))
print(kn.score(test_scaled,test_target))
0.8907563025210085
0.85
이제 타겟값을 어떻게 예측하는지 알아보자.
print(kn.classes_)
array(['Bream', 'Parkki', 'Perch', 'Pike', 'Roach', 'Smelt', 'Whitefish'],
dtype=object)
'Bream'이 첫 번째 클라스, 'Parkki'가 두 번째 클라스.. 방식 predict()메소드를 이용해서 타깃값으로 예측을 출력해보자.
Kn.predict(test_scaled[:5])
array(['Perch', 'Smelt', 'Pike', 'Perch', 'Perch'], dtype=object)
predit_proba()메소드는 클래스별 확률값을 반환한다.
import numpy as np
proba = Kn.predict_proba(test_scaled[:5])
print(np.round(proba, decimals=4) #np.round() = 반올림 , decimals = n >>소수 n번째 자리까지 표시
해석 => 첫 번째 열 : 'Bream'일 확률, 두 번째 열 : 'Parkki'일 확률 ,,,,,,,이다.
확률을 봤으니 직접 샘플의 최근접 이웃 (3개)가 무엇인지 살펴보자.
distances, indexes = Kn.kneighbors(test_scaled[3:4])
print(train_scaled[indexes])
[['Roach' 'Perch' 'Perch']]
1/3 = 0.33333333 2/3 = 0.66666667
기준 샘플 수가 3개이다 보니 확률이 0, 0.3, 0.6, 1 네 개의 숫자 밖에 나오지 않는다... 더 좋은 방법은 없을까?
로지스틱 회귀
로지스틱 회귀 (logistic regression)는 이름은 회귀이지만 분류 모델이다.
또한 로지스틱 회귀는 선형 회귀와 마찬가지로 선형 방정식을 학습한다.
변수 a,b,c,d,e는 가중치/계수.
z의 값은 0~1로 나오면 확률로 표현할 수 있다. 이를 위해 시그모이드 함수를 사용하면 된다!
import numpy as np
import matplot.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()
정말 0 ~ 1로 출력된다!
# 로지스틱 회귀로 이진 분류 수행해보자
이진 분류이므로 불리언 인덱싱을 통해 해결 ( T / F)
char_arr = np.array(['A','B','C','D','E'])
print(char_arr[[True,False,True,False,False]])
['A' 'C']
위와 같은 방식을 통해 훈련 세트에서 도미,빙어의 행만 골라 내자
bream_smelt_indexes = (train_target == "Bream" ) | (train_target == "Smelt")
train_bream_smelt = train_scaled[bream_smelt_indexes]
target_bream_smelt = train_scaled[bream_smelt_indexes]
# | = or 과 같음
위 코딩 => 도미,빙어에는 True값이 들어가있고 나머지는 모두 False가 들어가 있다.
따라서 이 배열을 사용해 train_scaled와 train_target 배열에 불리언 인덱싱을 적용하면
손쉽게 도미와 빙어 데이터만 골라낼 수 있을것 같다.
이제 준비된 데이터로 로지스틱 회귀 모델을 훈련해보자.
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']
두 번째 샘플을 빼고 모두 도미로 예측했다.!
KNeighborsClassifier()과 마찬가지로 예측확률은 preidct_proba() 메소드에서 제공한다.
lr.predict_proba(train_bream_smelt[:5])
array([[0.99759855, 0.00240145],
[0.02735183, 0.97264817],
[0.99486072, 0.00513928],
[0.98584202, 0.01415798],
[0.99767269, 0.00232731]])
샘플마다 두개의 확률이 출력되었다. !! 첫 번째 열 = 음성 클래스(0), 두 번째 열 = 양성 클래스(1)
무엇이 0, 1인지는 classes_ 를 통해 알아보자.
lr.classes_
array(['Bream', 'Smelt'], dtype=object)
빙어가 양성이다 !
이제 계수까지 확인해보자.
print( lr.coef_, lr.intercept_ )
[[-0.4037798 -0.57620209 -0.66280298 -1.01290277 -0.73168947]] [-2.16155132]
이 계수를 통해 보면 방정식은 다음과 같다.
위 방정식에서 z값을 구해보고싶다!!
= decision_function()메소드로 출력할 수 있다.
lr.decision_function(train_bream_smelt[:5])
array([-6.02927744, 3.57123907, -5.26568906, -4.24321775, -6.0607117 ])
이 z값을 시그모이드 함수에 통과시키면 확률을 얻을 수 있다!!
파이썬의 사이파이 라이브러리를 통해 시그모이드함수(expit()) == np.exp()함수를 이용할 수 있다.
from scipy.special import expit
expit(decision)
[0.00240145 0.97264817 0.00513928 0.01415798 0.00232731]
predict_proba()메소드를 사용했을 때의 두 번째 열과 동일하다.
즉, decision_function() 메소드는 양성 클래스(빙어)에 대한 z값을 반환함을 알 수 있다.
이제 다중 분류 문제로 넘어가보자.
로지스틱 회귀로 다중 분류 수행하기
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)
0.9327731092436975
0.925
처음 5개 샘플에 대한 예측을 출력해보자.
lr.predict(test_scaled[:5])
array(['Perch', 'Smelt', 'Pike', 'Roach', 'Perch'], dtype=object)
이번에는 테스트 세트의 처음 5개 샘플에 대한 예측확률을 출력해보자!
proba = lr.predict_proba(test_scaled[:5])
np.round(proba, decimals = 3)
array([[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]])
5개 샘플에 대한 예측이므로 5개의 행이 출력, 7개의 생선에 대한 확률을 계산했으므로 7개의 열이 출력되었다.
첫 번째 샘플을 보면 세 번째 열이 가장 높다. (Perch:농어)
lr.classes_
array(['Bream', 'Parkki', 'Perch', 'Pike', 'Roach', 'Smelt', 'Whitefish'],
dtype=object)
3번째 열이 농어임을 확인!!!
이제 다중 분류일 경우의 선형방정식을 살펴보자.
소프트맥스함수
시그모이드함수는 하나의 선형방정식의 출력값을 0~1로 반환하는 반면,
소프트맥스함수는 여러개의 방정식의 출력값을 0~1로 압축하고 전체합이 1이 되게한다.
소프트맥스함수를 정규화된 지수함수라고 부르기도 한다.
먼저 decision_function()메소드를 통해 z1 ~ z7까지의 값을 구하고,
소프트맥스함수를 이용해 확률로 바꿔보자.
decision = lr.decision_function(test_scaled[:5])
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]]
from scipy.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]
[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]]
앞서 구한 decision()배열을 softmax함수에 전달했다.
axis= 의 매개변수는 소프트맥스를 계산할 축을 지정한다.
여기서는 각 행(샘플)에 대해 소프트맥스를 계산한다. !
'머신러닝 & 딥러닝 기초 > 4장 - 다양한 분류 알고리즘' 카테고리의 다른 글
4 - 2 확률적 경사 하강법 (0) | 2023.01.05 |
---|