728x90
반응형
문제 정의
- 생선을 판매하는 앱 마켓인 "물꼬기" 에서는 생선을 판매하기로 했다.
- 물류 센터 직원이 생선 이름을 외우지 못해 매번 물어봐서 배송 지연이 발생했다.
- 이러한 문제를 해결하기 위해 Pupbani는 "생선 이름을 자동으로 알려주는 머신러닝"을 만들어야한다.
- 판매하는 생선은 "도미", "빙어"이다.
어떻게 분류할까?
- 생선의 특징(길이, 크기 , 무게 등)을 알면 구분할 수 있을 것 같다.
- 도미를 잘 아는 박팀장이 와서 "길이가 30cm 보다 크면 다 도미야"라고 했다.
if length >= 30 :
print("도미")
- 하지만 30cm 보다 큰 생선을 모두 도미라고 할 수 없다.
- 기존의 프로그램은 누군가 정해준 기준(ex. 30cm 이상은 도미야)대로 일을 한다.
- 머신러닝은 누구도 알려주지 않는 기준을 찾아 일을 한다.
- ex. 길이가 30~40cm인 생선은 도미야
- 머신 러닝은 이 기준을 통해 생선이 "도미"인지 아닌지 판별도 할 수 있다.
머신러닝 만들기
데이터 준비하기1 - 도미
- 머신러닝이 기준을 스스로 찾으려면 여러 개의 도미 생선을 보고 스스로 학습을 하여 어떤 생선이 도미인지를 구분할 기준을 찾는다.
- 도미 데이터를 준비한다.
// 생선의 길이
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]
// 생선의 무게
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]
- bream_length와 bream_weight 같은 특징들을 특성(Feature)라고 부른다.
도미 데이터 시각화하여 살펴 보기
- 두 특성을 시각화하여 그래프로 표현하여 보면 데이터를 잘 이해 할 수 있고 앞으로 어떤 알고리즘을 적용해야 할지 힌트를 얻을 수 있다.
- 길이를 X축 , 무게를 Y축으로 하여 산점도(Scatter Plot, 점으로 표시) 그래프를 그리겠다.
- 파이썬에서 시각화를 하는 대표적인 패키지는 Matplotlib이다.
- Matplotlib의 scatter() 메서드를 사용하면 산점도 그래프를 그릴 수 있다.
import matplotlib.pyplot as plt
// scatter(x_data,y_data)
plt.scatter(bream_length, bream_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
- 도미 35마리를 2차원 그래프(특성이 2개)에 점으로 나타냈다.
- 생선의 길이가 길수록 무게가 많이 나간다고 생각하면 자연스럽다.
- 그래프의 형태가 일직선에 가까운 형태 이다. - 선형(Linear)적
데이터 준비하기2 - 빙어
- 준비한 빙어 데이터는 14마리 이다.
- 앞에서 준비한 것 처럼 길이와 무게 데이터로 준비한다.
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]
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]
빙어 데이터 시각화하여 살펴 보기
- Matplotlib은 두개의 산점도를 색으로 구분하여 그려준다.
- 한 그래프에 도미와 빙어의 데이터를 시각화한다.
plt.scatter(bream_length, bream_weight) // 도미
plt.scatter(smelt_length, smelt_weight) // 빙어
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
- 빙어도 도미와 비슷하게 길이가 늘어나면 무게도 늘어나지만 늘어나는 정도가 다르다.
- 무게가 길이에 영향을 덜 받는다.
머신러닝 프로그램 작성 - K-최근접이웃(K-Nearest Neighbors) 알고리즘
- 먼저 앞에 도미와 빙어의 데이터를 길이, 무게별로 합친다.
length = bream_length+smelt_length
weight = bream_weight+smelt_weight
- 데이터는 다음과 같은 상태가 된다.
- 이제 머신러닝을 위한 패키지를 사용해 보자, 사용할 패키지는 사이킷런(scikit-learn)이다.
- 사이킷런을 사용하려면 데이터를 세로 방향으로 늘어 뜨린 2차원 리스트를 만들어야 한다.
- 이렇게 만드는 가장 쉬운 방법은 zip() 함수와 List Comprehension 구문을 사용하는 것이다.
- 각 리스트에서 하나씩 요소를 꺼내어 [길이, 무게] 쌍의 값들을 모아놓은 2차원 리스트를 만들 수 있다.
- 49개의 (길이,무게) 쌍을 가진 훈련 데이터를 완성 했다.
fish_data = [[l, w] for l, w in zip(length, weight)]
- 이제 마지막으로 정답 데이터(Targer data)를 준비해야한다.
- 도미를 1, 빙어를 0으로 생각 하고 데이터를 준비한다.
- [1] * 35개 , [0] * 14개를 합친 총 49개의 데이터를 준비한다.
- 정답 데이터는 훈련 데이터와 길이가 같아야 한다.
- ex) shape -> (49,1) , (49,2)
fish_target = [1] * 35 + [0] * 14
- 이제 데이터가 전부 준비 되었으니 모델을 불러와 학습을 진행 한다.
- 사이킷런 패키지의 K-최근접 이웃 알고리즘을 구현한 클래스인 "KNeighborsClassifier"를 import 한다.
- KNeighborsClassifier는 sklearn 패키지 아래 neighbors 모듈 아래 있다.
from sklearn.neighbors import KNeighborsClassifier
- KNeighborsClassifier 클래스의 객체를 만든다.
kn = KNeighborsClassifier()
- 이 객체에 훈련 데이터와 정답 데이터를 전달하여 도미를 찾기 위한 기준을 학습한다.
- 이런 과정을 훈련(Training)이라 부른다.
- 훈련을 하는 메서드는 fit(훈련 데이터, 정답 데이터)이다.
kn.fit(fish_data, fish_target)
- 훈련을 끝냈으니 얼마나 잘 훈련했는지 평가를 한다.
- 모델을 평가하는 메서드는 score(훈련 데이터, 정답 데이터)이다.
- 이 메서드는 0~1 사이의 값을 반환 한다.
print(f"훈련 결과 : {kn.score(fish_data, fish_target) * 100}%")
- 훈련 결과가 100.0%다 모든 fish_data의 값을 다 맞췄다.
- 이렇게 score를 통해 나온 값을 정확도(Accuracy)라고 부른다.
- K-최근접 알고리즘은 데이터의 대한 답을 구할 때 "주위의 다른 데이터를 보고 다수를 차지하는 것을 정답"으로 사용한다.
- 다음과 같은 경우 K-최근접 알고리즘은 모델은 생선을 무엇으로 판단할까?
- 길이 : 30cm , 무게 : 600g인 생선
- 시각화 하면 다음과 같다.
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.scatter(30, 600, marker='^') // 길이: 30cm, 무게: 600g 생선
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
- 그래프를 보면 새로운 생선은 주변에 도미가 많으므로 "도미"로 판단할 것으로 예상된다.
- 실제 예측을 해보자
- 예측을 하는 메서드는 predict(예측할 데이터)이다.
- 예측할 데이터는 훈련 데이터와 같은 형태로 전달해야한다.
- 그러므로 2차원 리스트 형태로 전달한다.
print("예측결과 : ",end="")
print("도미") if 1 == kn.predict([[30, 600]]) else print("빙어")
- 예상과 같이 "도미"로 예측 되었다.
- K-최근접 이웃 알고리즘을 통해 새로운 데이터를 예측할 때는 가장 가까운 직선 거리의 어떤 데이터가 있는지 살피는 것이 중요하다.
- 이러한 특징 때문에 데이터가 아주 많은 경우 사용하기 어렵다.
- 훈련된 모델의 X,Y의 데이터를 확인하면 학습할 때 사용한 데이터와 일치한다.
print(kn._fit_X) // X속성
print(kn._y) // Y속성
- K-최근접 이웃 알고리즘은 무언가 훈련되는 것이 없다.
- 새로운 데이터가 등장하면 가지고 있는 데이터에서 가장 가까운 데이터를 참고하여 구분한다.
- 몇개의 데이터를 참고할까?
- KNeighborsClassifier클래스의 n_neighbors매개변수를 통해 참고 데이터 개수를 변경할 수 있다.(기본값 = 5)
- 만약 49개의 데이터를 참고하면 어떻게 될까?
kn49 = KNeighborsClassifier(n_neighbors=49)
kn49.fit(fish_data, fish_target)
print(f"훈련 결과 : {kn49.score(fish_data, fish_target).round(2) * 100}%")
- kn49 모델은 49개의 생선 데이터 중 도미가 35개이므로 새로운 데이터가 들어오면 항상 도미로 예측할 것 이다.
- 정확도 = 도미의 개수 / 전체생선 개수
print(f"정확도 : {round(35/49,2)*100}%")
참고 데이터를 49개로 하는 것은 좋지 않다.
5개로 했을 때 정확도가 100%이므로 기본값 5로 하여 도미를 완벽하게 분류한 모델을 사용할 것이다.
하지만 이 방법이 과연 알맞는 방법일까? 다음 장에서 알아보자.
728x90
반응형
'AI > 기계학습(Machine Learning)' 카테고리의 다른 글
[기계학습/ML]6. 회귀 알고리즘(1) - K-최근접 이웃 회귀, 선형회귀 (0) | 2022.10.23 |
---|---|
[기계학습/ML]5. 데이터 전처리 - 표준점수, 브로드캐스팅 (0) | 2022.10.22 |
[기계학습/ML]4. 훈련 세트와 테스트 세트 - 샘플링 편향(Numpy 사용) (1) | 2022.10.22 |
[기계학습/ML]2. 실습 환경 - Colab Notebooks (0) | 2022.10.22 |
[기계학습/ML]1. 개요 - 인공지능, 머신러닝, 딥러닝 (0) | 2022.10.21 |