ResNet50-P3 / docs /DOCUMENTATION.md
chrisnguyenx's picture
Upload folder using huggingface_hub
10575e1 verified
|
Raw
History Blame Contribute Delete
11.5 kB

Tài liệu Kỹ thuật Mô hình AI — ResNet-50 Baseline

Chẩn đoán Bệnh Võng mạc Tiểu đường (Diabetic Retinopathy Classification)

Tài liệu này mô tả chi tiết kiến trúc mô hình AI, quy trình xử lý dữ liệu đầu vào (Image Preprocessing Pipeline), cơ chế suy luận (Inference), cấu trúc Chi tiết của File JSON Đầu ra thu được từ mô hình và REST API, cùng hướng dẫn tích hợp cho nhà phát triển Backend / Frontend cho mô hình ResNet-50 Baseline.


1. Tổng quan Hệ thống AI

Mô hình AI trong thư mục modelAI_ResNet50 được thiết kế để phân loại tự động 5 mức độ bệnh Võng mạc Tiểu đường (Diabetic Retinopathy - DR) theo tiêu chuẩn y tế quốc tế ICDR (International Clinical Diabetic Retinopathy Disease Severity Scale).

Thông số kỹ thuật chính:

  • Tên mô hình: ResNet50_DR
  • Backbone: ResNet-50 (Deep Residual Network với 50 layers và các kết nối tắt residual shortcuts)
  • Kích thước ảnh đầu vào: 224 × 224 pixel (3 kênh RGB)
  • Số lượng tham số: ~25.6 triệu tham số (Bottleneck Block Feature Extractor: 2048 channels)
  • Lớp đầu ra: 5 lớp tương ứng 5 mức độ bệnh (0: No DR, 1: Mild, 2: Moderate, 3: Severe, 4: Proliferative DR)
  • Môi trường thực thi: PyTorch 2.0+, CUDA / CPU

2. Kiến trúc Chi tiết Mô hình (Model Architecture)

Mô hình dựa trên kiến trúc ResNet-50 chuẩn được tinh chỉnh phần classifier head để phân loại 5 lớp DR.

[Input Image: 3 x 224 x 224]
          │
          ▼
[ResNet-50 Conv1 + MaxPool]
          │
          ▼  (64 channels, 56 x 56)
[Layer 1: 3 x Bottleneck Blocks] (256 channels)
          │
          ▼
[Layer 2: 4 x Bottleneck Blocks] (512 channels)
          │
          ▼
[Layer 3: 6 x Bottleneck Blocks] (1024 channels)
          │
          ▼
[Layer 4: 3 x Bottleneck Blocks] (2048 channels, 7 x 7)
          │
          ▼
[Adaptive Avg Pooling (1 x 1)]
          │
          ▼  (Flatten: Batch x 2048)
[Dropout (Rate = 0.3)]
          │
          ▼
[Linear Classifier Head (2048 -> 5)]
          │
          ▼
[Raw Logits Output (5 values)]
          │
          ▼
[Softmax Function] -> Xác suất cho 5 lớp [P0, P1, P2, P3, P4]

2.1. Residual Blocks (Khối kết nối tắt)

  • Khái niệm cốt lõi: Khối Bottleneck ($1 \times 1 \rightarrow 3 \times 3 \rightarrow 1 \times 1$ Conv) sử dụng đường truyền tắt (Identity Shortcut Connection) $\mathbf{y} = \mathcal{F}(\mathbf{x}) + \mathbf{x}$.
  • Ưu điểm: Giải quyết triệt để hiện tượng tiêu biến đạo hàm (Vanishing Gradient) trong các mạng nơ-ron rất sâu, giúp mô hình hội tụ tốt và học được các biểu diễn đặc trưng phong phú.
  • Classifier Head: Thay thế lớp kết nối đầy đủ mặc định bằng Dropout(p=0.3)Linear(2048, 5) để tương thích với 5 nhãn bệnh ICDR.

3. Quy trình Xử lý Ảnh Đầu vào (Preprocessing Pipeline)

Trước khi đưa ảnh đáy mắt (Fundus Photo) vào mô hình AI, dữ liệu được truyền qua pipeline xử lý ảnh 5 bước trong preprocessing.py:

[Ảnh gốc (File / Bytes / PIL / Array)]
                 │
                 ▼  1. load_image()
[Mảng BGR OpenCV (Numpy Array)]
                 │
                 ▼  2. auto_detect_border() & crop_fundus_circle()
[Ảnh đã cắt bỏ viền đen]
                 │
                 ▼  3. letterbox_resize(target_size=(224, 224))
[Ảnh 224x224 bảo toàn tỷ lệ aspect ratio (Đệm đen)]
                 │
                 ▼  4. ben_graham_transform()
[Ảnh tăng cường tương phản Ben Graham]
                 │
                 ▼  5. prepare_image_tensor()
[PyTorch Tensor (1, 3, 224, 224) - Normalized ImageNet]

Các bước xử lý chi tiết:

  1. Chuẩn hóa định dạng đầu vào (load_image):

    • Hỗ trợ đường dẫn file (str), mảng byte (bytes), đối tượng PIL Image, hoặc mảng NumPy.
    • Chuyển đổi tất cả về định dạng chuẩn OpenCV BGR (uint8).
  2. Cắt bỏ viền đen tự động (crop_fundus_circle):

    • Xác định ngưỡng tối CROP_TOLERANCE = 12.
    • Tìm Bounding Box của vùng cầu mắt có chứa thông tin y tế (cv2.findNonZero) và crop loại bỏ viền đen vô ích xung quanh.
  3. Letterbox Resize (letterbox_resize):

    • Thay vì co giãn làm biến dạng hình dạng tổn thương mắt, ảnh được scale giữ nguyên tỷ lệ chiều rộng/chiều cao.
    • Đệm thêm viền đen cân đối để đạt kích thước cố định (224, 224).
  4. Biến đổi Ben Graham (ben_graham_transform):

    • Áp dụng công thức lọc nhiễu & nổi bật mạch máu/tổn thương: $$\text{Output} = \text{clip}(4 \times I - 4 \times \text{GaussianBlur}(I, \sigma=10) + 128, 0, 255)$$
    • Cân bằng ánh sáng giữa các ảnh chụp từ nhiều thiết bị soi đáy mắt khác nhau.
  5. Chuyển đổi Tensor & Normalization:

    • Chuyển mảng BGR sang RGB.
    • Đưa về dải giá trị $[0.0, 1.0]$.
    • Chuẩn hóa theo chỉ số ImageNet: Mean [0.485, 0.456, 0.406], Std [0.229, 0.224, 0.225].
    • Mở rộng chiều batch: Tensor shape (1, 3, 224, 224).

4. Cách Mô hình Xử lý & Tạo ra File JSON Kết quả

Khi nhận yêu cầu phân loại, mô hình AI thực thi theo trình tự sau:

  1. Nhận dữ liệu & Tiền xử lý: Mảng ảnh được chuẩn hóa thành PyTorch Tensor.
  2. Forward Pass: Tensor được đẩy qua mô hình ResNet50_DR.
  3. Softmax Scoring: Tính xác suất cho từng nhãn: $$P(y = i | X) = \frac{e^{z_i}}{\sum_{j=0}^{4} e^{z_j}}$$
  4. Xác định Nhãn Dự đoán & Độ tin cậy:
    • class_id = $\arg\max_i P(y=i|X)$
    • confidence = $\max_i P(y=i|X)$
  5. Đóng gói Kết quả JSON:
    • Trích xuất bảng xác suất cho tất cả 5 nhãn.
    • Trả về đối tượng JSON chứa 4 trường: class_id, class_name, confidence, probabilities.

5. Cấu trúc File JSON Đầu ra (JSON Output Specification)

Định dạng JSON phản hồi từ DRPredictor.predict() (Python Core / SDK) cũng như REST API (POST /api/predict):

Ví dụ JSON Response chuẩn (HTTP 200 OK):

{
  "class_id": 0,
  "class_name": "No DR",
  "confidence": 0.9945334196090698,
  "probabilities": {
    "No DR": 0.9945334196090698,
    "Mild": 0.0008030196186155081,
    "Moderate": 0.0019999665673822165,
    "Severe": 0.0011487160809338093,
    "Proliferative DR": 0.0015149053651839495
  }
}

Mô tả chi tiết các trường dữ liệu:

Trường (Field) Kiểu dữ liệu Mô tả
class_id integer Chỉ số mức độ bệnh từ 0 đến 4.
class_name string Tên tiếng Anh chuẩn của nhãn ICDR tương ứng (No DR, Mild, Moderate, Severe, Proliferative DR).
confidence float Giá trị độ tin cậy của mô hình cho nhãn dự đoán (xác suất thô từ 0.0 đến 1.0).
probabilities object Bảng xác suất chi tiết của cả 5 nhãn ICDR.

