[혼자 공부하는 머신러닝+딥러닝] 교재 1장을 기반으로 작성되었습니다.
사람처럼 학습하고 추론할 수 있는 지능을 가진 컴퓨터 시스템을 만드는 기술
흔히 영화에서 보이는 인공지능은 인공일반지능(artificial general inteligence 혹은 강인공지능(Strong AI)이라 불리는 인공지능이다.
하지만, 우리가 현실에서 마주치고 있는 인공지능은 약인공지능(Week AI)이다.
약인공지능은 아직까지는 특정 분야에서 사람의 일을 도와주는 보조 역할만 가능하다.
ex) 음성 비서, 자율 주행 자동차, 음악 추천, 기계 번역 등
규칙을 일일이 프로그래밍하지 않아도 자동으로 데이터에서 규칙을 학습하는 알고리즘을 연구하는 분야.
인공지능의 하위 분야 중에서 지능을 구현하기 위한 소프트웨어를 담당하는 핵심 분야이다.
컴퓨터 과학 분야의 대표적인 머신러닝 라이브러리는 사이킷런(scikit-learn)이 있다.
많은 머신러닝 알고리즘 중에 인공 신경망(artificial neural network)을 기반으로 한 방법들.
인공 신경망이라고도 불린다
인공 신경망 알고리즘을 전문으로 다루고, 파이썬 API를 제공하는 오픈소스 머신러닝 라이브러리 텐서플로(TensorFlow), 파이토치(PyTorch)가 있다.
웹 브라우저에서 무료로 파이썬 프로그램을 테스트하고 저장할 수 있는 서비스.
클라우드 기반의 주피터 노트북 개발환경이다.
코랩의 프로그램 작성단위.
대화식으로 프로그램을 만들 수 있기 때문에 데이터 분석이나 교육에 매우 적합하다.
노트북은 자동으로 개인 구글 드라이브에 저장된다.
가장 간단한 머신러닝 알고리즘 중 하나인 k-최근접 이웃을 사용하여 2개의 종류를 분류하는 머신러닝 모델을 훈련한다.
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: 도미
도미의 길이, 무게와 같은 데이터의 특징을 특성(feature)이라 부른다.
x, y 축으로 이루어진 좌표계에 두 변수 (x,y)의 관계를 표현하는 그래프를 산점도(scatter plot)라 하는데, 파이썬에서 그래프를 그리는 대표적인 패키지 맷플롯립(matplotlib) 내의 scatter()
함수를 사용해 만들 수 있다.
도미의 길이를 x축, 무게를 y축으로 하겠다.
import matplotlib.pyplot as plt
plt.scatter(bream_length, bream_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
위와 같이 산점도 그래프가 일직선에 가까운 형태로 나타나는 경우를 선형적(linear)이라고 말한다.
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]
# smelt: 빙어
2개의 산점도를 한 그래프로 그리려면 그저 scatter() 함수를 연달아 사용하면 된다.
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
가장 간단한 k-최근점 이웃(K-Nearest Neighbors) 알고리즘을 사용해 도미와 빙어 데이터를 구분해 볼텐데, 그 전에 앞서 준비한 두 개의 데이터를 하나의 데이터로 합치고, 아래와 같이 각 특성의 리스트를 세로 방향으로 늘어뜨린 2차원 리스트를 만들어 입력 데이터를 만들겠다.
(사이킷런 패키지를 사용하기 위한 조건)
length = bream_length+smelt_length
weight = bream_weight+smelt_weight
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]]
생선 49개의 길이와 무게는 모두 준비했으니, 이제 정답 데이터를 준비할 차례이다.
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-최근접 이웃 알고리즘을 구현한 클래스인 KNeighborsClassfier를 임포트한 뒤, 클래스의 객체를 만든다.
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
위 객체에 fish_data와 fish_target을 전달하여 도미를 찾기 위한 기준을 학습시키는데, 이런 과정을 훈련(traning)이라고 부른다 사이킷런에서는 fit()
메서드가 이런 역할을 한다.
kn.fit(fish_data, fish_target)
이제 객체(또는 모델) kn이 얼마나 잘 훈련되었는지 평가하는데, 사이킷런에서 모델을 평가하는 메스드는 score()
메서드이다.
이 메서드는 0~1 사이의 값을 반환하는데, 1은 100%의 정확도, 0.5는 50%의 정확도를 뜻한다.
kn.score(fish_data, fish_target)
>>> 1.0
이 알고리즘은 어떤 데이터에 대한 답을 구할 때 주위의 다른 데이터를 보고 다수를 차지하는 것을 정답으로 사용한다. 마치 근묵자흑과 같이 주위의 데이터로 현재 데이터를 판단하는 것이다.
위와 같이 삼각형으로 표시된 새로운 데이터가 있다고 가정하면, 삼각형 주위에 도미 데이터가 많으므로 삼각형을 도미라고 판단한다.
이를 predict() 메서드를 통해 확인해보겠다.
predict()
메서드는 새로운 데이터의 정답을 예측한다. 아래 코드 내의 데이터는 위 설명의 삼각형을 나타낸다.
kn.predict([[30, 600]])
>>> array([1])
# 우리는 앞서 도미는 1, 빙어는 0으로 가정했으므로, 삼각형은 도미라는 출력을 보이는 것을 확인할 수 있다.
k-최근접 이웃 알고리즘을 위해 준비해야할 일은 데이터를 모두 가지고 있는게 전부이다. 예측을 할 때는 가장 가까운 직선거리에 어떤 데이터가 있는지 살피기만 하면 된다. 그렇기 때문에 데이터가 아주 많은 경우에는 사용하기 어렵다는 단점이 있다.
이는 사이킷런의 KNeighborsClassifier 클래스도 마찬가지이다.
_fit_X 속성에 우리가 전달한 fish_data를 모두 가지고 있고, _y 속성에 fish_target를 가지고 있다.
print(kn._fit_X)
>>> [[ 25.4 242. ]
[ 26.3 290. ]
...
[ 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]
그러면, 가까운 몇 개의 데이터를 참고할까?
이는 정하기 나름인데, 기본값은 5개이다. 이 기준은 n_neightbors
매개변수로 바꿀 수 있다.
kn49 = KNeighborsClassifier(n_neighbors=49)
kn49.fit(fish_data, fish_target)
kn49.score(fish_data, fish_target)
>>> 0.7142857142857143
fish_data 에 있는 생선 중에 도미가 35개이고, 빙어가 14개이다. 즉, 가까운 데이터 49개를 사용하는 것은 모든 생선을 사용하는 예측하게 되는 것이다. 그러므로 어떤 데이터를 넣어도 무조건 도미로 예측할 것이다.
이 kn49 모델은 도미만 올바르게 맞히기 때문에 다음과 같이 정확도를 계산하면 score()
메서드와 같은 값을 얻을 수 있다.
print(35/49)
>>> 0.7142857142857143
위를 보니 n_neighbors
매개변수를 49로 두는 것은 좋지 않다는 것을 알 수 있다.
기본값을 5로 하여 분류하는 모델을 사용하자.
+)
p
매개변수로 거리를 재는 방법을 지정할 수 있다. 1일 경우 맨해튼 거리, 2일 경우 유클리디안 거리를 사용한다. 기본값은 2인 유클리디안 거리이다.
예를 들어 도시 거리 계산(그리드 맵)과 같은 경우, 현실적으로 직선으로 이동할 수 없는 상황에서는 축을 따라 이동하는 방식인 맨해튼 거리가 더 적합하다.