본문 바로가기
인공지능/데이터분석

호텔 예약 수요 데이터셋

by hyunji00pj 2025. 2. 2.

1. 호텔 예약 수요 데이터셋

  • 데이터셋은 일반적으로 호텔 예약에 대한 수요 패턴을 분석하기 위한 데이터셋입니다. 이 데이터셋은 예약 취소, 체크인 날짜, 고객 유형, 체류 기간, 객실 유형, 예약 경로 등 다양한 요소를 포함하며, 주로 예약 트렌드 분석, 고객 행동 예측, 수요 예측 등에 사용됩니다.
  • https://www.kaggle.com/datasets/jessemostipak/hotel-booking-demand
 

Hotel booking demand

From the paper: hotel booking demand datasets

www.kaggle.com

 

2. 데이터셋 컬럼 설명

  • hotel: 호텔 유형 (Resort Hotel, City Hotel)
  • is_canceled: 예약 취소 여부 (0: 예약 유지, 1: 예약 취소)
  • lead_time: 예약과 실제 체크인 사이의 기간(일 단위)
  • arrival_date_year: 도착 연도
  • arrival_date_month: 도착 월
  • arrival_date_week_number: 해당 주의 주차
  • arrival_date_day_of_month: 도착 일
  • stays_in_weekend_nights: 주말(토, 일) 동안의 숙박일 수
  • stays_in_week_nights: 주중(월~금) 동안의 숙박일 수
  • adults: 성인 투숙객 수
  • children: 어린이 투숙객 수
  • babies: 유아 투숙객 수
  • meal: 예약된 식사 유형
  • country: 고객의 국가
  • market_segment: 예약 시장 세그먼트
  • distribution_channel: 예약 채널 (예: 온라인, 오프라인)
  • is_repeated_guest: 재방문 여부
  • previous_cancellations: 이전 예약 취소 횟수
  • reserved_room_type: 예약된 객실 유형
  • assigned_room_type: 실제 배정된 객실 유형
  • booking_changes: 예약 변경 횟수
  • deposit_type: 보증금 유형 (No Deposit, Non Refund, Refundable)
  • days_in_waiting_list: 대기자 명단에 있었던 일 수
  • customer_type: 고객 유형 (예: Transient, Group)
  • adr: 평균 일일 요금 (유로)
  • required_car_parking_spaces: 주차 공간 요구 수
  • total_of_special_requests: 특별 요청 수
  • reservation_status: 예약 상태 (Check-Out, Canceled, No-Show)
  • reservation_status_date: 예약 상태가 마지막으로 업데이트된 날짜
hotel_df = pd.read_csv('/내드라이브 경로/hotel_bookings.csv')
hotel_df

 

 

데이터 전처리 과정은 생략하였습니다

전처리 후 info

hotel_df.info()

테스트 데이터와 학습 데이터 나누기

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(hotel_df.drop('is_canceled', axis=1), hotel_df['is_canceled'], test_size=0.3, random_state=2025)
X_train.shape, y_train.shape
((81344, 38), (81344,))
X_test.shape, y_test.shape
((34862, 38), (34862,))

3. LogisticRegression

사이킷런의 LogisticRegression은 이진 분류(Binary Classification)와 다중 분류(Multiclass Classification) 문제를 해결하기 위한 머신러닝 알고리즘입니다. 로지스틱 회귀는 선형 모델로, 입력 데이터에 대한 선형 결합을 통해 확률을 예측하고, 이 확률을 로지스틱 함수(시그모이드 함수)를 사용해 이진 또는 다중 클래스에 대한 예측을 수행합니다. 사이킷런의 LogisticRegression은 과적합을 방지하기 위한 규제(Regularization) 기법(penalty)을 지원합니다. 또한, 반복 최적화의 최대 횟수를 max_iter로 설정할 수 있으며, 모델의 성능 평가는 정확도, ROC-AUC 등 다양한 지표를 통해 수행할 수 있습니다. 이 모델은 특히 해석 가능성이 높고, 계산이 효율적이며, 선형적으로 구분 가능한 데이터셋에서 뛰어난 성능을 발휘합니다.

 

※ 규제

규제(Regularization)는 머신러닝 모델이 과적합(Overfitting) 되는 것을 방지하기 위해 사용되는 기법입니다. 과적합은 모델이 학습 데이터에 지나치게 맞춰져서, 새로운 데이터(테스트 데이터)에는 제대로 일반화하지 못하는 현상입니다.

