해당 포스트는 2019년 강의 영상과 자료를 보고 작성하였으며, 2022년 강의 자료를 통해 보강하였습니다.
해당 포스트에 포함된 이미지는 2022년 강의 자료에서도 확인 가능합니다.
Image Classification: 컴퓨터 비전의 주요 작업
input: 이미지 → output: (주어진/고정된) 카테고리 label 중 해당 이미지에 맞는 label을 달아줌
인간에게는 매우 사소한 작업 (생각을 거치지 않고도 즉각적으로 수행 가능)
하지만 컴퓨터에게는 어려운 작업임 → Probelm: Semantic Gap
Problem: Semantic Gap (의미론적 차이)
우리가 고양이 이미지를 보고 고양이로 인식할 때 신체 내부적으로 많은 복잡한 처리를 거침
하지만 우리는 그 과정을 의식적으로 인식하지 않고, 즉각적으로 고양이라는 것을 인지함 → 직관
컴퓨터는 직관이 존재하지 않음 → 거대한 숫자 격자(grid)로 이미지를 이해
- 각각의 숫자는 0~255까지의 값을 가짐
- 해당 숫자 집합으로는 '이 숫자들이 고양이를 나타내야 하는 것인가'가 분명하지 않음 (컴퓨터가 이 값을 보고 고양이라고 바로 판단하지 못함)
- 상대적으로 작은 변화(약간의 노이즈 추가, 밝기/대비 변경 등)에도 전체 숫자 격자 값이 크게 달라질 수 있음
➡️ 의미론적 격차 우리가 이미지를 이해하는 것과 이미지가 raw pixel grid로 표시되는 것 사이의 차이
Challenges: Viewpoint Variation
- 인간: 고양이를 다른 각도에서 찍어도 고양이로 인식
- 컴퓨터: 다른 각도에서 고양이를 찍게 되면 숫자 값이 모두 달라짐
Challenges: Intraclass Variation
'고양이'라고 분류된다고 하여 모두 같은 것이 아님 → 고양이 내에서도 다양한 개체들이 존재(컴퓨터가 모두 다르게 인식할 것)
Challenges: Fine-Grained Categories
작업에 따라 좀 더 세분화된 카테고리를 인식하고 싶은 경우도 있을 수 有
고양이를 좀 더 세부적인 종으로 분류하고 싶을 경우 → 시각적으로 매우 유사해보이는 카테고리들이 생김
Challenges: Background Clutter
배경(자연환경 등)으로 인해 개체 식별이 어려운 경우가 생김
Challenges: lllumination Changes
조명을 끄거나 켤 때에도, 자연광에 혹은 어둠에 있을 때에도 이미지는 달라질 수 있지만 인식하고자 하는 물체 자체는 변화하지 않음
Challenges: Deformation
물체 변형에도 강건한 알고리즘이 필요함 → 같은 개체여도 포즈 등에 따라 시각적으로 매우 다르게 보일 수 있음 (especially 🐈🐈⬛...)
Challenges: Occlusion
폐색을 처리해야 하는 경우 생김 → 우리가 인식해야 하는 개체가 이미지에서 거의 눈에 띄지 않는 경우 등
➡️ 대규모 변형에 강건한 시스템(분류기)을 구축할 필요가 있음!
Image Classification: Building Block for other tasks!
이미지 분류는 컴퓨터 비전 내에서 우리가 수행하고자 하는 다양한 알고리즘의 기본 구성요소이기도 함 (Very Useful)
Object Detection
이미지에 어떤 객체가 있는지(What), 해당 객체가 어디에 있는지(Where)를 알려줌 (Using by Sliding Window)
Image Captioning
입력으로 들어온 이미지에 무엇이 있는지 설명하기 위한 자연어 문장을 작성 (일종의 분류 문제로 접근 가능)
- 분류기를 통해 단어를 분류하고 선택 → Problem: What word to say next?
Playing Go
바둑과 같은 게임에도 AI 시스템을 적용 → 이것 또한 분류 문제로 접근 가능
- input: 특정 위치에서의 게임 보드의 상태를 설명하는 이미지
- output: 다음 돌을 보드의 어느 위치에 놓아야하는 지에 대한 정보 (1, 1) (1, 2), ..., (1, 19), ..., (19, 19)
An Image Classifier
분류 알고리즘을 hard-coding하는, 어떻게 접근해야 하는가에 대한, 명확한 방법은 없음
우리는 이미지에서 edge와 corner를 찾아 고양이를 분류하기 위해 시도할 수 있음 → 해석 가능한 패턴을 찾으려고 시도
하지만 우리가 고양이에 대한 모든 인간의 지식을 hard cording하는 것은 불가능한 일
시간과 노력이 많이 들고, 시도하더라도 이는 깨지기 쉬운 방법 (brittle)
- 수염이 없는 고양이가 존재한다면? 귀가 뾰족하지 않은 고양이가 존재한다면?
- edge나 corner 검출에 실패한다면?
- 이제는 고양이가 아닌 은하를 분류하고 싶다면?
- 앞서 논의한 Challenge들의 문제
Machine Learning: 데이터 기반(Data-Driven) Approach
- Collect a dataset of images and labels
- Use Machine Learning to train a classifier
- Evaluate the classifier on new images
해당 접근 방법에는 Train 과정과 Predict 과정 두 가지가 필요함
def train(images, labels):
# Machine learning!
return model # some statistical model
def predict(model, test_images):
# Use model to predict labels
return test_labels
→ ML을 통해 우리는 매번 다른 학습 알고리즘을 만들어낼 필요가 없어짐. 새로운 작업을 수행햐기 위해서는 새로운 데이터를 공급하기만 하면 됨 (데이터의 중요성 높아짐)
Image Classification Datasets: MNIST
- 10 classes (0부터 9까지의 손글씨 숫자)
- 28*28 흑백 이미지 (grayscale)
- 50K / 10K (학습/테스트 이미지)
- 실제로 수표 등에 손으로 쓴 숫자를 인식하는 프로그램의 개발에 사용됨
"Drosophila(초파리) of computer vision"
- 생물학자들: 초파리를 통해 초기실험 진행 → 이후 다양한 동물들에 적용
- 실무자들이 MNIST를 이용하는 방식과 매우 유사
MNIST 데이터셋은 상대적으로 작고 간단한 데이터기 때문에 새로운 데이터를 빠르게 테스트해보기 좋음
하지만 그렇기 때문에 일반적으로 좋은 성능을 보이기도 함!
→ 따라서 간단한 아이디어의 증명 용도로는 괜찮지만 그 결과를 너무 맹신하면 안됨
Image Classification Datasets: CIFAR10
- 10 classes (airplane, automobile, bird...)
- 32*32 RGB 이미지
- 50k 학습 이미지 (5k per class)
- 10k 테스트 이미지 (1k per class)
Image Classification Datasets: CIFAR100
- 100 classes
- 20 superclasses with 5 classes each
- Aquatic mammals: beaver, dolphin, otter, seal, whale
- Trees: maple, oak, palm, pine, willow
- 32*32 RGB 이미지
- 50k 학습 이미지 (500 per class)
- 10k 테스트 이미지 (100 per class)
Image Classification Datasets: ImageNet
이미지 분류의 Gold standard → CIFAR10이나 CIFAR100 보다 훨씬 많은 class를 가짐
인터넷에서 다양한 크기의ImageNet 데이터셋을 받아올 수 있지만, 대개 256*256으로 resize해서 사용함
- 1000 classes
- ~1.3M 학습 이미지 (~1.3K per class)
- 50K 검증 이미지 (50 per class)
- 100K 테스트 이미지 (100 per class)
- 성능 지표: Top 5 accuracy
- 1000개의 카테고리가 있기 때문에 정확한 하나의 카테고리를 골라내는 것은 매우 어렵고 비합리적
- 각 이미지에 대해 5개의 label을 예측, 그 중 하나만이라도 정확하면 됨
Image Classification Datasets: MIT Places
장면에 초점을 맞춘 데이터셋 (cafeteria, bar, field road, shoe shop...)
- 365 classes of different scene types
- 다양한 크기를 가지고 있지만, 대개 256*256으로 resize해서 사용
- ~8M 학습 이미지
- 18.25K 검증 이미지 (50 per class)
- 328.5K 테스트 이미지 (900 per class)
Classification Datasets: Number of Training Pixels
ImageNet과 Places365 데이터셋의 이미지 크기를 256*256 으로 가정
- 각 데이터셋의 학습 데이터셋에 있는 pixel 수
- y축은 로그 척도 (log scale)
- ImageNet이 다른 데이터 셋과 어떻게 질적으로 다른지를 강조하는 중요한 포인트임 (Gold standard)
- 하지만 계산 비용이 많이 들기 때문에 중간 단계(middle ground)로써 CIFAR100를 사용하기도 함
- 각자의 작업이나 모델에 맞게 적당한 dataset을 택하면 됨
→ 데이터셋의 크기가 점차 커지는 추세!
Image Classification Datasets: Omniglot
데이터셋의 크기가 점차 커지는 추세지만 Omniglot과 같은 데이터셋도 존재함
Omniglot은 적은 수의 데이터(20 images per category)로 학습을 테스트하기 위한 것으로, 극단적인 상황을 다루며(pushes things to the extreme) 상대적으로 적은 데이터로 강건하게(rubustly) 학습할 수 있는 알고리즘(few shot learning)을 구축하고자 함
➕ Few-Shot Learning
First classifier: Nearest Neighbor
매우 간단하고 직관적인 학습 알고리즘이지만 구현을 위해서는 입력된 두 이미지 간의 유사성을 계산하는 함수를 작성해야함
def train(images, labels):
# Machine learning!
return model
모든 데이터와 라벨을 기억 (별도의 처리는 하지 않음)
def predict(model, test_images):
# Use model to predict labels
return test_labels
label을 예측하고 싶은 새 이미지를 가져와, 일종의 비교 또는 유사성 함수를 사용해 학습 데이터셋의 각 이미지와 비교
→ 학습 데이터셋에서 테스트 이미지와 가장 유사한 이미지를 추적하여 label을 반환해줌
Distance Metric to compare images
예측 단계에서 두 입력 이미지 간의 유사성을 계산할 수 있는 함수로, 의미론적으로 얼마나 유사한지 나타내는 어떤 숫자(유사도)를 출력하는 일종의 거리(pixel 간의 거리) 측정 방법을 이용
→ 가장 일반적이고 간단한 방법: L1 (Manhattan) distance
- 모든 픽셀 값이 명시적으로 적힌 4*4*4 이미지를 가정
- 테스트 이미지와 학습 이미지의 각 픽셀 값의 차에 절대값을 취해서 합산해줌
- 결과값: 두 이미지 사이의 거리(차이)를 나타내는 하나의 숫자
Nearest Neighbor Classifier
import numpy as np
class NearestNeighbor:
def __init__(self):
pass
# 학습 데이터를 기억하는 train 단계
def train(self, X, y):
""" X is N*D where each row is an example. Y is 1-dimension of size N """
# the nearest neighbor classifier simply remembers all the training data
self.Xtr = X
self.ytr = y
def predict(self, X):
""" X is N*D where each row is an example we wish to predict label for """
num_test = X.shape[0]
# lets make sure that the output type matches the input type
Ypred = np.zeros(num_test, dtype = self.ytr.dtype)
# 각각의 테스트 이미지에 대해 가장 유사한(가까운) 학습 이미지를 찾고, 해당 이미지의 라벨을 반환
# loop over all test rows
for i in xrange(num_test):
# find the nearest training image to the i'th test image
# using the L1 distance (sum of absolute value differences)
distances = np.sum(np.abs(self.Xtr - X[i, :]), axis = 1)
min_index = np.argmin(distances) # get the index with smallest distance
Ypred[i] = self.ytr[min_index] # predict the label of the nearest example
return Ypred
Q. N개의 예시가 있을 때, 학습 속도는 얼마나 빠른가? O(1)
- store pointers to all of the training → could be done in constant time
deep copy → linear time
Q. N개의 예시가 있을 때, 테스트 속도는 얼마나 빠른가? O(N)
- 테스트를 할 때마다 n개의 학습 데이터와 각각 비교해야 하기 때문에, 학습 데이터셋의 크기에 비례하여 성능 저하가 발생(pay a performance penalty that's linear in the size of the training set)함
→ This is bad: ML system에서 원하는 것과 정반대임. 학습 속도가 느린 것은 감당할 수 있지만, 우리에게는 빠른 테스트가 필요함 (실제로 모델을 사용해야 하니까...!)
신경망 기반 접근 방식(neural network based approaches)으로 전환하면 이 구조가 반전되는 것을 볼 수 있음
우리가 사용하게 될 신경망 기반 접근 방식에서는 학습하는 데 상대적으로 긴 시간이 들지만, 테스트 시에는 상대적으로 적은 시간이 소요됨
➕ 대규모 Nearest Neighbor search를 사용해야 할 때를 대비해 알아두면 좋은 알고리즘 (brute-force 방식보다 더 빠름)
제일 왼쪽 열: 테스트 셋의 예시 이미지
각 행: 학습 데이터에서 뽑아 낸 nearest neighbors
데이터셋: CIFAR10
- 픽셀 값을 직접 비교하여 이미지 간의 유사도를 계산 → 결과값은 대체로 시각적으로 매우 유사한 이미지
- L1 distance를 이용한 Nearest neighbor classifier는 실제로 그닥 똑똑하지 않고, 자신이 보고 있는 이미지에 대해 제대로 알지 못함 ( 세 번째 행을 참고: 주황 계열의 물체에, 초록 배경이 있는 이미지들이 비행기와 유사하게 판단되었음)
- 10개의 예시 이미지 중 4개의 이미지만 제대로 된 분류를 해냄
Nearest Neigbor Decision Boundaries
각각의 점: 학습 데이터
점의 색상: 학습 라벨 (red: cat, blue: dog, ...)
배경 색상: 테스트를 진행할 때 그 공간의 점에 할당될 카테고리 라벨
결정 경계(Decision boundary): 다른 범주 간의 경계
- 잡음이 많을 수 있음 (이상치에 영향을 받음, 매끄럽지 못한 경계)
- 가장 가까운 이웃에만 의존해 분류하기 때문
- 학습 데이터셋의 노란 점 하나가 초록 점들 사이에 있을 경우 → 노란 점 주변의 테스트 예시들이 노란 색으로 분류될 수 있음
Q. 어떻게 하면 결정 경계를 부드럽게 만들 수 있는가? 더 많은 이웃을 사용
K-Nearest Neighbors (KNN)
우리는 Nearest Neighbor 탐색을 진행할 때 가장 가까이에 위치한 이웃 하나를 사용했지만 (k=1)
여러 개의 가까운 이웃을 같이 고려할 수 있음 (k=3) → K개의 가장 가까운 이웃 label 중 다수결(majority vote)을 따르자!
여러 개의 이웃을 같이 고려할 경우 결정 경계가 부드러워지고, 이상치에 의한 영향이 줄어듦
여전히 학습 데이터 셋의 노란 점 하나가 초록 점 사이에 있지만 더이상 오분류가 발생하지 않음
하지만 K가 1보다 클 경우, 클래스 간의 동률이 생길 수 있음 (can be ties between classes) → 어느 클래스로도 분류되지 못함
따라서 이를 처리하기 위한 별도의 방법이 필요 (경험적 추론 등)
K-Nearest Neighbors: Distance Metric
더 많은 이웃을 사용하는 것 외에도 거리(유사도) 측정 방법을 변경함으로써 결정 경계를 부드럽게 할 수 있음
L2 (Euclidean) distance → 이미지의 픽셀을 긴 벡터로 변환, 유클리드 거리를 계산
- L1 distance: 모든 결정경계가 선형이며 축에 맞춰져 있음 (vertical line segments, horiaontal line segment, 45-degree angle line segment ...)
- L2 distance: 결정 경계가 여전히 선형이지만 여러 방향으로 나타날 수 있음
→ L1과 L2 중 어떤 것이 큰 차이를 만들지, 이미지 분류에 어떤 결과를 만들어낼지는 직관적으로 명확하지 않음
→ 하지만 적절한 거리 측정 방법을 선택한다면, 어떤 유형의 데이터에도 KNN 방법을 적용해볼 수 있음
tf-idf 유사성 계산 방식을 적용해 KNN을 수행한 예 → 상당히 좋은 결과를 내고 있음
➡️ KNN은 상당히 단순해보이지만 다양한 유형의 데이터에 강건하게 적용되는 알고리즘
: Distance Metric을 변경함으로써 더 다양하게 적용해볼 수 있음
위의 사이트에서 Distance Metric, Number of K, Number of class, Number of point의 수를 조정하며, 결정 경계의 변화를 직접 확인해볼 수 있음
Hyperparameters
KNN을 사용할 때는 직접 결정해야 할 것들이 존재함 → 하이퍼파라미터
- What is the best value of K to use?
- What is the best distance metric to use?
하이퍼파라미터는 학습을 시작할 때 직접 값을 설정해주어야 함 (알고리즘이 직접 학습할 수 없음)
문제마다 적합한 하이퍼파라미터 값이 매우 다르게 나타나므로 다양하게 시도해보고, 우리의 데이터/작업에 가장 잘 맞는 값이 무엇인지 직접 확인해야봐야 함
Setting Hyperparameters
Idea #1 주어진 데이터(training dataset)에 대해 가장 높은 성능을 보이는 하이퍼파라미터를 고르기
- 단점: 이 방법을 채택할 경우 항상 K=1로 설정하게 됨. 이 경우 주어진 데이터에 대해서는 항상 완벽한 성능을 보이지만 앞에서 확인했듯 잡음이 많고 이상치에 많은 영향을 받음
Idea #2 데이터를 학습 데이터셋과 테스트 데이터셋으로 나눈 후 테스트 데이터에 대해 가장 높은 성능을 보이는 하이퍼파라미터를 고르기
- 우리가 보지 못한 데이터에 대해서도 일반화하고 싶은 게 우리의 목표기 때문에 합리적으로 보임
하지만 틀렸어요! - 단점: 테스트 데이터에 대해 학습하는 방식으로 학습 데이터에 대해서는 훈련이 되지 않음. 또한 학습 과정에서 테스트 데이터를 사용하게 되면 보지 못한 데이터에 대해 일반화하고자 하는 우리의 목표를 달성할 수 없게 됨. (더이상 보이지 않는 데이터가 존재하지 않음)
Idea #3 데이터를 학습, 검증, 테스트 데이터셋으로 나눈 후 검증 데이터를 통해 하이퍼파라미터를 조정하고, 테스트 데이터를 통해 평가함
- train: 연습문제 / validation: 모의고사 / test: 수능
- 테스트 세트는 평가할 때만 사용 → 보이지 않는 데이터에 대한 알고리즘 성능을 평가할 수 있음
- 하지만 테스트 세트에서 결과가 좋지 않게 나오면 사용할 수 없게 됨
모든 노력이 수포로 돌아가...
Idea #4 교차검증 데이터를 학습 및 검증, 테스트 데이터셋으로 나눈 후 학습 및 검증 데이터를 fold로 나눔. 각각의 fold에 대해 검증을 수행 후 평균해서 결과를 냄
- 해당 예시에서는 5가지 버전을 시도해볼 수 있음
- fold 1~4 학습, fold 5 검증
- fold 1~3, 5 학습, fold 4 검증 등
- 하이퍼파라미터가 보이지 않는 데이터에 대해 어떠한 수행 능력을 낼지 좀 더 쉽게 파악할 수 있음
- 5개의 버전 중 가장 좋은 성능을 내는 하이퍼파라미터를 택하면 됨
- 가장 정확하고 좋은 성능을 낼 수 있는 작업임에도 불구하고 ML/DL에서는 잘 사용되지 않음 → 계산 비용 많이 듦
- 계산 비용을 감당할 수 있는 작은 모델이나 작은 데이터셋에 대해서는 유용할 수 있음
- X축: 하이퍼파라미터 K / Y축: 교차 검증 정확도
- 꺾은 선 그래프: 정확도의 평균값 / 세로 선: X에 대한 Y의 표준편차
- 5번의 교차검증을 하고 있으므로 각 X에 대해 5개의 Y값이 나타남
그래프를 통해 k가 7일 때의 교차 검증 정확도가 가장 높은 것을 확인할 수 있음!
K-Nearest Neighbor: Universal Approximation (보편성)
KNN은 학습 샘플의 수가 무한대로 갈 때, 어떠한 함수라도 나타낼 수 있음
- 어떠한이라고 표현하긴 했지만, 많은 기술적 조건이 전제되어 있음
- 특정 도메인 상의 연속적인 함수에만 적용, 학습 포인터의 간격에 대한 가정이 필요함 등
- 파란 선: 정답 함수 (우리는 이 함수에 가까운 출력을 하는 모델을 만들어내고 싶음)
- 초록 선: NN이 예측한 함수
- 검은 점: 개별 학습 데이터
학습에 사용하는 데이터가 늘어날수록 정답 함수를 잘 근사하고 있는 것을 확인할 수 있음!
→ 이제 우리가 할 일은 많은 데이터를 수집하는 것뿐...이라고 생각했지만 문제가 발생함 (Curse of Dimensionality)
Problem: Curse of Dimensionality
차원의 저주: 공간을 균일하게 커버하기 위해서 필요한 학습 데이터의 수는 차원의 증가와 함께 지수적으로 증가함
32*32 낮은 해상도의 흑백 이미지를 가정할 경우에도 2³²*³², 약 10³⁰⁸개의 학습 데이터가 필요함
→ 이는 매우 큰 값이므로 (눈에 보이는 우주에 존재하는 기본 입자의 수가 10⁹⁷) 필요한 학습 데이터를 준비하는 것이 불가능하다는 뜻
→ 그렇다면 공간에 여백이 많아진다는 것은 무슨 의미? 계산 비용이 많이 필요함을 의미함 (성능 저하)
→ 해결법: PCA와 같은 차원 축소 방법 적용
K-Nearest Neighbor in raw pixels is seldom used
KNN은 매우 좋은 알고리즘이지만 raw pixel에서는 거의 사용되지 않음
- 테스트 속도가 매우 느림 (우리가 ML에서 원하는 것과 반대)
- 데이터가 매우 부족함 (공간을 균일하게 커버할 만큼의 데이터를 얻는 게 매우 어려움)
- pixel에 대한 거리(유사도) 측정이 유용한 정보를 제공하지 못함
- L1과 L2 distance는 그다지 민감하지 않고, 이미지 간의 변화를 제대로 포착하지 못함
- 가장 왼쪽의 원본 이미지에서 변형을 적용한 세 개의 이미지 간의 L2 distance를 계산해보면 동일한 결과가 나옴 (우리가 직관적으로 판단할 땐 Shifted 이미지가 Boxed 이미지나 Tinted 이미지보다는 유사도가 높게 나와야 할 것 같지만 아님)
Nearest Neighbor with ConvNet features works well!
- 합성곱 신경망에서 계산된 특징 벡터를 NN 알고리즘에 사용하면 매우 잘 동작함
- 특징 벡터는 상당히 의미있는 값으로 유사한 이미지들을 출력할 수 있도록 도와줌 (기존 NN 알고리즘에서 파악하지 못했던 의미론적 격차를 메울 수 있음!)
- Example: Image Captioning with Nearest Neighbor
Summary
- 이미지 분류는 이미지와 라벨로 구성된 학습 데이터셋으로 시작해, 테스트 데이터셋에서 라벨 값을 예측함
- 이미지 분류는 의미론적 차이에 의해 해결해야할 사항들이 존재함
- 우리는 폐색, 변형, 조명, 클래스 내 세부 개체 등 앞서 언급한 다양한 문제점에 대해서도 강건한 알고리즘이 필요!
- 이미지 분류는 다양한 비전 작업의 구성 요소(building block)으로 사용됨
- KNN 분류기는 가장 가까운 학습 예시를 기반으로 라벨을 예측함
- Distance metric, K는 하이퍼파라미터
- 하이퍼파라미터는 검증 데이터를 이용해 선택해야하고, 테스트 데이터는 마지막 단계에서 단 한번만 이용해야함!
'AI > EECS 498-007 (598-005)' 카테고리의 다른 글
[EECS 498-007 / 598-005] Lecture 4. Optimization (1) | 2024.01.16 |
---|