cs

언제나 첫 스텝이 어려운법..

약간 늦더라도, 꾸준히 천천히 쭈욱 가야한다. 

 

다시, 남은 한해동안 목표한 리스트를 보면서 힘내보자아!!

 

아직 3개월 남았다!!   


정말 오래간만에 다시 포스팅을 하긴 하나보다, 진도를 많이 놓친 느낌 ㅎ 

 

암튼 지난 포스트에서는 k-mean을 사용하여 간단하게 분류 예측을 해보았는데, 당연히 문제가 있었던 분류예측모델이였다. 

 

이유는 간단하다.

 

문제에 사용되는 데이터를 모두 때려넣고 저장한 뒤 맞추는건 100%정답이지 않을까? 문제 안에서 고르는건데? 

 

차근차근 기본부터 나아가보자.  (다 안다고, 대충 안다고 절대 자만하지말고 다시 복습하자고! )

 

지도 학습과 비지도 학습

먼저, 머신러닝 알고리즘은 크게 두가지로 나뉜다.

 

지도학습과 비지도 학습으로 나뉘는데, 단어에서 보이듯 대충 감이 온다. 

 

아래의 이미지를 참고해보자면, 

https://medium.com/@dkatzman_3920/supervised-vs-unsupervised-learning-and-use-cases-for-each-8b9cc3ebd301

 

지도학습(Supervised Learning)의 경우 정답이 있는 데이터를 가지고 학습을 시키는 방식이고 (Task Driven)

 

비지도학습(Unsupervised Learning)의 경우에는, 정답이 없는 데이터를 가지고, 오로지 데이터를 넣어서 정답을 찾는 방식이라고 생각하면 쉽다. (Data Driven)

 

 

특히 지도학습의 경우에는 데이터와 정답을 입력(input)타깃(target)이라고 하며, 이 둘을 하나로 훈련데이터(trainning data)라고 보면 된다.

 

그리고 input으로 사용된 길이와 무게는 특성(feature)라고 부른다. 

 

 

다시한번 정리해보자. 

  • Supervised Learning: 정답이 있어, 알고리즘이 정답을 맞추는 것을 학습
  • Unsupervised Learning: 알고리즘이 target없이 input 데이터만을 사용함 (정답을 맞출 수 없지만 데이터 파악과 변형하는데 도움을 줌)

 

훈련 세트와 테스트 세트

만약에, 중간고사를 봐야하는데 학교 선생님이 출제될 시험 문제를 다 미리 알려주면 무조건 100점을 맞을거다.

(아닌 사람도 가끔 있었음)

 

첫번째 포스팅에서의 문제점이 그것이다. 

 

연습문제랑 시험문제가 달라야 올바르게 알고리즘의 성능을 평가 할 수 있을 것이다. 

 

그래서 가장 간단한 방법은, 연습문제, 즉 준비된 데이터 셋에서 일부를 떼어서 활용하는 것이다. 

 

그래서 평가에 사용하는 데이터를 테스트 셋(Test set)이라고 하고, 훈련에 사용 되는 데이터를 훈련 세트(Train set)라고 부른다. 

 

파이썬으로 직접 해보자.

 

파이썬 예제 

지난 포스트와 같이 생선의 길이와 무게를 위한 리스트를 가지고오고, 

 

생선의 길이와 무게를 하나의 리스트로 담은 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]
                

fish_data = [[l, w] for l, w in zip(fish_length, fish_weight)]
fish_target = [1]*35 +[0]*14

 

위에서 만들어진 데이터 하나하나를 샘플이라고 생각하며, 전체 데이터는 도미 35마리, 빙어 14마리로 49개 샘플이 있다. 

 

위에서 사용한 feature는 당연히 무게와 길이. 

 

이 데이터에서 처음 35개를 훈련, 14개를 테스트 셋으로 사용한다고 한다?..(그래 차근차근 가보자구)

 

다음 단계 하기 전에 간단하게 인덱스와 슬라이싱이라는 연산자를 알려준다. 

 

# 인덱스 방식
print(fish_data[4])

# 슬라이싱 방식
print(fish_data[0:5])

인덱스 방식으로는 정확하게 n번째의 샘플을 출력 할 수 있고, 

 

