fit,predict,scoreinterfeysi 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.
| Sinif | Tapşırıq | İdeya |
|---|---|---|
LinearRegression | reqressiya | ŷ = w · x + b, kvadratik xətaların minimumu |
LogisticRegression | təsnifat | xətti ifadə sigmoid (softmax) ilə ehtimala çevrilir |
DecisionTreeClassifier | təsnifat | «bəli / xeyr» suallar ağacı |
KNeighborsClassifier | təsnifat | ən yaxın k qonşunun səsverməsi |
StandardScaler | transformer | hə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.
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]
- 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.
- σ(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
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]]
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.
- 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ı
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ərHəllini gizlət
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.
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:
- 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ı
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
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ərHəllini gizlət
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.
- kqatların sayı, adətən 5 və ya 10
- scoreᵢi-ci qat test olanda alınan nəticə
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».
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']
İ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.
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]]
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?
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.