सामग्री पर जाएं

के-फोल्ड क्रॉस वैलिडेशन के साथ Ultralytics

परिचय

यह व्यापक मार्गदर्शिका के भीतर ऑब्जेक्ट डिटेक्शन डेटासेट के लिए के-फोल्ड क्रॉस वैलिडेशन के कार्यान्वयन को दर्शाती है Ultralytics पारिस्थितिकी तंत्र। हम लाभ उठाएंगे YOLO डिटेक्शन फॉर्मेट और कुंजी Python आवश्यक सेटअप, फीचर वैक्टर उत्पन्न करने की प्रक्रिया और के-फोल्ड डेटासेट विभाजन के निष्पादन के माध्यम से आपका मार्गदर्शन करने के लिए स्केलर्न, पांडा और PyYaml जैसे पुस्तकालय।

के-फोल्ड क्रॉस सत्यापन अवलोकन

चाहे आपकी परियोजना में फ्रूट डिटेक्शन डेटासेट या कस्टम डेटा स्रोत शामिल हो, इस ट्यूटोरियल का उद्देश्य आपके मशीन लर्निंग मॉडल की विश्वसनीयता और मजबूती को बढ़ाने के लिए के-फोल्ड क्रॉस सत्यापन को समझने और लागू करने में आपकी सहायता करना है। जबकि हम आवेदन कर रहे हैं k=5 इस ट्यूटोरियल के लिए फोल्ड, ध्यान रखें कि फोल्ड की इष्टतम संख्या आपके डेटासेट और आपके प्रोजेक्ट की बारीकियों के आधार पर भिन्न हो सकती है।

आगे की हलचल के बिना, आइए गोता लगाएँ!

सेटअप

  • आपके एनोटेशन YOLO पता लगाने का प्रारूप

  • यह मार्गदर्शिका मानती है कि एनोटेशन फ़ाइलें स्थानीय रूप से उपलब्ध हैं।

  • हमारे प्रदर्शन के लिए, हम फ्रूट डिटेक्शन डेटासेट का उपयोग करते हैं।

    • इस डेटासेट में कुल 8479 चित्र हैं।
    • इसमें 6 वर्ग लेबल शामिल हैं, जिनमें से प्रत्येक की कुल उदाहरण गणना नीचे सूचीबद्ध है।
कक्षा लेबल इंस्टेंस काउंट
सेब 7049
अंगूर 7202
अनन्‍नास 1613
नारंगी 15549
केला 3536
तरबूज़ 1976
  • ज़रूरी Python पैकेज में शामिल हैं:

    • ultralytics
    • sklearn
    • pandas
    • pyyaml
  • यह ट्यूटोरियल इसके साथ काम करता है k=5 परतों। हालांकि, आपको अपने विशिष्ट डेटासेट के लिए सबसे अच्छी संख्या निर्धारित करनी चाहिए।

  • एक नया आरंभ करें Python आभासी वातावरण (venv) अपने प्रोजेक्ट के लिए और इसे सक्रिय करें। प्रयोग pip (या आपका पसंदीदा पैकेज मैनेजर) स्थापित करने के लिए:

    • वही Ultralytics पुस्तकालय: pip install -U ultralytics. वैकल्पिक रूप से, आप अधिकारी को क्लोन कर सकते हैं रेपो.
    • स्किकिट-लर्न, पांडा और पाययम्ल: pip install -U scikit-learn pandas pyyaml.
  • सत्यापित करें कि आपके एनोटेशन YOLO पता लगाने का प्रारूप

    • इस ट्यूटोरियल के लिए, सभी एनोटेशन फाइलें Fruit-Detection/labels डायरेक्टरी।

ऑब्जेक्ट डिटेक्शन डेटासेट के लिए फ़ीचर वैक्टर जनरेट करना

  1. एक नया बनाकर प्रारंभ करें Python फ़ाइल और आवश्यक पुस्तकालयों को आयात करें।

    import datetime
    import shutil
    from collections import Counter
    from pathlib import Path
    
    import numpy as np
    import pandas as pd
    import yaml
    from sklearn.model_selection import KFold
    from ultralytics import YOLO
    
  2. अपने डेटासेट के लिए सभी लेबल फ़ाइलों को पुनः प्राप्त करने के लिए आगे बढ़ें।

    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'
    
  3. अब, डेटासेट YAML फ़ाइल की सामग्री पढ़ें और क्लास लेबल के सूचकांक निकालें।

    yaml_file = "path/to/data.yaml"  # your data YAML with data directories and names dictionary
    with open(yaml_file, "r", encoding="utf8") as y:
        classes = yaml.safe_load(y)["names"]
    cls_idx = sorted(classes.keys())
    
  4. किसी रिक्त को प्रारंभ करना pandas डेटाफ्रेम।

    indx = [l.stem for l in labels]  # uses base filename as ID (no extension)
    labels_df = pd.DataFrame([], columns=cls_idx, index=indx)
    
  5. एनोटेशन फ़ाइलों में मौजूद प्रत्येक वर्ग-लेबल के उदाहरणों की गणना करें।

    for label in labels:
        lbl_counter = Counter()
    
        with open(label, "r") as lf:
            lines = lf.readlines()
    
        for l in lines:
            # classes for YOLO label uses integer at first position of each line
            lbl_counter[int(l.split(" ")[0])] += 1
    
        labels_df.loc[label.stem] = lbl_counter
    
    labels_df = labels_df.fillna(0.0)  # replace `nan` values with `0.0`
    
  6. पॉपुलेटेड डेटा फ़्रेम का एक नमूना दृश्य निम्न है:

                                                           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
    

पंक्तियाँ लेबल फ़ाइलों को अनुक्रमित करती हैं, प्रत्येक आपके डेटासेट में एक छवि के अनुरूप होती है, और कॉलम आपके वर्ग-लेबल सूचकांकों के अनुरूप होते हैं। प्रत्येक पंक्ति एक छद्म सुविधा-वेक्टर का प्रतिनिधित्व करती है, जिसमें आपके डेटासेट में मौजूद प्रत्येक वर्ग-लेबल की गिनती होती है। यह डेटा संरचना ऑब्जेक्ट डिटेक्शन डेटासेट में के-फोल्ड क्रॉस वैलिडेशन के अनुप्रयोग को सक्षम बनाती है।

के-फोल्ड डेटासेट स्प्लिट

  1. अब हम KFold से वर्ग sklearn.model_selection उत्पन्न करने के लिए k डेटासेट के विभाजन।

    • महत्वपूर्ण:
      • सेटिंग shuffle=True आपके विभाजन में कक्षाओं का यादृच्छिक वितरण सुनिश्चित करता है।
      • सेट करके random_state=M कहां M एक चुना हुआ पूर्णांक है, आप दोहराने योग्य परिणाम प्राप्त कर सकते हैं।
    ksplit = 5
    kf = KFold(n_splits=ksplit, shuffle=True, random_state=20)  # setting random_state for repeatable results
    
    kfolds = list(kf.split(labels_df))
    
  2. डेटासेट को अब विभाजित कर दिया गया है k सिलवटों, प्रत्येक की एक सूची है train और val सूचकांक। हम इन परिणामों को अधिक स्पष्ट रूप से प्रदर्शित करने के लिए एक डेटाफ्रेम का निर्माण करेंगे।

    folds = [f"split_{n}" for n in range(1, ksplit + 1)]
    folds_df = pd.DataFrame(index=indx, columns=folds)
    
    for idx, (train, val) in enumerate(kfolds, start=1):
        folds_df[f"split_{idx}"].loc[labels_df.iloc[train].index] = "train"
        folds_df[f"split_{idx}"].loc[labels_df.iloc[val].index] = "val"
    
  3. अब हम प्रत्येक तह के लिए वर्ग लेबल के वितरण की गणना 1999 में उपस्थित वर्गों के अनुपात के रूप में करेंगे। val में उपस्थित लोगों के लिए train.

    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}"] = ratio
    

आदर्श परिदृश्य सभी वर्ग अनुपातों के लिए प्रत्येक विभाजन और सभी वर्गों के लिए यथोचित समान होना है। हालाँकि, यह आपके डेटासेट की बारीकियों के अधीन होगा।

  1. इसके बाद, हम प्रत्येक विभाजन के लिए निर्देशिका और डेटासेट YAML फ़ाइलें बनाते हैं।

    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 (unchanged)
    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,
            )
    
  2. अंत में, प्रत्येक विभाजन के लिए छवियों और लेबल को संबंधित निर्देशिका ('ट्रेन' या 'वैल') में कॉपी करें।

    • नोट: कोड के इस भाग के लिए आवश्यक समय आपके डेटासेट और आपके सिस्टम हार्डवेयर के आकार के आधार पर अलग-अलग होगा।
    for image, label in zip(images, labels):
        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)
    

रिकॉर्ड्स सहेजें (वैकल्पिक)

वैकल्पिक रूप से, आप भविष्य के संदर्भ के लिए के-फोल्ड स्प्लिट और लेबल वितरण डेटाफ्रेम के रिकॉर्ड को सीएसवी फाइलों के रूप में सहेज सकते हैं।

folds_df.to_csv(save_path / "kfold_datasplit.csv")
fold_lbl_distrb.to_csv(save_path / "kfold_label_distribution.csv")

रेलगाड़ी YOLO के-फोल्ड डेटा स्प्लिट का उपयोग करना

  1. सबसे पहले, लोड करें YOLO को गढ़ना।

    weights_path = "path/to/weights.pt"
    model = YOLO(weights_path, task="detect")
    
  2. इसके बाद, प्रशिक्षण चलाने के लिए डेटासेट YAML फ़ाइलों पर पुनरावृति करें। परिणाम द्वारा निर्दिष्ट निर्देशिका में सहेजे जाएंगे project और name तर्क। डिफ़ॉल्ट रूप से, यह निर्देशिका 'exp/runs#' है जहां # एक पूर्णांक सूचकांक है।

    results = {}
    
    # Define your additional arguments here
    batch = 16
    project = "kfold_demo"
    epochs = 100
    
    for k in range(ksplit):
        dataset_yaml = ds_yamls[k]
        model.train(data=dataset_yaml, epochs=epochs, batch=batch, project=project)  # include any train arguments
        results[k] = model.metrics  # save output metrics for further analysis
    

समाप्ति

इस गाइड में, हमने प्रशिक्षण के लिए के-फोल्ड क्रॉस-सत्यापन का उपयोग करने की प्रक्रिया का पता लगाया है YOLO वस्तु का पता लगाने का मॉडल। हमने सीखा कि अपने डेटासेट को K विभाजन में कैसे विभाजित किया जाए, जिससे विभिन्न सिलवटों में संतुलित वर्ग वितरण सुनिश्चित हो।

हमने इन विभाजनों में डेटा विभाजन और लेबल वितरण की कल्पना करने के लिए रिपोर्ट डेटाफ्रेम बनाने की प्रक्रिया का भी पता लगाया, जिससे हमें अपने प्रशिक्षण और सत्यापन सेट की संरचना में स्पष्ट जानकारी मिली।

वैकल्पिक रूप से, हमने भविष्य के संदर्भ के लिए अपने रिकॉर्ड सहेजे, जो विशेष रूप से बड़े पैमाने की परियोजनाओं में या मॉडल प्रदर्शन का समस्या निवारण करते समय उपयोगी हो सकते हैं।

अंत में, हमने लूप में प्रत्येक विभाजन का उपयोग करके वास्तविक मॉडल प्रशिक्षण को लागू किया, जिससे आगे के विश्लेषण और तुलना के लिए हमारे प्रशिक्षण परिणामों को बचाया जा सके।

के-फोल्ड क्रॉस-सत्यापन की यह तकनीक आपके उपलब्ध डेटा का अधिकतम लाभ उठाने का एक मजबूत तरीका है, और यह सुनिश्चित करने में मदद करता है कि आपका मॉडल प्रदर्शन विभिन्न डेटा सबसेट में विश्वसनीय और सुसंगत है। इसके परिणामस्वरूप एक अधिक सामान्य और विश्वसनीय मॉडल होता है जो विशिष्ट डेटा पैटर्न के लिए ओवरफिट होने की संभावना कम होती है।

याद रखें कि हालांकि हमने इस्तेमाल किया था YOLO इस गाइड में, ये चरण ज्यादातर अन्य मशीन लर्निंग मॉडल के लिए हस्तांतरणीय हैं। इन चरणों को समझने से आप अपनी मशीन लर्निंग परियोजनाओं में प्रभावी ढंग से क्रॉस-सत्यापन लागू कर सकते हैं। हैप्पी कोडिंग!



बनाया गया 2023-11-12, अपडेट किया गया 2024-05-18
लेखक: ग्लेन-जोचर (6), बुरहान-क्यू (1)

टिप्पणियाँ