XGBOOST 实践项目预测用户是否会点击广告

数据介绍

本题我们使用Criteo所共享的一周展示广告数据,数据中提炼了13个连续特征、26个离散特征和用户是否点击了该页面广告的标签。
数据预处理:对连续特征做等频的离散化处理,对类目特征做one hot encoding

参数说明

通用参数

  1. booster:基学习器类型,gbtree,gblinear 或 dart(增加了 Dropout) ,gbtree 和 dart 使用基于树的模型,而 gblinear 使用线性模型;
  2. silent:使用 0 会打印更多信息;
  3. nthread:运行时线程数;

Booster 参数

树模型

  1. List itemeta(learning_rate):更新过程中用到的收缩步长,(0, 1];
  2. gamma:在节点分裂时,只有在分裂后损失函数的值下降了,才会分裂这个节点。Gamma 指定了节点分裂所需的最小损失函数下降值。这个参数值越大,算法越保守;
  3. max_depth:树的最大深度,这个值也是用来避免过拟合的;
  4. min_child_weight:决定最小叶子节点样本权重和。当它的值较大时,可以避免模型学习到局部的特殊样本。但如果这个值过高,会导致欠拟合;
  5. max_delta_step:这参数限制每颗树权重改变的最大步长。如果是 0 意味着没有约束。如果是正值那么这个算法会更保守,通常不需要设置;
  6. subsample:这个参数控制对于每棵树,随机采样的比例。减小这个参数的值算法会更加保守,避免过拟合。但是这个值设置的过小,它可能会导致欠拟合;
  7. colsample_bytree:用来控制每颗树随机采样的列数的占比;
  8. colsample_bylevel:用来控制的每一级的每一次分裂,对列数的采样的占比;
  9. lambda(reg_lambda):L2 正则化项的权重系数,越大模型越保守;
  10. alpha(reg_alpha):L1 正则化项的权重系数,越大模型越保守;
  11. tree_method:树生成算法,auto, exact, approx, hist, gpu_exact, gpu_hist;
  12. scale_pos_weight:各类样本十分不平衡时,把这个参数设置为一个正数,可以使算法更快收敛。典型值是 sum(negative cases) / sum(positive cases);

Dart 额外参数

  1. sample_type:采样算法;
  2. normalize_type:标准化算法;
  3. rate_drop:前置树的丢弃率,有多少比率的树不进入下一个迭代,[0, 1];
  4. one_drop:设置为 1 的话每次至少有一棵树被丢弃;
  5. skip_drop:跳过丢弃阶段的概率,[0, 1],非零的 skip_drop 比 rate_drop 和 one_drop 有更高的优先级;

线性模型

  1. lambda(reg_lambda):L2 正则化项的权重系数,越大模型越保守;
  2. alpha(reg_alpha):L1 正则化项的权重系数,越大模型越保守;
  3. lambda_bias(reg_lambda_bias):L2 正则化项的偏置;

学习任务参数

  1. objective:这个参数定义需要被最小化的损失函数;
  2. base_score:初始化预测分数,全局偏置;
  3. eval_metric:对于有效数据的度量方法,取值范围取决于 objective;
  4. seed:随机数种子,相同的种子可以复现随机结果,用于调参;

建立模型步骤

  1. 使用pd.read_csv导入数据;
  2. 使用聚类算法离散化连续特征;
  3. 使用one hot处理类别特征;
  4. 建立xgboost模型;
  5. 使用XGBoost 提供的 cv 函数进行自动化参数选择;
  6. 使用 Sklearn 的 GridSearchCV 自动测试参数;
  7. 拟合模型,输出预测结果;

项目代码

详细调优参考:https://zhuanlan.zhihu.com/p/33700459

#! /usr/bin/env python3.6
# _*_ coding:utf-8 _*_
import xgboost as xgb
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from xgboost.sklearn import XGBClassifier
from sklearn.model_selection import GridSearchCV
from xgboost import callback
#忽略numpy的警告,因为numpy版本问题,有时使用会报警告
import warnings
warnings.filterwarnings(module='sklearn*', action='ignore', category=DeprecationWarning)

#加载数据
train = pd.read_csv(r'C:/Users/guan/Downloads/adver/train.csv')
test = pd.read_csv(r'C:/Users/guan/Downloads/adver/test.csv')
train1 = train.drop('Label', axis=1)
#不对train和test进行组合的话,两个数据内类目特征不一致,会导致onehot编码不同
train_test = train1.append(test)

#聚类离散化函数
def cluster_plot(x,column,k):
    data = x[column].copy()
    s = x[column][:len(x)]
    data.dropna(inplace=True)#丢弃nan值
    data = data.values
    #使用聚类算法找出连续数据的k个聚类点
    kmodel = KMeans(n_clusters=k)
    kmodel.fit(data.reshape(len(data),1))
    c = pd.DataFrame(kmodel.cluster_centers_, columns=['a']).sort_values(by='a')
    w1 = c.rolling(window=2).mean().iloc[1:]#rolling——mean()移动平均函数
    w2 = [-3] + list(w1['a']) + [s.max()]
    cluster_d = pd.cut(s, bins=w2, labels=range(k))#cut函数根据bins等频分割data,labels返回分割后的标签
    return cluster_d
