대구 교통사고 피해 예측
데이콘 링크 - https://dacon.io/competitions/official/236193/data
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from datetime import datetime
from workalendar.asia import SouthKorea
from catboost import CatBoostRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRegressor
from sklearn.ensemble import VotingRegressor
#압축풀기
!unzip /content/drive/MyDrive/open.zip
train_df = pd.read_csv('/content/drive/MyDrive/daegu/open/train.csv')
test_df = pd.read_csv('/content/drive/MyDrive/daegu/open/test.csv')
sub_df = pd.read_csv('/content/drive/MyDrive/daegu/open/sample_submission.csv')
ID 사고일시 요일 기상상태 시군구 도로형태 노면상태 사고유형 사고유형 - 세부분류 법규위반 ... 가해운전자 상해정도 피해운전자 차종 피해운전자 성별 피해운전자 연령 피해운전자 상해정도 사망자수 중상자수 경상자수 부상자수 ECLO
0 ACCIDENT_00000 2019-01-01 00 화요일 맑음 대구광역시 중구 대신동 단일로 - 기타 건조 차대사람 길가장자리구역통행중 안전운전불이행 ... 상해없음 보행자 여 70세 중상 0 1 0 0 5
1 ACCIDENT_00001 2019-01-01 00 화요일 흐림 대구광역시 달서구 감삼동 단일로 - 기타 건조 차대사람 보도통행중 기타 ... 상해없음 보행자 남 61세 경상 0 0 1 0 3
2 ACCIDENT_00002 2019-01-01 01 화요일 맑음 대구광역시 수성구 두산동 단일로 - 기타 건조 차대사람 차도통행중 안전운전불이행 ... 상해없음 보행자 남 38세 경상 0 0 1 0 3
3 ACCIDENT_00003 2019-01-01 02 화요일 맑음 대구광역시 북구 복현동 단일로 - 기타 건조 차대차 추돌 안전운전불이행 ... 상해없음 승용 남 36세 중상 0 1 0 0 5
4 ACCIDENT_00004 2019-01-01 04 화요일 맑음 대구광역시 동구 신암동 단일로 - 기타 건조 차대차 추돌 안전운전불이행 ... 상해없음 승용 남 52세 경상 0 0 1 0 3
ID 사고일시 요일 기상상태 시군구 도로형태 노면상태 사고유형
0 ACCIDENT_39609 2022-01-01 01 토요일 맑음 대구광역시 수성구 상동 교차로 - 교차로안 건조 차대사람
1 ACCIDENT_39610 2022-01-01 01 토요일 맑음 대구광역시 수성구 지산동 단일로 - 기타 건조 차대사람
2 ACCIDENT_39611 2022-01-01 04 토요일 맑음 대구광역시 수성구 수성동2가 교차로 - 교차로안 건조 차대차
3 ACCIDENT_39612 2022-01-01 04 토요일 맑음 대구광역시 수성구 신매동 단일로 - 기타 건조 차대차
4 ACCIDENT_39613 2022-01-01 06 토요일 맑음 대구광역시 달서구 감삼동 교차로 - 교차로안 건조 차대차
test_df 를 보니 train_df 에 없는 데이터들이 많았다.
test_df만으로 train_df에만 있는 열을 추론할 수 있을 것 같지 않아서 없는 열은 모두 drop했다.
train_df = train_df[['사고일시', '요일', '기상상태', '시군구', '도로형태', '노면상태', '사고유형', 'ECLO']]
test_df = test_df[['사고일시', '요일', '기상상태', '시군구', '도로형태', '노면상태', '사고유형']]
데이터중에 우리 조가 제일 중요하게 본 부분은 주말, 공휴일과 밤과 새벽이다.
그 시점에 사고가 많지않을까 라는 생각으로 전처리 했다.
# '사고일시' 열을 datetime 형식으로 변환
train_df['사고일시'] = pd.to_datetime(train_df['사고일시'], format='%Y-%m-%d %H')
# '공휴일' 및 '주말' 열 추가
cal = SouthKorea()
train_df['공휴일'] = train_df['사고일시'].apply(lambda x: 1 if cal.is_holiday(x) else 0)
train_df['주말'] = train_df['사고일시'].dt.dayofweek.isin([5, 6]).astype(int)
test_df['사고일시'] = pd.to_datetime(test_df['사고일시'], format='%Y-%m-%d %H')
test_df['공휴일'] = test_df['사고일시'].apply(lambda x: 1 if cal.is_holiday(x) else 0)
test_df['주말'] = test_df['사고일시'].dt.dayofweek.isin([5, 6]).astype(int)
# 시간 범주를 나누어 새로운 열에 인덱스로 추가
bins = [0, 6, 12, 18, 24]
labels = [0, 1, 2, 3]
train_df['시간대'] = pd.cut(train_df['사고일시'].dt.hour, bins=bins, labels=labels, include_lowest=True, right=False)
test_df['시간대'] = pd.cut(test_df['사고일시'].dt.hour, bins=bins, labels=labels, include_lowest=True, right=False)
categorical_cols = ['기상상태', '도로형태', '노면상태', '사고유형']
train_df = pd.get_dummies(train_df, columns=categorical_cols)
test_df = pd.get_dummies(test_df, columns=categorical_cols)
train_df['시간대'] = train_df['시간대'].astype(int)
test_df['시간대'] = test_df['시간대'].astype(int)
train_df = train_df.drop('기상상태_안개', axis=1)
model = CatBoostRegressor(iterations=100, depth=10, learning_rate=0.1, loss_function='RMSE')
X = train_df.drop('ECLO', axis=1)
y = train_df['ECLO']
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
model.fit(X_train, y_train)
y_val_pred = model.predict(X_val)
rmse = mean_squared_error(y_val, y_val_pred, squared=False)
print(f"Validation RMSE: {rmse}")
Validation RMSE: 3.110688184835299
catboost의 경우 public 480/1928 등수를 기록했다.
# RandomForestRegressor 모델 생성
rf_model = RandomForestRegressor(n_estimators=100, max_depth=10, random_state=42)
# 훈련 데이터로 모델 학습
rf_model.fit(X_train, y_train)
# 검증 데이터에 대한 예측 수행
y_val_pred_rf = rf_model.predict(X_val)
# RMSE 계산
rmse_rf = mean_squared_error(y_val, y_val_pred_rf, squared=False)
print(f"Validation RMSE (Random Forest): {rmse_rf}")
Validation RMSE (Random Forest): 3.113345023838463
RandomForest의 경우 public 473/1928 등수를 기록했다.
rf_model2 = RandomForestRegressor(n_estimators=100, max_depth=10, random_state=42)
xgb_model2 = XGBRegressor(n_estimators=100, max_depth=5, learning_rate=0.1, random_state=42)
ensemble_model = VotingRegressor([('rf', rf_model2), ('xgb', xgb_model2)])
ensemble_model.fit(X_train, y_train)
y_val_pred_ensemble = ensemble_model.predict(X_val)
rmse_ensemble = mean_squared_error(y_val, y_val_pred_ensemble, squared=False)
print(f"Validation RMSE (Ensemble): {rmse_ensemble}")
Validation RMSE (Ensemble): 3.112085168550964
앙상블의 경우 public 470/1928 등수를 기록했다.