Ch2에서는 지도학습을 공부하고 데이터 전처리의 필요성에 대해 공부합니다.
지도학습은 훈련데이터와 정답데이터를 통해 학습하는 머신러닝 방법입니다.
반면 비지도학습은 따로 정답이 없고 입력데이터만을 사용해 학습합니다.
지도학습에 필요한 훈련데이터를 만드는 방법은 두가지가 있습니다.
1. 충분한 양의 데이터가 있는 경우 훈련데이터를 따로 마련한다.
2. 한정된 양의 데이터로 훈련하는 경우 입력 데이터의 일부를 훈련데이터와 테스트데이터로 나눈다.
데이터를 분리할 때는 적절히 섞어서 편향이 없게끔 해줘야 합니다.
예를 들어 Ch1에서 도미와 빙어 데이터를 합쳤었는데 만약 훈련데이터는 전부 도미만 있고
테스트데이터에는 빙어만 있다면 0%의 효율을 내게 되겠죠.
사이킷런의 train_test_split() 함수는 이런걸 모두 수행해줍니다.
train_input, test_input, train_target, test_target=train_test_split(
fish_data, fish_target, stratify=fish_target, random_state=42)
train data와 test data가 잘 분리되어 있는지 산점도를 찍어봅시다.
train_input=np.array(train_input)
test_input=np.array(test_input)
plt.scatter(train_input[:, 0], train_input[:, 1])
plt.scatter(test_input[:, 0], test_input[:, 1])
plt.show()
편향없게 골고루 분리되었음을 확인했습니다. 이제 마지막 문제점만 남았습니다.
KNN 알고리즘은 거리기반의 알고리즘인데 x축과 y축을 보면 단위가 달라서 거리 계산시 값이 더 큰
y값에 의존하게 됩니다. 따라서 데이터 전처리를 통해 값들을 정규화시켜줄 필요가 있습니다.
numpy의 평균과 표준편차 계산으로 정규화를 시켜줍시다.
mean과 std 함수는 각각 평균과 표준편차를 구해주고, axis=0일 땐 한 열의 평균/표준편차 값을,
axis=1일 땐 한 행의 평균/표준편차값을 알려줍니다.
우리는 49*2 행렬에서 두 열이 각각 길이와 무게인 상태이므로 axis=0일 때 값을 구해줍니다.
mean=np.mean(train_input, axis=0)
std=np.std(train_input, axis=0)
train_scaled=(train_input-mean)/std
numpy의 브로드캐스팅 기능을 통해 매우 쉽게 구현할 수 있습니다.
일반적으로 다른 차원간 연산은 불가능하지만, 일정조건을 만족하면 넘파이가 잘 알아듣습니다.
이제 마지막으로 테스트 데이터를 정규화하여 평가해봅시다.
kn=KNeighborsClassifier()
kn.fit(train_scaled, train_target) # 훈련
test_scaled=(test_input-mean)/std # 정규화
print(kn.score(test_scaled, test_target)) # 평가치
print(test_input)
print("정답: ", kn.predict(test_scaled)) # 구체적 결과
결과를 확인해보면,
1.0
[[ 11. 9.7]
[ 11.8 9.9]
[ 29.7 450. ]
[ 11.8 10. ]
[ 26.5 340. ]
[ 12.4 13.4]
[ 34. 685. ]
[ 34. 575. ]
[ 38.5 920. ]
[ 35. 680. ]
[ 26.3 290. ]
[ 31. 500. ]
[ 41. 950. ]]
정답: [0 0 1 0 1 0 1 1 1 1 1 1 1]
모델의 테스트 성능은 1.0으로 완벽하고 각 테스트 데이터에 따른 예측 결과를 보여줍니다.
0이 나오는 쪽은 길이와 무게가 매우 작은걸 보면 빙어로 잘 분류되었네요.
오늘 배운 중요한건 데이터 전처리의 중요성과 넘파이와 사이킷런 데이터 분리입니다.
전체 코드입니다.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
fish_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0,
31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0,
35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0, 9.8,
10.5, 10.6, 11.0, 11.2, 11.3, 11.8, 11.8, 12.0, 12.2, 12.4, 13.0, 14.3,15.0]
fish_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0,500.0,
500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0,
700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0, 6.7,
7.5, 7.0, 9.7, 9.8, 8.7, 10.0, 9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9]
fish_data=[[l,w] for l,w in zip(fish_length, fish_weight)]
fish_target=[1]*35+[0]*14
train_input, test_input, train_target, test_target=train_test_split(
fish_data, fish_target, stratify=fish_target, random_state=42)
train_input=np.array(train_input)
test_input=np.array(test_input)
plt.scatter(train_input[:, 0], train_input[:, 1])
plt.scatter(test_input[:, 0], test_input[:, 1])
plt.show()
# 평균과 표준편차 구해서 정규화 시킴
mean=np.mean(train_input, axis=0)
std=np.std(train_input, axis=0)
train_scaled=(train_input-mean)/std
plt.scatter(train_scaled[:,0], train_scaled[:, 1])
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
kn=KNeighborsClassifier()
kn.fit(train_scaled, train_target) # 훈련
test_scaled=(test_input-mean)/std # 정규화
print(kn.score(test_scaled, test_target)) # 평가치
print(test_input)
print("정답: ", kn.predict(test_scaled)) # 구체적 결과
'CS > 머신러닝' 카테고리의 다른 글
혼자 공부하는 머신러닝 + 딥러닝 - Ch3-2 (0) | 2023.01.08 |
---|---|
혼자 공부하는 머신러닝 + 딥러닝 - Ch3-1 (0) | 2023.01.08 |
혼자 공부하는 머신러닝 + 딥러닝 - Ch1 (0) | 2023.01.04 |
로지스틱 회귀 (0) | 2022.12.20 |
선형 회귀 - 경사 하강법 (0) | 2022.12.02 |
댓글