🌵 02-1 훈련 세트와 테스트 세트

지도 학습 (supervised learning)

훈련 세트와 테스트 세트

샘플링 편향 (sampling bias)

💚 02-1 Code

훈련 세트와 테스트 세트를 나누어 머신러닝 모델 구축하기

# 도미와 빙어의 데이터를 합쳐 하나의 파이썬 리스트로 준비하기
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]
                
# 각 생선의 길이와 무게를 한 번에 담은 2차원 리스트 생성 
fish_data = [[l,w] for l,w in zip(fish_length, fish_weight)]
fish_target = [1]*35 + [0]*14

# 이 데이터의 처음 35개를 훈련 세트로, 나머지 14개를 테스트 세트로 사용한다

from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()

train_input = fish_data[:35] # 훈련세트 입력
train_target = fish_target[:35] # 훈련세트 정답
test_input = fish_data[35:] # 테스트세트 입력
test_target = fish_target[35:] # 테스트세트 정답

# 모델 훈련 및 정확도 평가
kn.fit(train_input, train_target)
kn.score(test_input, test_input)

# 정확도가 0이 나온다?

샘플링 편향을 방지하기 위해 넘파이 라이브러리 사용하기

# 넘파이는 파이썬의 대표적인 배열 라이브러리로, 고차원의 배열을 손쉽게 만들고 조작할 수 있는 간편한 도구들을 제공한다.

# array 함수를 사용해 파이썬 리스트를 넘파이 배열로 변환하기
input_arr = np.array(fish_data)
target_arr = np.array(fish_target)
print(input_arr.shape) #(샘플 수, 특성 수) 출력 

# 무작위로 샘플 고르기 (이때, 입력과 타깃은 함께 선택되어야 한다)
# 아예 인덱스 번호를 섞은 다음, input_arr와 target_arr 에서 샘플을 선택하는 방식 사용

# 넘파이의 arange 함수 사용해서 0에서부터 48까지 1씩 증가하는 인덱스 만들기
np.random.seed(42)
index = np.arange(49)
np.random.shuffle(index) #0부터 48까지의 정수가 잘 섞였다

# 섞인 인덱스 배열에서 처음 35개를 전달하여 훈련 랜덤 샘플 만들기
train_input = input_arr[index[:35]]
train_target = target_arr[index[:35]]

# 마찬가지로 테스트 랜덤 샘플 만들기
test_input = input_arr[index[35:]]
test_target = target_arr[index[35:]]

두 번째 머신러닝 프로그램 만들기

kn.fit(train_input, train_target)
kn.score(test_input, test_target)
# 정확도 1.0 달성!

kn.predict(test_input)
test_target
# 두 코드의 결과가 완전히 일치하는 것을 확인할 수 있다

🌵 02-2 데이터 전처리

💚 02-2 Code

넘파이로 데이터 준비하기

# 이번에는 파이썬 함수 말고 넘파이를 이용해서 2차원 리스트를 생성한다(입력 데이터)
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]

import numpy as np
fish_data = np.column_stack((fish_length, fish_weight))
#column_stack 함수는 전달받은 리스트를 일렬로 세운 다음 차례대로 나란히 연결, 파이썬 튜플로 전달함

# 넘파이를 이용해 정답 데이터도 생성한다(1 35개, 0 14개)
fish_target = np.concatenate((np.ones(35), np.zeros(14)))

사이킷런으로 데이터 분리하기

# train_test_split() 함수
# 전달되는 리스트나 배열을 비율에 맞게 훈련 세트와 테스트 세트로 나눠줌 (알아서 섞어줌)

from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target, random_state=42)
# 기본적으로 25%를 테스트 세트로 떼어 낸다

print(train_input.shape, test_input.shape) #shape 속성: 크기 

# 클래스 비율에 맞게 데이터를 분리하고 싶다면, stratify 속성에 타깃 데이터를 전달하면 된다
train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target, stratify = fish_target, random_state=42)

수상한 도미 한 마리

# 넘파이, 사이킷런으로 준비한 데이터로 1장과 똑같이 모델을 훈련, 평가한다
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_input, train_target)
kn.score(test_input, test_target) #정확도 1.0

# 도미 데이터를 넣고 결과를 확인해본다
kn.predict([[25,150]]) # 빙어로 예측. 왜 그럴까?

# 어떤 문제가 있는 것인지 훈련 데이터를 산점도로 나타내본다
import matplotlib.pyplot as plt
plt.scatter(train_input[:,0], train_input[:,1]) # 모든 행에서 각각 0과 1 선택
plt.scatter(25,150,marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show() # 산점도로 보았을 때도 역시 빙어보다는 도미에 더 가까워보임

# 이번에는 수치상으로 가까운 5개의 이웃을 직접 계산해보자, kneighbors 메소드 사용
distances, indexes = kn.neighbors([[25,150]])

# 그리고 이것을 포함해서 산점도를 다시 그려보자(이웃은 마름모로)
import matplotlib.pyplot as plt
plt.scatter(train_input[:,0], train_input[:,1]) # 모든 행에서 각각 0과 1 선택
plt.scatter(25,150,marker='^')
plt.scatter(train_input[indexes,0], train_input[indexes,1], marker='D')
plt.xlabel('length')
plt.ylabel('weight')
plt.show() #빙어가 4개, 도미가 1개

# 4개의 샘플이 빙어인 것을 확인
train_input[indexes] #훈련데이터 중 이웃 인덱스 반환
train_target[indexes] #타깃데이터는 더 명확하다

# 직관적으로 보기에는 도미에 더 가까워보이는데, 왜 빙어일까?

스케일과 데이터 전처리