Task : 머신러닝 진행
→ 분류 모델 활용해서 인기도가 어떤 컬럼과 연관성이 있는지(의미 있는지) 컬럼 별로 확인
실행 및 진행 사항 정리
feature_cols = [
'price',
'minimum_nights',
'availability_365',
'reviews_per_month',
'estimated_revenue_per_month',
'daily_guests',
'has_landmark' # 관광지 이름 포함 여부 (0 or 1)
]
target_col = 'is_popular' # 상위 25% 숙소 여부 (0 or 1)
Python
복사
# popularity_score 기준으로 지역 내 분위수로 is_popular 다시 부여
def get_popularity_cat(row):
group = df_filtered[df_filtered['neighbourhood_group'] == row['neighbourhood_group']]['popularity_score']
if len(group) < 4:
return 'Mid'
q25 = group.quantile(0.25)
q75 = group.quantile(0.75)
if row['popularity_score'] >= q75:
return 'High'
elif row['popularity_score'] <= q25:
return 'Low'
else:
return 'Mid'
# 다시 적용
df_filtered['popularity_category'] = df_filtered.apply(get_popularity_cat, axis=1)
df_filtered['is_popular'] = (df_filtered['popularity_category'] == 'High').astype(int)
Python
복사
from sklearn.model_selection import train_test_split
X = df_filtered[feature_cols]
y = df_filtered[target_col]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
Python
복사
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
Python
복사
from sklearn.metrics import classification_report, confusion_matrix
y_pred = model.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
Python
복사
import matplotlib.pyplot as plt
import seaborn as sns
importances = model.feature_importances_
feat_importance = pd.Series(importances, index=feature_cols).sort_values(ascending=True)
plt.figure(figsize=(8, 5))
sns.barplot(x=feat_importance, y=feat_importance.index)
plt.title('Feature Importance')
plt.xlabel('Importance')
plt.ylabel('Feature')
plt.grid(True)
plt.show()
Python
복사
결과
[[5747 75] → 실제 0 (비인기): 5822명 중 5747명 정확히 예측, 75명만 오답
[ 48 1899]] → 실제 1 (인기): 1947명 중 1899명 정확히 예측, 48명만 오답
분석 요약
지표 | 설명 | 값 |
Precision | 내가 '인기 숙소'라고 한 것 중에
실제 몇 %가 맞았나? | 0.96 (1번 기준) |
Recall | 진짜 인기 숙소를 내가 얼마나 잘 찾았나? | 0.98 |
F1-score | Precision이랑 Recall의 조화 평균 | 0.97 |
Accuracy | 전체 데이터 중에 몇 % 맞췄냐? | 0.98 |
해석
•
인기 숙소를 거의 다 찾아냄 (recall 98%)
•
잘못 예측하는 것도 거의 없음 (precision 96%)
•
전체 accuracy 98%면 그냥 이건 너네가 만든 feature들(6개 + 관광지 포함)이
진짜 인기도 예측하는 데 의미 있는 변수라는 걸 보여줌
결론
•
이 정도면 발표할 때 "우리는 머신러닝으로 실제 인기 숙소를 거의 정확하게 분류했습니다."
이 한 마디로 심사위원 눈 돌아간다.
•
다음 스텝은:
1.
feature importance 시각화 (어떤 피처가 중요했는지)
2.
다른 모델 (e.g. RandomForest, XGBoost)도 돌려서 비교
3.
최종 결과 발표 자료에 깔끔한 그래프 + 표 추가
feature importance는 모델이 예측할 때 각 변수에 얼마만큼 기여했는지를 상대적으로 보여주는 값.
그래서 모델 입장에선 "전체 중요도 = 100%"로 두고 각 feature가 몇 %나 영향을 미쳤냐.
•
reviews_per_month가 0.40 → 모델이 예측하는 데 40% 기여했다는 뜻
•
daily_guest 0.26 → 26% 기여
•
has_landmark가 0.01 → 거의 영향 없음 ㅋㅋ
우리 팀이 만든 feature 중에서 reviews_per_month, daily_guest, estimated_revenue_per_month
요 세 개가 거의 모든 예측을 다 잡고 있다는 뜻.
반대로 has_landmark 같은 건 좋은 아이디어지만 실제론 영향 미미했다.
→ 발표할 때 "재밌는 가설이었지만, 실측 결과는 약했다" 이렇게 말하면 개간지.
추가로 해볼 것
•
상위 3개 변수만 써서 돌려도 성능 괜찮은지 비교 → 성능 유지되면 feature selection 성공임
•
permutation importance로도 한 번 더 확인하면 신뢰도 ↑
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, confusion_matrix
# 핵심 피처만 추출
top_features = ['reviews_per_month', 'daily_guests', 'estimated_revenue_per_month']
X_top = df_filtered[top_features]
y = df_filtered['is_popular']
# 결측치 제거
X_top = X_top.dropna()
y = y.loc[X_top.index]
# 훈련/테스트 나누기
X_train, X_test, y_train, y_test = train_test_split(X_top, y, test_size=0.3, random_state=42)
# 모델 훈련
model_top = RandomForestClassifier(random_state=42)
model_top.fit(X_train, y_train)
# 예측 및 평가
y_pred = model_top.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
Python
복사
실제 0 (비인기) | 실제 1 (인기) | |
예측 0 (비인기) | 8688 (TN) | 123 (FN) |
예측 1 (인기) | 89 (FP) | 2753 (TP) |
성능 지표
•
정확도 (accuracy): 0.98 → 전체 예측 중 98%가 맞음
•
정밀도 (precision):
◦
인기 숙소(1)에 대해서: TP / (TP + FP) = 2753 / (2753 + 89) ≈ 0.97
◦
→ 예측한 인기 숙소 중 97%가 진짜 인기 숙소
•
재현율 (recall):
◦
인기 숙소(1)에 대해서: TP / (TP + FN) = 2753 / (2753 + 123) ≈ 0.96
◦
→ 실제 인기 숙소 중 96%를 잘 맞춤
•
F1-score: 0.96 → 정밀도와 재현율 사이 절충값
이 모델은 인기도 예측을 거의 완벽하게 잘함
→ 실전 배포용으로도 충분히 쓸만한 모델 성능.
Permutation Importance 결과:
“이 피처가 빠지면 성능이 얼마나 떨어지냐”를 수치화
결과 해석
Feature | 중요도 (Weight) | 의미 요약 |
reviews_per_month | 0.1739 | 가장 중요. 리뷰가 많을수록 인기 숙소다는 걸 모델이 강하게 인식함. |
estimated_revenue_per_month | 0.1151 | 수익성 높은 숙소가 인기도 높음. 당연한 귀결. |
daily_guests | 0.0355 | 방문자 수는 의미 있긴 한데 상대적으로 낮은 영향 |
minimum_nights | 0.0011 | 거의 영향 없음 |
price | 0.0007 | 인기랑 가격은 직접적인 관련 거의 없음 |
availability_365 | 0.0005 | 예약 가능일은 모델 입장에서 크게 쓸모 없는 피처 |
has_landmark | 0.0003 | 숙소 이름에 관광지 있어도 모델은 별 의미 없다 봄 |
결론 요약
•
진짜로 중요한 건 리뷰 수, 수익, 그리고 방문자 수
•
관광지 이름 같은 건 우리가 직관적으로 중요하다 생각했는데, 모델은 안 중요하게 봄
•
나머지 피처들은 걍 있는 둥 마는 둥 수준
발표용으로 한 줄 요약:
"인기 숙소를 구분 짓는 핵심 변수는 리뷰 수와 예상 수익이었고, 관광지 이름이나 가격, 예약 가능일은 실제로는 거의 영향이 없었습니다."
.png&blockId=21b2dc3e-f514-818b-b72b-f9aade6351bf)




