greatsangho의 이야기

캠프 20일차 - 머신러닝(분류와 로지스틱 회귀) 본문

프로그래밍/SK AI 캠프

캠프 20일차 - 머신러닝(분류와 로지스틱 회귀)

greatsangho 2024. 9. 23. 18:33

# 분류
  - 특성 - feature로 묶음
  - k 최근접 이웃

 

KNN(K-최근접 이웃)

# 학습
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(fish_data, fish_target)
kn.score(fish_data, fish_target)
sns.scatterplot(data=df, x='length', y='weight', hue='target')
plt.scatter(x=30,y=600,color='blue', marker='^')
plt.scatter(x=10,y=100,color='red', marker='^')

kn.predict([[30, 600],[10,100]]) # 데이터 학습할 때의 모양으로 넣어줌

 

# 파라미터의 n_neighbor의 값에 따른 성능변화
# n_neighbor의 개수를 전체 데이터로 한다면?
kn49 = KNeighborsClassifier(n_neighbors=49)
kn49.fit(fish_data, fish_target)
# 성능
print(kn49.score(fish_data,fish_target))
print(f'전체데이터 중에 35개만 맞출 확률 : {35/49}')
print(f'전체데이터를 예측데이터로 넣으면 모델이 예측한 정답은 : {kn49.predict(fish_data)}')
print('무조건 클래스 1만 예측했음')

"""
0.7142857142857143
전체데이터 중에 35개만 맞출 확률 : 0.7142857142857143
전체데이터를 예측데이터로 넣으면 모델이 예측한 정답은 : [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1]
무조건 클래스 1만 예측했음
"""

k-최근접 이웃에서 이웃의 범위를 너무 넓히면 다음과 같이 score 값을 신뢰할 수 없다.

모델의 정확도만 보고 성능이 어느 정도 나온다고 할 수 없다. 전체 데이터 중 대부분의 값이 같은 정답일 경우 하나의 값으로 예측해도 정확도가 높게 나오게 된다. 하지만 소수의 값을 찾아야 하는 경우 이러한 예측은 유의미하지 못하다.

 

# 데이터를 섞는 이유

# 데이터는 샘플링 편향 없이 클래스들이 잘 섞여서 학습을 해야 여러 특성을 골고루 반영한다

올바른 데이터 분류

target을 비율대로 잘 섞어주는 것이 좋다.

# 데이터는 셈플링 편향 없이 클래스들이 잘 섞어서 학습을 해야.. 여러 특성을 골고루 반영한다.

 

사이킷런의 데이터 분류 사용하기

from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(fish_data,fish_target,test_size=0.2, stratify=fish_target)

데이터 표준화

데이터를 표준화해보자. 삼각형을 보면 오른쪽 군집에 포함될 것처럼 보인다. 하지만 이를 KNN 사용해 분석하면 다음과 같이 초록색을 이웃으로 판단한다. 그 이유는 스케일이 x축은 40까지인 것에 비해 y축은 1000에 해당하여 세로로 늘어선 그래프처럼 보이기 때문이다.

StandardScaler()는 데이터의 표준편차를 건드리지 않으면서 데이터를 바꾸게 된다.

from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
x_train_scaled = ss.fit_transform(x_train)

스케일링 후 다시 확인해 보면 오른쪽 군집을 이웃으로 판단하는 것을 확인할 수 있다.

 

로지스틱 회귀, SVC

# 계단 함수
    # 입력데이터를 0 과 1로 만 출력
# 시그모이드 함수(sigmoid function; logistic function)
    # 선형회귀 출력값을 0 ~ 1 사이로 변경 --> 확률로 해석
    # x는  y = wx +b
    # 클래스 1에 속할 확률이 p(x) = 0.8
    # 임계치가 존재... 임계치 이상이면 1 아니면 0  보통은 0.5
# 손실함수(로그손실)
    # log loss, cross entropy
    # 실제 값과 예측값의 차이를 나타내는 함수 -> 차이를 최소화 하는 방향으로 학습
    # 경사 하강법 - 최적화 : 손실함수의 값이 최소가 되는 방향을 찾아서 원래 가중치를 갱신
# 학습 횟수 : epoch
    # 에포크 : 전체데이터를 한번 사용해서 학습
# 학습률 : learning late
    # 한번에 경사를 내려가는 보폭의 크기

 

로지스틱 회귀는 시그모이드를 사용하는 '분류 모델'이다.

# 시그모이드 함수
def sigmoid(x):
    return 1/(1 + np.exp(-x))
# 이진분류 데이터 생성
from sklearn.datasets import make_classification
X,y = make_classification(n_samples=100,n_features=4,n_classes=2,random_state=42)
print(X.shape, y.shape)
x_train,x_test,y_train,y_test = train_test_split(X,y,stratify=y,random_state=42)

from sklearn.linear_model import LogisticRegression
model_logistic =  LogisticRegression(); model_knn = KNeighborsClassifier()
model_logistic.fit(x_train,y_train); model_knn.fit(x_train,y_train)

model_logistic.score(x_test,y_test), model_knn.score(x_test,y_test)

 

데이터셋 분석하기

# 탐색적 데이터 분석
    # 주로 시각화를 통해 데이터의 분포 형태 모양
# 데이터를 전처리
# 피처엔지니어링(적합한 피처 선택(논리적/도메인지식) or 파생피처 생성(도메인지식))
# 모델선택
# 학습
# 평가
# 모델 채택

 

import seaborn as sns
sns.countplot(data=cardio,x='cardio')

countplot으로 타겟 데이터 분포 확인

 

sns.scatterplot(data=cardio, x='height',y='weight',hue='cardio')

Scatterplot으로 전반적인 분포 확인

전처리 진행 -> fit -> predict -> classification_report

이런 순서로 진행한다.

반응형