Deep learning fine tuning techniques

Posted by Hao Do on September 17, 2023

Deep learning fine tuning techniques

Kỹ thuật fine-tuning trong học sâu (deep learning)

là quá trình điều chỉnh lại mô hình đã được huấn luyện trước đó (thông qua pre-training) trên tập dữ liệu mới hoặc nhiệm vụ khác. Đây là một phương pháp phổ biến để tận dụng tri thức được học trước đó từ các mô hình lớn trên các tập dữ liệu lớn và áp dụng nó vào các tác vụ cụ thể hơn hoặc dữ liệu nhỏ hơn.

Dưới đây là một số kỹ thuật fine-tuning phổ biến:

  1. Full Fine-Tuning: Trong trường hợp này, toàn bộ mô hình (hoặc một phần lớn của nó) được tiếp tục huấn luyện trên dữ liệu mới. Điều này đòi hỏi có đủ lượng dữ liệu mới để tránh việc mô hình bị overfitting.

  2. Feature Extraction: Một cách phổ biến để fine-tuning là sử dụng mô hình đã được huấn luyện trước đó như một trình trích xuất đặc trưng. Điều này có nghĩa là các tầng cuối cùng của mô hình được loại bỏ, và một hoặc một số tầng mới được thêm vào để phù hợp với nhiệm vụ cụ thể.

  3. Fine-Tuning Một Phần: Thay vì huấn luyện toàn bộ mô hình, có thể huấn luyện chỉ một số tầng cụ thể. Thông thường, các tầng ở phía trên của mô hình (gần đầu) thường được fine-tuning nhiều hơn.

  4. Transfer Learning: Trong trường hợp mô hình đã được huấn luyện trước có nhiều lớp con và mỗi lớp con tương ứng với một tác vụ cụ thể, có thể chuyển đổi từng lớp con cho tác vụ mới mà không cần huấn luyện lại toàn bộ mô hình.

  5. Data Augmentation: Đây là kỹ thuật mở rộng tập dữ liệu bằng cách tạo ra các biến thể nhỏ về mặt hình ảnh hoặc dữ liệu đầu vào. Điều này giúp mô hình học tốt hơn trên các trường hợp biến đổi nhỏ.

  6. Regularization: Sử dụng các kỹ thuật như dropout hoặc các biến thể khác để tránh overfitting.

  7. Learning Rate Schedules: Điều chỉnh tốc độ học (learning rate) theo thời gian để đảm bảo rằng mô hình không bị dao động quá mạnh trong quá trình fine-tuning.

  8. Early Stopping: Dừng quá trình fine-tuning khi hiệu suất trên tập validation không còn cải thiện nữa, để tránh overfitting.

  9. Domain-Specific Modifications: Đôi khi, việc thay đổi một số phần của mô hình để phù hợp với đặc điểm cụ thể của ngữ cảnh hoặc tác vụ mới.

Lưu ý rằng, quá trình fine-tuning cũng đòi hỏi một số kiến thức về độ sâu của mô hình, quy trình huấn luyện và tinh chỉnh các tham số cụ thể.

Sử dụng các thuật toán tối ưu hóa metaheuristic như Particle Swarm Optimization (PSO)

