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:
- 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).
- 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.



