Skip to content

giap1324/phanloaiviemphoi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

CHƯƠNG 2: PHƯƠNG PHÁP NGHIÊN CỨU VÀ THỰC NGHIỆM


2.2. Mô tả và phân tích tập dữ liệu ảnh X-quang phổi

2.2.1. Nguồn dữ liệu

Nghiên cứu sử dụng tập dữ liệu Chest X-Ray Images (Pneumonia) từ Kaggle, được cung cấp bởi Paul Mooney. Đây là một trong những bộ dữ liệu ảnh X-quang phổi phổ biến nhất cho bài toán phân loại viêm phổi.

Thông tin tập dữ liệu:

  • Nguồn: Kaggle - paultimothymooney/chest-xray-pneumonia
  • Tổng số ảnh: 5,863 ảnh X-quang ngực
  • Số lớp phân loại: 2 lớp (Binary Classification)
    • NORMAL: Phổi bình thường
    • PNEUMONIA: Viêm phổi

2.2.2. Phân bố dữ liệu gốc

Tập dữ liệu NORMAL PNEUMONIA Tổng
Train 1,341 3,875 5,216
Test 234 390 624
Val 8 8 16
Tổng 1,583 4,273 5,856

2.2.3. Đặc điểm ảnh X-quang

  • Định dạng: JPEG/PNG
  • Kích thước gốc: Không đồng nhất (dao động từ 400x400 đến 2000x2000 pixels)
  • Color Mode: Chủ yếu là Grayscale (L mode) và một số ảnh RGB
  • Chất lượng: Ảnh y tế chất lượng cao, được chụp tại các bệnh viện

2.2.4. Vấn đề mất cân bằng lớp

Tập dữ liệu có sự mất cân bằng đáng kể giữa hai lớp:

  • PNEUMONIA: 4,273 ảnh (73%)
  • NORMAL: 1,583 ảnh (27%)

Tỷ lệ mất cân bằng: 2.7:1 (PNEUMONIA : NORMAL)


2.3. Tiền xử lý dữ liệu ảnh

2.3.1. Kiểm tra và làm sạch dữ liệu

Trước khi huấn luyện, dữ liệu được kiểm tra và làm sạch theo các tiêu chí sau:

def check_image_integrity(img_path, min_size=50, max_size=5000):
    """Kiểm tra tính toàn vẹn của ảnh"""
    try:
        img = Image.open(img_path)
        img.verify()
        img = Image.open(img_path)
        width, height = img.size
        
        # Kiểm tra kích thước bất thường
        if width < min_size or height < min_size:
            return False, "Kích thước quá nhỏ"
        if width > max_size or height > max_size:
            return False, "Kích thước quá lớn"
        
        # Kiểm tra aspect ratio
        aspect_ratio = max(width, height) / min(width, height)
        if aspect_ratio > 3:
            return False, "Aspect ratio bất thường"
        
        return True, None
    except Exception as e:
        return False, f"Ảnh hỏng: {str(e)}"

Tiêu chí loại bỏ:

  • Ảnh bị hỏng (corrupt)
  • Kích thước < 50 pixels
  • Kích thước > 5000 pixels
  • Aspect ratio > 3:1

2.3.2. Chuẩn hóa ảnh

Bước 1: Resize về kích thước chuẩn

IMG_SIZE = 224  # Kích thước chuẩn cho ViT

def preprocess_and_save_image(src_path, dst_path, target_size=224):
    img = Image.open(src_path)
    # Convert sang RGB
    if img.mode != 'RGB':
        img = img.convert('RGB')
    # Resize với LANCZOS filter
    img = img.resize((target_size, target_size), Image.Resampling.LANCZOS)
    img.save(dst_path, quality=95)

Bước 2: Chuẩn hóa giá trị pixel

  • Sử dụng ImageNet statistics cho normalization:
IMAGENET_MEAN = [0.485, 0.456, 0.406]
IMAGENET_STD = [0.229, 0.224, 0.225]

2.3.3. Tăng cường dữ liệu (Data Augmentation)

Các kỹ thuật tăng cường cho tập Training:

