[data dictionary]
pid- 품목 ID (p001-p005)
year -연도 (2017-2022)
month-월 (1-12)
day- 일 (10/20/30)
weight - 수입 중량(kg)
quantity - 수입 수량(unit)
value - 수입금액 (us달러)
- day: 산업 품목별 10일 단위의 수입자료로 10, 20, 30으로 구성
- day=10 : 매월 1~10일
- day=20 : 매월 11~20일
- day=30 : 매월 21~말일
- quantity
- 품목이 원자재, 소재 등인 경우, 수량 측정이 불가하여 수입 신고시 중량만 측정하여 기재함
- 그에 따라 대부분 quantity 값에 결측치가 존재하며 결측치는 0으로 처리
[데이터 전처리]
기존에 있던 열들을 이용해서 새로운 열(피처)를 최대한 많이 만드는 식으로 계획 .
1. 전월 value 가져오기 (시계열 특성)
전월 및 전년도 value 평균값 생성
train = train.sort_values(by=['pid', 'date'])
train['value_last_month'] = train.groupby('pid')['value'].shift(1)
# value_last_month이 NaN인 경우 해당 날짜의 value로 대체
train['value_last_month'] = train.apply(
lambda row: row['value'] if pd.isna(row['value_last_month']) else row['value_last_month'],
axis=1
)
2. 전월 weight 가져오기 (시계열 특성)
전월 및 전년도 weight 평균값 생성
train.sort_values(by=['pid','date'])
train['weight_last_month']=train.groupby('pid')['weight'].shift(1)
train['weight_last_month'] = train.apply(
lambda row: row['weight'] if pd.isna(row['weight_last_month']) else row['weight_last_month'],
axis=1
)
3. price 누적 데이터 피쳐
4. weight 누적 데이터 피쳐
train['cumulative_import_price'] = train.groupby(['year', 'pid'])['value'].cumsum()
train['cumulative_import_weight'] = train.groupby(['year', 'pid'])['weight'].cumsum()
5. 누적 평균
연도와 품목별 평균 증가 수치
train['cumulative_avg_weight'] = train['cumulative_import_weight'] / (train.groupby(['year', 'pid']).cumcount() + 1)
6. 각 달의 금액이 연간 총 금액에서 차지하는 비율 피처
train['yearly_total_value'] = train.groupby(['pid', 'year'])['value'].transform('sum')
train['monthly_value_ratio'] = train['value'] / train['yearly_total_value']
7. 각 pid 별로 value_last_month의 표준편차 계산하여 z-score 계산
train['value_semi_z_score'] = train.groupby('pid').apply(
lambda group: (group['value'] - group['value_last_month']) / group['value_last_month'].std()
).reset_index(level=0, drop=True)
8. 월 별 평균 수입 증량
train['monthly_avg_weight'] = train.groupby(['pid', 'month'])['weight'].transform('mean')
9. 수입 금액의 상대적 변화율
# value_change_rate와 weight_change_rate 계산
train['value_change_rate'] = train['value'].pct_change()
train['weight_change_rate'] = train['weight'].pct_change()
# 상대적 변화율 (relative_change_rate) 계산
train['relative_change_rate'] = train['value_change_rate'] / train['weight_change_rate']
# NaN 값 제거 (첫 번째 row와 변화율이 0인 경우)
train['relative_change_rate'].fillna(0, inplace=True)
train['value_change_rate'].fillna(0, inplace=True)
이 외에 환율데이터셋, GDP, 수출금액데이터셋을 활용해서 피쳐를 만들어봤지만 rmse 값이 떨어지는 것을 확인하고 피쳐 삭제....
[데이터 분할]
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error
# 사용할 특성과 타겟 변수 선택
features = ['value_last_month','weight_last_month', 'weight','cumulative_import_price','cumulative_import_weight','cumulative_avg_weight','monthly_value_ratio',
'value_semi_z_score','monthly_avg_weight','relative_change_rate','value_change_rate']
target = 'value'
# 학습 및 검증 데이터 분리 (2022년 데이터를 검증용으로 사용)
train_set = train[train['year'] < 2022]
test_set = train[train['year'] == 2022]
X_train = train_set[features]
y_train = train_set[target]
X_test = test_set[features]
y_test = test_set[target]
[모델링]
from lightgbm import LGBMRegressor
from sklearn.linear_model import LinearRegression
voting_regressor = VotingRegressor(estimators=[
#("lgbm", LGBMRegressor(random_state=0)),
("xgb", XGBRegressor(n_estimators=100, max_depth=6, random_state=0)),
("lr", LinearRegression())
])
# Create the final pipeline
model = Pipeline(steps=[("model", voting_regressor)])
# Fit the model
model.fit(X_train, y_train)
from catboost import CatBoostRegressor
from sklearn.linear_model import LinearRegression
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from sklearn.ensemble import VotingRegressor
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_squared_error
import numpy as np
from sklearn.linear_model import ElasticNet
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.ensemble import ExtraTreesRegressor
# CatBoost 기본 모델 생성
cat_model = CatBoostRegressor(
iterations=1000,
learning_rate=0.1,
depth=6,
silent=True, # 학습 로그를 출력하지 않음
random_seed=42
)
elasticnet_model = ElasticNet(alpha=0.1, l1_ratio=0.5, random_state=42)
rf_model = RandomForestRegressor(n_estimators=100, max_depth=None, random_state=42)
gbr_model = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42)
et_model = ExtraTreesRegressor(n_estimators=100, max_depth=None, random_state=42)
from sklearn.neural_network import MLPRegressor
mlp_model = MLPRegressor(hidden_layer_sizes=(100, 50), activation='relu', solver='adam', random_state=42)
# VotingRegressor 생성
voting_regressor = VotingRegressor(estimators=[
("xgb", XGBRegressor(
n_estimators=137,
max_depth=4,
learning_rate=0.10567854073293201,
subsample=0.39344347297910576,
random_state=0
)),
#("ela", elasticnet_model),
#("rf", rf_model),
#("gbr", gbr_model),
#("et", et_model),
#("mlp", mlp_model),
#("cat", cat_model),
("lr", LinearRegression())
])
# 파이프라인 생성
model = Pipeline(steps=[("model", voting_regressor)])
# 모델 학습
model.fit(X_train, y_train)
# 테스트 데이터 예측
y_pred = model.predict(X_test)
# 평가 (MSE와 RMSE)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
print(f"테스트 데이터 MSE: {mse}")
print(f"테스트 데이터 RMSE: {rmse}")
테스트 데이터 MSE: 1180863632903322.0
테스트 데이터 RMSE: 34363696.43829549
[예측 및 성능평가]
# 예측 및 성능 평가 - 베스트 (11/17)
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
# RMSE 계산
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
mse, rmse
#최적의 XGBoost 하이퍼파라미터: {'n_estimators': 173, 'max_depth': 5, 'learning_rate': 0.10906855810380661, 'subsample': 0.48296754965125244}
(1176656501706542.8, 34302427.05271076)
우리끼리 보는 리더보드에서는 그래도 7위 안에 들었는데 ..
막상 본게임에서는 순위가 완전히 하락했다 ..
왤까 ...
'프로젝트' 카테고리의 다른 글
부동산 허위매물 프로젝트 (0) | 2025.02.21 |
---|---|
캐글 중고차 가격 예측 프로젝트 (0) | 2025.02.21 |
이민자 사고 데이터 분석 및 시각화 (0) | 2024.06.22 |