데이터 전처리의 중요성
Il 기능 엔지니어링 그리고 데이터 전처리 이것이 가장 중요한 단계입니다 모든 머신러닝 프로젝트의 기록되지 않은 규칙에 따르면 데이터 과학자의 시간은 80%입니다. 데이터 준비에 소요되며 모델링에는 20%만 소요됩니다. 얼마나 정교한지는 중요하지 않습니다. 알고리즘: 입력 데이터가 더럽거나 불완전하거나 제대로 표현되지 않은 경우 모델은 출력합니다. 결과가 좋지 않습니다. 쓰레기는 들어가고, 쓰레기는 나온다.
전처리는 원시 데이터를 알고리즘에 적합한 형식으로 변환합니다. 기능 엔지니어링은 다음을 넘어선다. 도메인 지식을 사용하여 기존 변수에서 새로운 변수를 생성합니다. 알고리즘만으로는 찾을 수 없는 관계. 이러한 단계가 함께 성공을 결정합니다. 또는 ML 프로젝트의 실패.
이 기사에서 배울 내용
- 누락된 값을 처리하는 기술
- 범주형 변수의 인코딩
- 수치 특성의 스케일링 및 정규화
- 이상치 감지 및 관리
- 도메인 지식으로 새로운 기능 만들기
- scikit-learn을 사용한 전처리 파이프라인
누락된 값 처리
실제 데이터에는 거의 항상 다음이 포함됩니다. 누락된 값 (NaN, 널). 주요 전략 세 가지가 있습니다: 제거 (결측값이 너무 많은 행이나 열 제거) 통계적 대치 (평균, 중앙값 또는 최빈값으로 대체) e 예측 대치 (모델을 사용하여 결측값을 예측합니다.) 선택은 누락된 데이터의 양에 따라 달라집니다. 그리고 누락된 패턴(무작위 또는 체계적)을 기준으로 합니다.
import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer, KNNImputer
# Dataset con valori mancanti
data = pd.DataFrame({
'eta': [25, 30, np.nan, 45, 35, np.nan, 28, 50],
'reddito': [30000, np.nan, 45000, 60000, np.nan, 55000, 32000, 70000],
'categoria': ['A', 'B', 'A', np.nan, 'B', 'A', 'B', 'A'],
'target': [0, 1, 0, 1, 1, 0, 1, 0]
})
print("Valori mancanti per colonna:")
print(data.isnull().sum())
print(f"\nPercentuale mancanti:\n{(data.isnull().mean() * 100).round(1)}")
# Strategia 1: Imputazione con media/mediana
imputer_mean = SimpleImputer(strategy='mean')
data['eta_imputed'] = imputer_mean.fit_transform(data[['eta']])
imputer_median = SimpleImputer(strategy='median')
data['reddito_imputed'] = imputer_median.fit_transform(data[['reddito']])
# Strategia 2: Imputazione con KNN (usa i vicini)
knn_imputer = KNNImputer(n_neighbors=3)
numeric_cols = data[['eta', 'reddito']].values
imputed_knn = knn_imputer.fit_transform(numeric_cols)
# Strategia 3: Imputazione categoriche con moda
imputer_mode = SimpleImputer(strategy='most_frequent')
data['categoria_imputed'] = imputer_mode.fit_transform(data[['categoria']])
print("\nDopo imputazione:")
print(data[['eta_imputed', 'reddito_imputed', 'categoria_imputed']].head())
범주형 변수의 인코딩
ML 알고리즘은 문자열이 아닌 숫자로 작동합니다. 범주형 변수를 변환해야 합니다. 숫자 형식으로. 그만큼 라벨 인코딩 각 범주에 정수를 할당합니다(A=0, B=1, C=2). 간단하지만 존재하지 않는 주문을 도입합니다. 그만큼 원-핫 인코딩 이진 열을 생성합니다 각 범주에 대해: 순서를 도입하지는 않지만 범주가 높은 많은 열을 생성할 수 있습니다. 카디널리티. 그만큼 대상 인코딩 각 범주를 목표 평균으로 대체합니다. 해당 카테고리의 경우: 강력하지만 과적합에 위험합니다.
from sklearn.preprocessing import (
LabelEncoder, OneHotEncoder, OrdinalEncoder,
StandardScaler, MinMaxScaler, RobustScaler
)
from sklearn.compose import ColumnTransformer
import pandas as pd
import numpy as np
# Dataset di esempio
df = pd.DataFrame({
'colore': ['rosso', 'blu', 'verde', 'rosso', 'blu'],
'taglia': ['S', 'M', 'L', 'XL', 'M'],
'prezzo': [10.5, 25.0, 45.0, 80.0, 22.0],
'peso': [100, 500, 1200, 3000, 450]
})
# One-Hot per colore (nominale, no ordine)
ohe = OneHotEncoder(sparse_output=False, drop='first')
colore_encoded = ohe.fit_transform(df[['colore']])
print(f"One-Hot colore:\n{colore_encoded}")
# Ordinal per taglia (ordinale, ha un ordine)
oe = OrdinalEncoder(categories=[['S', 'M', 'L', 'XL']])
taglia_encoded = oe.fit_transform(df[['taglia']])
print(f"\nOrdinal taglia: {taglia_encoded.flatten()}")
# --- SCALING ---
# StandardScaler: media=0, std=1 (per distribuzioni normali)
ss = StandardScaler()
prezzo_standard = ss.fit_transform(df[['prezzo']])
# MinMaxScaler: range [0,1] (per distribuzioni non normali)
mms = MinMaxScaler()
prezzo_minmax = mms.fit_transform(df[['prezzo']])
# RobustScaler: usa mediana e IQR (robusto a outlier)
rs = RobustScaler()
peso_robust = rs.fit_transform(df[['peso']])
print(f"\nStandard: {prezzo_standard.flatten().round(2)}")
print(f"MinMax: {prezzo_minmax.flatten().round(2)}")
print(f"Robust: {peso_robust.flatten().round(2)}")
이상치 감지
그만큼 특이치 이는 나머지 데이터에서 크게 벗어나는 이상치입니다. 측정 오류, 손상된 데이터 또는 실제 극단값일 수 있습니다. 방법 IQR(사분위수간 범위) 1분위수 또는 3분위수에서 IQR의 1.5배를 초과하는 지점으로 이상값을 식별합니다. 방법 Z-점수 임계값(일반적으로 3)보다 높은 표준화된 값이 있는 지점을 식별합니다. 그만큼'고립된 숲 의사결정 트리를 사용하여 이상값을 격리하는 ML 접근 방식입니다. 무작위.
기능 선택
모든 기능이 모델에 긍정적으로 기여하는 것은 아닙니다. 관련성이 없거나 중복되는 기능은 성능이 저하되고 훈련 속도가 느려집니다. 거기 기능 선택 그들을 식별합니다 더 유익한 변수. 방법은 다음과 같습니다. 상관관계 (기능을 매우 제거 서로 관련되어 있음), 변동 임계값 (낮은 분산 기능 제거), SelectKBest (통계 테스트에 따라 최상의 K 선택) 및 특징 중요도 랜덤 포레스트 제작.
scikit-learn을 사용한 전처리 파이프라인
Le 파이프라인 scikit-learn은 전처리 및 모델링 단계를 하나로 연결합니다. 개체. 이는 다음을 방지합니다. 데이터 유출 (테스트 세트의 정보가 훈련) 교차 검증 및 배포를 단순화합니다. 그만큼 컬럼변환기 허용한다 다른 열에 다른 변환을 적용합니다.
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
import pandas as pd
import numpy as np
# Dataset realistico
np.random.seed(42)
n = 200
df = pd.DataFrame({
'eta': np.random.randint(18, 70, n).astype(float),
'reddito': np.random.normal(40000, 15000, n),
'esperienza': np.random.randint(0, 30, n).astype(float),
'citta': np.random.choice(['Milano', 'Roma', 'Napoli', 'Torino'], n),
'titolo_studio': np.random.choice(['Diploma', 'Laurea', 'Master'], n),
'target': np.random.randint(0, 2, n)
})
# Inserire valori mancanti random
for col in ['eta', 'reddito', 'esperienza']:
mask = np.random.random(n) < 0.1
df.loc[mask, col] = np.nan
# Definire colonne per tipo
numeric_features = ['eta', 'reddito', 'esperienza']
categorical_features = ['citta', 'titolo_studio']
# Preprocessing per numeriche: imputa + scala
numeric_transformer = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
# Preprocessing per categoriche: imputa + one-hot
categorical_transformer = Pipeline([
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(drop='first', handle_unknown='ignore'))
])
# ColumnTransformer combina tutto
preprocessor = ColumnTransformer(transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
# Pipeline completa: preprocessing + modello
full_pipeline = Pipeline([
('preprocessor', preprocessor),
('classifier', RandomForestClassifier(n_estimators=100, random_state=42))
])
# Cross-validation (il preprocessing avviene DENTRO ogni fold)
X = df.drop('target', axis=1)
y = df['target']
scores = cross_val_score(full_pipeline, X, y, cv=5, scoring='accuracy')
print(f"Accuracy: {scores.mean():.3f} (+/- {scores.std():.3f})")
누출 날짜: 전처리(스케일링, 대치)가 발생해야 합니다. 후에 는 훈련/테스트 분할은 이전에는 없었습니다. 전체 데이터세트로 확장하면 테스트 세트가 스케일러 매개변수에 영향을 미칩니다. scikit-learn 파이프라인은 fit_transform을 다음 항목에만 적용하여 이 문제를 자동으로 방지합니다. 훈련 세트를 만들고 테스트 세트를 변환합니다.
핵심 사항
- 전처리는 가장 중요한 단계입니다. 시간의 80%가 데이터 준비에 소요됩니다.
- 누락된 값: 상황에 따른 제거, 통계적 또는 예측적 대치
- 인코딩: 명목의 경우 One-Hot, 서수의 경우 서수, 대상 인코딩에는 주의가 필요합니다.
- 스케일링: 정규 분포의 경우 StandardScaler, 이상값이 있는 RobustScaler
- Pipeline + ColumnTransformer로 데이터 유출 방지 및 코드 단순화
- 도메인 지식을 사용한 기능 엔지니어링은 알고리즘 선택보다 더 큰 차이를 만드는 경우가 많습니다.







