학습을 위한 코드이며, 최선의 코드가 아님
데이터 로드 및 기본 정보 확인
import numpy as np
import pandas as pd
df = pd.read_csv('./titanic_csv')
df.info()
df.head(3)
"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
"""
- 데이터 로드
titanic.csv파일을 pandas의 read_csv 함수를 통해 데이터프레임으로 불러옴 - 데이터 정보 확인
df.info()를 통해 데이터의 열 정보, 데이터 타입, 결측값 여부 등을 확인
*컬럼 설명
PassengerID | 탑승자 데이터의 고유 ID |
Survived | 생존 여부 (0 : 사망, 1 : 생존) |
Pclass | 선실 등급 (1, 2, 3) |
Sex | 성별 |
Age | 나이 |
SibSp | 동반한 형제자매 또는 배우자 수 |
Parch | 동반한 부모 또는 자녀 수 |
Fare | 티켓 요금 |
Cabin | 선실 번호 |
Embarked | 승선 항구 (C: Cherbourg, Q = Queenstown, S = Southampton) |
데이터 전처리
결측값 처리
Age 평균 값으로 채움 (평균값 대신 중위값 또는 다른 대체값을 사용할 수도 있음)
Cabin ‘N’으로 채움
Embarked ‘N’으로 채움
def fillna(df):
df['Age'] = df['Age'].fillna(df['Age'].mean())
df['Cabin'] = df['Cabin'].fillna('N')
df['Embarked'] = df['Embarked'].fillna('N')
return df
불필요한 컬럼 제거
PassengerId
Name
Ticket
모델 학습에 사용하지 않을 컬럼 : 제거
def drop_features(df):
return df.drop(['PassengerId', 'Name', 'Ticket'], axis=1)
범주형 데이터 처리
Sex, Embarked: LabelEncoder를 이용해 숫자형으로 변환
Cabin: 문자열의 첫 번째 문자만 추출 후 숫자형으로 변환
from sklean.preprogressing import LabelEncoder
def format_features(df):
df['Cabin'] = df['Cabin'].astype(str).str[:1]
features = ['Cabin', 'Sex', 'Embarked']
for feature in features:
le = LabelEncoder()
df[feature] = le.fit_transform(df[feature])
return df
전처리 함수 통합
위의 모든 단계를 통합한 전처리 함수 작성
def transform_features(df):
df = fillna(df)
df = drop_features(df)
df = format_features(df)
return df
데이터 분리
Survived 종속변수(y), 나머지 데이터 독립변수(X)
train_test_split을 사용해 학습/테스트 데이터로 나눔
from sklearn.model_selection import train_test_split
y_titanic_df = df['Survived']
X_titanic_df = df.drop('Survived, axis = 1, inplace = False)
X_titanic_df = transform_features(X_titanic_df)
X_train, X_test, y_train, y_test = train_test_split(X_titanic_df, y_titanic_df, test_size=0.2, random_state=11)
모델 학습 및 평가
모델 정의
DecisionTreeClassifier
RandomForestClassifier
LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
models = {
'DecisionTree': DecisionTreeClassifier(random_state=0),
'RandomForest': RandomForestClassifier(random_state=0),
'LogisticRegression': LogisticRegression(solver='liblinear')
}
모델 학습 및 정확도 평가
accuracy_score
confusion_matrix
classification_report
→모델 성능 평가
def evaluate_models(models, X_train, X_test, y_train, y_test):
results = {}
for name, model in models.items():
model.fit(X_train, y_train)
pred = model.predict(X_test)
acc = accuracy_score(y_test, pred)
results[name] = acc
print(f'{name} 정확도: {acc:.4f}')
print("Confusion Matrix:\n", confusion_matrix(y_test, pred))
print("Classification Report:\n", classification_report(y_test, pred))
return results
#모델 평가
results = evaluate_models(models, X_train, X_test, y_train, y_test)
"""
DecisionTree 정확도: 0.8045
Confusion Matrix:
[[101 17]
[ 18 43]]
Classification Report:
precision recall f1-score support
0 0.85 0.86 0.85 118
1 0.72 0.70 0.71 61
accuracy 0.80 179
macro avg 0.78 0.78 0.78 179
weighted avg 0.80 0.80 0.80 179
RandomForest 정확도: 0.8436
Confusion Matrix:
[[106 12]
[ 16 45]]
Classification Report:
precision recall f1-score support
0 0.87 0.90 0.88 118
1 0.79 0.74 0.76 61
accuracy 0.84 179
...
accuracy 0.87 179
macro avg 0.85 0.84 0.85 179
weighted avg 0.86 0.87 0.86 179
"""
결과 시각화
모델 별 정확도를 막대그래프로 시각화
import matplotlib.pyplot as plt
plt.bar(results.keys(), results.values())
plt.title('Model Accuracy Comparison')
plt.ylabel('Accuracy')
plt.show()
교차 검증
K-Fold 교차 검증
KFold를 활용해 데이터를 K개로 나누어 검증
from sklearn.model_selection import KFold
def exec_kfold(clf, folds=5):
kfold = KFold(n_splits=folds)
scores = []
for iter_count, (train_index, test_index) in enumerate(kfold.split(X_titanic_df)):
X_train, X_test = X_titanic_df.values[train_index], X_titanic_df.values[test_index]
y_train, y_test = y_titanic_df.values[train_index], y_titanic_df.values[test_index]
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)
accuracy = accuracy_score(y_test, predictions)
scores.append(accuracy)
print(f'교차 검증 {iter_count} 정확도: {accuracy:.4f}')
mean_score = np.mean(scores)
print(f'평균 정확도: {mean_score:.4f}')
exec_kfold(DecisionTreeClassifier(random_state=0))
"""
교차 검증 0 정확도: 0.7542
교차 검증 1 정확도: 0.7809
교차 검증 2 정확도: 0.7865
교차 검증 3 정확도: 0.7697
교차 검증 4 정확도: 0.8202
평균 정확도: 0.7823
"""
cross_val_score를 이용한 교차 검증
cross_val_score로 평균 정확도 계산
from sklearn.model_selection import cross_val_score
scores = cross_val_score(DecisionTreeClassifier(random_state=0), X_titanic_df, y_titanic_df, cv=5)
for iter_count, accuracy in enumerate(scores):
print(f'교차 검증: {iter_count}, 정확도: {accuracy}')
print(f'평균 정확도 >>>> {np.mean(scores):.4f}')
"""
교차 검증: 0, 정확도: 0.7653631284916201
교차 검증: 1, 정확도: 0.7752808988764045
교차 검증: 2, 정확도: 0.797752808988764
교차 검증: 3, 정확도: 0.7808988764044944
교차 검증: 4, 정확도: 0.8258426966292135
평균 정확도 >>>> 0.7890
"""
하이퍼파라미터 튜닝
GridSearchCV를 사용해 하이퍼파라미터를 최적화
조합 정의 → 교차 검증 → 최적의 조합 선택 → 최적의 모델 반환
from sklearn.model_selection import GridSearchCV
parameters = {'max_depth': [2, 3, 5, 10],
'min_samples_split': [2, 3, 5],
'min_samples_leaf': [1, 5, 8]}
grid_dclf = GridSearchCV(DecisionTreeClassifier(random_state=0), param_grid=parameters, scoring='accuracy', cv=5)
grid_dclf.fit(X_train, y_train)
print(f'최적의 파라미터 >>>> {grid_dclf.best_params_}')
print(f'최고 교차 검증 정확도 >>>> {grid_dclf.best_score_}')
"""
GridSearchCV 최적 하이퍼 파라미터 >>>> {'max_depth': 3, 'min_samples_leaf': 5, 'min_samples_split': 2}
GridSearchCV 최고 정확도: 0.7991825076332119
"""
하이퍼파라미터 범위 조정: GridSearchCV의 파라미터 범위는 데이터의 특성에 따라 조정 필요
*parameters
depth
너무 깊으면 과적합될 가능성이 높음
split
작으면 작을수록 트리가 복잡해짐
leaf
리프 노드가 최소한의 데이터를 포함하도록 설정
조합의 개수
조합 수 = depth 수 x split 수 x leaf 수
*고려사항
데이터 불균형
Survived의 클래스 비율이 불균형하다면, class_weight 옵션을 설정하거나 오버샘플링(SMOTE) 등을 고려해야 함
전체 데이터셋을 활용하여 학습 및 검증
# 라이브러리 가져오기
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
parameters = {'max_depth': [2, 3, 5, 10],
'min_samples_split': [2, 3, 5],
'min_samples_leaf': [1, 5, 8]}
grid_dclf = GridSearchCV(
estimator=DecisionTreeClassifier(random_state=44),
param_grid=parameters,
scoring='accuracy',
cv=5
)
grid_dclf.fit(X_titanic_df, y_titanic_df)
print(f'최적의 파라미터 >>>> {grid_dclf.best_params_}')
print(f'최고 교차 검증 정확도 >>>> {grid_dclf.best_score_}')
best_model = grid_dclf.best_estimator_
best_model
pred = best_model.predict(X_titanic_df)
print(f'GridSearchCV 최적의 값 >>>> {accuracy_score(y_titanic_df, pred)}')
"""
최적의 파라미터 >>>> {'max_depth': 10, 'min_samples_leaf': 8, 'min_samples_split': 2}
최고 교차 검증 정확도 >>>> 0.8159751428033394
GridSearchCV 최적의 값 >>>> 0.8720538720538721
"""
- 데이터 활용 효율성 높음
데이터가 적은 상황에서도 최대한 성능을 끌어낼 수 있음 - 안정적인 결과
교차 검증 과정에서 모든 데이터가 학습과 검증에 포함되므로, 데이터 부족으로 인한 성능 변화를 최소화 - 과적합 가능성
전체 데이터에서 교차 검증을 수행하므로, 테스트 데이터가 학습 데이터와 겹칠 가능성이 있음
→최적의 하이퍼파라미터를 찾은 후 최종 평가 데이터로 독립적인 검증이 불가능
하이퍼파라미터 최적화와 검증을 동시에 수행하는 것이 주요 목표일 때
데이터셋이 작을 때
전체 데이터를 활용하여 학습 및 검증하는 방법을 사용할 수 있음
'Python to AI' 카테고리의 다른 글
클래스, 클래스 변수, 인스턴스 변수 (1) | 2025.02.05 |
---|---|
혼동행렬을 활용한 분류 성능 지표 (1) | 2025.02.02 |
Iris 데이터셋과 결정 트리(Decision Tree) 모델 : 평가 방법 비교 및 교차 검증 실습 (0) | 2025.01.24 |
Scikit-Learn과 Estimator (0) | 2025.01.21 |
Perceptron(퍼셉트론) (1) | 2025.01.14 |