Məzmuna keç
Educora
Universitet25 dəq35 / 42

scikit-learn ilə maşın öyrənməsi

scikit-learn-ün vahid interfeysi: verilənlərin bölünməsi, xətti və logistik reqressiya, qərar ağacı, MSE, R², dəqiqlik, qarışıqlıq matrisi, precision və recall, çarpaz yoxlama və verilənlərin sızmasından qoruyan konveyerlər.

Özünü yoxla
Bu dərsdə öyrənəcəksən
  • fit, predict, score interfeysi ilə istənilən modeli öyrətmək və verilənləri düzgün bölmək
  • Reqressiyanı MSE, RMSE və R² ilə, təsnifatı dəqiqlik, precision, recall və F1 ilə qiymətləndirmək
  • Qərar ağacında həddən artıq uyğunlaşmanı tanımaq və Gini qeyri-təmizliyini hesablamaq
  • Çarpaz yoxlama və konveyerlə modeli sızmasız qiymətləndirmək

«Maşın öyrənməsinin əsas anlayışları» dərsində qradiyent enişini əl ilə yazmışdıq. Praktikada isə hər dəfə sıfırdan başlamırıq: scikit-learn kitabxanası onlarla yoxlanılmış model, verilənlərin hazırlanması alətləri və metriklər təklif edir — hamısı eyni sadə interfeyslə. Bu dərsdə mənzilin qiymətini proqnozlaşdıracaq, gülləri növlərə ayıracaq və ən vacibi — modeli düzgün qiymətləndirməyi öyrənəcəksən.

Vahid interfeys: fit, predict, score

Verilənlər həmişə eyni formadadır: əlamətlər matrisi X (n nümunə × d əlamət) və hədəf vektoru y (uzunluğu n). Hər model (scikit-learn-də estimator) üç metod bilir: fit(X, y) öyrədir, predict(X) proqnoz verir, score(X, y) keyfiyyəti ölçür. Hiperparametrlər konstruktorda verilir (DecisionTreeClassifier(max_depth=3)), öyrənilmiş parametrlərin adları isə alt xətt ilə bitir: coef_, intercept_. Verilənləri dəyişən obyektlər (transformerlər) fit və transform metodlarına malikdir.

SinifTapşırıqİdeya
LinearRegressionreqressiyaŷ = w · x + b, kvadratik xətaların minimumu
LogisticRegressiontəsnifatxətti ifadə sigmoid (softmax) ilə ehtimala çevrilir
DecisionTreeClassifiertəsnifat«bəli / xeyr» suallar ağacı
KNeighborsClassifiertəsnifatən yaxın k qonşunun səsverməsi
StandardScalertransformerhər əlaməti z-bala çevirir

Bölmə və xətti reqressiya

train_test_split verilənləri təsadüfi olaraq öyrədici və test hissələrinə bölür: test_size=0.25 — dörddə biri testə gedir, random_state bölgünü təkrarlana bilən edir, təsnifatda isə stratify=y siniflərin nisbətini hər iki hissədə eyni saxlayır. Aşağıda 200 mənzilin sintetik verilənləri y = 1,5 · sahə + 12 · otaq + 20 + küy qaydası ilə yaradılıb (qiymət min manatla); model bu əmsalları bilmədən tapmalıdır.

Python
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

rng = np.random.default_rng(0)
area = rng.uniform(40, 140, 200)
rooms = rng.integers(1, 5, 200)
X = np.column_stack([area, rooms])
y = 1.5 * area + 12 * rooms + 20 + rng.normal(0, 10, 200)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
model = LinearRegression().fit(X_train, y_train)
print('coef:', model.coef_.round(2), 'intercept:', round(model.intercept_, 2))
pred = model.predict(X_test)
mse = mean_squared_error(y_test, pred)
print(f'MSE = {mse:.1f}, RMSE = {np.sqrt(mse):.2f}, R2 = {r2_score(y_test, pred):.3f}')
print(X_train.shape, X_test.shape)
print(model.predict([[80, 3]]).round(1))
▸ Gözlənilən nəticə
coef: [ 1.48 11.06] intercept: 23.97
MSE = 95.4, RMSE = 9.76, R2 = 0.960
(150, 2) (50, 2)
[175.4]
MSE = (1/n) · ∑ (yᵢ − ŷᵢ)² RMSE = √MSE R² = 1 − ∑ (yᵢ − ŷᵢ)² / ∑ (yᵢ − ȳ)²MSE = (1/n) · ∑ (yᵢ − ŷᵢ)² RMSE = √MSE R² = 1 − ∑ (yᵢ − ŷᵢ)² / ∑ (yᵢ − ȳ)²
burada:
  • yᵢ, ŷᵢhəqiqi qiymət və proqnoz
  • RMSEhədəflə eyni vahiddə orta xəta (burada min manat)
  • R²izah olunan variasiyanın payı: 1 — ideal, 0 — həmişə ortanı proqnozlaşdıran model səviyyəsi