#对I1-I13离散化
ob_feature1 = ['I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9', 'I11', 'I12', 'I13']
for o in ob_feature1:
    train_test[o] = cluster_plot(train_test, o, 10)
train_test['I10'] = cluster_plot(train_test, 'I10', 4)

#处理类目特征函数
def str2int(x,column):
    a = x[column].copy()
    a.dropna(inplace=True)
    lables = a.unique().tolist()
    value_dict = {}
    for index, value in enumerate(lables, start=1):
        value_dict[value] = index
    return x[column].apply(lambda s: value_dict.get(s))
#处理类目特征C1-C26
ob_feature2 = [* map(lambda x:'C' + str(x), list(range(27))[1:])]
for p in ob_feature2:
    train_test[p] = str2int(train_test, p)

#对类目特征独热编码
ytrain=train['Label']
xgb_train_test = pd.get_dummies(train_test, columns=ob_feature2)

#加载的I1-I13为category类型,转换为float类型
for i in ob_feature1:
    xgb_train_test[i] = xgb_train_test[i].astype('float64')
xgb_train_test['I10'] = xgb_train_test['I10'].astype('float64')

#分割训练集和预测集
xgb_train = xgb_train_test[:1599]
xgb_train = xgb_train.drop('Id', axis=1)
dtest = xgb_train_test[1599:]

#参数调优
#寻找最佳迭代次数函数
#cv_folds 是交叉验证的份数,early_stopping_rounds 是在多少次迭代 metrics 没有变好的情况下提前结束,
#这个函数可以找到此参数组下最佳的迭代次数(n_estimators)
def model_cv(model, X, y, cv_folds=5, early_stopping_rounds=50, seed=0):
    xgb_param = model.get_xgb_params()
    xgtrain = xgb.DMatrix(X, label=y)
    cvresult = xgb.cv(xgb_param, xgtrain, num_boost_round=model.get_params()['n_estimators'], nfold=cv_folds,
                    metrics='auc', seed=seed, callbacks=[xgb.callback.print_evaluation(show_stdv=False),
                                                         xgb.callback.early_stop(early_stopping_rounds)])
    num_round_best = cvresult.shape[0] - 1
    print('Best round num: ', num_round_best)
    return num_round_best

#建立模型
num_round = 85
seed = 0
max_depth = 10
min_child_weight = 1
gamma = 0
subsample = 0.8
colsample_bytree = 0.8
scale_pos_weight = 1
reg_alpha = 1
reg_lambda = 1e-5
learning_rate = 0.1
model = XGBClassifier(learning_rate=learning_rate, n_estimators=num_round, max_depth=max_depth,
                      min_child_weight=min_child_weight, gamma=gamma, subsample=subsample, reg_alpha=reg_alpha,
                      reg_lambda=reg_lambda, colsample_bytree=colsample_bytree, objective='binary:logistic',
                      nthread=4, scale_pos_weight=scale_pos_weight, seed=seed)

# num_round = model_cv(model, xgb_train, ytrain)

#自动测试参数
def gridsearch_cv(model, test_param, X, y, cv=5):
    if __name__ == '__main__':#不加这会报错
        gsearch = GridSearchCV(estimator=model, param_grid=test_param, scoring='roc_auc', n_jobs=4, iid=False, cv=cv)
        gsearch.fit(X, y)
        print('CV Results: ', gsearch.cv_results_)
        print('Best Params: ', gsearch.best_params_)
        print('Best Score: ', gsearch.best_score_)
        return gsearch.best_params_

# 调整 max_depth,min_child_weight,1.max_depth=9,1.min_child_weight=1,1.bestscore=0.6963890572291257
# param_test1 = {
#     'max_depth': range(3, 10, 2),
#     'min_child_weight': range(1, 10, 2)}
# param_test1 = {
#     'max_depth': [8, 9, 10],
#     'min_child_weight': [1, 2]}
# gridsearch_cv(model, param_test1, xgb_train, ytrain)

#调整gamma
param_test2 = {
    'gamma': [i / 10.0 for i in range(0, 5)]}
# gridsearch_cv(model, param_test2, xgb_train, ytrain)

model.fit(xgb_train, ytrain)

dtest1 = dtest.drop('Id', axis=1)

results = model.predict_proba(dtest1)#输出预测结果的概率

r = map(lambda x: results[x][1], range(len(results)))
results = pd.Series(list(r), name="Predicted")

submission = pd.concat([dtest['Id'], results], axis=1)#组合id和结果

submission.to_csv("adver_Result_xgboost.csv", index=False)#保存
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值