로지스틱 회귀 모델을 활용하여 고객 재구매를 예측하는 보고서 쓰기
import pandas as pd
import matplotlib.pyplot as plt
import koreanize_matplotlib
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 데이터 로드
df = pd.read_csv("customer_repurchase.csv")
# 할인쿠폰사용여부 재구매여부 관계 시각화
plt.figure(figsize=(8, 5))
sns.barplot(x="Used Discount", y="Repurchased", data=df, ci=None, palette="coolwarm")
plt.title("할인쿠폰 사용 여부에 따른 재구매율")
plt.xlabel("Used Discount (0=No, 1=Yes)")
plt.ylabel("재구매율 (Repurchase Rate)")
plt.ylim(0, 1) # 0~1 범위로 고정
plt.show()
# 고객등급과 재구매여부 비교
plt.figure(figsize=(8, 5))
sns.barplot(x="Loyalty Tier", y="Repurchased", data=df)
plt.title("고객등급에 따른 재구매여부 비교")
plt.xlabel("Loyalty Tier (0=No, 1=Yes)")
plt.ylabel("Conversion Rate")
plt.show()
plt.figure(figsize=(12, 5))
# 첫 구매 금액 vs. 재구매 여부
plt.subplot(1, 2, 1)
sns.boxplot(x="Repurchased", y="First Purchase Amount ($)", data=df, palette="Set3")
plt.title("첫 구매 금액과 재구매 여부")
# 첫 구매 후 경과일 vs. 재구매 여부
plt.subplot(1, 2, 2)
sns.boxplot(x="Repurchased", y="Days Since First Purchase", data=df, palette="Set2")
plt.title("첫 구매 후 경과일과 재구매 여부")
plt.tight_layout()
plt.show()
# 데이터셋 분리
X = df.drop(columns=["Repurchased"])
y = df["Repurchased"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 로지스틱 회귀 모델 학습
model = LogisticRegression()
model.fit(X_train, y_train)
# 예측 및 평가
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"모델 정확도: {accuracy:.2f}")
print("분류 보고서:\n", classification_report(y_test, y_pred))
# 혼동 행렬 시각화
plt.figure(figsize=(6, 4))
sns.heatmap(confusion_matrix(y_test, y_pred), annot=True, fmt='d', cmap='Blues')
plt.title("혼동 행렬")
plt.xlabel("Predicted Label")
plt.ylabel("True Label")
plt.show()
- 고객이 첫 구매 이후 재구매를 할 가능성을 분석하여 재구매 유도 마케팅 전략을 최적화한다.
- 로지스틱 회귀 모델을 활용하여 어떤 고객이 다시 구매할 가능성이 높은지 예측하고, 고객 충성도를 높이기 위한 프로모션 전략을 도출한다.
분석 목표
- 재구매율이 높은 고객의 특성을 파악하여 타겟 마케팅 전략을 개선.
- 할인 쿠폰 제공이 고객 재구매에 미치는 영향을 분석하여 프로모션 전략 최적화.
- VIP 고객과 일반 고객의 재구매 패턴을 비교하여 맞춤형 마케팅 전략 수립.




모델 성능 평가 및 다중 분류 개념
- 로지스틱 회귀 같은 이진 분류(Binary Classification / Binary Decision) 모델과 다중 분류(Multi-Class Classification) 모델을 평가하는 방법이 다를 수 있다.
모델 성능 평가 방법
- 머신러닝 모델을 평가할 때 자주 사용되는 주요 지표
(1) 정확도(Accuracy)
- 전체 샘플 중 올바르게 분류된 비율을 의미.
- 정확도가 높을수록 모델이 데이터를 잘 예측하고 있다고 볼 수 있다.
- 하지만 데이터가 불균형한 경우(Positive/Negative 비율 차이가 클 때), 정확도만으로 평가하면 모델 성능을 과대평가할 가능성이 있음.

※ 분자는 정답이고 분모는 전체
(2) 정밀도(Precision)
- 모델이 긍정 클래스(1, Positive) 라고 예측한 것 중 실제로 맞춘 비율을 의미.
- FP(실제로는 0인데 1이라고 예측한 경우)를 줄이는 데 초점을 맞춘다.

(3) 재현율(Recall)
- 실제로 긍정 클래스(1, Positive) 인 샘플 중 모델이 맞춘 비율을 의미.
- FN(실제로 1인데 0으로 예측한 경우)를 줄이는 데 초점을 맞춘다.

(4) F1-Score
- 정밀도(Precision)와 재현율(Recall)의 조화 평균.
- 데이터 불균형이 심한 경우, 단순한 정확도(Accuracy)보다 더 신뢰할 수 있는 평가 지표.
- Precision과 Recall 간 균형을 맞추는 데 유용함.

(5) ROC-AUC (Receiver Operating Characteristic - Area Under Curve)
- ROC는 정확도의 변화량을 볼때 쓴다. (AUC보단 ROC를 더 많이 쓴다.)
- ROC 곡선은 모델의 분류 성능을 시각적으로 평가하는 방법이다.
- AUC 값이 1에 가까울수록 모델이 긍정 클래스와 부정 클래스를 잘 구분한다는 의미.
- 임계값(Threshold)에 따라 Precision-Recall이 변화하는 경향을 분석 가능.
다중 분류(Multi-Class Classification)
이진 분류(Binary Classification)는 두 개의 클래스를 구분하는 문제이지만,
다중 분류(Multi-Class Classification) 는 세 개 이상의 클래스를 분류하는 문제이다.
- 손글씨 숫자 인식 (MNIST 데이터셋) → 0~9까지의 10개 숫자를 분류
- 상품 추천 시스템 → 고객을 여러 구매 성향(High-Spender, Medium-Spender, Low-Spender)으로 분류
(1) 소프트맥스 함수(Softmax Function) - 많이 씀
로지스틱 회귀는 이진 분류에서 시그모이드(Sigmoid) 함수를 사용하지만,
다중 분류에서는 소프트맥스(Softmax) 함수를 사용한다.
- 소프트맥스 함수는 각 클래스에 대한 확률 값을 출력하며, 확률 합은 항상 1이 된다.
- 가장 확률이 높은 클래스를 최종 예측값으로 선택.

(2) One-vs-Rest (OvR) 방식 - 별로 안씀
- 각 클래스를 이진 분류 문제로 변환하여 여러 개의 로지스틱 회귀 모델을 훈련하는 방식.
- 예시 (0~9 숫자 분류) : "0"과 "나머지", "1"과 "나머지", ..., "9"와 "나머지" 총 10개의 모델을 학습.
- 간단하고 빠르게 학습 가능하지만, 클래스 간 상관관계 학습이 어려울 수 있음.
(3) One-vs-One (OvO) 방식 - 별로 안씀
- 각 두 개의 클래스를 비교하는 방식으로 N(N - 1)/2 개의 모델을 학습.
- 예시 (0~9 숫자 분류) : (0,1), (0,2), (0,3), ..., (8,9) 총 45개의 모델을 학습.
- 데이터가 많을 경우 계산량이 많아질 수 있음.
다중 분류 모델 평가 방법
- 이진 분류와 마찬가지로 다중 분류에서도 정확도, Precision, Recall, F1-score 등을 활용하여 모델 성능을 평가할 수 있다. 다만 다중 분류에서는 각 클래스별로 Precision, Recall, F1-score를 구한 후 평균을 내는 방법을 사용한다.
(1) 매크로 평균(Macro Average)
- 각 클래스별 Precision, Recall, F1-score를 계산한 후 평균을 구함.
- 클래스의 샘플 수와 관계없이 동일한 가중치를 부여.
- 클래스 균형이 맞을 때 적절한 평가 방식.

(2) 가중 평균(Weighted Average)
- 클래스별 샘플 수(가중치)를 반영하여 평균을 계산.
- 데이터 불균형이 존재할 때 더 적절한 평가 방식.

(3) 마이크로 평균(Micro Average)
- 전체 샘플을 기준으로 TP, FP, FN을 합산하여 Precision, Recall, F1-score를 계산.
- 샘플 개수가 많을수록 더 높은 비중을 반영.
- 다중 분류 모델을 학습하고 평가하는 코드 예제
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.datasets import load_digits
# 다중 클래스 데이터셋 로드 (손글씨 숫자 데이터)
digits = load_digits()
X = digits.data
y = digits.target
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 다중 분류 로지스틱 회귀 모델 학습 (소프트맥스 사용)
model = LogisticRegression(max_iter=1000, multi_class="multinomial", solver="lbfgs")
model.fit(X_train, y_train)
# 예측 및 평가
y_pred = model.predict(X_test)
print("정확도(Accuracy):", model.score(X_test, y_test))
print("분류 보고서(Classification Report):\n", classification_report(y_test, y_pred))
# 혼동 행렬 시각화
plt.figure(figsize=(8,6))
plt.imshow(confusion_matrix(y_test, y_pred), cmap='Blues', interpolation='nearest')
plt.colorbar()
plt.title("혼동 행렬 (Confusion Matrix)")
plt.xlabel("Predicted Label")
plt.ylabel("True Label")
plt.show()


모델 성능을 평가할 때 Accuracy, Precision, Recall, F1-score, ROC-AUC 등을 활용해야 한다.
이진 분류와 다중 분류는 평가 방식이 다르며, 다중 분류에서는 Macro, Weighted, Micro 평균을 고려해야 한다.
실전에서는 클래스 불균형 여부를 고려하여 적절한 평가 방법을 선택하는 것이 중요하다.
- 로지스틱 회귀(Logistic Regression)를 이용한 다중 분류(Multiclass Classification) 예시
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.linear_model import LogisticRegression
# 1. 가상의 마케팅 데이터 생성
data = {
'age': [22, 45, 25, 47, 35, 50, 29, 41, 60, 33, 39, 28, 42, 23, 37],
'spending_score': [80, 55, 90, 40, 70, 35, 85, 50, 20, 75, 65, 88, 45, 95, 60],
'ad_click_rate': [0.9, 0.3, 0.8, 0.2, 0.7, 0.1, 0.85, 0.4, 0.05, 0.75, 0.6, 0.88, 0.35, 0.92, 0.5],
'email_open_rate': [0.95, 0.4, 0.9, 0.3, 0.75, 0.2, 0.89, 0.5, 0.1, 0.78, 0.65, 0.91, 0.37, 0.96, 0.55],
'engagement_level': ['High', 'Medium', 'High', 'Low', 'High', 'Low', 'High', 'Medium', 'Low',
'High', 'Medium', 'High', 'Medium', 'High', 'Medium']
}
df = pd.DataFrame(data)
# 2. 독립변수(X)와 종속변수(y) 설정
X = df[['age', 'spending_score', 'ad_click_rate', 'email_open_rate']]
y = df['engagement_level']
# 3. 라벨 인코딩 (문자 → 숫자 변환)
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)
# 4. 데이터 정규화
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 5. 훈련/테스트 데이터 분할 (7:3 비율)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_encoded, test_size=0.3, random_state=42, stratify=y_encoded)
# 6. 로지스틱 회귀 모델 훈련 (다중 분류)
model = LogisticRegression(multi_class='multinomial', solver='lbfgs', max_iter=200)
model.fit(X_train, y_train)
# 7. 테스트 데이터 예측
y_pred = model.predict(X_test)
# 8. 예측 결과 출력
print("테스트 데이터 예측 결과:")
for i, pred in enumerate(y_pred):
print(f"테스트 데이터 {i+1}: 예측된 참여 수준 - {label_encoder.inverse_transform([pred])[0]}")
각 고객의 나이, 소비 점수, 광고 클릭률, 이메일 오픈율을 바탕으로 고객이 해당 캠페인에 얼마나 적극적으로 반응할지(High, Medium, Low) 예측하는 모델을 활용하여 타겟 고객을 분류하고 맞춤형 마케팅 전략을 수립할 수 있다.
- 기업은 고객의 행동 패턴을 분석하여 적극적인 반응을 보일 고객층(High Engagement) 을 대상으로 집중적인 마케팅 전략을 수행할 수 있다.
- 반대로, 반응이 낮은 고객층(Low Engagement) 에게는 보다 효과적인 광고 소재나 재참여 유도 전략을 제공할 수 있다.
- 데이터를 지속적으로 업데이트하여 모델의 예측 성능을 개선할 수 있다.
결정 트리(Decision Tree) 기본 개념
- 트리 구조를 사용하여 데이터를 분류하거나 회귀하는 지도 학습 알고리즘. (라벨 존재)
- 트리의 각 노드는 특정 특징(feature)을 기준으로 데이터를 나누는 역할을 하며, 최종적으로 예측값(클래스 또는 수치)을 도출.
결정 트리의 구조
- 루트 노드(Root Node):
- 데이터가 처음 입력되는 노드
- 가장 중요한 특징(Feature)을 기준으로 데이터를 나누는 역할
- 내부 노드(Internal Nodes):
- 특정 특징을 기준으로 데이터를 분할(Split) 하는 역할
- 각 노드는 질문(조건문)을 포함하며, 예/아니오(Yes/No) 또는 특정 범위에 따라 데이터를 나눈다.
- 가지(Branches):
- 하나의 노드에서 데이터를 나누는 경로
- 각 조건을 만족하는 데이터는 새로운 노드(자식 노드)로 이동
- 단말 노드(Leaf Nodes):
- 더 이상 데이터를 나누지 않는 최종 노드
- 분류 문제에서는 클래스(0, 1, …) 를 나타내고, 회귀 문제에서는 수치 예측 값을 나타냄

결정 트리 학습 과정
결정 트리는 데이터를 기반으로 최적의 특징(feature)과 분할 조건(Split Condition)을 찾아 트리를 성장시키는 방식으로 학습한다.

(1) 분할 기준(Splitting Criteria) - 나뉘는 기준점을 보면 된다.
- 결정 트리는 데이터를 분할할 때 어떤 특징(feature)이 가장 효과적으로 데이터를 나눌 수 있는지를 평가해야 한다.
- 이를 위해 엔트로피(Entropy)와 지니 지수(Gini Index) 같은 수식을 사용하여 정보 이득(Information Gain) 을 계산한다.

