이미지 인식이란?
컴퓨터비전 및 객체인식 활용분야
- 오브젝트 디텍션 : 이미지에 사각형을 그려서 인식 (실시간)
- 이미지 세그멘테이션: 픽셀 단위로 분석 (분포 확인)
이미지 인식
- 인간은 이미지와 label을 매칭한 경험으로 이미지를 인식한다.
- 컴퓨터는 머신러닝 모델을 통해 이미지를 인식한다.
- 기계가 분석할 수 있는 데이터로 변경
- 입력값: 이미지
- 출력값: 픽셀의 색상 숫자 (흑백의 경우 0~255)
ILSVRC 2012 AlexNet
제프리 힌튼 교수팀이 lLSVRC 이미지 인식 대회에서, 딥러닝 모델인 AlextNet으로 우승하였다. 직전 성능에 비해 오류율을 10%나 줄였다.
CNN - 합성곱 신경망
CNN이란?
- 근접 수용 영역: 일정 범위 안의 자극에만 활성화되는 영역.
- 합성곱 신경망: 특정 국소 영역에 속하는 노드들의 연결로 이루어진 인공 신경망. 완전 연결층이 아니다.
- 완전 연결층: 인접한 두 층의 노드들이 전부 연결되어 있음.
- 얀 르쿤 교수는 특정 부분의 자극에 반응하는 합성곱 신경망 모델을 제안했다.
- '합성곱신경망'은 '필터링'과 '분류' 단계를 거친다.
- 필터링
- 피처맵: 필터링을 거친 데이터
- 필터링은 딥러닝 3가지 관점 중 2번째 관점과 유사하다.
- 2관점: 활성화 함수가 비선형 데이터를 선형패턴화하는 역할을 한다.
- Convolution층 + Pooling층 + Fully-connected층
- 필터링
- Convolution: 근접 수용 영역 존재
- Pooling
- 분류
- Fully-connected (완전연결층)
CNN 학습
- 공간정보 보존학습
- 거리가 가까운 픽셀들은 연관성을 갖는다.
- 인접한 픽셀들의 연관성을 학습한다.
- CNN은 완전 연결 신경망과 다르게 입력 데이터의 원래 구조(공간정보)를 유지한다. (높이, 너비, 채널)
- CNN은 그래서 a영역은 A노드가 b영역은 B노드가 계산할 수 있는 것이다.
- 합성곱
- 4 * 4 입력데이터에서, 특정 영역(3*3)만 뽑아서 필터링과 곱한다. 그 결과를 피처맵의 한 부분에 매핑한다.
- 각 피처는 뉴런 1개를 의미하며, 서로영역이 겹친다.
- min cost 필터
- cost를 최소화하는 필터를 찾는다.
- 필터의 크기는 일반적으로 3*3 사용.
- 필터의 크기가 작아지면 질이 떨어질 수 있다. 필터를 여러개 사용해서 양을 늘리자.
RGB의 합성곱
- RGB 이미지의 합성 곱은 어떻게 할까?
- 1채널: 채널 합, 입력채널 압축.
3채널: 채널별로 합, 입력채널 유지.
- 필터의 파라미터(weights + bias) 구하기
- 입력값의 shape
- 32 * 32 * 3채널
- 필터의 shape
- 3 * 3 * 3채널
- 인접한 수용영역의 간격은 1칸
- Q. 출력값의 shape은?
- 30 * 30 * 1채널
- 3*3 필터는 결과값을 3-1= 2칸 줄인다.
- 5*5 필터는 결과값을 5-1= 4칸 줄인다.
- Q. 만약 채널이 8종류 였다면, 출력값의 shape은?
- 30 * 30 * 8채널
- Q. 이때의 weights 의 값은?
- 필터(3 * 3 * 3) * 8채널 = 216
- Q. 이때의 bias 의 값은?
- 필터당 1개씩 존재하므로, = 8
- Q. 이때의 총 필터의 파라미터(weights + bias)는?
- 필터(3 * 3 * 3 + 1) * 8채널 = 224
- 두번째 conv 층에서 채널 설정
- 입력값의 shape
- 30 * 30 * 8채널
- Q. 3 * 3 필터의 shape은?
- 3 * 3 * 8채널
- 입력채널 = 필터채널
- Q. 출력값의 shape은?
- 28 * 28 * 1채널
- '필터+피처맵'의 연속성
- 첫번째 필터의 갯수(종류)가 8이면, 피처맵은 8채널이 되고, 그 다음 필터의 채널은 8채널이 된다.
패딩과 스트라이드
- Same padding
- Conv 연산을 수행할 때, 이미지의 크기가 2씩 줄어드는 것을 해소하기 위해 사용하는 패딩(padding) 작업의 일종.
- 원본 크기 유지 목적: 모델 설계시 원본 크기가 유지되면 결과를 예측하기 편하다.
( 풀링할 때 피처맵 사이즈가 홀수가 나오게 되는 것은 정보의 손실이 발생하는 것이므로 홀수가 나오지 않도록 설계하는 것이 필요하다. 이렇게 하려면 이미지 사이즈부터 잘 설계를 해야 하는데, 패딩을 주지 않고 이를 설계하는 것은 매우 불편하다. ) - 패딩을 1로 하여, 입력 데이터의 사방을 특정 값(보통 0)으로 채우는 것을 말한다.
- 4 * 4 입력 데이터에 패딩 1을 두르면, 6 * 6이 된다.
- 필터 사이즈에 따른 패딩 (Same padding = padding)
- 3*3 필터는 결과값을 3-1= 2칸 줄인다. 원본 유지시, 패딩은 1칸
- 5*5 필터는 결과값을 5-1= 4칸 줄인다. 원본 유지시, 패딩은 2칸
- 입력 데이터의 사방을 0으로 채우는 것은, 이미지의 테두리를 검정색(000000)으로 두르는 것이다.
- 스트라이드 값, n칸씩 이동
- 4*4 입력데이터에 3*3 필터를 사용한다. 패딩은 1이다.
- 원본크기를 유지하려고 한다면, 스트라이드를 1로 준다
- 스트라이드가 2이면, 출력값은 3*3이다.
- 스트라이드가 3이면, 출력값은 2*2이다.
- 일반적으로 스트라이크가 n이면, 원본 크기가 1/n로 준다.
풀링 층
풀링은 차원 축소용
- Convolution층: 원본 크기 유지
- 일반적으로 Padding 추가, stride = 1
- Pooling층: 차원 축소
- stride != 1
- 불필요한 정보들이 너무 많을 때, 필요한 정보만 남김으로써, 계산의 효율을 높이기 위해 사용된다.
풀링 층 원소 기준
- 최대: 가장 많이 사용. 필터링 중간중간에
- 최대값: 인접한 픽셀 4개 중 가장 밝은 값만 남긴다.
- 최소
- 평균: 필터링 마지막
- 입력 피처맵이 4*4이고 풀링 사이즈가 2*2일때, 4개의 픽셀이 1개로 줄어드는 것을 알 수 있다.
- 풀링은 진행하는 영역을 겹치지 않는다. (non-overlap) 즉, stride는 2라는 것을 알 수 있다. 일반적으로 풀링 사이즈가 N일때, stride는 n이다.
- 일반적인 풀링의 상세조건
- size = 2 * 2 * 1
- stride = 2
- 3*3을 풀링(2*2, stride=2)하면?
- 1*1 (애매한 것은 그냥 버린다.)
- 애초에 홀수에 풀링을 안 거는 게 좋다.
- 입력 이미지가 2^n이 좋다. (단, 224는 예외로 하자. 왜냐하면, 풀링은 보편적으로 5번을 넘지 않는다.)
Convolution층 + Pooling층 + Fully-connected층
Pooling층은 층으로 세지 않는다. Convolution층과 Fully-connected층만 센다.
- 모델복잡도: 파라미터 크기 (층수) -> 파라미터 개수에 비례
- Conv층 모델복잡도 < fc층 모델복잡도
- 데이터복잡도: 데이터 크기에 반비례
- Conv층 데이터복잡도 > fc층 데이터복잡도
01_pytorch_MNIST
import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import torch.nn.init
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 랜덤 시드 고정 : 고정된 무작위성
torch.manual_seed(777)
# GPU 사용 가능일 경우 랜덤 시드 고정
if device == 'cuda':
torch.cuda.manual_seed_all(777)
learning_rate = 0.001
training_epochs = 5
batch_size = 128
mnist_train = dsets.MNIST(root='MNIST_data/', # 다운로드 경로 지정
train=True, # True를 지정하면 훈련 데이터로 다운로드
transform=transforms.ToTensor(), # 텐서로 변환
download=True)
mnist_test = dsets.MNIST(root='MNIST_data/', # 다운로드 경로 지정
train=False, # False를 지정하면 테스트 데이터로 다운로드
transform=transforms.ToTensor(), # 텐서로 변환
download=True)
data_loader = torch.utils.data.DataLoader(dataset=mnist_train,
batch_size=batch_size,
shuffle=True,
drop_last=True)
CNN 모델 정의
class CNN(torch.nn.Module):
def __init__(self):
super(CNN, self).__init__()
# 첫번째층
# ImgIn shape=(?, 1, 28, 28)
# Conv -> (?, 32, 28, 28)
# Pool -> (?, 32, 14, 14)
self.layer1 = torch.nn.Sequential(
torch.nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2))
# 두번째층
# ImgIn shape=(?, 32, 14, 14)
# Conv ->(?, 64, 14, 14)
# Pool ->(?, 64, 7, 7)
self.layer2 = torch.nn.Sequential(
torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2))
# 전결합층 7x7x64 inputs -> 10 outputs
self.fc = torch.nn.Linear(7 * 7 * 64, 10, bias=True)
def forward(self, x):
out = self.layer1(x)
out = self.layer2(out)
out = out.view(out.size(0), -1) # 전결합층을 위해서 Flatten
out = self.fc(out)
return out
model = CNN().to(device)
# .to('cuda') == .cuda() / .to('cpu') == .cpu()
criterion = torch.nn.CrossEntropyLoss() # 비용 함수에 소프트맥스 함수 포함되어져 있음.
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
total_batch = len(data_loader)
print('총 배치의 수 : {}'.format(total_batch))
훈련 및 테스트
for epoch in range(training_epochs):
avg_cost = 0
for X, Y in data_loader:
X = X.to(device)
Y = Y.to(device)
optimizer.zero_grad()
hypothesis = model(X) # forward 실행, 추론
cost = criterion(hypothesis, Y) # CrossEntropyLoss, 오차 산출
cost.backward() # gradient 계산
optimizer.step() # weight 업데이트
avg_cost += cost / total_batch
print('[Epoch: {:>4}] cost = {:>.9}'.format(epoch + 1, avg_cost))
with torch.no_grad():
X_test = mnist_test.test_data.view(len(mnist_test), 1, 28, 28).float().to(device)
Y_test = mnist_test.test_labels.to(device)
prediction = model(X_test)
correct_prediction = torch.argmax(prediction, 1) == Y_test
accuracy = correct_prediction.float().mean()
print('Accuracy:', accuracy.item())
나만의 CNN 모델 학습하기
목표: 성능을 최대한 끌어올리기
성능에 대한 판단:
- Overfit: trainset에 대해서는 정확성이 높고, testset에 대해서는 정확성이 낮은 상태
- Underfit: trainset에 대해서는 정확성이 낮고, testset에 대해서도 정확성이 낮은 상태
정확성이 높다? 낮다? 의 기준은???
- 모델의 정확성은 2회 이상의 시도에 대한 결과를 비교하는 것을 통해서 판단해야 한다.
- trainset accuracy: 0.9 - 정확성이 높나요??
- trainset acc만 봐서는 알수 없다. test acc도 함께 봐야 한다.
- 예시)
- 1차 시도: trainset acc : 0.9 / testset acc : 0.8
- 2차 시도: trainset acc : 0.91 / testset acc : 0.79
- 모델 복잡도(층수, 필터갯수, epoch...)를 달리 했을 때, trainset과 testset의 추세를 비교한다.
- 예시)
- 5층일 때, trainset과 testset 비교
- 6층일 때, trainset과 testset 비교
(trainset은 높아졌으나, testset은 낮아짐, overfit 판단) - 4층일 때, trainset과 testset 비교
(trainset은 낮아지고, testset도 낮아짐, underfit 판단)
생각해보기
- 비교 값 하나를 최적화 시켰다고 해도, 고정해 두었던 다른 값의 최적화를 하고 난 후에는 해당 값의 최적 값이 여전히 유효할까?
- 그렇지 않을 수 있다. 요소간의 상관관계가 존재할 수 있기 때문이다. 그래서 여러 요소간의 조합을 찾아야 하는 어려움이 있다. 조합이 너무 많다.
- 사람이 일일히 다 해야 할까? 이런 부분을 자동화하는 Auto ML 기법이 존재한다.
Overfit 개념 정리
교수님은 문제가 쉽다. 데이터복잡도는 올리고, 모델복잡도(접근방식)는 낮추자.
Tags:
AI개발_교육