Datawhale之数据挖掘学习 - 6月 - task01
背景:
随着市场饱和度的上升,电信运营商的竞争也越来越激烈,电信运营商亟待解决减少用户流失,延长用户生命周期的问题。对于客户流失率而言,每增加5%,利润就可能随之降低25%-85%。因此,如何减少电信用户流失的分析与预测至关重要。
鉴于此,运营商会经常设有客户服务部门,该部门的职能主要是做好客户流失分析,赢回高概率流失的客户,降低客户流失率。某电信机构的客户存在大量流失情况,导致该机构的用户量急速下降。面对如此头疼的问题,该机构将部分客户数据开放,诚邀大家帮助他们建立流失预测模型来预测可能流失的客户。
赛事任务:
给定某电信机构实际业务中的相关客户信息,包含69个与客户相关的字段,其中“是否流失”字段表明客户会否会在观察日期后的两个月内流失。任务目标是通过训练集训练模型,来预测客户是否会流失,以此为依据开展工作,提高用户留存。
数据说明:
赛题数据由训练集和测试集组成,总数据量超过25w,包含69个特征字段。为了保证比赛的公平性,将会从中抽取15万条作为训练集,3万条作为测试集,同时会对部分字段信息进行脱敏。
数据特征:
客户ID、地理区域、是否双频、是否翻新机、当前手机价格、手机网络功能、婚姻状况、家庭成人人数、信息库匹配、预计收入、信用卡指示器、当前设备使用天数、在职总月数、家庭中唯一订阅者的数量、家庭活跃用户数、… 、过去六个月的平均每月使用分钟数、过去六个月的平均每月通话次数、过去六个月的平均月费用、
是否流失
任务task01:
赛事全流程实践:报名赛事实践并下载数据集;理解实践场景,梳理解题思路;按照给定的基线解决方案跑通代码;提交相应的结果文件。(4天)
ps:截止日期2022-06-17 03:00:00
个人独白:
因为自己没参加过这种比赛,就是想探索一下数据挖掘领域。希望自己可以根据大佬们的流程慢慢来,慢慢进行研究。
赛题分析:
这里的话,根据下载的数据集可以看出该赛题是一个分类的题目。通过数据集中的数据特征进一步分析是否流失的用户特性。如果用数据分析类的想法,就是说通过该数据集分析流失用户的特性和非流失用户的特性。然后我们大概得到一个类似决策树模型,知道哪些关键的特征处于相对应的哪些范围可以得到该用户是否是流失用户。
对于该赛题,应该是找到能够高精准度的模型,对测试集进行一个分类划分。就可以了。如果是数据分析的话,结合一定业务背景,应该还会给出相应的一些建议,然后相应的业务部门同事根据模型及建议及时推出有效防止用户流失的策略,进行一定的留存,从而使该模型有一定的意义。
但是,对于我来说,使用模型还可以,但是如何进行调优,如何进行特征工程,真的是一点思路没有,希望慢慢来吧,让自己更进步一点点。
任务结果:
baseline代码:
from sklearn import metrics
# auc = metrics.roc_auc_score(data['default_score_true'], data['default_score_pred'])
import pandas as pd
import os
import gc
import lightgbm as lgb
import xgboost as xgb
from catboost import CatBoostRegressor
from sklearn.linear_model import SGDRegressor, LinearRegression, Ridge
from sklearn.preprocessing import MinMaxScaler
from gensim.models import Word2Vec
import math
import numpy as np
from tqdm import tqdm
from sklearn.model_selection import StratifiedKFold, KFold
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score, log_loss
import matplotlib.pyplot as plt
import time
from sklearn.svm import SVC
import warnings
warnings.filterwarnings('ignore')
train = pd.read_csv('/电信客户流失预测挑战赛数据集/train.csv')
test = pd.read_csv('/电信客户流失预测挑战赛数据集/test.csv')
data = pd.concat([train, test], axis=0, ignore_index=True)
# print(data)
# print(train.shape)
# print(test.shape)
features = [f for f in data.columns if f not in ['是否流失','客户ID']]
train = data[data['是否流失'].notnull()].reset_index(drop=True)
test = data[data['是否流失'].isnull()].reset_index(drop=True)
x_train = train[features]
x_test = test[features]
y_train = train['是否流失']
def cv_model(clf, train_x, train_y, test_x, clf_name):
folds = 5
seed = 2022
kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
train = np.zeros(train_x.shape[0])
test = np.zeros(test_x.shape[0])
cv_scores = []
for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
print('************************************ {} ************************************'.format(str(i + 1)))
trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y[train_index], train_x.iloc[valid_index], \
train_y[valid_index]
if clf_name == "lgb":
train_matrix = clf.Dataset(trn_x, label=trn_y)
valid_matrix = clf.Dataset(val_x, label=val_y)
params = {
'boosting_type': 'gbdt',
'objective': 'binary',
'metric': 'auc',
'min_child_weight': 5,
'num_leaves': 2 ** 5,
'lambda_l2': 10,
'feature_fraction': 0.7,
'bagging_fraction': 0.7,
'bagging_freq': 10,
'learning_rate': 0.2,
'seed': 2022,
'n_jobs': -1
}
model = clf.train(params, train_matrix, 50000, valid_sets=[train_matrix, valid_matrix],
categorical_feature=[], verbose_eval=3000, early_stopping_rounds=200)
val_pred = model.predict(val_x, num_iteration=model.best_iteration)
test_pred = model.predict(test_x, num_iteration=model.best_iteration)
# print(list(sorted(zip(features, model.feature_importance("gain")), key=lambda x: x[1], reverse=True))[:20])
if clf_name == "xgb":
train_matrix = clf.DMatrix(trn_x, label=trn_y)
valid_matrix = clf.DMatrix(val_x, label=val_y)
test_matrix = clf.DMatrix(test_x)
params = {'booster': 'gbtree',
'objective': 'binary:logistic',
'eval_metric': 'auc',
'gamma': 1,
'min_child_weight': 1.5,
'max_depth': 5,
'lambda': 10,
'subsample': 0.7,
'colsample_bytree': 0.7,
'colsample_bylevel': 0.7,
'eta': 0.2,
'tree_method': 'exact',
'seed': 2020,
'nthread': 36,
"silent": True,
}
watchlist = [(train_matrix, 'train'), (valid_matrix, 'eval')]
model = clf.train(params, train_matrix, num_boost_round=50000, evals=watchlist, verbose_eval=3000,
early_stopping_rounds=200)
val_pred = model.predict(valid_matrix, ntree_limit=model.best_ntree_limit)
test_pred = model.predict(test_matrix, ntree_limit=model.best_ntree_limit)
if clf_name == "cat":
params = {'learning_rate': 0.2, 'depth': 5, 'l2_leaf_reg': 10, 'bootstrap_type': 'Bernoulli',
'od_type': 'Iter', 'od_wait': 50, 'random_seed': 11, 'allow_writing_files': False}
model = clf(iterations=20000, **params)
model.fit(trn_x, trn_y, eval_set=(val_x, val_y),
cat_features=[], use_best_model=True, verbose=3000)
val_pred = model.predict(val_x)
test_pred = model.predict(test_x)
train[valid_index] = val_pred
test = test_pred / kf.n_splits
cv_scores.append(roc_auc_score(val_y, val_pred))
print(cv_scores)
print("%s_scotrainre_list:" % clf_name, cv_scores)
print("%s_score_mean:" % clf_name, np.mean(cv_scores))
print("%s_score_std:" % clf_name, np.std(cv_scores))
return train, test
def lgb_model(x_train, y_train, x_test):
lgb_train, lgb_test = cv_model(lgb, x_train, y_train, x_test, "lgb")
return lgb_train, lgb_test
def xgb_model(x_train, y_train, x_test):
xgb_train, xgb_test = cv_model(xgb, x_train, y_train, x_test, "xgb")
return xgb_train, xgb_test
def cat_model(x_train, y_train, x_test):
cat_train, cat_test = cv_model(CatBoostRegressor, x_train, y_train, x_test, "cat")
return cat_train, cat_test
# lgb_train, lgb_test = lgb_model(x_train, y_train, x_test)
# xgb_train, xgb_test = xgb_model(x_train, y_train, x_test)
# cat_train, cat_test = cat_model(x_train, y_train, x_test)
svc_train, svc_test = svc_model(x_train, y_train, x_test)
# test['是否流失'] = lgb_test
# test[['客户ID','是否流失']].to_csv('/电信客户流失预测挑战赛数据集/test_sub.csv', index=False)
参考资料:
电信客户流失预测挑战赛
科大讯飞:电信客户流失预测挑战赛baseline
Datawhale 零基础入门数据挖掘-Task3 特征工程
电信运营商:客户流失预警案例