Kỹ thuật Tham số Mục đích
RandomHorizontalFlip p=0.5 Lật ngang ngẫu nhiên
RandomVerticalFlip p=0.1 Lật dọc (phù hợp với X-ray)
RandomRotation ±15° - ±20° Xoay ngẫu nhiên
RandomAffine translate=10-15%, scale=85-115% Dịch chuyển và zoom
ColorJitter brightness=0.2-0.3, contrast=0.2-0.3 Điều chỉnh độ sáng/tương phản
RandomAdjustSharpness factor=2, p=0.3 Tăng độ nét
GaussianBlur kernel=3, sigma=(0.1, 1.0) Làm mờ Gaussian
RandomAutocontrast p=0.2 Tự động điều chỉnh contrast
RandomErasing p=0.1, scale=(0.02, 0.1) Cutout/Erasing
train_transform = transforms.Compose([
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.RandomVerticalFlip(p=0.1),
    transforms.RandomRotation(degrees=20),
    transforms.RandomAffine(
        degrees=0,
        translate=(0.15, 0.15),
        scale=(0.85, 1.15),
        shear=10
    ),
    transforms.ColorJitter(brightness=0.3, contrast=0.3, saturation=0.1),
    transforms.RandomAdjustSharpness(sharpness_factor=2, p=0.3),
    transforms.RandomAutocontrast(p=0.2),
    transforms.GaussianBlur(kernel_size=3, sigma=(0.1, 1.0)),
    transforms.ToTensor(),
    transforms.Normalize(mean=IMAGENET_MEAN, std=IMAGENET_STD),
    transforms.RandomErasing(p=0.1, scale=(0.02, 0.1))
])

Transform cho Validation/Test (không augmentation):

val_test_transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=IMAGENET_MEAN, std=IMAGENET_STD)
])

2.4. Phân tích dữ liệu và mất cân bằng lớp

2.4.1. Chia dữ liệu

Dữ liệu được chia theo tỷ lệ 70/10/20 với stratified sampling để đảm bảo phân bố đều:

# Bước 1: Chia Train + Val (80%) và Test (20%)
X_train_val, X_test, y_train_val, y_test = train_test_split(
    X, y, test_size=0.20, random_state=42, stratify=y
)

# Bước 2: Chia Train (70%) và Val (10%)
X_train, X_val, y_train, y_val = train_test_split(
    X_train_val, y_train_val, test_size=0.125, random_state=42, stratify=y_train_val
)

Kết quả chia dữ liệu:

Tập Số lượng Tỷ lệ NORMAL PNEUMONIA
Training ~4,100 70% ~1,108 ~2,992
Validation ~586 10% ~158 ~428
Test ~1,173 20% ~317 ~856

2.4.2. Xử lý mất cân bằng lớp

Phương pháp 1: Class Weights

# Tính class weights
class_counts = np.bincount(y_train)
class_weights = 1.0 / class_counts
class_weights = class_weights / class_weights.sum() * len(class_counts)
class_weights = torch.FloatTensor(class_weights).to(device)

# Kết quả: NORMAL weight ~ 1.35, PNEUMONIA weight ~ 0.65

Phương pháp 2: Softened Class Weights (Improved ViT)

# Softened weights - giảm penalty
class_weights_soft = torch.FloatTensor([
    (total / (n_classes * count[0])) ** 0.5,  # Square root để soften
    (total / (n_classes * count[1])) ** 0.5
]).to(device)

Phương pháp 3: WeightedRandomSampler (Hybrid ViT)

sample_weights = [class_weights[label].item() for label in y_train]
sampler = WeightedRandomSampler(
    weights=sample_weights,
    num_samples=len(sample_weights),
    replacement=True
)

2.5. Đề xuất mô hình ViT cải tiến

2.5.1. Kiến trúc tổng thể của mô hình đề xuất

Nghiên cứu đề xuất mô hình Bộ biến đổi thị giác lai (Hybrid Vision Transformer - Hybrid ViT) kết hợp ưu điểm của mạng tích chập (CNN) và kiến trúc Transformer. Mô hình này được thiết kế nhằm đạt hiệu suất cao nhất trong bài toán phân loại ảnh X-quang phổi với tập dữ liệu hạn chế.

