机器学习算法的实现

机器学习算法的实现

1、随机森林RF

博客:

决策树(上)——ID3、C4.5、CART(非常详细)

决策树(中)——Random Forest、Adaboost、GBDT (非常详细)

论文:随机森林算法优化研究

原理

随机森林是一种常见的机器学习模型,可以根据特征对样本进行分类预测,因此被广泛使用。随机森林是由多棵决策树构成的组合分类器,由Breiman于2001年提出,其算法思想是通对bootstrap样本进行决策树建模,再将多个决策树进行组合输出最终的预测结果。

随机森林算法还可以在分类的基础上进行回归分析,通过将样本分类的结果进行一定的运算可以获得各个特征重要性特征的重要性表示特征对预测结果影响程度,某一特征重要性越大,表明该特征对预测结果的影响越大,重要性越小,表明该特征对预测结果越小。随机森林算法中某一特征的重要性,是该特征在内部所有决策树重要性的平均值。

过程

随机森林算法主要有两个重要的随机过程,一个是随机选择每棵决策树的训练样本,另外一个是随机选择特征子集。随机森林是通过自助采样的方式有放回的选取对应数据集,并且在总的特征集合中随机选取指定数目的特征作为特征子集。具体如下:

训练随机森林的过程就是训练各个决策树的过程,由于各个决策树的训练是相互独立的,因此随机森林的训练可以通过并行处理来实现,这将大大提高生成模型的效率。

