完整代码 练习入口 补充一个画图工具 xgboost与lightgbm比较, 我也要测一次 据说stacking得分会更高 https://blog.csdn.net/zhouwenyuan1015/article/details/77372863 首先说下总的mae:19.7 但是gridSearch的best_csore_并不高,是个负数,这一点我还没搞懂,希望网友帮解惑。 我敢提交是因为测试结果mae是20.XXX,觉得结果还不错。
-------------------------------------------------------------分割线-------------------------------------------------------
首先看下所有的特征介绍
特征解释类型id行编号没有实际意义club该球员所属的俱乐部该信息已经被编码league该球员所在的联赛已被编码birth_date生日格式为月/日/年height_cm身高(厘米)数值变量weight_kg体重(公斤)数值变量nationality国籍已被编码potential球员的潜力数值变量pac球员速度数值变量sho射门(能力值)数值变量pas传球(能力值)数值变量dri带球(能力值)数值变量def防守(能力值)数值变量phy身体对抗(能力值)数值变量international_reputation国际知名度数值变量skill_moves技巧动作数值变量weak_foot非惯用脚的能力值数值变量work_rate_att球员进攻的倾向分类变量,Low,Medium,Highwork_rate_def球员防守的倾向分类变量,Low,Medium,Highpreferred_foot惯用脚1表示右脚、2表示左脚crossing传中(能力值)数值变量finishing完成射门(能力值)数值变量heading_accuracy头球精度(能力值)数值变量short_passing短传(能力值)数值变量volleys凌空球(能力值)数值变量dribbling盘带(能力值)数值变量curve弧线(能力值)数值变量free_kick_accuracy定位球精度(能力值)数值变量long_passing长传(能力值)数值变量ball_control控球(能力值)数值变量acceleration加速度(能力值)数值变量sprint_speed冲刺速度(能力值)数值变量agility灵活性(能力值)数值变量reactions反应(能力值)数值变量balance身体协调(能力值)数值变量shot_power射门力量(能力值)数值变量jumping弹跳(能力值)数值变量stamina体能(能力值)数值变量strength力量(能力值)数值变量long_shots远射(能力值)数值变量aggression侵略性(能力值)数值变量interceptions拦截(能力值)数值变量positioning位置感(能力值)数值变量vision视野(能力值)数值变量penalties罚点球(能力值)数值变量marking卡位(能力值)数值变量standing_tackle断球(能力值)数值变量sliding_tackle铲球(能力值)数值变量gk_diving门将扑救(能力值)数值变量gk_handling门将控球(能力值)数值变量gk_kicking门将开球(能力值)数值变量gk_positioning门将位置感(能力值)数值变量gk_reflexes门将反应(能力值)数值变量rw球员在右边锋位置的能力值数值变量rb球员在右后卫位置的能力值数值变量st球员在射手位置的能力值数值变量lw球员在左边锋位置的能力值数值变量cf球员在锋线位置的能力值数值变量cam球员在前腰位置的能力值数值变量cm球员在中场位置的能力值数值变量cdm球员在后腰位置的能力值数值变量cb球员在中后卫的能力值数值变量lb球员在左后卫置的能力值数值变量gk球员在守门员的能力值数值变量y该球员的市场价值(单位为万欧元)这是要被预测的数值
1、预处理
函数功能full_birthDate原表中的年份数据是2位,比如格式是这样的,09/10/89,因为计算年龄,所以补为完整的09/10/1989trans把csv中的非数值字符换为数值judgecsv中有一些数据是空的,需要去除空数据
def full_birthDate(x):
if(x[-2:] == '00'):
return x[:-2]+'20'+x[-2:]
else:
return x[:-2]+'19'+x[-2:]
def trans(x):
if(x == 'Medium'):
return 1
elif(x == 'High'):
return 2
else:
return 0
def judge(x):
if(x > 0):
return 1
else:
return 0
2、读取数据,并新增初步的特征
增加的特征有:age、BMI、is_gk 这部分是看网站的标杆做的,自己本身没研究更多的特征工程
# 读取数据
def getData():
train = pd.read_csv('./data/train.csv')
test = pd.read_csv('./data/test.csv')
train['birth_date_'] = train['birth_date'].apply(lambda x: full_birthDate(x))
test['birth_date_'] = test['birth_date'].apply(lambda x: full_birthDate(x))
train['birth_date'] = pd.to_datetime(train['birth_date_'])
train['age'] = ((pd.Timestamp.now() - train['birth_date']).apply(lambda x: x.days) / 365).apply(lambda t: int(t))
test['birth_date'] = pd.to_datetime(test['birth_date_'],format='%m/%d/%Y', errors='coerce')
test['age'] = ((pd.Timestamp.now() - test['birth_date']).apply(lambda x: x.days) / 365).apply(lambda t: int(t))
train['work_rate_att_'] = train['work_rate_att'].apply(lambda x: trans(x)).apply(lambda t: int(t))
train['work_rate_def_'] = train['work_rate_def'].apply(lambda x: trans(x)).apply(lambda t: int(t))
test['work_rate_att_'] = test['work_rate_att'].apply(lambda x: trans(x)).apply(lambda t: int(t))
test['work_rate_def_'] = test['work_rate_def'].apply(lambda x: trans(x)).apply(lambda t: int(t))
train = train.drop('id',axis=1)
train = train.drop('birth_date',axis=1)
train = train.drop('birth_date_',axis=1)
train = train.drop('work_rate_att',axis=1)
train = train.drop('work_rate_def',axis=1)
test = test.drop('id',axis=1)
test = test.drop('birth_date',axis=1)
test = test.drop('birth_date_',axis=1)
test = test.drop('work_rate_att',axis=1)
test = test.drop('work_rate_def',axis=1)
return train,test
3、数据分析
新增一个特征:best_pos(最佳位置)是通过对[‘rw’, ‘rb’, ‘st’, ‘lw’, ‘cf’, ‘cam’, ‘cm’, ‘cdm’, ‘cb’, ‘lb’, ‘gk’]这11个特征的汇总。
特征解释类型rw球员在右边锋位置的能力值数值变量rb球员在右后卫位置的能力值数值变量st球员在射手位置的能力值数值变量lw球员在左边锋位置的能力值数值变量cf球员在锋线位置的能力值数值变量cam球员在前腰位置的能力值数值变量cm球员在中场位置的能力值数值变量cdm球员在后腰位置的能力值数值变量cb球员在中后卫的能力值数值变量lb球员在左后卫置的能力值数值变量gk球员在守门员的能力值数值变量
盒图是用来观测离群点的,目前还没用到,等下一步用到在更新…
def data_ana(train, test):
# 获得球员最擅长位置上的评分
positions = ['rw', 'rb', 'st', 'lw', 'cf', 'cam', 'cm', 'cdm', 'cb', 'lb', 'gk']
train['best_pos'] = train[positions].max(axis=1)
test['best_pos'] = test[positions].max(axis=1)
# 计算球员的身体质量指数(BMI)
train['BMI'] = 10000. * train['weight_kg'] / (train['height_cm'] ** 2)
test['BMI'] = 10000. * test['weight_kg'] / (test['height_cm'] ** 2)
# 判断一个球员是否是守门员
train['is_gk'] = train['gk'].apply(lambda x: judge(x))
test['is_gk'] = test['gk'].apply(lambda x: judge(x))
return train,test
def view_filter(train):
# 可视化盒图
# # 统计输出信息
percentile_result = np.percentile(train['y'], [25, 50, 75])
num = 0
for i in list(train['y']):
if(i > percentile_result[2] * 1.5):
num+=1
print(i)
# print('离群点个数:',num,'\n四分位数Q3:',percentile_result[2])
# print(num/len(list(train['y'])))
# 显示图例
plt.boxplot(x=train['y'],showmeans=True,meanline=True,whis=1.5)
plt.legend()
savefig('盒图.jpg')
# 显示图形
plt.show()
plt.close()
4、训练
4.1 特征选择
注意n_estimators一定初始化大一点,因为会自动在收敛的地方自己停 选择特征,顺便确定n_estimators
def xgboost_select_feature(data_, labels_,cols,target):# # 特征选择
xgb1 = XGBRegressor(learning_rate =0.1,max_depth=5,min_child_weight=1,n_estimators=1000,
gamma=0,subsample=0.8,colsample_bytree=0.8,objective= 'reg:logistic',
nthread=4,scale_pos_weight=1,seed=27)
feature_ = list(modelfit(xgb1, data_.values,labels_.values,cols,target)) # 特征选择
return feature_
def modelfit(alg, data, labels_, cols, target, useTrainCV=True, cv_folds=7, early_stopping_rounds=50):
# 可以返回n_estimates的最佳数目,为什么呢, 哪里返回?
if useTrainCV:
xgb_param = alg.get_xgb_params()
xgtrain = xgb.DMatrix(data, label=labels_)
cvresult = xgb.cv(xgb_param, xgtrain, num_boost_round=alg.get_params()['n_estimators'], nfold=cv_folds,
metrics='mae', early_stopping_rounds=early_stopping_rounds)
alg.set_params(n_estimators=cvresult.shape[0])
#Fit the algorithm on the data
seed = 20
# seed=20从0.97升为了0.98
# Model Report
# r2_score : 0.9845
# MAE: 0.4723899992310908 %
test_size = 0.3
x_train,x_test,y_train,y_test = train_test_split(data, labels_, test_size=test_size,random_state=seed)
print(x_train.shape[1],y_train.shape[1])
eval_set = [(x_test,y_test)]
alg.fit(x_train, y_train, early_stopping_rounds=early_stopping_rounds, eval_metric='mae',eval_set=eval_set,verbose=True)
#Predict training set:
dtrain_predictions = alg.predict(x_test)
# print(type(dtrain_predictions),type(labels_))
y_true = list(y_test)
y_pred = list(dtrain_predictions)
print(type(y_pred),type(y_true))
#Print model report:
print("\nModel Report")
print("r2_score : %.4g" % metrics.r2_score(y_true, y_pred))
mae_y = 0.00
for i in range(len(y_true)):
mae_y += np.abs(np.float(y_true[i])-y_pred[i])
print("MAE: ", (mae_y*4799+6)/len(y_true))
# Model Report
# r2_score : 0.9673
# MAE: 0.636517748270864 %
feat_imp = pd.Series(alg.get_booster().get_fscore()).sort_values(ascending=False)
# feat_imp.plot(kind='bar', title='Feature Importances')
# plt.ylabel('Feature Importance Score')
fig, ax = plt.subplots(1, 1, figsize=(8, 13))
plot_importance(alg, max_num_features=25, height=0.5, ax=ax)
plt.show()
# 重要性筛选
feat_sel = list(feat_imp.index)
feat_val = list(feat_imp.values)
featur = []
for i in range(len(feat_sel)):
featur.append([cols[int(feat_sel[i][1:])],feat_val[i]])
print('所有特征的score:\n',featur)
feat_sel2 = list(feat_imp[feat_imp.values > target].index)
featur2 = []
for i in range(len(feat_sel2)):
featur2.append(cols[int(feat_sel2[i][1:])])
return featur2
def MAE_(xgb1,train_x,train_y):
y_pre = list(xgb1.predict(train_x))
train_y = train_y.as_matrix()
num = 0
for i in range(len(y_pre)):
num += np.abs(y_pre[i] - train_y[i])
print((num*4799+6)/len(y_pre))
4.2训练
根据上一步获得特征排序,选择前11个作为训练的特征,选择好特征,就可以进行训练了。
def xgboost_train(train_x, train_y):
# # 半手动调参-------------------是个过程------调参成功需要注释掉---------------------------------------------------
# param_test1 = {
# 'max_depth':range(22,27)
# }
# gsearch1 = GridSearchCV(estimator = XGBRegressor(learning_rate=0.1, n_estimators=366, min_child_weight=1,subsample=0.85,colsample_bytree=0.8,
# gamma=0,objective= 'reg:logistic', nthread=4, seed=27),
# param_grid = param_test1,scoring='neg_median_absolute_error',n_jobs=4, iid=False, cv=5)
#gsearch1.fit(train_x,train_y)
# print(gsearch1.best_params_,gsearch1.best_score_)
# 半手动调参---结果太差了-----------------------------------------------------------------------------------------
# 20个特征,mae=19
# {'max_depth': 19} -0.000962098801735801
# {'max_depth': 20} -0.0009953797204438424
# {'max_depth': 24} -0.0009504750202941337
# 15个特征
# {'max_depth': 25} -0.0010135409208229943
# 24个特征
# {'max_depth': 18} -0.0009839476411412358
# 22个特征 结果不如19,mae=20
# {'max_depth': 23} -0.0009574992929236896
# 虽然是负数,最后的mae还是可以的19
train_x = train_x.as_matrix()
xgb1 = XGBRegressor(learning_rate=0.1, n_estimators=366, max_depth=23, min_child_weight=1,subsample=0.8,colsample_bytree=0.8,
gamma=0,objective= 'reg:logistic', nthread=4, scale_pos_weight=1, seed=27)
xgb1.fit(train_x,train_y)
MAE_(xgb1,train_x,train_y)
return xgb1