trong việc fine-tuning mô hình học sâu có thể cung cấp một cách tiếp cận mạnh mẽ để tìm kiếm không gian siêu tham số để cực tiểu hóa hoặc tối ưu hóa một hàm mục tiêu. Dưới đây là một hướng dẫn cơ bản về cách tích hợp các thuật toán này vào quá trình fine-tuning:

  1. Định nghĩa hàm mục tiêu (Objective Function):
    • Xác định hàm mục tiêu mà bạn muốn tối ưu hóa. Ví dụ, có thể là mức độ hiệu suất (accuracy, F1-score, …) của mô hình trên tập validation.
  2. Biểu diễn không gian siêu tham số:
    • Xác định không gian siêu tham số cần tối ưu hóa. Đây là tập hợp các tham số mà bạn muốn tối ưu hóa, ví dụ: learning rate, kích thước batch, số lượng tầng ẩn, …
  3. Khởi tạo quần thể (Swarm Initialization):
    • Khởi tạo một quần thể gồm nhiều các cá thể (particles), mỗi cá thể đại diện cho một bộ siêu tham số.
  4. Cập nhật vị trí và tốt nhất cá thể (Update Particle Positions and Best):
    • Mỗi cá thể trong quần thể di chuyển theo một tốc độ được xác định bởi vị trí hiện tại của nó và vị trí tốt nhất của nó. Cập nhật vị trí mới dựa trên công thức của thuật toán PSO.
  5. Đánh giá hiệu suất (Evaluate Performance):
    • Đánh giá hiệu suất của mô hình với các siêu tham số hiện tại trên tập validation sử dụng hàm mục tiêu.
  6. Cập nhật vị trí tốt nhất của từng cá thể (Update Best Positions):
    • Nếu hiệu suất của một cá thể được cải thiện, cập nhật vị trí tốt nhất của nó.
  7. Kiểm tra điều kiện dừng (Termination Condition):
    • Kiểm tra điều kiện dừng (ví dụ: số lượng thế hệ tối đa, độ chính xác đạt mục tiêu).
  8. Áp dụng siêu tham số tốt nhất lên mô hình:
    • Áp dụng các siêu tham số tốt nhất đã tìm được lên mô hình và tiếp tục quá trình huấn luyện hoặc fine-tuning.
  9. Lặp lại các bước trên cho đến khi điều kiện dừng được đáp ứng.

Lưu ý rằng việc sử dụng metaheuristic như PSO trong fine-tuning yêu cầu một số tham số như số lượng particles, tốc độ học, và các tham số liên quan đến quá trình tối ưu hóa. Điều này đòi hỏi thử nghiệm và điều chỉnh kỹ thuật để tìm ra các cài đặt phù hợp nhất cho vấn đề cụ thể của bạn.

Ví dụ sử dụng PSO để tối ưu siêu tham số

Dưới đây là một ví dụ về cách sử dụng thuật toán PSO để tối ưu hóa các siêu tham số cho một mô hình học sâu đã được huấn luyện trước cho bài toán phân loại hình ảnh:

  1. Bước 1: Chuẩn bị Dữ liệu:
    • Chuẩn bị tập dữ liệu hình ảnh để fine-tuning. Bao gồm tập huấn luyện, tập validation và tập kiểm tra.
  2. Bước 2: Chọn mô hình cơ sở và Tiến hành Pre-training:
    • Chọn một mô hình học sâu có thể được huấn luyện trước, chẳng hạn như một trong các mô hình từ hệ thống như ResNet, VGG, hoặc EfficientNet.
    • Tiến hành pre-training trên một tập dữ liệu lớn như ImageNet.
  3. Bước 3: Chuẩn bị không gian siêu tham số:
    • Xác định các tham số mà bạn muốn tối ưu hóa. Ví dụ: tốc độ học (learning rate), kích thước batch (batch size), số lượng tầng ẩn, …
  4. Bước 4: Định nghĩa Hàm Mục Tiêu:
    • Xác định hàm mục tiêu mà bạn muốn tối ưu hóa. Ví dụ, có thể là accuracy trên tập validation.
  5. Bước 5: Khởi tạo Quần Thể PSO:
    • Khởi tạo một quần thể gồm nhiều particles (cá thể), mỗi cá thể đại diện cho một bộ siêu tham số.
  6. Bước 6: Cập Nhật Vị Trí và Tốt Nhất:
    • Áp dụng thuật toán PSO để cập nhật vị trí của các particles.
  7. Bước 7: Đánh Giá Hiệu Suất:
    • Đánh giá hiệu suất của mô hình với các siêu tham số hiện tại trên tập validation sử dụng hàm mục tiêu.
  8. Bước 8: Cập Nhật Vị Trí Tốt Nhất Của Cá Thể:
    • Nếu hiệu suất của một cá thể được cải thiện, cập nhật vị trí tốt nhất của nó.
  9. Bước 9: Kiểm Tra Điều Kiện Dừng:
    • Kiểm tra điều kiện dừng (ví dụ: số lượng thế hệ tối đa, độ chính xác đạt mục tiêu).
  10. Bước 10: Áp Dụng Siêu Tham Số Tốt Nhất Lên Mô Hình:
    • Áp dụng các siêu tham số tốt nhất đã tìm được lên mô hình và tiếp tục quá trình fine-tuning.
  11. Lặp Lại Các Bước Trên Cho Đến Khi Điều Kiện Dừng Được Đáp Ứng.

