20장. 교육 콘텐츠 설계와 종합 실습
정답표와 자동 채점
운전면허 기능 시험장은 차가 선을 밟으면 센서가 바로 감점합니다. 시험관이 모든 차를 눈으로 따라다니지 않아도 되고, 누가 시험을 봐도 같은 기준으로 매겨집니다. 감점이 되면 "선을 밟았습니다"라는 안내도 나옵니다. 수강생 서른 명의 결과 그림을 강사가 하나하나 보는 대신, 정답과 견주는 채점 함수를 만들어 두면 같은 일을 할 수 있습니다.
그림의 다섯 걸음이 자동 채점의 순서입니다. 여기서 시험장의 선이 정답 마스크이고, 센서가 견주는 코드이고, "선을 밟았습니다"가 피드백입니다. 비유와 다른 점도 있습니다. 면허 시험은 감점 항목이 정해져 있지만, 영상처리 답은 "조금 넓게 칠했다"처럼 정도가 있어서 점수를 0~1 사이의 비율로 매깁니다.
겹친 넓이로 매기는 점수, IoU
초록 상자가 정답, 다홍 상자가 답입니다. 둘 다 가로 60, 세로 40 이라 넓이가 2400 입니다. 가운데 그림의 보라 칸이 겹친 곳으로 40 × 30 = 1200 이고, 오른쪽 그림처럼 두 상자를 합친 넓이는 2400 + 2400 − 1200 = 3600 입니다. 겹친 곳을 두 번 세지 않으려고 한 번 뺍니다. IoU 는 1200 ÷ 3600 = 0.333 입니다. 18장에서 탐지 상자를 견줄 때 쓴 것과 같은 계산이고, 마스크에도 칸 수를 세어 똑같이 씁니다.
채점에 쓰는 점수들
| 점수 | 계산 | 좋은 점 | 아쉬운 점 |
|---|---|---|---|
| 정확도(맞힌 칸 비율) | 정답과 같은 칸 ÷ 전체 칸 | 계산이 쉽다(8장) | 물체가 작으면 다 0 으로 칠해도 높게 나온다 |
| IoU | 겹친 칸 ÷ 합친 칸 | 물체 크기와 상관없이 엄격하다 | 작은 물체는 몇 칸만 어긋나도 크게 떨어진다 |
| 찾은 비율(재현율) | 겹친 칸 ÷ 정답 칸 | 빠뜨린 것을 잡는다(11장) | 넓게 칠하면 높아진다 |
| 맞은 비율(정밀도) | 겹친 칸 ÷ 답의 칸 | 넘친 것을 잡는다(11장) | 조금만 칠하면 높아진다 |
| 개수 | 윤곽선 수 ÷ 정답 개수 | 수강생이 알아듣기 쉽다(12장) | 자리가 틀려도 개수만 맞으면 통과한다 |
짧은 예시
작은 마스크 두 장으로 네 가지 점수를 손계산과 함께 확인합니다.
import numpy as np
# 6칸짜리 정답과 답. 1 은 물체, 0 은 바탕
answer = np.array([[0, 1, 1],
[0, 1, 1]], dtype=bool)
student = np.array([[0, 0, 1],
[1, 1, 1]], dtype=bool)
inter = int((answer & student).sum()) # 겹친 칸: 3
union = int((answer | student).sum()) # 합친 칸: 5
print("IoU:", inter, "/", union, "=", round(inter / union, 3)) # 결과: 0.6
print("정확도:", round(float((answer == student).mean()), 3)) # 같은 칸 4 / 6 = 0.667
print("찾은 비율:", round(inter / int(answer.sum()), 3)) # 3 / 4 = 0.75
print("맞은 비율:", round(inter / int(student.sum()), 3)) # 3 / 4 = 0.75& 는 두 칸이 모두 True 일 때(겹친 곳), | 는 하나라도 True 일 때(합친 곳) True 입니다. 각각 and(그리고), or(또는)의 뜻입니다.
주의할 점
- 정답 파일은 수강생에게 나눠 주는 묶음과 따로 둡니다. 채점 함수만 주고 정답은 강사가 가지고 있거나, 수업이 끝난 뒤 나눠 줍니다.
- 점수만 돌려주면 수강생은 무엇을 고칠지 모릅니다. 점수가 낮은 까닭(잡티, 빠뜨림, 넘침)에 맞춰 다음에 볼 장을 함께 알려 줍니다(실습 3).