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 Kiểm chứng chéo K-Fold 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 quan trọng như sklearn, pandas và PyYAML để hướng dẫn bạn thiết lập cần thiết, quy trình tạo vectơ đặc trưng và thực hiện phân tách tập dữ liệu K-Fold.
Cho dù dự án của bạn liên quan đến tập dữ liệu Fruit Detection hay nguồn dữ liệu tùy chỉnh, hướng dẫn này nhằm mục đích giúp bạn hiểu và áp dụng Kiểm chứng chéo K-Fold để tăng cường độ tin cậy và tính mạnh mẽ của các mô hình machine learning của bạn. Mặc dù chúng ta đang áp dụng k=5 fold cho hướng dẫn này, hãy lưu ý 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 chi tiết cụ thể của dự án của bạn.
Hãy bắt đầu nào.
Thiết lập
-
Các chú thích của bạn phải ở định dạng phát hiện YOLO.
-
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 trình diễn 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 cá thể được liệt kê bên dưới.
| Nhãn lớp | Số lượng 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 vận hành 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 ở định dạng phát hiện YOLO.
- Đối với hướng dẫn này, tất cả các tệp chú thích được tìm thấy 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 được tìm thấy trong thư mục
Tạo các vectơ đặc trưng cho tập dữ liệu Object Detection
-
Bắt đầu bằng việc tạo một tệp Python
example.pymới cho các bước bên dưới. -
Tiến hành truy xuất tất cả các tệp nhãn cho tập dữ liệu của bạn.
from pathlib import Path dataset_path = Path("./Fruit-detection") # replace with 'path/to/dataset' for your custom data labels = sorted(dataset_path.rglob("*labels/*.txt")) # all data in 'labels' -
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ỉ mục của các nhãn lớp.
import yaml yaml_file = "path/to/data.yaml" # your data YAML with data directories and names dictionary with open(yaml_file, encoding="utf8") as y: classes = yaml.safe_load(y)["names"] cls_idx = sorted(classes.keys()) -
Khởi tạo một
pandasDataFrame trống.import pandas as pd index = [label.stem for label in labels] # uses base filename as ID (no extension) labels_df = pd.DataFrame([], columns=cls_idx, index=index) -
Đếm các cá thể của từng nhãn lớp có trong các tệp chú thích.
from collections import Counter for label in labels: lbl_counter = Counter() with open(label) as lf: lines = lf.readlines() for line in lines: # classes for YOLO label uses integer at first position of each line lbl_counter[int(line.split(" ", 1)[0])] += 1 labels_df.loc[label.stem] = lbl_counter labels_df = labels_df.fillna(0.0) # replace `nan` values with `0.0` -
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 đánh chỉ mục các tệp nhãn, mỗi hàng tương ứng với một hình ảnh trong tập dữ liệu của bạn và các cột tương ứng với các chỉ mục nhãn lớp của bạn. Mỗi hàng đại diện cho một vectơ đặc trưng giả, với số lượng của từng nhãn lớp có trong tập dữ liệu của bạn. Cấu trúc dữ liệu này cho phép áp dụng Kiểm chứng chéo K-Fold vào một tập dữ liệu object detection.
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ạokphần phân tách của tập dữ liệu.- Quan trọng:
- Việc đặt
shuffle=Trueđảm bảo sự phân phối ngẫu nhiên các lớp trong các phần phân tách của bạn. - Bằng cách đặt
random_state=Mtrong đóMlà một số nguyên đã chọn, bạn có thể nhận được kết quả có thể lặp lại.
- Việc đặt
import random from sklearn.model_selection import KFold random.seed(0) # for reproducibility 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 hiện đã đượ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=index, columns=folds) for i, (train, val) in enumerate(kfolds, start=1): folds_df[f"split_{i}"].loc[labels_df.iloc[train].index] = "train" folds_df[f"split_{i}"].loc[labels_df.iloc[val].index] = "val" -
Bây giờ chúng ta sẽ tính toán sự phân phối các nhãn lớp cho từng fold dưới dạng tỷ lệ giữa các lớp có trong
valso vớ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 phải tương đối giống 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 điểm cụ thể của tập dữ liệu của bạn.
-
Tiếp theo, chúng ta tạo các thư mục và tệp YAML tập dữ liệu cho mỗi lần phân tách.
import datetime supported_extensions = [".jpg", ".jpeg", ".png"] # Initialize an empty list to store image file paths images = [] # Loop through supported extensions and gather image files for ext in supported_extensions: images.extend(sorted((dataset_path / "images").rglob(f"*{ext}"))) # Create the necessary directories and dataset YAML files save_path = Path(dataset_path / f"{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-val") save_path.mkdir(parents=True, exist_ok=True) ds_yamls = [] for split in folds_df.columns: # Create directories split_dir = save_path / split split_dir.mkdir(parents=True, exist_ok=True) (split_dir / "train" / "images").mkdir(parents=True, exist_ok=True) (split_dir / "train" / "labels").mkdir(parents=True, exist_ok=True) (split_dir / "val" / "images").mkdir(parents=True, exist_ok=True) (split_dir / "val" / "labels").mkdir(parents=True, exist_ok=True) # Create dataset YAML files dataset_yaml = split_dir / f"{split}_dataset.yaml" ds_yamls.append(dataset_yaml) with open(dataset_yaml, "w") as ds_y: yaml.safe_dump( { "path": split_dir.as_posix(), "train": "train", "val": "val", "names": classes, }, ds_y, ) -
Cuối cùng, sao chép hình ảnh và nhãn vào thư mục tương ứng ('train' hoặc 'val') cho mỗi lần phân tách.
- LƯU Ý: Thời gian cần thiết cho phần này của mã sẽ thay đổi dựa trên kích thước tập dữ liệu của bạn và phần cứng hệ thống của bạn.
import shutil from tqdm import tqdm for image, label in tqdm(zip(images, labels), total=len(images), desc="Copying files"): for split, k_split in folds_df.loc[image.stem].items(): # Destination directory img_to_path = save_path / split / k_split / "images" lbl_to_path = save_path / split / k_split / "labels" # Copy image and label files to new directory (SamefileError if file already exists) shutil.copy(image, img_to_path / image.name) shutil.copy(label, lbl_to_path / label.name)
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 các DataFrame phân tách K-Fold và 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 phân tách dữ liệu K-Fold
-
Trước tiên, hãy 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 tập dữ liệu để chạy 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à 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.utils.autosplit để tự động phân tách tập dữ liệu:
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 đã khám phá quy trình sử dụng kiểm chứng chéo K-Fold để huấn luyện mô hình object detection YOLO. Chúng ta đã học cách chia tập dữ liệu của mình thành K phân vùng, đảm bảo sự phân phối lớp cân bằng trên các fold khác nhau.
Chúng ta cũng đã khám phá quy trình tạo các DataFrame báo cáo để 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 phân tách 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à xác thực của chúng ta.
Tùy chọn, chúng ta đã lưu các bản ghi để tham khảo sau này, đ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 đã thực hiện việc 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 các kết quả huấn luyện để phân tích và so sánh thêm.
Kỹ thuật kiểm chứng chéo K-Fold này là một cách mạnh mẽ để tận dụng tối đa dữ liệu hiện có của bạn và nó giúp đảm bảo rằng hiệu suất mô hình 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 dẫn đến một mô hình có khả năng tổng quát hóa tốt hơn và đáng tin cậy hơn, ít có khả năng overfit vào 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ể áp dụng cho các mô hình machine learning khác. Việc hiểu các bước này cho phép bạn áp dụng hiệu quả việc kiểm chứng chéo vào các dự án machine learning của riêng bạn.
Câu hỏi thường gặp (FAQ)
Kiểm chứng chéo K-Fold là gì và tại sao nó hữu ích trong object detection?
Kiểm chứng chéo K-Fold 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 mô hình một cách đáng tin cậy hơn. Mỗi fold đóng vai trò là cả dữ liệu huấn luyện và dữ liệu xác thực. Trong bối cảnh object detection, việc sử dụng Kiểm chứng chéo K-Fold giúp đảm bảo hiệu suất của mô hình Ultralytics YOLO của bạn mạnh mẽ và có khả năng tổng quát hóa trên các phần phân tách dữ liệu khác nhau, nâng cao độ tin cậy của nó. Để biết hướng dẫn chi tiết về cách thiết lập Kiểm chứng chéo K-Fold với Ultralytics YOLO, hãy tham khảo Kiểm chứng chéo K-Fold với Ultralytics.
Làm thế nào để tôi triển khai Kiểm chứng chéo K-Fold bằng Ultralytics YOLO?
Để triển khai Kiểm chứng chéo K-Fold với Ultralytics YOLO, bạn cần thực hiện các bước sau:
- Xác minh các chú thích nằm ở định dạng phát hiện YOLO.
- 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 từng phần phân tách.
Để có hướng dẫn toàn diện, hãy xem phần Phân tách tập dữ liệu K-Fold trong tài liệu của chúng tôi.
Tại sao tôi nên sử dụng Ultralytics YOLO để thực hiện object detection?
Ultralytics YOLO cung cấp tính năng object detection thời gian thực, hiện đại với độ chính xác cao và hiệu quả. Nó rất linh hoạt, hỗ trợ nhiều tác vụ computer vision như phát hiện, phân đoạn và phân loại. Ngoài ra, nó tích hợp liền mạch với các công cụ như Nền tảng Ultralytics cho việc huấn luyện và triển khai mô hình 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 trang Ultralytics YOLO của chúng tôi.
Làm thế nào tôi có thể đảm bảo các chú thích của mình ở đúng định dạng cho Ultralytics YOLO?
Các chú thích của bạn nên 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 tinh giản và chuẩn hóa để huấn luyện các mô hình object detection. Để biết thêm thông tin về định dạng chú thích phù hợp, hãy truy cập hướng dẫn định dạng phát hiện YOLO.
Tôi có thể sử dụng Kiểm chứng chéo K-Fold với các tập dữ liệu tùy chỉnh khác ngoài Fruit Detection không?
Có, bạn có thể sử dụng Kiểm chứng chéo K-Fold 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 những nhãn cụ thể cho tập dữ liệu tùy chỉnh của bạn. Sự linh hoạt này đảm bảo rằng bất kỳ dự án object detection nào cũng có thể hưởng lợi từ việc đánh giá mô hình mạnh mẽ bằng cách sử dụng Kiểm chứng chéo K-Fold. Để có ví dụ thực tế, hãy xem lại phần Tạo vectơ đặc trưng của chúng tôi.