Feature engineering grafika - adattisztítás Python kódokkal

5 Python script, ami rendbe teszi az alapokat

Nem a modell a leggyengébb láncszem. Hanem amit megetetsz vele. Ha azt hiszed, hogy a mesterséges intelligencia építése a bonyolult algoritmusok kiválasztásával kezdődik, tévúton jársz. A siker 80 százaléka ugyanis unalmasnak tűnő, de kritikus fontosságú „takarítás”. Ez a feature engineering.

Sokszor látom, hogy lelkes csapatok azonnal a legújabb neurális hálózatokat akarják ráereszteni a vállalati adatbázisra, aztán csodálkoznak, amikor a kimenet használhatatlan zagyvaság lesz. A garbage in, garbage out (szemét be, szemét ki) elv az MI világában hatványozottan igaz. A gépi tanulási modellek ugyanis nem rendelkeznek azzal a kontextuális tudással, amivel te. Nekik a számok csak számok. Ahhoz, hogy a modell „lássa” az összefüggéseket, az adatokat fogyaszthatóvá kell tenni számára.

Ebben a cikkben végigvesszük azt az öt Python alapú technikát, amivel a nyers, zajos adathalmazból precíz, tanításra kész alapanyagot gyúrhatsz. Nemcsak elméletben, kódszinten is.

Mi is az a Feature Engineering?

Mielőtt megnyitnánk a Jupyter Notebookot, tisztázzuk az alapokat, mert ezen áll vagy bukik a projekted megtérülése.

A mivagyunk.hu definíciója szerint: A Feature Engineering (jellemzők mérnöksége) az a folyamat, amely során a nyers adatokból olyan új változókat, azaz jellemzőket hozunk létre vagy alakítunk át, amelyek jobban tükrözik a megoldandó probléma szerkezetét, ezáltal javítják az MI-modellek pontosságát és tanulási hatékonyságát.

Ez nem egyszerű adminisztráció. Ez kreatív munka. Itt dől el, hogy az MI felismeri-e, hogy a „péntek este” és a „hétfő reggel” közötti vásárlói viselkedés nem csupán időbeli, hanem minőségi eltérés. Lássuk a gyakorlatban!

1. A hiányzó láncszemek: Mit kezdjünk a lyukas adatokkal?

A probléma

A valós életben az adatok sosem tökéletesek. Egy ügyfél nem adta meg az életkorát, a szenzor két percre kihagyott, vagy a CRM rendszer nem rögzítette a tranzakció helyét. A legrosszabb, amit tehetsz, hogy ezeket a sorokat gondolkodás nélkül törlöd (dropna), mert ezzel értékes információt veszíthetsz, sőt, torzíthatod a mintát. Ha például a tehetősebb vásárlók hajlamosabbak nem megadni a jövedelmüket, és te törlöd ezeket a sorokat, az MI-d „szegényebbnek” fogja látni a valóságot.

A megoldás: Imputálás

A hiányzó értékeket pótolni kell. A legegyszerűbb, ha az oszlop átlagával töltöd fel a lyukakat (SimpleImputer). De ha profi vagy, a KNN (K-Nearest Neighbors) módszert használod. Ez az eljárás megkeresi a hiányzó adathoz legjobban hasonlító többi adatsort (a „szomszédokat”), és azok alapján becsüli meg, mi lehet a hiányzó érték.

Python megvalósítás
import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer, KNNImputer

# Minta adat: Az egyik vásárlónál (Age, Salary) hiányzik az adat
data = pd.DataFrame({
    'Age': [25, 30, np.nan, 35, 28],
    'Salary': [50000, 60000, 58000, np.nan, 52000]
})

# 1. opció: A "lusta" megoldás (Átlaggal pótlás)
simple_imputer = SimpleImputer(strategy='mean')
print("Átlaggal pótolva:\n", simple_imputer.fit_transform(data))