규제는 모델의 복잡도를 줄이고, 불필요한 가중치(Weights)를 작게 만들어 과적합을 방지합니다.

 

 

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(X_train, y_train)

 

  • 반복 횟수가 부족하면 ConvergenceWarning 경고가 나타날 수 있습니다.
  • 이는 알고리즘이 최적해를 찾지 못했다는 의미입니다.
  • max_iter=1000: 최대 1000번 반복하여 최적의 가중치를 찾습니다.
  • 기본값: max_iter=100

4. 데이터 스케일링

데이터 스케일링은 서로 다른 범위와 단위를 가진 데이터를 일정한 범위로 변환하여 모델 학습을 더 효율적으로 수행할 수 있도록 만드는 전처리 과정입니다. 주로 변수 간의 값의 크기 차이가 클 때 발생하는 불균형을 해결하기 위해 사용되며, 대표적인 방법으로 표준화(Standardization)와 정규화(Normalization)가 있습니다. 스케일링을 통해 학습 속도를 높이고, 기울기 소실(Gradient Vanishing) 문제를 완화하며, 특정 변수에 모델이 과도하게 의존하는 것을 방지할 수 있습니다.

 

4-1. 표준화

표준화(Standardization)는 데이터의 평균을 0으로, 표준편차를 1로 변환하여 모든 변수가 동일한 척도를 갖도록 만드는 데이터 전처리 기법입니다. 주로 데이터의 분포가 정규 분포를 따를 때 효과적이며, 값의 크기나 단위가 서로 다른 변수를 비교하거나 머신러닝 알고리즘(예: 로지스틱 회귀, SVM)에서 최적의 성능을 내기 위해 사용됩니다.

 

 

 

4-2. 정규화

정규화(Normalization)는 데이터의 값을 특정 범위(주로 0과 1 사이)로 변환하여 변수 간의 스케일 차이를 줄이는 데이터 전처리 기법입니다. 이는 주로 최소값과 최대값을 사용해 데이터를 조정하며, 대표적인 방법으로 Min-Max Scaling이 있습니다.

 

 

 

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(X_train)
x_test_scaled = scaler.fit_transform(X_test)
x_train_scaled
model = LogisticRegression(max_iter=1000)
model.fit(x_train_scaled, y_train)
pred = model.predict(x_test_scaled)
from sklearn.metrics import accuracy_score
accuracy_score(y_test, pred)
# accuracy_score 회귀에서는 괜찮은 지표지만 분류에서는 아닐 수 있음
0.9293786931329241
hotel_df['is_canceled'].value_counts()

 

5. 혼돈 행렬

혼돈 행렬(Confusion Matrix)은 분류 모델의 성능을 평가하기 위해 사용되는 도구로, 예측 결과와 실제 레이블 간의 관계를 요약하여 나타낸 행렬입니다. 이 행렬은 이진 분류 문제에서 네 가지 값으로 구성됩니다. True Positive (TP), True Negative (TN), False Positive (FP), False Negative (FN). TP와 TN은 모델이 올바르게 예측한 경우를 나타내며, FP와 FN은 모델이 잘못 예측한 경우를 나타냅니다. 이를 통해 분류 모델의 정확도(Accuracy), 정밀도(Precision), 재현율(Recall), F1 점수와 같은 다양한 성능 지표를 계산할 수 있습니다. 혼돈 행렬은 특히 클래스 간 불균형이 있는 데이터에서 모델의 예측 성능을 구체적으로 분석할 때 유용합니다.

 

  • True Positive (TP)
    • 실제값이 양성이고, 모델도 양성으로 올바르게 예측한 경우
    • 예: 실제로 스팸 메일이고, 모델이 스팸 메일로 예측
  • True Negative (TN)
    • 실제값이 음성이고, 모델도 음성으로 올바르게 예측한 경우
    • 예: 실제로 정상 메일이고, 모델이 정상 메일로 예측
  • False Positive (FP)
    • 실제값은 음성이지만, 모델이 양성으로 잘못 예측한 경우
    • 예: 정상 메일을 스팸으로 잘못 예측
  • False Negative (FN)
    • 실제값은 양성이지만, 모델이 음성으로 잘못 예측한 경우
    • 예: 스팸 메일을 정상 메일로 잘못 예측

