데이터 분석

네비게이션 도착시간 예측 모델링

lhg010524 2024. 11. 15. 13:53

1. 데이터 불러오기

import pandas as pd
import numpy as np

df = pd.read_csv("onenavi_train.csv", sep="|")
df_eval = pd.read_csv("onenavi_evaluation.csv",sep="|")

# 학습/평가 데이터의 전처리 기준을 통일하기위해 데이터 합본
df_total=pd.concat([df,df_eval],ignore_index=True)

2. 추가 변수 생성

import pandas as pd

df_pnu = pd.read_csv("onenavi_pnu.csv",sep="|") # 주소(시도/시군구 정보)
df_signal = pd.read_csv("onenavi_signal.csv",sep="|") # 경로의 신호등 갯수

df_pnu
df_signal

df_total=pd.merge(df_total,df_pnu , on="RID")
df_total=pd.merge(df_total,df_signal , on="RID")
df_total

3. 데이터 분석하기

!pip install seaborn

import seaborn as sns
import matplotlib.pyplot as plt

# 설치된 폰트 리스트 출력
import matplotlib.font_manager as fm

font_list = [font.name for font in fm.fontManager.ttflist]
font_list

sns.set(font="NanumGothicCoding", 
        rc={"axes.unicode_minus":False}, # 마이너스 부호 깨짐 현상 해결
        style='darkgrid')

ax = sns.countplot(x=df_total['level1_pnu'], palette = "RdBu")

ax = sns.countplot(x=df_total['level1_pnu'], palette = "RdBu")

 

DistChart

x = df_total['signaltype'] # 샘플 생성

sns.distplot(x)
plt.show()

 

Boxplot

sns.boxplot(x = df_total['level1_pnu'], y = df_total['A_DISTANCE'], data = df_total, palette = "RdBu")
plt.show()

sns.boxplot(x = df_total['level1_pnu'], y = df_total['ET'], data = df_total, palette = "RdBu")
plt.show()

 

Heatmap

uniform_data = np.random.rand(10, 12) # 난수로 데이터 만들기

sns.heatmap(uniform_data)
plt.show()

 

Pairplot

sns.pairplot(df_total)
plt.show()

 

상관관계 분석

df_total.corr()

sns.heatmap(df_total.corr(), annot=True, cmap="RdBu")
plt.show()

 

4. 요인 분석

: 중요 요인 분석하는 단계

# FactorAnalyzer는 설치안된 경우가 많을 것입니다. 설치를 먼저 진행합니다.
!pip install factor-analyzer

from factor_analyzer import FactorAnalyzer
from factor_analyzer.factor_analyzer import calculate_kmo

1) Kaiser-Meyer-Olkin (KMO) 검정 : 요인 분석을위한 데이터의 적합성을 측정(0.6 미만의 KMO 값은 부적절한 것으로 간주)

# 요인분석은 수치형변수(int, float 등)으로만 이루어진 데이터에서 가능함으로 문자형 변수는 제거 필요
df.drop(['RID', 'TIME_DEPARTUREDATE', 'TIME_ARRIVEDATE'], axis=1)

kmo_all,kmo_model=calculate_kmo(df.drop(['RID','TIME_DEPARTUREDATE','TIME_ARRIVEDATE'],axis=1))
kmo_model # 0.642878086837649 : 0.6 이상으로 양호함

2) ScreePlot을 활용한 요인수 결정 : Elbow 기법

# 요인분석 오브젝트를 만들고 실행해보겠습니다.
fa = FactorAnalyzer()
fa.set_params(rotation=None)
fa.fit(df.drop(['RID','TIME_DEPARTUREDATE','TIME_ARRIVEDATE'],axis=1))
# 고유값 확인 * 고유값(eigenvalue):각각의 요인으로 설명할 수 있는 변수들의 분산 총합
ev, v = fa.get_eigenvalues()
ev

