본문 바로가기
Python/머신러닝+딥러닝 Ⅰ

Logistic_KNN

by Mr.DonyStark 2024. 3. 22.

□ K-최근접 이웃 알고리즘은 주변 이웃의 클래스 비율과 확률을 기반으로 대상을 분류함

그렇다면 렄키백이 있다고 가정하고, 렄키백마다 타겟별 꺼내질 확률은 어떻게 알까?

타겟값이 2개인 이진분류일때는 시그모이드(로지스틱) 함수를 사용하고, 타겟값이 3개 이상인 소프트 맥스일 경우에는 소프트맥스함수를 사용하여, 인풋값의 이웃들에 대한 확률 기반으로 특정 값으로 분류되는 것을 확인할 수 잇음

□ 예제

○ 데이터 호출 및 확인

#데이터 호출 및 확인
import pandas as pd
fish = pd.read_csv("https://bit.ly/fish_csv_data")
print(fish.head(2))

print("\n")
#타겟값 중복값 제거하여 확인
print(pd.unique(fish["Species"]))

 

○ 호출한 데이터셋 인풋/타겟 데이터로 분리

#전처리 : 인풋과 타겟 데이터 분리 후 배열로 저장
fish_input = fish[["Weight", "Length", "Diagonal", "Height", "Width"]]
print(fish_input[:2])

fish_target = fish["Species"].to_numpy()
print(fish_target[:2])

 

○ 분리한 데이터셋 트레이닝 + 테스트 셋으로 분리

#트레이닝, 테스트 세트 분리
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)

 

○ 데이터 스케일링 작업을 통한 전처리 진행

  → 평균과 표준편차를 직접 구해 특성을 표준점수로 바꾸어주는 데이터 스케일링 작업 → StandardScaler

# 트레이닝, 테스트 데이터 전처리
# 평균과 표준편차를 직접 구해 특성을 표준점수로 바꾸어주는 데이터 스케일링 작업 → StandardScaler
from sklearn.preprocessing import StandardScaler

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

 

○ 분류모델 생성 및 학습, 정확도 계산

#k-최근접 이웃분류기 확률예측
#k-최근접 이웃 알고리즘 생성 및 학습
from sklearn.neighbors import KNeighborsClassifier
#모델생성
kn = KNeighborsClassifier(n_neighbors=3) #이웃개수 3개
#모델학습
kn.fit(train_scaled, train_target)
print(f"트레이닝 데이터 학습 점수 : {kn.score(train_scaled,train_target)}")
print(f"테스트 데이터 학습 점수 : {kn.score(test_scaled,test_target)}")

 

○ 분류모델에서 지정한 타겟확인

#사이킷런 모델에 전달하면 순서가 자동으로 알파벳 순으로 정렬됨
print(kn.classes_)

.

○ 테스트데이터 5개 입력을 통한 예측

#5개 데이터 예측진행
kn.predict(test_scaled[:5])

 

 

※ 그렇다면 위 테스트 데이터 5개에 대한 예측은 어떤 확률로 분류되었을까?

※ 사이킷런의 분류모델은 predict_proba(0 메서드로 클래스 분류 확률을 확인 할 수 있음.

 

import numpy as np
proba = kn.predict_proba(test_scaled[:5]) #확률 출력을 위해 predict_proba 메서드 사용
print(kn.classes_)  #속성값 확인
print("\n")
print(np.round(proba, decimals=2)) #소수점 자리수 조정을 위해 decimals 조정, 해당코드에서는 소수점 3자리부터 반올림함

1은 100%를 의미하며 4~5번째는 perch확률과 roach 확률이 출력되었고 출력확률에따라 분류됬음을 유추할 수 있음

 

○ 4번째 테스트 데이터가 어떠한 확률로 perch로 지정되었는지 확인

#네번째샘플에 대한 이웃 인덱스를 활용한 시각화 ★★★

distances, indexes = kn.kneighbors(test_scaled[3:4])
print(train_target[indexes])

#3분의 2확률로 perch

#시그모이드 함수시각화

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()

 

회귀식의 결과값을 0~1사이의 확률값으로 반환하기위해 시그모이드 함수사용

 

※ 로지스틱회귀 : z = [a*(weight) + b*(length) + c*(Diagonal) + d*(height)+ e*(weight)] + f
 로지스틱회귀 값 z를 확률로 변환해주는데 필요한 함수가 시그모이드함수와 소프트맥스가 있음
시그모이드함수(로지스틱함수) : 이진분류를 목표로할때 사용하며, 선형방정식의 출력을 0과 1사이의 값으로 압축함(0~100%)

→ 위에서는 perch와 roach 이진분류에 대한 확률을 위해 시그모이드를 사용하였음

소프트맥스 : 다중분류를 목표로할때 사용하며, 여러 선형 방정식의 출력결과를 정규화하여 합이 1이되도록 만듬(0~100%)

 

○ 이진분류 예제

#이진분류를 위한 데이터 분리
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]

#모델생성 및 학습
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_bream_smelt,target_bream_smelt)

print(lr.classes_)
print(lr.predict(train_bream_smelt[:5]))
print(lr.predict_proba(train_bream_smelt[:5]))

classes_를 통해 타겟이 Bream과 Smelt인것을 확인할 수 있으며 트레이닝 데이터를 통한 예측한 결과를 predict_proba()로 확률을 출력

 

○ 이진분류에서의 기울기와 절편 산출 및 z값 구하기 : decision_function()

print(f"회귀계수:{lr.coef_}, 절편:{lr.intercept_}")

#z값 구하기
decisions = lr.decision_function(train_bream_smelt[:5])
print(f"z값 : {decisions}")

 

○ 이진분류에서의 시그모이드 함수기반의 확률 반환 : expit()

#이진분류에서의 확률변환 : 시그모이드함수
from scipy.special import expit
print(f"z값 : {decisions}")
print(f"z값에 시그모이드함수 적용 : {expit(decisions)}")

 

○ 다중분류에서의 소프트맥스 함수기반의 확률 반환 : softmax()

#다중분류에서의 확률변환 : 소프트맥스
lr = LogisticRegression(C=20, max_iter=1000) #C규제값 20, 1000번 반복
lr.fit(train_scaled, train_target)
print(f"학습데이터 점수 : {lr.score(train_scaled, train_target)}")
print(f"학습데이터 점수 : {lr.score(test_scaled, test_target)}")

print(lr.predict(test_scaled[:5]))
print(np.round(lr.predict_proba(test_scaled[:5]),decimals=2))

import numpy as np

from scipy.special import softmax
#z값 구하기
decision = lr.decision_function(test_scaled[:5])
print(f"z값 : {np.round(decision,decimals=2)}")
proba = softmax(decision, axis = 1)
print(f"z값 소프트맥스함수 적용\n{np.round(proba,decimals=2)}")

'Python > 머신러닝+딥러닝 Ⅰ' 카테고리의 다른 글

Decision Tree(결정트리 알고리즘)  (0) 2024.03.22
확률적경사하강법  (1) 2024.03.22
규제(L1, L2)와 Ridge, Lasso  (0) 2024.03.15
Multiple Regression(다중회귀)  (0) 2024.03.15
KNN_Regression&LinearRegression  (1) 2024.03.13