
AI한테 맡기기 전에 이것부터 알고 시작하자!!
요새 ChatGPT나 Claude한테 "이 데이터 분석 좀 해줘~" 하면 뚝딱뚝딱 코드 짜주잖아요? 근데 진짜 문제는 그 코드를 그냥 돌렸다가는 마음에 안드는 결과가 나온다는 거예요 ㅠㅠ
저도 처음에는 생성형 AI한테 의존하다가 삼일동안 디버깅만 했던 기억이... 결국 깨달은 건 데이터의 특징을 먼저 파악하고 그걸 코드에 반영해야 한다는 거였어요. 알고리즘만 믿다가는 큰코다친다는 얘기죠!
이번 글에서는 머신러닝 모델을 활용해서 데이터 분석할 때 코드 짤 때 주의해야 할 점들을 정리해봤습니다. 특히 실무에서 자주 마주치는 함정들 위주로 다뤄볼게요 ^_^
1. 편차가 큰 놈이 더 큰 영향을 준다? - 데이터 스케일링의 비밀
왜 스케일링이 필요한가
데이터를 보면 어떤 피처는 0~1 사이 값인데 어떤 피처는 1000~ 10000 사이 값이잖아요? 이럴 때 스케일이 큰 피처가 모델한테 더 큰 영향을 줄 수 있어요. 예를 들어 집값 예측 모델에서 방 개수(1~5)와 가격(수억 원)을 같이 쓰면, 가격이 압도적으로 큰 영향을 주게 되는 거죠.
그래서 단순히 알고리즘만 의존하면 안 되고, df.describe()를 보고 "아 이게 더 많이 영향 줄 수 있으니 스케일링을 해야겠다"라고 판단할 수 있어야 해요!
언제 스케일링을 해야 하나?
| 알고리즘 | 스케일링 필요 여부 | 이유 |
|---|---|---|
| SVM, KNN, 선형회귀, 로지스틱회귀 | ✅ 필요 | 거리 기반 또는 경사하강법 사용 |
| 딥러닝 모델 | ✅ 필요 | 경사하강법 최적화 |
| 트리 기반 모델 (Decision Tree, Random Forest, XGBoost) |
❌ 불필요 | 데이터의 상대적 순서만 중요 |
주요 스케일링 기법
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
# 1. StandardScaler: 평균=0, 분산=1 (정규분포 가정)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_train)
# 2. MinMaxScaler: 0~1 사이로 변환
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X_train)
# 3. RobustScaler: 이상치에 강함 (중앙값 기준)
scaler = RobustScaler()
X_scaled = scaler.fit_transform(X_train)
⚠️ 주의사항:
- 학습 데이터로
fit()한 스케일러를 테스트 데이터에도 동일하게 적용해야 해요! - 테스트 데이터에 다시
fit()하면 데이터 누수(Data Leakage) 발생!
# ❌ 잘못된 예시
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
scaler.fit(X_test) # 이러면 안됨!
X_test_scaled = scaler.transform(X_test)
# ✅ 올바른 예시
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test) # 학습 데이터 기준으로 변환
2. df.describe() - 데이터의 특징을 한눈에!
AI한테 코드 짜달라고 하기 전에 먼저 데이터 특징부터 파악해야 해요. df.describe()는 그걸 한 번에 보여주는 완전 유용한 함수입니다!
import pandas as pd
# 데이터 기초 통계량 확인
df.describe()
df.describe()가 보여주는 것들:
| 통계량 | 의미 | 왜 중요한가? |
|---|---|---|
| count | 데이터 개수 | 결측치 확인 |
| mean | 평균 | 중심 경향 파악 |
| std | 표준편차 | 데이터 분산 정도 (클수록 편차 큼) |
| min/max | 최소/최대값 | 이상치 존재 여부 판단 |
| 25%/50%/75% | 사분위수 | 데이터 분포 확인 |
예를 들어 표준편차가 엄청 크면 "아 이 피처는 스케일링이 필요하겠구나"라고 판단할 수 있는 거죠! 이런 특성을 생성형 AI한테 같이 넘기면 훨씬 더 정확한 코드를 받을 수 있어요.
# 예시: 데이터 특징 파악
print(df.describe())
# 만약 Age의 std가 15이고, Salary의 std가 50000이면?
# → 스케일 차이가 너무 크니까 스케일링 필요!
3. 데이터 정제 - 여기서 시간 제일 많이 든다노
진짜로 데이터 정제가 머신러닝에서 제일 수고가 많이 드는 부분이에요 ㅠㅠ 데이터 분석의 80%가 전처리라는 말이 괜히 있는 게 아니라는 거...
주요 데이터 정제 작업
| 작업 | 설명 | 코드 예시 |
|---|---|---|
| 결측치 처리 | NaN 값 제거 또는 대체 | df.fillna(df.mean()) |
| 이상치 제거 | 극단값 처리 | df[df['age'] < 100] |
| 중복 제거 | 중복 데이터 삭제 | df.drop_duplicates() |
| 데이터 타입 변환 | 올바른 타입으로 변환 | df['date'] = pd.to_datetime(df['date']) |
# 결측치 확인
print(df.isnull().sum())
# 결측치 처리 방법
df.fillna(df.mean(), inplace=True) # 평균값으로 채우기
df.dropna(inplace=True) # 결측치 있는 행 삭제
# 이상치 확인 (IQR 방법)
Q1 = df['column'].quantile(0.25)
Q3 = df['column'].quantile(0.75)
IQR = Q3 - Q1
df = df[(df['column'] >= Q1 - 1.5*IQR) & (df['column'] <= Q3 + 1.5*IQR)]
4. RANDOM_STATE - 재현성을 위한 필수 설정
random_state는 완전 중요한데 많이들 간과하는 부분이에요. 이거 설정 안 하면 코드 돌릴 때마다 결과가 달라져요!
RANDOM_STATE가 뭔데?
random_state는 랜덤 시드값을 고정시켜서 같은 코드를 실행하면 항상 같은 결과가 나오게 해줘요. 재현성(Reproducibility)을 위해서는 필수입니다!
from sklearn.model_selection import train_test_split
# random_state 없이 실행하면 매번 다른 train/test 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# random_state 설정하면 항상 같은 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
왜 42를 많이 쓰나요?
- 사실 아무 숫자나 써도 돼요! (0, 11, 101 등등)
- 42는 더글라스 애덤스의 소설 "은하수를 여행하는 히치하이커를 위한 안내서"에서 나온 숫자라 프로그래머들 사이에서 유명해졌어요 ㅋㅋ
- 중요한 건 같은 숫자를 일관성 있게 사용하는 거예요!
어디에 RANDOM_STATE를 써야 하나?
# 데이터 분할
train_test_split(..., random_state=42)
# 모델 학습
RandomForestClassifier(random_state=42)
XGBClassifier(random_state=42)
# 교차 검증
cross_val_score(..., cv=KFold(n_splits=5, shuffle=True, random_state=42))
5. fit() 함수로 학습시킨다노
fit() 함수는 머신러닝 모델을 학습시키는 핵심 함수예요. 근데 스케일러에서도 쓰고, 모델에서도 쓰니까 헷갈릴 수 있어요!
Scaler의 fit()
# 스케일러를 학습 데이터에 맞춰서 "학습"시킴
scaler = StandardScaler()
scaler.fit(X_train) # 평균과 표준편차 계산
# 그 다음 변환
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 또는 한 번에
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test) # fit 말고 transform만!
모델의 fit()
from sklearn.ensemble import RandomForestClassifier
# 모델을 학습 데이터로 학습시킴
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)
# 예측
predictions = model.predict(X_test)
⚠️ 핵심:
- 학습 데이터에만 fit()을 써야 해요!
- 테스트 데이터에 fit()을 쓰면 데이터 누수 발생!
6. 피처 임포턴스 - 뭐가 중요했는지 뽑아봐라
모델 학습이 끝나면 어떤 피처가 중요한 영향을 줬는지 확인하는 게 중요해요. 이게 바로 피처 임포턴스(Feature Importance)입니다!
피처 임포턴스 확인하기
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
# 모델 학습
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)
# 피처 임포턴스 추출
importances = model.feature_importances_
# DataFrame으로 정리
feature_importance_df = pd.DataFrame({
'feature': X_train.columns,
'importance': importances
}).sort_values('importance', ascending=False)
print(feature_importance_df)
피처 임포턴스를 왜 봐야 하나?
| 이유 | 설명 |
|---|---|
| 모델 해석 | 어떤 변수가 예측에 중요한지 이해 |
| 피처 선택 | 중요하지 않은 변수 제거로 모델 간소화 |
| 도메인 지식 검증 | 예상과 다른 결과 발견 시 데이터 재검토 |
| 비즈니스 인사이트 | 실무에서 어떤 요인이 중요한지 파악 |
# 시각화
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.barh(feature_importance_df['feature'], feature_importance_df['importance'])
plt.xlabel('Importance')
plt.title('Feature Importance')
plt.show()
7. 추가로 알면 좋은 팁들
데이터 누수(Data Leakage) 조심!
데이터 누수는 테스트 데이터의 정보가 학습 과정에 새어 들어가는 거예요. 이러면 모델 성능이 비현실적으로 좋게 나와요!
# ❌ 잘못된 예시 - 전체 데이터에 스케일링 후 분할
scaler.fit_transform(X) # 전체 데이터 사용
X_train, X_test = train_test_split(X, test_size=0.2)
# ✅ 올바른 예시 - 분할 후 스케일링
X_train, X_test = train_test_split(X, test_size=0.2, random_state=42)
scaler.fit(X_train) # 학습 데이터만 사용
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
교차 검증(Cross-Validation) 써보자
한 번만 train/test 나누면 운이 좋아서 성능이 좋게 나올 수도 있어요. 교차 검증으로 여러 번 검증하면 더 신뢰할 수 있는 결과가 나와요!
from sklearn.model_selection import cross_val_score, KFold
# 5-Fold 교차 검증
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kfold, scoring='accuracy')
print(f"평균 정확도: {scores.mean():.3f} (+/- {scores.std():.3f})")
하이퍼파라미터 튜닝
모델 성능을 극대화하려면 하이퍼파라미터를 조정해야 해요!
from sklearn.model_selection import GridSearchCV
# 탐색할 파라미터 설정
param_grid = {
'n_estimators': [100, 200, 300],
'max_depth': [10, 20, 30],
'min_samples_split': [2, 5, 10]
}
# Grid Search
grid_search = GridSearchCV(
RandomForestClassifier(random_state=42),
param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1
)
grid_search.fit(X_train, y_train)
print(f"Best params: {grid_search.best_params_}")
print(f"Best score: {grid_search.best_score_:.3f}")
결론: 데이터 이해가 먼저, 코드는 그 다음!
정리하자면 요런 것들이 중요해요:
- df.describe()로 데이터 특징 먼저 파악하기 → 스케일링 필요 여부 판단
- 데이터 정제에 시간 투자하기 → 쓰레기 데이터는 쓰레기 결과만 나온다
- RANDOM_STATE 설정으로 재현성 확보 → 같은 결과를 계속 얻을 수 있음
- fit()은 학습 데이터에만 → 테스트 데이터 누수 방지
- 피처 임포턴스로 모델 해석 → 어떤 변수가 중요한지 파악
- 데이터 누수 조심 → 분할 후 전처리!
- 교차 검증으로 신뢰성 확보 → 한 번 평가로는 부족해요
생성형 AI한테 코드 짜달라고 하기 전에 이런 특징들을 먼저 정리해서 같이 넘기면 훨씬 더 좋은 코드를 받을 수 있어요! 데이터의 특징을 모르고 그냥 알고리즘만 돌리는 건 진짜 위험합니다 ^^
끝~ 모두들 행복한 데이터 분석하시길! 🎉
참고 자료
- scikit-learn 공식 문서: https://scikit-learn.org/
- Pandas 공식 문서: https://pandas.pydata.org/
#머신러닝 #데이터분석 #데이터전처리 #피처스케일링 #StandardScaler #MinMaxScaler #파이썬 #sklearn #사이킷런 #데이터과학 #AI #인공지능 #데이터분석팁 #머신러닝입문 #코딩팁 #데이터엔지니어링 #RandomState #피처임포턴스 #교차검증 #데이터누수 #하이퍼파라미터튜닝 #데이터정제 #EDA #탐색적데이터분석 #dfDescribe #판다스 #넘파이 #모델학습 #데이터과학자 #빅데이터 #통계분석
'주식 예측 프로그램 > 머신러닝' 카테고리의 다른 글
| CNN으로 주식 예측이 가능할까? 딥러닝 초보자들이 꼭 알아야 할 진실 (0) | 2025.12.23 |
|---|---|
| CNN이 피처 간 중요도를 정해주지만 블랙박스인 이유 & SHAP가 그래서 뭔데? (0) | 2025.12.23 |
| 머신러닝 모델 A to Z - 전통부터 최신까지 (0) | 2025.12.23 |