赞
踩
LightGBM(Light Gradient Boosting Machine):一个实现GBDT算法的框架,解决GBDT在海量数据遇到的问题。
(1)GOSS(Gradient-based One-Side Sampling):减少样本数
(2)EFB (Exclusive Feature Bundling ):减少特征数
XGBoost的缺点:先预排序再找分割点,空间消耗大
XGBoost与LightGBM的区别:
lightGBM | XGBoost | |
---|---|---|
分裂方式 | leaft-wise选择分裂收益最大的节点,要限制深度容易过拟合 | level-wise无差别分裂 |
输入 | lightgbm支持直接输入categorical 的feature | 需要one-hot编码 |
时间复杂度 | 基于直方图的决策树算法,直方图的优化算法只需要计算K次,时间复杂度为O(Kfeature) | 基于预排序的决策树算法,每遍历一个特征就需要计算一次特征的增益,时间复杂度为O(datafeature) |
特征捆绑转化为图着色问题,减少特征数量 |
导包
import lightgbm as lgb
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
gbm = lgb.LGBMRegressor(objective='regression', num_leaves=31, learning_rate=0.05, n_estimators=20)
gbm.fit(X_train, y_train, eval_set=[(X_test, y_test)], eval_metric='l1', early_stopping_rounds=5)
数据集切分与转换
lgb_train = lgb.Dataset(X_train, y_train)
#If this is Dataset for validation, training data should be used as reference.
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train)
将参数写为字典形式
params = {
'task': 'train',
'boosting_type': 'gbdt', # 设置提升类型
'objective': 'regression', # 目标函数
'metric': {'l2', 'auc'}, # 评估函数
'num_leaves': 31, # 叶子节点数
'learning_rate': 0.05, # 学习速率
'feature_fraction': 0.9, # 建树的特征选择比例
'bagging_fraction': 0.8, # 建树的样本采样比例
'bagging_freq': 5, # k 意味着每 k 次迭代执行bagging
'verbose': 1 # <0 显示致命的, =0 显示错误 (警告), >0 显示信息
}
交叉验证与预测评估
gbm = lgb.train(params, lgb_train, num_boost_round=20, valid_sets=lgb_eval, early_stopping_rounds=5)
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration)
一个完整的数据集通过了神经网络一次并且返回了一次。梯度下降的方法来优化学习过程,随着epoch
batch需要完成一个epoch的次数
一个迭代=一个正向通过+一个反向通过。
不能将数据一次性通过神经网络的时候,就需要将数据集分成几个batch。
batchsize的选择:Batch:数据集较小选择全批次
mini batch:选定后以batch的大小输入网络,计算这个batch的所有样本的平均损失,即代价函数是所有样本的平均
stochastic:每次修正方向以各自样本的梯度方向修正,难收敛
如果batchsize过小,训练数据难以收敛容易欠拟合,增加batchsize相对处理速度加快但是占用内存增加
预先固定的参数 | 调整策略 |
---|---|
learning_rate | 0.05~0.1 学习率较小比较稳定。默认0.1 |
n_estimators | 100~1000。可以设置一个较大的值配合early_stopping_round来让模型根据性能自动选择最好的迭代次数。默认100 |
min_split_gain | 执行节点分裂的最小增益。默认为0。不建议去调整。增大这个数值会得到相对浅的树深。可调整其他参数得到类似效果。 |
min_child_sample | 一个叶子上的最小数据量。默认设置为20.数据量大适当增加 |
min_child_weight | 一个叶子上的最小hessian和。默认设置为0.001,一般设置为1。不建议调整,增大数值会得到较浅的树深 |
通过算法来搜索的参数 | 调整策略 |
---|---|
max_depth | 3,4,5(过大容易过拟合) |
num_leaves | 小于2^max_depth-1 |
subsample | 大致的搜索范围[0.8, 0.9, 1.0] |
colsample_bytree | 大致的搜索范围[0.8, 0.9, 1.0] |
reg_alpha | 服务于L1正则化,一般取0-1000的范围。通过特征筛选该数值由大变小可以增加模型信心 |
reg_lambda | 服务于L2正则化,一般0-1000的范围。如果有非常强势的特征,可以人为加大一些reg_lambda使得整体特征效果平均一些,一般会比reg_alpha的数值略大一些,但如果这个参数大的夸张也需要再查看一遍特征是否合理 |
import lightgbm as lgb
def cv_model(clf, train_x, train_y, test_x, clf_name):
划分100折并进行数据打乱
folds = 10
seed = 2022
kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
设置测试集的输出矩阵。每一组数据输出:[0,0,0,0]以概率值填入
test = np.zeros((test_x.shape[0],4))
#交叉验证分数
cv_scores = []
onehot_encoder = OneHotEncoder(sparse=False)
根据折数进行划分,i值代表第(i+1)折。每一个K折都进行「数据混乱:随机」操作
train_index:10折里9折在train_index
valid_index:剩下1折样本索引值,作为验证集用于给出「训练误差」
for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
if i < 9:
#打印第(i+1)个模型结果
print('模型:'i+1)
#将训练集分为:真正训练的数据(K-1折),和 训练集中的测试数据(1折)
trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y.iloc[train_index], train_x.iloc[valid_index], train_y.iloc[valid_index]
#LGB模型 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', #boosting方式 'objective': 'multiclass', #任务类型为「多分类」 'num_class': 4, #类别个数 'num_leaves': 2 ** 5, #最大的叶子数,树模型的复杂度 'feature_fraction': 0.8, #每次迭代中随机选择特征的比例(0.5-0.9之间调整) 'bagging_fraction': 0.8, #不进行重采样的情况下随机选择部分数据(0.5-0.9之间调整) 'bagging_freq': 5, #每5次迭代,进行一次bagging(3-5之间调整) 'learning_rate': 0.05, #学习率 'seed': seed, #seed值,保证模型复现 'nthread': 28, 'n_jobs':24, #多线程 'verbose': 1, 'lambda_l1': 0.4, # L1正则化 'lambda_l2': 0.5, #L2正则化 'min_data_in_leaf':100, #叶子可能具有的最小记录数 } #模型 model = clf.train(params, train_set=train_matrix, #训练样本 valid_sets=valid_matrix, #测试样本 num_boost_round=2000, #迭代次数 verbose_eval=100, early_stopping_rounds=200) #如果数据在200次内没有提高,停止计算
val_pred = model.predict(val_x, num_iteration=model.best_iteration) test_pred = model.predict(test_x, num_iteration=model.best_iteration) val_y = np.array(val_y).reshape(-1, 1) val_y = onehot_encoder.fit_transform(val_y) print('预测的概率矩阵:') print(test_pred) test += test_pred #验证集计算训练误差 score = loss(val_y, val_pred) cv_scores.append(score) 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)) #i个模型输出结果的平均值。 test = test / 10 return test
def lgb_model(x_train, y_train, x_test):
lgb_test = cv_model(lgb, x_train, y_train, x_test, "lgb")
return lgb_test
def loss(y_p,y_t):
y_p=np.array(y_p)
y_t=np.array(y_t)
loss=sum(sum(abs(y_p-y_t)))
return loss
lgb_test = lgb_model(X_train, y_train, X_test)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。