Model əmsalları 1,48 və 11,06 tapıb — həqiqi 1,5 və 12-yə yaxındır. RMSE ≈ 9,8 verilənlərə qatdığımız küyün (σ = 10) səviyyəsidir: model siqnalı tam tutub, küyü isə proqnozlaşdırmaq mümkün deyil.

Təsnifat: logistik reqressiya və qərar ağacı

Logistik reqressiya xətti ifadəni z = w · x + b sigmoid funksiyası ilə 0 və 1 arasındakı ehtimala çevirir; ikidən çox sinif üçün onun ümumiləşməsi olan softmax işlədilir. Məşhur iris verilənləri (1936-cı ildən statistikanın klassik nümunəsi) 3 növdən 150 gülün 4 ölçüsünü saxlayır və scikit-learn-ün içindədir — internet lazım deyil.

p = σ(z) = 1 / (1 + e^(−z)), z = w · x + bp = σ(z) = 1 / (1 + e^(−z)), z = w · x + b
burada:
  • σ(z)sigmoid: istənilən ədədi (0; 1) aralığına salır, σ(0) = 0,5
  • pnümunənin müsbət sinfə aid olma ehtimalı; p ≥ 0,5 olanda «1» proqnozlaşdırılır
Python
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix

X, y = load_iris(return_X_y=True)
print(X.shape, np.bincount(y))
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, stratify=y, random_state=9)
clf = LogisticRegression(max_iter=1000).fit(X_train, y_train)
pred = clf.predict(X_test)
print('accuracy:', round(accuracy_score(y_test, pred), 3))
print(confusion_matrix(y_test, pred))
print(clf.predict_proba(X_test[:2]).round(2))
▸ Gözlənilən nəticə
(150, 4) [50 50 50]
accuracy: 0.956
[[15  0  0]
 [ 0 14  1]
 [ 0  1 14]]
[[0.  0.1 0.9]
 [0.  0.2 0.8]]
Qarışıqlıq matrisində sətirlər həqiqi, sütunlar proqnozlaşdırılan sinifdir: bir versicolor virginica kimi, bir virginica isə versicolor kimi tanınıb. predict_proba hər sinfin ehtimalını verir.

Qərar ağacı verilənləri «ləçəyin uzunluğu < 2,45 sm?» kimi suallarla addım-addım bölür. Hər addımda elə sual seçilir ki, alınan qruplar mümkün qədər «təmiz» olsun — təmizliyi Gini qeyri-təmizliyi ölçür. Ağacı məhdudlaşdırmasaq, o, hər öyrədici nümunəni əzbərləyənə qədər böyüyür.

G = 1 − ∑ₖ pₖ² Gsplit = (nL / n) · GL + (nR / n) · GRG = 1 − ∑ₖ pₖ² Gsplit = (nL / n) · GL + (nR / n) · GR
burada:
  • pₖdüyündə k sinfinin payı
  • G0 — düyün təmizdir (bir sinif), iki sinif üçün maksimum 0,5
  • nL, nRsol və sağ övlad düyünlərdəki nümunələrin sayı
Nümunə 1: bölgü nə qədər yaxşıdır?

Düyündə 10 nümunə var: 6 A sinfi, 4 B sinfi. Bir sual onları sol (5 A, 0 B) və sağ (1 A, 4 B) qruplara bölür. Bölgüdən əvvəl və sonra Gini qeyri-təmizliyini hesabla.

Həllini göstər
Əvvəl: G = 1 − (0,6² + 0,4²) = 1 − (0,36 + 0,16) = 0,48.
Sol: yalnız A → GL = 0.
Sağ: GR = 1 − (0,2² + 0,8²) = 1 − (0,04 + 0,64) = 0,32.
Sonra: Gsplit = 5/10 · 0 + 5/10 · 0,32 = 0,16.
Qeyri-təmizlik 0,48 − 0,16 = 0,32 azaldı; ağac bütün mümkün suallar arasından ən böyük azalma verənini seçir.
Python
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