# Scree Plot을 그려서 Elbow 지점을 찾아봅시다.
plt.scatter(range(1,df.drop(['RID','TIME_DEPARTUREDATE','TIME_ARRIVEDATE'],axis=1).shape[1]+1),ev)
plt.plot(range(1,df.drop(['RID','TIME_DEPARTUREDATE','TIME_ARRIVEDATE'],axis=1).shape[1]+1),ev)
plt.title('Scree Plot')
plt.xlabel('Factors')
plt.ylabel('Eigenvalue')
plt.grid()
plt.show()

3) 요인부하량 확인 및 시각화

# 요인분석 오브젝트를 만들고 실행해보겠습니다.
fa = FactorAnalyzer()
fa.set_params(n_factors=3, rotation=None)
fa.fit(df.drop(['RID','TIME_DEPARTUREDATE','TIME_ARRIVEDATE'],axis=1))
pd.DataFrame(fa.loadings_) # 요인부하량 확인 : 0.4이상 유의미, 0.5이상 중요

# Heat Map으로 그려서 확인해보겠습니다.
plt.figure(figsize=(6,10))
sns.heatmap(fa.loadings_, cmap="Blues", annot=True, fmt='.2f')

4) 크론바흐 계수 계산 : 0.8 이상 양호
# 크론바흐 계수를 계산하는 함수를 선언하겠습니다.
def CronbachAlpha(itemscores):
    itemscores = np.asarray(itemscores)
    itemvars = itemscores.var(axis=0, ddof=1)
    tscores = itemscores.sum(axis=1)
    nitems = itemscores.shape[1]
    return (nitems / (nitems-1)) * (1 - (itemvars.sum() / tscores.var(ddof=1)))
    
# ET와 ETA 신뢰계수
print(CronbachAlpha(df[['ET','ETA']]))

# ET와 ETAA 신뢰계수
print(CronbachAlpha(df[['ET','A_DISTANCE']]))

 

5. LinearRegression 부터 해보자

!pip install statsmodels

# 통계기법에서 LinearRegression
import statsmodels.api as sm

results = sm.OLS(train_y, train_x).fit()

results.summary()

# *** p<0.001, ** p<0.01, * p<0.05
# https://stats.stackovernet.xyz/ko/q/37406

# 기계학습에서 LinearRegression
from sklearn.linear_model import LinearRegression as lr
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

model=lr()
model.fit(train_x, train_y)

print("모델의 회귀계수는 : ", model.coef_, "이고 모델의 절편은 : ",model.intercept_)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

 

6. Random Forest

from sklearn.ensemble import RandomForestRegressor as rfr
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

# 다차원 배열을 1차원으로 평평하게 만들어주기!
train_y = np.ravel(train_y, order='C')

model=rfr(n_estimators=100,max_depth=5,min_samples_split=30,min_samples_leaf=15)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# Feature의 중요도 확인
import matplotlib.pyplot as plt
import seaborn as sns

rf_importances_values = model.feature_importances_
rf_importances = pd.Series(rf_importances_values, index = train_x.columns)
rf_top10 = rf_importances.sort_values(ascending=False)[:10]

plt.rcParams["font.family"] = 'NanumGothicCoding'
plt.figure(figsize=(8,6))
plt.title('Top 10 Feature Importances')
sns.barplot(x=rf_top10, y=rf_top10.index,palette = "RdBu")
plt.show()

 

7. Gradient Boosting

from sklearn.ensemble import GradientBoostingRegressor as grb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

# 다차원 배열을 1차원으로 평평하게 만들어주기!
train_y = np.ravel(train_y, order='C')

model=grb(n_estimators=100,learning_rate=0.1,max_depth=5,min_samples_split=30,min_samples_leaf=15)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# Feature의 중요도 확인
import matplotlib.pyplot as plt
import seaborn as sns

grb_importances_values = model.feature_importances_
grb_importances = pd.Series(grb_importances_values, index = train_x.columns)
grb_top10 = grb_importances.sort_values(ascending=False)[:10]