※ 확률이 0.5일때 엔트로피는 1이다 → 안좋은거임.
※ Impurity Measure - 불순도, 불확도
※ 엔트로피(Entropy)와 지니 계수(Gini Index) 실생활 사례
1. 엔트로피(Entropy)
- 편의점에서 손님이 어떤 음료를 선택할까?
- 편의점에서 손님이 콜라(50%), 사이다(50%) 를 고를 확률이 같다면, 어떤 음료를 선택할지 예측이 어렵다.
- 이 경우 엔트로피(불확실성)가 높음 → 엔트로피 값 ≈ 1
- 반면, 손님이 콜라(90%), 사이다(10%) 를 선택한다면?
- 콜라를 선택할 가능성이 매우 높아 예측이 쉬움 → 엔트로피 값 ≈ 0.47 (낮음)
결론:
- 엔트로피가 높을수록 선택이 랜덤(불확실)하므로, 데이터를 더 정밀하게 분류해야 함.
- 결정 트리는 엔트로피가 가장 크게 줄어드는(정보 이득이 높은) 기준으로 데이터를 나눔.
2. 지니 계수(Gini Index)
- 농구팀에서 선수 선발하기
- 농구팀을 꾸릴 때, 신장(키)에 따라 선수 선발을 한다고 가정하자.
- 만약 선수 10명 중 5명이 190cm 이상, 5명이 180cm 이하라면?
- 불순도가 높음 (팀 구성이 균등하여 선택이 어렵다) → 지니 계수 ≈ 0.5 (최대값)
- 하지만 선수 9명이 190cm 이상이고, 1명만 180cm 이하라면?
- 대부분 키가 크므로 불순도가 낮다 → 지니 계수 ≈ 0.18 (낮음)
결론:
- 지니 계수가 낮을수록 특정 그룹으로 쉽게 분류할 수 있음.
- 결정 트리는 지니 계수가 가장 낮아지는 기준으로 데이터를 나눔.
3. ☆ 엔트로피 vs 지니 계수 차이 ☆
비교 항목 | 엔트로피(Entropy) | 지니 계수(Gini Index) |
개념 | 불확실성을 측정 | 그룹 간 불순도를 측정 |
최대값 | 0.5 vs 0.5 (동일 확률일 때) | 0.5 vs 0.5 (동일 확률일 때) |
최소값 | 0 (완전히 한쪽으로 치우침) | 0 (완전히 한쪽으로 치우침) |
특징 | 더 정밀하게 분류 | 계산이 더 빠름 |
사용 예제 | 광고 클릭 여부 예측 | 고객 만족도 그룹 분류 |
4. 실무 적용
- 엔트로피: 고객이 구매할 상품을 예측할 때 → 정보 이득(Information Gain)이 높은 기준으로 데이터를 나눔
- 지니 계수: 병원에서 질병 유무를 판단할 때 → 빠르고 간결한 계산으로 그룹을 나눔
둘 다 불순도를 낮추는 역할을 하지만, 지니 계수는 계산이 더 빠르고, 엔트로피는 좀 더 정밀한 분류를 유도. 따라서 실제 프로젝트에서는 두 방법을 비교하여 더 좋은 결과를 내는 방식을 선택하는 것이 중요함.
# 엔트로피(Entropy)
- 데이터의 불확실성(혼잡도, Randomness) 을 측정하는 값
- 값이 낮을수록 불확실성이 적으며, 하나의 클래스에 가까운 데이터
- 엔트로피가 가장 크게 감소하는 기준으로 데이터를 분할함


# 지니 지수(Gini Index)
- 불순도(Impurity)를 측정하는 값
- 낮을수록 데이터가 특정 클래스에 속할 확률이 높음
- 지니 지수가 낮을수록 불순도가 낮으며, 해당 특징을 기준으로 데이터를 나누는 것이 효과적임