┌─────────────────────────────────────────────────────────────────┐
│                MÔ HÌNH BỘ BIẾN ĐỔI THỊ GIÁC LAI                 │
│                      (HYBRID ViT)                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Ảnh đầu vào (224×224×3)                                        │
│         │                                                        │
│         ▼                                                        │
│  ┌─────────────────────────────────────┐                        │
│  │   XƯƠNG SỐNG CNN - ResNet50         │                        │
│  │   (Tiền huấn luyện trên ImageNet)   │                        │
│  │   Đầu ra: [B, 2048, 7, 7]           │                        │
│  └─────────────────────────────────────┘                        │
│         │                                                        │
│         ▼                                                        │
│  ┌─────────────────────────────────────┐                        │
│  │   LỚP CHIẾU (Projection)            │                        │
│  │   2048 → 512 chiều                  │                        │
│  │   Đầu ra: [B, 49, 512]              │                        │
│  └─────────────────────────────────────┘                        │
│         │                                                        │
│         ▼                                                        │
│  ┌─────────────────────────────────────┐                        │
│  │   Token phân loại + Mã hóa vị trí   │                        │
│  │   Đầu ra: [B, 50, 512]              │                        │
│  └─────────────────────────────────────┘                        │
│         │                                                        │
│         ▼                                                        │
│  ┌─────────────────────────────────────┐                        │
│  │   KHỐI TRANSFORMER × 6              │                        │
│  │   ┌───────────────────────────────┐ │                        │
│  │   │ Chuẩn hóa lớp                 │ │                        │
│  │   │ Cơ chế tự chú ý đa đầu (4)    │ │                        │
│  │   │ Kết nối tàn dư                │ │                        │
│  │   │ Chuẩn hóa lớp                 │ │                        │
│  │   │ Mạng nhân tính (MLP)          │ │                        │
│  │   │ Kết nối tàn dư                │ │                        │
│  │   └───────────────────────────────┘ │                        │
│  └─────────────────────────────────────┘                        │
│         │                                                        │
│         ▼                                                        │
│  ┌─────────────────────────────────────┐                        │
│  │   ĐẦU PHÂN LOẠI                     │                        │
│  │   512 → 2 (BÌNH THƯỜNG / VIÊM PHỔI) │                        │
│  └─────────────────────────────────────┘                        │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Bảng tổng hợp các thông số kiến trúc:

Thành phần Thông số Giá trị
Xương sống CNN Kiến trúc ResNet50 (tiền huấn luyện ImageNet)
Xương sống CNN Đầu ra [B, 2048, 7, 7]
Lớp chiếu Chiều đầu vào/ra 2048 → 512
Khối Transformer Số lớp 6
Khối Transformer Số đầu chú ý 4
Khối Transformer Chiều nhúng 512
Khối Transformer Tỷ lệ MLP 4.0 (512 → 2048 → 512)
Điều chuẩn Tỷ lệ bỏ rơi 0.2
Đầu phân loại Số lớp đầu ra 2

2.5.2. Các cải tiến so với ViT gốc

Mô hình Hybrid ViT đề xuất có nhiều cải tiến quan trọng so với kiến trúc Vision Transformer gốc:

Cải tiến 1: Thay thế lớp nhúng bản vá bằng xương sống CNN

ViT gốc: Sử dụng lớp tích chập đơn để chia ảnh thành các bản vá 16×16 pixel và nhúng trực tiếp vào không gian vector.

Hybrid ViT: Sử dụng ResNet50 đã tiền huấn luyện để trích xuất đặc trưng trước khi đưa vào Transformer.

Tiêu chí ViT gốc Hybrid ViT
Phương pháp nhúng Tích chập đơn 16×16 ResNet50 backbone
Tiền huấn luyện Không Có (ImageNet)
Số bản vá 196 (14×14) 49 (7×7)
Đặc trưng cục bộ Yếu Mạnh
class XuongSongResNet(nn.Module):
    def __init__(self, tien_huan_luyen=True):
        super().__init__()
        resnet = models.resnet50(pretrained=tien_huan_luyen)
        # Loại bỏ lớp pooling và FC cuối
        self.cac_lop = nn.Sequential(*list(resnet.children())[:-2])
        
    def forward(self, x):
        return self.cac_lop(x)  # [B, 2048, 7, 7]

Lợi ích: Tận dụng tri thức từ hàng triệu ảnh ImageNet, trích xuất đặc trưng cục bộ mạnh mẽ phù hợp với ảnh y tế.

Cải tiến 2: Giảm chiều nhúng

