前三个部分分别介绍了如何清洗广告数据集、用户数据集、曝光广告数据集和测试集,以及构如何构造训练的标签,具体链接见下文,在我们构造好训练集之后,我们开始使用XGBOOST模型训练数据集,训练方法分为两个版本,第一个版本是简单版本,训练集的属性列中只包含取唯一值的数据,第二个版本是加上取多值的属性列。参考的代码链接是bryan大佬18年腾讯算法大赛公布的baseline。
第一部分: 如何清洗广告数据集和用户数据集
第二部分: 如何清洗曝光广告数据集以及构造标签
第三部分: 如何整理测试数据集以及构造训练集
前半年一直做的是GAN生成图像相关,所以在对这个XGBOOST不是很了解,只是简单参考别人的模型比着葫芦画个瓢,版本一代码能跑同,但是最后提交代码效果很差,版本二应该是训练集中的数据出现了非法字符例如 (' ,)一类的跑不通,准备先写论文就不做了。
版本1:属性列只是取唯一值 加上单调性的话 在测试集A上是可以达到79.75分的 已经试验过了
# -*- coding: utf-8 -*-
# @Time : 2019/5/4 9:11
# @Author : YYLin
# @Email : [email protected]
# @File : Code_For_Tencent.py
import pandas as pd
import matplotlib.pyplot as plt
import xgboost as xgb
import numpy as np
import sys
from xgboost import plot_importance
from sklearn.preprocessing import Imputer
def loadDataset(filePath):
df = pd.read_csv(filepath_or_buffer=filePath)
return df
def featureSet(data):
data_num = len(data)
XList = []
for row in range(0, data_num):
tmp_list = []
tmp_list.append(data.iloc[row]['ad_bid'])
tmp_list.append(data.iloc[row]['Ad_material_size'])
tmp_list.append(data.iloc[row]['Ad_Industry_Id'])
tmp_list.append(data.iloc[row]['Commodity_type'])
# 该参数用来表示投放时间 暂时不使用
# tmp_list.append(data.iloc[row]['Delivery_time'])
XList.append(tmp_list)
yList = data.num_click.values
return XList, yList
def loadTestData(filePath):
data = pd.read_csv(filepath_or_buffer=filePath)
data_num = len(data)
XList = []
for row in range(0, data_num):
tmp_list = []
tmp_list.append(data.iloc[row]['ad_bid'])
tmp_list.append(data.iloc[row]['Ad_material_size'])
tmp_list.append(data.iloc[row]['Ad_Industry_Id'])
tmp_list.append(data.iloc[row]['Commodity_type'])
# 该参数用来表示投放时间 暂时不使用
# tmp_list.append(data.iloc[row]['Delivery_time'])
XList.append(tmp_list)
return XList
def trainandTest(X_train, y_train, X_test):
# XGBoost训练过程
model = xgb.XGBRegressor(max_depth=5, learning_rate=0.1, n_estimators=160, silent=False, objective='reg:gamma')
model.fit(X_train, y_train)
# 对测试集进行预测 并且对预测结果保留四位有效数字
ans = model.predict(X_test)
ans_len = len(ans)
id_list = np.arange(1, ans_len+1)
data_arr = []
# 如果预测的数据长度和定义的数据长度一致 则将其合并保存
if ans_len == len(id_list):
for row in range(0, ans_len):
data_arr.append([int(id_list[row]), round(ans[row], 4)])
else:
print("!!!!!测试数据的长度和定义的标签长度不一致!!!!!")
sys.exit()
np_data = np.array(data_arr)
# 保存结果
pd_data = pd.DataFrame(np_data)
# print(pd_data)
pd_data.to_csv('submission.csv', index=None)
# 显示重要特征
# plot_importance(model)
# plt.show()
if __name__ == '__main__':
trainFilePath = '../Dataset/Result/Result_For_Train_test.csv'
testFilePath = '../Dataset/Result/Result_For_Test.csv'
print("!!!!!!!!!正在加载数据集!!!!!!!!!")
data = loadDataset(trainFilePath)
print("训练集中的数据信息是:\n", data.info())
X_test = loadTestData(testFilePath)
print("!!!!!!!!!正在构建模型的特征!!!!!!!!!!!")
X_train, y_train = featureSet(data)
print("!!!!!!正在训练中!!!!!!!!!!")
trainandTest(X_train, y_train, X_test)
版本2:2019-07-07新加对XGB能够使用网格搜索自动寻找最优参数,
# -*- coding: utf-8 -*-
# @Time : 2019/5/21 23:35
# @Author : YYLin
# @Email : [email protected]
# @File : new_submission_used_xgboost_v4.py
# 在模型中加入新的特征 广告 例如每日广告ID的出现次数
# 现在是讲LGB转化成XGBoost阶段 暂时不在数据集中增加数据
import pandas as pd
from sklearn.preprocessing import OneHotEncoder,LabelEncoder, StandardScaler
import xgboost as xgb
import numpy as np
import sys
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt
from xgboost import plot_importance
import math
# v4 加上一些特征选择的方法
from sklearn.feature_selection import SelectPercentile
# 05.21能够完全打印数据的信息
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)
pd.set_option('display.max_rows', None)
# 初始的时候 将该变量设置为 True 等待寻找好参数之后 然后将其设置成 False 并修改成训练集中的参数信息
find_params = False
# 对某些变量使用one-hot encoding 对另一些变量使用StandardScaler() encoding
def encode_feature_data(data, for_train=True):
XList = []
data_num = len(data)
if for_train:
print("*****正在加载训练数据, 训练数据的属性特点是*******", data.info())
else:
print("*****正在加载测试数据,测试数据的属性特点是*******", data.info())
# 仿照lgb对所有的数据使用one-hot encoding
enc = OneHotEncoder(categories='auto')
enc.fit(data)
enc.transform(data)
print("Standard_feature 相关的属性已经编码完毕")
if for_train:
# 对进行编码处理之后的数据转化成list用于输出
data['Exporse'] = data['Exporse'].apply(lambda x: math.log(x))
for row in range(0, data_num):
tmp_list = []
tmp_list.append(data['ad_request_datetime'][row])
tmp_list.append(data['ad_account_id'][row])
tmp_list.append(data['commodity_id'][row])
tmp_list.append(data['commodity_type'][row])
tmp_list.append(data['ad_industry_id'][row])
tmp_list.append(data['ad_martril_size'][row])
XList.append(tmp_list)
# Ylist.append(data.iloc[row]['Exporse'])
Ylist = data.Exporse.values
return XList, Ylist
else:
# 对进行编码处理之后的数据转化成list用于输出
for row in range(0, data_num):
tmp_list = []
tmp_list.append(data['ad_request_datetime'][row])
tmp_list.append(data['ad_account_id'][row])
tmp_list.append(data['commodity_id'][row])
tmp_list.append(data['commodity_type'][row])
tmp_list.append(data['ad_industry_id'][row])
tmp_list.append(data['ad_martril_size'][row])
XList.append(tmp_list)
return XList
# 定义使用XGBoost训练模型 需要增加自动调参的代码
def XGB_predict(X_train, y_train, X_test):
if find_params:
# cv_params 表示循行多少次 可以取得最优解 优化其他的参数见https://blog.csdn.net/sinat_35512245/article/details/79700029
cv_params = {'n_estimators': [4000, 5000, 6000, 7000, 10000]}
'''
cv_params = {'n_estimators': [400, 500, 600, 700, 800], 'max_depth': [3, 4, 5, 6, 7, 8, 9, 10],
'min_child_weight': [1, 2, 3, 4, 5, 6], 'gamma': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6], 'subsample': [0.6, 0.7, 0.8, 0.9],
'colsample_bytree': [0.6, 0.7, 0.8, 0.9], 'reg_alpha': [0.05, 0.1, 1, 2, 3], 'reg_lambda': [0.05, 0.1, 1, 2, 3],
'learning_rate': [0.01, 0.05, 0.07, 0.1, 0.2]}
'''
other_params = {'learning_rate': 0.1, 'n_estimators': 5000, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}
# 首先使用XGBRegressor做回归预测 预测结果之后使用 GridSearchCV 选择最优参数
model = xgb.XGBRegressor(**other_params)
optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5, verbose=1, n_jobs=4)
# model.fit(X_train, y_train)
grid_search = optimized_GBM.fit(X_train, y_train)
print("Best: %f using %s" % (grid_search.best_score_, grid_search.best_params_))
means = grid_search.cv_results_['mean_test_score']
params = grid_search.cv_results_['params']
for mean, param in zip(means, params):
print("%f with: %r" % (mean, param))
else:
# 对测试集进行预测
model = xgb.XGBRegressor(learning_rate=0.1, n_estimators=6000, max_depth=5, min_child_weight=1, seed=0,
subsample=0.8, colsample_bytree=0.8, gamma=0, reg_alpha=0, reg_lambda=1)
model.fit(X_train, y_train)
# 对测试集进行预测
predict_result = model.predict(X_test)
predict_result = np.exp(predict_result)
ans_len = len(predict_result)
id_list = np.arange(1, ans_len + 1)
data_arr = []
# 如果预测的数据长度和定义的数据长度一致 则将其合并保存
if ans_len == len(id_list):
for row in range(0, ans_len):
data_arr.append([int(id_list[row]), round(predict_result[row], 4)])
else:
print("!!!!!测试数据的长度和定义的标签长度不一致!!!!!")
sys.exit()
# 保存最后的生成结果 该程序没有增加单调性 需要对结果单独处理
# np_data = np.array(data_arr)
pd_data = pd.DataFrame(data_arr)
pd_data.to_csv('../Dataset/dataset_for_train/submission.csv', index=None, header=None)
# 需要手动关闭画图的面板 运行程序的时候 暂不执行
plot_importance(model)
plt.show()
if __name__ == '__main__':
trainFilePath = '../Dataset/dataset_for_train/train_op_dp.csv'
testFilePath = '../Dataset/dataset_for_train/update_Btest_sample.csv'
print("正在加载数据!!!!构建数据特征")
# 对数据进行encoding时 比较慢 所以在测试的时候可以只读取前10行的数据
# data = pd.read_csv(trainFilePath, nrows=10)
data = pd.read_csv(trainFilePath)
X_train, y_train = encode_feature_data(data)
# 原始代码中读取是文件信息 现在读取的是类型信息
print("X_train的类型是:", type(X_train), type(X_train[1]), X_train[1], type(y_train))
data_test = pd.read_csv(testFilePath)
X_test = encode_feature_data(data_test, for_train=False)
print("*******正在训练中*******")
XGB_predict(X_train, y_train, X_test)