티스토리 뷰
chapter.1 나의 첫 머신러닝¶
01-1 인공지능과 머신러닝, 딥러닝¶
- 인공지능이란?¶
인공지능은 사람처럼 학습하고 추론할 수 있는 지능을 가진 컴퓨터 시스템을 만드는 기술이다. 우리가 현실에서 마주하고 있는 인공지능은 약인공지능이다. 약인공지능은 아직까지는 특정 분야에서 사람의 일을 도와주는 보조 역할만 한다. 예를 들면 음성 비서, 자율 주행 자동차, 음악 추천, 기계 번역등이다. 알파고도 좋은 예이다.
- 머신러닝이란?¶
머신러닝은 규칙을 일일이 프로그래밍하지 않아도 자동으로 데이터에서 규칙을 학습하는 알고리즘을 연구하는 분야이다. 인공지능의 하위 분야 중에서 지능을 구현하기 위한 소프트웨어를 담당하는 핵심 분야이다. 머신러닝은 통계학과 관련이 있다. 통계학에서 유래된 머신러닝 알고리즘이 많으며 통계학과 컴퓨터 과학 분야가 상호 작용하면서 발전하고 있다. 하지만 최근 머신러닝의 발전은 통계나 수학 이론보다 경험을 바탕으로 발전하는 경우도 많다. 컴퓨터 과학 분야의 대표적인 머신러닝 라이브러리는 사이킷런이다.
- 딥러닝이란?¶
많은 머신러닝 알고리즘 중이 인공 신경망을 기반으로 한 방법들을 통칭하여 딥러닝이라고 부른다. 종종 인공 신경망과 딥러닝을 크게 구분하지 않고 사용한다.
01-3 마켓과 머신러닝¶
- 생선 분류 문제¶
예를들어 한빛 마켓에서 팔기 시작한 생선을 도미,곤들매기,농어,강꼬치고기,로치,빙어,송어이다. 이 생선들을 프로그램으로 분류한다고 가정해보자. 어떻게 프로그램을 만들어야 할까? 생선 분류를 위해 생선의 특징을 알면 쉽게 구분할 수 있다. 생선길이가 30cm 이상이면 도미이다. 하지만 30cm 보다 큰 생선이 무조건 도미라고 말할 수 없다. 또 도미의 크기가 모두 같을리도 없다. 그럼 이것을 머신러닝으로 어떻게 해결할 수 있을까? 보통 프로그램은 '누군가 정해준 기준대로 일'을 한다. 반대로 머신러닝은 누구도 알려주지 않는 기준을 찾아서 일을 한다. 다시 말해 누가 말해 주지 않아도 머신러닝은 "30~40cm 길이의 생선은 도미이다"라는 기준을 찾는 것이다.
- 도미 데이터 준비하기¶
아래와 같이 35마리의 도미를 준비해보자.
# 생선의 길이
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]
위 리스트에서 각 도미의 길이와 무게로 표현한 것을 특성(feature)라고 부르자. 두 특성을 숫자로 보는 것보다 그래프로 표현하면 데이터를 잘 이해할 수 있고 앞으로 할 작업에 대한 힌트도 얻을 수 있다. 길이를 x축, 무게를 y축으로 정한다. 그 다음 각 도미를 그래프에 점으로 표시하자. 아래와 같은 그래프를 산점도라고 부른다.
import matplotlib.pyplot as plt
plt.scatter(bream_length, bream_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
위와같이 산점도 그래프가 일직선에 가까운 형태로 나타나는 경우를 선형적이라고 한다. 다음으로 빙어 데이터도 준비해 보자.
- 빙어 데이터 준비하기¶
빙어 데이터 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]
도미와 빙어 데이터를 같이 산점도 그래프로 나타내보자.
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
빙어는 길이가 길어도 무게가 크게 늘어나지 않는다. 도미와 빙어 데이터를 모두 준비했고 산점도도 그려보았다. 이제 이 두 데이터를 스스로 구분하기 위한 첫 번째 머신러닝 프로그램을 만들어 보자.
- 첫 번째 머신러닝 프로그램¶
여기에선 가장 간단하고 이해하기 쉬운 k-최근접 이웃 알고리즘을 사용해 도미와 빙어 데이터를 구분해 보자. k-최근접 이웃 알고리즘을 사용하기 전에 앞에서 준비했던 도미와 빙어의 데이터를 하나의 데이터로 합치자. 다음 코드를 따라해보자.
length = bream_length + smelt_length
weight = bream_weight + smelt_weight
여기서 사용하는 머신러닝 패키지는 사이킷런이다 이 패키지를 사용하려면 다음 코드를 입력하여 리스트를 세로 방향으로 늘어뜨린 2차원 리스트를 만들어야 한다. 파이썬의 zip()함수를 이용하자. zip() 함수는 나열된 리스트에서 원소를 하나씩 꺼내주는 일을 한다.
fish_data = [[l,w] for l, w in zip(length,weight)]
print(fish_data)
[[25.4, 242.0], [26.3, 290.0], [26.5, 340.0], [29.0, 363.0], [29.0, 430.0], [29.7, 450.0], [29.7, 500.0], [30.0, 390.0], [30.0, 450.0], [30.7, 500.0], [31.0, 475.0], [31.0, 500.0], [31.5, 500.0], [32.0, 340.0], [32.0, 600.0], [32.0, 600.0], [33.0, 700.0], [33.0, 700.0], [33.5, 610.0], [33.5, 650.0], [34.0, 575.0], [34.0, 685.0], [34.5, 620.0], [35.0, 680.0], [35.0, 700.0], [35.0, 725.0], [35.0, 720.0], [36.0, 714.0], [36.0, 850.0], [37.0, 1000.0], [38.5, 920.0], [38.5, 955.0], [39.5, 925.0], [41.0, 975.0], [41.0, 950.0], [9.8, 6.7], [10.5, 7.5], [10.6, 7.0], [11.0, 9.7], [11.2, 9.8], [11.3, 8.7], [11.8, 10.0], [11.8, 9.9], [12.0, 9.8], [12.2, 12.2], [12.4, 13.4], [13.0, 12.2], [14.3, 19.7], [15.0, 19.9]]
이제 정답 데이터를 만들어 보자. 머신러닝과 컴퓨터 프로그램은 문자를 직접 이해하지 못한다. 대신에 도미와 빙어를 숫자 1,0 으로 표현해 보자. 에를 들어 첫 번째 생선은 도미이므로 1이고 마지막 생선은 빙어이므로 0이다. 앞에서 도미와 빙어를 순서대로 나열했기 때문에 1은 35번,0은 14번 나올 것이다.
fish_target = [1] * 35 + [0] * 14
print(fish_target)
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
이제 사이킷런 패키지에서 k-최근접 이웃 알고리즘을 구현한 클래스인 KNeighborsClassifier를 임포트하자.
from sklearn.neighbors import KNeighborsClassifier
임포트한 KNeighborsClassifier 클래스의 객체를 먼저 만들자.
kn = KNeighborsClassifier()
이 객체에서 fish_data와 fish_target을 전달하여 도미를 찾기 위한 기준을 학습시키자. 이런 과정을 머신러닝에서는 훈련이라고 한다. 사이킷런에서는 fit()메서드가 이런 역할을 한다.
kn.fit(fish_data, fish_target)
KNeighborsClassifier()
fit() 메서드는 주어진 데이터로 알고리즘을 훈련시킨 뒤 훈련한다. 이제 k객체 kn이 얼마나 잘 훈련되었는지 평가해보자. 사이킷런에서 모델을 평가하는 메서드는 score()메서드이다. 이 메서드는 0에서 1 사이의 값을 반환한다. 1은 모든데이터를 정확히 맞혔다는 것을 나타낸다.
kn.score(fish_data, fish_target)
1.0
1이 나왔기 때문에 모든 fish_data를 정확히 맞혔다. 이 값을 정확도라고 부른다.
- k-최근접 이웃 알고리즘¶
아래 그래프를 보면 [30,600] 인 생선은 아마 도미라고 생각할 것이다. 왜냐하면 이 데이터 주변에 다른 도미 데이터가 많기 때문이다. k-최근접 이웃 알고리즘도 마찬가지이다.
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.scatter(30, 600, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
kn.predict([[30,600]])
array([1])
predict() 메서드는 새로운 데이터의 정답을 예측한다. 위 처럼 1이 나온것을 보아 도미로 예측하였다. 이렇게 생각하면 k-최근접 이웃 알고리즘을 위해 준비해야 할 일은 데이터를 모두 가지고 있는 게 전부이다. 새로운 데이터에 대해 예측할 때는 가장 가까운 직선거리에 어떤 데이터가 있는지를 살피기만 하면 된다. 단점은 k-최근접 이웃 알고리즘의 이런 특징 때문에 데이터가 아주 많은 경우 사용하기 어렵다. 데이터가 크기 때문에 메모리가 많이 필요하고 직선거리를 계산하는 데도 많은 시간이 필요하다. KNeighborsClassifier 클래스도 마찬가지이다. 이 클래스는 _fit_X 속성에 우리가 전달한 fish_data를 모두 가지고 있다. 또 _y 속성에 fish_target을 가지고 있다.
print(kn._fit_X)
[[ 25.4 242. ] [ 26.3 290. ] [ 26.5 340. ] [ 29. 363. ] [ 29. 430. ] [ 29.7 450. ] [ 29.7 500. ] [ 30. 390. ] [ 30. 450. ] [ 30.7 500. ] [ 31. 475. ] [ 31. 500. ] [ 31.5 500. ] [ 32. 340. ] [ 32. 600. ] [ 32. 600. ] [ 33. 700. ] [ 33. 700. ] [ 33.5 610. ] [ 33.5 650. ] [ 34. 575. ] [ 34. 685. ] [ 34.5 620. ] [ 35. 680. ] [ 35. 700. ] [ 35. 725. ] [ 35. 720. ] [ 36. 714. ] [ 36. 850. ] [ 37. 1000. ] [ 38.5 920. ] [ 38.5 955. ] [ 39.5 925. ] [ 41. 975. ] [ 41. 950. ] [ 9.8 6.7] [ 10.5 7.5] [ 10.6 7. ] [ 11. 9.7] [ 11.2 9.8] [ 11.3 8.7] [ 11.8 10. ] [ 11.8 9.9] [ 12. 9.8] [ 12.2 12.2] [ 12.4 13.4] [ 13. 12.2] [ 14.3 19.7] [ 15. 19.9]]
print(kn._y)
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
fit() 메서드에 전달한 데이터를 모두 저장하고 있다가 새로운 데이터가 등장하면 가장 가까운 데이터를 참고하여 도미인지 빙어인지 구분한다. 그럼 가까운 몇개의 데이터를 참고할까? 이는 정하기 나름이지만 KNeighborsClassifier 클래스의 기본값은 5이다. 이 기준은 n_neighbors 매개변수로 바꿀 수 있다. 예를 들어 다음을 확인해 보자.
kn49 = KNeighborsClassifier(n_neighbors=49)
가장 가까운 데이터 49개를 사용하는 k-최근접 이웃 모델에 fish_data를 적용하면 fish_data에 있는 모든 생선을 사용하여 예측하게 된다. 다시말해 fish_data의 데이터 49개 중에 도미가 35개로 다수를 차지하므로 어떤 데이터를 넣어도 무조건 도미로 예측할 것이다.
kn49.fit(fish_data, fish_target)
kn49.score(fish_data, fish_target)
0.7142857142857143
fish_data에 있는 생선 중에 도미가 35개이고 빙어가 14개이다. kn49 모델은 도미만 올바르게 맞히기 때문에 다음과 같이 정확도를 계산하면 score() 메서드와 같은 값을 얻을 수 있다.
print(35/49)
0.7142857142857143
n_neighbors 매개변수를 49로 두는 것은 좋지 않다. 기본값을 5로 하여 도미를 완벽하게 분류한 모델을 사용하자.
kn = KNeighborsClassifier()
kn.fit(fish_data, fish_target)
for n in range(5, 50):
# 최근접 이웃 개수 설정
kn.n_neighbors = n
# 점수 계산
score = kn.score(fish_data, fish_target)
# 100% 정확도에 미치지 못하는 이웃 개수 출력
if score < 1:
print(n, score)
break
18 0.9795918367346939
출처 : 혼자 공부하는 머신러닝 + 딥러닝
'혼자공부하는 머신러닝+딥러닝' 카테고리의 다른 글
혼자 공부하는 머신러닝+딥러닝(ch4-1 로지스틱 회귀) (0) | 2021.04.30 |
---|---|
혼자 공부하는 머신러닝+딥러닝(ch3-3 특성 공학과 규제) (1) | 2021.04.29 |
혼자 공부하는 머신러닝+딥러닝(ch3-2 선형회귀) (0) | 2021.04.28 |
혼자 공부하는 머신러닝+딥러닝(ch.3-1 k-최근접 이웃 회귀) (0) | 2021.04.27 |
혼자 공부하는 머신러닝+딥러닝(ch.2) (0) | 2021.04.26 |