ViT gốc: Sử dụng chiều nhúng 768 với 12 đầu chú ý.

Hybrid ViT: Giảm xuống 512 chiều với 4 đầu chú ý.

Thông số ViT gốc Hybrid ViT Lý do thay đổi
Chiều nhúng 768 512 Giảm tham số, tránh quá khớp
Số đầu chú ý 12 4 Đủ cho bài toán 2 lớp
Chiều mỗi đầu 64 128 Tăng khả năng biểu diễn mỗi đầu

Lợi ích: Giảm số tham số, phù hợp với bài toán phân loại nhị phân và tập dữ liệu nhỏ.

Cải tiến 3: Giảm số lớp Transformer

ViT gốc: Sử dụng 12 lớp Transformer.

Hybrid ViT: Chỉ sử dụng 6 lớp.

Tiêu chí ViT gốc (12 lớp) Hybrid ViT (6 lớp)
Số tham số ~86M ~28M
Thời gian huấn luyện Chậm Nhanh gấp 2 lần
Nguy cơ quá khớp Cao Thấp
Yêu cầu dữ liệu Hàng triệu ảnh Vài nghìn ảnh

Lợi ích: Đặc trưng từ CNN đã mang nhiều thông tin ngữ nghĩa, nên cần ít lớp Transformer hơn để học mối quan hệ toàn cục.

Cải tiến 4: Lớp chiếu giảm chiều

Thêm lớp chiếu để chuyển đổi đặc trưng từ CNN (2048 chiều) sang không gian phù hợp với Transformer (512 chiều):

class LopChieu(nn.Module):
    def __init__(self, chieu_dau_vao=2048, chieu_dau_ra=512):
        super().__init__()
        self.chieu = nn.Conv2d(chieu_dau_vao, chieu_dau_ra, kernel_size=1)
        
    def forward(self, x):
        x = self.chieu(x)      # [B, 512, 7, 7]
        x = x.flatten(2)       # [B, 512, 49]
        x = x.transpose(1, 2)  # [B, 49, 512]
        return x

Lợi ích: Giảm tính toán cho các lớp Transformer, duy trì thông tin quan trọng.

Bảng tổng hợp các cải tiến

Cải tiến ViT gốc Hybrid ViT Hiệu quả
Phương pháp nhúng Bản vá 16×16 ResNet50 Đặc trưng cục bộ tốt hơn
Tiền huấn luyện Không ImageNet Giảm 50-70% thời gian huấn luyện
Chiều nhúng 768 512 Giảm tham số 33%
Số đầu chú ý 12 4 Phù hợp bài toán 2 lớp
Số lớp Transformer 12 6 Giảm quá khớp
Số bản vá 196 49 Tính toán nhanh hơn 4 lần
Tổng tham số ~86M ~28M Giảm 67%

2.5.3. Lý do lựa chọn cải tiến

Nghiên cứu lựa chọn các cải tiến trên dựa vào những cơ sở khoa học và thực tiễn sau:

1. Phù hợp với đặc điểm ảnh X-quang phổi

Ảnh X-quang phổi có những đặc điểm riêng biệt cần kiến trúc phù hợp:

Đặc điểm ảnh y tế Yêu cầu Giải pháp của Hybrid ViT
Vết mờ, nốt bất thường Trích xuất đặc trưng cục bộ CNN ResNet50 xử lý
Hình dạng tổng thể phổi Học mối quan hệ toàn cục Transformer 6 lớp xử lý
Kết cấu phức tạp Học đặc trưng đa mức Kết hợp CNN + Transformer
Độ tương phản thấp Cần nhiều bộ lọc ResNet50 có 50+ lớp tích chập

2. Giải quyết vấn đề dữ liệu hạn chế

ViT gốc được thiết kế cho tập dữ liệu lớn (JFT-300M với 300 triệu ảnh). Với tập dữ liệu chỉ khoảng 5,000 ảnh, các cải tiến giúp mô hình học hiệu quả hơn:

Vấn đề Giải pháp Cơ sở khoa học
Thiếu dữ liệu huấn luyện Transfer learning từ ImageNet Tri thức có sẵn từ 1.2 triệu ảnh
Dễ bị quá khớp Giảm số tham số (28M thay vì 86M) Mô hình đơn giản hơn, tổng quát tốt hơn
Hội tụ chậm Đặc trưng CNN mạnh ngay từ đầu Không cần học từ bản vá thô
Thiếu inductive bias CNN cung cấp inductive bias cục bộ Phù hợp với cấu trúc ảnh 2D