- 엔트로피와 지니계수를 구하는 코드
import numpy as np
def calculate_gini(labels):
"""
지니 계수(Gini Index)를 계산하는 함수
- 공식: Gini = 1 - sum(p_i^2)
- 값이 낮을수록 한쪽 클래스에 집중된 데이터
labels: 리스트 형태의 클래스 라벨 (예: [0, 1, 1, 0, ...])
반환값: 지니 계수 (0~1 사이 값)
"""
unique_classes, counts = np.unique(labels, return_counts=True) # 각 클래스의 개수 계산
probabilities = counts / len(labels) # 각 클래스의 확률 계산
gini = 1 - np.sum(probabilities**2) # 지니 계수 계산
return gini
# 지니계수 - 각 클래스 확률의 제곱을 다 더해서 그 값을 1에서 빼면 된다.
def calculate_entropy(labels):
"""
엔트로피(Entropy)를 계산하는 함수
- 공식: Entropy = -sum(p_i * log2(p_i))
- 값이 낮을수록 한쪽 클래스에 집중된 데이터
labels: 리스트 형태의 클래스 라벨 (예: [0, 1, 1, 0, ...])
반환값: 엔트로피 값 (0~1 사이 값, 균등할수록 1에 가까움)
"""
unique_classes, counts = np.unique(labels, return_counts=True) # 각 클래스의 개수 계산
probabilities = counts / len(labels) # 각 클래스의 확률 계산
entropy = -np.sum(probabilities * np.log2(probabilities)) # 엔트로피 계산
return entropy
# 엔트로피 - 각 클래스의 확률에 대해 로그를 취하고 그 로그값과 확률을 곱하고 그것들의 합을 구해서 그 부호를 바꾼것.
# 예제 데이터 (0: "구매 안 함", 1: "구매")
labels = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1] # 0이 4개, 1이 6개 (비율: 0.4 vs 0.6)
# 지니 계수 및 엔트로피 계산
gini_value = calculate_gini(labels)
entropy_value = calculate_entropy(labels)
# 결과 출력
print(f"지니 계수: {gini_value:.4f}") # 0.4800 (순도가 낮음)
print(f"엔트로피: {entropy_value:.4f}") # 0.9709 (데이터가 혼합됨)
결과 :
지니 계수: 0.4800 엔트로피: 0.9710
(2) 가지치기(Pruning)
- 결정 트리가 과적합(Overfitting) 되는 것을 방지하기 위해 불필요한 가지(branch)를 제거하는 과정
- 너무 많은 노드를 사용하면 데이터에 너무 맞춰진 복잡한 모델(Overfitting) 이 될 수 있음
# 사전 가지치기(Pre-Pruning)
- 트리가 성장하는 동안 미리 제한 조건을 설정하여 과적합을 방지
- 예제:
- 트리의 최대 깊이(Max Depth) 제한
- 최소 샘플 수(Min Samples Split) 제한
# 사후 가지치기(Post-Pruning)
- 먼저 트리를 최대한 성장시킨 후, 성능이 저하되지 않는 범위에서 가지를 제거하는 방법
- 불필요한 노드를 제거하여 모델을 단순화
결정 트리의 장점과 단점
# 장점
- 해석이 쉬움(Interpretability)
- 트리 구조는 직관적이며 사람이 이해하기 쉬움
- "이 특징이 특정 값보다 크면 A, 작으면 B" 같은 논리적 규칙 기반으로 분류 가능
- 전처리가 거의 필요 없음
- 스케일링(Scaling) 필요 없음 (예: Min-Max Scaling, Standardization 불필요)
- 결측치(Missing Values)와 이상치(Outlier)에 강함 - 결측치가 생겨도 빨리 판단 가능.
- 범주형 및 연속형 데이터 모두 처리 가능
- 숫자형 변수와 범주형 변수를 모두 다룰 수 있음
# 단점
- 과적합(Overfitting) 위험
- 트리가 너무 깊어지면 데이터에 너무 맞춰져 새로운 데이터 예측 성능이 낮아질 수 있음
- 해결 방법: 가지치기(Pruning) 또는 최소 샘플 수 제한 적용
- 작은 변화에도 민감(High Variance)
- 데이터가 조금만 바뀌어도 트리의 구조가 크게 달라질 수 있음
- 해결 방법: 랜덤 포레스트(Random Forest)와 같은 앙상블 기법 적용
- 비효율적인 분할 가능성
- 일부 데이터에서는 균형이 맞지 않는 트리(Unbalanced Tree) 가 생성될 수 있음
※ 지니 계수(Gini Index)와 엔트로피(Entropy)에 의해 결정되는 임계값 예제
(1) 데이터 생성
아래 데이터는 특징 값(Feature)과 클래스(Label)로 이루어진 간단한 데이터셋이다.
특징 값이 5 이하일 때 클래스 0, 6 이상일 때 클래스 1로 분류된다.
(2) 코드 구현 (지니 계수와 엔트로피 비교)
import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
# 간단한 데이터 생성
X = np.array([[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]) # 특징값
y = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1]) # 클래스 값 (0 또는 1)
# 지니 계수를 사용한 결정 트리 모델
tree_gini = DecisionTreeClassifier(criterion="gini", max_depth=1, random_state=42)
tree_gini.fit(X, y)
# 엔트로피를 사용한 결정 트리 모델
tree_entropy = DecisionTreeClassifier(criterion="entropy", max_depth=1, random_state=42)
tree_entropy.fit(X, y)
# 임계값 출력
print("지니 계수를 사용한 분할 기준:", tree_gini.tree_.threshold[0])
print("엔트로피를 사용한 분할 기준:", tree_entropy.tree_.threshold[0])
(3) 코드 설명
- X: 1부터 10까지의 숫자로 이루어진 특징 값.
- y: 5 이하일 때 클래스 0, 6 이상일 때 클래스 1로 분류됨.
- DecisionTreeClassifier(criterion="gini"): 지니 계수를 사용한 트리 학습.
- DecisionTreeClassifier(criterion="entropy"): 엔트로피를 사용한 트리 학습.
- tree.tree_.threshold[0]: 트리에서 최초로 데이터를 나눈 임계값(Split Point)을 출력.
(4) 결과 예측
- 지니 계수와 엔트로피는 데이터에서 가장 최적의 분할 기준(임계값)을 자동으로 계산한다.
- 결과:
- 두 방식 모두 5.5를 기준으로 데이터를 나눔.
- 하지만 특정 데이터셋에서는 다른 임계값이 선택될 수도 있음.
- 지니 계수를 사용한 분할 기준: 5.5 / 엔트로피를 사용한 분할 기준: 5.5
지니 계수와 엔트로피는 결정 트리의 분할 기준을 정하는 핵심 요소.
지니 계수는 계산이 빠르고, 엔트로피는 정보 이득을 극대화하는 경향이 있음.
둘의 차이는 크지 않지만, 특정 데이터에서는 다르게 작용할 수 있음.
- 결정 트리 모델을 학습하고 평가하는 예제
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score, classification_report
# 데이터 생성
np.random.seed(42)
n_samples = 200
X1 = np.random.randint(1, 100, n_samples) # Feature 1
X2 = np.random.randint(1, 100, n_samples) # Feature 2
y = (X1 + X2 > 100).astype(int) # 단순한 이진 분류 기준
df = pd.DataFrame({"Feature 1": X1, "Feature 2": X2, "Label": y})
# 데이터 분리
X = df[["Feature 1", "Feature 2"]]
y = df["Label"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 결정 트리 모델 학습
tree_model = DecisionTreeClassifier(max_depth=3, random_state=42)
tree_model.fit(X_train, y_train)
# 예측 및 평가
y_pred = tree_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"모델 정확도: {accuracy:.2f}")
print("분류 보고서:\n", classification_report(y_test, y_pred))
# 트리 시각화
plt.figure(figsize=(10, 6))
plot_tree(tree_model, feature_names=["Feature 1", "Feature 2"], class_names=["Class 0", "Class 1"], filled=True)
plt.title("결정 트리 구조")
plt.show()


- 결정 트리는 특징을 기반으로 데이터를 분할하여 예측하는 모델이며, 해석이 쉬운 머신러닝 알고리즘이다.
- (예측의 기준점은 엔트로피와 지니계수)
- 과적합을 방지하기 위해 가지치기(Pruning)와 트리 깊이 제한(Max Depth)을 조절해야 한다.
- 랜덤 포레스트(Random Forest) 와 같은 앙상블 기법을 사용하면 결정 트리의 단점을 보완할 수 있다.
- 다양한 산업에서 의사 결정 시스템, 신용 평가, 의료 진단, 마케팅 분석 등 광범위하게 활용된다. → 다만 데이터가 간단할때만 쓴다. 데이터가 복잡해지면 불확실성이 높다.
- 의사결정트리를 이용하여 고객의 구매 여부를 예측하기 (분류)
변수명
|
설명
|
방문 빈도(Frequency)
|
최근 한 달 동안 웹사이트 방문 횟수
|
평균 구매 금액(Avg_Purchase_Amount)
|
고객이 과거에 평균적으로 지출한 금액
|
이메일 캠페인 반응 여부(Email_Response)
|
이메일 마케팅에 반응했는지 여부 (1: 예, 0: 아니오)
|
소셜 미디어 활동(Social_Media_Activity)
|
소셜 미디어에서 브랜드 콘텐츠와 상호작용한 횟수
|
구매 여부(Purchase)
|
제품을 구매했는지 여부 (1: 구매, 0: 구매 안 함)
|
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score
# 1. 가상의 고객 데이터 생성 (하드코딩된 값 사용)
data = {
"Frequency": [3, 10, 5, 8, 1, 12, 4, 7, 6, 2],
"Avg_Purchase_Amount": [30, 120, 80, 150, 10, 200, 50, 100, 90, 20],
"Email_Response": [1, 0, 1, 1, 0, 1, 0, 1, 1, 0],
"Social_Media_Activity": [2, 8, 4, 7, 0, 10, 3, 6, 5, 1],
"Purchase": [1, 0, 1, 1, 0, 1, 0, 1, 1, 0] # 타겟 변수 (1: 구매, 0: 구매 안 함)
}
# 데이터프레임 생성
df = pd.DataFrame(data)
# 2. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["Purchase"]) # 독립변수
y = df["Purchase"] # 종속변수 (목표 예측값)
# 3. 데이터 분할 (훈련 데이터 80%, 테스트 데이터 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 4. 의사결정트리 모델 학습
dt_model = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_model.fit(X_train, y_train)
# 5. 모델 예측
y_pred = dt_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# 6. 결정 트리 시각화
fig, ax = plt.subplots(figsize=(12, 6))
plot_tree(dt_model, feature_names=X.columns, class_names=["No Purchase", "Purchase"], filled=True, ax=ax)
plt.title(f"Decision Tree for Growth Marketing Campaign (Accuracy: {accuracy:.2f})")
plt.show()
# 7. 고객 데이터 입력 후 구매 예측 함수 (Feature Name 문제 해결)
def predict_purchase(Frequency, Avg_Purchase_Amount, Email_Response, Social_Media_Activity):
"""
입력한 고객 데이터를 기반으로 구매 여부를 예측하는 함수
"""
# 입력 데이터를 DataFrame 형태로 변환하여 Feature Names 유지
input_data = pd.DataFrame([[Frequency, Avg_Purchase_Amount, Email_Response, Social_Media_Activity]],
columns=X.columns)
prediction = dt_model.predict(input_data)
return "구매할 가능성이 높음" if prediction[0] == 1 else "구매하지 않을 가능성이 높음"
# 8. 예제 입력 데이터 (사용자가 예측하고 싶은 값)
example_input = {
"Frequency": 5, # 웹사이트 방문 횟수
"Avg_Purchase_Amount": 90, # 평균 구매 금액
"Email_Response": 1, # 이메일 캠페인 반응 여부 (1: 반응, 0: 반응 없음)
"Social_Media_Activity": 4 # 소셜 미디어 활동 횟수
}
# 9. 예측 실행
prediction_result = predict_purchase(**example_input)
print(f"예측 결과: {prediction_result}")