Lưu ý rằng bạn cần phải cài đặt và sử dụng thư viện PSO hoặc metaheuristic tương tự. Đồng thời, điều chỉnh các tham số của PSO như số lượng particles, tốc độ học, v.v. cũng là một phần quan trọng trong quá trình này.

Cách tiếp cận này giúp tối ưu hóa các siêu tham số cho mô hình học sâu dựa trên một hàm mục tiêu được chọn mà không yêu cầu thử nghiệm thủ công hoặc tinh chỉnh tham số theo cách truyền thống.

Code pytorch cho ví dụ

Dưới đây là một ví dụ về cách sử dụng thuật toán PSO để tối ưu hóa learning rate của một mô hình học sâu đã được huấn luyện trước bằng PyTorch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import torch
import torch.nn as nn
import torch.optim as optim
from pyswarm import pso

# Tạo mô hình cơ sở (pre-trained)
base_model = torchvision.models.resnet18(pretrained=True)
num_features = base_model.fc.in_features
base_model.fc = nn.Linear(num_features, 10)  # Thay đổi số lớp đầu ra tùy theo bài toán

# Chuẩn bị dữ liệu (giả sử có dữ liệu)
transform = torchvision.transforms.Compose([
    torchvision.transforms.RandomResizedCrop(224),
    torchvision.transforms.RandomHorizontalFlip(),
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, transform=transform, download=True)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)

validation_dataset = torchvision.datasets.CIFAR10(root='./data', train=False, transform=transform, download=True)
validation_loader = torch.utils.data.DataLoader(validation_dataset, batch_size=32, shuffle=False)

# Định nghĩa hàm mục tiêu (accuracy trên tập validation)
def objective(lr):
    optimizer = optim.SGD(base_model.parameters(), lr=lr, momentum=0.9)
    criterion = nn.CrossEntropyLoss()
    
    # Huấn luyện mô hình
    base_model.train()
    for epoch in range(5):  # Số epoch tùy chọn
        for images, labels in train_loader:
            optimizer.zero_grad()
            outputs = base_model(images)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
    
    # Đánh giá hiệu suất trên tập validation
    base_model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in validation_loader:
            outputs = base_model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    accuracy = correct / total
    return -accuracy  # Đảo ngược để tối ưu hóa

# Định nghĩa khoảng giá trị cho learning rate
lb = 1e-6  # Lower bound
ub = 1e-2  # Upper bound

# Sử dụng PSO để tối ưu hóa learning rate
best_params, best_value = pso(objective, lb, ub, swarmsize=5, maxiter=10)

print(f'Best Learning Rate: {best_params[0]}')

Trong ví dụ này, chúng ta sử dụng mô hình ResNet18 đã được huấn luyện trước. Mục tiêu của chúng ta là tối ưu hóa learning rate của mô hình. Hàm mục tiêu được định nghĩa là accuracy trên tập validation. Để chạy ví dụ này, bạn cần cài đặt thư viện pyswarm bằng cách sử dụng pip install pyswarm.

Hãy đảm bảo bạn đã chuẩn bị dữ liệu huấn luyện và validation và thực hiện các điều chỉnh cần thiết.

Sử dụng GA