# 2. opció: A profi megoldás (KNN)
# Ez a többi adat hasonlósága alapján következtet
knn_imputer = KNNImputer(n_neighbors=2)
data_knn = knn_imputer.fit_transform(data)

print("\nKNN (Szomszédság alapú) pótlás:\n", data_knn)

2. Hogyan érti meg a gép a „piros” színt? (Kategorikus kódolás)

A probléma

A gépi tanulási modellek, legyen szó egy egyszerű regresszióról vagy egy összetett XGBoostról, alapvetően matematikai műveleteket végeznek. A matematika pedig nem érti azt, hogy „Budapest”, „Debrecen” vagy „Pécs”. Számokat akar.

A megoldás: Encoding

Két fő iskolát különböztetünk meg, és kritikus, hogy mikor melyiket használod:

  1. Label Encoding: Minden kategóriához rendelünk egy számot (pl. Budapest=1, Debrecen=2). Veszélyes terep! A modell ugyanis azt hiheti, hogy Debrecen (2) „többet ér” vagy nagyobb, mint Budapest (1). Ezt csak sorrendiség esetén használd (pl. XS, S, M, L, XL méretek).
  2. One-Hot Encoding: Ez a biztonságosabb út a nominális (sorrend nélküli) adatoknál. Ilyenkor minden városnak külön oszlopot hozunk létre, ahol 1-es jelzi a jelenlétet, és 0 a hiányt.
Python megvalósítás
from sklearn.preprocessing import OneHotEncoder

# Kategorikus adatok: Városok
cities = pd.DataFrame({'City': ['Budapest', 'Debrecen', 'Pécs', 'Budapest']})

# One-Hot Encoding létrehozása
# A sparse_output=False miatt olvasható tömböt kapunk vissza
encoder = OneHotEncoder(sparse_output=False)
encoded_cities = encoder.fit_transform(cities[['City']])

# Visszaalakítjuk DataFrame-be, hogy lássuk az oszlopneveket
encoded_df = pd.DataFrame(encoded_cities, columns=encoder.get_feature_names_out(['City']))

print(encoded_df)
# Eredmény: Külön oszlopok (City_Budapest, City_Debrecen...), benne 1 és 0 értékekkel.

3. Almát a körtével: A skálázás művészete

A probléma

Képzeld el, hogy egy lakásárakat becslő MI-t építesz. Két bemenő adatod van. A lakás alapterülete (pl. 50-150 nm) és a szobák száma (1-5). Ha ezeket nyersen adod a modellnek, az algoritmus a négyzetmétert fogja dominánsnak tekinteni, egyszerűen azért, mert a számok nagyobbak. Pedig lehet, hogy a szobaszám sokkal fontosabb tényező az árképzésben.

A megoldás: Skálázás (Scaling)

Közös nevezőre kell hozni a változókat.

  • A Standardizálás (StandardScaler) során az adatokat úgy alakítod át, hogy az átlaguk 0, a szórásuk pedig 1 legyen. Ez akkor kiváló, ha az adataid eloszlása haranggörbét követ.
  • Ez elengedhetetlen a távolságalapú algoritmusoknál (pl. KNN, SVM, K-Means), ahol a távolság fogalma torzulna skálázás nélkül.
Python megvalósítás
from sklearn.preprocessing import StandardScaler

# Nagy eltérésű változók: Alapterület (nm) vs. Szobaszám
housing_data = pd.DataFrame({
    'Area': [50, 150, 80, 200], # Nagy számok
    'Rooms': [1, 5, 2, 6]       # Kicsi számok
})

scaler = StandardScaler()
scaled_data = scaler.fit_transform(housing_data)

print("Skálázott adatok:\n", scaled_data)
# Most már mindkét változó azonos nagyságrendben mozog (pl. -1.5 és +1.5 között)

4. A fekete bárányok kiszűrése (Outlier kezelés)

A probléma