- 의사결정트리를 이용하여 자사의 B2B 고객이 유료 플랜으로 전환할 가능성을 예측하기 (분류)
- 사용 일수(Days_Active): 사용자가 무료 체험판을 사용한 일수
- 기능 활용 개수(Features_Used): 사용자가 활성화한 기능 개수
- 고객 지원 요청 횟수(Support_Tickets): 고객이 요청한 지원 티켓 수
- 팀원 추가 여부(Added_Team_Member): 팀원을 추가했는지 여부 (1: 예, 0: 아니오)
- 유료 플랜 전환 여부(Upgrade): 고객이 유료 플랜으로 전환했는지 여부 (목표 변수, 1: 전환, 0: 유지)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score
# 1. 가상의 고객 데이터 생성
data = {
"Days_Active": [5, 20, 10, 15, 3, 25, 8, 18, 12, 7],
"Features_Used": [2, 8, 5, 7, 1, 10, 3, 6, 6, 2],
"Support_Tickets": [0, 2, 1, 3, 0, 4, 0, 2, 1, 0],
"Added_Team_Member": [0, 1, 1, 1, 0, 1, 0, 1, 1, 0],
"Upgrade": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0] # 1: 유료 플랜 전환, 0: 무료 체험 유지
}
# 2. 데이터프레임 생성
df = pd.DataFrame(data)
# 3. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["Upgrade"])
y = df["Upgrade"]
# 4. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 5. 의사결정트리 모델 학습
dt_model = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_model.fit(X_train, y_train)
# 6. 모델 예측 및 정확도 평가
y_pred = dt_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# 7. 결정 트리 시각화
fig, ax = plt.subplots(figsize=(12, 6))
plot_tree(dt_model, feature_names=X.columns, class_names=["No Upgrade", "Upgrade"], filled=True, ax=ax)
plt.title(f"Decision Tree for SaaS User Upgrade Prediction (Accuracy: {accuracy:.2f})")
plt.show()
# 8. 유료 플랜 전환 예측 함수
def predict_upgrade(Days_Active, Features_Used, Support_Tickets, Added_Team_Member):
input_data = pd.DataFrame([[Days_Active, Features_Used, Support_Tickets, Added_Team_Member]],
columns=X.columns)
prediction = dt_model.predict(input_data)
return "유료 플랜으로 전환할 가능성이 높음" if prediction[0] == 1 else "무료 체험 유지 가능성이 높음"
# 9. 예제 입력 데이터 및 예측 실행
example_input = {"Days_Active": 10, "Features_Used": 5, "Support_Tickets": 1, "Added_Team_Member": 1}
prediction_result = predict_upgrade(**example_input)
print(f"예측 결과: {prediction_result}")

- 의사결정트리를 이용하여 이메일 마케팅 캠페인에 대한 고객 반응을 예측하기 (분류)
- 이메일 발송 횟수(Emails_Sent): 해당 고객에게 보낸 이메일 수
- 과거 이메일 클릭 횟수(Email_Clicks): 고객이 과거에 클릭한 이메일 수
- 웹사이트 방문 빈도(Website_Visits): 고객이 최근 한 달 동안 웹사이트를 방문한 횟수
- 할인 코드 사용 여부(Used_Discount_Code): 고객이 이전 구매 시 할인 코드를 사용했는지 여부 (1: 예, 0: 아니오)
- 이메일 참여 여부(Clicked_Email): 고객이 이메일을 클릭했는지 여부 (목표 변수, 1: 클릭, 0: 클릭 안 함)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score
# 1. 가상의 고객 데이터 생성
data = {
"Emails_Sent": [5, 15, 10, 20, 3, 25, 8, 18, 12, 7],
"Email_Clicks": [1, 5, 2, 7, 0, 10, 1, 6, 4, 2],
"Website_Visits": [3, 10, 5, 12, 1, 15, 4, 8, 6, 3],
"Used_Discount_Code": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0],
"Clicked_Email": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0] # 1: 클릭, 0: 클릭 안 함
}
# 2. 데이터프레임 생성
df = pd.DataFrame(data)
# 3. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["Clicked_Email"])
y = df["Clicked_Email"]
# 4. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 5. 의사결정트리 모델 학습
dt_model = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_model.fit(X_train, y_train)
# 6. 모델 예측 및 정확도 평가
y_pred = dt_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# 7. 결정 트리 시각화
fig, ax = plt.subplots(figsize=(12, 6))
plot_tree(dt_model, feature_names=X.columns, class_names=["No Click", "Clicked"], filled=True, ax=ax)
plt.title(f"Decision Tree for Email Marketing Campaign (Accuracy: {accuracy:.2f})")
plt.show()
# 8. 이메일 클릭 예측 함수
def predict_email_click(Emails_Sent, Email_Clicks, Website_Visits, Used_Discount_Code):
input_data = pd.DataFrame([[Emails_Sent, Email_Clicks, Website_Visits, Used_Discount_Code]],
columns=X.columns)
prediction = dt_model.predict(input_data)
return "이메일을 클릭할 가능성이 높음" if prediction[0] == 1 else "이메일을 클릭하지 않을 가능성이 높음"
# 9. 예제 입력 데이터 및 예측 실행
example_input = {"Emails_Sent": 10, "Email_Clicks": 2, "Website_Visits": 5, "Used_Discount_Code": 0}
prediction_result = predict_email_click(**example_input)
print(f"예측 결과: {prediction_result}")

