Application: tam data science pipeline
Application: tam data science pipeline
İndiyədək hər fəsil bir aləti ayrıca göstərirdi: NumPy massivləri, pandas cədvəlləri, Matplotlib qrafikləri, scikit-learn-in supervised və unsupervised model-ləri. Real məsələ isə heç vaxt bir alətlə həll olunmur. O, alətlərin zəncirindən ibarətdir və zəncirin hər halqasında qərar vermək lazımdır. Bu fəsil Python Data Science Handbook-un son nümunəsini, şəkildə üz tapan face detection pipeline-ını, başdan sona keçir, sonra isə geri çəkilib hər hansı data science layihəsinin anatomiyasına baxır. Məqsəd state-of-the-art üz detektoru qurmaq deyil; məqsəd "model" ilə "pipeline" arasındakı fərqi hiss etmək və layihəni kəşfiyyatdan nəticəyə qədər aparmağı öyrənməkdir.
Məsələ: model yox, pipeline
Sual sadə səslənir: verilmiş şəkildə üzlər haradadır? Amma bu, classifier-in birbaşa cavab verə biləcəyi sual deyil. Classifier "bu kiçik parça üzdür, ya yox?" sualına cavab verir. Şəkildən o parçalara çatmaq və parçaların cavablarını geri şəklə yığmaq ayrı işdir. Buna görə həll dörd mərhələdən ibarət pipeline-dır:
şəkil → feature extraction (HOG) → classifier (linear SVM)
→ sliding window + scale → overlapping detection-ların birləşdirilməsi
Pipeline-ın hər mərhələsi ayrıca test edilə, dəyişdirilə və ölçülə bilər. Bu, layihənin ən vacib dizayn qərarıdır.
HOG: şəkildən feature-lərə
Xam piksellər pis feature-dir. Eyni üz işıq dəyişəndə tamam fərqli piksel dəyərləri alır; iki piksel sağa sürüşəndə vektor tamamilə dəyişir. Classifier-ə lazım olan işığa və kiçik sürüşmələrə dözümlü, amma formaya həssas təqdimatdır.
HOG (histogram of oriented gradients) məhz bunu verir. Addımları:
- Hər piksel üçün gradient hesablanır: parlaqlıq hansı istiqamətdə və nə qədər sürətlə dəyişir. Kənarlar böyük gradient, hamar səthlər kiçik gradient verir.
- Şəkil kiçik cell-lərə (məsələn, 8×8 piksel) bölünür. Hər cell-də gradient istiqamətlərinin histogramı qurulur: 9 istiqamət bin-i, hər gradient öz böyüklüyü ilə çəkilənir. Nəticədə cell "burada əsasən şaquli kənarlar var" kimi bir məlumat daşıyır.
- Qonşu cell-lər block-lara (2×2 cell) qruplaşdırılır və hər block-un histogramları normalize edilir. Bu, lokal kontrast dəyişikliklərini silir: kölgədəki və günəşdəki eyni kənar eyni vektor verir.
- Bütün block-ların histogramları bir uzun vektora yığılır.
from skimage.feature import hog
features = hog(image, orientations=9, pixels_per_cell=(8, 8),
cells_per_block=(2, 2))
# 62x47 piksellik şəkil -> təxminən 1200 ədədlik vektor
HOG-un fəlsəfəsi ümumidir: xam data-nı deyil, onun invariant xülasəsini modelə verin. Bu, əvvəlki fəsillərdəki TF-IDF və PCA ilə eyni ideyadır.
Training set-i qurmaq
Supervised classifier üçün iki class lazımdır. Müsbət nümunələr hazırdır: Labeled Faces in the Wild dataset-ində 13 mindən çox kəsilmiş üz var və fetch_lfw_people onları 62×47 ölçüsündə qaytarır.
Mənfi nümunələr daha maraqlıdır, çünki "üz olmayan şey" sonsuz müxtəlifdir. Praktik həll: üz olmayan bir neçə şəkil (dəniz, bina, mətn, təbiət) götürüb onlardan təsadüfi parçalar kəsmək. scikit-learn-in PatchExtractor-u bunu edir; parçaları müxtəlif miqyasda kəsib hamısını 62×47-yə gətirmək detektoru fərqli fon teksturalarına hazırlayır:
from sklearn.feature_extraction.image import PatchExtractor
ext = PatchExtractor(patch_size=(62, 47), max_patches=1000, random_state=0)
patches = ext.transform(background_images) # shape: (n_patches, 62, 47)
Bir neçə min müsbət və on minlərlə mənfi nümunə yığıldıqdan sonra hər biri HOG-dan keçirilir və X, y massivləri alınır. Burada class imbalance düşünülməlidir: real şəkildə sliding window-ların böyük əksəriyyəti üz deyil. Mənfi class-ın training-də çox olması bunu əks etdirir, amma qiymətləndirmədə accuracy aldadıcı olacaq; bu barədə aşağıda.
Classifier: linear SVM
Feature-lər hazır olanda classifier seçimi sürətli olmalıdır. Həmişə baseline ilə başlayın: GaussianNB üzərində cross_val_score bir neçə saniyədə təxminən 0.9 accuracy verir. Sonra linear SVM sınayın: HOG vektoru yüksək ölçülüdür, nümunə sayı böyükdür və əvvəlki fəsildə gördüyümüz kimi bu şəraitdə kernel lazım deyil, LinearSVC kifayətdir və qat-qat sürətlidir.
from sklearn.svm import LinearSVC
from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(LinearSVC(), {"C": [0.5, 1.0, 2.0, 4.0]}, cv=3)
grid.fit(X_train, y_train)
print(grid.best_params_, grid.best_score_) # {'C': 1.0} 0.99
model = grid.best_estimator_
C kiçik grid üzərində seçilir: soft margin nə qədər sərt olmalıdır? 0.99 cross-validation accuracy yaxşı görünür, amma bu, kəsilmiş parçalar üzərindədir. Pipeline-ın əsl testi hələ qabaqdadır.
Sliding window və scale
Yeni şəkildə üz tapmaq üçün 62×47 ölçülü pəncərəni şəkil üzərində addım-addım sürüşdürür, hər mövqedə HOG hesablayır və model-dən cavab alırıq. Addımın ölçüsü sürətlə dəqiqlik arasında trade-off-dur: 2 piksel addım hər şeyi tapır, amma çox yavaşdır; 8 piksel dəfələrlə sürətlidir, amma üz pəncərələrin arasına düşə bilər.
İki incəlik var. Birincisi, üzlər fərqli ölçüdə olur, pəncərə isə sabitdir. Həll şəkli kiçiltməkdir: orijinal, 0.8 dəfə, 0.64 dəfə və beləcə davam; hər miqyasda eyni pəncərə ilə keçin. Kiçildilmiş şəkildə tapılan üz orijinalda böyük üzə uyğundur. Bu, image pyramid yanaşmasıdır. İkincisi, predict yox, decision_function istifadə edin: o, margin-dən məsafəni qaytarır və hədd 0 əvəzinə, məsələn, 1.0 seçmək false positive-lərin sayını kəskin azaldır. Hədd pipeline-ın tənzimlənə bilən parametridir, model-in yox.
Overlapping detection-ları birləşdirmək
Pəncərə üzün üzərindən 2 piksel addımla keçəndə eyni üz üçün onlarla müsbət cavab alınır. Bunları bir detection-a yığmaq lazımdır. Standart yol non-maximum suppression-dır: bütün detection-ları score-a görə sıralayın, ən yüksəyini qəbul edin, onunla müəyyən həddən çox (məsələn, kəsişmə/birləşmə nisbəti 0.3-dən böyük) üst-üstə düşən hamısını silin, qalanlar arasında təkrarlayın. Nəticə hər üz üçün bir çərçivədir. Üst-üstə düşmə həddi də pipeline parametridir: çox kiçik seçsəniz, yan-yana duran iki üzdən biri silinir; çox böyük seçsəniz, eyni üz iki dəfə sayılır. Bu addımın model ilə heç bir əlaqəsi yoxdur, amma son nəticənin keyfiyyətinə classifier qədər təsir edir.
Dürüst qiymətləndirmə
Pipeline işləyəndə ilk reaksiya "0.99 accuracy" demək olur. Bu, yanlışdır. Real şəkildə pəncərələrin 99.9%-i üz deyil; "heç vaxt üz demə" strategiyası belə 99.9% accuracy verir. Düzgün suallar başqadır: tapılan üzlərin neçə faizi həqiqətən üzdür (precision) və həqiqi üzlərin neçə faizi tapılıb (recall)? Hədd yüksəldikcə precision artır, recall düşür; precision-recall əyrisi pipeline-ın əsl portretidir. Bu metrikalar Machine Learning kitabında ətraflı müzakirə olunur.
Precision-ı yaxşılaşdırmağın klassik üsulu hard negative mining-dir: detektoru üz olmayan şəkillərə tətbiq edin, səhv tapdığı hər parçanı mənfi nümunə kimi training set-ə əlavə edin və yenidən train edin. Model məhz ən çətin səhvlərini öyrənir. Bir-iki iterasiya adətən false positive-ləri dəfələrlə azaldır.
Hara qədər işləyir? HOG və linear SVM frontal, yaxşı işıqlanmış, təxminən şaquli üzlərdə yaxşıdır. Üz profildən olanda, 30 dərəcə fırlananda, yarısı örtüləndə və ya çox qaranlıqda HOG-un histogramları training-dəkilərə bənzəmir və model susur. Bu məhdudiyyətlər model-in yox, əl ilə dizayn edilmiş feature-in məhdudiyyətləridir. Müasir detektorlar məhz buna görə HOG-u atıb convolutional neural network-lərlə feature-ləri data-dan öyrənir; image pyramid və non-maximum suppression isə onlarda da yaşamağa davam edir. Pipeline-ın strukturu alətlərindən daha uzunömürlüdür.
Hər layihənin anatomiyası
Üz detektorunu kənara qoyun. Eyni mərhələlər hər data science layihəsində təkrarlanır:
- Sual. "Bu şəkildə üz varmı?", "bu müştəri gedəcəkmi?", "bu məhsulun tələbi niyə düşdü?" Sual dəqiq olmayanda sonrakı hər addım boşa gedir. Nəticənin kim tərəfindən və hansı qərar üçün istifadə olunacağını əvvəlcədən yazın.
- Data əldə etmək. Dataset, API, database, log faylları. Data-nın hardan gəldiyini və nəyi təmsil etmədiyini qeyd edin: LFW-dəki üzlər əsasən məşhur insanların press-foto çəkilişləridir.
- Təmizləmə pandas ilə: missing value-lar, dublikatlar, tiplər, uyğunsuz kodlaşdırma. Layihə vaxtının yarısı burada keçir və bu normaldır.
- Kəşfiyyat Matplotlib ilə: paylanmalar, korrelyasiyalar, zaman üzrə dəyişmə, outlier-lər. Qrafik çəkmədən model qurmaq data-nın sürprizlərini modelə gizlətməkdir.
- Baseline. Ən sadə model, hətta "ortanı proqnozlaşdır". Sonrakı hər şey bununla müqayisə olunur.
- İterasiya. Daha yaxşı feature-lər, başqa model, hiperparametr seçimi: hər biri validation curve və cross-validation ilə yoxlanır. Training score-un yüksəlməsi heç nə sübut etmir.
- Nəticənin çatdırılması. Qrafik, qısa yazı, konkret tövsiyə. Nəticə başa düşülməyəndə layihə mövcud deyil.
Bu siyahı xətti deyil. Kəşfiyyat sualı dəyişdirir, model data-da yeni problem üzə çıxarır, çatdırılma yeni sual doğurur.
Reproducibility
Nəticə təkrar alına bilmirsə, ona inanmaq olmaz, nə sizin, nə də başqasının. Üç ucuz vərdiş:
- Sabit seed-lər.
random_state=0hərtrain_test_split,KMeans,PatchExtractorvəRandomForestClassifierçağırışında. NumPy üçünnp.random.default_rng(0). - Sabitlənmiş mühit. Kitabxanaların dəqiq versiyaları bir faylda; altı ay sonra scikit-learn-in yeni versiyası default-ları dəyişə bilər.
- Notebook-dan modula. Notebook kəşfiyyat üçün əvəzsizdir, amma hücrələrin sırasız icrası gizli state yaradır. Pipeline formalaşan kimi funksiyaları
.pyfaylına köçürün, notebook isə onları çağırıb nəticəni göstərsin. Data faylının hansı versiyası ilə işlədiyinizi də qeyd edin: eyni kod, fərqli data, fərqli nəticə ən çox rast gəlinən "təkrar alınmır" səbəbidir.
Növbəti addım
Bu kitab data science-ın alət dəstini verdi: massivlər, cədvəllər, qrafiklər və scikit-learn ilə modelləşdirmə. Bundan sonra yollar budaqlanır:
- Alqoritmlərin özləri, evaluation metodologiyası, feature engineering və model-in production-a çıxarılması üçün kitabxanadakı Machine Learning kitabı.
- HOG-un yerini tutan neural network-lər, transformer-lər və böyük model-lərin train edilməsi üçün Foundation Model Engineering kitabı.
- Statistika: hipotez testləri, confidence interval-lar, causal inference. "Fərq var" ilə "fərq təsadüfi deyil" arasındakı məsafəni ölçmək üçün.
- SQL: real data pandas-a çatmazdan əvvəl database-də yaşayır və onu orada filter və aggregate etmək çox vaxt daha düzgündür.
- Deep learning: şəkil, səs və mətn üçün feature-ləri əl ilə dizayn etmək dövrü bağlanıb; bu fəsildəki detektor həmin dövrün ən yaxşı nümunəsi və onun niyə keçildiyinin izahıdır.
Tapşırıqlar
- LFW üzləri və
PatchExtractorilə kəsilmiş mənfi parçalardan HOG feature-ləri çıxarın.GaussianNB,LinearSVCvəRandomForestClassifierüçün 3-fold cross-validation ilə precision və recall hesablayın (accuracy yox). Hansı model false positive-lərə daha meyllidir? - Train etdiyiniz
LinearSVC-ni bir qrup fotoya sliding window ilə tətbiq edin.decision_functionhəddini 0, 0.5, 1.0 və 2.0 götürün; hər həddə tapılan çərçivələrin sayını və əl ilə yoxlayıb neçəsinin həqiqətən üz olduğunu cədvələ yazın. Sonra non-maximum suppression-ı özünüz implement edib nəticəni təkrarlayın. - Kiçik bir tabular dataset seçin və bu fəsildəki yeddi mərhələni başdan sona bir
.pymodulunda icra edin: sual, data, təmizləmə, kəşfiyyat qrafikləri, baseline, validation curve ilə iki iterasiya və nəticəni bir səhifəlik yazıda çatdırın. Modulu ikinci dəfə işlədəndə eyni rəqəmlərin alındığını yoxlayın.