Fine Tuning (1)

5단 분석법

순서
분석
단어
내용
1
일반 명사
Fine
질 높은, 질 좋은
Tuning
조율, 세부 조정
Fine Tuning
질 좋은 조율, 조정
2
고유 명사
Fine Tuning
사전 훈련된 모델을 새로운 데이터셋에 맞춰 미세 조정하여 성능을 최적화하는 과정
3
사용 이유
Fine Tuning
새로운 데이터셋에 대해 모델의 성능을 최적화하면서 학습 시간을 단축하고, 데이터 부족 문제를 극복하기 위해서
4
사용 방법
Fine Tuning
5
다른 기술과의 비교
Fine Tuning
-

정의

일반 명사

Fine
질 높은, 질 좋은
Tuning
조율, 세부 조정
Fine Tuning
질 좋은 조율, 조정
Fine은 질 높은, 질 좋은 이라는 뜻입니다.
Tuning은 조율, 세부 조정 입니다.
Fine Tuning의 뜻을 추측해보면, 질 좋은 조율, 조정이라고 생각할 수 있습니다.
고유 명사를 알아볼까요?

고유 명사

Fine Tuning
사전 훈련된 모델을 새로운 데이터셋에 맞춰 미세 조정하여 성능을 최적화하는 과정
Fine Tuning은 사전 훈련된 모델을 새로운 데이터셋에 맞춰 미세 조정하여 성능을 최적화하는 과정 입니다.
Fine Tuning을 통해 사전 훈련된 모델의 기존 지식을 활용하면서 새로운 데이터셋에 대한 학습을 쉽고 빠르게 진행할 수 있습니다.

사용 이유

Fine Tuning
새로운 데이터셋에 대해 모델의 성능을 최적화하면서 학습 시간을 단축하고, 데이터 부족 문제를 극복하기 위해서
Fine Tuning을 사용하는 이유는 새로운 데이터셋에 대해 모델의 성능을 최적화하면서 학습 시간을 단축하고, 데이터 부족 문제를 극복하기 위해서 입니다.
이유
설명
학습 시간 단축
사전 훈련된 모델을 사용하여 처음부터 모델을 학습시키는 것보다 빠르게 학습을 진행할 수 있습니다.
데이터 부족 문제 해결
충분한 데이터가 없는 상황에서도 사전 훈련된 모델의 지식을 활용하여 좋은 성능을 얻을 수 있습니다.
모델 성능 향상
새로운 데이터셋에 맞춰 모델을 조정함으로써 최적의 성능을 도출할 수 있습니다.

사용 방법

아래와 같은 방법이 있습니다.

1. Full Fine Tuning

Full Fine Tuning은 모델의 모든 파라미터를 새로운 데이터셋에 맞추어 학습하는 과정입니다.
Full Fine Tuning은 모델이 새로운 작업에 완전히 적응하도록 하기 때문에 가장 높은 성능을 기대할 수 있습니다.
다만, 많은 데이터와 계산 자원이 필요할 수 있으며, 학습 시간이 오래 걸릴 수 있습니다.

단계

