파이토치 기초
역전파 흐름 w/ 예제
활성화 함수 모듈화로 구현
등등 정리 예정
파이토치 공식문서 주석달기 미션 수행
1. Data load
'''이미지 랜덤으로 크기 조절 및 자르고, 텐서변환'''
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
'''데이터 로드 및 전처리 설정'''
data_dir = '/content/hymenoptera_data'
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
data_transforms[x])
for x in ['train', 'val']} # 이미지 데이터셋 생성
dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4,
shuffle=True, num_workers=4)
for x in ['train', 'val']} # 데이터 로더 생성
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
class_names = image_datasets['train'].classes # 클래스 이름 설정
'''장치 설정 (CUDA 사용 가능시 GPU 사용, 그렇지 않으면 CPU 사용)'''
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
2. Visualize few images
'''Tensor 이미지를 화면에 표시하는 함수'''
def imshow(inp, title=None):
# Tensor를 numpy 배열로 변환 및 정규화
inp = inp.numpy().transpose((1, 2, 0))
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
inp = std * inp + mean
inp = np.clip(inp, 0, 1)
plt.imshow(inp)
if title is not None:
plt.title(title)
plt.pause(0.001)
# 훈련 데이터에서 배치 하나를 가져옴
inputs, classes = next(iter(dataloaders['train']))
# 배치에서 그리드 형태로 이미지 생성
out = torchvision.utils.make_grid(inputs)
# 이미지 화면에 표시
imshow(out, title=[class_names[x] for x in classes])
3. Train model
'''모델 훈련 함수 정의'''
def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
since = time.time() # 시작 시간 기록
# 훈련 체크포인트를 저장할 임시 디렉터리 생성
with TemporaryDirectory() as tempdir:
best_model_params_path = os.path.join(tempdir, 'best_model_params.pt')
torch.save(model.state_dict(), best_model_params_path) # 모델 초기 가중치 저장
best_acc = 0.0 # 최고 정확도 초기화
for epoch in range(num_epochs): # 각 epoch에 대해 반복
print(f'Epoch {epoch}/{num_epochs - 1}') # 현재 epoch 출력
print('-' * 10)
# 각 epoch는 훈련 및 검증 단계로 구성
for phase in ['train', 'val']:
if phase == 'train':
model.train() # 모델을 훈련 모드로 설정
else:
model.eval() # 모델을 평가 모드로 설정
running_loss = 0.0 # 누적 손실 초기화
running_corrects = 0 # 누적 정확도 초기화
# 데이터 반복
for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device) # 입력 데이터를 GPU로 이동
labels = labels.to(device) # 라벨 데이터를 GPU로 이동
# 매개변수 경사 초기화
optimizer.zero_grad()
# forward
# train 단계에서만 연산 기록 추적
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs) # 모델의 예측값 계산
_, preds = torch.max(outputs, 1) # 예측된 클래스 추출
loss = criterion(outputs, labels) # 손실 계산
# train 단계에서만 역전파 및 최적화
if phase == 'train':
loss.backward() # 역전파를 통해 그라디언트 계산
optimizer.step() # 옵티마이저 업데이트
# 통계
running_loss += loss.item() * inputs.size(0) # 손실 누적
running_corrects += torch.sum(preds == labels.data) # 정확도 누적
if phase == 'train':
scheduler.step() # 학습률 스케줄러 업데이트
epoch_loss = running_loss / dataset_sizes[phase] # epoch 손실 계산
epoch_acc = running_corrects.double() / dataset_sizes[phase] # epoch 정확도 계산
print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}') # 손실과 정확도 출력
# 최적 모델 복사
if phase == 'val' and epoch_acc > best_acc:
best_acc = epoch_acc # 최고 정확도 업데이트
torch.save(model.state_dict(), best_model_params_path) # 모델 가중치 저장
print() # 줄바꿈
time_elapsed = time.time() - since # 전체 훈련 시간 계산
print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s') # 훈련 시간 출력
print(f'Best val Acc: {best_acc:4f}') # 최고 검증 정확도 출력
# 최적 모델 가중치 로드
model.load_state_dict(torch.load(best_model_params_path))
return model # 최적 모델 반환
4. Visualizing predictions
'''모델 예측 시각화 함수 정의'''
def visualize_model(model, num_images=6):
was_training = model.training # 현재 모델의 훈련 상태 저장
model.eval() # 모델을 평가 모드로 전환
images_so_far = 0 # 시각화된 이미지 수 초기화
fig = plt.figure() # 새로운 그림 생성
with torch.no_grad(): # 그라디언트 계산 비활성화
for i, (inputs, labels) in enumerate(dataloaders['val']): # 검증 데이터 로더에서 데이터 가져오기
inputs = inputs.to(device) # 입력 데이터를 GPU로 이동
labels = labels.to(device) # 라벨 데이터를 GPU로 이동
outputs = model(inputs) # 모델의 예측값 계산
_, preds = torch.max(outputs, 1) # 예측된 클래스 추출
for j in range(inputs.size()[0]): # 각 입력에 대해 반복
images_so_far += 1 # 시각화된 이미지 수 증가
ax = plt.subplot(num_images // 2, 2, images_so_far) # 서브플롯 생성
ax.axis('off') # 축 제거
ax.set_title(f'predicted: {class_names[preds[j]]}') # 예측된 클래스 타이틀 설정
imshow(inputs.cpu().data[j]) # 이미지를 시각화
if images_so_far == num_images: # 시각화할 이미지 수에 도달하면
model.train(mode=was_training) # 원래의 훈련 상태로 복구
return # 함수 종료
model.train(mode=was_training) # 원래의 훈련 상태로 복구
... 복습 후 업로드 하기
'AI studying > TIL' 카테고리의 다른 글
ML regression wrap-up report (0) | 2024.07.25 |
---|---|
AI_lab 중간 회고! (0) | 2024.07.16 |
[ML] Classification 정리 (0) | 2024.06.05 |
코딩테스트 공부하기 (0) | 2024.05.21 |
Python EDA (1) | 2024.05.01 |