- 의사결정트리를 이용하여 사용자의 유료 결제 가능성을 예측하기. (분류)
- 앱 사용 일수(App_Usage_Days): 사용자가 앱을 사용한 총 일수
- 게임/콘텐츠 이용 횟수(Feature_Usage_Count): 사용자가 특정 프리미엄 기능을 사용한 횟수
- 푸시 알림 클릭 여부(Clicked_Push_Notification): 사용자가 푸시 알림을 클릭했는지 여부 (1: 예, 0: 아니오)
- 친구 초대 여부(Invited_Friends): 사용자가 친구를 초대했는지 여부 (1: 예, 0: 아니오)
- 유료 결제 여부(Paid_User): 사용자가 유료 결제를 했는지 여부 (목표 변수, 1: 결제, 0: 결제 안 함)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score
# 1. 가상의 고객 데이터 생성
data = {
"App_Usage_Days": [3, 20, 7, 15, 2, 30, 6, 18, 10, 5],
"Feature_Usage_Count": [1, 10, 3, 8, 0, 15, 2, 7, 5, 1],
"Clicked_Push_Notification": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0],
"Invited_Friends": [0, 1, 1, 1, 0, 1, 0, 1, 1, 0],
"Paid_User": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0] # 1: 유료 결제, 0: 무료 사용자
}
# 2. 데이터프레임 생성
df = pd.DataFrame(data)
# 3. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["Paid_User"])
y = df["Paid_User"]
# 4. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 5. 의사결정트리 모델 학습
dt_model = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_model.fit(X_train, y_train)
# 6. 모델 예측 및 정확도 평가
y_pred = dt_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# 7. 결정 트리 시각화
fig, ax = plt.subplots(figsize=(12, 6))
plot_tree(dt_model, feature_names=X.columns, class_names=["Free User", "Paid User"], filled=True, ax=ax)
plt.title(f"Decision Tree for Mobile App Payment Prediction (Accuracy: {accuracy:.2f})")
plt.show()
# 8. 유료 결제 예측 함수
def predict_payment(App_Usage_Days, Feature_Usage_Count, Clicked_Push_Notification, Invited_Friends):
input_data = pd.DataFrame([[App_Usage_Days, Feature_Usage_Count, Clicked_Push_Notification, Invited_Friends]],
columns=X.columns)
prediction = dt_model.predict(input_data)
return "유료 결제 가능성이 높음" if prediction[0] == 1 else "무료 사용자 유지 가능성이 높음"
# 9. 예제 입력 데이터 및 예측 실행
example_input = {"App_Usage_Days": 14, "Feature_Usage_Count": 9, "Clicked_Push_Notification": 0, "Invited_Friends": 1}
prediction_result = predict_payment(**example_input)
print(f"예측 결과: {prediction_result}")

- 의사결정트리를 활용하여 주어진 데이터셋을 이용해 특정 지역의 매출건수예시 (회귀)
- “서울시 상권분석 데이터.csv” 데이터셋을 이용해 “사가정역”에서의 “당월매출건수”를 예측 (회귀)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor, plot_tree
from sklearn.metrics import mean_absolute_error, r2_score
# 1. CSV 파일 로드
file_path = "서울시 상권분석 데이터.csv" # CSV 파일 경로 입력
df = pd.read_csv(file_path, encoding="utf-8")
# 2. "사가정역" 데이터 필터링
df = df[df["상권_코드_명"] == "사가정역"]
# 3. 필요없는 컬럼 제거
drop_columns = ["기준_년분기_코드", "상권_구분_코드", "상권_구분_코드_명", "상권_코드", "상권_코드_명",
"서비스_업종_코드", "서비스_업종_코드_명"] # 분석에 필요 없는 컬럼 제거
df = df.drop(columns=drop_columns)
# 4. 결측값 제거
df = df.dropna()
# 5. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["당월_매출_건수"]) # 입력 변수 (매출 건수를 예측해야 하므로 제외)
y = df["당월_매출_건수"] # 타겟 변수 (예측 대상)
# 6. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 7. 결정트리 회귀 모델 학습
dt_model = DecisionTreeRegressor(max_depth=5, random_state=42)
dt_model.fit(X_train, y_train)
# 8. 모델 예측 및 평가
y_pred = dt_model.predict(X_test)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Absolute Error (MAE): {mae:.2f}")
print(f"R² Score: {r2:.2f}")
# 9. 결정 트리 시각화
fig, ax = plt.subplots(figsize=(15, 8))
plot_tree(dt_model, feature_names=X.columns, filled=True, ax=ax, fontsize=8)
plt.title(f"Decision Tree for Monthly Sales Count Prediction (R² Score: {r2:.2f})")
plt.show()
# 10. 예측 함수
def predict_sales_count(data_input):
input_data = pd.DataFrame([data_input], columns=X.columns)
prediction = dt_model.predict(input_data)
return f"예상 당월 매출 건수: {prediction[0]:,.0f} 건"
# 예측 예시
sample_input = X.iloc[0].values # 첫 번째 샘플 데이터로 예측
print(predict_sales_count(sample_input))

랜덤 포레스트 개념과 구현
- 랜덤 포레스트(Random Forest)는 여러 개의 결정 트리(Decision Tree)를 조합하여 예측 성능을 향상시키는 앙상블 학습(Ensemble Learning) 기법이다. 단일 결정 트리의 한계를 극복하고 과적합(Overfitting)을 줄이며, 예측 성능을 개선하는 데 효과적이다.
랜덤 포레스트 개념
- 랜덤 포레스트는 배깅(Bagging, Bootstrap Aggregating) 방식을 기반으로 여러 개의 결정 트리를 학습하고,
각 트리의 예측을 평균(회귀) 하거나 투표(분류) 하여 최종 예측을 수행한다.

랜덤 포레스트의 특징
- 여러 개의 결정 트리를 조합하여 예측
- 하나의 모델이 아닌 다수의 결정 트리를 훈련하여 결과를 조합함.
- 단일 결정 트리보다 일반화 성능(Generalization) 이 높아짐.
- 배깅(Bagging) 기법 사용
- 데이터 샘플링(부트스트랩 샘플링, Bootstrap Sampling)을 통해 중복된 데이터를 포함한 여러 개의 훈련 데이터셋을 생성.
- 각 트리는 서로 다른 데이터 샘플을 사용하여 학습됨.
- 랜덤한 특징 선택
- 각 트리는 전체 데이터가 아닌 일부 랜덤한 특징(Feature Subset) 을 사용하여 분할(Split) 수행.
- 이렇게 하면 특정 변수에 의존하는 문제를 방지하고, 모델의 다양성을 증가시킴.
- 결과 결합 방법
- 분류(Classification): 개별 트리의 예측 중 가장 많은 표를 받은 클래스(다수결, Majority Voting) 를 선택.
- 회귀(Regression): 개별 트리의 예측값을 평균 하여 최종 결과를 생성.
랜덤 포레스트의 장점과 단점
# 장점
- 과적합(Overfitting) 방지
- 여러 개의 트리를 조합하여 사용하므로 단일 결정 트리보다 과적합 가능성이 낮음.
- 높은 예측 성능
- 다양한 트리의 결과를 조합하기 때문에 단일 결정 트리보다 일반화 성능이 뛰어남.
- 특징 중요도 제공
- 랜덤 포레스트는 각 특징이 예측에 미치는 영향을 평가할 수 있어 특징 선택에 유용.
- 다양한 데이터 유형 지원
- 숫자형 변수 및 범주형 변수를 모두 처리 가능.
# 단점
- 훈련 속도가 느림
- 개별 결정 트리 여러 개를 학습해야 하므로 단일 결정 트리보다 훈련 시간이 오래 걸림.
- 해석이 어려움
- 단일 결정 트리는 해석이 쉽지만, 랜덤 포레스트는 여러 개의 트리를 조합하기 때문에 직관적으로 이해하기 어려움.
- 메모리 사용량이 많음
- 여러 개의 트리를 저장해야 하므로 메모리 사용량이 큼.
- 랜덤 포레스트를 활용한 광고클릭 예측 (분류)
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 데이터 로드
df = pd.read_csv("ad_click_prediction.csv")
# 독립 변수(X)와 종속 변수(y) 설정
X = df.drop(columns=["Clicked Ad"])
y = df["Clicked Ad"]
# 학습/테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 랜덤 포레스트 모델 학습
rf_model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
rf_model.fit(X_train, y_train)
# 예측 및 평가
y_pred = rf_model.predict(X_test)
print("모델 정확도:", accuracy_score(y_test, y_pred))
print("분류 보고서:\n", classification_report(y_test, y_pred))
# 혼동 행렬 시각화
plt.figure(figsize=(6, 4))
sns.heatmap(confusion_matrix(y_test, y_pred), annot=True, fmt='d', cmap='Blues')
plt.title("혼동 행렬 (Confusion Matrix)")
plt.xlabel("Predicted Label")
plt.ylabel("True Label")
plt.show()
# 특징 중요도 시각화
feature_importances = rf_model.feature_importances_
feature_names = X.columns
plt.figure(figsize=(10,6))
sns.barplot(x=feature_importances, y=feature_names, color="royalblue")
plt.xlabel("Feature Importance")
plt.ylabel("Features")
plt.title("랜덤 포레스트 - 광고 클릭 예측 특징 중요도")
plt.show()