plt.rcParams["font.family"] = 'NanumGothicCoding'
plt.figure(figsize=(8,6))
plt.title('Top 10 Feature Importances')
sns.barplot(x=grb_top10, y=grb_top10.index,palette = "RdBu")
plt.show()

 

8. XGBoost

from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

# 다차원 배열을 1차원으로 평평하게 만들어주기!
train_y = np.ravel(train_y, order='C')

model=xgb(n_estimators=100,gamma=1,eta=0.1,max_depth=5,reg_lambda=5,reg_alpha=5)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# Feature의 중요도 확인
import matplotlib.pyplot as plt
import seaborn as sns

xgb_importances_values = model.feature_importances_
xgb_importances = pd.Series(xgb_importances_values, index = train_x.columns)
xgb_top10 = xgb_importances.sort_values(ascending=False)[:10]

plt.rcParams["font.family"] = 'NanumGothicCoding'
plt.figure(figsize=(8,6))
plt.title('Top 10 Feature Importances')
sns.barplot(x=xgb_top10, y=xgb_top10.index,palette = "RdBu")
plt.show()

다 같이 확인

from sklearn.linear_model import LinearRegression as lr
from sklearn.ensemble import RandomForestRegressor as rfr
from sklearn.ensemble import GradientBoostingRegressor as grb
from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

import pickle
import joblib
import time

model_list=[
            lr(),
            rfr(),
            grb(),
            xgb()
            ]

# 다차원 배열을 1차원으로 평평하게 만들어주기!
train_y = np.ravel(train_y, order='C')

model_rslt = []
for i in range(len(model_list)):
    start_time = time.process_time()
    model = model_list[i]
    model.fit(train_x, train_y)
    end_time = time.process_time()
    joblib.dump(model, '{}_model.pkl'.format(i)) # 모델 저장, sklearn을 통해서 만들어진 모델은 pkl 파일로 저장
    print(f"* {model} 결과 시작")
    print('----  {0:.5f}sec, training complete  ----'.format(end_time-start_time))
    pred_y = model.predict(test_x)
    model_rslt.append(model)
    print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
    print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))
    print("---------------------------------------------------------------------------")

 

이번엔 딥러닝 모델로 알아보자

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from keras.callbacks import ModelCheckpoint, EarlyStopping

# 모델 만들기 : 아주 간단한 모델

def build_model():
    model = keras.Sequential([
        layers.Dense(64, activation='relu', input_shape=[len(train_x.keys())]),
        layers.Dense(64, activation='relu'),
        layers.Dense(1)
    ])
    
    model.compile(loss='mse', optimizer='adam', metrics=['mae', 'mse'])
    return model

 

tip. 만약 분류 문제라면?

  1. activation설정
  • 마지막 출력층에 Label의 열이 하나고 두 개의 값으로 이루어진 이진분류라면 sigmoid
  • Label의 열이 두개 이상이라면 softmax
  1. loss설정
  • 출력층 activation이 sigmoid 인 경우: binary_crossentropy
  • 출력층 activation이 softmax 인 경우:
    • 원핫인코딩(O): categorical_crossentropy
    • 원핫인코딩(X): sparse_categorical_crossentropy
  1. metrics를 'acc' 혹은 'accuracy'로 지정하면, 학습시 정확도를 모니터링 할 수 있다
# 모델 학습
early_stopping = EarlyStopping(monitor='val_loss', patience=10) # 조기종료 콜백함수 정의

checkpoint_path = 'tmp_checkpoint.ckpt'
cb_checkpoint = ModelCheckpoint(checkpoint_path, save_weights_only=True, monitor='val_loss',
                               verbose=1, save_best_only=True) # 체크포인트 저장