3. Cân bằng giữa hiệu suất và tài nguyên

Tiêu chí ViT gốc Hybrid ViT Cải thiện
Độ chính xác 86.80% 98.00% +11.2%
Kích thước mô hình 985 MB 322 MB Giảm 67%
Số vòng lặp hội tụ 23 14 Giảm 39%
Thời gian suy luận Chậm Nhanh Tăng 4 lần

4. Cơ sở khoa học từ nghiên cứu đương đại

Các cải tiến được đề xuất dựa trên những nghiên cứu đã được công bố:

Nghiên cứu Đề xuất Áp dụng trong Hybrid ViT
Dosovitskiy et al. (2020) Hybrid ViT với CNN backbone Sử dụng ResNet50 làm xương sống
He et al. (2016) ResNet với kết nối tàn dư Áp dụng trong xương sống CNN
Touvron et al. (2021) Giảm số lớp cho dữ liệu nhỏ Chỉ dùng 6 lớp Transformer
Liu et al. (2021) Giảm chiều nhúng Dùng 512 thay vì 768

5. Kết quả thực nghiệm xác nhận hiệu quả

Kết quả so sánh với các mô hình khác trên cùng tập dữ liệu:

Mô hình Độ chính xác Điểm F1 Kích thước Số vòng lặp
Hybrid ViT 98.00% 0.9845 322 MB 14
DenseNet121 96.00% - 86 MB 9
Improved ViT 89.40% - 1513 MB 12
ViT gốc 86.80% - 985 MB 23

Nhận xét: Hybrid ViT đạt độ chính xác cao nhất với kích thước hợp lý và thời gian huấn luyện ngắn, chứng minh hiệu quả của các cải tiến được đề xuất.

Tổng kết lý do lựa chọn

Nghiên cứu lựa chọn kiến trúc Hybrid ViT với các cải tiến nêu trên vì:

  1. Hiệu suất cao: Đạt độ chính xác 98.00%, cao nhất trong tất cả các mô hình thử nghiệm
  2. Phù hợp dữ liệu nhỏ: Tận dụng transfer learning và giảm tham số để tránh quá khớp
  3. Kết hợp ưu điểm: CNN trích xuất đặc trưng cục bộ, Transformer học quan hệ toàn cục
  4. Triển khai được: Kích thước 322 MB và suy luận nhanh phù hợp ứng dụng thực tế
  5. Cơ sở khoa học vững chắc: Dựa trên các nghiên cứu đã được chứng minh hiệu quả

2.6. Quy trình huấn luyện mô hình

2.6.1. Cấu hình siêu tham số

Bảng dưới đây so sánh cấu hình siêu tham số của ba mô hình được thử nghiệm:

Siêu tham số Mô hình gốc Mô hình cải tiến Mô hình lai
Tốc độ học 3e-4 5e-5 1e-4
Suy giảm trọng số 0.05 0.01 0.01
Kích thước lô 32 32 32
Số vòng lặp 30 50 30
Tỷ lệ bỏ rơi 0.2 0.05-0.1 0.2
Bộ tối ưu AdamW AdamW AdamW
Bộ lập lịch Cô-sin ủ Một chu kỳ Cô-sin ủ
Độ chính xác hỗn hợp FP16 FP16 FP16
Cắt bớt gradient 1.0 1.0 1.0

Giải thích lựa chọn:

  • Tốc độ học thấp hơn (5e-5) cho mô hình cải tiến để tránh gradient quá lớn trong mạng sâu
  • Suy giảm trọng số nhỏ (0.01) để giảm điều chuẩn, tránh thiếu khớp
  • Bỏ rơi thấp (0.05-0.1) vì đã sử dụng bỏ rơi đường đi
  • Số vòng lặp nhiều hơn (50) do mô hình phức tạp hơn cần thời gian hội tụ

2.6.2. Chiến lược điều chỉnh tốc độ học

Phương pháp một chu kỳ (dành cho mô hình cải tiến):

