1019
[8주차 - Day3] ML_basics - 실습
최종 제출 코드
시행착오는 이후에 천천히 업로드
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
dataset = pd.read_csv("./delivery_raw.csv")
df = dataset.copy()
df.head(5)
# 데이터프레임 확인해 본 결과 '\' 해당 문자로 나뉘어 한 줄에 다 출력됨
df = pd.read_csv("./delivery_raw.csv", delimiter='\t')
df
# 데이터 나눈 문자를 delimiter 인자로 처리해 주니 예쁘게 출력됨
df.dtypes
df['created_at_time'] = pd.to_datetime(df['created_at'])
df['actual_delivery_time_time'] = pd.to_datetime(df['actual_delivery_time'])
df['time'] = df['actual_delivery_time_time'] - df['created_at_time']
df['delivery_time'] = df['time'].dt.total_seconds()
df.dtypes
df = df.drop(labels=['time', 'actual_delivery_time', 'created_at',
'created_at_time', 'actual_delivery_time_time'],axis=1)
# 주문 생성 시간과 배달 도착 시간 빼서 총 배달 시간 'delivery_time' 열 생성
df.isnull().sum()
df_del = df.dropna()
df_del.isnull().sum()
df_del.reset_index(drop=False, inplace=True)
df_del = df_del.drop(labels=['index'],axis=1)
df_del
# 결측치 데이터 삭제 후 인덱스 값 조정
df_del['store_primary_category'].value_counts()
category = []
category = df_del['store_primary_category'].unique().tolist()
df_category = df_del['store_primary_category'].to_list()
for i in range(len(df_category)):
df_category[i] = category.index(df_category[i])
df_del['store_primary_category'] = df_category
df_del
# 가게 카테고리 연관성에 반영하기 위해 숫자형 데이터로 바꿔 주기
plt.figure(figsize=(20,15))
sns.heatmap(data = df_del.corr(), annot=True, fmt = '.2f', linewidths=.5, cmap='Blues')
# 상관계수 히트맵 그래프로 쉽게 확인
plt.figure(figsize=(20,8))
sns.violinplot(data=df_del, palette='muted')
plt.xticks(rotation=45)
plt.show()
# 평균값을 크게 벗어나는 값들이 존재하는지 그래프로 확인
for i in list(df_del.columns):
Q1 = df_del[i].quantile(0.25)
Q3 = df_del[i].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
df_del = df_del[df_del[i] > lower_bound]
df_del = df_del[df_del[i] < upper_bound]
df_del
# IQR을 계산하고 해당 값을 이용해 각 열의 이상치 탐지 및 제거
from sklearn.model_selection import train_test_split
train_dataset, val_dataset = train_test_split(df_del, test_size=0.1)
X_train = train_dataset.drop(labels='delivery_time',axis=1)
y_train = train_dataset['delivery_time']
X_val = val_dataset.drop(labels='delivery_time',axis=1)
y_val = val_dataset['delivery_time']
model = LinearRegression()
model.fit(X_train, y_train)
score = model.score(X_train, y_train)
print(f'Train : {score}')
score = model.score(X_val, y_val)
print(f'Test : {score}')
# 학습 데이터: 0.2294 검증 데이터 0.2261
from sklearn.model_selection import GridSearchCV
X = df_del.drop(labels='delivery_time',axis=1)
y = df_del['delivery_time']
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
X_train, X_val, y_train, y_val = train_test_split(X_poly, y, test_size=0.1, random_state=42)
model = Ridge(alpha=11.0)
model.fit(X_train, y_train)
y_pred = model.predict(X_val)
print('학습 평가 : ', model.score(X_train, y_train))
print('검증 평가 : ', model.score(X_val, y_val))
# 데이터 다항회귀와 Ridge모델 등을 적용하여
# 학습 데이터: 0.2627 검증 데이터 0.5868
dataset2 = pd.read_csv("./delivery_raw.csv", delimiter='\t')
dataset2['time'] = pd.to_datetime(dataset2['created_at']).dt.hour
dataset2.loc[(0 <= dataset2['time']) & (dataset2['time'] < 7), 'day'] = 0
dataset2.loc[(7 <= dataset2['time']) & (dataset2['time'] < 11), 'day'] = 1
dataset2.loc[(11 <= dataset2['time']) & (dataset2['time'] < 17), 'day'] = 2
dataset2.loc[(17 <= dataset2['time']) & (dataset2['time'] < 21), 'day'] = 3
dataset2.loc[(21 <= dataset2['time']) & (dataset2['time'] < 24), 'day'] = 4
dataset2.loc[dataset2['time'] == 0, 'day'] = 4
# 데이터 전처리를 더 수행하기 위해 주문이 생성된 시간을 제거하지 않고
# 아침/점심/오후/저녁/밤-새벽 등으로 시간대를 나누어 숫자형으로 저장
Q1 = dataset2['estimated_order_place_duration'].quantile(0.25)
Q3 = dataset2['estimated_order_place_duration'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
dataset2 = dataset2[dataset2['estimated_order_place_duration'] > lower_bound]
dataset2 = dataset2[dataset2['estimated_order_place_duration'] < upper_bound]
dataset2.reset_index(drop=False, inplace=True)
dataset2 = dataset2.drop(labels=['index'],axis=1)
# 'estimated_order_place_duration'열의 이상치 삭제
plt.scatter(dataset2['day'], dataset2['estimated_order_place_duration'], alpha=0.4)
plt.show()
# 그래프를 통해 시간대별로 값이 확연히 차이는 나지만,
# 평균 250 - 450에서 크게 벗어나지 않음을 확인
dataset2['making'] = dataset2['delivery_time'] - dataset2['estimated_order_place_duration'] - dataset2['estimated_store_to_consumer_driving_duration']
ch_dataset = dataset2[['store_id', 'day', 'estimated_order_place_duration']]
mk_dataset = dataset2[['store_id', 'store_primary_category', 'total_items',
'num_distinct_items', 'max_item_price', 'delivery_time']]
del_dataset = dataset2[['market_id', 'day', 'total_onshift',
'total_busy', 'total_outstanding_orders',
'estimated_store_to_consumer_driving_duration']]
# 가게에서 주문을 수락하는 시간
# 가게에서 음식을 제조하는 시간
# 가게에서 주문자에게까지 배달되는 시간을 나누어 계산
pred = []
datasets = [ch_dataset, mk_dataset, del_dataset]
datacolumns = ['estimated_order_place_duration', 'making',
'estimated_store_to_consumer_driving_duration']
for i in range(3):
train_dataset, val_dataset = train_test_split(datasets[i], test_size=0.1)
X_train = train_dataset.drop(labels=datacolumns[i],axis=1)
y_train = train_dataset[datacolumns[i]]
X_val = val_dataset.drop(labels=datacolumns[i],axis=1)
y_val = val_dataset[datacolumns[i]]
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
X_train, X_val, y_train, y_val = train_test_split(X_poly, y, test_size=0.1, random_state=42)
model = Ridge(alpha=10.0)
model.fit(X_train, y_train)
pred.append(model.predict(X_val))
y_pred = sum(pred)
mse = mean_squared_error(y_val, y_pred)
rmse = np.sqrt(mse)
print("평균 제곱 오차 (MSE):", mse)
print("평균 제곱근 오차 (RMSE):", rmse)
print('학습 평가 : ', model.score(X_train, y_train))
print('검증 평가 : ', model.score(X_val, y_val))
for actual, predicted in zip(X_val, y_pred):
underpredictions = (predicted < actual).sum()
total_predictions = len(X_val)
underprediction_ratio = underpredictions / total_predictions
print(f'Under-prediction 비율: {underprediction_ratio:.2%}')
#평균 제곱 오차 (MSE): 29061233.036536735
#평균 제곱근 오차 (RMSE): 5390.847153883769
#학습 평가 : 0.262776247965373
#검증 평가 : 0.25868989235748285
#Under-prediction 비율: 0.32%
pred = []
datasets = [mk_dataset, del_dataset]
datacolumns = ['making',
'estimated_store_to_consumer_driving_duration']
for i in range(2):
train_dataset, val_dataset = train_test_split(datasets[i], test_size=0.1)
X_train = train_dataset.drop(labels=datacolumns[i],axis=1)
y_train = train_dataset[datacolumns[i]]
X_val = val_dataset.drop(labels=datacolumns[i],axis=1)
y_val = val_dataset[datacolumns[i]]
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
X_train, X_val, y_train, y_val = train_test_split(X_poly, y, test_size=0.1, random_state=42)
model = Ridge(alpha=1.0)
model.fit(X_train, y_train)
pred.append(model.predict(X_val))
y_pred = sum(pred) + 700
mse = mean_squared_error(y_val, y_pred)
rmse = np.sqrt(mse)
print("평균 제곱 오차 (MSE):", mse)
print("평균 제곱근 오차 (RMSE):", rmse)
print('학습 평가 : ', model.score(X_train, y_train))
print('검증 평가 : ', model.score(X_val, y_val))
for actual, predicted in zip(X_val, y_pred):
underpredictions = (predicted < actual).sum()
total_predictions = len(X_val)
underprediction_ratio = underpredictions / total_predictions
print(f'Under-prediction 비율: {underprediction_ratio:.2%}')
# 가게에서 주문을 받는 시간이 크게 의미가 없어 보여서 700으로 맞추고 성능 검사
#평균 제곱 오차 (MSE): 11838977.181209398
#평균 제곱근 오차 (RMSE): 3440.7814782705104
#학습 평가 : 0.26277630303647725
#검증 평가 : 0.2586902844903438
#Under-prediction 비율: 0.33%