1.
사전 학습된 모델 불러오기
2.
모델의 구조 변경 (새로운 분류 레이어 추가)
3.
모든 레이어를 동결 해제
4.
모델 컴파일
5.
전체 모델 학습
6.
모델 평가
기존 코드
튜닝 후 코드
동결이라는게 무엇인가요?
모델의 레이어를 동결(freeze)한다는 것은 해당 레이어의 가중치가 학습 중에 업데이트되지 않도록 고정하는 것을 의미합니다. 이는 사전 학습된 모델의 특정 레이어가 이미 충분히 잘 학습되었다고 판단될 때 사용됩니다. 동결을 통해 다음과 같은 이점을 얻을 수 있습니다:
계산 자원 절약: 동결된 레이어는 학습 중에 업데이트되지 않기 때문에, 계산 비용이 줄어듭니다.
과적합 방지: 일부 레이어를 동결하여 학습 파라미터 수를 줄이면, 과적합을 방지할 수 있습니다.
효율적 학습: 상위 레이어만 조정하여 새로운 데이터셋에 맞추는 방식으로 학습 시간을 단축할 수 있습니다.
동결을 해제(unfreeze)하는 경우, 해당 레이어의 가중치가 학습 중에 업데이트되어 새로운 데이터셋에 맞춰 조정됩니다. 이는 모델이 새로운 작업에 더 잘 적응할 수 있게 합니다.
왜 학습 파라미터 수가 줄어들면 과적합 방지에 도움이 되나요?
1.
모델 복잡도 감소: 모델의 학습 파라미터 수를 줄이면 모델의 복잡도가 낮아집니다. 이는 모델이 훈련 데이터의 특정 패턴이나 노이즈에 과도하게 맞추는 것을 방지하여, 새로운 데이터에 대해 더 잘 일반화할 수 있게 합니다.
2.
정규화 효과: 동결된 레이어는 이미 잘 학습된 가중치를 유지하고, 새로운 데이터셋에 대해 상위 레이어만 학습하게 됩니다. 이는 모델이 새로운 데이터셋에 대해 더 안정적이고 일관된 학습을 할 수 있게 도와줍니다.
3.
과도한 최적화 방지: 모든 레이어를 학습시키면 모델이 훈련 데이터에 너무 잘 맞추려 하여, 훈련 데이터에 대한 성능은 높지만 새로운 데이터에 대해 성능이 떨어지는 과적합이 발생할 수 있습니다. 일부 레이어를 동결하면 이런 과도한 최적화를 방지할 수 있습니다.

2. Partial Fine Tuning

Partial Fine Tuning은 모델의 일부 파라미터만 조정하는 방법입니다.
예를 들어, 모델의 상위 층(layer)만 미세 조정하고, 하위 층은 그대로 두는 방식입니다.
이렇게 하면 학습 시간이 단축되고, 과적합(overfitting) 문제를 줄일 수 있습니다.

단계

사전 학습된 모델 불러오기
모델의 구조 변경 (새로운 분류 레이어 추가)
하위 레이어를 동결하고, 상위 레이어만 동결 해제
모델 컴파일
일부 레이어 학습
모델 평가
하위 레이어와 상위 레이어가 무엇인가요?

하위 레이어 (Lower Layers)

입력층에 가까운 레이어: 하위 레이어는 모델의 입력층(input layer) 근처에 있는 레이어를 의미합니다.
기본 특징 추출: 이 레이어들은 주로 이미지나 텍스트의 저수준(low-level) 특징을 추출하는 역할을 합니다. 예를 들어, 이미지의 경우 가장 기본적인 에지(edge)나 색상, 텍스처 등을 추출합니다.

상위 레이어 (Upper Layers)

출력층에 가까운 레이어: 상위 레이어는 모델의 출력층(output layer) 근처에 있는 레이어를 의미합니다.
고수준 특징 추출 및 분류: 이 레이어들은 하위 레이어에서 추출된 저수준 특징을 바탕으로 더 복잡하고 추상적인 고수준(high-level) 특징을 추출하고, 최종적으로 분류(classification)나 예측(prediction) 등의 작업을 수행합니다.

예시: CNN 모델

예를 들어, CNN(Convolutional Neural Network) 모델의 경우:
하위 레이어: 초기의 합성곱(convolutional) 및 풀링(pooling) 레이어는 이미지의 저수준 특징을 추출합니다. 이러한 레이어들은 입력층에 가깝습니다.
상위 레이어: 나중의 완전 연결층(fully connected layers) 또는 밀집층(dense layers)은 추출된 특징을 바탕으로 분류를 수행합니다. 이러한 레이어들은 출력층에 가깝습니다.

파인튜닝과 상위/하위 레이어

파인튜닝을 할 때 상위 레이어와 하위 레이어의 역할을 이해하는 것은 중요합니다:
하위 레이어 동결: 일반적으로 하위 레이어는 기본적인 특징 추출 능력을 잘 학습하고 있기 때문에, 새로운 데이터셋에 대해 동결(freeze)됩니다. 이렇게 하면 모델이 이미 잘 학습된 저수준 특징을 유지할 수 있습니다.
상위 레이어 재학습: 상위 레이어는 새로운 데이터셋에 맞춰 조정되며, 새로운 데이터셋의 고수준 특징을 학습합니다. 이를 통해 모델이 새로운 작업에 적응할 수 있습니다.
튜닝 후 코드

3. 단계적 파인튜닝