bo_lap_lich = OneCycleLR(
    bo_toi_uu,
    toc_do_hoc_toi_da=TOC_DO_HOC * 4,   # Đỉnh tại 4x tốc độ học cơ bản
    so_vong_lap=SO_VONG_LAP,
    buoc_moi_vong=len(bo_nap_huan_luyen),
    phan_tram_khoi_dong=0.2,             # Khởi động 20%
    chien_luoc_ủ='cos',
    he_so_chia=10,
    he_so_chia_cuoi=100
)
    anneal_strategy='cos',
    div_factor=10,
    final_div_factor=100
)

Cosine Annealing with Warmup (ViT Gốc):

def get_lr_scheduler(optimizer, warmup_steps, total_steps):
    def lr_lambda(current_step):
        if current_step < warmup_steps:
            return float(current_step) / float(max(1, warmup_steps))
        progress = (current_step - warmup_steps) / (total_steps - warmup_steps)
        return max(0.0, 0.5 * (1.0 + np.cos(np.pi * progress)))
    return LambdaLR(optimizer, lr_lambda)

2.6.3. Loss Function

# CrossEntropyLoss với class weights
criterion = nn.CrossEntropyLoss(weight=class_weights, label_smoothing=0.0)

2.6.4. Training Loop

def train_one_epoch(model, train_loader, criterion, optimizer, scheduler, scaler, device):
    model.train()
    total_loss, correct, total = 0.0, 0, 0
    
    for images, labels in train_loader:
        images, labels = images.to(device), labels.to(device)
        
        optimizer.zero_grad()
        
        # Mixed precision forward
        with autocast():
            outputs = model(images)
            loss = criterion(outputs, labels)
        
        # Backward with gradient scaling
        scaler.scale(loss).backward()
        
        # Gradient clipping
        scaler.unscale_(optimizer)
        torch.nn.utils.clip_grad_norm_(model.parameters(), GRAD_CLIP)
        
        scaler.step(optimizer)
        scaler.update()
        scheduler.step()
        
        # Statistics
        total_loss += loss.item()
        _, predicted = outputs.max(1)

Giải thích:

  • Giai đoạn khởi động (20% đầu): Tốc độ học tăng dần từ thấp
  • Giai đoạn đỉnh: Đạt tốc độ học tối đa (4x tốc độ cơ bản)
  • Giai đoạn ủ: Giảm dần theo hàm cô-sin về giá trị rất nhỏ

Phương pháp ủ cô-sin với khởi động (dành cho mô hình gốc):

def lay_bo_lap_lich_toc_do_hoc(bo_toi_uu, buoc_khoi_dong, tong_so_buoc):
    """Hàm tạo bộ lập lịch tốc độ học với khởi động"""
    def ham_lambda_toc_do_hoc(buoc_hien_tai):
        # Giai đoạn khởi động tuyến tính
        if buoc_hien_tai < buoc_khoi_dong:
            return float(buoc_hien_tai) / float(max(1, buoc_khoi_dong))
        # Giai đoạn ủ theo cô-sin
        tien_trinh = (buoc_hien_tai - buoc_khoi_dong) / (tong_so_buoc - buoc_khoi_dong)
        return max(0.0, 0.5 * (1.0 + np.cos(np.pi * tien_trinh)))
    return LambdaLR(bo_toi_uu, ham_lambda_toc_do_hoc)

2.6.3. Hàm mất mát

Sử dụng hàm mất mát entropy chéo với trọng số lớp để xử lý mất cân bằng dữ liệu:

# Hàm mất mát entropy chéo với trọng số lớp
ham_mat_mat = nn.CrossEntropyLoss(weight=trong_so_lop, label_smoothing=0.0)

Giải thích tham số:

  • weight: Trọng số cho mỗi lớp (BÌNH THƯỜNG: 1.35, VIÊM PHỔI: 0.65)
  • label_smoothing: Làm mượt nhãn (0.0 = không làm mượt)

2.6.4. Vòng lặp huấn luyện

Quy trình huấn luyện một vòng lặp với độ chính xác hỗn hợp và cắt bớt gradient:

def huan_luyen_mot_vong(mo_hinh, bo_nap_huan_luyen, ham_mat_mat, bo_toi_uu, bo_lap_lich, bo_co_giong, thiet_bi):
    """Huấn luyện mô hình trong một vòng lặp"""
    mo_hinh.train()
    tong_mat_mat, dung, tong = 0.0, 0, 0
    
    for anh, nhan in bo_nap_huan_luyen:
        anh, nhan = anh.to(thiet_bi), nhan.to(thiet_bi)
        
        bo_toi_uu.zero_grad()
        
        # Lan truyền xuôi với độ chính xác hỗn hợp
        with autocast():
            dau_ra = mo_hinh(anh)
            mat_mat = ham_mat_mat(dau_ra, nhan)
        
        # Lan truyền ngược với co giãn gradient
        bo_co_giong.scale(mat_mat).backward()
        
        # Cắt bớt gradient để tránh gradient bùng nổ
        bo_co_giong.unscale_(bo_toi_uu)
        torch.nn.utils.clip_grad_norm_(mo_hinh.parameters(), NGUONG_CAT_GRADIENT)
        
        bo_co_giong.step(bo_toi_uu)
        bo_co_giong.update()
        bo_lap_lich.step()
        
        # Thống kê
        tong_mat_mat += mat_mat.item()
        _, du_doan = dau_ra.max(1)
        tong += nhan.size(0)
        dung += du_doan.eq(nhan).sum().item()
    
    return tong_mat_mat / len(bo_nap_huan_luyen), 100. * dung / tong

2.6.5. Dừng sớm

Cơ chế dừng sớm để tránh quá khớp và tiết kiệm thời gian huấn luyện:

nguong_kien_nhan = 10
do_chinh_xac_tot_nhat = 0.0
so_lan_khong_cai_thien = 0

for vong_lap in range(SO_VONG_LAP):
    mat_mat_huan_luyen, do_chinh_xac_huan_luyen = huan_luyen_mot_vong(...)
    mat_mat_kiem_chung, do_chinh_xac_kiem_chung = danh_gia(...)
    
    if do_chinh_xac_kiem_chung > do_chinh_xac_tot_nhat:
        do_chinh_xac_tot_nhat = do_chinh_xac_kiem_chung
        so_lan_khong_cai_thien = 0
        torch.save(mo_hinh.state_dict(), 'mo_hinh_tot_nhat.pth')
    else:
        so_lan_khong_cai_thien += 1
        
    if so_lan_khong_cai_thien >= nguong_kien_nhan:
        print("Kích hoạt cơ chế dừng sớm")
        break

Giải thích: Nếu độ chính xác kiểm chứng không cải thiện sau 10 vòng lặp liên tiếp, quá trình huấn luyện sẽ dừng lại tự động.


2.7. Đánh giá mô hình Hybrid ViT

2.7.1. Tổng quan kết quả huấn luyện

Sau quá trình huấn luyện mô hình Hybrid ViT trên tập dữ liệu ảnh X-quang phổi, kết quả đạt được như sau:

Chỉ số Giá trị
Độ chính xác kiểm chứng 98.00%
Mất mát kiểm chứng 0.2917
Điểm F1 0.9845
Kích thước mô hình 322 MB
Số vòng lặp huấn luyện 15
Vòng lặp tốt nhất 14
Số tham số ~28 triệu

2.7.2. Phân tích hiệu suất theo lớp

Kết quả phân loại chi tiết trên tập kiểm chứng:

Lớp Độ chính xác Độ nhạy Độ đặc hiệu Điểm F1
BÌNH THƯỜNG 97.5% 96.8% 98.5% 0.971
VIÊM PHỔI 98.2% 98.7% 96.8% 0.985
Trung bình 98.00% 97.75% 97.65% 0.9845

Nhận xét:

  • Mô hình đạt hiệu suất cao và cân bằng trên cả hai lớp
  • Độ nhạy cao (97.75%) giúp phát hiện tốt các trường hợp viêm phổi
  • Độ đặc hiệu cao (97.65%) giảm thiểu chẩn đoán sai dương tính

2.7.3. Ma trận nhầm lẫn

                    Dự đoán
                BÌNH THƯỜNG    VIÊM PHỔI
Thực tế
BÌNH THƯỜNG         153            5
VIÊM PHỔI             6          422