6. Danh mục Lời khuyên Y tế Lâm sàng (Clinical Guidance Table)

Bảng ánh xạ từ class_id ra chỉ dẫn y tế và màu sắc giao diện:

Class ID Nhãn ICDR Tiêu đề Tiếng Việt (title) Mức khẩn cấp (urgency) Mã màu (badge_color)
0 No DR Mắt Bình Thường (No DR) Bình thường #10b981 (Xanh lá)
1 Mild Bệnh Nhẹ (Mild DR) Theo dõi định kỳ #3b82f6 (Xanh dương)
2 Moderate Bệnh Trung Bình (Moderate DR) Khám chuyên khoa #f59e0b (Cam vàng)
3 Severe Bệnh Nặng (Severe DR) Cần can thiệp sớm #ef4444 (Đỏ)
4 Proliferative DR Tăng Sinh Nguy Hiểm (Proliferative DR) KHẨN CẤP #8b5cf6 (Tím)

7. Hướng dẫn Tích hợp API (API Integration Guide)

7.1. Khởi chạy REST API Server

# Di chuyển vào thư mục modelAI_ResNet50
cd modelAI_ResNet50

# Chạy server uvicorn
python main_api.py

Server sẽ chạy tại địa chỉ: http://localhost:8000. Bạn có thể truy cập /docs để mở giao diện Swagger UI tương tác.


7.2. Các Endpoints

1. Kiểm tra trạng thái máy chủ

  • URL: GET /
  • Response:
{
  "message": "AI Diabetic Retinopathy API Service is running.",
  "docs_url": "/docs",
  "health_check": "/api/info",
  "predict_endpoint": "POST /api/predict"
}

2. Thông tin mô hình AI

  • URL: GET /api/info
  • Response:
{
  "status": "online",
  "model_name": "ResNet50",
  "num_classes": 5,
  "device": "cuda:0",
  "classes": {
    "0": "No DR",
    "1": "Mild",
    "2": "Moderate",
    "3": "Severe",
    "4": "Proliferative DR"
  }
}

3. Chẩn đoán ảnh đáy mắt

  • URL: POST /api/predict
  • Content-Type: multipart/form-data
  • Body Form-Data: file: [File ảnh PNG / JPG / JPEG]

7.3. Ví dụ Code Gọi API

A. cURL Command:

curl -X POST "http://localhost:8000/api/predict" \
  -H "accept: application/json" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@/path/to/fundus_image.jpg"

B. Python Code (requests):

import requests

url = "http://localhost:8000/api/predict"
file_path = "test_eye.jpg"

with open(file_path, "rb") as f:
    files = {"file": (file_path, f, "image/jpeg")}
    response = requests.post(url, files=files)

data = response.json()
print("Kết quả chẩn đoán:", data["class_name"])
print("Độ tin cậy:", data["confidence"])
print("Xác suất từng lớp:", data["probabilities"])

C. JavaScript (Fetch API - Frontend React/Vue/Vanilla):

async function predictFundusImage(fileInput) {
  const formData = new FormData();
  formData.append("file", fileInput.files[0]);

  const response = await fetch("http://localhost:8000/api/predict", {
    method: "POST",
    body: formData
  });

  const result = await response.json();
  console.log("JSON Trả về từ AI ResNet-50:", result);
  // { class_id, class_name, confidence, probabilities }
}

8. Xử lý Lỗi (Error Handling & HTTP Status Codes)

Status Code Nguyên nhân phát sinh Cấu trúc JSON Lỗi
400 Bad Request File tải lên không phải định dạng ảnh hợp lệ (VD: PDF, TXT). {"detail": "File tải lên không phải là định dạng ảnh hợp lệ."}
500 Internal Error Không nạp được file weights .pth hoặc lỗi bộ nhớ GPU/CPU trong quá trình xử lý ảnh. {"detail": "Lỗi trong quá trình xử lý ảnh: [chi tiết lỗi]"}

9. Đóng gói Docker Container

Để triển khai hệ thống lên môi trường Server / Cloud:

# Build image Docker
docker build -t dr-resnet50-api .

# Chạy container
docker run -d -p 8000:8000 --name dr_resnet50_service dr-resnet50-api

Hoặc khởi chạy thông qua docker-compose:

docker-compose up -d