슬라이싱 방식으로는 범위를 설정하여 여러 샘플을 가지고 올 수 있다. 

 

그럼 슬라이싱 방식으로 train set을 구성해보자.

 

# 훈련 세트로 입력값중 0부터 34번째 인덱스까지 사용 
train_input = fish_data[:35]

# 훈련 세트로 타깃값중 0부터 34번째 인덱스까지 사용
train_target = fish_target[0:35]

# 테스트 세트로 입력값중 35번째부터 마지막 인덱스까지
test_input = fish_data[35:]

# 테스트 세트로 타깃값 중 35번부터 마지막까지 
test_target = fish_target[35:]

 

그럼 지난 포스트처럼 다시, k-최근접 이웃 (k-Nearest Neighbors) 알고리즘을 활용해봅시다!

 

from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()

kn = kn.fit(train_input, train_target)
kn.score(test_input, test_target)

 

스코어를 체크해보니..! 당연하게도 0점이 나와버린다ㅎㅎ

 

이유는 훈련세트와 테스트세트가 나뉘어지지 않아, 샘플링편향이 되었기 때문이다.

 

샘플링 편향 

처음 35개의 도미, 그리고 14개의 빙어를 순서대로 테스트셋과 훈련셋으로 만들어 놓으니,  훈련세트에는 빙어가 하나도 없었던 것이다. ㅎㅎ (정말 차근차근이라 뭔가 더 좋음..)

 

샘플링 편향(sampling bias)는 train set과 test set의 샘플이 골고루 섞여 있지 않으면 나타나는, 샘플링이 한쪽으로 치우처진 현상을 말한다. 

 

그러면, 데이터를 섞어서 혹은 골고루 샘플을 뽑아 훈련셋과 테스트셋을 나누어야하는데 , 책에선 강력히 넘파이를 추천했다. 

 

현제 리스트 형식인 셋을 배열형태, array형태로 바꾸게되면 편리한점이 많다고 하니 일단 변환시켜보자. 

 

input_arr = np.array(fish_data)
target_arr = np.array(fish_target)

print(input_arr.shape)

shape를 통해 속성을 확인해보면

 

(49, 2) 

 

가 나오는데, 샘플의 수와, 특성 수를 한번에 확인이 된다. 

 

그럼 배열이 준비되었으니, 랜덤하게 만들어봅시다. 

 

np.random.seed(42) #책과 동일한 결과를 얻게 하려고 랜덤 시드 42를 설정해줌 
index = np.arange(49) #arange 함수는 0부터 48까지 1씩 증가하는 인덱스를 만든다 
np.random.shuffle(index) #index를 랜덤하게 셔플해준다

print(index)

책과 동일하게 만들어주었다.

넘파이에서는 배열 인덱싱 기능을 통해서 1개의 인덱스가 아닌 여러 인덱스로도 원소를 여러개 선택 가능하다. 

 

비슷하게 리스트 대신에 넘파이 배열을 인덱스로도 전달이 가능하기 때문에 인덱스 배열 처음 35개를 input_arr, target_arr에 전달하고 랜덤한 훈련셋을 만들 수 있다.

 

이렇게 되면 인덱스의 첫번째 값이 13이기 때문에, train_input 첫번째 원소는 input_arr의 14번째 값이 있어아야한다. 

 

그리고 나머지 14개를 테스트로도 만들어주쟈 .

 

train_input = input_arr[index[:35]]
train_target = target_arr[index[:35]]

test_input = input_arr[index[35:]]
test_target = target_arr[index[:35]]

 

간단하게 플롯을 그려서 잘 섞인건지 확인이 필요하다.

 

plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(test_input[:,0], test_input[:,1]) #2차원 배열은 행과 열 인덱스를 ,로 나눔

plt.xlabel('length')
plt.ylabel('weight')
plt.show()

섞였으니, 모델을 적용해봐?,,,

 

kn = kn.fit(train_input, train_target)
kn.score(test_input, test_target)

결과는 놀랍게도? (1.0)이 나와버렸다.ㅎㅎ

 

문제는 많지만, 어떤 문제가 있는지는 다음 포스트에서 다시 보쟈 ㅋㅋㅋ 

+ Recent posts