Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Qurilishi va ishlashi
- 2.2. Ustun tanlashning uch usuli
- 2.3. remainder
- 2.4. make_column_selector
- 2.5. get_feature_names_out va nomlar
- 2.6. Siyrak va zich chiqish
- 2.7. Tuzoqlar
- 2.8. Tayyorlashning markazi
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Uch usulda ustun tanlash
- Misol 2 — remainder va yo'qolgan ustunlar
- Misol 3 — To'liq tayyorlash markazi
- Misol 4 — Siyrak chiqish va xotira
- 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.3-dars: ColumnTransformer
19-QISM — SCIKIT-LEARN TO'LIQ · 3-dars
1. Kirish va motivatsiya
Real ma'lumot bir jinsli emas: sonli ustunlar masshtablashni, kategoriyali ustunlar kodlashni, matn ustunlari vektorizatsiyani, sanalar esa komponentlarga ajratishni talab qiladi. Pipeline esa butun matritsaga bitta transformer qo'llaydi.
ColumnTransformer aynan shu bo'shliqni to'ldiradi: u ustunlar guruhlariga turli transformerlarni parallel qo'llaydi va natijalarni birlashtiradi. Bu — real loyihadagi har qanday tayyorlash quvurining markazi.
Lekin u bir nechta nozik joyga ega: ustunlarni qanday tanlash (nom, indeks, tanlagich), tanlanmagan ustunlar bilan nima bo'ladi (remainder), chiqishdagi ustun nomlari qanday hosil bo'ladi, siyrak va zich matritsalar qanday birlashadi va ustunlar tartibi qanday o'zgaradi.
Bu darsda: qurilishi, ustun tanlash uch usuli, make_column_selector, remainder, get_feature_names_out, siyrak chiqish, ichma-ich quvurlar va verbose_feature_names_out.
Real vaziyat. Jamoa ColumnTransformer ni indekslar bilan qurdi: ("son", StandardScaler(), [0, 1, 2, 3]). Keyin ma'lumot manbaiga yangi ustun qo'shildi va u ikkinchi o'ringa tushdi. Kod xatosiz ishladi, lekin endi kategoriyali ustun masshtablanardi va sonli ustun kodlanardi. Xato ishlab chiqarishda uch hafta sezilmadi.
Bu darsda ColumnTransformer ni o'rganamiz.
Bu darsda:
- Ustun tanlashning uch usuli
- remainder
- make_column_selector
- get_feature_names_out
- Siyrak va zich chiqish
- Ichma-ich quvurlar
- Tuzoqlar
- Amaliy: tayyorlash markazi
ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14, sklearn 1.9, pandas 3).
2. Nazariya — chuqur tushuntirish
2.1. Qurilishi va ishlashi
ColumnTransformer([
("nom1", transformer1, ustunlar1),
("nom2", transformer2, ustunlar2),
], remainder="drop", verbose_feature_names_out=True)
ISHLASHI:
har (transformer, ustunlar) juftligi ALOHIDA fit qilinadi
natijalar GORIZONTAL birlashtiriladi (hstack)
tartib: transformerlar ro'yxatdagi tartibda, keyin remainder
DIQQAT: chiqish ustunlari tartibi KIRISH tartibiga MOS EMAS
u transformerlar ro'yxatiga bog'liqChiqish ustunlari tartibi transformerlar ro'yxatiga bog'liq, kirish DataFrame tartibiga emas.
2.2. Ustun tanlashning uch usuli
1. NOMLAR ro'yxati (ENG XAVFSIZ)
("son", StandardScaler(), ["yosh", "daromad"])
+ ustun joyi o'zgarsa ham ishlaydi
+ o'qishga tushunarli
2. INDEKSLAR ro'yxati (XAVFLI)
("son", StandardScaler(), [0, 1, 2])
- yangi ustun qo'shilsa JIM buziladi
- faqat numpy massivda oqlanadi
3. TANLAGICH (dinamik)
("son", StandardScaler(),
make_column_selector(dtype_include=np.number))
+ yangi sonli ustun avtomatik qo'shiladi
- qaysi ustun tushganini ko'rish qiyinroq
BITTA USTUN: ["yosh"] (ro'yxat) - "yosh" (satr) EMAS
satr bersangiz transformer 1D oladi va ko'pchiligi xato beradiNomlar ro'yxati — sukut tanlov; indekslar faqat numpy massiv bilan ishlaganda oqlanadi.
2.3. remainder
remainder="drop" (SUKUT)
ro'yxatda yo'q ustunlar TASHLANADI
xavfli: yangi ustun jim yo'qoladi
remainder="passthrough"
qolgan ustunlar O'ZGARTIRILMASDAN qo'shiladi
xavfli: kategoriyali ustun modelga xom holda tushishi mumkin
remainder=transformer
qolganlariga shu transformer qo'llanadi
masalan remainder=SimpleImputer(strategy="median")
TAVSIYA: ustunlarni ANIQ sanang va remainder="drop" qoldiring,
keyin get_feature_names_out bilan tekshiring remainder="drop" sukut — ro'yxatga kirmagan ustun jim yo'qoladi, shuning uchun chiqish nomlarini har doim tekshiring.
2.4. make_column_selector
from sklearn.compose import make_column_selector as tanla
tanla(dtype_include=np.number) # barcha sonli
tanla(dtype_include="str") # matn (pandas 3 da 'str' dtype)
tanla(dtype_exclude=np.number) # sonli bo'lmagan
tanla(pattern="^oy_") # nomi shablonga mos
DIQQAT (pandas 3):
dtype_include=object -> Pandas4Warning beradi
matn ustunlar uchun "str" yoki dtype_exclude=np.number ishlating
TANLAGICH CHAQIRILADI: tanlagich(df) -> ustun nomlari ro'yxati
fit paytida bajariladi, ya'ni DINAMIK pandas 3 da dtype_include=object ogohlantirish beradi — matn ustunlari uchun "str" yoki dtype_exclude=np.number ishlating.
2.5. get_feature_names_out va nomlar
verbose_feature_names_out=True (SUKUT)
chiqish nomlari: "transformer_nomi__asl_nom"
masalan: "son__yosh", "kat__hudud_shimol"
+ to'qnashuv bo'lmaydi
- nomlar uzun
verbose_feature_names_out=False
chiqish nomlari: "yosh", "hudud_shimol"
+ qisqa
- ikki transformer bir xil nom bersa XATO
TEKSHIRISH:
ct.get_feature_names_out() # barcha nomlar
ct.named_transformers_["kat"] # fit qilingan transformer
ct.output_indices_ # qaysi ustunlar qayerdan ct.output_indices_ har transformer chiqishdagi qaysi ustunlarni egallaganini ko'rsatadi — nosozlikni topishda juda foydali.
2.6. Siyrak va zich chiqish
sparse_threshold=0.3 (SUKUT)
agar siyrak ustunlar ulushi > 0.3 bo'lsa -> SIYRAK chiqish
MUAMMO:
HistGradientBoosting, ba'zi transformerlar siyrakni qabul qilmaydi
set_output("pandas") siyrak bilan ishlamaydi
YECHIMLAR:
OneHotEncoder(sparse_output=False) # eng oddiy
ColumnTransformer(..., sparse_threshold=0) # majburan zich
yoki modelga siyrakni qabul qiladiganini tanlang (LogisticRegression)
XOTIRA: 10 000 darajali kategoriya -> zich matritsa GB larni oladiMatn yoki ko'p darajali kategoriya bo'lsa siyrakni saqlang; zichga aylantirish xotirani portlatishi mumkin.
2.7. Tuzoqlar
Asosiy tuzoqlar: indeks bilan ustun tanlash; bitta ustunni satr sifatida berish; remainder ni unutish; chiqish nomlarini tekshirmaslik; pandas 3 da dtype_include=object; siyrak chiqishda set_output("pandas"); bir ustunni ikki transformerga berish (u ikki marta chiqadi); ColumnTransformer ichida fit_transform ni qo'lda chaqirish.
2.8. Tayyorlashning markazi
ColumnTransformer — har qanday jiddiy tayyorlash quvurining markazi. Ustunlarni nom bilan tanlang, remainder ni ongli qo'ying va get_feature_names_out() hamda output_indices_ bilan natijani tekshiring. Har bir ustun guruhi o'z ichki Pipeline iga ega bo'lishi mumkin — shunda imputatsiya, kodlash va masshtablash ham leakage dan himoyalangan bo'ladi.
3. Tez ma'lumotnoma
import numpy as np
from sklearn.compose import ColumnTransformer, make_column_selector
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
son_quvur = Pipeline([("imp", SimpleImputer(strategy="median")),
("sc", StandardScaler())])
kat_quvur = Pipeline([("imp", SimpleImputer(strategy="most_frequent")),
("oh", OneHotEncoder(handle_unknown="ignore",
sparse_output=False))])
ct = ColumnTransformer([
("son", son_quvur, make_column_selector(dtype_include=np.number)),
("kat", kat_quvur, make_column_selector(dtype_include="str")),
], remainder="drop", verbose_feature_names_out=True)
ct.fit(df)
ct.get_feature_names_out() · ct.output_indices_ · ct.named_transformers_["kat"]
QOIDA: nom bilan tanla · remainder ni ongli qo'y ·
nomlarni tekshir · siyrakni ongli boshqarColumnTransformer xulosasi
Ustun guruhlariga TURLI transformer
Tanlash: nomlar (xavfsiz) / indeks (xavfli) / tanlagich (dinamik)
remainder: drop (sukut) / passthrough / transformer
Nomlar: transformer__asl_nom
output_indices_: qaysi ustun qayerdan
sparse_threshold: siyrak yoki zich4. Batafsil misollar
Misollar real numpy/pandas/sklearn bilan (Python 3.14).
Misol 1 — Uch usulda ustun tanlash
"""Nom, indeks va tanlagich (real pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer, make_column_selector
from sklearn.preprocessing import OneHotEncoder, StandardScaler
def yarat(n: int = 200, seed: int = 0, yangi_ustun: bool = False):
rng = np.random.default_rng(seed)
ustunlar = {}
if yangi_ustun:
ustunlar["mijoz_id"] = rng.integers(1000, 9999, n).astype(float)
ustunlar.update({
"yosh": rng.integers(18, 70, n).astype(float),
"daromad": rng.lognormal(10, 0.5, n),
"hudud": rng.choice(["shimol", "janub"], n),
})
return pd.DataFrame(ustunlar)
def main() -> None:
df = yarat()
print("=== 1. Ma'lumot ===")
print(f" ustunlar: {list(df.columns)}")
print(f" turlari: {[str(t) for t in df.dtypes]}")
print("\n=== 2. Uch usul bir xil natija beradi ===")
variantlar = {
"nomlar": ColumnTransformer([
("son", StandardScaler(), ["yosh", "daromad"]),
("kat", OneHotEncoder(sparse_output=False), ["hudud"])]),
"indekslar": ColumnTransformer([
("son", StandardScaler(), [0, 1]),
("kat", OneHotEncoder(sparse_output=False), [2])]),
"tanlagich": ColumnTransformer([
("son", StandardScaler(),
make_column_selector(dtype_include=np.number)),
("kat", OneHotEncoder(sparse_output=False),
make_column_selector(dtype_include="str"))]),
}
print(f" {'usul':<12} {'shakl':>10} {'nomlar':<44}")
for nom, ct in variantlar.items():
chiqish = ct.fit_transform(df)
print(f" {nom:<12} {str(chiqish.shape):>10} "
f"{str(ct.get_feature_names_out().tolist()):<44}")
print("\n=== 3. Yangi ustun qo'shilganda ===")
df2 = yarat(yangi_ustun=True)
print(f" yangi ustunlar: {list(df2.columns)}")
print(f" {'usul':<12} {'shakl':>10} {'sonli qadamga tushgan ustunlar'}")
for nom, ct in variantlar.items():
yangi_ct = ColumnTransformer(ct.transformers)
chiqish = yangi_ct.fit_transform(df2)
nomlar = [n for n in yangi_ct.get_feature_names_out()
if n.startswith("son__")]
print(f" {nom:<12} {str(chiqish.shape):>10} {nomlar}")
print("\n=== 4. Nima bo'ldi ===")
print(" nomlar: o'sha ikkita ustun - TO'G'RI")
print(" indekslar: [0, 1] endi mijoz_id va yosh - JIM XATO")
print(" tanlagich: uchala sonli ustun - yangi ustun avtomatik")
print(" ⭐ Indeks bilan tanlash ustun qo'shilganda jim buziladi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumot ===
ustunlar: ['yosh', 'daromad', 'hudud']
turlari: ['float64', 'float64', 'str']
=== 2. Uch usul bir xil natija beradi ===
usul shakl nomlar
nomlar (200, 4) ['son__yosh', 'son__daromad', 'kat__hudud_janub', 'kat__hudud_shimol']
indekslar (200, 4) ['son__yosh', 'son__daromad', 'kat__hudud_janub', 'kat__hudud_shimol']
tanlagich (200, 4) ['son__yosh', 'son__daromad', 'kat__hudud_janub', 'kat__hudud_shimol']
=== 3. Yangi ustun qo'shilganda ===
yangi ustunlar: ['mijoz_id', 'yosh', 'daromad', 'hudud']
usul shakl sonli qadamga tushgan ustunlar
nomlar (200, 4) ['son__yosh', 'son__daromad']
indekslar (200, 202) ['son__mijoz_id', 'son__yosh']
tanlagich (200, 5) ['son__mijoz_id', 'son__yosh', 'son__daromad']
=== 4. Nima bo'ldi ===
nomlar: o'sha ikkita ustun - TO'G'RI
indekslar: [0, 1] endi mijoz_id va yosh - JIM XATO
tanlagich: uchala sonli ustun - yangi ustun avtomatik
⭐ Indeks bilan tanlash ustun qo'shilganda jim buziladiNima ko'rsatdi: 2.2-bo'lim.
Misol 2 — remainder va yo'qolgan ustunlar
"""Ro'yxatga kirmagan ustunlar taqdiri (real pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
def main() -> None:
rng = np.random.default_rng(0)
n = 300
df = pd.DataFrame({
"yosh": rng.integers(18, 70, n).astype(float),
"daromad": rng.lognormal(10, 0.5, n),
"ball": rng.normal(600, 80, n), # ro'yxatga KIRMAYDI
"hudud": rng.choice(["shimol", "janub"], n),
"tarif": rng.choice(["oddiy", "premium"], n), # KIRMAYDI
})
asos = [("son", StandardScaler(), ["yosh", "daromad"]),
("kat", OneHotEncoder(sparse_output=False), ["hudud"])]
print("=== 1. remainder='drop' (sukut) ===")
ct = ColumnTransformer(asos).fit(df)
print(f" kirish ustunlari: {len(df.columns)}")
print(f" chiqish ustunlari: {len(ct.get_feature_names_out())}")
print(f" nomlar: {ct.get_feature_names_out().tolist()}")
yoqolgan = set(df.columns) - {"yosh", "daromad", "hudud"}
print(f" JIM YO'QOLGAN: {sorted(yoqolgan)}")
print("\n=== 2. remainder='passthrough' ===")
ct2 = ColumnTransformer(asos, remainder="passthrough").fit(df)
print(f" chiqish ustunlari: {len(ct2.get_feature_names_out())}")
print(f" nomlar: {ct2.get_feature_names_out().tolist()}")
chiqish = ct2.transform(df)
print(f" chiqish dtype: {chiqish.dtype}")
print(" DIQQAT: 'tarif' matn holida qoldi -> model xato beradi")
print("\n=== 3. remainder=transformer ===")
ct3 = ColumnTransformer(
[("son", StandardScaler(), ["yosh", "daromad", "ball"]),
("kat", OneHotEncoder(sparse_output=False), ["hudud", "tarif"])],
remainder="drop").fit(df)
print(f" barcha ustun sanaldi: {len(ct3.get_feature_names_out())} ta")
print(f" nomlar: {ct3.get_feature_names_out().tolist()}")
print("\n=== 4. output_indices_ bilan tekshirish ===")
print(f" {'transformer':<14} {'chiqish ustunlari':>20}")
for nom, kesim in ct3.output_indices_.items():
if kesim.stop > kesim.start:
print(f" {nom:<14} {f'{kesim.start}..{kesim.stop - 1}':>20}")
print(f" named_transformers_ kalitlari: "
f"{list(ct3.named_transformers_)}")
oh = ct3.named_transformers_["kat"]
print(f" OneHotEncoder ko'rgan darajalar: "
f"{[c.tolist() for c in oh.categories_]}")
print(" ⭐ remainder='drop' sukut - ustunni jim yo'qotadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. remainder='drop' (sukut) ===
kirish ustunlari: 5
chiqish ustunlari: 4
nomlar: ['son__yosh', 'son__daromad', 'kat__hudud_janub', 'kat__hudud_shimol']
JIM YO'QOLGAN: ['ball', 'tarif']
=== 2. remainder='passthrough' ===
chiqish ustunlari: 6
nomlar: ['son__yosh', 'son__daromad', 'kat__hudud_janub', 'kat__hudud_shimol', 'remainder__ball', 'remainder__tarif']
chiqish dtype: object
DIQQAT: 'tarif' matn holida qoldi -> model xato beradi
=== 3. remainder=transformer ===
barcha ustun sanaldi: 7 ta
nomlar: ['son__yosh', 'son__daromad', 'son__ball', 'kat__hudud_janub', 'kat__hudud_shimol', 'kat__tarif_oddiy', 'kat__tarif_premium']
=== 4. output_indices_ bilan tekshirish ===
transformer chiqish ustunlari
son 0..2
kat 3..6
named_transformers_ kalitlari: ['son', 'kat']
OneHotEncoder ko'rgan darajalar: [['janub', 'shimol'], ['oddiy', 'premium']]
⭐ remainder='drop' sukut - ustunni jim yo'qotadiNima ko'rsatdi: 2.3, 2.5-bo'limlar.
Misol 3 — To'liq tayyorlash markazi
"""Har guruhga o'z quvuri (real pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer, make_column_selector
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
def yarat(n: int = 800, seed: int = 0) -> pd.DataFrame:
rng = np.random.default_rng(seed)
df = pd.DataFrame({
"yosh": rng.integers(18, 70, n).astype(float),
"daromad": rng.lognormal(10, 0.5, n),
"ball": rng.normal(600, 80, n),
"hudud": rng.choice(["shimol", "janub", "markaz"], n),
"tarif": rng.choice(["oddiy", "premium", "biznes"], n),
})
# yo'qolgan qiymatlar
for ustun, ulush in [("daromad", 0.12), ("ball", 0.07), ("tarif", 0.09)]:
idx = rng.choice(n, int(n * ulush), replace=False)
df.loc[idx, ustun] = None
return df
def main() -> None:
df = yarat()
kuch = (0.02 * df["yosh"].fillna(40)
+ 0.004 * df["ball"].fillna(600)
+ 1.2 * (df["tarif"].fillna("oddiy") == "biznes") - 3.4)
rng = np.random.default_rng(1)
y = (rng.random(len(df)) < 1 / (1 + np.exp(-kuch))).astype(int)
print("=== 1. Ma'lumot ===")
print(f" {len(df)} qator, {len(df.columns)} ustun")
print(f" {'ustun':<10} {'dtype':<10} {'yo_qolgan':>10}")
for ustun in df.columns:
print(f" {ustun:<10} {str(df[ustun].dtype):<10} "
f"{df[ustun].isna().sum():>10}")
print("\n=== 2. Har guruhga o'z quvuri ===")
son_quvur = Pipeline([("imp", SimpleImputer(strategy="median")),
("sc", StandardScaler())])
kat_quvur = Pipeline([("imp", SimpleImputer(strategy="most_frequent")),
("oh", OneHotEncoder(handle_unknown="ignore",
sparse_output=False))])
tayyor = ColumnTransformer([
("son", son_quvur, make_column_selector(dtype_include=np.number)),
("kat", kat_quvur, make_column_selector(dtype_include="str")),
])
tayyor.fit(df)
print(f" sonli ustunlar: "
f"{make_column_selector(dtype_include=np.number)(df)}")
print(f" matn ustunlar: "
f"{make_column_selector(dtype_include='str')(df)}")
print(f" chiqish: {tayyor.transform(df).shape}")
print("\n=== 3. Chiqish nomlari ===")
nomlar = tayyor.get_feature_names_out()
print(f" jami {len(nomlar)} ta:")
for i in range(0, len(nomlar), 4):
print(f" {nomlar[i:i + 4].tolist()}")
print(f" output_indices_:")
for nom, kesim in tayyor.output_indices_.items():
if kesim.stop > kesim.start:
print(f" {nom}: {kesim.start}..{kesim.stop - 1}")
print("\n=== 4. Ichki qadamlarga murojaat ===")
son_imp = tayyor.named_transformers_["son"].named_steps["imp"]
print(f" median qiymatlar: "
f"{np.round(son_imp.statistics_, 2).tolist()}")
kat_oh = tayyor.named_transformers_["kat"].named_steps["oh"]
print(f" kategoriyalar: {[c.tolist() for c in kat_oh.categories_]}")
print("\n=== 5. Modelga ulash ===")
quvur = Pipeline([("t", tayyor),
("m", LogisticRegression(max_iter=3000))])
cv = StratifiedKFold(5, shuffle=True, random_state=0)
b = cross_val_score(quvur, df, y, cv=cv, scoring="roc_auc")
print(f" CV ROC AUC: {b.mean():.4f} (+-{b.std():.4f})")
quvur.fit(df, y)
koef = quvur["m"].coef_[0]
tartib = np.argsort(-np.abs(koef))[:5]
print(f" {'eng kuchli belgi':<22} {'koeffitsiyent':>14}")
for i in tartib:
print(f" {nomlar[i]:<22} {koef[i]:>+14.4f}")
print(" ⭐ Har guruh o'z quvuriga ega - imputatsiya ham himoyalangan")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumot ===
800 qator, 5 ustun
ustun dtype yo_qolgan
yosh float64 0
daromad float64 96
ball float64 56
hudud str 0
tarif str 72
=== 2. Har guruhga o'z quvuri ===
sonli ustunlar: ['yosh', 'daromad', 'ball']
matn ustunlar: ['hudud', 'tarif']
chiqish: (800, 9)
=== 3. Chiqish nomlari ===
jami 9 ta:
['son__yosh', 'son__daromad', 'son__ball', 'kat__hudud_janub']
['kat__hudud_markaz', 'kat__hudud_shimol', 'kat__tarif_biznes', 'kat__tarif_oddiy']
['kat__tarif_premium']
output_indices_:
son: 0..2
kat: 3..8
=== 4. Ichki qadamlarga murojaat ===
median qiymatlar: [45.0, 21354.65, 598.27]
kategoriyalar: [['janub', 'markaz', 'shimol'], ['biznes', 'oddiy', 'premium']]
=== 5. Modelga ulash ===
CV ROC AUC: 0.6815 (+-0.0306)
eng kuchli belgi koeffitsiyent
kat__tarif_biznes +0.8884
kat__tarif_oddiy -0.5078
kat__tarif_premium -0.3795
son__ball +0.2708
son__yosh +0.2680
⭐ Har guruh o'z quvuriga ega - imputatsiya ham himoyalanganNima ko'rsatdi: 2.1, 2.4, 2.5-bo'limlar.
Misol 4 — Siyrak chiqish va xotira
"""sparse_threshold va xotira (real numpy/pandas/scipy/sklearn)."""
import numpy as np
import pandas as pd
from scipy import sparse
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
def yarat(n: int = 4000, darajalar: int = 400, seed: int = 0):
rng = np.random.default_rng(seed)
kod = rng.integers(0, darajalar, n)
df = pd.DataFrame({
"yosh": rng.integers(18, 70, n).astype(float),
"daromad": rng.lognormal(10, 0.5, n),
"mahsulot": [f"m{k}" for k in kod],
})
kuch = -1.2 + 0.02 * df["yosh"] + 1.1 * np.sin(kod * 0.7)
y = (rng.random(n) < 1 / (1 + np.exp(-kuch))).astype(int)
return df, y
def hajm_mb(matritsa) -> float:
if sparse.issparse(matritsa):
baytlar = (matritsa.data.nbytes + matritsa.indices.nbytes
+ matritsa.indptr.nbytes)
else:
baytlar = matritsa.nbytes
return baytlar / 1024 / 1024
def main() -> None:
df, y = yarat()
print("=== 1. Ma'lumot ===")
print(f" {len(df)} qator, mahsulot darajalari: "
f"{df['mahsulot'].nunique()}")
print("\n=== 2. sparse_threshold ta'siri ===")
print(f" {'sparse_threshold':>17} {'chiqish turi':<16} "
f"{'shakl':>14} {'hajm (MB)':>11}")
for chegara in [0.0, 0.3, 1.0]:
ct = ColumnTransformer([
("son", StandardScaler(), ["yosh", "daromad"]),
("kat", OneHotEncoder(handle_unknown="ignore"), ["mahsulot"])],
sparse_threshold=chegara)
chiqish = ct.fit_transform(df)
turi = "siyrak" if sparse.issparse(chiqish) else "zich"
print(f" {chegara:>17} {turi:<16} {str(chiqish.shape):>14} "
f"{hajm_mb(chiqish):>11.2f}")
print("\n=== 3. Siyraklik darajasi ===")
ct = ColumnTransformer([
("son", StandardScaler(), ["yosh", "daromad"]),
("kat", OneHotEncoder(handle_unknown="ignore"), ["mahsulot"])],
sparse_threshold=0.3)
siyrak = ct.fit_transform(df)
toldirilgan = siyrak.nnz / (siyrak.shape[0] * siyrak.shape[1])
print(f" nolmas elementlar ulushi: {toldirilgan:.4%}")
print(f" siyrak hajm: {hajm_mb(siyrak):.2f} MB")
print(f" zich hajm: "
f"{siyrak.shape[0] * siyrak.shape[1] * 8 / 1024 / 1024:.2f} MB")
print(f" tejash: "
f"{siyrak.shape[0] * siyrak.shape[1] * 8 / 1024 / 1024 / hajm_mb(siyrak):.0f}x")
print("\n=== 4. Model siyrakni qabul qiladimi ===")
cv = StratifiedKFold(4, shuffle=True, random_state=0)
variantlar = {
"siyrak + LogisticRegression": ColumnTransformer([
("son", StandardScaler(), ["yosh", "daromad"]),
("kat", OneHotEncoder(handle_unknown="ignore"), ["mahsulot"])],
sparse_threshold=0.3),
"zich + LogisticRegression": ColumnTransformer([
("son", StandardScaler(), ["yosh", "daromad"]),
("kat", OneHotEncoder(handle_unknown="ignore",
sparse_output=False), ["mahsulot"])],
sparse_threshold=0),
}
print(f" {'variant':<30} {'CV AUC':>9}")
for nom, tayyor in variantlar.items():
quvur = Pipeline([("t", tayyor),
("m", LogisticRegression(max_iter=1000))])
b = cross_val_score(quvur, df, y, cv=cv, scoring="roc_auc")
print(f" {nom:<30} {b.mean():>9.4f}")
print(" natija bir xil, lekin xotira sezilarli farq qiladi")
print(" ⭐ Ko'p darajali kategoriyada siyrakni saqlang")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumot ===
4000 qator, mahsulot darajalari: 400
=== 2. sparse_threshold ta'siri ===
sparse_threshold chiqish turi shakl hajm (MB)
0.0 zich (4000, 402) 12.27
0.3 siyrak (4000, 402) 0.15
1.0 siyrak (4000, 402) 0.15
=== 3. Siyraklik darajasi ===
nolmas elementlar ulushi: 0.7463%
siyrak hajm: 0.15 MB
zich hajm: 12.27 MB
tejash: 80x
=== 4. Model siyrakni qabul qiladimi ===
variant CV AUC
siyrak + LogisticRegression 0.6605
zich + LogisticRegression 0.6605
natija bir xil, lekin xotira sezilarli farq qiladi
⭐ Ko'p darajali kategoriyada siyrakni saqlangNima ko'rsatdi: 2.6-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Indeks bilan tanlash qulay" | Ustun qo'shilsa jim buziladi |
| "Bitta ustun uchun satr yetarli" | Ro'yxat kerak: ["yosh"] |
"remainder sukut bo'yicha saqlaydi" |
"drop" — tashlaydi |
| "Chiqish tartibi kirish tartibi bilan bir xil" | Transformerlar tartibida |
"object dtype tanlagichi ishlaydi" |
pandas 3 da ogohlantirish |
| "Siyrakni har doim zichga aylantirish kerak" | Xotira portlashi mumkin |
| "Nomlarni tekshirish shart emas" | Asosiy diagnostika |
| "Bir ustunni ikki transformerga berish mumkin" | Ikki marta chiqadi |
6. Keng tarqalgan xatolar va yechimlari
1. Indeks bilan tanlash
("son", StandardScaler(), [0, 1, 2]) # ⚠️
("son", StandardScaler(), ["yosh", "daromad", "ball"]) # ✅2. Bitta ustun satr sifatida
("kat", OneHotEncoder(), "hudud") # 1D -> xato # ⚠️
("kat", OneHotEncoder(), ["hudud"]) # ✅3. remainder ni unutish
ColumnTransformer([...]) # qolgan ustunlar yo'qoladi # ⚠️
# barcha ustunni sanang yoki remainder ni ongli tanlang # ✅4. pandas 3 da object
make_column_selector(dtype_include=object) # ogohlantirish # ⚠️
make_column_selector(dtype_include="str") # ✅5. Siyrakda set_output("pandas")
OneHotEncoder(); ct.set_output(transform="pandas") # xato # ⚠️
OneHotEncoder(sparse_output=False) # ✅6. Nomlarni tekshirmaslik
quvur.fit(df, y) # nima bo'lganini bilmaymiz # ⚠️
print(tayyor.get_feature_names_out(), tayyor.output_indices_) # ✅7. Imputatsiyani tashqarida qilish
df = df.fillna(df.median()); ct.fit(df) # leakage # ⚠️
Pipeline([("imp", SimpleImputer()), ("sc", StandardScaler())]) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 17.9-dars (o'tilgan): Pipeline va leakage
- 19.2-dars (o'tilgan): Pipeline chuqur
- 19.4-dars: O'z transformeringiz
- 19.9-dars: Tezlik va xotira
- 19.10-dars: To'liq loyiha
8. Eng yaxshi amaliyotlar
Ustunlarni nom bilan tanlang.
Bitta ustun ham ro'yxatda.
remainderni ongli qo'ying.get_feature_names_out()ni tekshiring.output_indices_bilan joylashuvni ko'ring.Har guruhga o'z
Pipelinei.Siyraklikni ongli boshqaring.
pandas 3 da
"str"tanlagichi.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # ColumnTransformer nima qiladi?
2. # ustun tanlashning uch usuli?
3. # eng xavfsizi qaysi?
4. # bitta ustun qanday beriladi?
5. # remainder sukut qiymati?
6. # chiqish tartibi nimaga bog'liq?
7. # nomlar qanday hosil bo'ladi?
8. # output_indices_ nima?
9. # sparse_threshold nima qiladi?
10. # pandas 3 da matn tanlagichi?
11. # named_transformers_ nima?
12. # bir ustun ikki transformerda bo'lsa?Javoblar
- Ustun guruhlariga turli transformer
- Nomlar, indekslar, tanlagich
- Nomlar
- Ro'yxatda:
["yosh"] "drop"- Transformerlar ro'yxatiga
transformer__asl_nom- Qaysi chiqish ustuni qaysi transformerdan
- Siyrak/zich chiqishni tanlaydi
dtype_include="str"- Fit qilingan transformerlar lug'ati
- Ikki marta chiqadi
Vazifa 2: Xatolarni tuzating
1. ("son", StandardScaler(), [0, 1, 2])
2. ("kat", OneHotEncoder(), "hudud")
3. make_column_selector(dtype_include=object)
4. OneHotEncoder(); ct.set_output(transform="pandas")
5. df = df.fillna(df.median()); ct.fit(df)Javoblar
1. ("son", StandardScaler(), ["yosh", "daromad", "ball"])
2. ("kat", OneHotEncoder(), ["hudud"])
3. make_column_selector(dtype_include="str")
4. OneHotEncoder(sparse_output=False)
5. Pipeline([("imp", SimpleImputer()), ("sc", StandardScaler())])Vazifa 3: Tanlash
Modellang:
- Ma'lumot
- Uch usul
- Yangi ustun
- Xulosa
Vazifa 4: remainder
Modellang:
droppassthrough- To'liq sanash
output_indices_
Vazifa 5: Markaz
Modellang:
- Ma'lumot
- Guruh quvurlari
- Nomlar
- Ichki qadamlar
Vazifa 6: Siyraklik
Modellang:
- Ma'lumot
sparse_threshold- Siyraklik
- Model
Vazifa 7: O'ylash
ColumnTransformer ni make_column_selector(dtype_include=np.number) bilan qurdingiz. Ma'lumotda mijoz_id ustuni bor va u ham sonli. Model CV da 0.99 beradi. Nima bo'lgan va qanday tuzatasiz?
Javob
Qisqa javob: mijoz_id identifikator, lekin tanlagich uni oddiy sonli belgi deb qabul qilgan. Model mijozlarni yodlab olgan — bu leakage yoki (guruh tuzilmasi bo'lsa) guruh leakage i.
1. Nima uchun sodir bo'ldi
make_column_selector(dtype_include=np.number) dtype ga qaraydi, ma'noga emas. Identifikatorlar, kodlar, telefon raqamlari, pochta indekslari — hammasi sonli dtype ga ega bo'lishi mumkin.
2. Qanday aniqlash
# 1. tanlagich nimani tanlaganini ChOP ETING
print(make_column_selector(dtype_include=np.number)(df))
# 2. har belgining YAKKA CV bahosi
for ustun in sonli_ustunlar:
b = cross_val_score(model, df[[ustun]], y, cv=cv, scoring="roc_auc")
if b.mean() > 0.85:
print("SHUBHALI:", ustun, round(b.mean(), 4))
# 3. noyob qiymatlar ulushi
print((df[sonli].nunique() / len(df)).sort_values(ascending=False))nunique / n nisbati 1 ga yaqin bo'lgan sonli ustun — deyarli har doim identifikator.
3. Uchta yechim
a) Aniq ro'yxat (eng ishonchli)
SONLI = ["yosh", "daromad", "ball"]
KATEGORIYA = ["hudud", "tarif"]
ct = ColumnTransformer([("son", son_quvur, SONLI),
("kat", kat_quvur, KATEGORIYA)])b) Tanlagichdan keyin chiqarib tashlash
def sonli_tanla(df):
ustunlar = make_column_selector(dtype_include=np.number)(df)
return [u for u in ustunlar if u not in TASHLANADIGANLAR]c) Identifikatorni X ga umuman kiritmaslik
guruh = df["mijoz_id"].to_numpy() # GroupKFold uchun
X = df.drop(columns=["mijoz_id"]) # modelga kirmaydi4. Qo'shimcha: guruh tuzilmasi
Agar bir mijozning bir necha qatori bo'lsa, mijoz_id ni olib tashlash yetarli emas — GroupKFold(groups=mijoz_id) ham kerak (18.2-dars), aks holda boshqa belgilar orqali ham leakage qoladi.
5. Umumiy qoida
Dinamik tanlagichlar qulay, lekin ular ma'noni bilmaydi. Ishlab chiqarish quvurida aniq ro'yxat afzal: u hujjat vazifasini ham bajaradi va yangi ustun jim qo'shilib qolmaydi.
6. Xulosa
- Tanlagich natijasini chop eting
- Yakka CV bahosi bilan shubhalilarni toping
- Ishlab chiqarishda aniq ro'yxat
- Identifikatorni
Xdan chiqarib,groupsga bering
Nimani mustahkamlaydi: 2.2, 2.4-bo'limlar.
Xulosa
Bu darsda ColumnTransformer ni o'rgandik.
Eng muhim uch fikr:
Ustunlarni nom bilan tanlang. Indekslar (
[0, 1, 2]) ma'lumot manbaiga yangi ustun qo'shilganda jim buziladi va xato oylar davomida sezilmasligi mumkin. Dinamik tanlagichlar (make_column_selector) qulay, lekin ular dtype ga qaraydi, ma'noga emas — shuning uchun identifikatorlar ham sonli belgi sifatida tushib qolishi mumkin.remaindersukut bo'yicha"drop". Ro'yxatga kirmagan har qanday ustun jim yo'qoladi. Shuning uchunfitdan keyinget_feature_names_out()vaoutput_indices_ni chop eting: bu kutilgan ustunlar borligini va ular qayerga tushganini bir qarashda ko'rsatadi.Har ustun guruhiga o'z
Pipelinei. Imputatsiya, kodlash va masshtablashColumnTransformerichidagiPipelineda bo'lsa, ular ham leakage dan himoyalangan bo'ladi. Siyraklikni esa ongli boshqaring: ko'p darajali kategoriyadasparse_output=Falsexotirani portlatishi mumkin.
Keyingi darsda o'z transformeringizni yozamiz: BaseEstimator va TransformerMixin, get_feature_names_out, check_estimator bilan tekshirish va keng tarqalgan xatolar.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!