본문 바로가기

인공지능/머신러닝

[머신러닝ML]머신러닝 실습 - 생선 구분하기(K최근접이웃 모델, KNN)

~ 목차 ~

 
 

목차

1. 머신러닝 실습

2. 데이터 분포 확인하기

3. 생선 분류하기

4. 하이퍼파라메터 튜닝

 


머신러닝 실습  

먼저 문제를 내주고 답을 준다음 학습하도록 한다.

 

 

1. 생선구분하기 K최근접이웃모델

: 분류분석
- 독립변수 : 길이와 무게

- 종속변수 : 도미? 빙어?
- 정답을 만들어야 한다 = 라벨링 작업(머신러닝 중 가장 오래걸리는 작업)

 

2. 라이브러리

- import matplotlib.pyplot as plt

 

3. 데이터 처리

- 빙어와 도미 데이터

- 생선의 종류를 분류(구분)하기 위한 모델 생성을 위해 독립변수와 종속변수로 데이터를 가공해야함

- 독립변수(x) : 길이, 무게

- 종속변수(y) : 생선종류(빙어 또는 도미)

 

< 훈련모델 처리 절차 >

 1. 데이터 전처리
 2. 데이터 정규화(표준화)
 3. 훈련 : 검증 : 테스트 데이터로 분류 ( 또는 훈련 : 테스트 데이터로 분류)
    - 6 : 2 : 2 또는 7 : 2 : 1, 데이터가 작은 경우에는 8 : 2 또는 7 : 3 정도로 분류
 4. 모델 생성
 5. 모델 훈련 (훈련 데이터와 검증 데이터 사용, 또는 테스트 데이터)

     - 훈련(fit)
 6. 모델 평가 (모델 선정, 검증데이터)
 7. 하이퍼파라메터 튜닝
 8. 5번~6번 진행
 9. 최종 테스트 (테스트 데이터 또는 새로운 데이터로 사용)

     - 예측(predict)

 

✨꼭 알아둬야할 단어

 - 모델 훈련 : fit

 - 예측 : predict

 
 

 


 

 

데이터 분포 확인하기 

 

 

1. 데이터 불러들이기 (도미)


    - 도미 길이(cm)
bream_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]

    - 도미 무게(g)
bream_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]

 

2. 데이터 불러들이기 (빙어)

    - 빙어 길이(cm)
smelt_length = [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]

    - 빙어 무게(g)
smelt_weight = [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]

 

3. 산점도 그래프 그리기 (도미)

    - 도미 산점도 그래프 그리기 : scatter()
    - x축에는 길이, y축에는 무게
    - 길이가 길어질수록, 무게가 커질까??
plt.scatter(bream_length, bream_weight)
plt.xlabel("length")
plt.ylabel("weight")
plt.show()

 

4. 산점도 그래프 그리기 (빙어)

    - 빙어 산점도 그래프 그리기 : scatter()
    - x축에는 길이, y축에는 무게
    - 길이가 길어질수록, 무게가 커질까??
plt.scatter(smelt_length, smelt_weight)
plt.xlabel("length")
plt.ylabel("weight")
plt.show()

 

 < 해석🪄 >


  : 길이가 길어질수록, 무게가 커지는 특징을 가지고 있음

  • 분포의 방향은 양(+)의 상관관계를 나타내고 있음
  • 양(+)의 상관관계를 우상향 분포라고 칭한다.
  • 우상향 분포를 선형 형태라고도 칭한다.
  • 모델을 분석하는 입장에서는 선형 형태를 나타낸다고 해석하며,
    → 선형형태에 대한 분석은 회귀분석을 사용.
  • 선형형태 = 회귀분석
    도미와 생선을 구분하기 위한 모델 사용
    구분 = 분류
            분류 모델을 이용해서 진행.
  • 알고 있는 정보 : 길이, 무게, 생선 이름

5. 도미와 빙어의 분포 확인하기(산점도 그리기)

plt.scatter(bream_length, bream_weight, c="lightcoral", label="bream")
plt.scatter(smelt_length, smelt_weight, c="royalblue", label="smelt")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.show()

   - 도미와 빙어 비교
  : 도미와 빙어 모두 우상향 분포를 나타내고 있으며,

    도미 데이터는 경사가 급한 반면, 빙어 데이터는 경사가 완만하게 분포되어 있음.

 

 

도미와 빙어 데이터 산점도 그래프

 


생선 분류하기  

 

 

1. 생선 분류하기(도미와 빙어 구분하기)


    - 회귀분석의 분류모델을 사용

    - K최근접이웃 모델 사용

 

※ KNN: K최근접이웃 모델
   - 머신러닝에서 가장 간단한 모델
   - 비교용으로 주로 사용되는 모델(실제 사용되기에는 성능이 약한 모델)

   - KNN 처리 방식
     : 예측하고자 하는 값과 가장 가까운 이웃 갯수의 비율(또는 평균)을 이용하여,
       비율이 가장 많은 쪽(다수결의 원칙을 따름)의 값으로 판단하는 방식

 

2. 데이터 통합하기

    - 도미와 빙어 데이터를 각각 하나의 길이와 무게 데이터로 통합하기

    - 길이(Length)
length = bream_length + smelt_length
    - 무게(Weight)
weight = bream_weight + smelt_weight

len(length), len(weight)

 

3. 머신러닝에서 사용하는 데이터 차원은 2차원

    - 독립변수(길이와 무게)

       → 독립변수는 2차원 데이터 형태
    - 종속변수(생선이름)
       → 종속변수는 1차원 데이터 형태

    - 독립변수(길이와 무게) 생성하기

          2차원으로 생성 : [[길이, 무게],[길이, 무게]...]

