* 자료 출처: Kaggle - Google Analytics Customer Revenue Prediction
1. 문제 배경
- GA 로그데이터를 활용해 구매자 예측 모델링 시도
- 매출액 칼럼에서 NaN은 미구매로 간주하고 0, 매출액이 있는 값은 1로 대치
- 데이터 분리, 인코딩 및 스케일링 작업 진행
- 프로젝트 시간이 부족하여 추가 전처리 및 x변수 조정 작업하지 못하고 실패로 마무리
2. 모델링
- 데이터 분리
from sklearn.model_selection import train_test_split
# 데이터를 train, test로 분리
X = df.drop(columns = ['Revenue_yn'])
y = df[['Revenue_yn']]
# 학습과 평가를 위해 데이터 셋 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify = y, random_state= 42)
#분리된 데이터 차원 확인
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
- 인코딩 및 스케일링
# 라벨 인코더(범주형): channelGrouping, device.deviceCategory, geoNetwork.country
# 스케일링 (수치형): totals.pageviews, totals.visits, totals.hits (기타 - 평균 세션 시간, 재방문 수 등)
from sklearn.preprocessing import LabelEncoder, StandardScaler
en_lb = LabelEncoder()
# 0: (Other) 1: Affiliates 2: Direct 3: Display 4: Organic Search 5: Paid Search, 6: Referral, 7: Social
df['channel_en'] = en_lb.fit_transform(df[['channelGrouping']])
# 0: desktop 1: mobile 2: tablet
df['deviceCategory_en'] = en_lb.fit_transform(df[['device.deviceCategory']])
# 0: (not set) 1: Africa 2: Americas 3: Asia 4: Europe 5: Oceania
df['continent_en'] = en_lb.fit_transform(df[['geoNetwork.continent']])
sc_sd = StandardScaler()
df['pageviews_sc'] = sc_sd.fit_transform(df[['totals.pageviews']])
df['visits_sc'] = sc_sd.fit_transform(df[['totals.visits']])
df['hits_sc'] = sc_sd.fit_transform(df[['totals.hits']])
df.describe(include='all')
- 모델링 학습 및 평가
def get_score(train:pd.DataFrame, test:pd.DataFrame, x_var_list:list):
""" train과 test 데이터와 X변수 컬럼을 받아 평가지표를 내는 함수입니다.
Args:
train (pd.DataFrame): train 데이터프레임
test (pd.DataFrame): test 데이터프레임
x_var_list (list): 모델링에 사용할 변수 리스트
"""
#외부 전달인자를 내부변수에 할당
X_train = train
X_test = test
#일부 컬럼만 가져오기
X_train = X_train[x_var_list]
X_test = X_test[x_var_list]
#모듈불러오기
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBRFClassifier
from sklearn.metrics import accuracy_score, f1_score
#모델 가져오기
model_log = LogisticRegression()
model_dt = DecisionTreeClassifier(random_state=42)
model_rf = RandomForestClassifier(random_state=42)
model_xgb = XGBRFClassifier(random_state=42)
#모델 학습하기
model_log.fit(X_train, y_train)
model_dt.fit(X_train, y_train)
model_rf.fit(X_train, y_train)
model_xgb.fit(X_train, y_train)
# 학습하여 결과 저장
y_pred_log_train = model_log.predict(X_train)
y_pred_log_test = model_log.predict(X_test)
y_pred_dt_train = model_dt.predict(X_train)
y_pred_dt_test = model_dt.predict(X_test)
y_pred_rf_train = model_rf.predict(X_train)
y_pred_rf_test = model_rf.predict(X_test)
y_pred_xgb_train = model_xgb.predict(X_train)
y_pred_xgb_test = model_xgb.predict(X_test)
#평가표 생성
result = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_log_train), accuracy_score(y_train, y_pred_dt_train), accuracy_score(y_train, y_pred_rf_train), accuracy_score(y_train, y_pred_xgb_train),
accuracy_score(y_test, y_pred_log_test),accuracy_score(y_test, y_pred_dt_test),accuracy_score(y_test, y_pred_rf_test),accuracy_score(y_test, y_pred_xgb_test)],
'f1_score' : [f1_score(y_train, y_pred_log_train),f1_score(y_train, y_pred_dt_train),f1_score(y_train, y_pred_rf_train),f1_score(y_train, y_pred_xgb_train),
f1_score(y_test, y_pred_log_test), f1_score(y_test, y_pred_dt_test), f1_score(y_test, y_pred_rf_test), f1_score(y_test, y_pred_xgb_test)]},
index=pd.MultiIndex.from_tuples([('train', 'logistic'),('train', 'dt'), ('train', 'rf'), ('train', 'XGB'),
('test', 'logistic'),('test', 'dt'), ('test', 'rf'), ('test', 'XGB')]))
display(result.round(2))
# duration 변수만 사용하여 결과내기
get_score(X_train, X_test, ['channel_en','deviceCategory_en','campaign_yn','newVisits_yn'])
> 결론: F1 스코어 0점으로 예측 모델링 실패
3. 추후 과제
- SMOTE 기법 활용한 오버샘플링 적용
└ 구매 비중이 전체의 1.3 %로 데이터 불균형이 심해 제대로된 학습이 어려웠을 것으로 추측
└ 정확도는 97%인데 반해 f1 스코어가 0점이라는 것에서도 데이터 불균형 문제가 여실히 드러남
- 전체 평균 세션수가 1인 데이터는 제외해보는 등 모델링에 활용할 표본 범위를 조정하는 것도 방법이 될 듯
'TIL' 카테고리의 다른 글
[240220] SQL: 코드카타 123~124(not exists, offset, group_concat) & 파이썬: 코드카타 31~32(zip) (0) | 2024.02.20 |
---|---|
[240219] SQL: 코드카타 122 (0) | 2024.02.19 |
[240215] 피벗 테이블을 활용한 히트맵 시각화 (0) | 2024.02.16 |
[240214] 파이차트: 기준값 추가 / 막대그래프: X축 이름 및 간격 변경 (0) | 2024.02.14 |
[240213] 유저ID와 방문시작시간으로 세션ID/평균세션시간 생성(feat. ECDF) (0) | 2024.02.14 |