Table of Contents Տեղինակային բաղադրիչներ Հիմնական հոդվածը: Ապրանքանիշները գեղեցիկ են, նկարները անվճար են 1-րդ մասը — Data Exploration: Կարդալեք, որ տվյալները դուք աշխատում եք 2-րդ մասը — Preprocessing: Speaking the Model’s Language Ապրիշ 3 — Նկարագրության արտադրություն: Տեսակներ փոխելու համարչական մանրամասներ Ապրիշ 4 - Unsurveiled Clustering: Discovering Structure in the Dark (Ապրիշ 4 - Ապրիշ 4 - Ապրիշ 4 - Ապրիշ 4 - Ապրիշ 4 - Ապրիշ 4 - Ապրիշ 4 ) 5-րդ մասը — Semi-Supervised Training: The Core Experiment Արդյոք, դուք կարող եք ստանալ ավելի շատ բաղադրիչներ, քան դուք կարող եք ստանալ. Հյուրատետր Ապրանքանիշները գեղեցիկ են, նկարները անվճար են «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալ»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապատալական»: «Ապ Հետեւաբար, ընկերությունները հաճախ ունեն միլիոններ տեսանյութեր (կամերերերի, սենզորների, օգտագործողների բեռնելների), բայց կարող են մանրամասել միայն մի քիչ մասը: Սա այնտեղ է, որտեղ Արդյոք, այնպես էլ, որ չնայած մանրամասները, մենք օգտագործում ենք այդ մանրամասները մանրամասների բարելավման համար, որը միացվում է փոքր մանրամասների հետ մեծ մանրամասների հետ: semi-supervised learning Տեսեք, որ դուք մի ուսանող եք 30 ուսանողների հետ: Դուք բոլորին ստանում եք փորձը, բայց դուք միայն ունեք ժամանակ 5 գրքերով: Դուք ճշգրիտորեն ստանում եք այդ 5 գրքերով, եւ դուք ստանում եք մոդելներ: ուսանողները, ովքեր շատ գրել են, սովորաբար ստանում են բարձր գովակներ, եւ ուսանողները, ովքեր փակել են պատասխանները, սովորաբար ստանում են ցածր գովակներ: Այս մոդելներ օգտագործելով, դուք կարող եք գնահատել այլ 25 գրքերից գովակները, առանց կարդալ բոլոր գովակները: Սա կասկածել է ուսուցում: Դուք օգտագործում եք մի քանի գովակված գրքեր (լաստագրված տվյալները), որպեսզի հասկանալ մոդելներ, ապա օգտագործեք այդ մոդելներ անպասկած Այս հոդվածը կառուցում է ամբողջական semi-supervised image classification խողովակների գիշերից. Մենք աշխատում ենք բոլոր քայլերի հետ ներգրավված բացառություններ, քանի որ մենք գնալ. Տեսագրություն: Ապրանքի սխալները մետաղական մակերեսներում հայտնաբերվում են: Ապրանքի գործարանը արտադրում է պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պողպատ պ Case Studies Վիքիպահեստում Ապրանքանիշը արտադրում է պողպատ թերթիկներ, եւ կատեգորիաներ տպագրում են յուրաքանչյուր թերթիկը, քանի որ այն արտադրական գծի վրա կտրում է: Շատ թերթիկները բնական են, մի քանի սխալներ են (լոգեր, թռիչքներ, ծախսերը, ներսումներ): Մենք ունենք 10,000 թերթիկներ, բայց միայն 200 նշված են: detecting manufacturing defects on metal surfaces. Բարձրացնել Semi-Supervised Learning Pipeline- ը Պահպանելու առաջ, որ ցանկացած կոդը, Let's map out the entire pipeline. Կարդալ, որ թռչունը առաջինը կարող է անել յուրաքանչյուր քայլը զգում է նպատակային, այլեւ անմիջապես. Ստացեք մի քիչ հետազոտել այս դիզայնը - յուրաքանչյուր փաթեթը մի քայլ է, մենք պետք է իրականացնել: THE COMPLETE SEMI-SUPERVISED PIPELINE: [10,000 raw images] ──▶ [Exploration & Cleaning] │ ▼ [Preprocessing: resize, normalize, histogram equalization] │ ▼ [Feature Extraction: pretrained ResNet50 → 2048-dim embedding per image] │ ┌─────────┴──────────┐ │ │ ▼ ▼ [200 LABELED images] [9,800 UNLABELED images] │ │ │ ▼ │ [Clustering: K-Means, DBSCAN │ on embeddings → pseudo-labels] │ │ │ ▼ │ [WEAKLY labeled dataset] │ (cluster assignments) │ │ ▼ ▼ ┌────────────────────────────────────┐ │ SEMI-SUPERVISED TRAINING: │ │ 1. Pre-train CNN on weakly labeled │ │ 2. Fine-tune CNN on strongly labeled│ │ 3. Compare vs supervised-only │ └────────────────────────────────────┘ │ ▼ [Evaluation: F1, AUC-ROC, confusion matrix, comparison] Հիմնական տեղեկություն: Մենք պետք է փոխել անլոգված տեսանյութեր Տեսեք այն, թե ինչպես պետք է ուսանողը ստանալ ճշգրիտ ուսուցման ուղեցույց, նախքան ճշգրիտ փորձը - դա ոչ թե լավ չէ, բայց դա ավելի լավ է, քան ոչինչ: Հյուրատետր Մենք նաեւ պետք է բացահայտել, թե ինչ խոսքեր ենք օգտագործում այս հոդվածում, քանի որ սխալները միասին միասին միասին միասին միասին միասին: Բարձրորեն նշված (լուսանկարներ `լուսանկարներ`): Image with labels verified by a human expert. Gold standard. «Այս ամենը» (տեսանյութ) «Այս ամենը» (տեսանյութ) «Այս ամենը», «Այս ամենը» (տեսանյութ) «Այս ամենը» (տեսանյութ) Նկարագրված: Նկարագրվածներ ոչ մի նամակով: Այսն է իրենց մակարդակը, երբ մենք նամակում ենք նրանց: Embeding: մի խոշոր թվային վերլուծություն տեսակը, որը արտադրվում է նախընտրված սերտիֆիկային ցանցի. Մեր հիմնական գործիք է ստեղծել տեսանյութեր համեմատելի. Ավելի ավելին կարդալ: Ավելի ավելին կարդալ: Հիմնական դասընթաց - scikit-learn Google- ի հետազոտություններ է semi-supervised learning- ի մասին Հիմնական դասընթաց - scikit-learn Google- ի հետազոտություններ է semi-supervised learning- ի մասին 1. Data Exploration: իմանալ, որ տվյալները դուք աշխատում եք Ինչու դուք պետք է տեսնել ձեր տվյալները, նախքան ինչ-որ բան անել Image datasets- ում միավոր սխալային ձեւեր են, որոնք դուք չեք գտնում tabular տվյալների մեջ: սխալված ֆայլեր, որոնք սխալում են ձեր դասընթացային փաթեթը 3 AM- ում, անսահմանափակ resolutions- ում, որոնք անսահմանափակորեն սխալում են ձեր մանրամասները, սխալ color channels- ում (լուսանկարներ RGB- ում) եւ անսահմանափակ դասընթացային անսահմանափակությունը, որտեղ 95% մանրամասներ են "normals" - ում: Եթե դուք անսահմանափակեք exploration- ը, ձեր մոդելը անսահմանափակորեն կգիտվի սխալը - եւ դուք չեք գիտեք, թե ինչու այն անսահմանափակ է: Ով է Golden Rule: Տեսենք, թե ինչ ենք աշխատում. never trust data you haven't inspected. 1.1 — Բեռնել եւ բեռնել նկարները Մեր տվյալների բաղադրիչը տեղադրվում է երկու հիմնական փաթեթներով: մեկի հետ տպագրված մանրամասները (լուսանկարներ) (լուսանկարներ) եւ մեկի հետ տպագրված մանրամասներ (լուսանկարներ) (լուսանկարներ) (լուսանկարներ) Ֆիլմեր .png import os import numpy as np import pandas as pd import matplotlib.pyplot as plt from PIL import Image from pathlib import Path data_dir = Path("data/metal_surfaces") labeled_dir = data_dir / "labeled" unlabeled_dir = data_dir / "unlabeled" Մենք օգտագործում ենք Արդյոք, թե ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան, ինչ-որ բան pathlib.Path labeled_files = list(labeled_dir.glob("**/*.png")) unlabeled_files = list(unlabeled_dir.glob("**/*.png")) print(f"Labeled images: {len(labeled_files)}") print(f"Unlabeled images: {len(unlabeled_files)}") print(f"Total: {len(labeled_files) + len(unlabeled_files)}") label_ratio = len(labeled_files) / (len(labeled_files) + len(unlabeled_files)) print(f"Label ratio: {label_ratio:.1%}") Այս մետաղադրամների մակարդակը սովորաբար մոտ 2%: Մեր տվյալների միայն 2%-ն ունի մասնագետների ստուգված մետաղադրամներ: Ավելի 98%-ն մի գույքի մետաղադրամն է, որը մենք չենք կարող վերցնել, եւ դա պարզապես այն է, ինչը հաստորեն վերահսկված ուսուցման օգտագործում է: 1.2 — Problems scanning: resolution, color, corruption — սխալների համար scanning: resolution, color, corruption Հաջորդը, մենք պետք է ստուգել յուրաքանչյուր տեսակը մասնավորապես: Մեկ սխալված ֆայլը կարող է սխալել ամբողջ դասընթացը: Անհատական տարբերակները կախված են տեսանյութերը, եթե դուք չեք ճշգրիտ: Եւ սխալ գույնի մոդելները (հայմանում է, որ ձեր մոդելը RGB- ն է) կօգնեն արտադրել սխալ հատկանիշներ: Մենք գրում ենք մի փոքր գործառույթ, որը փորձում է բացել յուրաքանչյուր նկարը եւ գրել իր բաղադրիչները: def get_image_info(filepath): """ Try to open an image and record its properties. If the file is corrupted, Pillow will throw an exception. """ try: img = Image.open(filepath) return { "path": str(filepath), "width": img.size[0], "height": img.size[1], "mode": img.mode, # 'RGB', 'L' (grayscale), 'RGBA' "filesize_kb": os.path.getsize(filepath) / 1024, "corrupted": False, } except Exception: return { "path": str(filepath), "width": None, "height": None, "mode": None, "filesize_kb": None, "corrupted": True, } Դա Բարձրապես կարեւոր է տարածք. 3 գունավոր սենյակներ (լուսանկարներ, Red, Green, Blue) Արդյոք, դա նշանակում է, որ Gray Scale (1 Channel) RGB- ը նշանակում է alpha (լուսանկարներ) Channel- ի հետ: Մեր նախապատրաստված մոդելը RGB- ի համար է, այնպես որ մենք պետք է փոխել ամեն ինչ հետո: img.mode 'RGB' 'L' 'RGBA' Ապրիշի 10 000 տեսանյութեր: all_files = labeled_files + unlabeled_files image_info = [get_image_info(f) for f in all_files] info_df = pd.DataFrame(image_info) Տեսեք այդ արդյունքները: print(f"Total images scanned: {len(info_df)}") print(f"Corrupted images: {info_df['corrupted'].sum()}") print(f"\nResolution distribution:") print(info_df[~info_df["corrupted"]][["width", "height"]].describe().round(0)) print(f"\nColor modes: {info_df['mode'].value_counts().to_dict()}") print(f"File size (KB): min={info_df['filesize_kb'].min():.0f}, " f"max={info_df['filesize_kb'].max():.0f}, " f"mean={info_df['filesize_kb'].mean():.0f}") Ի՞նչ պետք է գտնել արտադրանքի մեջ: Հեղինակային նկարներ > 0: Հեղինակային ֆայլը կարող է սխալել ձեր դասընթացը. Արդյոք, եթե min ≠ max է լայնության կամ բարձրության համար, տեսանյութերի չափերը տարբեր են: Մենք վերլուծենք նրանց բոլորը 224 × 224 ժամանակ preprocessing. Multiple color modes: Եթե դուք տեսնում եք «RGB» եւ «L», դուք ունեք մի mix of color and greyscale. We will convert everything to RGB. Բարձր ֆայլերի չափերը: 1KB ֆայլը կարող է վախենալ կամ վախենալ: 50MB ֆայլը կարող է ոչ մի փաթեթավորվել, որքան արժեք է հետազոտել: Տեղադրեք սեղմված ֆայլերը: corrupted_paths = set(info_df[info_df["corrupted"]]["path"].tolist()) if corrupted_paths: print(f"Removing {len(corrupted_paths)} corrupted images") labeled_files = [f for f in labeled_files if str(f) not in corrupted_paths] unlabeled_files = [f for f in unlabeled_files if str(f) not in corrupted_paths] 1.3 — Class Distribution: Արդյոք մեր labeled սերտիֆիկը հարմար է: Արդյունաբերական եւ բժշկական սարքավորումներում, սխալները հեշտ են: Ձեր նշված սերտիֆիկը կարող է լինել 90% -ը «դիմնական» եւ 10% -ը «դիմնական»: Սա շատ կարեւոր է: մի լուսավոր մոդել, որը միշտ «դիմնական» նախընտրում է, 90% -ի ճշգրտությունը ստանում է, իսկ այն ամբողջականապես անսահմանափակ է: Մենք պետք է գիտենք, որ սխալը նախընտրում է, որպեսզի մենք կարող ենք վերահսկել այն հետո: class_counts = {} for class_dir in labeled_dir.iterdir(): if class_dir.is_dir(): count = len(list(class_dir.glob("*.png"))) class_counts[class_dir.name] = count print("Class distribution (labeled set):") for cls, count in class_counts.items(): pct = count / sum(class_counts.values()) * 100 print(f" {cls}: {count} images ({pct:.1f}%)") Եթե սխալը դժվար է, մենք կարող ենք վերահսկել այն հետո, օգտագործելով մի տեխնոլոգիան, որը կոչվում է Ապրիշի բաղադրիչը ասում է, որ «պրիշի բաղադրիչը 4 անգամ վտանգավոր է, քան սխալ բաղադրիչը». pos_weight Մենք նաեւ տեսնում ենք այն: fig, ax = plt.subplots(figsize=(6, 4)) ax.bar(class_counts.keys(), class_counts.values(), color=["#2ecc71", "#e74c3c"]) ax.set_title("Class Distribution (Labeled Images)") ax.set_ylabel("Number of images") plt.tight_layout() plt.savefig("outputs/class_distribution.png", dpi=150) plt.show() 1.4 — Visualizing sample images: միշտ տեսնել նախքան ձեր մոդել Դա կարող է լինել ամենամեծ քայլ ամբողջ խողովակով: Տեսեք ձեր տվյալները: Դուք կարող եք տեսնել, որ տեսանյութերը բացառապես սխալ է նամակված են, scanning բաղադրիչներ (լուսանկարներ, rotations), որակի խնդիրներ (լոգ, overerexposure), կամ, որ սխալները տեսականորեն սխալ են եւ ձեր աշխատանքը ավելի դժվար է, քան դուք կարծում եք. fig, axes = plt.subplots(2, 5, figsize=(15, 6)) fig.suptitle("Sample Images — Top: Normal | Bottom: Defect", fontsize=14) for i, class_name in enumerate(["normal", "defect"]): class_files = list((labeled_dir / class_name).glob("*.png"))[:5] for j, filepath in enumerate(class_files): img = Image.open(filepath) axes[i, j].imshow(img, cmap="gray" if img.mode == "L" else None) axes[i, j].set_title(class_name, fontsize=10) axes[i, j].axis("off") plt.tight_layout() plt.savefig("outputs/sample_images.png", dpi=150) plt.show() Տեղադրեք այս տեսանյութը, կարող եք Տեսեք սխալները ձեր սեփական աչքերով: Եթե դուք չեք կարող, մոդելը կախված է նաեւ: Եթե սխալները բացառիկ են (լայն սխալը, մեծ սխալը), դա խուսափելի է - մոդելը պետք է կարող լինել սովորել տարբերությունը: Եթե նրանք սխալ են (լայն սխալը, սխալը), դուք պետք է պետք է հատկապես լավ preprocessing եւ feature extract. Դուք Ավելի ավելին կարդալ: Ավելի ավելին կարդալ: Pillow գրասենյակ — Python imaging գրասենյակ, որը մենք օգտագործում ենք բեռնել տեսանյութեր NEU Surface Defect Database — իրական աշխարհում պողպատային մակերեսի սխալների տվյալների բազան, որը կարող եք գործել Pillow գրասենյակներ New Surface Defect տվյալների բազան 2-րդ մաս — Preprocessing: խոսել մոդելի լեզուը Ինչու մենք չենք կարող պարզապես սննդել սեղմված տեսանյութեր մի սննդային ցանցի համար ResNet50- ի նման նախապատրաստված CNN- ը դասընթացվել է շատ հատուկ տեսակի մուտք: 224×224 մետաղադրամներ, RGB- ի գույնում, normalized- ի համար, որը որոշված է ImageNet- ի տվյալների միասնական եւ ստանդարտ փոխանակման արժեքների հետ: Եթե դուք մատակարարեք այն տարբեր չափերի մետաղադրամներ, կամ մետաղադրամների արժեքների համար, այլեւ normalized- ի համար, այն մետաղադրամները, որոնք այն արտադրում է, չեն նշանակում: Տեսեք այն որպես լեզու: ResNet50- ը «փսում է ImageNet- ը»: Եթե մենք ցանկանում ենք, որ այն հասկանում է մեր մետաղական մակերեսի նկարները, մենք պետք է «փսում ենք» նրանց ImageNet- ի ձեւաչափով: RGB- ի փոխանակման համար (3 Channel Converter) Բարձրացնել kontrast via histogram equalization Հիմնական չափը 224×224 Տեղադրեք Pixel- ի արժեքները ImageNet- ի statistics- ի հետ 2.1 - Ի՞նչ է histogram equalization, եւ ինչու դա կարեւոր է այստեղ: Արդյունաբերական մանրամասները հաճախ ունի շատ ցածր համեմատություն: Արդյունաբերական մանրամասների տարբերությունը սովորական մանրամասների եւ ծախսված մանրամասների միջեւ կարող է լինել միայն մի քանի մանրամասների հզորության մակարդակներ, որոնք հեշտ է տեսնել մանրամասների համար: Տեղադրում է piksel- ի հզորությունը այնպես, որ ամբողջ մակարդակը (0 մինչեւ 255) օգտագործվում է միասին: Ապրանքը: մանրամասն առանձնահատկությունները «պահպանվում են» տեսական եւ թվային: Histogram equalization Մենք օգտագործում ենք ավելի առաջատար տարբերակը, որը կոչվում է (Անհարկե սահմանափակ Adaptive Histogram Equalization) Ահարկե, ոչ թե Global Equalization- ից, որը օգտագործում է նույն փոխանցման ամբողջ տեսանյութը, CLAHE- ը սեղմում է տեսանյութը փոքր թերթիկներին (8×8 սեղմում) եւ սեղմում է յուրաքանչյուր թերթիկը անմիջապես: Այսպիսով տեղական մանրամասները ավելի լավ պաշտպանված են: CLAHE Հետեւեք, թե ինչպե՞ս կարող եք վերահսկել գեղեցկությունը. Global equalization- ը նման է, թե ինչպես կարող եք օգտագործել միայն մեկ գեղեցկության թռիչք ամբողջ գեղեցկության համար: Դուք կարող եք գեղեցկել գեղեցկ գեղեցկության գեղեցկությունը, բայց մաքրել գեղեցկության կենտրոնը: CLAHE- ը նման է, թե ինչպես կարող եք վերահսկել գեղեցկությունը յուրաքանչյուր տարածքում, այնպես որ գեղեցկության ամեն մասը կանգնած է: 2.2.2 Պաշտոնական PyTorch տվյալների բաղադրիչը PyTorch- ը տեղադրում է տվյալների բեռնելը երկու դասերի վրա: (Ես գիտեմ, թե ինչպե՞ս պետք է բեռնել մի բան) եւ (Ես գիտեմ, թե ինչպե՞ս կարող եմ փոխել, թե ինչպե՞ս կարող եմ փոխել) PyTorch- ը ապահովում է Մեր տվյալների սերտիֆիկը ունի նաեւ մանրամասներ եւ մանրամասներ, այնպես որ, մենք պետք է մանրամասներ. Dataset DataLoader ImageFolder Հաջորդը, մենք պետք է փնտրենք այն, ինչը պետք է անել: Առաջին, սխալը: import torch import torchvision.transforms as T from torch.utils.data import Dataset, DataLoader import cv2 class MetalSurfaceDataset(Dataset): """ Custom Dataset that handles both labeled and unlabeled images. Returns -1 as the label for unlabeled images. """ def __init__(self, image_paths, labels=None, transform=None): self.image_paths = image_paths self.labels = labels # None for unlabeled images self.transform = transform def __len__(self): return len(self.image_paths) PyTorch-ը ասում է, թե ինչպիսիք են մեր տեսանյութերը: Տեղադրում է տեսանյութերի ճանապարհները եւ (սահմանափակորեն) իրենց նամակները: __len__ __init__ Այժմ հիմնական մեթոդը, , որը բեռնում է եւ preprocesses մի միակ տեսակը. Մենք կտրում է այն երեք մակարդակներում: __getitem__ Stage 1 — Load the image and force RGB: def __getitem__(self, idx): # Load image and convert to RGB # .convert("RGB") handles grayscale → RGB conversion automatically # (it duplicates the single channel into R, G, and B) img = Image.open(self.image_paths[idx]).convert("RGB") Ինչու Արդյոք, երբ ResNet50-ը պահանջում է 3 սենյակում: Եթե մեր նկարը սառեցկված է (1 սենյակում), դա R, G, եւ B- ում սառեցկված է: Եթե այն bereits RGB- ը, դա ոչինչ չի գործում: Եթե այն RGBA (4 սենյակում) է, ապա այն կտրում է ալբա սենյակում: .convert("RGB") Stage 2 — Apply CLAHE histogram equalization: # Convert PIL Image → numpy array for OpenCV processing img_np = np.array(img) # Convert RGB → LAB color space # L = Lightness (brightness), A and B = color channels # We only equalize L (brightness) to avoid distorting colors img_lab = cv2.cvtColor(img_np, cv2.COLOR_RGB2LAB) # Create CLAHE object and apply to L channel # clipLimit=2.0 prevents over-amplification of noise # tileGridSize=(8,8) means 8x8 tiles for local equalization clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) img_lab[:, :, 0] = clahe.apply(img_lab[:, :, 0]) # Convert back LAB → RGB → PIL Image img_np = cv2.cvtColor(img_lab, cv2.COLOR_LAB2RGB) img = Image.fromarray(img_np) Ինչու է LAB եւ ոչ միայն օգտագործել CLAHE- ը ուղղակիորեն RGB- ի վրա: Քանի որ, եթե դուք R, G, եւ B- ի Channel- ում անմիջապես համեմատեք, դուք կախված եք գույնները, ինչպիսիք են Blue- ը գլուխի համար: Այսպիսով, աշխատելով LAB- ի տարածքում, մենք պարզապես կախված ենք լայնության (L) Channel- ում եւ կախված չենք գույնները (A, B): Այսպիսիք է ստանդարտ գործառույթ Image Processing- ում: Stage 3 — Apply transforms and return: # Apply resize + normalize transforms if self.transform: img = self.transform(img) # Return the label (or -1 if this image has no label) label = self.labels[idx] if self.labels is not None else -1 return img, label 2.3 — The transform pipeline: ինչ է կատարում յուրաքանչյուր քայլը Այժմ մենք սահմանում ենք փոխանակման սերտիֆիկները. յուրաքանչյուրը ունի հատուկ նպատակը: preprocessing = T.Compose([ T.Resize((224, 224)), # (1) Resize to model's expected input size T.ToTensor(), # (2) PIL Image → PyTorch Tensor, scale [0,1] T.Normalize( mean=[0.485, 0.456, 0.406], # (3) Normalize with ImageNet statistics std=[0.229, 0.224, 0.225], ), ]) Տեսեք յուրաքանչյուր քայլը: ResNet50- ի դիզայնը պահանջում է ճիշտ այս չափը: Եթե դուք փնտրում եք 300 × 400 տեսակը, tensor ձեւները չեն համատեղելի, եւ PyTorch- ը կախվածվի: Կրթելը կարող է մի քիչ փոխարինել դիզայնը, բայց texture-based գործառույթների համար (հարկե, սխալը վերահսկողության համար) դա ոչ մի խնդիր է: (1) Resize to 224×224. Դա կատարում է երկու բաներ: փոխանցում է pixel format- ը HWC- ից (High × Width × Channels) է CHW- ում (Channels × Height × Width), որը այն է, ինչ է PyTorch- ը սպասում, եւ ծախսում է pixel- ի արժեքները [0, 255] ամբողջականից [0.0, 1.0] թռիչքներում: (2) ToTensor. Այս հագուստը - եւ — են մանրամասական եւ ստանդարտ փոխանակման pixel արժեքները ամբողջ ImageNet տվյալների միասին, փոխանակված Channel- ի համար Channel- ի համար (R, G, B). ResNet50- ը դասընթացվել է այդ ճշգրիտ ստանդարտացման արժեքների հետ, այնպես որ իր ներքին քանակները «պայման են» ինտեգրված ինտեգրված մանրամասները, որոնք կենտրոնացած են մոտ 0- ի հետ մանրամասների փոխանակման համար: Օգտագործելով տարբեր մանրամասները, ինչպիսիք են մանրամասների համար մանրամասների համար, բայց մանրամասների համար: (3) Normalize with ImageNet mean and std. [0.485, 0.456, 0.406] [0.229, 0.224, 0.225] 2.4 — DataSets եւ DataLoaders ստեղծում Այժմ մենք բոլորը համատեղում ենք: Հիմնական principle: Նրանք ներառում են, որ մեր արժեքը ծախսենում է. labeled and unlabeled data must be kept strictly separate at all times. Առաջին, հավաքել նշված տեսանյութերի ճանապարհներ եւ իրենց դասընթացների նամակներ: labeled_paths = [] labeled_labels = [] for class_idx, class_name in enumerate(["normal", "defect"]): class_dir = labeled_dir / class_name for fp in class_dir.glob("*.png"): labeled_paths.append(str(fp)) labeled_labels.append(class_idx) # 0 = normal, 1 = defect Հաջորդը, համացրեք անլոգված տեսանյութերի ճանապարհները (լոգներ չեն պահանջվում): unlabeled_paths = [str(fp) for fp in unlabeled_files] PyTorch Dataset- ի բաղադրիչները ստեղծելու համար: labeled_dataset = MetalSurfaceDataset(labeled_paths, labeled_labels, preprocessing) unlabeled_dataset = MetalSurfaceDataset(unlabeled_paths, labels=None, transform=preprocessing) print(f"Labeled dataset: {len(labeled_dataset)} images") print(f"Unlabeled dataset: {len(unlabeled_dataset)} images") DataLoader- ը միասին բաղադրում է տեսանյութերը (batch_size=32- ը նշանակում է 32 տեսանյութեր մեկ անգամ) եւ ցանկալիորեն shuffles նրանց հետ: labeled_loader = DataLoader(labeled_dataset, batch_size=32, shuffle=False) unlabeled_loader = DataLoader(unlabeled_dataset, batch_size=32, shuffle=False) Ինչու Քանի որ մենք պետք է բեռնել առանձնահատկություններ, եւ մենք պետք է բեռնել այնպես էլ, որ մեր ֆայլերի ցուցանիշները. Մենք կփակենք հետո, դասընթացների ընթացքում. shuffle=False Ավելի ավելին կարդալ: Ավելի ավելին կարդալ: Տղամարդկանց բաղադրիչները — Full List CLAHE explained (OpenCV դասընթաց) PyTorch Dataset & DataLoader- ը Տղամարդկանց բաղադրիչները — Full List CLAHE explained (OpenCV դասընթաց) PyTorch Dataset & DataLoader- ը Ապրիշ 3 — Նկարագրության վերլուծություն: Image Conversion to Significant Numbers 3.1 — Ինչու պլաստիկ պլաստիկները վտանգավոր արտադրություն են 224×224 RGB տեսակը ունի 150,528 մանրամասներ (224 × 224 × 3 մանրամասներ). Նրանք ամենամեծը սխալներ են - լույսի քիչ տարբերակներ, մանրամասների բաղադրիչները, փաթեթավորման բաղադրիչներ: Լավագույնն է, որ երկու տեսանյութերը ճշգրտապես նույն գծի վրա, որոնք ստանում են մի քանի տարբեր տեսակի կամ լույսի վրա, ունի ամբողջապես տարբեր մանրամասների արժեքներ: Եթե մենք փորձում ենք խոշոր մանրամասներ կասկածել կամ կասկածել, այն տեսանյութերը, որոնք մեր համար տեսնում են նույնպես, կասկածեն մի քանի տարբեր տեսանյութեր: Մենք պետք է ունենք մի արտադրություն, որը ներառում է «Այս տեսնում է, որ մի կտրում է», «Այս մի գլուխ է», «Այս գլուխ է», «Այս կտրում է», «Այս կտրում է», «Այս կտրում է»: Դա։ meaning embeddings 3.2 — Ինչ է նախապատրաստված մոդել եւ թե ինչու մենք չենք ուսուցել գիշերից Training a deep neural network from scratch requires a LOT of data — typically hundreds of thousands of images. We have 200 labeled images. If we tried to train ResNet50's 25 million parameters on 200 images, the model would memorize every single training image perfectly but fail completely on new images. This is called . overfitting Հիմա, մենք օգտագործում ենք մի մոդել, որը արդեն ուսուցվել է ImageNet- ում - 14 միլիոն մոդելների տվյալների բաղադրիչը 1,000 տեսակի (կուններ, կտերներ, մեքենաներ, բաղադրիչներ, եւ այլն): Այս մոդելը արդեն սովորեցրել է ճանաչել հիմնական տեսական առանձնահատկությունները: գծեր, բաղադրիչներ, ձեւեր, գույնի բաղադրիչներ, geometric մոդելներ: Այս ցածր մակարդակի առանձնահատկություններ են: — Նրանք օգտագործվում են պողպատային մակերեսների համար, ինչպես նաեւ կտորների համար: universal Տեսեք այն, ինչպիսիք է, որ աշխատում եք փորձնական ֆոտրատորը ձեր գործարանը վերահսկելու համար: Նրանք երբեք չի տեսնում պողպատ թերթիկներ, բայց նրանք bereits գիտեն, թե ինչպես : նրանք կարող են տեսնել անսահմանափակ բաղադրիչներ, անսահմանափակ փոխանցումներ է մակարդակի որակի, մոդելներ, որոնք փրկում են ստանդարտը: Նրանք պետք է իմանալ, թե ինչ է բաղադրվում որպես "խաղադրիչ" ձեր հատուկ գործարանում. Տես 3.3 — Բեռնել ResNet50 Տեղադրել ենք նախնական մոդելը: import torchvision.models as models resnet = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1) Այս միավոր գիծը բեռնել է (կամ առաջին անգամ) ResNet50 մոդելը, որ քաշները սովորվել են ImageNet- ում: Մոդելը գիտի, թե ինչպես է դասընթացել 1,000 դասընթացների օրինակներ: 3.4 — Կառուցել պարամետրերը Մենք չենք ցանկանում փոխել ցանկացած սովորված առանձնահատկությունները: Մենք օգտագործում ենք ResNet- ը որպես միայն կարդալ գործիք: for param in resnet.parameters(): param.requires_grad = False PyTorch- ը ասում է, որ «լուսանկարներ չեք բեռնել այս մետրերի համար»: Սա ունի երկու առավելությունները: այն խուսափում է նախապատրաստված քանակների անջատական փոխարինման, եւ դա արագ է բեռնել (լուսանկարներ չեք բեռնել = ավելի քիչ բեռնել եւ ավելի քիչ մանրամասներ): requires_grad = False 3.5 — Կառուցում է դասընթացային կետը ResNet50-ի դիզայնը տեսնում է այսպես: Input image (224×224×3) ↓ [Convolutional layers] — learn visual features ↓ [Average Pooling] — compress spatial dimensions → 2048-dim vector ↓ [Fully Connected layer] — classify into 1000 ImageNet categories ↓ Output (1000 probabilities) Մենք ցանկանում ենք 2048-րդ մետաղական vektor- ը, որը արտադրվում է Average Pooling- ի մակերեսից — այդ է մեր ներառումը: Մենք չենք ցանկանում վերջին Fully Connected մակերեսը, քանի որ այն հատուկ է ImageNet- ի 1000 մակերեսի (կուն, կինը, օդանավիչը ...) եւ չի օգտագործվում մեր գործի համար: feature_extractor = torch.nn.Sequential(*list(resnet.children())[:-1]) Ի՞նչ է անել այս գիծը: Տեղադրում է ResNet- ի բոլոր մակարդակները, ինչպիսիք են ցուցակ. Հիմնական հոդվածը (լուսանկարներ) Հիմնական հոդվածը (լուսանկարներ) Նրանք վերադառնալ են մոդելում. resnet.children() [:-1] Sequential(*) feature_extractor.eval() Դիմում է, թե ինչ է կատարվում, թե ինչ է կատարվում, եւ թե ինչ է կատարվում: Արդյոք, այնպես էլ, այնպես էլ, այնպես էլ, այնպես էլ, այնպես էլ, այնպես էլ, այնպես էլ, այնպես էլ, այնպես էլ, այնպես էլ: eval() deterministic device = torch.device("cuda" if torch.cuda.is_available() else "cpu") feature_extractor = feature_extractor.to(device) print(f"Feature extractor ready on {device}") Օգտագործելով GPU- ը (հարկե, եթե հասանելի է) գործառույթների արտահանման արագությունը 10x ավելի արագ է: 3.6 — Extraction գործառույթը Այժմ կպասենք մի գործառույթը, որը սննդում է տեսանյութերի տոմսերի միջոցով գործառույթը արտադրողը եւ հավաքում է ներարկմանները: Մենք կպասենք այն փաթեթից փաթեթից: Արդյունաբերական կառուցվածքը: def extract_embeddings(dataloader, model, device): """ Feed all images through the model and collect embeddings. Returns: embeddings: numpy array, shape (n_images, 2048) labels: numpy array, shape (n_images,) — -1 if unlabeled """ all_embeddings = [] all_labels = [] Մենք բաղադրում ենք արդյունքները ցուցանիշներում, քանի որ մենք բաղադրում ենք բաղադրիչները (32 մեկ անգամ), ոչ բոլորը միասին (լուսանկարներ) Հիմնական loop: with torch.no_grad(): for batch_images, batch_labels in dataloader: batch_images = batch_images.to(device) features = model(batch_images) Արդյոք, մենք պարզապես չգիտենք, թե ինչ է անում այն, թե ինչ է անում այն, թե ինչ է անում այն, թե ինչ է անում այն, թե ինչ է անում այն, թե ինչ է անում այն, թե ինչ է անում այն, թե ինչ է անում այն, թե ինչ է անում այն. Տեսակները փոխվում են GPU- ում, եթե մենք ունենք մեկը: torch.no_grad() batch_images.to(device) արտադրանքը Կարդալ Form — վերջին երկու մակարդակները տարածքի վերադառնալներ են միջին համատեղից: Մենք պետք է սեղմենք նրանց: model(batch_images) (batch_size, 2048, 1, 1) features = features.squeeze(-1).squeeze(-1) # Now shape is (batch_size, 2048) — that's our embedding Իհարկե, մենք վերցնում ենք արդյունքները CPU- ում (numpy- ը չի կարող աշխատել GPU tensors- ի հետ): all_embeddings.append(features.cpu().numpy()) all_labels.append(batch_labels.numpy()) return np.concatenate(all_embeddings), np.concatenate(all_labels) Բոլոր բաղադրիչները միասին միավոր են միասին. np.concatenate 3.7 — Ուղեցնում է արտադրանքի print("Extracting embeddings for labeled images...") labeled_embeddings, labeled_labels_arr = extract_embeddings( labeled_loader, feature_extractor, device ) print(f" Shape: {labeled_embeddings.shape}") # Expected: (200, 2048) 200 տեսանյութեր, ամենը 2048-րդ մետաղական vektor- ի հետ: Դա 73x-ն է սեղմելու, քան սեղմված մետաղական pixels (150,528 → 2,048) - եւ սեղմված տեսանյութը: ավելի կարեւոր է. Լավ print("Extracting embeddings for unlabeled images...") unlabeled_embeddings, _ = extract_embeddings( unlabeled_loader, feature_extractor, device ) print(f" Shape: {unlabeled_embeddings.shape}") # Expected: (9800, 2048) Մենք վախենում ենք նամակները (հարկե, նրանք բոլորը -1 են) Հիմնական տարբերակ _ 3.8 - Շատացեք ներկառումներ (լուծեք ոչինչ ամեն անգամ!) Նկարագրության արտադրանքը ամենամեծ գործառույթն է — հնարավորապես 30+ րոպե GPU- ում 10,000 սմարթների համար: Շատեք արդյունքները, որպեսզի դուք երբեք չեք պետք թարմացնել այն: np.save("data/labeled_embeddings.npy", labeled_embeddings) np.save("data/labeled_labels.npy", labeled_labels_arr) np.save("data/unlabeled_embeddings.npy", unlabeled_embeddings) print("Embeddings saved to disk") Մինչեւ դուք կարող եք անմիջապես վերահսկել . np.load("data/labeled_embeddings.npy") 3.9 — Sanity check: Արդյոք բաղադրիչները ճշգրիտ են: Պահպանեք սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը, սխալը print(f"Embedding statistics:") print(f" Mean: {labeled_embeddings.mean():.4f}") print(f" Std: {labeled_embeddings.std():.4f}") print(f" Min: {labeled_embeddings.min():.4f}") print(f" Max: {labeled_embeddings.max():.4f}") print(f" NaN: {np.isnan(labeled_embeddings).any()}") print(f" Inf: {np.isinf(labeled_embeddings).any()}") Ի՞նչ պետք է ստանալ: քանակը 0.3-0.5, std մոտ 0.5-1.0, ոչ NaN, ոչ Inf. Եթե դուք տեսնում եք NaN արժեքները, կախված տեսակը կարող է վառել մաքրման քայլում: Եթե քանակը ճիշտ է 0, ինչ-որ բան սխալ է normalization- ի հետ: Բարձրացվել է: Բարձրացվել է: Transfer learning explained (PyTorch դասընթաց) ResNet- ի գրասենյակ (He et al., 2015) - Original Architecture- ը, որը ներկայացրել է Skip Connections- ը Գործիքային արտադրություն vs fin-tuning — Stanford CS231n դասընթացը գրառումներ Transfer learning explained (PyTorch դասընթաց) Հիմնական հոդվածը (He et al., 2015) Բարձրություն vs Fine-Tuning Ապրիշ 4 — Անհարկված բաղադրիչների բաղադրիչները: Սկսում են սեւում 4.1 — Ի՞նչ է clustering- ը եւ ինչու պետք է այն Մենք այժմ ունենք 10,000 բաղադրիչներ — կպտակտ թվային վերլուծություններ յուրաքանչյուր տեսանյութի համար: Նրանցից 200- ում են նամակներ, այլ 9800- ից ոչ: Մեր նպատակն է գտնել բաղադրիչները Տեսակները, որոնք հավատում են, որ «դիմնական» եւ «դիմնական» են: groupings Հիմնական հավատում է, որ եթե մեր բաղադրիչները լավ են ( եւ ResNet50 բաղադրիչները սովորաբար են), նույն տեսակը կունենա Հիմնական բաղադրիչները կասկածեն միասին, սխալ բաղադրիչները կասկածեն միասին, նույնիսկ առանց բաղադրիչների, բաղադրիչները կասկածեն միասին: Հաջորդ Բայց առաջին, մի գործնական խնդիրը: 2048 չափերը չի կարող տեսնել եւ որոշ ալբոմսերը անջատում են: Մենք պետք է առաջին անգամ կտրել չափերը: 4.2 — Standardize ներբեռնվածները Եթե մեկ չափը գնում է 0- ից 1000- ից եւ մեկ չափը գնում է 0- ից 0.01- ից, առաջինը ամբողջապես կունենա հեռավորության վրա, ինչպես նաեւ այնպես, որ երկրորդ չափը չկան: Standardization (mean=0, std=1 per dimension) տեղադրում է բոլոր առանձնահատկությունները միասին: from sklearn.preprocessing import StandardScaler # Combine labeled + unlabeled for joint standardization all_embeddings = np.concatenate([labeled_embeddings, unlabeled_embeddings], axis=0) scaler = StandardScaler() all_embeddings_scaled = scaler.fit_transform(all_embeddings) Ինչպե՞ս ստանդարտել սեղմված եւ չեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված սեղմված ս # Split back — we'll need them separate later labeled_scaled = all_embeddings_scaled[:len(labeled_embeddings)] unlabeled_scaled = all_embeddings_scaled[len(labeled_embeddings):] print(f"After standardization: mean={all_embeddings_scaled.mean():.4f}, " f"std={all_embeddings_scaled.std():.4f}") 4.3 — Կառուցեք չափերը PCA- ի հետ PCA-ն (Principal Component Analysis) գտնում է տվյալների ամենամեծ տարբերության ուղղությունները եւ նախագծում է առավելագույն ուղղությունները: Մենք գնում ենք 2048- ից 50 մակերեսին: from sklearn.decomposition import PCA pca = PCA(n_components=50, random_state=42) all_pca = pca.fit_transform(all_embeddings_scaled) print(f"PCA: 2048 → 50 dimensions") print(f"Variance retained: {pca.explained_variance_ratio_.sum():.1%}") ~95% variance behold means we have discarded only 5% of the information but reduced dimensionality by 40x. Այսպիսով t-SNE եւ DBSCAN շատ ավելի արագ եւ ավելի հարմար է: Տեսեք նաեւ, թե ինչպիսիք են յուրաքանչյուր բաղադրիչը: plt.figure(figsize=(10, 4)) plt.plot(np.cumsum(pca.explained_variance_ratio_), marker="o", markersize=3) plt.xlabel("Number of PCA components") plt.ylabel("Cumulative explained variance") plt.title("PCA: How many components do we need?") plt.axhline(y=0.95, color="r", linestyle="--", label="95% threshold") plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.savefig("outputs/pca_variance.png", dpi=150) plt.show() Այս «լոգի բաղադրիչը» ցույց է տալիս, թե որտեղ ավելացնել ավելի բաղադրիչներ կանգնած է մեծ բաղադրիչներ: Եթե բաղադրիչը 50 բաղադրիչների առաջ կանգնած է, դուք կարող եք օգտագործել ավելի քիչ: 4.4 — Visualize հետ t-SNE t-SNE- ը ոչ-linear dimensionality reduction տեխնոլոգիան է, որը մասնավորապես նախագծված է տեսանյութերի համար: Տեսակներ, որոնք տեւում են բարձր մետաղական տարածքում, պետք է տեւում են 2D բաղադրիչում: Այսպիսով, այն հարմար է ստուգելու համար, թե բնական եւ սխալ բաղադրիչների բաղադրիչները բաղադրիչ են: local structure Մեկ կարեւոր խոստովանություն: t-SNE- ը բաղադրում է ամբողջական հեռավորությունները — սեղմիչների միջեւ տարածքը ոչինչ չի նշանակում: Օգտագործեք այն միայն բաղադրիչների համար, եւ բաղադրիչները բաղադրիչներ են Original ( կամ PCA-reduced) բաղադրիչների վրա: never cluster on t-SNE output. from sklearn.manifold import TSNE # Apply t-SNE on PCA output (faster and more stable than on raw 2048-dim) tsne = TSNE(n_components=2, random_state=42, perplexity=30, n_iter=1000) all_tsne = tsne.fit_transform(all_pca) Դա «Կարունքի չափը» (t-SNE)- ը վերահսկում է, թե ինչպիսիք են մեր չափի տվյալների բաղադրիչները: perplexity Այժմ պետք է կտրել t-SNE koordinates: labeled_tsne = all_tsne[:len(labeled_embeddings)] unlabeled_tsne = all_tsne[len(labeled_embeddings):] եւ տեսանյութը: fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # Left plot: labeled images only, colored by true label for cls_idx, cls_name, color in [(0, "Normal", "#2ecc71"), (1, "Defect", "#e74c3c")]: mask = labeled_labels_arr == cls_idx axes[0].scatter(labeled_tsne[mask, 0], labeled_tsne[mask, 1], label=cls_name, alpha=0.7, s=40, c=color) axes[0].set_title("t-SNE: Labeled Images (True Labels)") axes[0].legend() Եթե դուք տեսնում եք երկու առանձնահատկային մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղական մետաղ # Right plot: all images (unlabeled in gray, labeled overlaid) axes[1].scatter(unlabeled_tsne[:, 0], unlabeled_tsne[:, 1], c="lightgray", alpha=0.2, s=10, label="Unlabeled") for cls_idx, cls_name, color in [(0, "Normal", "#2ecc71"), (1, "Defect", "#e74c3c")]: mask = labeled_labels_arr == cls_idx axes[1].scatter(labeled_tsne[mask, 0], labeled_tsne[mask, 1], label=f"Labeled: {cls_name}", alpha=0.8, s=40, c=color) axes[1].set_title("t-SNE: All Images (Labeled in Color)") axes[1].legend() plt.tight_layout() plt.savefig("outputs/tsne_visualization.png", dpi=150) plt.show() Հավատում է, որ սառիկ գլուխը (լուսանկարներ) պետք է վերլուծվի գլուխների գլուխների հետ: Այսպիսով հավատում է, որ նամակված եւ անլոգված գլուխները ապրում են նույն մատակարարման վրա, որը պետք է աշխատել semi-supervised learning- ի համար: 4.5 — K-Means բաղադրիչները K-Means- ը ամենամեծ եւ ամենամեծ օգտագործված clustering algorithm- ը է: Այն կտրում է տվյալները ճշգրտաբար k- ի թիմերում, այնպես որ միասին կտրում է յուրաքանչյուր կետը մոտագույն cluster- ի կենտրոնի համար, ապա նորաձեւում է կենտրոնները: Քանի որ մենք գիտենք, որ ունենք 2 դասեր (normal եւ defect), մենք սկսում ենք k=2. Բայց մենք նաեւ փորձում ենք k=3, 4, 5, որպեսզի ստուգենք, որ տվյալները կարող են լինել ավելի կառուցվածքներ (հարկե, տարբեր) Արդյունաբերական բաղադրիչներ, որոնք ստեղծում են միասնական բաղադրիչներ) Տեսակներ Տեսելու համար, թե ինչպես լավ են բաղադրիչները ճշգրտվում իրական բաղադրիչների հետ, մենք օգտագործում ենք ARI = 1.0- ը նշանակում է, որ ճշգրտությունը ճշգրիտ է: ARI = 0,0- ը նշանակում է, որ սխալները սխալ են: ARI < 0- ը նշանակում է, որ սխալները սխալ են: ARI (Adjusted Rand Index) from sklearn.cluster import KMeans from sklearn.metrics import adjusted_rand_score, silhouette_score print("K-Means Clustering:") print(f" {'k':<5s} {'ARI':>8s} {'Silhouette':>12s}") print(f" {'-'*27}") for k in [2, 3, 4, 5]: kmeans = KMeans(n_clusters=k, random_state=42, n_init=10) all_clusters = kmeans.fit_predict(all_embeddings_scaled) # ARI: compare clusters vs true labels (on labeled images only) labeled_clusters = all_clusters[:len(labeled_embeddings)] ari = adjusted_rand_score(labeled_labels_arr, labeled_clusters) # Silhouette: internal quality measure (no labels needed) # How well-separated are the clusters? Range: -1 to +1 sil = silhouette_score(all_embeddings_scaled, all_clusters) print(f" {k:<5d} {ari:>8.4f} {sil:>12.4f}") Դա K-Means- ը 10 անգամ աշխատում է տարբեր անմիջական բաղադրիչների հետ եւ պահպանում է լավագույն արդյունքը: Այսպիսով փրկվում է անմիջական բաղադրիչների բաղադրիչը: n_init=10 Եթե k=2 ապահովում է բարձրագույն ARI, այն հավատում է, որ մեր տվյալները ունի երկու բնական թիմեր, որոնք հարմարվում են բնական vs սխալ. 4.6 — DBSCAN clustering (լուսանկարներ) DBSCAN- ը աշխատում է շատ տարբերորեն K-Means- ից: Մինչեւ որոշեք, թե ինչ է միասին միասին միասին միասին միասին միասին միասին միասին միասին: Eps (Epsilon): Երկու կետների միջեւ առավելագույն հեռավորությունը, որը պետք է կարծես, որ նրանք միասին են: Տեսեք այն, ինչպիսիք են «Ինչքան հեշտ է հասնել, որքան հեշտ է»: Min_samples: Հիմնական քանակը, որը պետք է ստեղծել խոշոր տարածք (լուսանկարներ): Տեսեք այն, ինչպիսիք են «Ինչքան խոշոր է մի տարածք, որ պետք է բեռնել որպես խոշորը»: DBSCAN- ը ավտոմատորեն որոշում է խոշորների համար եւ identifies outliers (մոտները, որոնք ոչ մի խոշորի մեջ չեն ներառում - նամակվել -1): Սա կարող է օգտակար լինել, որպեսզի գտնել անսահմանափակ նկարներ, որոնք կարող են լինել անսահմանափակ կամ անսահմանափակ: from sklearn.cluster import DBSCAN print("\nDBSCAN Clustering:") print(f" {'eps':<6s} {'min_s':<7s} {'clusters':>9s} {'noise':>7s} {'ARI':>8s}") print(f" {'-'*40}") Մենք պետք է փորձել բազմաթիվ պարամետրային համատեղերի համար, քանի որ «բավատ» արժեքները կախված են տվյալների վրա: for eps in [3.0, 5.0, 7.0, 10.0]: for min_samples in [5, 10, 20]: dbscan = DBSCAN(eps=eps, min_samples=min_samples) db_clusters = dbscan.fit_predict(all_pca) # Use PCA-reduced data n_clusters = len(set(db_clusters)) - (1 if -1 in db_clusters else 0) n_noise = (db_clusters == -1).sum() if n_clusters >= 2: labeled_db = db_clusters[:len(labeled_embeddings)] mask = labeled_db != -1 # Exclude noise points from ARI if mask.sum() > 10: ari = adjusted_rand_score(labeled_labels_arr[mask], labeled_db[mask]) print(f" {eps:<6.1f} {min_samples:<7d} {n_clusters:>9d} " f"{n_noise:>7d} {ari:>8.4f}") Տեղադրեք, որ մենք օգտագործում ենք PCA-reduced տվյալներ ( DBSCAN- ը վախենում է շատ բարձր մակարդակներում, քանի որ բոլոր մակարդակները միասնական են (լուսանկարներ) all_pca Տեղադրեք DBSCAN- ի լավագույն ARI-ը K-Means- ի լավագույնի հետ եւ ընտրեք հաղթողը: 4.7 — Տեսագրություն clusters վրա t-SNE բաղադրիչը Տեսենք, թե ինչ է տեսնում մեր լավագույն clustering- ը մեր t-SNE տեսանյութում: best_kmeans = KMeans(n_clusters=2, random_state=42, n_init=10) all_cluster_ids = best_kmeans.fit_predict(all_embeddings_scaled) fig, ax = plt.subplots(figsize=(8, 6)) scatter = ax.scatter(all_tsne[:, 0], all_tsne[:, 1], c=all_cluster_ids, cmap="coolwarm", alpha=0.4, s=15) ax.set_title("K-Means Clusters (k=2) on t-SNE") plt.colorbar(scatter, label="Cluster ID") plt.tight_layout() plt.savefig("outputs/kmeans_clusters_tsne.png", dpi=150) plt.show() Եթե այս բաղադրիչի երկու գույնները մոտավորապես համեմատ են այն երկու բաղադրիչների հետ, որոնք դուք տեսել եք նամակված t-SNE բաղադրիչի վրա, բաղադրիչը աշխատում է: 4.8 — Pseudo-labels- ի հավելվածությունը անլոգված նկարների համար Այժմ կարեւոր քայլը: Մենք ստանում ենք cluster- ի գործառույթները եւ բուժում ենք նրանց որպես "մոր մանրամասներ" անլոգված մանրամասների համար: Բայց կա մի մանրամասը — K-Means- ը բուժում է cluster- ի ID- ները անլոգաբար: Cluster 0- ը կարող է համեմատել "խաղադրված" կամ "normally". Մենք պետք է ստուգենք: Ավելացնել pseudo-լուսանկարներ unlabeled_pseudo_labels = all_cluster_ids[len(labeled_embeddings):] Տեղադրեք ճշգրտությունը ճշգրտությունների հետ: labeled_cluster_ids = all_cluster_ids[:len(labeled_embeddings)] # What fraction of labeled images in cluster 0 are actually "normal"? cluster_0_normal_rate = (labeled_labels_arr[labeled_cluster_ids == 0] == 0).mean() cluster_1_normal_rate = (labeled_labels_arr[labeled_cluster_ids == 1] == 0).mean() print(f"Cluster 0: {cluster_0_normal_rate:.1%} of labeled images are 'normal'") print(f"Cluster 1: {cluster_1_normal_rate:.1%} of labeled images are 'normal'") Եթե cluster 0- ը հիմնականում սխալներ է (normal_rate < 50%), մենք վերլուծում ենք սխալները: if cluster_0_normal_rate < 0.5: unlabeled_pseudo_labels = 1 - unlabeled_pseudo_labels print("Cluster IDs flipped to match convention (0=normal, 1=defect)") Տեսենք, թե ինչ է արտադրությունը: print(f"\nPseudo-label distribution:") print(f" Normal (0): {(unlabeled_pseudo_labels == 0).sum()} images") print(f" Defect (1): {(unlabeled_pseudo_labels == 1).sum()} images") Մենք այժմ ունենք երկու տարբեր տվյալների միավորներ, որոնք շատ տարբեր հատկանիշներ են: Բարձր ճշգրիտ — 200 նկարներ իրական մասնագիտական ճշգրիտության հետ. Բարձր որակի, փոքր քանակը. Սա մեր բնական ճշգրիտությունը. Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված Ով է Golden Rule: Նրանք ծառայում են տարբեր նպատակները հաջորդ քայլում. never mix these two. Ավելի ավելին կարդալ: Ավելի ավելին կարդալ: K-Means բացահայտվել է (scikit-learn) DBSCAN բացահայտել է (scikit-learn) Ինչպե՞ս կարդալ t-SNE ճիշտ (Distill) K-Means բացահայտվել է (scikit-learn) DBSCAN բացահայտել է (scikit-learn) Ինչպե՞ս կարդալ t-SNE ճիշտ (Distill) 5-րդ մասը — Semi-supervised training: The actual experiment 5.1 — Մեր երկու փետրվարի հարմարավետությունը Տեսեք, որ դուք ուսուցում եք նոր որակի վերահսկողը գործարանում: : Դուք ցույց եք տալիս նրանց 9,800 լուսանկարներ եւ ասում եք, որ «Ես «Ես չգիտեմ, թե ինչ է անում, թե ինչ է անում, թե ինչ է անում, թե ինչ է անում, թե ինչ է անում, թե ինչ է անում, թե ինչ է անում, թե ինչ է անում, թե ինչ է անում» (տեսանյութ) . Phase 1 (pre-training on pseudo-labels) Տեսեք Հիմնական : Այնուհետեւ դուք ցույց եք տալիս նրանց 200 ֆիլմերը, որոնք մասնագետի հետազոտությամբ ստուգված են: «Անհարկե, այդ սխալները բնական են, եւ այդ սխալները բնական են»: Դիտիչը բարելավում է իրենց հոգեբանային մոդելը, վերահսկում է 1- ի սխալները եւ խոշորեցնում է իրենց ճշգրտությունը գծի հարցերի մասին: Phase 2 (fine-tuning on real labels) Արդյոք: Մարդիկ, ովքեր ունեն 10 000 նկարներ (կպտելով լայն intuition) եւ ստացել է Մենք հավատում ենք, որ այս սեղմիչը ավելի լավ է, քան այն, ով միայն տեսնում է 200 սեղմիչներ: Տեսակ Kalibrated Այս մասին փորձարկելու համար, մենք կատարում ենք երկու միասնական փորձեր: Ուսուցում A- ը - միայն վերահսկվում է: կանգնեք միայն 200 նկարների համար Արդյունաբերական փորձը B - Semi-supervised: Pre-train 9800 pseudo-labelled images, then fine-tune on 200 labelled images Միայն տարբերությունը այն է, թե՞ մոդելը տեսնում է անլոգված տվյալները, կամ ոչ: 5.2 — Բարձրացումը classifier: Architecture Մենք օգտագործում ենք ResNet50- ը, քանի որ այս անգամ մենք The final layer with a binary classifier եւ մենք Ավելի լավ է, քանի որ այն (համփակվել է 3, որտեղ մենք պարզապես extracted առանձնահատկություններ). replace train import torch.nn as nn class DefectClassifier(nn.Module): """ Binary classifier: Normal (0) vs Defect (1). Based on ResNet50 with a custom classification head. """ def __init__(self, dropout_rate=0.5): super().__init__() self.backbone = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1) num_features = self.backbone.fc.in_features # 2048 Այստեղ մենք փոխարինում ենք Original ImageNet classification head (2048 → 1000 դասընթացներ) մեր սեփական: self.backbone.fc = nn.Sequential( nn.Dropout(p=dropout_rate), # Anti-overfitting nn.Linear(num_features, 1), # Binary output ) def forward(self, x): return self.backbone(x) Ինչու «Ինչի՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու՞ն է, թե ինչու է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ է, թե ինչ Dropout(0.5) Ինչու 2048, 2): Բինական դասընթացների համար մեկ արտադրանքի ռեժոնը sigmoid activation- ի հետ մետաղականորեն համատեղելի է երկու ռեժոնների հետ softmax- ի հետ, բայց ավելի պարզ եւ մի քիչ ավելի մետաղականորեն հարմար է: Linear(2048, 1) 5.3 — The Loss Function: Գնացուցման դասընթացը Հաջորդ հոդվածըՄենք պետք է խոսենք, թե ինչ է սխալը: (Binary Cross-Entropy with Logits), որը համատեղում է sigmoid activation- ի հետ binary cross-entropy- ի հետ մի մեկ, թվային stabil operation- ում: BCEWithLogitsLoss Հիմնական լրացուցիչը : pos_weight pos_weight = torch.tensor([4.0]).to(device) criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight) Ինչ է Դա ասում է, որ ծախսերի գործառույթը: «Համակված սխալը (լուսանկարային սխալը) պետք է ծախսվել» «Անհարկե, այս մոդելը կարող է հասնել 80% ճշգրիտությունը, երբ միշտ նախընտրում է «normals» - ինչը անսահմանափակ է». pos_weight=4.0 4 times more Արդյոք, եթե դուք ունեք 80% բնական / 20% սխալ, ապա Դուք կարող եք տեղադրել այս արժեքը, բայց 4.0- ը լավ փնտրում է: pos_weight = 80/20 = 4.0 5.4 — The optimizer: AdamW հետ քաշը կախված import torch.optim as optim optimizer = optim.AdamW(model.parameters(), lr=lr, weight_decay=1e-4) Ինչու է AdamW? Դա Adam- ի հետ ճշգրիտ քաշը (L2 regularization) «Այս ամենը, ինչ պետք է անել, այն է, ինչ պետք է պետք է անել», - ասել է նա: weight_decay=1e-4 5.1 - Կարդացուցման քանակը scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=3, factor=0.5) Դա ավտոմատորեն նվազեցնում է ուսուցման արագությունը, երբ ստուգման ծախսերը չի բարելավում. «Մենք պետք է վախենում ենք 3 շաբաթ, երբ չենք բարելավում», - ասում է նա. Դա կարեւոր է convergence- ի համար, քանի որ մոդել մոտեցում է minimum, փոքրիկ քայլերը փնտրում են overshooting. patience=3 factor=0.5 5.6 — The training loop: One epoch at a time Հիմա, մենք պետք է ստեղծել ամբողջական ուսուցման գործառույթը. Մենք պետք է անցնել յուրաքանչյուր մասը սեղմի մասնավորապես. (One epoch — One pass through all training data) The training phase from sklearn.metrics import f1_score def train_model(model, train_loader, val_loader, epochs, lr, device, phase_name=""): """Train the model and track validation F1 score.""" pos_weight = torch.tensor([4.0]).to(device) criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight) optimizer = optim.AdamW(model.parameters(), lr=lr, weight_decay=1e-4) scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=3, factor=0.5) best_f1 = 0 for epoch in range(epochs): # ---- TRAINING ---- model.train() # Enable dropout, update batch norm stats for images, labels in train_loader: images = images.to(device) labels = labels.float().unsqueeze(1).to(device) # .float() because BCEWithLogitsLoss expects float targets # .unsqueeze(1) adds a dimension: shape (batch,) → (batch, 1) optimizer.zero_grad() # Reset gradients from previous batch outputs = model(images) # Forward pass loss = criterion(outputs, labels) # Compute loss loss.backward() # Compute gradients (backpropagation) optimizer.step() # Update weights Ամեն բաղադրիչ անցնում է դասական բաղադրիչը: forward pass → calculate loss → backpropagate gradients → update weights → reset gradients for next batch. (Անհարկե, յուրաքանչյուր դասընթացից հետո): The validation phase # ---- VALIDATION ---- model.eval() # Disable dropout, use fixed batch norm stats all_preds, all_true = [], [] val_loss_total = 0 with torch.no_grad(): # No gradients needed for evaluation for images, labels in val_loader: images = images.to(device) outputs = model(images) # Compute validation loss val_loss_total += criterion( outputs, labels.float().unsqueeze(1).to(device) ).item() # Convert raw logits → binary predictions # sigmoid maps logits to [0, 1], then threshold at 0.5 preds = (torch.sigmoid(outputs) >= 0.5).int().cpu().numpy().flatten() all_preds.extend(preds) all_true.extend(labels.numpy()) Տեսեք The Դա կարեւոր է: Դա անջատում է dropout- ը (Այս բոլոր ռեժոնները աշխատում են) եւ օգտագործում է աշխատումային ստանդարտները բաղադրիչների ստանդարտության համար, այլեւ բաղադրիչների ստանդարտության համար: Երբ այն չի կատարվում, ձեր ստանդարտության մետրիկները կախված եւ չժանգահարված են: model.eval() Track metrics and update scheduler: val_f1 = f1_score(all_true, all_preds, average="binary") scheduler.step(val_loss_total) # Reduce LR if loss plateaued if val_f1 > best_f1: best_f1 = val_f1 if (epoch + 1) % 5 == 0: print(f" [{phase_name}] Epoch {epoch+1}/{epochs}: val_f1={val_f1:.4f}") print(f" [{phase_name}] Best F1: {best_f1:.4f}") return best_f1 Մենք փնտրում ենք F1 բոլոր ժամանակների ընթացքում, ոչ միայն վերջինը: Մոդելները հաճախ կախված են դասընթացների վերջը առաջ (հարկե, այն հետո, երբ նրանք կարող են մի քիչ ծախսել): best 5.7 — Data splits- ի պատրաստումը Տեղադրված տվյալները կտրում ենք տրանսպորտային (70%) եւ փորձարկման (30%) համար: Տեղադրված տվյալները կտրում են Նրանք երբեք չեն օգտագործվում դասընթացների համար ցանկացած փորձում: Stratification- ը ապահովում է, որ դասընթացը պահպանվում է երկու splits- ում: sacred from sklearn.model_selection import train_test_split labeled_train_idx, labeled_test_idx = train_test_split( range(len(labeled_paths)), test_size=0.3, random_state=42, stratify=labeled_labels, ) Մենք պետք ենք ստեղծել երեք տվյալների միավորներ: # 1. Labeled training data (for supervised training + fine-tuning) train_labeled_ds = MetalSurfaceDataset( [labeled_paths[i] for i in labeled_train_idx], [labeled_labels[i] for i in labeled_train_idx], preprocessing, ) # 2. Test data (for evaluation only — NEVER used for training) test_ds = MetalSurfaceDataset( [labeled_paths[i] for i in labeled_test_idx], [labeled_labels[i] for i in labeled_test_idx], preprocessing, ) # 3. Weakly labeled data (pseudo-labels from clustering) weakly_labeled_ds = MetalSurfaceDataset( unlabeled_paths, unlabeled_pseudo_labels.tolist(), preprocessing, ) եւ DataLoaders: train_labeled_loader = DataLoader(train_labeled_ds, batch_size=16, shuffle=True) test_loader = DataLoader(test_ds, batch_size=16, shuffle=False) weakly_labeled_loader = DataLoader(weakly_labeled_ds, batch_size=32, shuffle=True) print(f"Train (labeled): {len(train_labeled_ds)} images") print(f"Test: {len(test_ds)} images") print(f"Weakly labeled: {len(weakly_labeled_ds)} images") Նշեք տարբեր բաղադրիչների չափները: 16 համար փոքր բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադր Արդյոք, որ մոդել չի կարող սովորել մոդելների դասընթացը. shuffle=True 5.8 — փորձը A: վերահսկվում է միայն (դիմնական) Մենք ուսուցում ենք նոր մոդել, որը օգտագործում է միայն 140- ի նշված ուսուցման մոդելներ (լուսանկարներ): Այսպիսին է կատարումը, որը մենք կարող ենք ստանալ առանց semi-supervised ուսուցման: print("=" * 60) print("EXPERIMENT A: SUPERVISED ONLY (140 labeled images)") print("=" * 60) model_supervised = DefectClassifier(dropout_rate=0.5).to(device) f1_supervised = train_model( model_supervised, train_labeled_loader, test_loader, epochs=30, lr=1e-4, device=device, phase_name="Supervised" ) 5.9 — փորձը B: semi-supervised (հարկը երկու փուլով) Հիմա ամբողջ գիծը. Fase 1 ապահովում է մոդելը լայն ինտեգրման 9800 pseudo-labelled տեսանյութերի. Fase 2 հաստեցնում է այն հետ 140 իրական նամակներ. Phase 1 — Pre-training on weakly labeled data: print("\n" + "=" * 60) print("EXPERIMENT B: SEMI-SUPERVISED") print("=" * 60) model_semi = DefectClassifier(dropout_rate=0.5).to(device) print("\nPhase 1: Pre-train on pseudo-labeled data (9,800 images)...") train_model( model_semi, weakly_labeled_loader, test_loader, epochs=10, lr=1e-4, device=device, phase_name="Pre-train" ) Մենք միայն 10 շաբաթվա ընթացքում ուսուցում ենք այստեղ, քանի որ pseudo-etiquettes սխալ են. Training too long on noisy labels would reinforce the mistakes. Phase 2 — Fine-tuning on strongly labeled data: print("\nPhase 2: Fine-tune on real labeled data (140 images)...") f1_semi = train_model( model_semi, train_labeled_loader, test_loader, epochs=20, lr=5e-5, device=device, phase_name="Fine-tune" ) Տեսեք The (5e-5 vs 1e-4 in phase 1): Սա խոստովանելի եւ կարեւոր է: Եթե մենք օգտագործենք բարձր ուսուցման արագությունը fin-tuning- ի ընթացքում, մոդելը արագ «մոռացնի» ամեն ինչ, ինչ նա ուսուցել է pre-training- ի ընթացքում: գոտիները շատ մեծ են, եւ պետք է վերլուծեն pre-trained գոտիները: Մի հեշտ ուսուցման արագությունը թույլ է տալիս մոդելը կատարելու փոքր ճշգրտություններ է իր հասանելի գիտելիքի, պահպանելով լայն մոդելները 1- ից, իսկ ճշգրտման սխալները ճշգրտելով ճշգրտական մանրամասները: lower learning rate Դա նման է գործարանային վերահսկողի հետ: Դուք չեք սկսում իրենց դասընթացը սխալից սկսելու համար 2. Դուք հեշտությամբ վերահսկում եք իրենց սխալը, իսկ պահպանեք իրենց ամբողջական ինտեգրիա: 5.10 — Հիմնական արժեքը: ճշմարտության ժամանակը Այժմ մենք ստուգում ենք երկու մոդելերը միասին փորձարկման սերտիֆիկների հետ: Առաջին, evaluation գործառույթը: from sklearn.metrics import roc_auc_score, classification_report def full_evaluation(model, test_loader, device, name): """ Evaluate on the test set. Returns F1 score and AUC-ROC. """ model.eval() all_preds, all_probs, all_true = [], [], [] with torch.no_grad(): for images, labels in test_loader: outputs = model(images.to(device)) probs = torch.sigmoid(outputs).cpu().numpy().flatten() all_probs.extend(probs) all_preds.extend((probs >= 0.5).astype(int)) all_true.extend(labels.numpy()) Մենք համատեղում ենք երկու (AUC-ROC-ի համար, որը չափում է դասընթացային որակի) եւ (F1-ի համար, որը չափում է դասընթացային որակի 0.5- ի ծախսում): probabilities binary predictions f1 = f1_score(all_true, all_preds, average="binary") auc = roc_auc_score(all_true, all_probs) print(f"\n{name}:") print(f" F1 Score: {f1:.4f}") print(f" AUC-ROC: {auc:.4f}") print(classification_report( all_true, all_preds, target_names=["Normal", "Defect"] )) return f1, auc Ինչու Երբ սխալային դասընթացների հետ ճշգրիտությունը վախենում է: Մոդելը, որը միշտ նախընտրում է «դիմնական» ստանում է 80% ճշգրիտությունը, բայց 0% վերցնում է սխալները: F1- ը ճշգրիտության եւ վերցնումի սխալների սխալային միջին է: Այն վերցնում է մոդելները, որոնք չգիտեն քիչության դասընթացը: F1 Ինչու Դա նշանակում է, թե ինչպես լավ է մոդել Տեսակներ (լուսանկարներ պետք է ստանալ ավելի բարձր հավասարություն, քան բնականներ), այնպես էլ, թե ինչ է դասընթացը: AUC- ը 1.0- ը նշանակում է Perfect Ranking- ը, 0.5- ը նշանակում է random. AUC-ROC Ռենսեր Այժմ համեմատություն: f1_sup, auc_sup = full_evaluation( model_supervised, test_loader, device, "SUPERVISED ONLY" ) f1_semi, auc_semi = full_evaluation( model_semi, test_loader, device, "SEMI-SUPERVISED" ) Հիմնական ճշգրիտությունը: print("=" * 60) print("FINAL COMPARISON") print("=" * 60) print(f" {'Metric':<12s} {'Supervised':>12s} {'Semi-supervised':>16s} {'Delta':>8s}") print(f" {'-'*50}") print(f" {'F1':<12s} {f1_sup:>12.4f} {f1_semi:>16.4f} {f1_semi - f1_sup:>+8.4f}") print(f" {'AUC-ROC':<12s} {auc_sup:>12.4f} {auc_semi:>16.4f} {auc_semi - auc_sup:>+8.4f}") Եթե Delta սեղմը ցույց է տալիս հավասար թվերը, մենք հավատում ենք, որ սեղմված տվյալները օգտակար են: Pseudo-Label-ները, նույնիսկ անսահմանափակ են, տալիս են մոդելը մի head start- ը, որ պակաս վերահսկողությունը 200 նկարներում չի կարող համատեղել: 5.11 - Ապրանքների բացահայտումը Այսպիսով, ինչպիսիք են կարդալ Comparison: F1 բարելավվել է +0.05 կամ ավելի: Հիմնական վերահսկողության համար հուսալի հաղթանակը: Անհարկված տվյալները ապահովել են նշանակական Signal: F1 բարելավվել է +0.01 մինչեւ +0.04: Հիմնական բարելավումը: Հիմնական վերահսկողությունը օգնում է, բայց լայնությունը փոքր է: Տեսեք, թե ինչպես է բարելավել բաղադրիչների որակի կամ օգտագործել ավելի հարմարավետ pseudo-labeling: F1 չի փոխվել կամ ավելի վատ: Pseudo-labels են շատ խոշոր է օգնել, կամ clustering- ը չգիտել է ճշգրիտ կառուցվածքը. փորձեք տարբեր առանձնահատկություններ extracters, տարբեր clustering algorithms, կամ ավելի բարձր հավասարության գծեր pseudo-labels. Ավելի ավելին կարդալ: Ավելի ավելին կարդալ: Pseudo-labelling գրասենյակ (Lee, 2013) — original approach Հիմնական վերահսկողության դասընթաց (van Engelen & Hoos) - մոդելների ամբողջական վերահսկողություն PyTorch դասընթացների լավագույն գործիքները Pseudo-labelling գրասենյակ (Lee, 2013) Հիմնական դասընթաց (Van Engelen & Hoos) PyTorch դասընթացների լավագույն գործիքները Արդյունք 6 — Մարդիկ մանրամասների մանրամասների մանրամասների մանրամասների մանրամասների մանրամասներ Աշխատանքային հարցը «Մենք ունենք 4 միլիոն տեսանյութեր, որոնք պետք է մշակել. կարող ենք այս խողովակների ծախսել 5,000-ի բովանդակությամբ» Դա մի հարց է, որ դուք կանգնած եք ցանկացած իրական նախագծում: Տեսեք, թե ինչ է դա: Computing ծախսերը Իմ 10 000 տեսանյութերի հետ մեկ GPU- ի հետ, այն պետք է մոտ 30 րոպե: Feature extraction 4,000,000 images ÷ 10,000 images × 30 min = 12,000 min = 200 GPU-hours ~€2/ ժամ է Cloud GPU- ի տեղադրման համար (Azure NC-series հետ T4 կամ A10 GPU- ի հետ) . €400 Հիմնական K-Means բեռնում է բոլոր տվյալները մանրամասին, որպեսզի բեռնում է հեռավորությունները: 4M- ի մանրամասների հետ 2048 չափերի բեռնելը (4-բետային flot): Clustering 4,000,000 × 2,048 × 4 bytes = ~32 GB just for the embeddings Արդյոք, այն չի կտա RAM- ում մեծ մասի մեքենաների վրա: լուծում: օգտագործեք Սկսիկտ-լարն է, որը բուժում է տվյալները (հարկե) 10,000 նմուշների բաղադրիչների հետ մեկ անգամ: Հիմնական արդյունքը, սմարթության քանակը: MiniBatchKMeans 4M Pseudo-Labeled Images- ի նախընտրական դասընթացը պետք է մոտ 50 GPU ժամ: . CNN training €100 Storage ծախսերը Raw images: 4M × ~50 KB = Հյուրատետր Մետաղադրամներ: 4M × 2048 × 4 բայտ = Azure Blob Storage- ում ~€0.02/GB / ամիս, այն մասին . 200 GB 32 GB €5/month Հիմնական etikette Եթե 200 մետաղադրամներ չեն տեւում, մենք կարող ենք մետաղադրամներ ավելացնել: ~ 1 € մեկ մետաղադրամի համար (կամ որակի վերահսկողությունը ներառում է), 2000 ավելի մետաղադրամներ կարող են գնել: Բայց կա ավելի խելացի ձեւը: . €2,000 active learning Արդյունաբերական ուսուցում թույլ է տալիս մոդել ընտրել Արդյոք, այնպես էլ, որ մոդելը անմիջապես ընտրում է 2000 մոդելներ, այն մոդելները, որոնց մասին այն շատ չգիտեն, այն մոդելներ են, որոնք կարող են ավելի շատ ուսուցել այն: Այսպիսով սովորաբար անհրաժեշտ է 3-4 անգամ ավելի փոքր մոդելներ, որպեսզի հասկանալ նույն արագության բարելավել: Ինչի Արդյունաբերական ուսուցման հետ, մենք կարող ենք պետք է միայն 500 լրացուցիչ նամակներ, քան 2,000 . €500 Հյուրատետր Budget Estimate Feature extraction (GPU): €400 CNN training (GPU): €100 Storage (year 1): €60 Additional labeling: €500 – €2,000 ────────────────────────────────────── TOTAL: €1,060 – €2,560 Ավելի լավ է, որ 5,000- ի բովանդակության ընթացքում, որը կարող է մուտք գործել փորձարկման եւ վերադարձման համար: 5 պայմաններ հաջողության համար Օգտագործեք Cloud GPU- ները, ոչ տեղական սարքի: Գնել է ժամ, վճարեք միայն այն համար, ինչ դուք օգտագործում եք: Օգտագործեք MiniBatchKMeans- ից, այլեւ ստանդարտ KMeans- ից: Հիմնական որակի, 100x ավելի քիչ մանրամասներ: Տեղադրեք բաղադրիչները եւ բաղադրիչները, որոնք բաղադրիչները եւ բաղադրիչները են: Չնայեք բաղադրիչները եւ բաղադրիչները, որոնք բաղադրիչները եւ բաղադրիչները են: Արդյոք ամեն ինչ, ինչ կարող եք անել, այն է, ինչ դուք կարող եք անել այնպես, ինչ դուք կարող եք անել: 4M- ի բաղադրիչների վերլուծումը գնում է € 400-ի համար, սեղմվող բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղադրիչների բաղ Ավելի ավելին կարդալ: Ավելի ավելին կարդալ: MiniBatchKMeans (scikit-learn) — how to label smarter, not more Active learning overview MiniBatchKMeans (լուսանկարներ) Արդյունաբերական ուսուցման վերլուծություն Հյուրատետր Հիմնական վերահսկողության ուսուցման չէ, դա տեխնոլոգիան. Դուք վերահսկողված տվյալների (լուսանկարներ եւ clustering- ի միջոցով) սեղմված կառուցվածքը ստանում եք, վերահսկողված մոդելը վերահսկողված մոդելը վերահսկողելու համար օգտագործեք այն, որը վերահսկողված մոդելը վերահսկողում է: Նրանք վերահսկողված տվյալները չի վերահսկողում իրական մոդելները, այլն: Նրանք վերահսկողվում են: Տեսեք ամբողջ խողովակը, որը մենք կառուցել ենք: Ուսանություն — Մենք ստուգել ենք 10,000 տեսանյութեր ծախսության, անսահմանափակ ձեւաչափերի եւ դասընթացների անսահմանափակության համար: Մենք տեսել ենք տվյալները մեր աչքերով: Preprocessing — Մենք ստանդարտել ենք ամեն տեսանյութը ResNet50- ի համար: 224×224, RGB, CLAHE-enhanced, ImageNet-normalized. Նկարագրության արտադրություն — Մենք օգտագործում ենք Pre-Trained ResNet50- ը, որպեսզի յուրաքանչյուր նկարը փոխել է 2048- ի մետաղական ներարկման մեջ, որը փնտրում է իր տեսական բարդությունը: Clustering — Մենք օգտագործում ենք K-Means- ը եւ DBSCAN- ը, որպեսզի սեղմել չորակագրված բաղադրիչները clusters- ում, ապա սեղմել pseudo-labels- ում cluster- ի անդամության վրա: Շատ վերահսկված դասընթաց - Մենք նախընտրում ենք CNN- ում 9,800 pseudo-labelled տեսանյութերի վրա, ապա finested- ի 200 իրական տեսանյութերի վրա, եւ համեմատվել է միայն վերահսկված վերահսկված կայքի. Շատահասենյակային վերլուծություն — Մենք կասկածել ենք 4M- ի տեսանյութերի հաշվարկման, մատակարարման եւ մատակարարման ծախսերը, որը հավատում է կատարելիությունը 5,000- ի budget- ում: Հիմնական Takeaways: Պահպանված CNN- ը կարող է արտադրել նշանակական առանձնահատկությունները ցանկացած տեսանյութի տարածքում, նույնիսկ այն տարածքում, որտեղ նա երբեք չի ուսուցվել: Պահպանվածների վրա բաղադրիչները բացահայտում են բնական բաղադրիչները, որոնք հաճախ ճշգրտվում են ճշգրտական դասընթացների հետ: Pseudo-labels- ը անսահմանափակ են, բայց մի մոդել, որը նախընտրում է անսահմանափակ մանրամասների վրա եւ ապա ճշգրտված է ճշգրտական մանրամասների վրա, գերազանցում է միայն ճշգրտական մանրամասների վրա ուսուցված մոդելը: Այսպիսով, semi-supervised մանրամասը ամենամեծ արժեքն է այն ժամանակ, երբ մանրամասները Այս մոդելը աշխատում է բազմաթիվ մակարդակներում: բժշկական imaging, արդյունաբերական որակի վերահսկողությունը, satellite imaging, գրառումների դասընթացը, եւ biological diversity monitoring.Where labelings are expensive and unlabeled data is abundant — which, by 2025, is everywhere.