728x90
VGGNet
카렌 시모니안(Karen Simonyan)과 앤드류 지서만(Andrew Zisserman)이 2015
ICLR에 게재한 “Very deep convolutional networks for large-scale image recognition” 논문
에서 처음 발표
합성곱층의 파라미터 수를 줄이고 훈련 시간을 개선
- 커널의 크기 3x3, 최대 풀링 커널 크기 2x2 스트라이드 2
copy
얕은복사 vs 깊은 복사
얕은 복사는 복사 전 값을 바꿔도 복사한 것이 바뀌지 않음
얕은 복사는 copy.copy()를 이용
Code
def calculate_accuracy(y_pred, y):
top_pred = y_pred.argmax(1, keepdim = True)
correct = top_pred.eq(y.view_as(top_pred)).sum()
acc = correct.float() / y.shape[0]
return acc
- eq는 equal의 약자로 서로 같은지를 비교하는 표현식
- view_as(other)는 other의 텐서 크기를 사용하겠다는 의미
def train(model, iterator, optimizer, criterion, device):
epoch_loss = 0
epoch_acc = 0
model.train()
for (x, y) in iterator:
x = x.to(device)
y = y.to(device)
optimizer.zero_grad()
y_pred, _ = model(x)
loss = criterion(y_pred, y)
acc = calculate_accuracy(y_pred, y)
loss.backward()
optimizer.step()
epoch_loss += loss.item()
epoch_acc += acc.item()
return epoch_loss / len(iterator), epoch_acc / len(iterator)
- epoch_loss, epoch_acc 누적
평가함수
def evaluate(model, iterator, criterion, device):
epoch_loss = 0
epoch_acc = 0
model.eval()
with torch.no_grad():
for (x, y) in iterator:
x = x.to(device)
y = y.to(device)
y_pred, _ = model(x)
loss = criterion(y_pred, y)
acc = calculate_accuracy(y_pred, y)
epoch_loss += loss.item()
epoch_acc += acc.item()
return epoch_loss / len(iterator), epoch_acc / len(iterator)
- torch.no_grad()를 사용하여 반복
시간 측정 함수
def epoch_time(start_time, end_time):
elapsed_time = end_time - start_time
elapsed_mins = int(elapsed_time / 60)
elapsed_secs = int(elapsed_time - (elapsed_mins * 60))
return elapsed_mins, elapsed_secs
-
시간 측정 함수
-
time.monotonic() : 하드웨어에서 계산하는 시간
모델 학습
import time
EPOCHS = 5
best_valid_loss = float('inf')
for epoch in range(EPOCHS):
start_time = time.monotonic()
train_loss, train_acc = train(model, train_iterator, optimizer, criterion, device)
valid_loss, valid_acc = evaluate(model, valid_iterator, criterion, device)
if valid_loss < best_valid_loss:
best_valid_loss = valid_loss
torch.save(model.state_dict(), 'VGG-model.pt')
end_time = time.monotonic()
epoch_mins, epoch_secs = epoch_time(start_time, end_time)
print(f'Epoch: {epoch+1:02} | Epoch Time: {epoch_mins}m {epoch_secs}s')
print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')
print(f'\t Valid. Loss: {valid_loss:.3f} | Valid. Acc: {valid_acc*100:.2f}%')
예측
def get_predictions(model, iterator):
model.eval()
images = []
labels = []
probs = []
with torch.no_grad():
for (x, y) in iterator:
x = x.to(device)
y_pred, _ = model(x)
y_prob = F.softmax(y_pred, dim = -1)
top_pred = y_prob.argmax(1, keepdim = True)
images.append(x.cpu())
labels.append(y.cpu())
probs.append(y_prob.cpu())
images = torch.cat(images, dim = 0)
labels = torch.cat(labels, dim = 0)
probs = torch.cat(probs, dim = 0)
return images, labels, probs
- y_prob = F.softmax(y_pred, dim = -1) = -1은 맨 마지막 인덱스 의미
- softmax는 클래스 확률 계산(다중분류)에 주로 쓰임
예측중에서 정확하게 예측한 것 추출
images, labels, probs = get_predictions(model, test_iterator)
pred_labels = torch.argmax(probs, 1)
corrects = torch.eq(labels, pred_labels)
correct_examples = []
for image, label, prob, correct in zip(images, labels, probs, corrects):
if correct:
correct_examples.append((image, label, prob))
correct_examples.sort(reverse = True, key = lambda x: torch.max(x[2], dim = 0).values)
[.2 .8 .4 .4 .5]
np.max -> .8 (최대값)
np.argmax -> 1 (최대값의 인덱스)
번외
x = torch.randn([4,4])
print(x)
max_elements, max_idxs = torch.max(x, dim=0)
print(max_elements)
print(max_idxs)
'''
tensor([[-0.2984, 0.2491, -0.0098, -0.3784],
[-0.0150, 0.3422, 1.7460, -0.1150],
[-0.3944, -0.3097, 1.9204, 0.2835],
[ 1.7026, 1.3582, -0.2195, -0.3425]])
tensor([1.7026, 1.3582, 1.9204, 0.2835])
tensor([3, 3, 2, 2])
'''
- dim=0 행 기준으로 가장 큰 값
이미지 출력을 위한 전처리
def normalize_image(image):
image_min = image.min()
image_max = image.max()
image.clamp_(min = image_min, max = image_max)
image.add_(-image_min).div_(image_max - image_min + 1e-5)
return image
- clamp는 주어진 min, max의 범주에 이미지가 위치하도록 함
- image.clamp_ 는 원본의 이미지를 수정하면서 반환하지 않는 조건
- image.add_ 는 이미지의 픽셀값을 정렬하기위한 연산
- 픽셀 값은 0이상의 값으로 세팅이됨
- (image_max - image_min + 1e-5) 최대에서 최소값을 빼고 엡실론을 더해서 ZeroDivision 방지
- Clamping이란 최댓값과 최솟값으로 범주화 시키는 것을 의미
def plot_most_correct(correct, classes, n_images, normalize = True):
rows = int(np.sqrt(n_images))
cols = int(np.sqrt(n_images))
fig = plt.figure(figsize = (25, 20))
for i in range(rows*cols):
ax = fig.add_subplot(rows, cols, i+1)
image, true_label, probs = correct[i]
image = image.permute(1, 2, 0)
true_prob = probs[true_label]
correct_prob, correct_label = torch.max(probs, dim = 0)
true_class = classes[true_label]
correct_class = classes[correct_label]
if normalize:
image = normalize_image(image)
ax.imshow(image.cpu().numpy())
ax.set_title(f'true label: {true_class} ({true_prob:.3f})\n' \
f'pred label: {correct_class} ({correct_prob:.3f})')
ax.axis('off')
fig.subplots_adjust(hspace = 0.4)
- image.permute(1, 2, 0) 기존의 (채널, 행, 열)을 -> (행, 열, 채널)로 변경
- if normalize: 대체 행열
반응형
'Education > ICT AI 중급' 카테고리의 다른 글
4주차_16 필기 (RNN) (0) | 2023.10.15 |
---|---|
4주차_15 필기 (ResNet) (0) | 2023.10.15 |
3주차_13 필기 (LeNet, Alexnet) (0) | 2023.10.15 |
3주차_12 필기 (전이학습) (1) | 2023.10.15 |
3주차_11 필기 (CNN) (1) | 2023.10.15 |