将以同样的方式训练得到 K 个决策树组合起来,就可以得到一个随机森林。当输入待分类的样本时,随机森林输出的分类结果由每个决策树的输出结果进行简单投票(分类取众数,回归取平均数

优点(树模型共有的优点)

随机森林对噪声和异常值有较好的容忍性,能够在不需要降维的条件下处理具有高维特征的输入样本,而且能够评估各个特征在分类问题上的重要性,具有良好的可扩展性和并行性

2、梯 度 提 升 树 GBDT

基于LightGBM的用户购买行为预测研究

梯 度 提 升 树 (Gradient Boosting Decision Tree, GBDT) 是 集 成 学 习 中Boosting 思 想 的 算 法 , 基 学 习 器 是 CART 回 归 树 [19], 它 实 际 上 是 提 升 树(Boosting Decision Tree) 的推广, 二者的区别在于损失函数, 提升树损失函数是特定的, 梯度提升树的损失函数更具一般性, 可以自定义, 它在刚开始被提出时就是公认的泛化能力较强的算法.

通俗理解: 假设我们希望预测一个人的年龄, 他的实际年龄为 30 岁, 首先用一个模型预测为 20 岁, 发现离真实值还有 10 岁差距, 为了不改变原有模型的参数, 于是想到在原有模型的基础上做一些改善来弥补差距, 建立一个新的模型来拟合未完全拟合的部分即这 10 岁的差距, 继续迭代下去, 最终将预测的岁数相加就是模型输出的结果 .

3、XGBoost

好的博客:

决策树(下)——XGBoost、LightGBM(非常详细)

Boosting算法4 --- LightGBM介绍与分布式

论文:

基于LightGBM的用户购买行为预测研究

近似算法

结点分裂时, 传统算法的基本思想为: 遍历每一个特征, 根据特征值的大小对结点中样本进行升序排列, 分别将每个特征值作为分割阈值, 阈值左边的样本分到左结点, 右边的样本分到右结点; 计算增益, 若增益增大, 则更新目前的分割特征和阈值; 所有特征遍历完后, 输出最终的特征和阈值.

当数据量太大时, 传统算法将数据加载到内存或者分布式环境时会超出, 传统算法将不再适合. 于是 XGBoost 提出了一种近似算法 (Approximate Algorithm)解决这个问题. 具体思想为: 根据每个特征的分布, 找到候选分割点集合, 在结点分裂时, 遍历分割点集合中的值计算增益即可, 不需要遍历全部样本的值, 加快训练速度。

稀疏特征的分裂算法

若样本某个特征缺失, 结点分裂遍历该特征时, 没办法对样本进行左右结点的分配, 基于此, XGBoost 提出了Sparsity Aware Split Finding 算法, 通过该算法可以自动为样本分配一个使增益最大的分裂方向, 这加快了模型的训练速度。

4、LightGBM

同一系列算法(梯 度 提 升 树 GBDT,XGBoost

那些老的算法,硕士博士学位论文一般讲的比较详细

好的博客:

决策树(下)——XGBoost、LightGBM(非常详细)

Boosting算法4 --- LightGBM介绍与分布式

论文:

基于LightGBM的用户购买行为预测研究

基于LightGBM模型的车辆保险购买兴趣预测研究

三、代码实现

1、预处理

① 首先读取表格数据并合并(一般用pandas),获取变量df和标签y

import pandas  as pd

# 读取表格,相对路径,默认第一个表
df1=pd.read_excel("ERa_activity.xlsx")
df2=pd.read_excel("Molecular_Descriptor.xlsx")

# 根据"SMILES"列合并表格
df=pd.merge(df1,df2,on="SMILES")

#弹出无用的列,获取标签y,剩下的df即为自变量
df.pop("SMILES")
df.pop("IC50_nM")
y=df.pop("pIC50")

② 划分训练集和验证集(当做测试集用)

from sklearn.model_selection import train_test_split
x_train, x_val, y_train, y_val = train_test_split(df, y, test_size = 0.3, random_state = 2021)</pre>

2、模型构建

LGB的实现

  1. lightbgm构建有两种方法:
    一种用原生形式使用lightgbm,另一种用Sklearn接口形式使用lightgbm
    第二种才能使用GridSearchCV搜索最优参数
  2. 而且两种方法得到特征重要性权重的方式也不同,但只要说的有道理就好了
第一种方法实现

① 原生形式使用lightgbm构建模型与训练

from sklearn.metrics import mean_absolute_error
import lightgbm as lgb

# 参数设置
params = {
 'boosting_type': 'gbdt',
 'objective': 'regression',    # 用于回归
 'learning_rate': 0.1,    # 选定一较高的值,通常是0.1
 'num_leaves': 50,    # 由于lightGBM是leaves_wise生长,官方说法是要小于2^max_depth
 'max_depth': 10,    # 由于数据集不大,所以选择一个适中的值,4-10都可以
 'subsample': 0.8,    # 数据采样
 'colsample_bytree': 0.8,    # 特征采样
 }

dtrain = lgb.Dataset(x_train, y_train, silent=True)
dvalid = lgb.Dataset(x_val, y_val, silent=True)
# 模型训练
clf_first = lgb.train(
 params=params,
 train_set=dtrain,
 num_boost_round=50000,
 valid_sets=[dtrain, dvalid],
 early_stopping_rounds=100,   # 如果验证集效果100轮未提升就停止
 verbose_eval=100
 )
# 误差
print(mean_absolute_error(clf_first.predict(x_train),y_train))
print(mean_absolute_error(clf_first.predict(x_val),y_val))

② 作图(这里截取获得前20重要性特征的部分)

import  matplotlib.pyplot as plt
import numpy as np

def plot_feature_importance(dataset, model_bst):
 list_feature_name = list(dataset.columns[:])
 list_feature_importance =model_bst.feature_importance()
 dataframe_feature_importance = pd.DataFrame(
 {'feature_name': list_feature_name, 'importance': list_feature_importance})
 dataframe_feature_importance20 = dataframe_feature_importance.sort_values(by='importance', ascending=False)[:30]
第二种方法

用Sklearn接口形式使用lightgbm,并使用Gridsearchcv对lightgbm调参:网格搜索和交叉验证

  1. 网格搜索,搜索的是参数,即在指定的参数范围内,按步长依次调整参数,利用调整的参数训练学习器,从所有的参数中找到在验证集上精度最高的参数,这其实是一个循环和比较的过程。 GridSearchCV可以保证在指定的参数范围内找到精度最高的参数,但是这也是网格搜索的缺陷所在,它要求遍历所有可能参数的组合,在面对大数据集和多参数的情况下,非常耗时。
  1. 交叉验证的概念也很简单: 将训练数据集划分为K份,K一般为10(我个人取3到5比较多) ; 依次取其中一份为验证集,其余为训练集训练分类器,测试分类器在验证集上的精度 ; 取K次实验的平均精度为该分类器的平均精度

说实话,对回归模型进行网格搜索不是很靠谱,必须cv足够大比如10,才能找到真正在验证集上效果最好的参数。(也可能是因为这里我自己划分了验证集的原因),如果评估的时候采用交叉验证那肯定是没问题的

① 参数优化(这里只以优化max_depth和num_leaves为例,其它参数优化见代码)

from sklearn.model_selection import GridSearchCV

print('网格搜索,参数优化')
#step1 调节max_depth以及num_leaves,确定树的深度及复杂度
# 设置网格参数范围
parameters = {'max_depth': range(4, 12, 2),
 'num_leaves': range(20, 60, 10)
 }
# 用Sklearn接口形式使用lightgbm
estimator = lgb.LGBMRegressor(objective='regression',
 learning_rate=0.1,
 subsample=0.8,#数据采样
 colsample_bytree=0.8,#特征采样
 early_stopping_rounds=100,
 importance_type="gain"
 )

# 构建网格交叉验证搜索,评分函数:平均绝对误差,训练集划分为5份
gsearch = GridSearchCV(estimator, param_grid=parameters, scoring='neg_mean_absolute_error', cv=10)

gsearch.fit(x_train, y_train,
 eval_set=[(x_val, y_val)],  # 评估数据集
 eval_names=['val'],
 )

print('参数的最佳取值:{0}'.format(gsearch.best_params_))
print('最佳模型得分:{0}'.format(gsearch.best_score_))
print(gsearch.cv_results_['mean_test_score'])
print(gsearch.cv_results_['params'])

② 模型构建

estimator = lgb.LGBMRegressor(objective='regression',
 learning_rate=0.1,
 subsample=0.8,#数据采样
 colsample_bytree=0.8,#特征采样
 early_stopping_rounds=100,
 num_leaves= 50,    # 由于lightGBM是leaves_wise生长,官方说法是要小于2^max_depth
 max_depth=10,    # 由于数据集不大,所以选择一个适中的值,4-10都可以
 importance_type="gain"
 )

estimator.fit(x_train, y_train,
 eval_set=[(x_val, y_val)],  # 评估数据集
 eval_names=['val'],
 )

print(mean_absolute_error(estimator.predict(x_train),y_train))
print(mean_absolute_error(estimator.predict(x_val),y_val))

③ 打印前20重要性的分子和它的权重

def plot_feature_importance(dataset, model_bst):
 list_feature_name = list(dataset.columns[:])
 list_feature_importance =model_bst.feature_importances_
 dataframe_feature_importance = pd.DataFrame(
 {'feature_name': list_feature_name, 'importance': list_feature_importance})
 dataframe_feature_importance20 = dataframe_feature_importance.sort_values(by='importance', ascending=False)[:30]
 print(dataframe_feature_importance20)
 x = range(len(dataframe_feature_importance20['feature_name']))
 plt.xticks(x, dataframe_feature_importance20['feature_name'], rotation=90, fontsize=8)
 plt.plot(x, dataframe_feature_importance20['importance'])
 plt.xlabel("Feature name")
 plt.ylabel("Importance")
 plt.title("The importance of features")
 plt.show()
 return np.array(dataframe_feature_importance20['feature_name'])

plot_feature_importance(x_train,estimator)

参考文献

LGB的实现

用Sklearn接口形式使用lightgbm,并使用Gridsearchcv对lightgbm调参:网格搜索和交叉验证

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342