혼돈 행렬로 계산할 수 있는 지표

 

from sklearn.metrics import confusion_matrix , classification_report, roc_auc_score
confusion_matrix(y_test, pred)
from sklearn.metrics import precision_score, recall_score, f1_score
print(precision_score(y_test, pred))
print(recall_score(y_test, pred))
print(f1_score(y_test, pred))
lr.coef_
#기울기
#독립변수 갯수만큼 나옴
array([[ 9.18793261e-03,  1.44217354e-03,  2.18389627e-02,
         5.96175587e-03, -6.62703157e-02, -9.83973926e-01,
         2.98148521e-03,  1.68179915e-03, -9.12455121e-02,
         1.19331642e-02, -4.56796792e-01, -1.95102426e+00,
        -9.09444902e-02, -8.20492580e-01,  7.18528470e-01,
         9.75744529e-01, -3.77896439e-01, -1.02874693e-02,
         7.56234430e-03, -4.11976995e-01,  5.54643600e-01,
        -2.44669414e-01,  1.02468932e-01,  2.37448194e-04,
        -4.20637895e-01, -3.31488868e-03,  3.97971115e-01,
         3.60541548e-04,  1.31276456e+00, -3.49220810e-03,
        -2.08090538e-02,  7.24630585e-01, -6.14192129e-01,
        -4.98244456e+00,  1.67590552e-01,  4.55759769e-02,
        -2.32558856e-01,  1.48591543e-01]])
lr.intercept_ # 절편
#바이어스값 절편
array([6.40583186e-05])
proba = lr.predict_proba(X_test)
proba
#확률값
#[0일확률, 1일확률]
array([[0.03802158, 0.96197842],
       [0.63404974, 0.36595026],
       [0.97801328, 0.02198672],
       ...,
       [0.94531688, 0.05468312],
       [0.11721987, 0.88278013],
       [0.9862966 , 0.0137034 ]])
proba = lr.predict_proba(X_test)[:, 1]
proba
array([0.96197842, 0.36595026, 0.02198672, ..., 0.05468312, 0.88278013,
       0.0137034 ])
# 임계값 설정
threshold = 0.5
pred = (proba >= threshold).astype(int)
pred
#1과 0으로 바꿔서 데이터각각의 정답 0,1 로 뽑기
array([1, 0, 0, ..., 0, 1, 0])

6. 분류 문제에서의 랜덤 포레스트

랜덤 포레스트는 결정 트리(Decision Trees)를 여러 개 만들어서 결합(앙상블)하여 예측 성능을 향상시키는 앙상블 학습(Ensemble Learning) 기법입니다. 분류 문제에서 랜덤 포레스트는 각 트리의 예측값을 모아서 다수결(Majority Voting)을 통해 최종 클래스를 결정합니다.

  • 각 트리의 노드 분할(Split) 단계에서, 전체 특성이 아닌 무작위로 선택된 일부 특성만을 사용합니다.
  • 이를 통해 트리 간의 상관관계를 줄이고, 과적합을 방지합니다.
  • 각 트리에 들어가는 데이터의 개수는 원본 데이터셋 크기와 동일합니다.(중복 샘플링 될수있다)
  • 그러나 중복을 허용하여 샘플링하므로, 일부 데이터는 여러 번 샘플링되고, 일부 데이터는 선택되지 않을 수 있습니다.
  • 부트스트래핑된 데이터와 랜덤하게 선택된 특성을 사용하여 결정 트리를 학습합니다.
  • 사이킷런(Sklearn)에서 랜덤 포레스트의 기본 트리 개수는 100개입니다.
  • 다수결(Majority Voting): 분류 문제에서 가장 많이 예측된 클래스를 선택합니다.
X_train, X_test, y_train, y_test = train_test_split(hotel_df.drop('is_canceled', axis=1), hotel_df['is_canceled'], test_size=0.3, random_state=2025)
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(random_state=2025)
rf.fit(X_train, y_train)
pred = rf.predict(X_test)
proba = rf.predict_proba(X_test)
proba
array([[0.  , 1.  ],
       [0.02, 0.98],
       [0.96, 0.04],
       ...,
       [1.  , 0.  ],
       [0.99, 0.01],
       [1.  , 0.  ]])