fish_data = [[l, w] for l, w in zip(length, weight)]
len(fish_data)

 

    - 종속변수(생선이름) 생성하기

       →  1차원으로 생성 : ["도미", "도미"..."빙어"]

    - 종속변수로 사용하는 데이터 형태 : 정수형을 주로 사용

        범주 값의 갯수에 따라 :0~n 값을 사용

        이진분류 : 0 또는 1 사용

        다중분류 : 0~n개 사용

     - 이진분류는 찾고자하는 값을 1로 정의하는 것이 일반적 개념.

         도미 : 빙어 = 1 : 0

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

 

4. 모델 생성하기

    - 분류모델
from sklearn.neighbors import KNeighborsClassifier

    - 선형모델
from sklearn.neighbors import KNeighborsRegressor


    - 모델(클래스) 생성시키기

kn = KNeighborsClassifier()
kn

 

5. 모델 훈련(학습)시키기

    - KNN은 지도학습모델 : 독립변수와 종속변수 모두 사용
    - 훈련(학습) 시키는 함수 : fit()
kn.fit(fish_data, fish_target)

 

6. 훈련 정확도 확인하기

  ▶ 모델 훈련(학습)이 잘 되었는지 확인하는 절차
       - score() : 정확도 확인하는 함수
       - 첫번째 값 : 예측하고자 하는 값
       - 두번째 값 : 실제 정답
       -  score()함수는 첫번째 값만 이용해서 훈련모델의 패턴에 적용하여 예측결과를 추출,
         추출된 예측결과와 두번째값(실제 정답)과 비교하여 얼마나 잘 맞추었는지 비교
kn.score(fish_data, fish_target)

 < 해석🪄 >

  : 분류에서의 정확도 : 0~1 사이의 값이 출력됨

  • 0~1 : 0% ~ 100% 정확도를 의미함
  • 훈련에 사용한 데이터를 이용해서 정확도를 확인 했을때 1.0의 정확도 : 과대적합이라고 칭한다.⭐⭐⭐
  • 따라서 보통 정확도 1.0이 나오면 0.9999999로 조절하는 경우가 많음

7. 임의값으로 예측하기

       - 예측 : predict() 함수 사용
       - 예측 시에는 정답은 알려주지 않고, 문제만 넣어 준다.
       - 즉, 문제는 독립변수에 속하며, 2차원 데이터를 사용해야 한다.
       - 훈련에 사용된 독립변수 형태 그대로를 사용해야 한다 ⭐⭐⭐

kn.predict([[30, 600]])

 

출력 : array([1])

    ;도미로 분류됨!!!

 

8. 산점도 그리기

plt.scatter(bream_length, bream_weight, c="lightcoral", label="bream")
plt.scatter(smelt_length, smelt_weight, c="royalblue", label="smelt")
plt.scatter(30, 600, marker="^", c="green", label="pred")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.title("임의 예측 데이터 분포")
plt.show()

 

해석🪄

-  임의 예측 데이터가 분포한 위치를 통해서 시각적으로 확인 가능
-  모델(클래스)이 사용하는 기본 이웃의 값은 5개를 기준으로 한다.(default)

 

 

임의 예측 데이터 분포

 

 

하이퍼파라메터 튜닝  

 

 

< 하이퍼파라메터 튜닝 >
- 모델 성능을 향상시키기 위한 방법
- 과대적합 또는 과소적합이 일어난 경우 튜닝 진행

< 하이퍼파라메터 >
- 모델(클래스)의 속성 중에 사람이 직접 값을 지정해 주어야하는 변수들을 통칭 합니다.

 

 

1. KNN 모델 생성하기

    - n_neighbors : 이웃의 갯수(하이퍼파라메터 속성)

kn20 = KNeighborsClassifier(n_neighbors=20)
kn20

 

2. 모델 훈련 시키기

kn20.fit(fish_data, fish_target)

 

3. 훈련 정확도 확인하기

kn20.score(fish_data, fish_target)

 출력 : 0.9795918367346939

    ; 매우 좋은 성능을 보이는 모델이다라고 표현한다.

 

4. 예측하기

kn20.predict([[30, 600]])

 출력 : array([1])

 

5. 튜닝 계속 진행

kn20.n_neighbors = 40
kn20.score(fish_data, fish_target)

 출력 : 0.7142857142857143

 

6. 튜닝 반복문

  ▶ 1보다 작은 가장 좋은 정확도일 때의 이웃의 갯수 찾기

  반복문 사용 : 범위는 3 ~ 전체 데이터 갯수 (짝수갯수로 찾으면 안되고 홀수갯수로 찾아야함)


       - 모델(클래스) 생성

kn = KNeighborsClassifier()


       - 훈련시키기

kn.fit(fish_data, fish_target)


       - 정확도가 가장 높을 때의 이웃의 갯수를 담을 변수

nCnt = 0


       -  정확도가 가장 높을 때의 값을 담을 변수

nScore = 0

 

       - 반복문

for n in range(3, len(fish_data), 2):
    kn.n_neighbors = n
    score = kn.score(fish_data, fish_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 = 19 / nScore = 0.9795918367346939

 

해석🪄

-  모델의 성능이 가장 좋은 시점의 이웃의 갯수를 추출하기 위한 하이퍼파라메터 튜닝결과,
   이웃의 갯수가 19개를 사용하였을 때 가장 좋은 성능을 발휘하는 것으로 확인 됨

 

7. 최종 모델 검증

kn.n_neighbors = nCnt
kn.score(fish_data, fish_target)
kn.predict([[30, 600]])

 출력 : array([1])

 

 

 

 

728x90