history = model.fit(train_x, train_y, epochs=30,  
                   validation_data = (test_x,test_y),
                    callbacks=[cb_checkpoint, early_stopping]
                    )
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, 30), history.history["loss"], label="train_loss")
plt.plot(np.arange(0, 30), history.history["val_loss"], label="val_loss")
plt.title("Training Loss")
plt.xlabel("Epoch #")
plt.ylabel("Loss")
plt.legend()
plt.show()

plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, 30), history.history["mae"], label="train_mae")
plt.plot(np.arange(0, 30), history.history["val_mae"], label="val_mae")
plt.title("Training mae")
plt.xlabel("Epoch #")
plt.ylabel("mae")
plt.legend()
plt.show()

# 최적 모델 불러오기 및 저장
model.load_weights(checkpoint_path)
model.save("DeeplearningModel.h5")

 

모델 최적화

1. pandas 전략

 

[Panda 전략 Tip : XGBoost 기준]

  • 모델 성능을 높이고 싶다면!
  1. n-estimators는 높게, eta는 낮게
  • 튜닝 예시
  1. n-estimators와 learning_rate를 먼저 지정(n-estimators를 100으로 고정하고 최적 learning_rate 찾기)
  2. 나머지 hyperparameter 튜닝
  3. n-estimators와 learning_rate 조정(둘은 반비례, 꼭 법칙은 아님!)
    • (예시) n-estimators를 2배 늘리면 learning_rate는 1/2로, n-estimators를 10배 늘리면 learning_rate는 1/10
# 1단계 n-estimators와 learning_rate(eta)를 먼저 지정 : eta 0.1 => R-squared Score on Test set : 0.71631
from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

model=xgb(n_estimators=100, eta=0.1)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# 1단계 n-estimators와 learning_rate(eta)를 먼저 지정 : eta 0.2 => R-squared Score on Test set : 0.71680
from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

model=xgb(n_estimators=100, eta=0.2)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# 1단계 n-estimators와 learning_rate(eta)를 먼저 지정 : eta 0.3 => R-squared Score on Test set : 0.70988
from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

model=xgb(n_estimators=100, eta=0.3)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# 2단계 나머지 hyperparameter 튜닝 : 0.71724
from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

model=xgb(n_estimators=100, eta=0.2, 
          max_depth=5, subsample= 0.8, colsample_bytree=0.5, reg_alpha=3, gamma=5)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# 3단계 n-estimators와 learning_rate 조정 : 0.71890
from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score

model=xgb(n_estimators=200, eta=0.1,
          max_depth=5, subsample= 0.8, colsample_bytree=0.5, reg_alpha=3, gamma=5)
model.fit(train_x, train_y)

pred_y = model.predict(test_x)
print("RMSE on Test set : {0:.5f}".format(mean_squared_error(test_y,pred_y)**0.5))
print("R-squared Score on Test set : {0:.5f}".format(r2_score(test_y,pred_y)))

# 모델을 저장합니다.
import pickle
import joblib


joblib.dump(model, '4_model.pkl')

 

Cavier 전략

: Gridsearch 사용

from xgboost import XGBRegressor as xgb
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, r2_score
from sklearn.model_selection import GridSearchCV
import time

params = { 'n_estimators' : [50, 100, 200],
           'learning_rate' : [0, 0.01],
           'max_depth' : [0, 3],
            }

xgb_model = xgb(random_state = 0, n_jobs = 1)
grid_cv = GridSearchCV(xgb_model, param_grid = params, cv = 3, n_jobs = 1)
start_time = time.process_time()
grid_cv.fit(train_x, train_y)
end_time = time.process_time()

print('----  {0:.5f}sec, training complete  ----'.format(end_time-start_time))
print('최적 하이퍼 파라미터: ', grid_cv.best_params_)
print('최고 예측 정확도: {:.4f}'.format(grid_cv.best_score_))

'데이터 분석' 카테고리의 다른 글

가입 고객 유형 예측 모델링  (0) 2024.11.15
악성 사이트 탐지 모델링  (1) 2024.11.15
데이터 전처리 python 코드  (0) 2024.11.14