Để sử dụng thuật toán Genetic Algorithm (GA) vào việc fine-tuning mô hình học sâu cho bài toán phân loại hình ảnh, bạn cần thực hiện các bước sau:

  1. Import các thư viện cần thiết:
    1
    2
    3
    4
    5
    
    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torchvision import models, transforms, datasets
    import numpy as np
    
  2. Chuẩn bị dữ liệu (chúng ta sẽ sử dụng dữ liệu CIFAR-10 như ví dụ): ```python transform = transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ])

train_data = datasets.CIFAR10(root=’./data’, train=True, transform=transform, download=True) train_loader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)

test_data = datasets.CIFAR10(root=’./data’, train=False, transform=transform, download=True) test_loader = torch.utils.data.DataLoader(test_data, batch_size=64, shuffle=False)

1
2
3
4
5
6
3. **Định nghĩa mô hình cơ sở và tầng Fully Connected**:
```python
base_model = models.resnet18(pretrained=True)
num_features = base_model.fc.in_features
base_model.fc = nn.Linear(num_features, 10)  # Đối với CIFAR-10, có 10 lớp
  1. Định nghĩa hàm mục tiêu (objective function). Hàm này sẽ đánh giá hiệu suất của mô hình trên tập validation:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    def evaluate(model, criterion, test_loader, device):
     model.eval()
     correct = 0
     total = 0
     with torch.no_grad():
         for inputs, labels in test_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 = correct / total
     return accuracy
    
  2. Định nghĩa các tham số của GA:
    1
    2
    3
    
    population_size = 10
    num_generations = 10
    mutation_rate = 0.1
    
  3. Định nghĩa các phép toán của GA:

    • Khởi tạo quần thể (Initialize Population):
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      def initialize_population(model, population_size):
       population = []
       for _ in range(population_size):
         new_model = model.clone()
         for param in new_model.parameters():
             if len(param.size()) >= 2:
                 param.data = torch.randn(param.size()) * 0.1
             else:
                 param.data = torch.randn(param.size())
         population.append(new_model)
       return population
      
    • Đánh giá (Fitness Function):
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
      def fitness(model, train_loader, test_loader, criterion, device):
       model.train()
       optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
       for epoch in range(5):
         for inputs, labels in train_loader:
             inputs, labels = inputs.to(device), labels.to(device)
             optimizer.zero_grad()
             outputs = model(inputs)
             loss = criterion(outputs, labels)
             loss.backward()
             optimizer.step()
       accuracy = evaluate(model, criterion, test_loader, device)
       return accuracy
      
    • Lai ghép (Crossover):
      1
      2
      3
      4
      5
      6
      7
      
      def crossover(model1, model2):
       child_model = model1.clone()
       for (child_param, parent1_param, parent2_param) in zip(child_model.parameters(), model1.parameters(), model2.parameters()):
         mask = torch.randint(0, 2, child_param.size(), dtype=torch.bool)
         child_param.data[mask] = parent1_param.data[mask]
         child_param.data[~mask] = parent2_param.data[~mask]
       return child_model
      
    • Biến đổi (Mutation):
      1
      2
      3
      4
      5
      6
      
      def mutate(model, mutation_rate):
       mutated_model = model.clone()
       for param in mutated_model.parameters():
         if np.random.rand() < mutation_rate:
             param.data = param.data + torch.randn(param.size()) * 0.1
       return mutated_model
      
  4. Tiến hành GA:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

criterion = nn.CrossEntropyLoss()
best_accuracy = 0

population = initialize_population(base_model, population_size)

for generation in range(num_generations):
    print(f"Generation {generation+1}")
    
    for i, model in enumerate(population):
        print(f"Evaluating model {i+1}...")
        accuracy = fitness(model, train_loader, test_loader, criterion, device)
        print(f"Accuracy: {accuracy}")
        
        if accuracy > best_accuracy:
            best_accuracy = accuracy
            best_model = model.clone()
    
    new_population = []
    for _ in range(population_size):
        parent1, parent2 = np.random.choice(population, 2, replace=False)
        child = crossover(parent1, parent2)
        child = mutate(child, mutation_rate)
        new_population.append(child)
    
    population = new_population

print(f"Best Accuracy: {best_accuracy}")

Trong ví dụ trên, chúng ta đã sử dụng GA để tối ưu hóa mô hình. Quần thể ban đầu được khởi tạo bằng cách tạo ra các mô hình ngẫu nhiên.

Mỗi mô hình được đánh giá bằng cách huấn luyện và đánh giá trên tập kiểm tra. Các mô hình tốt nhất được sử dụng để tạo ra thế hệ tiếp theo thông qua lai ghép và biến đổi.

Việc tiến hành này được lặp lại qua nhiều thế hệ để tối ưu hóa mô hình. Cuối cùng, mô hình có độ chính xác tốt nhất được chọn là kết quả.

Tài liệu tham khảo

Internet

Hết.