[오늘의 일지]
머신러닝 프로젝트 - 조편성, 주제선정, 대회 파악하기, 데이터 파악하기, 베이스라인
[상세 내용]
머신러닝 프로젝트
조편성
- 조편성은 기존 프로젝트에서는 선호도를 조사해서 랜덤 하게 편성되는 구조를 가지고 있었는데 이번에는 사전에 마음이 맞는 사람끼리 조를 미리 구성해도 된다고 공지를 해줬습니다. 저는 처음에는 그냥 새로운 사람들과 그냥 해보자는 생각이었는데 마침 감사하게도 전에 EDA 프로젝트를 같이했던 조원분께서 먼저 이번에도 같이 해보자고 권해주셔서 두 명이서 같이 하게 되었습니다. 지난 프로젝트 때 좋은 경험을 했기 때문에 이번 조편성도 기분 좋게 출발할 수 있었던 거 같습니다.
주제선정
- 주제는 총 6개가 있었습니다. 캐글 대회 3개와 데이콘 대회 3였는데 캐글에서는 현재 진행되고 있는 대회가 2개였고 데이콘은 1개가 있었습니다. 강사님께서 현재 진행되고 있는 대회를 선택하는 것이 프로젝트를 위해서 동기부여가 잘 된다고 말씀하셔서 저희 조는 현재 진행되고 있는 대회로 간추려서 선택지를 3개로 줄였습니다. 그리고 캐글 대회의 경우는 기간이 굉장히 긴 대회들만 있었고 데이콘이 기간이 비교적 짧아서 결과도 금방 나올 거 같다는 생각이 들어서 신청하게 되었습니다. 그렇게 선택하게 된 대회의 주제 '선박 정보를 기반으로 선박의 대기 시간 예측하기'로 HD한국조선해양에서 주관하고 있는 대회였습니다. 자세한 정보는 아래에 링크를 남기겠습니다.
대회 파악하기
- 데이터를 제공하는 이유에 대해서 간략하게 설명하자면 코로나19가 끝난 후로 선박을 통한 물류들이 많아지면서 항만에서 대기하는 선박들이 많아졌다고 합니다. 그래서 여러 가지 데이터를 제공해서 대기 시간을 예측하는 AI 알고리즘 모델을 구축하는 것을 큰 목표로 두고 있다고 합니다. 결론적으로 저희가 구해야 하는 타깃은 대기시간이고 다양한 데이터의 피처들을 이용해서 구해야 하며 평가지표와의 차이에 따라서 점수를 매기고 순위를 정하는 구조였습니다. 여기서 강사님이 말씀해 주신 동기부여라는 것이 실시간으로 순위를 올리는 부분에서 동기부여가 된다는 것을 느꼈습니다.
데이터 파악하기
- 대회의 주제를 보면 알 수 있듯이 데이트는 조선해양과 관련되어 있었습니다. 아래에 피처들에 대해서 자세하게 나와있는데 몇몇의 피처들은 object형식으로 인코딩이 필요한 것을 파악할 수 있었습니다.
Feature Name | Description |
ARI_CO | 도착항의 소속국가(도착항 앞 2글자) |
ARI_PO | 도착항의 항구명(도착항 뒤 글자) |
SHIP_TYPE_CATEGORY | 선종 통합 바탕으로 5대 선종으로 분류 |
DIST | 정박지(ber_port)와 접안지 사이의 거리 |
ATA | anc_port에 도착한 시점의 utc. 실제 정박 시각(Actual Time of Arrival) |
ID | 선박식별 일련번호 |
BREADTH | 선박의 폭 |
BUILT | 선박의 연령 |
DEADWEIGHT | 선박의 재화중량톤수 |
DEPTH | 선박의 깊이 |
DRAUGHT | 흘수 높이 |
GT | 용적톤수(Gross Tonnage)값 |
LENGTH | 선박의 길이 |
SHIPMANAGER | 선박 소유주 |
FLAG | 선박의 국적 |
U_WIND | 풍향 u벡터 |
V_WIND | 풍향 v벡터 |
AIR_TEMPERATURE | 기온 |
BN | 보퍼트 풍력 계급 |
ATA_LT | anc_port에 도착한 시점의 현지 정박 시각(Local Time of Arrival)(단위 : H) |
DUBAI | 해당일의 두바이유 값 |
BRENT | 해당일의 브렌트유 값 |
WTI | 해당일의 WTI 값 |
BDI_ADJ | 조정된 벌크운임지수 |
PORT_SIZE | 접안지 폴리곤 영역의 크기 |
CI_HOUR | 대기시간 |
베이스라인
- 프로젝트를 시작하기 전에 강사님께서 대회에서 주어지는 베이스라인 코드나 캐글 같은 경우는 사람들이 먼저 구축해 놓은 템플릿 코드를 이용하는 것이 좋다고 말씀해 주셨는데 이번 대회도 역시 데이콘에서 베이스 코드를 제공해 주고 있었습니다. 베이스 코드에 대해서 설명하자면 ATA라는 피처의 연도, 날짜, 시간, 분, 주까지 분리를 해주었고 object파일들의 인코딩까지 해주었으며 결측치도 간단하게 평균값으로 대체해 주면서 전처리를 모두 해줬습니다. 그리고 퓨처 importance를 통해서 피처의 중요도를 정해주고 스레드홀드를 통해서 과감하게 피처들을 drop 시켜서 K-FoldK-Fold Model Fitting & Validation 과정까지 마무리하면 큰 틀을 정해준 거 같았습니다. 당연하게도 평가지표는 매우 기본적으로 나와 있습니다.
# Import & Data Load
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import lightgbm as lgb
import bisect
from tqdm import tqdm
from sklearn.metrics import mean_absolute_error
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import KFold
train = pd.read_csv('train.csv').drop(columns=['SAMPLE_ID'])
test = pd.read_csv('test.csv').drop(columns=['SAMPLE_ID'])
# Data Pre-processing
# datetime 컬럼 처리
train['ATA'] = pd.to_datetime(train['ATA'])
test['ATA'] = pd.to_datetime(test['ATA'])
# datetime을 여러 파생 변수로 변환
for df in [train, test]:
df['year'] = df['ATA'].dt.year
df['month'] = df['ATA'].dt.month
df['day'] = df['ATA'].dt.day
df['hour'] = df['ATA'].dt.hour
df['minute'] = df['ATA'].dt.minute
df['weekday'] = df['ATA'].dt.weekday
# datetime 컬럼 제거
train.drop(columns='ATA', inplace=True)
test.drop(columns='ATA', inplace=True)
# Categorical 컬럼 인코딩
categorical_features = ['ARI_CO', 'ARI_PO', 'SHIP_TYPE_CATEGORY', 'ID', 'SHIPMANAGER', 'FLAG']
encoders = {}
for feature in tqdm(categorical_features, desc="Encoding features"):
le = LabelEncoder()
train[feature] = le.fit_transform(train[feature].astype(str))
le_classes_set = set(le.classes_)
test[feature] = test[feature].map(lambda s: '-1' if s not in le_classes_set else s)
le_classes = le.classes_.tolist()
bisect.insort_left(le_classes, '-1')
le.classes_ = np.array(le_classes)
test[feature] = le.transform(test[feature].astype(str))
encoders[feature] = le
# 결측치 처리
train.fillna(train.mean(), inplace=True)
test.fillna(train.mean(), inplace=True)
# 모델 학습 및 특성 중요도 확인
def train_and_evaluate(model, model_name, X_train, y_train):
print(f'Model Tune for {model_name}.')
model.fit(X_train, y_train)
feature_importances = model.feature_importances_
sorted_idx = feature_importances.argsort()
plt.figure(figsize=(10, len(X_train.columns)))
plt.title(f"Feature Importances ({model_name})")
plt.barh(range(X_train.shape[1]), feature_importances[sorted_idx], align='center')
plt.yticks(range(X_train.shape[1]), X_train.columns[sorted_idx])
plt.xlabel('Importance')
plt.show()
return model, feature_importances
X_train = train.drop(columns='CI_HOUR')
y_train = train['CI_HOUR']
# Model Tune for LGBM
lgbm_model, lgbm_feature_importances = train_and_evaluate(lgb.LGBMRegressor(), 'LGBM', X_train, y_train)
# 특성 중요도로부터 Feature Selection
threshold = 85 # Your Threshold
low_importance_features = X_train.columns[lgbm_feature_importances < threshold]
X_train_reduced = X_train.drop(columns=low_importance_features)
X_test_reduced = test.drop(columns=low_importance_features)
# K-Fold Model Fitting & Validation
lgbm = lgb.LGBMRegressor()
# 5-Fold 설정
kf = KFold(n_splits=5, shuffle=True, random_state=42)
# 각 fold의 모델로부터의 예측을 저장할 리스트와 MAE 점수 리스트
ensemble_predictions = []
scores = []
for train_idx, val_idx in tqdm(kf.split(X_train_reduced), total=5, desc="Processing folds"):
X_t, X_val = X_train_reduced.iloc[train_idx], X_train_reduced.iloc[val_idx]
y_t, y_val = y_train[train_idx], y_train[val_idx]
# 두 모델 모두 학습
lgbm.fit(X_t, y_t)
# 각 모델로부터 Validation set에 대한 예측을 평균내어 앙상블 예측 생성
val_pred = lgbm.predict(X_val)
# Validation set에 대한 대회 평가 산식 계산 후 저장
scores.append(mean_absolute_error(y_val, val_pred))
# test 데이터셋에 대한 예측 수행 후 저장
lgbm_pred = lgbm.predict(X_test_reduced)
lgbm_pred = np.where(lgbm_pred < 0, 0, lgbm_pred)
ensemble_predictions.append(lgbm_pred)
# K-fold 모든 예측의 평균을 계산하여 fold별 모델들의 앙상블 예측 생성
final_predictions = np.mean(ensemble_predictions, axis=0)
# 각 fold에서의 Validation Metric Score와 전체 평균 Validation Metric Score출력
print("Validation : MAE scores for each fold:", scores)
print("Validation : MAE:", np.mean(scores))
[마무리]
오늘은 이번 머신러닝 프로젝트를 시작하게 되는 초기 과정에 대해서 정리해 보았습니다. 실제로는 베이스라인 코드를 활용해서 많은 시도를 하고 있지만 자세한 것은 차즘차즘 정리해서 써보도록 하겠습니다. 프로젝트를 시작하게 되면서 비로소 머신러닝이라는 것의 정의에 대해서 다시 한번 적립하게 되는 것 같습니다. 제가 느낀 머신러닝이라는 것은 간략하게 말하자면 누가 어떻게 자신만의 코드를 통해서 주어진 평가지표에 더 적합한 모델을 만드느냐였던 거 같습니다. 프로젝트가 끝날 때까지 좋은 모델을 만들기 위해 노력해야겠습니다.
'AI > AI 부트캠프' 카테고리의 다른 글
[AI 부트캠프] DAY 59 - 머신러닝 프로젝트 3 (0) | 2023.10.14 |
---|---|
[AI 부트캠프] DAY 58 - 머신러닝 프로젝트 2 (0) | 2023.10.13 |
[AI 부트캠프] DAY 39 - EDA 프로젝트 10 (0) | 2023.09.09 |
[AI 부트캠프] DAY 38 - EDA 프로젝트 9 (2) | 2023.09.08 |
[AI 부트캠프] DAY 37 - EDA 프로젝트 8 (0) | 2023.09.07 |
댓글