Minden adatbázisban vannak kivételek. Egy banki tranzakciós listában a pár ezres tételek között felbukkanó százmilliós utalás, vagy egy hőmérő szenzor hibája miatt mért 500 fok. Ezeket hívjuk kiugró értékeknek, vagyis outliereknek. Ha ezek bent maradnak a tanító halmazban, elhúzzák a modell súlyozását, és az MI a kivételekre fog optimalizálni az általános szabályok helyett.

A megoldás: Z-score szűrés

A statisztikai alapú szűrés a legmegbízhatóbb. A Z-score megmutatja, hogy egy adatpont hány szórásnyira van az átlagtól. Az iparági ökölszabály szerint, ha egy érték abszolút értéke nagyobb mint 3 (tehát nagyon messze van az átlagtól), azt érdemes vagy törölni, vagy egy felső küszöbértékre korlátozni.

Python megvalósítás
from scipy import stats

# Adatsor egy kiugró értékkel (10000 - ez nyilvánvaló hiba vagy extrém eset)
df = pd.DataFrame({'Value': [10, 12, 11, 13, 10000, 10, 11]})

# Z-score kiszámítása minden sorra
z_scores = np.abs(stats.zscore(df))

# Csak azokat tartjuk meg, ahol a Z-score kisebb, mint 3
df_clean = df[(z_scores < 3).all(axis=1)]

print("Tisztított adat (10000 nélkül):\n", df_clean)

5. Az igazi varázslat: Feature Interaction

A probléma

Ez az a pont, ahol a data scientistből üzleti gondolkodó válik. A meglévő oszlopok tisztítása fontos, de az igazi érték gyakran a változók kombinálásában rejlik. Sokszor az összefüggés nem lineáris: nem egyszerűen „A” és „B” hat a kimenetre, hanem „A és B szorzata”.

A megoldás: Új változók generálása

Mondok egy példát. Van egy adatsorod a házakról, benne a „telek mérete” és a „ház alapterülete”. Önmagukban is hasznosak. De ha létrehozol egy új változót, mondjuk „beépítettségi arány” néven (ház területe / telek mérete), hirtelen egy sokkal erősebb indikátort kapsz a zsúfoltság mérésére. A PolynomialFeatures eszköz segít abban, hogy a változók szorzatait automatikusan legeneráld.

Python megvalósítás
from sklearn.preprocessing import PolynomialFeatures

# Eredeti változók: Hirdetési költség és Eladások száma
features = pd.DataFrame({
    'Ad_Spend': [100, 200, 300],
    'Sales': [10, 25, 40]
})

# Másodfokú interakciók generálása (pl. Ad_Spend^2 vagy Ad_Spend * Sales)
poly = PolynomialFeatures(degree=2, interaction_only=False, include_bias=False)
interactions = poly.fit_transform(features)

print("Interakciós jellemzők mátrixa:\n", interactions)
# Az új oszlopok segíthetnek a modellnek felismerni a nem-lineáris (gyorsuló) trendeket.

A Feature Engineering nem egyszeri munka

Ne feledd, a fenti öt lépés nem egy „check-list”, amit a projekt elején egyszer lefuttatsz, aztán elfelejtesz. Ez egy iteratív folyamat. Kísérletezned kell. Új jellemzőket létrehozni, tesztelni a hatásukat a modell pontosságára, majd finomítani.

A mivagyunk.hu-nál azt tapasztaljuk, hogy egy közepes algoritmus kiváló (jól előkészített) adatokkal szinte mindig megver egy csúcs algoritmust pocsék adatokkal. Építsd be ezeket a Python kódokat a pipeline-odba, és adj esélyt az MI-dnek, hogy valóban tanulni tudjon.

Kérjük, ellenőrizd a mező formátumát, és próbáld újra.
Köszönjük, hogy feliratkoztál.

vagyunk.hu hírlevél

Hozzászólás

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük