Kiểm chứng chéo K-Fold với Ultralytics#
Giới thiệu#
Hướng dẫn toàn diện này minh họa cách triển khai K-Fold Cross Validation cho các tập dữ liệu object detection trong hệ sinh thái Ultralytics. Chúng ta sẽ tận dụng định dạng phát hiện YOLO và các thư viện Python chính như sklearn, pandas và PyYAML để hướng dẫn bạn thiết lập các bước cần thiết, quy trình tạo vector đặc trưng và thực hiện phân chia tập dữ liệu K-Fold.
Dù dự án của bạn liên quan đến tập dữ liệu Fruit Detection hay một nguồn dữ liệu tùy chỉnh, hướng dẫn này nhằm giúp bạn hiểu và áp dụng K-Fold Cross Validation để củng cố độ tin cậy và sự mạnh mẽ cho các machine learning model của bạn. Mặc dù chúng tôi đang áp dụng k=5 fold cho hướng dẫn này, hãy nhớ rằng số lượng fold tối ưu có thể thay đổi tùy thuộc vào tập dữ liệu và các đặc thù của dự án bạn. K-Fold Cross Validation mang lại giá trị lớn nhất khi tập dữ liệu của bạn nhỏ, có nhiều nhiễu hoặc có độ biến động cao; đối với các tập dữ liệu lớn và đa dạng, việc phân tách train/val/test được xây dựng tốt thường là đủ.
Hãy bắt đầu thôi.
Thiết lập#
-
Các chú thích của bạn phải ở định dạng YOLO detection format.
-
Hướng dẫn này giả định rằng các tệp chú thích đã có sẵn cục bộ.
-
Đối với phần minh họa của chúng tôi, chúng tôi sử dụng tập dữ liệu Fruit Detection.
- Tập dữ liệu này chứa tổng cộng 8479 hình ảnh.
- Nó bao gồm 6 nhãn lớp, mỗi nhãn có tổng số lượng thực thể được liệt kê dưới đây.
| Nhãn lớp | Số lượng thực thể |
|---|---|
| Apple | 7049 |
| Grapes | 7202 |
| Pineapple | 1613 |
| Orange | 15549 |
| Banana | 3536 |
| Watermelon | 1976 |
-
Các gói Python cần thiết bao gồm:
ultralyticssklearnpandaspyyaml
-
Hướng dẫn này hoạt động với
k=5fold. Tuy nhiên, bạn nên xác định số lượng fold tốt nhất cho tập dữ liệu cụ thể của mình.
-
Khởi tạo một môi trường ảo Python mới (
venv) cho dự án của bạn và kích hoạt nó. Sử dụngpip(hoặc trình quản lý gói ưa thích của bạn) để cài đặt:- Thư viện Ultralytics:
pip install -U ultralytics. Ngoài ra, bạn có thể clone repo chính thức. - Scikit-learn, pandas và PyYAML:
pip install -U scikit-learn pandas pyyaml.
- Thư viện Ultralytics:
-
Xác minh rằng các chú thích của bạn nằm ở YOLO detection format.
- Đối với hướng dẫn này, tất cả các tệp chú thích đều nằm trong thư mục
Fruit-Detection/labels.
- Đối với hướng dẫn này, tất cả các tệp chú thích đều nằm trong thư mục
Tạo vectơ đặc trưng cho tập dữ liệu phát hiện đối tượng#
-
Bắt đầu bằng cách tạo một tệp Python
example.pymới cho các bước dưới đây. -
Tải các ảnh huấn luyện và xác thực đã được cấu hình thông qua dataset owner của gói, giữ nguyên phần test split.
from pathlib import Path from ultralytics.data.dataset import YOLODataset from ultralytics.data.utils import check_det_dataset yaml_file = "path/to/data.yaml" data = check_det_dataset(yaml_file) dataset_path = Path(data["path"]) sources = [] for split in ("train", "val"): source = data.get(split) if source: sources.extend(source if isinstance(source, list) else [source]) dataset = YOLODataset(sources, data=data, augment=False) images = [Path(p) for p in dataset.im_files] -
Bây giờ, hãy đọc nội dung của tệp YAML tập dữ liệu và trích xuất các chỉ số của nhãn lớp.
classes = data["names"] cls_idx = sorted(classes.keys()) -
Khởi tạo một DataFrame
pandastrống.import pandas as pd labels_df = pd.DataFrame(0.0, columns=cls_idx, index=images) -
Đếm các thực thể của mỗi nhãn lớp có mặt trong các tệp chú thích.
from collections import Counter for image, label in zip(images, dataset.labels): lbl_counter = Counter(label["cls"].flatten().astype(int)) labels_df.loc[image, list(lbl_counter)] = list(lbl_counter.values()) -
Sau đây là một chế độ xem mẫu của DataFrame đã được điền dữ liệu:
0 1 2 3 4 5 '0000a16e4b057580_jpg.rf.00ab48988370f64f5ca8ea4...' 0.0 0.0 0.0 0.0 0.0 7.0 '0000a16e4b057580_jpg.rf.7e6dce029fb67f01eb19aa7...' 0.0 0.0 0.0 0.0 0.0 7.0 '0000a16e4b057580_jpg.rf.bc4d31cdcbe229dd022957a...' 0.0 0.0 0.0 0.0 0.0 7.0 '00020ebf74c4881c_jpg.rf.508192a0a97aa6c4a3b6882...' 0.0 0.0 0.0 1.0 0.0 0.0 '00020ebf74c4881c_jpg.rf.5af192a2254c8ecc4188a25...' 0.0 0.0 0.0 1.0 0.0 0.0 ... ... ... ... ... ... ... 'ff4cd45896de38be_jpg.rf.c4b5e967ca10c7ced3b9e97...' 0.0 0.0 0.0 0.0 0.0 2.0 'ff4cd45896de38be_jpg.rf.ea4c1d37d2884b3e3cbce08...' 0.0 0.0 0.0 0.0 0.0 2.0 'ff5fd9c3c624b7dc_jpg.rf.bb519feaa36fc4bf630a033...' 1.0 0.0 0.0 0.0 0.0 0.0 'ff5fd9c3c624b7dc_jpg.rf.f0751c9c3aa4519ea3c9d6a...' 1.0 0.0 0.0 0.0 0.0 0.0 'fffe28b31f2a70d4_jpg.rf.7ea16bd637ba0711c53b540...' 0.0 6.0 0.0 0.0 0.0 0.0
Các hàng sử dụng đường dẫn ảnh tuyệt đối và các cột tương ứng với chỉ mục nhãn lớp. Các nhãn bị thiếu vẫn là các hàng nền toàn số không. Cấu trúc dữ liệu này cho phép áp dụng K-Fold Cross Validation cho một dataset phát hiện đối tượng.
Phân tách tập dữ liệu K-Fold#
-
Bây giờ chúng ta sẽ sử dụng lớp
KFoldtừsklearn.model_selectionđể tạo rakphần chia của tập dữ liệu.- Quan trọng:
- Việc thiết lập
shuffle=Trueđảm bảo phân phối ngẫu nhiên các lớp trong các phần chia của bạn. - Bằng cách đặt
random_state=Mtrong đóMlà một số nguyên đã chọn, bạn có thể thu được các kết quả có thể lặp lại.
- Việc thiết lập
from sklearn.model_selection import KFold ksplit = 5 kf = KFold(n_splits=ksplit, shuffle=True, random_state=20) # setting random_state for repeatable results kfolds = list(kf.split(labels_df)) - Quan trọng:
-
Tập dữ liệu giờ đây đã được chia thành
kfold, mỗi fold có một danh sách các chỉ mụctrainvàval. Chúng ta sẽ xây dựng một DataFrame để hiển thị các kết quả này rõ ràng hơn.folds = [f"split_{n}" for n in range(1, ksplit + 1)] folds_df = pd.DataFrame(index=labels_df.index, columns=folds) for i, (train, val) in enumerate(kfolds, start=1): folds_df.loc[labels_df.index[train], f"split_{i}"] = "train" folds_df.loc[labels_df.index[val], f"split_{i}"] = "val" -
Bây giờ chúng ta sẽ tính toán sự phân phối của các nhãn lớp cho mỗi fold dưới dạng tỷ lệ giữa các lớp có trong
valvới các lớp có trongtrain.fold_lbl_distrb = pd.DataFrame(index=folds, columns=cls_idx) for n, (train_indices, val_indices) in enumerate(kfolds, start=1): train_totals = labels_df.iloc[train_indices].sum() val_totals = labels_df.iloc[val_indices].sum() # To avoid division by zero, we add a small value (1E-7) to the denominator ratio = val_totals / (train_totals + 1e-7) fold_lbl_distrb.loc[f"split_{n}"] = ratioKịch bản lý tưởng là tất cả các tỷ lệ lớp đều hợp lý tương tự nhau cho mỗi lần phân tách và trên các lớp. Tuy nhiên, điều này sẽ phụ thuộc vào các đặc thù của tập dữ liệu của bạn.
-
Viết các danh sách ảnh và một dataset YAML cho từng split. Các danh sách dạng văn bản giúp tránh việc sao chép dataset
klần.import yaml save_path = dataset_path.parent / f"{ksplit}-Fold_Cross-val" save_path.mkdir(parents=True, exist_ok=True) ds_yamls = [] for split in folds_df.columns: for partition in ("train", "val"): split_images = folds_df.index[folds_df[split] == partition] paths = "\n".join(map(str, split_images)) (save_path / f"{split}_{partition}.txt").write_text(f"{paths}\n") dataset_yaml = save_path / f"{split}.yaml" ds_yamls.append(dataset_yaml) with open(dataset_yaml, "w") as ds_y: yaml.safe_dump( { "path": save_path.as_posix(), "train": f"{split}_train.txt", "val": f"{split}_val.txt", "names": classes, }, ds_y, )
Lưu bản ghi (Tùy chọn)#
Tùy chọn, bạn có thể lưu các bản ghi của việc phân tách K-Fold và DataFrame phân phối nhãn dưới dạng tệp CSV để tham khảo sau này.
folds_df.to_csv(save_path / "kfold_datasplit.csv")
fold_lbl_distrb.to_csv(save_path / "kfold_label_distribution.csv")Huấn luyện YOLO sử dụng các phân tách dữ liệu K-Fold#
-
Đầu tiên, tải mô hình YOLO.
from ultralytics import YOLO weights_path = "path/to/weights.pt" # use yolo26n.pt for a small model model = YOLO(weights_path, task="detect") -
Tiếp theo, lặp qua các tệp YAML của tập dữ liệu để chạy quá trình huấn luyện. Các kết quả sẽ được lưu vào một thư mục được chỉ định bởi các đối số
projectvàname. Theo mặc định, thư mục này là 'runs/detect/train#' trong đó # là một chỉ mục số nguyên.results = {} # Define your additional arguments here batch = 16 project = "kfold_demo" epochs = 100 for k, dataset_yaml in enumerate(ds_yamls): model = YOLO(weights_path, task="detect") results[k] = model.train( data=dataset_yaml, epochs=epochs, batch=batch, project=project, name=f"fold_{k + 1}" ) # include any additional train arguments -
Bạn cũng có thể sử dụng hàm Ultralytics data.split.autosplit để chia tập dữ liệu tự động:
from ultralytics.data.split import autosplit # Automatically split dataset into train/val/test autosplit(path="path/to/images", weights=(0.8, 0.2, 0.0), annotated_only=True)
Kết luận#
Trong hướng dẫn này, chúng ta đã tìm hiểu quy trình sử dụng K-Fold cross-validation để huấn luyện model phát hiện đối tượng YOLO. Chúng ta đã học cách chia tập huấn luyện và xác thực thành K phân vùng và sử dụng bảng tỷ lệ đã tạo để kiểm tra sự cân bằng lớp sau khi chia ngẫu nhiên.
Chúng ta cũng đã khám phá quy trình tạo các báo cáo DataFrame để trực quan hóa việc phân tách dữ liệu và phân phối nhãn trên các phần này, cung cấp cho chúng ta cái nhìn rõ ràng về cấu trúc của các tập huấn luyện và kiểm chứng của mình.
Tùy chọn, chúng ta đã lưu các bản ghi của mình để tham khảo trong tương lai, điều này có thể đặc biệt hữu ích trong các dự án quy mô lớn hoặc khi khắc phục sự cố hiệu suất mô hình.
Cuối cùng, chúng ta đã triển khai huấn luyện mô hình thực tế bằng cách sử dụng từng phần phân tách trong một vòng lặp, lưu lại kết quả huấn luyện để phân tích và so sánh thêm.
Kỹ thuật cross-validation K-Fold này là một cách mạnh mẽ để tận dụng tối đa dữ liệu khả dụng của bạn, và nó giúp đảm bảo rằng hiệu suất model của bạn đáng tin cậy và nhất quán trên các tập con dữ liệu khác nhau. Điều này mang lại một model tổng quát hóa tốt hơn và đáng tin cậy hơn, ít có khả năng overfit với các mẫu dữ liệu cụ thể.
Hãy nhớ rằng mặc dù chúng ta đã sử dụng YOLO trong hướng dẫn này, các bước này hầu như có thể chuyển đổi cho các mô hình học máy khác. Hiểu được các bước này cho phép bạn áp dụng kiểm chứng chéo một cách hiệu quả trong các dự án học máy của riêng bạn.
Câu hỏi thường gặp#
K-Fold Cross Validation là một kỹ thuật trong đó tập dữ liệu được chia thành 'k' tập con (fold) để đánh giá hiệu suất model đáng tin cậy hơn. Mỗi fold đóng vai trò là cả validation data và dữ liệu huấn luyện. Trong bối cảnh phát hiện đối tượng, việc sử dụng K-Fold Cross Validation giúp đảm bảo hiệu suất của Ultralytics YOLO model của bạn luôn mạnh mẽ và có khả năng tổng quát hóa trên các phân chia dữ liệu khác nhau, nâng cao độ tin cậy của nó. Để có hướng dẫn chi tiết về cách thiết lập K-Fold Cross Validation với Ultralytics YOLO, hãy tham khảo K-Fold Cross Validation with Ultralytics.
Để triển khai Kiểm chứng chéo K-Fold với Ultralytics YOLO, bạn cần thực hiện theo các bước sau:
- Xác minh các chú thích nằm ở YOLO detection format.
- Sử dụng các thư viện Python như
sklearn,pandasvàpyyaml. - Tạo các vectơ đặc trưng từ tập dữ liệu của bạn.
- Chia tập dữ liệu của bạn bằng cách sử dụng
KFoldtừsklearn.model_selection. - Huấn luyện mô hình YOLO trên mỗi phần phân tách.
Để có hướng dẫn toàn diện, hãy xem phần K-Fold Dataset Split trong tài liệu của chúng tôi.
Quy trình trong hướng dẫn này hướng đến định dạng YOLO detection, nhưng cách tiếp cận tương tự có thể áp dụng cho mọi tác vụ YOLO — tác vụ chỉ thay đổi cách bạn cấu trúc các fold, chứ không thay đổi việc cross-validation có hữu ích hay không:
Tác vụ Thiết kế fold detectChia tách ở cấp độ ảnh, cân bằng phân phối đối tượng và lớp trên các fold. Giữ các ảnh có liên quan (cùng bệnh nhân, chuỗi video, máy ảnh hoặc địa điểm) trong một fold duy nhất. segmentSử dụng chiến lược ở cấp độ ảnh giống như detection, đồng thời duy trì độ bao phủ của mask và lớp ở mọi fold. classifyƯu tiên các fold phân tầng (stratified) để tần suất các lớp được giữ cân bằng giữa quá trình training và validation. poseChia tách theo chủ thể hoặc chuỗi để cùng một người hoặc động vật không bao giờ xuất hiện ở cả hai phía của một fold. obbChia tách ở cấp độ ảnh, giữ các ô (tile) hoặc phần cắt (crop) từ cùng một cảnh lại với nhau — điều này đặc biệt quan trọng đối với ảnh chụp từ trên không (aerial imagery). Dù là tác vụ gì đi nữa, hãy giữ các mẫu gần như trùng lặp và có liên quan tránh xa các fold đối lập: loại rò rỉ (leakage) đó sẽ làm thổi phồng các metric validation vượt xa những gì model sẽ đạt được trong môi trường production.
Ultralytics YOLO cung cấp khả năng phát hiện đối tượng thời gian thực, tiên tiến với độ accuracy và hiệu quả cao. Nó rất linh hoạt, hỗ trợ nhiều tác vụ computer vision như detection, instance segmentation, semantic segmentation và classification. Ngoài ra, nó tích hợp liền mạch với các công cụ như Ultralytics Platform để huấn luyện và triển khai model không cần mã (no-code). Để biết thêm chi tiết, hãy khám phá các lợi ích và tính năng trên Ultralytics YOLO page của chúng tôi.
Các chú thích của bạn phải tuân theo định dạng phát hiện YOLO. Mỗi tệp chú thích phải liệt kê lớp đối tượng, cùng với tọa độ bounding box của nó trong hình ảnh. Định dạng YOLO đảm bảo quá trình xử lý dữ liệu được hợp lý hóa và chuẩn hóa để huấn luyện các model phát hiện đối tượng. Để biết thêm thông tin về định dạng chú thích phù hợp, hãy truy cập YOLO detection format guide.
Có, bạn có thể sử dụng K-Fold Cross Validation với bất kỳ tập dữ liệu tùy chỉnh nào miễn là các chú thích ở định dạng phát hiện YOLO. Thay thế các đường dẫn tập dữ liệu và nhãn lớp bằng các đường dẫn và nhãn cụ thể cho tập dữ liệu tùy chỉnh của bạn. Tính linh hoạt này đảm bảo rằng bất kỳ dự án phát hiện đối tượng nào cũng có thể hưởng lợi từ việc đánh giá model mạnh mẽ bằng cách sử dụng K-Fold Cross Validation. Để xem ví dụ thực tế, hãy xem lại phần Generating Feature Vectors của chúng tôi.