🐻 04-1 로지스틱 회귀

<aside> 🐴 럭키백에 들어갈 수 있는 생선은 7개! 럭키백에 들어간 생선의 크기, 무게 등이 주어졌을 때 7개 생선이 들어있을 각각의 확률을 출력해야 한다!

</aside>

<aside> 🐴 길이, 높이, 두께 외에도 대각선 길이무게를 사용한다.

</aside>

🥥 04-1 Code

데이터 준비하기

# 라이브러리 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 판다스를 이용해 인터넷에서 데이터 불러오기
fish = pd.read_csv('<https://bit.ly/fish_csv_data>')
fish.head #상위 5개만 보기
#무게, 길이, 대각선길이, 두께, 너비

# 어떤 종류의 생선이 있는지 unique 함수로 알아보기
pd.unique(fish['Species'])

# 종(species)를 타깃으로, 나머지 특성 5개를 입력데이터로 사용한다.
# 입력데이터가 되는 열 5개를 추출한다.
# 넘파이 배열로 바꾸어서 저장한다.

fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
fish_input[:5] #처음 5개 행 출력하기

# 똑같은 방식으로 Species 열을 선택하여 타깃 데이터를 만든다.
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-최근접 이웃 분류기의 확률 예측

# 모델 훈련 후 훈련 세트와 테스트 세트 점수 확인하기 (k=3)

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

<aside> 🐴 현재 타깃 데이터에는 7개의 생선이 들어가있다. 이렇게 타깃 데이터에 2개 이상의 클래스가 포함된 문제를 다중 분류라고 부른다.

</aside>

<aside> 🐴 이진 분류를 사용했을 때는 클래스를 각각 1과 0으로 지정하여 타깃 데이터를 만들었다. 하지만 편리하게도 사이킷런에서는 문자열로 된 타깃값을 그대로 사용할 수 있다.

이때 주의할 점: 타깃값을 그대로 사이킷런 모델에 전달하면 순서가 자동으로 알파벳 순서대로 매겨진다.

</aside>

# 테스트 세트에 있는 처음 5개 샘플값의 타깃값 예측하기
kn.predict(test_scaled[:5])

# predict_proba()메서드로 클래스별 확률값 반환하기
proba = kn.predict_proba(test_scaled[:5])
np.round(proba, decimals=4)

# 모델이 계산한 확률이 가장 가까운 이웃의 비율이 맞는지 확인해보기
# 네 번째 샘플 하나를 선택한다
distances, indexes = kn.kneighbors(test_scaled[3:4])
train_target[indexes] #0.6667 (동일)

<aside> 🐴 그러나, 3개의 최근접이웃을 사용하기 때문에 가능한 확률은 0/3, 1/3, 2/3, 3/3이 전부이다. 럭키백의 확률을 이렇게만 표기한다면 확률이라고 하기에는 애매한 상황이 펼쳐진다. 더 좋은 방법을 찾을 수는 없을까?

</aside>

로지스틱 회귀

로지스틱 회귀(Logistic Regression)

<aside> 🐴 z 값은 모든 실수가 가능하다. 그러나 확률로 정의하기 위해 0과 1 사이로 변환하는 과정이 필요하다. 따라서 시그모이드 함수를 이용한다.

</aside>

시그모이드 함수(sigmoid function)

$$ \sigma(x) = \frac{1}{1 + e^{-x}} $$

# 넘파이 사용하여 시그모이드 함수 그래프 간단히 그려보기
# -5와 5 사이에 0.1 간격으로 배열 z를 만들고 z 위치마다 시그모이드 함수를 계산한다.

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

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

<aside> 🐴 로지스틱 회귀 분석 수행: Logistic Regression 클래스

</aside>

<aside> 🐴 이진 분류일 경우 0.5보다 크면 양성 클래스, 0.5보다 작으면 음성 클래스로 분류한다.

</aside>