멀티캠퍼스 데이터분석 5월 20일 수업 내용 — 해적지표(AARRR)/플라이휠 이론, 통신사 고객 이탈 분석, RFM 분석, 마케팅 믹스 모델링, 딥러닝/PyTorch 이론
AARRR 이론
1. 해적지표 (AARRR)
2. 퍼널의 종말과 플라이휠 (Flywheel)
실습
딥러닝 이론


| 단계 | 영어 | 의미 |
|---|---|---|
| A | Acquisition | 고객 획득 — 어떻게 유입시킬 것인가? |
| A | Activation | 활성화 — 첫 핵심 경험을 제공했는가? |
| R | Retention | 유지 — 고객이 다시 돌아오는가? |
| R | Revenue | 수익 — 돈을 버는가? |
| R | Referral | 추천 — 고객이 다른 사람에게 추천하는가? |

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report
df = pd.read_csv('../data/Telco_Customer-Churn.csv')
| 컬럼 | 설명 |
|---|---|
| customerID | 고객 고유 식별자 |
| gender | 성별 |
| SeniorCitizen | 고령자 여부 (1: 고령자, 0: 아님) |
| Partner | 파트너 여부 (Yes/No) |
| Dependents | 부양 가족 여부 (Yes/No) |
| tenure | 서비스 이용 기간 (개월 수) |
| PhoneService | 전화 서비스 가입 (Yes/No) |
| MultipleLines | 다중 회선 (Yes/No/No phone service) |
| InternetService | 인터넷 서비스 방식 (DSL/Fiber optic/No) |
| OnlineSecurity | 온라인 보안 서비스 (Yes/No/No internet service) |
| DeviceProtection | 기기 보호 서비스 (Yes/No/No internet service) |
| TechSupport | 기술 지원 서비스 (Yes/No/No internet service) |
| StreamingTV | 스트리밍 TV (Yes/No/No internet service) |
| StreamingMovies | 스트리밍 영화 (Yes/No/No internet service) |
| Contract | 계약 유형 (Month-to-month/One year/Two year) |
| PaperlessBilling | 전자 청구서 사용 (Yes/No) |
| PaymentMethod | 결제 방식 |
| MonthlyCharges | 월 청구 요금 |
| TotalCharges | 누적 총 청구 요금 |
| Churn | 해지 여부 (Yes: 해지, No: 유지) ← target |
# TotalCharges — 공백 문자(' ')가 있어 object 타입
# pd.to_numeric(errors='coerce') → 변환 불가 데이터는 NaN 처리
df['TotalCharges'] = pd.to_numeric(df['TotalCharges'], errors='coerce')
# NaN은 신규 가입자로 간주 → 이탈 여부와 무관하여 제거
df.dropna(inplace=True)
# InternetService, PaymentMethod, Contract → 더미 변수 생성
df2 = pd.get_dummies(df, columns=['InternetService', 'PaymentMethod', 'Contract'])
# 불필요한 customerID 제거
df2.drop('customerID', axis=1, inplace=True)
# gender → LabelEncoder
le = LabelEncoder()
df2['gender'] = le.fit_transform(df2['gender'])
# 나머지 object 컬럼 → Yes=1, 나머지=0
obj_cols = df2.select_dtypes('object').columns
for col in obj_cols:
df2[col] = df2[col].map(lambda x: 1 if x == 'Yes' else 0)
💡
pd.to_numeric()errors 매개변수
'raise'(기본값) : 변환 실패 시 에러'coerce': 변환 실패 시 NaN 처리'ignore': 변환 실패 시 원본 데이터 유지
x = df2.drop('Churn', axis=1)
y = df2['Churn']
X_train, X_test, y_train, y_test = train_test_split(
x, y, test_size=0.2, random_state=42, stratify=y
)
model = RandomForestClassifier(random_state=42, class_weight='balanced_subsample')
model.fit(X_train, y_train)
pred = model.predict(X_test)
print(classification_report(y_test, pred))
feature_df = pd.DataFrame({
'feature_name' : x.columns,
'importance' : model.feature_importances_
}).sort_values('importance', ascending=False).reset_index(drop=True)
print('해적 지표 Retention 분석 : 이탈에 영향을 미치는 핵심 요인 Top 5')
print(feature_df.head())
💡 AARRR 중 Retention(유지) 관점에서 분석합니다.
피처 중요도 Top 5를 파악하면 어떤 서비스/요금제가 이탈에 가장 큰 영향을 주는지 알 수 있습니다.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score
df = pd.read_excel('../data/Online Retail.xlsx')
| RFM | 의미 | 계산 방법 |
|---|---|---|
| R (Recency) | 최근성 — 얼마나 최근에 구매했는가 | 현재 시간 - 마지막 주문일 (일 수) |
| F (Frequency) | 빈도 — 얼마나 자주 구매했는가 | 고객별 거래 횟수 |
| M (Monetary) | 금액 — 얼마나 많이 지출했는가 | 고객별 총 지출 합계 |
# CustomerID 없는 행 제거 (비회원 거래)
df.dropna(subset='CustomerID', inplace=True)
# 거래 금액 파생변수
df['price'] = df['Quantity'] * df['UnitPrice']
# 현재 시간 = 마지막 주문일 + 1일
now_time = df['InvoiceDate'].max() + pd.Timedelta(days=1)
# 고객별 RFM 집계
customers = df.groupby('CustomerID').agg(
{
'InvoiceDate' : lambda x: (now_time - x.max()).days, # 최근성
'InvoiceNo' : 'count', # 빈도
'price' : 'sum' # 총지출
}
)
customers.columns = ['최근성', '빈도', '총지출']
x = customers[['최근성', '빈도']]
y = customers['총지출']
X_train, X_test, y_train, y_test = train_test_split(
x, y, test_size=0.2, random_state=42
)
model = RandomForestRegressor(random_state=42)
model.fit(X_train, y_train)
pred = model.predict(X_test)
print('R2 Score :', r2_score(y_test, pred))
importance_df = pd.DataFrame({
'feature_name' : x.columns,
'importance' : model.feature_importances_
}).sort_values('importance', ascending=False)
print(importance_df)
💡
pd.Timedelta(days=1)— 날짜에 1일을 더할 때 사용합니다.
lambda x: (now_time - x.max()).days— 그룹별 최근 주문일로부터 현재까지의 일 수를 계산합니다.
TV, 검색광고, SNS 등 각 마케팅 채널이 매출에 얼마나 기여했는지를 수치로 분석하는 방법입니다.
PolynomialFeatures + Ridge 를 활용하여 채널 간 상호작용 효과까지 분석합니다.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import Ridge
from sklearn.metrics import r2_score
df = pd.read_csv('../data/Alternative.csv', index_col=0)
x = df.drop('sales', axis=1)
y = df['sales']
# 상호작용 항 생성
# degree=2 → 2차 다항 특성 생성
# interaction_only=True → 상호작용 항만 생성 (제곱 항 제외)
# include_bias=False → 상수항(1) 컬럼 제외
poly = PolynomialFeatures(degree=2, interaction_only=True, include_bias=False)
x_poly = poly.fit_transform(x)
poly_columns = poly.get_feature_names_out(x.columns)
X_train, X_test, y_train, y_test = train_test_split(
x_poly, y, test_size=0.2, random_state=42
)
# 스케일링
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# Ridge 모델 — L2 규제로 상호작용 항이 많아져도 과적합 방지
model = Ridge()
model.fit(X_train, y_train)
# 회귀 계수 확인 — 어떤 채널(상호작용)이 매출에 가장 큰 영향?
coef_df = pd.DataFrame({
'feature_names' : poly_columns,
'coefficient' : model.coef_
}).sort_values('coefficient', ascending=False)
print(coef_df)
| 매개변수 | 기본값 | 설명 |
|---|---|---|
degree | 2 | 다항 차수 |
interaction_only | False | True 시 상호작용 항만 생성 (제곱 항 제외) |
include_bias | True | False 시 상수항(1) 컬럼 제외 |
💡 상호작용 항이란?
TV × SNS처럼 두 변수를 곱한 항입니다.
TV 광고와 SNS 광고를 함께 집행할 때 매출 시너지 효과를 포착할 수 있습니다.
💡 왜 Ridge를 사용하는가?
상호작용 항을 추가하면 피처 수가 급격히 증가합니다.
Ridge의 L2 규제로 과적합을 방지하고 계수를 안정적으로 추정합니다.
| 개념 | 설명 |
|---|---|
| 인공지능 (AI) | 사람의 지능을 흉내 내는 기계의 모든 기술 (가장 넓은 의미) |
| 머신러닝 (ML) | 데이터를 주어 기계가 스스로 규칙을 학습하게 만드는 방법론 |
| 딥러닝 (DL) | 머신러닝 중 사람의 뇌(신경망) 구조를 모방한 최신 기술 |
AI ⊃ 머신러닝 ⊃ 딥러닝


입력층 → 은닉층 → 출력층 방향으로 데이터가 흐르며 예측값을 생성합니다.
| 개념 | 설명 | 예시 |
|---|---|---|
| Batch Size | 한 번에 몇 개의 샘플을 처리하고 가중치를 업데이트할 것인가 | Batch Size=100 → 100개 처리 후 가중치 업데이트 |
| Epoch | 전체 데이터셋을 처음부터 끝까지 몇 번 반복 학습할 것인가 | Epoch=3 → 전체 데이터를 3회 반복 학습 |
💡 Batch Size가 작을수록 업데이트가 잦아 학습이 불안정하지만 일반화 성능이 좋을 수 있습니다.
Epoch가 너무 크면 과적합 위험이 있습니다.

1. 순전파 (Forward) → 입력 데이터를 모델에 통과시켜 예측값 생성
2. 손실 계산 (Loss) → 예측값과 실제값의 오차(손실) 계산
3. 기울기 초기화 → optimizer.zero_grad() (이전 기울기 초기화)
4. 역전파 (Backward) → loss.backward() (기울기 계산)
5. 가중치 업데이트 → optimizer.step() (가중치 수정)
__init__ 함수 : 사용할 레이어(Linear 등) 를 미리 선언forward 함수 : 레이어를 어떤 순서로 통과시킬지 조립 레시피 정의