- 광고 비용, 웹사이트 방문, SNS 상호작용, 이메일 캠페인 횟수를 고려하여 광고 클릭 가능성을 예측.
- 혼동 행렬(Confusion Matrix) 및 특징 중요도 그래프를 통해 중요한 요소 분석 가능.
- 랜덤 포레스트를 활용한 고객 지출 예측 (회귀)
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
# 데이터 로드
df = pd.read_csv("customer_spending_prediction.csv")
# 독립 변수(X)와 종속 변수(y) 설정
X = df.drop(columns=["Customer Spending ($)"])
y = df["Customer Spending ($)"]
# 학습/테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 랜덤 포레스트 회귀 모델 학습
rf_regressor = RandomForestRegressor(n_estimators=100, max_depth=5, random_state=42)
rf_regressor.fit(X_train, y_train)
# 예측 및 평가
y_pred = rf_regressor.predict(X_test)
print("MSE (Mean Squared Error):", mean_squared_error(y_test, y_pred))
print("R² (결정 계수):", r2_score(y_test, y_pred))
# 실제값 vs 예측값 시각화
plt.figure(figsize=(8,6))
sns.scatterplot(x=y_test, y=y_pred, alpha=0.6, color="red")
plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], linestyle="--", color="black")
plt.xlabel("Actual Customer Spending")
plt.ylabel("Predicted Customer Spending")
plt.title("실제 고객 지출 vs 예측 고객 지출 (랜덤 포레스트)")
plt.show()

# 데이터 준비: 고객 지출 예측을 위해 데이터를 불러오고, 독립 변수와 종속 변수를 설정.
# 모델 학습: 랜덤 포레스트 회귀 모델을 학습.
# 모델 평가: 예측값과 실제값을 비교하여 MSE와 결정 계수(R²)를 출력하고, 모델 성능을 평가.
# 결과 시각화: 실제값과 예측값을 시각적으로 비교하여 예측이 잘 됐는지 확인.
- 고객의 과거 구매 패턴, 멤버십 여부, 마지막 구매 이후 경과일 등을 고려하여 지출 예측.
- 실제 vs 예측값 그래프를 통해 예측 성능 평가 가능.
- 랜덤 포레스트를 활용하여 주어진 데이터셋을 이용해 특정 지역의 매출건수예시
- “서울시 상권분석 데이터.csv” 데이터셋을 이용해 “사가정역”에서의 “당월매출건수”를 예측하는 Random forest 회귀 코드 예시
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error, r2_score
# 1. CSV 파일 로드
file_path = "서울시 상권분석 데이터.csv" # CSV 파일 경로 입력
df = pd.read_csv(file_path, encoding="utf-8")
# 2. "사가정역" 데이터 필터링
df = df[df["상권_코드_명"] == "사가정역"]
# 3. 필요없는 컬럼 제거
drop_columns = ["기준_년분기_코드", "상권_구분_코드", "상권_구분_코드_명", "상권_코드", "상권_코드_명",
"서비스_업종_코드", "서비스_업종_코드_명"] # 분석에 불필요한 컬럼 제거
df = df.drop(columns=drop_columns)
# 4. 결측값 제거
df = df.dropna()
# 5. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["당월_매출_건수"]) # 입력 변수
y = df["당월_매출_건수"] # 타겟 변수 (예측 대상)
# 6. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 7. 랜덤포레스트 회귀 모델 학습
rf_model = RandomForestRegressor(n_estimators=100, max_depth=5, random_state=42)
rf_model.fit(X_train, y_train)
# 8. 모델 예측 및 평가
y_pred = rf_model.predict(X_test)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Absolute Error (MAE): {mae:.2f}")
print(f"R² Score: {r2:.2f}")
# 9. 변수 중요도 시각화
feature_importances = rf_model.feature_importances_
sorted_idx = np.argsort(feature_importances)[::-1]
plt.figure(figsize=(10, 6))
plt.bar(range(X.shape[1]), feature_importances[sorted_idx], align="center")
plt.xticks(range(X.shape[1]), X.columns[sorted_idx], rotation=90)
plt.xlabel("Feature")
plt.ylabel("Importance")
plt.title("Feature Importance in Random Forest Model")
plt.show()
# 10. 예측 함수
def predict_sales_count(data_input):
input_data = pd.DataFrame([data_input], columns=X.columns)
prediction = rf_model.predict(input_data)
return f"예상 당월 매출 건수: {prediction[0]:,.0f} 건"
# 예측 예시
sample_input = X.iloc[0].values # 첫 번째 샘플 데이터로 예측
print(predict_sales_count(sample_input))

