1장. 머신러닝 프로세스와 기본 개념
머신러닝이란
택배 회사가 지연을 미리 알고 싶다고 해 봅시다. 첫 번째 방법은 사람이 규칙을 적는 것입니다. "거리가 100km 를 넘으면 지연"처럼요. 그런데 비, 주말, 저녁 주문, 무거운 짐까지 겹치면 규칙이 끝없이 늘어납니다. 두 번째 방법은 베테랑 기사처럼 지난 기록을 잔뜩 보여 주고 규칙을 스스로 찾게 하는 것입니다. 두 번째가 머신러닝입니다.
왼쪽은 사람이 조건을 하나씩 적는 보통의 프로그램이고, 오른쪽은 지난 기록에서 규칙을 찾는 머신러닝입니다. 여기서 지난 배송 기록이 데이터이고, 기사가 익힌 감이 모델입니다. 다만 비유와 다른 점이 있습니다. 기사의 감은 말로 설명할 수 있지만, 모델이 찾은 규칙은 숫자 묶음이라 사람이 바로 읽기 어려울 때가 많습니다.
두 방법 견주기
| 견줄 것 | 규칙을 적는 프로그램 | 머신러닝 |
|---|---|---|
| 규칙은 누가 만드나 | 사람이 적는다 | 모델이 데이터에서 찾는다 |
| 필요한 것 | 업무를 잘 아는 사람 | 정답이 붙은 기록 |
| 조건이 늘어나면 | 규칙이 끝없이 길어진다 | 기록만 충분하면 그대로 배운다 |
| 왜 그렇게 답했는지 | 규칙을 읽으면 안다 | 바로 알기 어렵다 |
| 어울리는 일 | 주소가 비면 접수 거절 | 어느 주문이 늦을지 맞히기 |
짧은 예시
배송 여섯 건으로 모델을 하나 만들어 봅니다. 입력은 거리와 주문시각이고, 정답은 지연 여부입니다.
from sklearn.tree import DecisionTreeClassifier
# 배송 여섯 건: [거리km, 주문시각]
X = [[5, 10], [8, 20], [200, 9], [150, 21], [12, 14], [220, 19]]
# 같은 순서의 정답: 1 이 지연, 0 이 정시
y = [0, 0, 1, 1, 0, 1]
# 의사결정나무 모델을 만들고, 여섯 건을 보여 주며 학습시킨다
model = DecisionTreeClassifier(random_state=0).fit(X, y)
# 처음 보는 주문 두 건(180km 낮 주문, 6km 밤 주문)의 답을 물어본다
print(model.predict([[180, 11], [6, 22]]))규칙을 하나도 적지 않았는데, 모델은 180km 주문을 지연(1)으로, 6km 주문을 정시(0)로 답합니다. 여섯 건에서 "거리가 멀면 늦는다"를 찾아낸 것입니다.
코드에 나오는 함수
| 코드 | 쉬운 뜻 |
|---|---|
from sklearn.tree import DecisionTreeClassifier | scikit-learn 의 tree(나무) 묶음에서 의사결정나무 모델을 불러온다. 코드에서는 scikit-learn 을 sklearn 이라는 이름으로 부른다 |
DecisionTreeClassifier(...) | Decision Tree(의사결정나무)와 Classifier(분류기)를 붙인 이름이다. 예·아니요 질문을 이어 가며 답을 고르는 분류 모델을 만든다 |
random_state=0 | 모델 안에서 쓰는 난수의 씨앗을 고정한다. 다시 돌려도 같은 모델이 나온다 |
.fit(X, y) | fit 은 "맞추다"라는 뜻이다. 문제(X)와 정답(y)을 보여 주며 학습시킨다. 학습한 모델을 그대로 돌려주므로 만들기와 한 줄로 이어 쓸 수 있다 |
.predict([[180, 11], [6, 22]]) | predict 는 "예측하다"라는 뜻이다. 새 주문의 답을 묻는다. 학습할 때와 같은 [거리km, 주문시각] 꼴로 넣는다 |
이 코드가 뜻하는 것
신입 기사에게 지난 배송 전표 여섯 장을 보여 주고, 새 전표 두 장을 내밀며 "이건 늦을까요?" 하고 묻는 장면입니다. 여기서 전표 여섯 장이 X 와 y, 신입 기사가 model, 새 전표 두 장이 predict 에 넣은 목록입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
X = [[5, 10], ...] | 배송 여섯 건의 거리와 주문시각을 적는다 | 전표 앞면에 적힌 사정 |
y = [0, 0, 1, 1, 0, 1] | 같은 순서로 정답을 적는다 | 전표 뒷면의 "늦음·제때" 도장 |
DecisionTreeClassifier(random_state=0) | 아직 아무것도 모르는 모델을 만든다 | 신입 기사를 뽑는다 |
.fit(X, y) | 여섯 건으로 학습한다 | 전표를 넘겨 보며 감을 익힌다 |
model.predict([[180, 11], [6, 22]]) | 처음 보는 두 건의 답을 묻는다 | 새 전표 두 장을 내민다 |
결과 [1 0] 은 첫 주문이 지연, 둘째 주문이 정시라는 뜻입니다. 비유와 다른 점은, 기사는 왜 그렇게 봤는지 말해 주지만 모델은 묻지 않으면 말하지 않는다는 것입니다. 아래처럼 찾은 규칙을 직접 꺼내 봐야 합니다.
모델이 찾은 규칙 꺼내 보기
같은 여섯 건으로 학습한 모델의 질문을 글로 꺼냅니다. export_text 는 export(내보내다)와 text(글)를 붙인 이름으로, 나무가 만든 질문을 글로 보여 줍니다.
from sklearn.tree import DecisionTreeClassifier, export_text
X = [[5, 10], [8, 20], [200, 9], [150, 21], [12, 14], [220, 19]]
y = [0, 0, 1, 1, 0, 1]
model = DecisionTreeClassifier(random_state=0).fit(X, y)
# 모델이 찾은 규칙을 글로 꺼내 본다
print(export_text(model, feature_names=["거리km", "주문시각"]))|--- 거리km <= 81.00
| |--- class: 0
|--- 거리km > 81.00
| |--- class: 1| 결과 | 읽는 법 |
|---|---|
거리km <= 81.00 아래의 class: 0 | 거리가 81km 이하이면 정시(0)라고 답한다 |
거리km > 81.00 아래의 class: 1 | 81km 를 넘으면 지연(1)이라고 답한다 |
| 주문시각이 나오지 않는다 | 여섯 건은 거리 하나로 다 갈렸으므로 주문시각은 쓰지 않았다 |
81 은 정시 주문 가운데 가장 먼 12km 와 지연 주문 가운데 가장 가까운 150km 의 한가운데입니다. 180km 는 81km 를 넘으니 지연, 6km 는 넘지 않으니 정시라고 답한 것입니다. export_text 는 "과적합" 절에서 다시 씁니다.
주의할 점
- 머신러닝은 기록에 있는 것만 배웁니다. 기록에 눈 오는 날이 하나도 없으면 눈 오는 날은 맞히지 못합니다.
- 규칙이 짧고 분명하면 그냥 규칙을 적는 편이 낫습니다. "주소가 비어 있으면 접수 거절"에 머신러닝은 필요 없습니다.