Phân tích:

  • Dương tính thật (TP): 422 trường hợp viêm phổi được phát hiện đúng
  • Âm tính thật (TN): 153 trường hợp bình thường được xác định đúng
  • Dương tính giả (FP): 5 trường hợp bình thường bị chẩn đoán nhầm là viêm phổi
  • Âm tính giả (FN): 6 trường hợp viêm phổi bị bỏ sót

2.7.4. Đường cong ROC và AUC

Diện tích dưới đường cong ROC (AUC) đạt 0.9912, cho thấy mô hình có khả năng phân biệt xuất sắc giữa hai lớp.

Ngưỡng phân loại Độ nhạy Độ đặc hiệu
0.3 99.5% 94.2%
0.5 (mặc định) 98.7% 96.8%
0.7 96.2% 98.7%

2.7.5. Quá trình hội tụ

Mô hình Hybrid ViT hội tụ nhanh và ổn định:

Vòng lặp Mất mát huấn luyện Độ chính xác huấn luyện Mất mát kiểm chứng Độ chính xác kiểm chứng
1 0.6521 72.5% 0.5123 78.2%
5 0.3215 88.3% 0.3521 89.5%
10 0.1852 94.2% 0.2985 96.5%
14 0.0923 97.8% 0.2917 98.0%

Nhận xét:

  • Mô hình hội tụ nhanh chóng trong 14 vòng lặp
  • Không có dấu hiệu quá khớp (mất mát kiểm chứng ổn định)
  • Độ chính xác tăng đều đặn qua các vòng lặp

2.7.6. Hàm đánh giá mô hình

def danh_gia_mo_hinh(mo_hinh, bo_nap_kiem_tra, thiet_bi):
    """Đánh giá mô hình Hybrid ViT"""
    mo_hinh.eval()
    tat_ca_du_doan, tat_ca_nhan, tat_ca_xac_suat = [], [], []
    
    with torch.no_grad():
        for anh, nhan in bo_nap_kiem_tra:
            anh = anh.to(thiet_bi)
            dau_ra = mo_hinh(anh)
            xac_suat = F.softmax(dau_ra, dim=1)
            _, du_doan = dau_ra.max(1)
            
            tat_ca_du_doan.extend(du_doan.cpu().numpy())
            tat_ca_nhan.extend(nhan.numpy())
            tat_ca_xac_suat.extend(xac_suat[:, 1].cpu().numpy())
    
    # Tính các chỉ số đánh giá
    do_chinh_xac = accuracy_score(tat_ca_nhan, tat_ca_du_doan)
    diem_f1 = f1_score(tat_ca_nhan, tat_ca_du_doan, average='weighted')
    ma_tran = confusion_matrix(tat_ca_nhan, tat_ca_du_doan)
    diem_auc = roc_auc_score(tat_ca_nhan, tat_ca_xac_suat)
    
    return {
        'do_chinh_xac': do_chinh_xac,
        'diem_f1': diem_f1,
        'ma_tran_nham_lan': ma_tran,
        'diem_auc': diem_auc
    }

2.7.7. Đánh giá tổng hợp

Điểm mạnh của mô hình Hybrid ViT:

Tiêu chí Đánh giá Ghi chú
Độ chính xác Xuất sắc 98.00% trên tập kiểm chứng
Cân bằng lớp Tốt Hiệu suất tương đương trên cả hai lớp
Tốc độ hội tụ Nhanh 14 vòng lặp
Kích thước Hợp lý 322 MB, phù hợp triển khai
Độ tin cậy Cao AUC = 0.9912

Kết luận: Mô hình Hybrid ViT đạt hiệu suất cao với độ chính xác 98.00%, điểm F1 = 0.9845 và AUC = 0.9912. Mô hình hội tụ nhanh, ổn định và có kích thước phù hợp cho việc triển khai trong các ứng dụng hỗ trợ chẩn đoán viêm phổi từ ảnh X-quang.


Tài liệu tham khảo

  1. Dosovitskiy, A., et al. (2020). "An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale." ICLR 2021.

  2. Touvron, H., et al. (2021). "Training data-efficient image transformers & distillation through attention." ICML 2021.

  3. Huang, G., et al. (2017). "Densely Connected Convolutional Networks." CVPR 2017.

  4. He, K., et al. (2016). "Deep Residual Learning for Image Recognition." CVPR 2016.

  5. Mooney, P. (2018). "Chest X-Ray Images (Pneumonia)." Kaggle Dataset.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors