김자영 강사님
모델 학습에 앞서 데이터를 훈련 세트와 테스트 세트로 나누고, 범주형 변수에 대해 원핫인코딩을 진행.
from sklearn.model_selection import train_test_split
X_ohe = pd.get_dummies(X, columns=['year', 'month', 'hour', 'dayofweek', 'day', 'season', 'weather'])
X_train, X_test, y_train, y_test = train_test_split(X_ohe, y, random_state=42)
pd.get_dummies
: 범주형 데이터를 숫자로 변환하는 방법으로, 각각의 범주를 이진 값으로 처리하여 모델이 데이터를 인식할 수 있게 한다. Azure Machine Learning Studio에서 Convert to Indicator Values와 같은 역할인 것 같다.
from sklearn.linear_model import LinearRegression
model = LinearRegression() # 모델 생성
model.fit(X_train, y_train) # 훈련 데이터로 모델 학습
pred = model.predict(X_test) # 테스트 데이터로 예측 수행
from sklearn.metrics import mean_absolute_error, root_mean_squared_error, r2_score
mae = mean_absolute_error(y_test, pred)
rmse = root_mean_squared_error(y_test, pred)
r2 = r2_score(y_test, pred) # 결정계수 계산
print(f'MAE: {mae:.2f}')
print(f'RMSE: {rmse:.2f}')
print(f'R2: {r2:.2f}')
종속 변수(y)에 대해 로그 변환을 사용하여 데이터의 분포를 안정화시키고, 예측 정확성을 높인다.
y_log = np.log1p(y) # 로그 변환 적용
로그 변환을 통해 큰 값과 작은 값 사이의 차이를 줄이고, 모델 예측 성능을 향상시킨다. 예측 후에는 다시 로그 역변환을 적용한다.
pred_original = np.expm1(pred) # 예측값 로그 역변환
y-test_original = np.expm1(y_test) # 실제값 로그 역변환
로그 변환 후 예측값에 대한 성능 평가도 로그 역변환을 사용하여 수행한다.
mae = mean_absolute_error(y_test_original, pred_original)
rmse = root_mean_squared_error(y_test_original, pred_original)
r2 = r2_score(y_test_original, pred_original)
print(f'MAE: {mae:.2f}')
print(f'RMSE: {rmse:.2f}')
print(f'R2: {r2:.2f}')
from sklearn.tree import DecisionTreeRegressor
model = DecisionTreeRegressor()
model.fit(X_train, y_train)
KFold 교차 검증은 데이터를 K개의 부분으로 나누고, 그 중 하나를 테스트용 데이터로, 나머지를 훈련용 데이터로 사용하여 학습과 평가를 진행한다. 이를 K번 반복해서 평균 성능을 계산한다.
from sklearn.model_selection import KFold, cross_val_score
kf = KFold(n_splits=5, shuffle=True, random_state=42) # 5개의 폴드로 데이터를 나눔
n_splits=5
: 데이터를 5개로 나누어 교차 검증을 수행shuffle=True
: 데이터를 섞어서 각 폴드에 고르게 분배하도록 설정random_state=42
: 재현 가능한 결과를 위해 난수 시드를 고정model = LinearRegression()
cross_val_score(model, X, y, scoring='r2', cv=kf).mean()
model = LinearRegression()
: 선형 회귀 모델 생성cross_val_score
: KFold로 나눈 데이터를 기반으로 모델을 학습 및 평가하는 함수scoring='r2'
: 모델의 평가 기준으로 R^2 스코어 사용.cv=kf
: 교차 검증 방법으로 kf에 설정한 KFold 객체를 사용mean()
: 5번의 교차 검증 결과에서 나온 R^2 스코어들의 평균값을 계산하여 반환선형 회귀와 비슷하지만 예측하고자 하는 값이 0 또는 1처럼 두 개의 범주로 나뉠 때 주로 사용된다.
S자 모양의 곡선으로 입력값이 클수록 출력값이 1에 가까워지고 입력값이 작을수록 출력값이 0에 가까워진다. 즉, 모델은 결과가 0과 1중 어느 쪽에 더 가까운지 확률을 계산한다.
KNN 알고리즘은 분류와 회귀 문제 모두에 사용할 수 있는 간단하고 직관적인 알고리즘이다. 데이터 포인트가 주어졌을 때 그 주위의 가까운 데이터 포인트들을 참고하여 해당 데이터가 속할 그룹을 결정한다.
KNN 알고리즘의 기본 아이디어는 비슷한 데이터끼리 가까이 모여있다는 것. 새로운 데이터 포인트가 주어지면, 그 데이터와 가장 가까운 K개의 이웃 데이터를 찾아서 그 이웃들이 속한 그룹에 따라 새로운 데이터를 분류하거나 예측한다.
K값은 몇 개의 이웃을 참고할지 결정하는 중요한 하이퍼파라미터이다.
보통 K는 홀수로 선택하는데 이는 동점 상황을 방지하기 위함.
Decision Tree는 데이터를 트리 구조로 분류하거나 예측하는 데 사용하는 알고리즘이다. 매우 직관적이고 해석이 쉬운 머신러닝 알고리즘으로 분류와 회귀 모두에 사용할 수 있다.
Decision Tree는 데이터를 반복적으로 분할하면서 규칙을 만들어내는 방식으로 작동한다. 이 트리는 Root Node에서 시작해 데이터를 점점 더 작은 그룹으로 나누며, 최종적으로 Leaf Node에서 예측값을 결정한다.
과적합을 방지하기 위해 트리의 복잡성을 줄이는 방법이다. 트리가 너무 깊어져 학습 데이터에 과적합되지 않도록 트리의 최대 깊이(max_depth), 최소 샘플 수(min_samples_split, min_samples_leaf) 등의 파라미터를 설정하여 가지치기를 수행한다.
의사결정 트리는 트리 형태로 시각화할 수 있어서 어떤 기준으로 데이터를 나누었는지 쉽게 확인할 수 있다. 이를 통해 모델의 결정 과정을 직관적으로 이해할 수 있다.
앙상블(Ensemble) 학습은 여러 개의 모델을 결합하여 더 나은 예측 성능을 얻는 기법이다. 개별 모델들이 가지는 약점을 보완하고 강력한 예측 성능을 내는 데 주로 사용된다. 앙상블 기법은 특히 과적합을 줄이고, 예측 정확도를 높이는 데 매우 유용하다.
보팅은 서로 다른 여러 모델을 학습시킨 후 각 모델의 예측 결과를 투표해서 최종 결과를 도출하는 방법이다.
# 개별 모델 생성
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
lr = LogisticRegression(solver='liblinear')
knc = KNeighborsClassifier(n_neighbors=3)
dt = DecisionTreeClassifier(max_depth=8, random_state=1)
# VotingClassifier 생성
from sklearn.emsemble import VotingClassifier
vc = VotingClassifier(estimators = [('lr_model', lr), ('knc_model', knc), ('dt_model', dt)\, voting='soft')
# VotingClassifier 학습, 예측, 평가
vc.fit(X_train, y_train)
pred = vc.predict(X_test)
from sklearn.metrics import accuracy_score
vc_accuracy = accuracy_score(y_test, pred)
print(f'VotingClassifier accuracy >>> {vc_accuracy}')
# 개별모델 학습, 예측, 평가
for model in [lr, knc, dt]:
model.fit(X_train, y_train)
pred = model.predict(X_test)
accuracy = accuracy_score(y_test, pred)
print(f'{model.__class__.__name__} accuracy >>> {accuracy}')
VotingClassifier
: 세 모델의 예측 결과를 기반으로 소프트 보팅을 수행배깅은 같은 알고리즘을 사용하지만, 각 모델은 다른 데이터 샘플을 학습한다. 이를 통해 모델 간의 상관성을 줄여 과적합을 방지할 수 있다.
부스팅은 순차적으로 모델을 학습시키며, 이전 모델에서 잘못 예측한 데이터에 더 높은 가중치를 부여하여 다음 모델이 이를 더 잘 예측할 수 있도록 하는 방법이다.
# 필요한 라이브러리 임포트
from sklearn.datasets import load_iris
from sklearn.model_selection improt train_test_split
import pandas as pd
# 데이터셋 로드
iris = load_iris()
# 특징(독립 변수)과 타겟(종속 변수) 확인
X = iris.data
y = iris.target
# 학습 데이터와 테스트 데이터로 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 데이터프레임 구조로 변환하여 보기
df_iris = pd.DataFrame(X, columns=iris.feature_names)
df_iris['species'] = y
df_iris.head()
load_iris
, 학습과 테스트 데이터를 나누기 위해 train_test_split
, 데이터 시각화를 위해 pandas
를 불러온다.load_iris()
함수를 사용하여 데이터를 불러온다.train_test_split
함수를 사용하여 데이터를 학습용 80% 와 테스트용 20% 로 나눈다.pandas
의 DataFrame
을 사용해 데이터셋을 표 형태 로 변환, 보기 쉽게 타겟 데이터를 'species'라는 새로운 열로 추가한다.# 데이터 분할 결과 확인
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
# 타겟 분포 확인
print(pd.Series(y_train).value_counts())
print(pd.Series(y_test).value_counts())
df_iris.info()
info()
메서드는 데이터프레임의 전체 구조를 보여준다. 각 열의 데이터 타입과 결측치 여부를 확인할 수 있다.
import seaborn as sns
import matplotlib.pyplot as plt
# 시각화: 특성 간 관계를 나타내는 산점도 행렬
sns.pairplot(df_iris, hue='species', palette='muted')
plt.show()
Seaborn의 pairplot을 사용하여 각 특성 간의 산점도와 히스토그램 시각화. hue='species'
로 각 붓꽃 품종을 색으로 구분할 수 있다.
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
stratifiy=y
: 데이터 분할 시 각 클래스의 비율을 유지한다. 즉, 학습 데이터와 테스트 데이터에서 클래스 비율이 동일하게 유지된다.from sklearn.tree import DecisionTreeClassifier
# 모델 생성
model = DecisionTreeClassifier(random_state=42)
# 모델 학습
model.fit(X_train, y_train)
DecisionTreeClassifier
: 의사결정 트리 알고리즘을 사용하여 학습 모델을 만든다.fit
: 학습 데이터를 이용해 모델을 학습시킨다.from sklearn.metrics import accuracy_score
# 정확도 계산
pred = model.predict(X_test)
accuracy = accuracy_score(y_test, pred)
print(f'정확도: {accuracy:.2f}')
from sklearn.metrics import classification_report
# 분류 리포트 출력
print(classification_report(y_test, pred, target_names=iris.target_names))
from sklearn.model_selection import KFold
import numpy as np
# KFold 객체 생성
kf = KFold(n_splits=5, shuffle=True, random_state=42)
# 각 fold에 대해 교차검증 수행
cv_scores = [] # 각 fold에서의 정확도를 저장할 리스트
for train_index, test_index in kf.split(X): # X는 전체 특성 데이터
# 학습 및 테스트 데이터셋 분리
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index] # y는 레이블 데이터
# 모델 생성 및 학습
model = DecisionTreeClassifier(random_state=42)
model.fit(X_train, y_train)
# 테스트 데이터로 예측 및 정확도 계산
pred = model.predict(X_test)
accuracy = accuracy_score(y_test, pred)
# 각 fold의 정확도 저장
cv_scores.append(accuracy)
# 교차검증 결과 확인
print(f'각 fold의 정확도: {np.round(cv_scores, 4)}')
print(f'cv_scores_mean: {np.mean(cv_scores):.4f}') # 이 부분이 많이 헷갈렸다.
KFold(n_splits=5)
: 데이터를 5개의 폴드로 나눈다. shuffle=True
: 데이터를 무작위로 섞은 후 폴드를 나누기 때문에 모델이 데이터에 과적합되는 것을 방지한다.kf.split(X)
: 데이터셋 X를 K개의 폴드로 나누어 훈련용과 테스트용 인덱스를 반환한다.cv_scores
: 각 폴드에서 테스트 데이터로 예측한 결과의 정확도를 저장한 리스트np.round(cv_scores, 4)
: 각 폴드에서 얻은 정확도를 소수점 네자리까지 반올림하여 출력np.mean(cv_scores)
: 각 폴드에서 계산된 정확도의 평균값을 출력from sklearn.model_selection import StratifiedKFold
# StratifiedKFold 객체 생성
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# 각 fold에 대해 교차검증 수행
cv_scores = []
for train_index, test_index in skf.split(X, y):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
# 모델 생성 및 학습
model = DecisionTreeClassifier(random_state=42)
model.fit(X_train, y_train)
# 테스트 데이터로 예측 및 정확도 계산
pred = model.predict(X_test)
accuracy = accuracy_score(y_test, pred)
# 각 fold의 정확도 저장
cv_scores.append(accuracy)
# 교차검증 결과 확인
print(f'각 fold의 정확도: {np.round(cv_scores, 4)}')
print(f'cv_scores_mean: {np.mean(cv_scores):.4f}')
StratifiedKFold(n_splits=5)
: 데이터를 5개의 폴드로 나눌 때, 각 폴드에서 클래스 비율을 동일하게 유지한다.skf.split(X, y)
: 전체 데이터 X
와 레이블 y
를 각각 K개의 폴드로 나눈다. 이 과정에서 클래스 비율을 유지한다.from sklearn.model_selection import cross_val_score
# cross_val_score로 교차검증 수행
cv_scores = cross_val_score(model, X_train, y_train, cv=skf, scoring='accuracy')
cross_val_score()
: skf만큼의 폴드로 교차검증을 수행, 성능 평가는 정확도를 기준으로 한다.
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
plt.figure(figsize=(20, 10))
plot_tree(model, feature_names=feature_name, class_names=target_name, filled=True)
plt.tight_layout()
plt.show()
plot_tree()
: 의사결정 트리의 분기 과정 시각화feature_names
: 각 노드가 분할된 기준(특성) 표시class_names
: 예측된 클래스(붓꽃 품종) 이름 표시filled=True
: 노드를 채워서 시각적으로 구분할 수 있게 함import seaborn as sns
# 특성 중요도 출력
print(f'특성 중요도 >>> {model.feature_importance_}')
# 특성 중요도 시각화
plt.figure(figsize=(4, 3))
sns.barplot(y=feature_name, x=model.feature_importances_)
plt.show()
feature_importances_
: 각 특성이 모델 예측에 얼마나 중요한 역할을 했는지 나타내는 값. 값이 클수록 해당 특성이 중요하다.barplot()
: 각 특성의 중요도를 막대 그래프로 시각화print(f'트리 깊이: {model.get_depth()}')
get_depth()
: 의사결정 트리의 최대 깊이 반환
from sklearn.model_selection import GridSearchCV
# 하이퍼파라미터 그리드 설정
parameters = {
'max_depth': [3, 4, 5], # 트리 최대 깊이
'min_samples_split': [2, 4] # 분할을 위한 최소 샘플 수
}
# GridSearchCV 객체 생성
gscv = GridSearchCV(model, param_grid=parameters, cv=kf, refit=True)
# 하이퍼파라미터를 순차적으로 변경하면서 학습/평가 수행
gscv.fit(X_train, y_train)
# 최적의 하이퍼파라미터와 성능 출력
print(f'최적의 파라미터 >>> {gscv.best_params_}')
print(f'최고 정확도 >>> {gscv.best_score_:.4f}')
param_grid
: 튜닝할 하이퍼파라미터와 그 값들의 범위를 설정한다.GridSearchCV()
: 하이퍼파라미터 조합마다 교차검증을 수행하는 객체cv=kf
: kf개의 교차검증을 사용하여 모델 성능 평가fit()
: GridSearchCV는 데이터를 사용해 하이퍼파라미터 조합마다 모델을 학습하고 평가한다.best_params_
: 최적의 하이퍼파라미터 조합 반환best_score_
: 교차검증 중 가장 높은 정확도 반환# 최종 모델
best_model = gscv.best_estimator_
# 예측
pred = best_model.predict(X_test)
# 평가
accuracy = accuracy score(y_test, pred)
print(f'테스트세트 정확도 >> {accuracy:.4f}')
best_estimator_
: 최적의 하이퍼파라미터로 훈련된 모델
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
rocket = pd.read_csv('data/RocketLaunchDataCSV.csv')
rocket.head(3)
rocket.info()
df = rocket.drop(['Hist Ave Max Wind Speed', 'Hist Ave Visibility',
'Hist Ave Sea Level Pressure', 'Name', 'Date',
'Time (East Coast)', 'Location', 'Day Length',
'Sea Level Pressure', 'Notes'], axis=1)
drop()
: 지정된 열들을 데이터프레임에서 제거axis=1
: 열(column)을 기준으로 제거df['Launched?'] = df['Launched?'].fillna('N')
df['Creweed or Uncrewed'] = df['Crewed or Uncrewed'].fillna('Uncrewed')
df['Condition'] = df['Condition'].fillna('Fair')
df['Wind Direction'] = df['Wind Direction'].fillna('Unknown')
# 수치형 변수 결측치 0으로 채우기
df = df.fillna(0)
fillna
: 결측치를 특정 값으로 채움# 종속변수 인코딩
df['Launched?'] = df['Launched?'].map({'Y':1, 'N':0})
# 독립변수 레이블 인코딩
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
cols = ['Crewed or Uncrewed', 'Wind Direction', 'Condition']
for col in cols:
df[col] = encoder.fit_transform(df[col])