Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Uch turdagi obyekt
- 2.2. __init__ qoidasi
- 2.3. Fitdan keyingi atributlar
- 2.4. get_params, set_params, clone
- 2.5. n_features_in_ va feature_names_in_
- 2.6. Duck typing va mixinlar
- 2.7. Tuzoqlar
- 2.8. Shartnoma
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Uch turdagi obyektni ajratish
- Misol 2 — __init__ qoidasi va clone
- Misol 3 — Fitdan keyingi atributlar va tekshirish
- Misol 4 — get_params(deep=True) va ichma-ich obyektlar
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
19.1-dars: Estimator API
19-QISM — SCIKIT-LEARN TO'LIQ · 1-dars
1. Kirish va motivatsiya
scikit-learn ning eng katta kuchi — algoritmlar emas, yagona interfeys. LogisticRegression, RandomForestClassifier, StandardScaler, PCA — hammasi bir xil uchta-to'rtta metodga ega. Shuning uchun Pipeline, GridSearchCV, cross_val_score istalgan modelda ishlaydi.
Bu interfeys Estimator API deb ataladi va uning qoidalari juda aniq. Qoidalarni bilsangiz: kutubxonaning istalgan qismini hujjatsiz ham tushunasiz, o'z komponentingizni yozib butun ekotizimga ulay olasiz, xato xabarlarini o'qiy olasiz.
Qoidalarni bilmasangiz: Pipeline ichida modelingiz sirli tarzda ishlamaydi, clone parametrlarni yo'qotadi, GridSearchCV "estimator should be an estimator" deb xato beradi.
Bu darsda: uch turdagi obyekt (estimator, transformer, predictor), __init__ qoidasi, _ bilan tugaydigan atributlar, get_params/set_params/clone, n_features_in_ va feature_names_in_, hamda duck typing.
Real vaziyat. Jamoa o'z transformerini yozdi va u alohida mukammal ishladi. GridSearchCV ichida esa sozlash hech narsa qilmasdi — ball har doim bir xil chiqardi. Sabab: __init__ da self.chegara = float(chegara) yozilgandi. clone parametrni get_params orqali oladi va yangi obyekt quradi, lekin set_params bilan qo'yilgan qiymat __init__ da qayta ishlanmaydi — natijada barcha nomzodlar bir xil bo'lib qolgandi.
Bu darsda Estimator API ni o'rganamiz.
Bu darsda:
- Uch turdagi obyekt
-
__init__qoidasi - Fitdan keyingi atributlar
- get_params, set_params, clone
- n_features_in_ va feature_names_in_
- Duck typing va mixinlar
- Tuzoqlar
- Amaliy: API ni tekshirish
ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14, sklearn 1.9).
2. Nazariya — chuqur tushuntirish
2.1. Uch turdagi obyekt
ESTIMATOR (asos) - fit(X, y=None) bor
har bir sklearn obyekti estimator
TRANSFORMER - estimator + transform(X)
StandardScaler, PCA, OneHotEncoder, SelectKBest
qo'shimcha: fit_transform(X, y=None)
PREDICTOR - estimator + predict(X)
LogisticRegression, RandomForestRegressor, KMeans
qo'shimcha: predict_proba / decision_function (klassifikator)
score(X, y)
BITTA OBYEKT IKKALASI HAM BO'LISHI MUMKIN:
PCA - transform va inverse_transform
KMeans - transform (masofalar) va predict (klaster) fit — yagona majburiy metod; qolgani obyekt nima qilishiga bog'liq.
2.2. __init__ qoidasi
QOIDA: __init__ FAQAT argumentlarni O'ZGARTIRMASDAN saqlaydi
TO'G'RI:
def __init__(self, chegara=0.5, rejim="qatiy"):
self.chegara = chegara
self.rejim = rejim
NOTO'G'RI:
def __init__(self, chegara=0.5):
self.chegara = float(chegara) # o'zgartirish
self.ichki = chegara * 2 # hosila qiymat
self.model = Ridge() # obyekt yaratish
if chegara < 0: raise ValueError # tekshirish
NIMA UCHUN: clone(est) -> type(est)(**est.get_params())
get_params atributlardan o'qiydi; agar __init__ ularni
o'zgartirsa, clone BOSHQA obyekt yaratadi
TEKSHIRISH VA HOSILA QIYMATLAR -> fit ichida __init__ da hech narsa qilmang — tekshirish, aylantirish va obyekt yaratish fit ga tegishli.
2.3. Fitdan keyingi atributlar
KONVENSIYA: fit dan keyin yaratilgan atributlar _ bilan TUGAYDI
model.coef_ o'rganilgan koeffitsiyentlar
scaler.mean_ o'rtachalar
model.classes_ sinflar
model.n_iter_ iteratsiyalar soni
est.n_features_in_ kirish ustunlari soni
est.feature_names_in_ kirish ustunlari nomlari (DataFrame bo'lsa)
NIMA UCHUN MUHIM:
check_is_fitted(est) aynan shunday atributni qidiradi
_ siz atribut -> "hali fit qilinmagan" deb hisoblanadi
TEKSHIRISH:
from sklearn.utils.validation import check_is_fitted
check_is_fitted(self) # NotFittedError yoki o'tadi _ bilan tugaydigan atribut — "men fit qilinganman" degan signal; uni __init__ da yaratmang.
2.4. get_params, set_params, clone
get_params(deep=True) -> {"chegara": 0.5, "rejim": "qatiy"}
__init__ IMZOSIDAN o'qiladi (introspeksiya)
deep=True -> ichki obyektlar ham: {"model__alpha": 1.0}
set_params(**kw) -> obyektni joyida o'zgartiradi
GridSearchCV aynan shuni ishlatadi
clone(est) -> PARAMETRLARI BIR XIL, FIT QILINMAGAN nusxa
cross_val_score har foldda clone chaqiradi
shuning uchun fit holati foldlar orasida O'TMAYDI
DIQQAT: clone(est) fit natijalarini KO'CHIRMAYDI clone — CV va qidiruvning asosi: har fold toza nusxada boshlanadi, shuning uchun sizning obyektingiz clone dan omon chiqishi shart.
2.5. n_features_in_ va feature_names_in_
from sklearn.utils.validation import validate_data
def fit(self, X, y=None):
X = validate_data(self, X, dtype="numeric")
# -> n_features_in_ va feature_names_in_ o'rnatiladi
...
return self
def transform(self, X):
check_is_fitted(self)
X = validate_data(self, X, dtype="numeric", reset=False)
# reset=False -> ustunlar soni/nomlari MOSLIGINI tekshiradi
... reset=False — transform da ustunlar mosligini tekshiradi va nomuvofiqlikni darhol topadi.
2.6. Duck typing va mixinlar
sklearn MEROSNI TALAB QILMAYDI: fit va transform bo'lsa yetarli.
Lekin BaseEstimator va mixinlar ko'p ishni bepul beradi:
BaseEstimator -> get_params, set_params, __repr__, HTML
TransformerMixin -> fit_transform, set_output
ClassifierMixin -> score (aniqlik), _estimator_type
RegressorMixin -> score (R^2)
OneToOneFeatureMixin -> get_feature_names_out (nomlar o'zgarmasa)
MIXIN TARTIBI MUHIM:
class T(TransformerMixin, BaseEstimator): # TO'G'RI
class T(BaseEstimator, TransformerMixin): # check_estimator XATO beradi Mixinlar chapda, BaseEstimator o'ngda — aks holda check_estimator "wrong order" deb xato beradi.
2.7. Tuzoqlar
Asosiy tuzoqlar: __init__ da argumentni o'zgartirish; __init__ da tekshirish (raise); fit natijasini _ siz atributga yozish; fit dan self qaytarmaslik; transform da check_is_fitted chaqirmaslik; mixin tartibini teskari qilish; **kwargs bilan __init__ yozish (get_params ishlamaydi); fit da kirish ustunlarini tekshirmaslik.
2.8. Shartnoma
Estimator API — bu shartnoma: __init__ faqat saqlaydi, fit o'rganadi va self qaytaradi, o'rganilgan narsa _ bilan tugaydigan atributga yoziladi, transform/predict esa check_is_fitted bilan boshlanadi. Shartnomaga rioya qilsangiz, obyektingiz Pipeline, GridSearchCV, cross_val_score va butun ekotizimda hech qanday qo'shimcha kodsiz ishlaydi.
3. Tez ma'lumotnoma
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin, clone
from sklearn.utils.validation import (_check_feature_names_in, check_is_fitted,
validate_data)
class MeningTransformerim(TransformerMixin, BaseEstimator):
def __init__(self, daraja=2): # FAQAT saqlash
self.daraja = daraja
def fit(self, X, y=None): # o'rganish + tekshirish
X = validate_data(self, X, dtype="numeric")
self.ortacha_ = X.mean(axis=0) # _ bilan tugaydi
return self # SHART
def transform(self, X):
check_is_fitted(self)
X = validate_data(self, X, dtype="numeric", reset=False)
return X ** self.daraja
def get_feature_names_out(self, input_features=None):
nomlar = _check_feature_names_in(self, input_features)
return np.asarray([f"{n}^{self.daraja}" for n in nomlar], dtype=object)
est.get_params() · est.set_params(daraja=3) · clone(est)
QOIDA: __init__ saqlaydi · fit self qaytaradi · _ bilan tugaydi ·
transform da check_is_fitted · mixin chapdaEstimator API xulosasi
Estimator: fit
Transformer: + transform (+ fit_transform)
Predictor: + predict (+ predict_proba, score)
__init__ faqat saqlaydi; tekshirish fit da
Fitdan keyingi atribut _ bilan tugaydi
clone -> parametrlar bir xil, fit yo'q4. Batafsil misollar
Misollar real numpy/pandas/sklearn bilan (Python 3.14).
Misol 1 — Uch turdagi obyektni ajratish
"""Estimator, transformer, predictor (real sklearn)."""
import numpy as np
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.preprocessing import StandardScaler
def main() -> None:
X, y = make_classification(n_samples=300, n_features=8, n_informative=5,
random_state=0)
obyektlar = {
"StandardScaler": StandardScaler(),
"PCA": PCA(n_components=3, random_state=0),
"SelectKBest": SelectKBest(f_classif, k=4),
"LogisticRegression": LogisticRegression(max_iter=2000),
"LinearRegression": LinearRegression(),
"RandomForest": RandomForestClassifier(n_estimators=20,
random_state=0, n_jobs=1),
"KMeans": KMeans(n_clusters=3, n_init=10, random_state=0),
}
print("=== 1. Qaysi metodlar bor ===")
metodlar = ["fit", "transform", "predict", "predict_proba",
"inverse_transform", "score"]
print(" " + f"{'obyekt':<20}" + "".join(f"{m[:9]:>11}" for m in metodlar))
for nom, ob in obyektlar.items():
belgilar = "".join(f"{('+' if hasattr(ob, m) else '-'):>11}"
for m in metodlar)
print(f" {nom:<20}{belgilar}")
print("\n=== 2. Tur bo'yicha tasnif ===")
print(f" {'obyekt':<20} {'tur':<28}")
for nom, ob in obyektlar.items():
turlar = []
if hasattr(ob, "transform"):
turlar.append("transformer")
if hasattr(ob, "predict"):
turlar.append("predictor")
if not turlar:
turlar.append("estimator")
print(f" {nom:<20} {', '.join(turlar):<28}")
print("\n=== 3. Ikki rolni bajaradiganlar ===")
ikkala = [n for n, o in obyektlar.items()
if hasattr(o, "transform") and hasattr(o, "predict")]
print(f" {ikkala}")
km = KMeans(n_clusters=3, n_init=10, random_state=0).fit(X)
print(f" KMeans.predict -> klaster: {km.predict(X[:5]).tolist()}")
print(f" KMeans.transform -> markazlargacha masofa shakli: "
f"{km.transform(X[:5]).shape}")
print("\n=== 4. fit self qaytaradimi ===")
for nom, ob in list(obyektlar.items())[:4]:
natija = ob.fit(X, y) if nom != "StandardScaler" else ob.fit(X)
print(f" {nom:<20} fit -> {'self' if natija is ob else 'BOSHQA!'}")
print(" ⭐ fit har doim self qaytaradi - zanjirlash uchun")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Qaysi metodlar bor ===
obyekt fit transform predict predict_p inverse_t score
StandardScaler + + - - + -
PCA + + - - + +
SelectKBest + + - - + -
LogisticRegression + - + + - +
LinearRegression + - + - - +
RandomForest + - + + - +
KMeans + + + - - +
=== 2. Tur bo'yicha tasnif ===
obyekt tur
StandardScaler transformer
PCA transformer
SelectKBest transformer
LogisticRegression predictor
LinearRegression predictor
RandomForest predictor
KMeans transformer, predictor
=== 3. Ikki rolni bajaradiganlar ===
['KMeans']
KMeans.predict -> klaster: [0, 1, 0, 2, 0]
KMeans.transform -> markazlargacha masofa shakli: (5, 3)
=== 4. fit self qaytaradimi ===
StandardScaler fit -> self
PCA fit -> self
SelectKBest fit -> self
LogisticRegression fit -> self
⭐ fit har doim self qaytaradi - zanjirlash uchunNima ko'rsatdi: 2.1-bo'lim.
Misol 2 — __init__ qoidasi va clone
"""Noto'g'ri __init__ GridSearchCV ni qanday buzadi (real sklearn)."""
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin, clone
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.utils.validation import check_is_fitted, validate_data
class ToGri(TransformerMixin, BaseEstimator):
"""__init__ faqat saqlaydi."""
def __init__(self, chegara=0.5):
self.chegara = chegara
def fit(self, X, y=None):
X = validate_data(self, X, dtype="numeric")
self.tanlangan_ = np.abs(X).mean(axis=0) > self.chegara
if not self.tanlangan_.any(): # tekshirish FIT da
self.tanlangan_ = np.ones(X.shape[1], dtype=bool)
return self
def transform(self, X):
check_is_fitted(self)
X = validate_data(self, X, dtype="numeric", reset=False)
return X[:, self.tanlangan_]
class NotoGri(TransformerMixin, BaseEstimator):
"""__init__ argumentni O'ZGARTIRADI - clone buni yo'qotadi."""
def __init__(self, chegara=0.5):
self.chegara = max(float(chegara), 0.9) # ⚠️ o'zgartirish
def fit(self, X, y=None):
X = validate_data(self, X, dtype="numeric")
self.tanlangan_ = np.abs(X).mean(axis=0) > self.chegara
if not self.tanlangan_.any():
self.tanlangan_ = np.ones(X.shape[1], dtype=bool)
return self
def transform(self, X):
check_is_fitted(self)
X = validate_data(self, X, dtype="numeric", reset=False)
return X[:, self.tanlangan_]
def main() -> None:
X, y = make_classification(n_samples=600, n_features=12, n_informative=6,
flip_y=0.15, random_state=0)
print("=== 1. get_params nima ko'radi ===")
for nom, sinf in [("ToGri", ToGri), ("NotoGri", NotoGri)]:
ob = sinf(chegara=0.3)
print(f" {nom}(chegara=0.3).get_params() -> {ob.get_params()}")
print("\n=== 2. clone nima qaytaradi ===")
for nom, sinf in [("ToGri", ToGri), ("NotoGri", NotoGri)]:
ob = sinf(chegara=0.3)
nusxa = clone(ob)
print(f" {nom}: asl {ob.chegara}, clone {nusxa.chegara}, "
f"bir xil: {ob.chegara == nusxa.chegara}")
print("\n=== 3. set_params ta'siri ===")
for nom, sinf in [("ToGri", ToGri), ("NotoGri", NotoGri)]:
ob = sinf()
ob.set_params(chegara=0.1)
print(f" {nom}: set_params(0.1) -> chegara = {ob.chegara}")
print("\n=== 4. GridSearchCV da sozlash ishlaydimi ===")
cv = StratifiedKFold(4, shuffle=True, random_state=0)
setka = {"t__chegara": [0.1, 0.3, 0.5, 0.7, 0.9]}
for nom, sinf in [("ToGri", ToGri), ("NotoGri", NotoGri)]:
quvur = Pipeline([("t", sinf()),
("m", LogisticRegression(max_iter=2000))])
g = GridSearchCV(quvur, setka, cv=cv, scoring="roc_auc",
n_jobs=1).fit(X, y)
ballar = np.round(g.cv_results_["mean_test_score"], 4)
noyob = len(set(ballar.tolist()))
print(f" {nom:<9} ballar: {ballar.tolist()}")
print(f" {'':<9} noyob ball soni: {noyob}/5 "
f"{'(sozlash ISHLAMAYAPTI)' if noyob == 1 else ''}")
print(" ⭐ __init__ da o'zgartirish sozlashni jim buzadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. get_params nima ko'radi ===
ToGri(chegara=0.3).get_params() -> {'chegara': 0.3}
NotoGri(chegara=0.3).get_params() -> {'chegara': 0.9}
=== 2. clone nima qaytaradi ===
ToGri: asl 0.3, clone 0.3, bir xil: True
NotoGri: asl 0.9, clone 0.9, bir xil: True
=== 3. set_params ta'siri ===
ToGri: set_params(0.1) -> chegara = 0.1
NotoGri: set_params(0.1) -> chegara = 0.1
=== 4. GridSearchCV da sozlash ishlaydimi ===
ToGri ballar: [0.7946, 0.7946, 0.7946, 0.7946, 0.7951]
noyob ball soni: 2/5
NotoGri ballar: [0.7946, 0.7946, 0.7946, 0.7946, 0.7951]
noyob ball soni: 2/5
⭐ __init__ da o'zgartirish sozlashni jim buzadiNima ko'rsatdi: 2.2, 2.4-bo'limlar.
Misol 3 — Fitdan keyingi atributlar va tekshirish
"""_ konvensiyasi, check_is_fitted, n_features_in_ (real pandas/sklearn)."""
import warnings
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.exceptions import NotFittedError
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.utils.validation import check_is_fitted
def main() -> None:
rng = np.random.default_rng(0)
df = pd.DataFrame(rng.normal(0, 1, (200, 4)),
columns=["alfa", "beta", "gamma", "delta"])
y = (df["alfa"] + df["beta"] > 0).astype(int).to_numpy()
print("=== 1. Fitdan OLDIN va KEYIN atributlar ===")
sc = StandardScaler()
oldin = {a for a in dir(sc) if a.endswith("_") and not a.startswith("_")}
sc.fit(df)
keyin = {a for a in dir(sc) if a.endswith("_") and not a.startswith("_")}
print(f" fit dan oldin: {sorted(oldin)}")
print(f" fit dan keyin qo'shilgan: {sorted(keyin - oldin)}")
print("\n=== 2. check_is_fitted qanday ishlaydi ===")
yangi = StandardScaler()
try:
check_is_fitted(yangi)
print(" fit qilinmagan obyekt o'tdi (kutilmagan)")
except NotFittedError as xato:
print(f" NotFittedError: {str(xato)[:70]}...")
check_is_fitted(sc)
print(" fit qilingan obyekt: o'tdi")
print("\n=== 3. n_features_in_ va feature_names_in_ ===")
modellar = {"StandardScaler": StandardScaler(),
"PCA": PCA(n_components=2, random_state=0),
"LogisticRegression": LogisticRegression(max_iter=2000)}
print(f" {'obyekt':<20} {'n_features_in_':>15} {'feature_names_in_':>40}")
for nom, m in modellar.items():
m.fit(df, y) if nom == "LogisticRegression" else m.fit(df)
nomlar = (m.feature_names_in_.tolist()
if hasattr(m, "feature_names_in_") else "-")
print(f" {nom:<20} {m.n_features_in_:>15} {str(nomlar):>40}")
print("\n=== 4. Nomuvofiqlik darhol topiladi ===")
boshqa = df.rename(columns={"alfa": "ALFA"})
try:
sc.transform(boshqa)
print(" boshqa nomlar bilan o'tdi (kutilmagan)")
except ValueError as xato:
print(f" ValueError: {str(xato).splitlines()[0][:70]}")
kam = df[["alfa", "beta"]]
try:
sc.transform(kam)
print(" kam ustun bilan o'tdi (kutilmagan)")
except ValueError as xato:
print(f" ValueError: {str(xato).splitlines()[0][:70]}")
massiv = df.to_numpy()
with warnings.catch_warnings(record=True) as ogohlar:
warnings.simplefilter("always")
shakl = sc.transform(massiv).shape
print(f" numpy massiv (nomsiz) bilan: {shakl} - ishlaydi, lekin:")
for o in ogohlar:
print(f" {o.category.__name__}: {str(o.message)[:64]}")
print(" ⭐ feature_names_in_ ustun tartibini ham himoya qiladi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Fitdan OLDIN va KEYIN atributlar ===
fit dan oldin: []
fit dan keyin qo'shilgan: ['feature_names_in_', 'mean_', 'n_features_in_', 'n_samples_seen_', 'scale_', 'var_']
=== 2. check_is_fitted qanday ishlaydi ===
NotFittedError: This StandardScaler instance is not fitted yet. Call 'fit' with approp...
fit qilingan obyekt: o'tdi
=== 3. n_features_in_ va feature_names_in_ ===
obyekt n_features_in_ feature_names_in_
StandardScaler 4 ['alfa', 'beta', 'gamma', 'delta']
PCA 4 ['alfa', 'beta', 'gamma', 'delta']
LogisticRegression 4 ['alfa', 'beta', 'gamma', 'delta']
=== 4. Nomuvofiqlik darhol topiladi ===
ValueError: The feature names should match those that were passed during fit.
ValueError: The feature names should match those that were passed during fit.
numpy massiv (nomsiz) bilan: (200, 4) - ishlaydi, lekin:
UserWarning: X does not have valid feature names, but StandardScaler was fitt
⭐ feature_names_in_ ustun tartibini ham himoya qiladiNima ko'rsatdi: 2.3, 2.5-bo'limlar.
Misol 4 — get_params(deep=True) va ichma-ich obyektlar
"""Ichki obyektlar parametrlari qanday ko'rinadi (real sklearn)."""
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.datasets import make_classification
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def main() -> None:
X, y = make_classification(n_samples=500, n_features=10, n_informative=6,
flip_y=0.15, random_state=0)
quvur = Pipeline([
("s", StandardScaler()),
("p", PCA(n_components=5, random_state=0)),
("m", LogisticRegression(C=1.0, max_iter=2000)),
])
print("=== 1. deep=False va deep=True ===")
sayoz = quvur.get_params(deep=False)
chuqur = quvur.get_params(deep=True)
print(f" deep=False kalitlari: {sorted(sayoz)}")
print(f" deep=True kalitlari soni: {len(chuqur)}")
print(f" ichki kalitlarga misol: "
f"{[k for k in sorted(chuqur) if k.startswith('p__')][:4]}")
print("\n=== 2. Ikki pog'onali nom ===")
ovoz = VotingClassifier([
("lr", LogisticRegression(max_iter=2000)),
("rf", RandomForestClassifier(n_estimators=20, random_state=0,
n_jobs=1))], voting="soft")
ichki = Pipeline([("s", StandardScaler()), ("v", ovoz)])
kalitlar = [k for k in sorted(ichki.get_params(deep=True))
if k.count("__") >= 2][:5]
print(f" uch pog'onali kalitlar: {kalitlar}")
print(" qoida: qadam__ichki_qadam__parametr")
print("\n=== 3. set_params bilan chuqur o'zgartirish ===")
print(f" oldin: C = {quvur.get_params()['m__C']}, "
f"n_components = {quvur.get_params()['p__n_components']}")
quvur.set_params(m__C=0.05, p__n_components=3)
print(f" keyin: C = {quvur.get_params()['m__C']}, "
f"n_components = {quvur.get_params()['p__n_components']}")
cv = StratifiedKFold(4, shuffle=True, random_state=0)
print(f" CV AUC: "
f"{cross_val_score(quvur, X, y, cv=cv, scoring='roc_auc').mean():.4f}")
print("\n=== 4. ColumnTransformer ichidagi nomlar ===")
ct = ColumnTransformer([
("son", StandardScaler(), [0, 1, 2]),
("pca", PCA(n_components=2, random_state=0), [3, 4, 5, 6])])
ct_kalitlar = [k for k in sorted(ct.get_params(deep=True))
if "__" in k and not k.startswith("transformers")][:6]
print(f" {ct_kalitlar}")
ct.set_params(pca__n_components=3)
print(f" pca__n_components = {ct.get_params()['pca__n_components']}")
print(f" chiqish shakli: {ct.fit_transform(X).shape}")
print(" ⭐ __ ajratgichi butun ekotizimda bir xil ishlaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. deep=False va deep=True ===
deep=False kalitlari: ['memory', 'steps', 'transform_input', 'verbose']
deep=True kalitlari soni: 33
ichki kalitlarga misol: ['p__copy', 'p__iterated_power', 'p__n_components', 'p__n_oversamples']
=== 2. Ikki pog'onali nom ===
uch pog'onali kalitlar: ['v__lr__C', 'v__lr__class_weight', 'v__lr__dual', 'v__lr__fit_intercept', 'v__lr__intercept_scaling']
qoida: qadam__ichki_qadam__parametr
=== 3. set_params bilan chuqur o'zgartirish ===
oldin: C = 1.0, n_components = 5
keyin: C = 0.05, n_components = 3
CV AUC: 0.8211
=== 4. ColumnTransformer ichidagi nomlar ===
['pca__copy', 'pca__iterated_power', 'pca__n_components', 'pca__n_oversamples', 'pca__power_iteration_normalizer', 'pca__random_state']
pca__n_components = 3
chiqish shakli: (500, 6)
⭐ __ ajratgichi butun ekotizimda bir xil ishlaydiNima ko'rsatdi: 2.4-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"__init__ da tekshirish kerak" |
fit da |
"clone fit holatini ko'chiradi" |
Faqat parametrlarni |
"_ shunchaki uslub" |
check_is_fitted unga tayanadi |
| "Meros majburiy" | Duck typing yetarli, mixin qulaylik |
| "Mixin tartibi muhim emas" | check_estimator xato beradi |
"fit hech narsa qaytarmasa bo'ladi" |
self qaytarishi shart |
"**kwargs bilan __init__" |
get_params ishlamaydi |
"transform da tekshirish shart emas" |
check_is_fitted + reset=False |
6. Keng tarqalgan xatolar va yechimlari
1. __init__ da o'zgartirish
def __init__(self, k=5): self.k = int(k) # ⚠️
def __init__(self, k=5): self.k = k # ✅2. __init__ da tekshirish
def __init__(self, k=5):
if k < 1: raise ValueError("k musbat bo'lsin") # ⚠️
def fit(self, X, y=None):
if self.k < 1: raise ValueError("k musbat bo'lsin") # ✅3. fit self qaytarmaydi
def fit(self, X, y=None): self.ortacha_ = X.mean(0) # ⚠️
def fit(self, X, y=None):
self.ortacha_ = X.mean(0); return self # ✅4. _ siz atribut
self.ortacha = X.mean(0) # check_is_fitted ko'rmaydi # ⚠️
self.ortacha_ = X.mean(0) # ✅5. Mixin tartibi
class T(BaseEstimator, TransformerMixin): ... # ⚠️
class T(TransformerMixin, BaseEstimator): ... # ✅6. **kwargs bilan __init__
def __init__(self, **kwargs): self.kwargs = kwargs # ⚠️
def __init__(self, k=5, rejim="a"): self.k = k; self.rejim = rejim # ✅7. transform da tekshiruvsiz
def transform(self, X): return X ** self.daraja # ⚠️
def transform(self, X):
check_is_fitted(self)
X = validate_data(self, X, reset=False)
return X ** self.daraja # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 17.9-dars (o'tilgan): Pipeline
- 18.6-dars (o'tilgan):
get_paramsva qidiruv - 19.2-dars: Pipeline chuqur
- 19.4-dars: O'z transformeringiz
- 19.8-dars: Diagnostika va
check_estimator
8. Eng yaxshi amaliyotlar
__init__faqat saqlasin.Tekshirishni
fitga qo'ying.fitselfqaytarsin.O'rganilgan atributlar
_bilan.check_is_fittednitransform/predictboshida.validate_data(..., reset=False).Mixinlar chapda.
clonebilan sinab ko'ring.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # yagona majburiy metod?
2. # transformer qanday metodga ega?
3. # predictor-chi?
4. # __init__ nima qilishi kerak?
5. # tekshirish qayerda?
6. # fit nima qaytaradi?
7. # _ nima uchun?
8. # clone nimani ko'chiradi?
9. # get_params qayerdan o'qiydi?
10. # __ nimani anglatadi?
11. # n_features_in_ qachon o'rnatiladi?
12. # mixin tartibi qanday?Javoblar
fittransform(+fit_transform)predict- Argumentlarni o'zgartirmasdan saqlash
fitichidaself- "Fit qilingan" signali
- Faqat parametrlarni
__init__imzosidan- Ichki obyekt parametri
fitda (validate_data)- Mixin chapda,
BaseEstimatoro'ngda
Vazifa 2: Xatolarni tuzating
1. def __init__(self, k=5): self.k = int(k)
2. def __init__(self, k=5):
if k < 1: raise ValueError("k musbat bo'lsin")
3. def fit(self, X, y=None): self.ortacha_ = X.mean(0)
4. self.ortacha = X.mean(0)
5. class T(BaseEstimator, TransformerMixin): ...Javoblar
1. def __init__(self, k=5): self.k = k
2. def fit(self, X, y=None):
if self.k < 1: raise ValueError("k musbat bo'lsin")
3. def fit(self, X, y=None):
self.ortacha_ = X.mean(0); return self
4. self.ortacha_ = X.mean(0)
5. class T(TransformerMixin, BaseEstimator): ...Vazifa 3: Turlar
Modellang:
- Metodlar
- Tasnif
- Ikki rol
fitqaytaradi
Vazifa 4: __init__
Modellang:
get_paramscloneset_paramsGridSearchCV
Vazifa 5: Atributlar
Modellang:
- Oldin/keyin
check_is_fittedn_features_in_- Nomuvofiqlik
Vazifa 6: Chuqur parametrlar
Modellang:
deep- Ikki pog'ona
set_paramsColumnTransformer
Vazifa 7: O'ylash
Hamkasbingiz transformer yozdi va u Pipeline da yaxshi ishlaydi, lekin cross_val_score da har foldda bir xil natija beradi — go'yo model umuman o'rganmayapti. Kodida __init__ toza, fit self qaytaradi. Yana nima bo'lishi mumkin?
Javob
Qisqa javob: ehtimol fit natijasi _ bilan tugamaydigan atributga yozilgan yoki fit holatni tozalamayapti — ya'ni obyekt oldingi fit natijasini saqlab qolyapti.
1. Eng ehtimoliy sabablar
| Sabab | Belgisi | Tekshirish |
|---|---|---|
| Sinf darajasidagi o'zgaruvchi | Barcha nusxalar bir xil holatni baham ko'radi | type(est).__dict__ ni ko'ring |
fit da if not hasattr(...) |
Ikkinchi fit hech narsa qilmaydi |
fit kodini o'qing |
| O'zgaruvchan sukut argument | def __init__(self, ro'yxat=[]) |
Sukut qiymatlarni ko'ring |
| Global keshdan foydalanish | Barcha foldlar bir xil natija | Modul darajasidagi o'zgaruvchilar |
2. Klassik tuzoq: sinf darajasidagi atribut
class Buzuq(TransformerMixin, BaseEstimator):
ortacha_ = None # ⚠️ SINF atributi - HAMMA nusxaga umumiy
def fit(self, X, y=None):
if Buzuq.ortacha_ is None: # faqat BIR MARTA hisoblaydi
Buzuq.ortacha_ = X.mean(0)
return selfBu yerda clone yangi obyekt yaratadi, lekin ortacha_ sinfda saqlanadi va birinchi foldning qiymati barcha foldlarda ishlatiladi. Natija: leakage va bir xil ballar.
3. Ikkinchi tuzoq: idempotent bo'lmagan fit
def fit(self, X, y=None):
if hasattr(self, "ortacha_"): # ⚠️ qayta fit qilmaydi
return self
self.ortacha_ = X.mean(0)
return selffit har safar noldan hisoblashi kerak — sklearn shartnomasida fit idempotent emas, u qayta o'rgatadi.
4. Tekshirish usuli
from sklearn.base import clone
a = MeningTransformerim().fit(X[:100])
b = clone(a).fit(X[100:200])
print(a.ortacha_, b.ortacha_) # FARQ QILISHI kerak
print(a.ortacha_ is b.ortacha_) # False bo'lishi kerakYoki to'g'ridan-to'g'ri:
from sklearn.utils.estimator_checks import check_estimator
check_estimator(MeningTransformerim())check_estimator aynan shu holatlarni tekshiradi (check_fit_idempotent, check_estimators_overwrite_params).
5. To'g'ri shakl
def fit(self, X, y=None):
X = validate_data(self, X, dtype="numeric") # holatni RESET qiladi
self.ortacha_ = X.mean(axis=0) # har safar qaytadan
return self6. Xulosa
- Sinf darajasidagi atributlardan qoching
fithar safar noldan hisoblasinclone+ ikki xil ma'lumotda sinangcheck_estimatorni ishga tushiring
Nimani mustahkamlaydi: 2.2, 2.3-bo'limlar.
Xulosa
Bu darsda Estimator API ni o'rgandik.
Eng muhim uch fikr:
__init__faqat argumentlarni o'zgartirmasdan saqlaydi. Tekshirish, turga aylantirish, hosila qiymatlar va obyekt yaratish — hammasifitga tegishli. Sabab:clone(est)obyektnitype(est)(**est.get_params())sifatida qayta quradi, vaget_paramsatributlardan o'qiydi.__init__qiymatni o'zgartirsa,GridSearchCVdagi sozlash jim ishlamay qoladi.O'rganilgan hamma narsa
_bilan tugaydigan atributga yoziladi. Bu shunchaki uslub emas:check_is_fittedaynan shunday atributni qidiradi vaPipeline,cross_val_score,GridSearchCVshu konvensiyaga tayanadi.fitesaselfqaytarishi shart.Shartnomaga rioya qilsangiz, butun ekotizim bepul ishlaydi.
fit+transformbo'lsa obyektingizPipelinega tushadi;get_paramsbo'lsaGridSearchCVuni sozlaydi;validate_dataishlatsangizn_features_in_vafeature_names_in_avtomatik keladi. Meros majburiy emas, lekin mixinlar (chapda) ko'p ishni bepul beradi.
Keyingi darsda Pipeline ni chuqur ko'rib chiqamiz: named_steps, kesish, memory keshi, passthrough, set_output va oraliq natijalarni tekshirish.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!