이 방법은 먼저 상위 레이어만 재학습하고, 그 다음 단계에서 하위 레이어까지 포함하여 재학습하는 접근법입니다.
이는 점진적으로 모델을 최적화하는 데 사용됩니다.

단계:

1.
사전 학습된 모델 불러오기
2.
모델의 구조 변경 (새로운 분류 레이어 추가)
3.
기본 레이어를 동결
4.
모델 컴파일
5.
상위 레이어 학습
6.
하위 레이어 동결 해제 및 상위 레이어 일부 동결 유지
7.
모델 재컴파일 및 전체 모델 학습
8.
모델 평가
튜닝 후 코드

4. 전이 학습 (Transfer Learning)

전이 학습은 사전 학습된 모델의 하위 레이어를 그대로 사용하고, 상위 레이어만 변경하여 새로운 데이터셋에 맞추는 것입니다. 이는 원래 데이터셋과 새로운 데이터셋이 매우 유사할 때 효과적입니다.

단계:

1.
사전 학습된 모델 불러오기 (include_top=False로 로드)
2.
모델의 구조 변경 (새로운 분류 레이어 추가)
3.
모든 하위 레이어를 동결
4.
모델 컴파일
5.
새로운 상위 레이어 학습
6.
모델 평가
튜닝 후 코드

5. 하이브리드 방법

이 방법은 여러 파인튜닝 방법을 결합하여 사용합니다. 예를 들어, 일부 레이어 파인튜닝과 단계적 파인튜닝을 결합하여 모델을 최적화합니다.

단계:

1.
사전 학습된 모델 불러오기
2.
모델의 구조 변경 (새로운 분류 레이어 추가)
3.
하위 레이어를 동결하고, 상위 레이어만 동결 해제
4.
모델 컴파일
5.
상위 레이어 학습
6.
일부 하위 레이어 동결 해제
7.
모델 재컴파일 및 전체 모델 학습
8.
모델 평가
튜닝 후 코드
예시는 ‘Partial Fine Tuning’으로 사례를 들도록 하겠습니다.

TensorFlow

PyTorch

알아 두면 좋은 정보

미니 퀘스트

1번 미니퀘스트 - MNIST 데이터셋을 사용해 Fine Tuning 하기

MNIST 데이터셋을 사용하여 FCNN을 학습하고 평가해 보세요.

문제 설명

1.
라이브러리 임포트
2.
데이터 준비
# 데이터 변환 및 로드 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform) val_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)
Python
복사
3.
모델 정의
4.
손실 함수 및 옵티마이저 정의
5.
모델 훈련
6.
모델 평가 및 예측

코드

import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader from torchvision import datasets, transforms # 데이터 변환 및 로드 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform) val_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False) class FCNN(nn.Module): def __init__(self, input_dim, num_classes): super(FCNN, self).__init__() self.fc1 = nn.Linear(input_dim, 128) self.fc2 = nn.Linear(128, 64) self.fc3 = nn.Linear(64, num_classes) def forward(self, x): x = x.view(-1, 28*28) # Flatten the image x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) x = self.fc3(x) return x model = FCNN(28*28, 10) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 모델 훈련 함수 def train_model(model, criterion, optimizer, train_loader, val_loader, num_epochs=10): for epoch in range(num_epochs): print(f'Epoch {epoch}/{num_epochs - 1}') print('-' * 10) # 각 에포크마다 훈련 및 검증 for phase in ['train', 'val']: if phase == 'train': model.train() loader = train_loader else: model.eval() loader = val_loader running_loss = 0.0 running_corrects = 0 # 데이터 반복 for inputs, labels in loader: inputs, labels = inputs.to(device), labels.to(device) # 매개변수 경사도를 0으로 설정 optimizer.zero_grad() # 순전파 with torch.set_grad_enabled(phase == 'train'): outputs = model(inputs) _, preds = torch.max(outputs, 1) loss = criterion(outputs, labels) # 훈련 시에만 역전파 및 옵티마이저 단계 수행 if phase == 'train': loss.backward() optimizer.step() # 통계 계산 running_loss += loss.item() * inputs.size(0) running_corrects += torch.sum(preds == labels.data) epoch_loss = running_loss / len(loader.dataset) epoch_acc = running_corrects.double() / len(loader.dataset) print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}') print() return model # GPU 사용 설정 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model = model.to(device) # 모델 훈련 model = train_model(model, criterion, optimizer, train_loader, val_loader, num_epochs=10) # 모델 평가 model.eval() correct = 0 total = 0 with torch.no_grad(): for inputs, labels in val_loader: inputs, labels = inputs.to(device), labels.to(device) outputs = model(inputs) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total print(f"Validation Accuracy: {accuracy:.2f}%") # 모델 예측 sample_input = torch.tensor(val_dataset.data[:5].float()).to(device) sample_input = sample_input.view(-1, 28*28) predictions = model(sample_input).detach().cpu().numpy() print("Predictions: ", predictions) print("True labels: ", val_dataset.targets[:5].numpy())
Python
복사

