코딩헤딩

[ML(머신러닝)] 머신러닝 기초 3-1 <훈련 및 테스트 분류(numpy 셔플링)> 본문

머신러닝 | 딥러닝

[ML(머신러닝)] 머신러닝 기초 3-1 <훈련 및 테스트 분류(numpy 셔플링)>

멈머이 2023. 12. 21. 20:27
728x90

<훈련, 검증, 테스트 데이터 분류 시 주로 사용되는 변수명>

 - 정의된 변수 이름은 없음
 - 훈련데이터 : 훈련(fit)에 사용되는 데이터
             : (훈련 독립변수) train_input, train-x, X_train
             : (훈련 종속변수) train_target, train_y, Y_ train
 - 검증데이터 : 훈련 정확도(score)에 사용되는 데이터
             : (검증 독립변수) val_input, val-x, X_val
             : (검증 종속변수) val_target, val_y, Y_ val
 - 테스트데이터 : 예측(predict)에 사용되는 데이터
             : (테스트 독립변수) test_input, test-x, X_test
             : (테스트 종속변수) test_target, test_y, Y_ test

 

앞으로 변수의 이름은 위와 같이 통일한다. 


<데이터 분류 순서>
 1. 훈련과 테스트를 비율로 먼저 나누기
   - 훈련과 테스트 비율 : 주로 7:3으로 사용, 또는 7.5:2.5 또는 8:2
 2. 훈련과 검증 데이터 나누기
   - 훈련과 검증 비율 : 주로 4:2 또는 6:2를 사용
 3. 가장 많이 사용되는 훈련 : 검출 : 테스트 비율 대략  =>  6:2: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]

 

* 훈련에 사용할 2차원 데이터 형태로 만들기

fish_data = [ [l,w]for l,w in zip(fish_length, fish_weight)]
print(fish_data)
len(fish_data)

 

 

* 종속변수 정의하기

fish_target = [1]*35 + [0]*14
print(fish_target)
len(fish_target)

 - 도미 : 방어 = 1 : 0
 - 이진분류에서 찾고자 하는 값을 1로 정의 하는것이 일반적 개념.
 - 다만, 어떤 값을 사용하여도 무관.

 

* 훈련데이터(train)및  테스트데이터(test)로 분류하기 

# - 훈련 독립변수
train_input = fish_data[:35]
            
# - 훈련 종속변수
train_target = fish_target[:35]

print(len(train_input),len(train_target))

# - 훈련 독립변수
test_input = fish_data[35:]
            
# - 훈련 종속변수
test_target = fish_target[35:]

print(len(test_input),len(test_target))

결과 : 35 35

          14 14

 

* 모델 생성하기

  * 라이브러리 정의

from sklearn.neighbors import KNeighborsClassifier

 

* 모델 훈련시키기

kn.fit(train_input, train_target)
kn

 - 훈련데이터 적용

 

* 훈련 정확도 검증하기

# - 훈련데이터 사용 abs
train_score = kn.score(train_input, train_target)

# 검증하기 : 검증정확도
# - 테스트 데이터 사용
test_score = kn.score(test_input, test_target)

train_score, test_score

결과 : (1.0, 1.0)


* <해석>
 - 훈련 정확도가 1이기 때문에 과대적합이 발생했으며, 검증 정확도가 0으로 나타났음  

          ==>  따라서 이 훈련 모델은 튜닝을 통해 성능 향상을 시켜야 할 필요성이 있음

 

<윈인분석>
 - 데이터 분류 시 : 35개의 도미값으로만 훈련을 시켰기 때문에 발생한 문제
     즉, 검증데이터가 0이 나왔다는 것은, 또는 매우 낮은 정확도가 나온 경우, ***데이터에 편향이 발생하였을 가능성이 있다고 의심.
 - 샘플링편향 : 특정 데이터에 집중되어 데이터가 구성되어 훈련이 이루어진 경우 발생하는 현상
     --> 해소방법 : 훈련/검증/테스트 데이터 구성시에 잘 섞어야 한다. (셔플)


* 샘플링 편향 해소하기

import numpy as np


numpy의 셔플링 함수 사용
import numpy as np

 

* 넘파이 배열 형태로 변형하기

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


* 데이터 개수 확인하기

input_arr.shape, target_arr.shape

 - shape : 차원을 확인하는 넘파이 속성(행, 열)

 

* 랜덤 하게 섞기

np.random.seed(42)

np.random.shuffle(index)

np.random.shuffle(index)
index

 - random.seed() : 데이터를 랜덤하게 생성할 때 규칙성을 띄도록 정의
                 :             숫자값은 의미 없는 값으로 규칙을 의미 대부분 42를 쓴다.

결과 :array([13, 45, 47, 44, 17, 27, 26, 25, 31, 19, 12,  4, 34,  8,  3,  6, 40,
         41, 46, 15,  9, 16, 24, 33, 30,  0, 43, 32,  5, 29, 11, 36,  1, 21,
         2, 37, 35, 23, 39, 10, 22, 18, 48, 20,  7, 42, 14, 28, 38])

 

* 훈련 및 테스트 데이터 분류하기

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

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

print(train_input.shape, train_target.shape)
print(test_input.shape, test_target.shape)

 

* 산점도 그리기

plt.scatter(train_input[:,0], train_input[:,1], c="red", label="bream")
plt.scatter(test_input[:,0], test_input[:,1], c="blue", label="smeelt")
plt.xlabel("lenght")
plt.ylabel("weight")
plt.legend()
plt.show()

* 예측하기

test_pred = kn.predict(test_input)
print(f"preidct : {test_pred}")
print(f"실제값 : {test_target}")

- predict() : 사용

결과 : preidct : [0 0 1 0 1 1 1 0 1 1 0 1 1 0]
          실제값 : [0 0 1 0 1 1 1 0 1 1 0 1 1 0]

 

* 정확도가 가장 높을 때의 이웃의 개수를 담을 변수

kn = KNeighborsClassifier()
kn
kn.fit(train_input, train_target)
# 정확도가 가장 높을떄의 이웃의 갯수를 담을 변수
nCnt = 0
# 정확도가 가장 낮을떄의 이웃의 갯수를 담을 변수
nScore = 0

for n in range(3, len(train_input),2):
    kn.n_neighbors = n
    score = kn.score(train_input, train_target)
    # print(f"{n} / {score}")

    ### 1보다 작은 정확도인 경우
    if score <1:
        ### nScore의 값이 score보다 작은 경우 담기
        if nScore < score:
            nScore = score
            nCnt = n

print(f"nCnt = {nCnt} / nScore = {nScore}")

 결과 : nCnt = 17 / nScore = 0.7714285714285715

728x90