| 알고리즘 | 특징 |
|---|---|
| SGD | 가장 기본적인 경사하강법 |
| Momentum | 이전 기울기를 관성처럼 활용하여 수렴 속도 향상 |
| Adam | Momentum + 학습률 자동 조정, 현재 가장 많이 사용 |


| 개념 | 설명 |
|---|---|
| AARRR | 해적지표 — Acquisition/Activation/Retention/Revenue/Referral |
| Flywheel | 고객 경험 선순환 성장 구조 |
| RFM | Recency/Frequency/Monetary — 고객 가치 분석 지표 |
pd.to_numeric(errors='coerce') | 변환 불가 값을 NaN으로 처리 |
pd.Timedelta(days=1) | 날짜에 특정 기간 추가 |
groupby().agg() | 여러 집계 함수를 한 번에 적용 |
PolynomialFeatures | 다항/상호작용 특성 생성 |
interaction_only=True | 상호작용 항만 생성 (제곱 항 제외) |
poly.get_feature_names_out() | 생성된 다항 피처명 확인 |
| Ridge | L2 규제 선형 회귀 — 과적합 방지 |
model.coef_ | Ridge 회귀 계수 — 각 채널의 매출 기여도 |
class_weight='balanced_subsample' | RandomForest 클래스 불균형 보정 |
feature_importances_ | 피처별 중요도 (합계=1) |
| 퍼셉트론 | 생물학적 뉴런을 수학적으로 모방한 인공 뉴런 |
| 순전파 | 입력→출력 방향으로 예측값 생성 |
| 역전파 | 출력→입력 방향으로 오차 원인 추적 & 가중치 수정 |
| Epoch | 전체 데이터를 몇 번 반복 학습할 것인가 |
| Batch Size | 한 번에 처리할 샘플 수 |
| Tensor | PyTorch의 기본 다차원 배열 |
nn.Module | PyTorch 신경망 기본 뼈대 |
| Adam | 현재 가장 많이 사용하는 최적화 알고리즘 |
| 학습률(lr) | 가중치 업데이트 보폭 — 너무 크면 발산, 너무 작으면 느림 |