코드 설명

2번 미니퀘스트 - CIFAR-10 데이터셋을 사용해 Fine Tuning 하기

이번에는 CIFAR-10 데이터셋을 사용해 Fine Tuning을 진행해 보세요.
CIFAR-10 데이터셋은 10개의 클래스(비행기, 자동차, 새, 고양이, 사슴, 개, 개구리, 말, 배, 트럭)로 구성된 60,000개의 32x32 컬러 이미지로 이루어져 있습니다.

문제 설명

1.
라이브러리 임포트
2.
데이터 준비
# 데이터 변환 및 로드 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) val_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)
Python
복사
3.
모델 정의
4.
손실 함수 및 옵티마이저 정의
5.
모델 훈련
6.
모델 평가 및 예측

코드

import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader from torchvision import datasets, transforms # 데이터 변환 및 로드 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) val_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False) # 모델 정의 class FCNN(nn.Module): def __init__(self, input_dim, num_classes): super(FCNN, self).__init__() self.fc1 = nn.Linear(input_dim, 512) self.fc2 = nn.Linear(512, 256) self.fc3 = nn.Linear(256, num_classes) def forward(self, x): x = x.view(-1, 32*32*3) # Flatten the image x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) x = self.fc3(x) return x model = FCNN(32*32*3, 10) # 손실 함수 및 옵티마이저 정의 criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 모델 훈련 함수 def train_model(model, criterion, optimizer, train_loader, val_loader, num_epochs=10): for epoch in range(num_epochs): print(f'Epoch {epoch}/{num_epochs - 1}') print('-' * 10) # 각 에포크마다 훈련 및 검증 for phase in ['train', 'val']: if phase == 'train': model.train() loader = train_loader else: model.eval() loader = val_loader running_loss = 0.0 running_corrects = 0 # 데이터 반복 for inputs, labels in loader: inputs, labels = inputs.to(device), labels.to(device) # 매개변수 경사도를 0으로 설정 optimizer.zero_grad() # 순전파 with torch.set_grad_enabled(phase == 'train'): outputs = model(inputs) _, preds = torch.max(outputs, 1) loss = criterion(outputs, labels) # 훈련 시에만 역전파 및 옵티마이저 단계 수행 if phase == 'train': loss.backward() optimizer.step() # 통계 계산 running_loss += loss.item() * inputs.size(0) running_corrects += torch.sum(preds == labels.data) epoch_loss = running_loss / len(loader.dataset) epoch_acc = running_corrects.double() / len(loader.dataset) print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}') print() return model # GPU 사용 설정 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model = model.to(device) # 모델 훈련 model = train_model(model, criterion, optimizer, train_loader, val_loader, num_epochs=10) # 모델 평가 model.eval() correct = 0 total = 0 with torch.no_grad(): for inputs, labels in val_loader: inputs, labels = inputs.to(device), labels.to(device) outputs = model(inputs) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total print(f"Validation Accuracy: {accuracy:.2f}%") # 모델 예측 sample_input = torch.tensor(val_dataset.data[:5]).float().to(device) sample_input = sample_input.permute(0, 3, 1, 2) # Change shape from (N, H, W, C) to (N, C, H, W) predictions = model(sample_input).detach().cpu().numpy() print("Predictions: ", predictions) print("True labels: ", val_dataset.targets[:5])
Python
복사

코드 설명

미니퀘스트 답안지

ⓒ 2024 startupcode. 모든 권리 보유. 무단 복제 금지.