X, y = make_moons(n_samples=400, noise=0.3, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
for depth in [1, 3, 5, None]:
    tree = DecisionTreeClassifier(max_depth=depth, random_state=0).fit(X_train, y_train)
    train_acc = tree.score(X_train, y_train)
    test_acc = tree.score(X_test, y_test)
    print(f'max_depth={str(depth):>4}: train {train_acc:.3f}, test {test_acc:.3f}, leaves {tree.get_n_leaves()}')
▸ Gözlənilən nəticə
max_depth=   1: train 0.814, test 0.817, leaves 2
max_depth=   3: train 0.889, test 0.908, leaves 7
max_depth=   5: train 0.907, test 0.892, leaves 15
max_depth=None: train 1.000, test 0.883, leaves 38
make_moons iki iç-içə «aypara» şəklində küylü sintetik verilənlər yaradır. Dərinlik 1 — zəif uyğunlaşma; 3 — ən yaxşı test nəticəsi; məhdudiyyətsiz ağac öyrədici dəsti 100% əzbərləyir, testdə isə pisləşir.

Dəqiqlikdən kənar metriklər

İkili təsnifatda scikit-learn-ün qarışıqlıq matrisi belə düzülür: birinci sətir [TN, FP], ikinci sətir [FN, TP]. Burada TP — düzgün tapılmış müsbətlər, FP — yalan həyəcanlar, FN — buraxılmış müsbətlər, TN — düzgün rədd edilmiş mənfilər. Spam filtri nümunəsində «1» spam deməkdir:

Accuracy = (TP + TN) / N Precision = TP / (TP + FP) Recall = TP / (TP + FN) F1 = 2 · P · R / (P + R)Accuracy = (TP + TN) / N Precision = TP / (TP + FP) Recall = TP / (TP + FN) F1 = 2 · P · R / (P + R)
burada:
  • Precision«spam» dediklərimizin neçə faizi həqiqətən spamdır
  • Recallbütün spamın neçə faizini tuta bildik
  • F1precision və recall-un harmonik ortası
  • Nbütün nümunələrin sayı
Python
from sklearn.metrics import (accuracy_score, confusion_matrix, f1_score,
                             precision_score, recall_score)

y_true = [1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0]
y_pred = [1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0]
print(confusion_matrix(y_true, y_pred))
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
print('TP, FP, FN, TN =', tp, fp, fn, tn)
print('accuracy :', round(accuracy_score(y_true, y_pred), 3))
print('precision:', round(precision_score(y_true, y_pred), 3))
print('recall   :', round(recall_score(y_true, y_pred), 3))
print('F1       :', round(f1_score(y_true, y_pred), 3))
▸ Gözlənilən nəticə
[[5 2]
 [1 4]]
TP, FP, FN, TN = 4 2 1 5
accuracy : 0.75
precision: 0.667
recall   : 0.8
F1       : 0.727
Nümunə 2: dəqiqlik paradoksu

Skrininq testi 1000 nəfəri yoxlayır, onlardan 10-u xəstədir. Model 8 xəstəni tapır (TP = 8, FN = 2) və 40 yalan həyəcan verir (FP = 40, TN = 950). Dəqiqliyi, precision-u və recall-u tap və onları «hamı sağlamdır» deyən modellə müqayisə et.

Həllini göstər
Accuracy = (8 + 950) / 1000 = 0,958.
Precision = 8 / (8 + 40) ≈ 0,167 — həyəcanların yalnız hər altıncısı həqiqidir.
Recall = 8 / (8 + 2) = 0,8 — xəstələrin 80%-i tapılıb.
«Hamı sağlamdır» modeli: accuracy = 990 / 1000 = 0,99 (daha yüksək!), amma recall = 0 — heç bir xəstə tapılmır.
Nəticə: balanssız verilənlərdə dəqiqlik aldadıcıdır; recall, precision və F1-ə bax.

Çarpaz yoxlama və konveyerlər

Bir test bölgüsünün nəticəsi şansdan asılıdır: başqa random_state başqa ədəd verə bilər. k qatlı çarpaz yoxlama verilənləri k hissəyə bölür, modeli k dəfə öyrədir — hər dəfə bir hissə test olur — və k nəticənin ortasını götürür. Nəticələrin səpələnməsi qiymətləndirmənin nə qədər etibarlı olduğunu göstərir.

CV = (1/k) · ∑ᵢ₌₁ᵏ scoreᵢCV = (1/k) · ∑ᵢ₌₁ᵏ scoreᵢ
burada:
  • kqatların sayı, adətən 5 və ya 10
  • scoreᵢi-ci qat test olanda alınan nəticə
Python
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score

X, y = load_iris(return_X_y=True)
scores = cross_val_score(LogisticRegression(max_iter=1000), X, y, cv=5)
print(scores.round(3))
print(f'mean = {scores.mean():.3f}, std = {scores.std():.3f}')
▸ Gözlənilən nəticə
[0.967 1.    0.933 0.967 1.   ]
mean = 0.973, std = 0.025

Konveyer (Pipeline) hazırlıq addımlarını və modeli bir estimator-da birləşdirir. Çarpaz yoxlamada o, hər qatda miqyaslayıcını yalnız həmin qatın öyrədici hissəsi üzərində fit edir — test hissəsinin məlumatı modelə sızmır. Məsafəyə əsaslanan KNN üçün miqyaslama həlledicidir: şərab verilənlərində bir əlamət təxminən 11–15, digəri 278–1680 aralığındadır və ikinci əlamət məsafəni tam «udur».

Python
from sklearn.datasets import load_wine
from sklearn.model_selection import cross_val_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

X, y = load_wine(return_X_y=True)
print(X.shape, X.min(axis=0).round(1)[[0, 12]], X.max(axis=0).round(1)[[0, 12]])
raw = cross_val_score(KNeighborsClassifier(), X, y, cv=5).mean()
pipe = make_pipeline(StandardScaler(), KNeighborsClassifier())
scaled = cross_val_score(pipe, X, y, cv=5).mean()
print(f'without scaling: {raw:.3f}')
print(f'with scaling:    {scaled:.3f}')
print([name for name, _ in pipe.steps])
▸ Gözlənilən nəticə
(178, 13) [ 11. 278.] [  14.8 1680. ]
without scaling: 0.691
with scaling:    0.949
['standardscaler', 'kneighborsclassifier']
Tapşırıq

İris verilənlərini test_size=0.3, stratify=y, random_state=1 ilə böl. DecisionTreeClassifier(max_depth=3, random_state=0) modelini öyrət. Birinci sətirdə test dəqiqliyini (2 onluq rəqəmlə), sonra qarışıqlıq matrisini çap et.

Tapşırıq · Python
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

X, y = load_iris(return_X_y=True)
# split, train, predict, print accuracy and the confusion matrix
▸ Gözlənilən nəticə
0.98
[[15  0  0]
 [ 0 15  0]
 [ 0  1 14]]
Tapşırıq

Verilmiş həqiqi və proqnozlaşdırılan etiketlər üçün ayrı sətirlərdə accuracy, precision, recall və F1-i, hər birini 3 onluq rəqəmə qədər yuvarlaqlaşdıraraq çap et. Sonra əl ilə yoxla: TP, FP, FN neçədir?

Tapşırıq · Python
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score

y_true = [0, 1, 1, 0, 1, 0, 1, 1, 0, 0]
y_pred = [0, 1, 0, 0, 1, 1, 1, 0, 0, 0]
# print accuracy, precision, recall and F1 (3 decimals each)
▸ Gözlənilən nəticə
0.7
0.75
0.6
0.667

Əsas fikirlər

  • Bütün modellər eyni interfeysə malikdir: fit, predict, score; öyrənilmiş parametrlər _ ilə bitir.
  • train_test_split(..., random_state=..., stratify=y) təkrarlana bilən və balanslı bölgü verir.
  • Reqressiya: MSE, RMSE, R²; təsnifat: accuracy, precision, recall, F1 və qarışıqlıq matrisi.
  • Balanssız verilənlərdə dəqiqlik aldadıcıdır; öyrədici və test nəticələri arasında böyük fərq həddən artıq uyğunlaşmadır.
  • Çarpaz yoxlama daha etibarlı qiymət verir; konveyer hazırlığı hər qatda yalnız öyrədici hissədə öyrədərək sızmanın qarşısını alır.

Özünü yoxla

10 sual. Hər düzgün cavab XP qazandırır.

1 / 10
Modelin öyrədici dəqiqliyi 1,00, test dəqiqliyi 0,72-dir. Bu nə deməkdir?