# 첫번째 테스트 데이터에 대한 예측 결과
proba[0]
array([0., 1.])
# 모든 테스트 데이터에 대한 호텔 예약을 취소할 확률만 출력
proba[:,1]
array([1.  , 0.98, 0.04, ..., 0.  , 0.01, 0.  ])
accuracy_score(y_test, pred)
1.0
confusion_matrix(y_test, pred)
array([[22217,     0],
       [    0, 12645]])
print(classification_report(y_test, pred))

 

7. ROC AUC Score

ROC AUC Score(Receiver Operating Characteristic - Area Under the Curve)는 이진 분류 모델의 성능을 평가하는 지표로, 분류기의 예측 능력을 직관적으로 나타냅니다. ROC 곡선은 FPR(거짓 양성 비율)과 TPR(참 양성 비율)을 축으로 하여 다양한 임계값에서 모델의 성능을 시각화한 곡선입니다. AUC(Area Under the Curve)는 이 곡선 아래의 면적을 나타내며, 값이 1에 가까울수록 완벽한 분류 성능을 의미하고, 0.5에 가까울수록 랜덤 추측에 가까운 성능을 나타냅니다. 따라서 ROC AUC Score는 모델의 분류 성능이 얼마나 좋은지를 평가하는 데 중요한 역할을 합니다.

 

7-1. ROC Curve

ROC 곡선은 이진 분류 모델의 성능을 평가하기 위해 사용하는 곡선으로, 모델의 민감도(참 양성 비율, TPR)와 특이도(참 음성 비율, TNR)의 반대인 거짓 양성 비율(FPR)의 관계를 시각화한 그래프입니다.

 

7-2. AUC (Area Under the Curve)

AUC는 ROC 곡선 아래의 면적을 나타내며, 이진 분류기의 성능을 하나의 숫자로 나타내는 지표입니다. AUC는 다음을 의미합니다:

  • AUC = 1: 완벽한 분류기
  • AUC = 0.5: 랜덤 추측 수준
  • AUC < 0.5: 모델 성능이 무작위 추측보다 나쁨

수학적으로 AUC는 양성 클래스와 음성 클래스의 예측 점수를 비교해 양성 클래스가 더 높은 점수를 받을 확률을 나타냅니다.

 
roc_auc_score(y_test, proba[:,1])
1.0
import matplotlib.pyplot as plt
from sklearn.metrics._plot.roc_curve import roc_curve

fpr, tpr, thr = roc_curve(y_test, proba[:, 1])
print(fpr, tpr, thr)

plt.plot(fpr, tpr, label='ROC Curve')
plt.plot([0, 1], [0, 1])
plt.show()

8. 교차 검증

교차 검증 (Cross Validation)은 모델의 성능을 더 정확히 평가하기 위해 데이터를 반복적으로 학습용 데이터와 검증용 데이터로 나누어 사용하는 기법입니다. 가장 일반적인 방식인 k-겹 교차 검증(k-fold Cross Validation)은 데이터를 k개의 동일한 크기로 나누고, 각 부분을 한 번씩 검증 데이터로 사용하며 나머지 부분을 학습 데이터로 사용하여 모델을 훈련하고 평가합니다. 이를 통해 데이터 분할에 따른 편향을 줄이고, 모델의 일반화 성능(새로운 데이터에 대한 예측 능력)을 신뢰성 있게 측정할 수 있습니다. 크로스 밸리데이션은 특히 데이터셋이 작거나 편향된 경우에 유용하며, 과적합(overfitting)을 방지하는 데 도움을 줍니다.

 

from sklearn.model_selection import KFold
kf = KFold(n_splits=5)
kf
KFold(n_splits=5, random_state=None, shuffle=False)
for train_index, test_index in kf.split(range(len(hotel_df))):
    print(train_index, test_index,len(train_index), len(test_index))

 

acc_list = []

for train_index, test_index in kf.split(range(len(hotel_df))):
    X = hotel_df.drop('is_canceled', axis=1)
    y = hotel_df['is_canceled']

    X_train = X.iloc[train_index]
    X_test = X.iloc[test_index]

    y_train = y.iloc[train_index]
    y_test = y.iloc[test_index]

    lr = RandomForestClassifier()
    lr.fit(X_train, y_train)

    pred = lr.predict(X_test)
    acc_list.append(accuracy_score(y_test, pred))
acc_list
[1.0, 1.0, 1.0, 1.0, 1.0]
np.array(acc_list).mean()
1.0