- 랜덤 포레스트를 이용한 고객의 반품 여부 예측 (분류)
- 구매 금액(Total_Spend): 고객이 해당 주문에서 지출한 총 금액
- 구매 제품 수(Items_Purchased): 한 번의 주문에서 구매한 제품 수
- 배송 기간(Delivery_Days): 고객이 제품을 배송받는 데 걸린 시간 (일 단위)
- 할인 사용 여부(Used_Coupon): 할인 쿠폰을 사용했는지 여부 (1: 예, 0: 아니오)
- 반품 여부(Returned_Item): 고객이 반품했는지 여부 (목표 변수, 1: 반품, 0: 반품 안 함)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 1. 가상의 반품 데이터 생성
data = {
"Total_Spend": [30, 200, 80, 150, 10, 250, 50, 180, 90, 40, 50, 100],
"Items_Purchased": [1, 5, 3, 4, 1, 6, 2, 4, 3, 2, 2, 4],
"Delivery_Days": [2, 5, 3, 7, 1, 10, 2, 6, 5, 2, 2, 8],
"Used_Coupon": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1],
"Returned_Item": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1] # 1: 반품, 0: 반품 안 함
}
# 2. 데이터프레임 생성
df = pd.DataFrame(data)
# 3. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["Returned_Item"]) # 독립 변수
y = df["Returned_Item"] # 종속 변수 (반품 여부 예측)
# 4. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 5. 랜덤포레스트 모델 학습
rf_model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
rf_model.fit(X_train, y_train)
# 6. 모델 예측 및 정확도 평가
y_pred = rf_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"모델 정확도(Accuracy): {accuracy:.2f}")
# 7. 특징 중요도 시각화
feature_importances = rf_model.feature_importances_
sorted_idx = np.argsort(feature_importances)[::-1]
plt.figure(figsize=(8, 5))
plt.bar(range(X.shape[1]), feature_importances[sorted_idx], align="center")
plt.xticks(range(X.shape[1]), X.columns[sorted_idx], rotation=90)
plt.xlabel("Feature")
plt.ylabel("Importance")
plt.title("Feature Importance in Random Forest Model")
plt.show()
# 8. 반품 예측 함수
def predict_return(Total_Spend, Items_Purchased, Delivery_Days, Used_Coupon):
input_data = pd.DataFrame([[Total_Spend, Items_Purchased, Delivery_Days, Used_Coupon]],
columns=X.columns)
prediction = rf_model.predict(input_data)
return "반품 가능성이 높음" if prediction[0] == 1 else "반품하지 않을 가능성이 높음"
# 9. 예측 함수 실행 예시
sample_prediction = predict_return(100, 3, 4, 1)
print(f"예측 결과: {sample_prediction}")

- 랜덤 포레스트를 이용한 정상거래/사기거래 예측 (분류)
- 거래 금액(Transaction_Amount): 거래에서 사용된 금액
- 거래 횟수(Daily_Transactions): 하루 동안 발생한 거래 횟수
- 해외 거래 여부(International_Transaction): 해외 거래인지 여부 (1: 예, 0: 아니오)
- 고위험 국가 거래 여부(High_Risk_Country): 고위험 국가에서 발생한 거래인지 여부 (1: 예, 0: 아니오)
- 사기 여부(Fraudulent): 거래가 사기인지 여부 (목표 변수, 1: 사기, 0: 정상)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 1. 가상의 신용카드 사기 데이터 생성
data = {
"Transaction_Amount": [100, 5000, 200, 7000, 50, 8000, 150, 6000, 250, 90, 300],
"Daily_Transactions": [5, 50, 10, 70, 3, 80, 7, 60, 12, 6, 4],
"International_Transaction": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0],
"High_Risk_Country": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0],
"Fraudulent": [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0] # 1: 사기, 0: 정상
}
# 2. 데이터프레임 생성
df = pd.DataFrame(data)
# 3. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["Fraudulent"]) # 입력 변수
y = df["Fraudulent"] # 타겟 변수 (사기 거래 여부)
# 4. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 5. 랜덤포레스트 모델 학습
rf_model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
rf_model.fit(X_train, y_train)
# 6. 모델 예측 및 정확도 평가
y_pred = rf_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"모델 정확도(Accuracy): {accuracy:.2f}")
# 7. 특징 중요도 시각화
feature_importances = rf_model.feature_importances_
sorted_idx = np.argsort(feature_importances)[::-1]
plt.figure(figsize=(8, 5))
plt.bar(range(X.shape[1]), feature_importances[sorted_idx], align="center")
plt.xticks(range(X.shape[1]), X.columns[sorted_idx], rotation=90)
plt.xlabel("Feature")
plt.ylabel("Importance")
plt.title("Feature Importance in Random Forest Model")
plt.show()
# 8. 사기 거래 예측 함수
def predict_fraud(Transaction_Amount, Daily_Transactions, International_Transaction, High_Risk_Country):
input_data = pd.DataFrame([[Transaction_Amount, Daily_Transactions, International_Transaction, High_Risk_Country]],
columns=X.columns)
prediction = rf_model.predict(input_data)
return "사기 거래 가능성이 높음" if prediction[0] == 1 else "정상 거래 가능성이 높음"
# 9. 예측 함수 실행 예시
sample_prediction = predict_fraud(6000, 55, 1, 1)
print(f"예측 결과: {sample_prediction}")

- 랜덤 포레스트를 이용한 고객 이탈가능성 예측 (분류)
- 월 주문 횟수(Monthly_Orders): 고객이 한 달 동안 주문한 횟수
- 평균 주문 금액(Avg_Order_Value): 고객의 평균 주문 금액
- 리뷰 점수(Review_Score): 고객이 남긴 평균 리뷰 점수 (1~5)
- 이탈 여부(Churned): 고객이 이탈했는지 여부 (목표 변수, 1: 이탈, 0: 유지)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 1. 가상의 고객 이탈 데이터 생성
data = {
"Monthly_Orders": [5, 12, 3, 15, 2, 20, 4, 18, 7, 6],
"Avg_Order_Value": [15, 35, 10, 50, 8, 55, 12, 40, 20, 14],
"Review_Score": [4.2, 4.8, 3.5, 4.9, 2.9, 5.0, 3.0, 4.6, 4.0, 3.8],
"Churned": [1, 0, 1, 0, 1, 0, 1, 0, 0, 1] # 1: 이탈, 0: 유지
}
# 2. 데이터프레임 생성
df = pd.DataFrame(data)
# 3. 입력(X)과 타겟(y) 분리
X = df.drop(columns=["Churned"])
y = df["Churned"]
# 4. 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 5. 랜덤포레스트 모델 학습
rf_model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
rf_model.fit(X_train, y_train)
# 6. 모델 예측 및 정확도 평가
y_pred = rf_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# 7. 랜덤포레스트 모델 평가
print(f"모델 정확도: {accuracy:.2f}")
# 8. 고객 이탈 예측 함수
def predict_churn(Monthly_Orders, Avg_Order_Value, Review_Score):
"""
입력한 고객 데이터를 기반으로 이탈 여부를 예측하는 함수
"""
input_data = pd.DataFrame([[Monthly_Orders, Avg_Order_Value, Review_Score]], columns=X.columns)
prediction = rf_model.predict(input_data)
return "고객이 이탈할 가능성이 높음" if prediction[0] == 1 else "고객이 계속 유지될 가능성이 높음"
# 9. 예제 입력 데이터 및 예측 실행
example_input = {"Monthly_Orders": 5, "Avg_Order_Value": 15, "Review_Score": 4.2}
prediction_result = predict_churn(**example_input)
print(f"예측 결과: {prediction_result}")
결과 :
모델 정확도: 0.50
예측 결과: 고객이 이탈할 가능성이 높음
'데이터 분석 part' 카테고리의 다른 글
인공신경망(ANN), 다층신경망(MLP), 심층신경망(DNN) / ( 결정트리, 랜덤포레스트, K-평균군집화 복습 ) (0) | 2025.03.13 |
---|---|
k-NN 알고리즘, 서포트 벡터 머신(SVM), flask 웹실습 (2) | 2025.03.13 |
데이터 전처리, 특징 엔지니어링, 선형회귀, 로지스틱회귀 (0) | 2025.03.11 |
머신러닝의 기본 개념 이해 (2) | 2025.03.10 |
웹서버로 보고서 구현(flask) / 루커 스튜디오 실습 및 데이터 소스 연결 (0) | 2025.03.06 |