BƯỚC 01
Bắt đầu từ đâu?
Học sau U-Net nhỏ. Cần phân biệt phân đoạn nhị phân và nhiều lớp loại trừ nhau.
Bạn sẽ xử lý mặt nạ nhiều lớp và đánh dấu vùng cần bỏ qua. Bài giải thích cách loại vùng đó khỏi cả hàm mất mát lẫn chỉ số đánh giá.
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install numpy matplotlib torchÝ nghĩa đoạn mã
Tạo môi trường riêng rồi gọi đúng Python trong môi trường. Không cần kích hoạt bằng một lệnh khác.
BƯỚC 02
Chuẩn bị điểm số đầu ra và target đúng kích thước
Với ba lớp loại trừ nhau, điểm số đầu ra có kích thước N×3×H×W, còn target có kích thước N×H×W và kiểu dữ liệu long. Mỗi pixel mang đúng một mã lớp.
Ta dùng 255 cho vùng chưa gán nhãn. Đây là giá trị bỏ qua, không phải lớp thứ tư. Không thêm chiều kênh bằng 1 vào target của CrossEntropyLoss trong thiết lập này.
from pathlib import Path
import json
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
OUTPUT = Path(__file__).resolve().parent / "results"
OUTPUT.mkdir(exist_ok=True)
plt.rcParams.update({"font.size": 12, "axes.spines.top": False,
"axes.spines.right": False, "figure.facecolor": "#f3f7f6",
"axes.facecolor": "white", "axes.titleweight": "bold"})
FIGURE = OUTPUT / "segmentation-multiclass-ignore.png"
import torch
from torch import nn
import torch.nn.functional as F
torch.manual_seed(7)
torch.set_num_threads(1)
target = torch.zeros(1,24,32,dtype=torch.long)
target[:,5:19,5:14] = 1
target[:,8:21,20:29] = 2
target[:,:3,:] = 255
logits = torch.randn(1,3,24,32,requires_grad=True)
loss = F.cross_entropy(logits,target,ignore_index=255)
loss.backward()
ignored = (target==255).unsqueeze(1).expand_as(logits)
assert logits.grad[ignored].abs().sum() == 0
assert torch.isfinite(logits.grad).all()
print("Loss:", float(loss.detach()))BƯỚC 03
Tính IoU theo lớp trên vùng hợp lệ
Dự đoán lấy argmax theo chiều lớp. IoU của mỗi lớp chỉ dùng pixel có nhãn thật khác 255.
Nếu một lớp không xuất hiện trong cả nhãn và dự đoán trên vùng hợp lệ, union bằng 0. Ví dụ báo NaN và bỏ lớp đó khỏi trung bình, thay vì tùy tiện gán điểm 0 hay 1. Chính sách này phải ghi rõ khi báo cáo.
prediction = logits.detach().argmax(dim=1)
valid = target != 255
ious = []
for class_id in range(3):
pred_class = (prediction==class_id) & valid
true_class = (target==class_id) & valid
intersection = (pred_class & true_class).sum().item()
union = (pred_class | true_class).sum().item()
ious.append(intersection/union if union else float("nan"))
mean_iou = float(np.nanmean(ious))
assert all(0 <= score <= 1 for score in ious)
print("IoU by class:", np.round(ious,3), "Mean:", round(mean_iou,3))BƯỚC 04
Hiển thị vùng bỏ qua bằng màu riêng
Vùng không có nhãn được tô xám để người đọc không nhầm với nền. Dự đoán từ điểm số đầu ra ngẫu nhiên chỉ để kiểm tra chương trình, không đại diện cho U-Net đã học.
Nếu một lô dữ liệu không có pixel hợp lệ, cần bỏ qua lô dữ liệu hoặc xử lý riêng. mean mất mát trên tập rỗng có thể không xác định.
from matplotlib.colors import ListedColormap
cmap = ListedColormap(["#dfe8d9","#317f55","#bb9149","#777777"])
display_target = target[0].numpy().copy()
display_target[display_target==255] = 3
display_pred = prediction[0].numpy().copy()
display_pred[~valid[0].numpy()] = 3
fig,axs = plt.subplots(1,3,figsize=(12,8),layout="constrained")
axs[0].imshow(display_target,cmap=cmap,vmin=0,vmax=3)
axs[0].set_title("Target, gray = ignored")
axs[1].imshow(display_pred,cmap=cmap,vmin=0,vmax=3)
axs[1].set_title("Random logits: shape check only")
for ax in axs[:2]:
ax.axis("off")
axs[2].bar(["Background","Class 1","Class 2"],ious,color=["#b3c9ae","#317f55","#bb9149"])
axs[2].set(ylim=(0,1),ylabel="IoU",title=f"Mean IoU = {mean_iou:.3f}")
axs[2].tick_params(axis="x",rotation=25)
fig.savefig(FIGURE, dpi=100)
plt.close(fig)
print("Saved:", FIGURE.name)BƯỚC 05
Chạy thử và đọc kết quả
Gradient tại mọi pixel bị bỏ qua bằng 0. IoU được tính trên vùng hợp lệ và nằm trong khoảng 0 đến 1.

.\.venv\Scripts\python.exe segmentation_multiclass_ignore.pyÝ nghĩa đoạn mã
Lệnh chạy toàn bộ tệp vừa tải. Nếu một assert không đúng, dừng lại và kiểm tra dữ liệu cùng bước tương ứng trước khi diễn giải hình.
Kiểm tra số liệu in ra trước, sau đó mới dùng hình để giải thích.
ĐẾN LƯỢT BẠN
Thử một thay đổi nhỏ
- Xóa lớp 2 khỏi target rồi tạo dự đoán cũng không có lớp 2.
- Kiểm tra IoU của lớp đó là NaN theo chính sách đã chọn.




