🏆🏆🏆教程全知识点简介:1.定位、目标。2. K-近邻算法涵盖距离度量、k值选择、kd树、鸢尾花种类预测数据集介绍、练一练、交叉验证网格搜索、facebook签到位置预测案例。3. 线性回归包括线性回归简介、线性回归损失和优化、梯度下降法介绍、波士顿房价预测案例、欠拟合和过拟合、正则化线性模型、正规方程推导方式、梯度下降法算法比较优化、维灾难。4. 逻辑回归涵盖逻辑回归介绍、癌症分类预测案例(良恶性乳腺癌肿瘤预测、获取数据)、ROC曲线绘制。5. 朴素贝叶斯算法包括朴素贝叶斯算法简介、概率基础复习、产品评论情感分析案例(取出内容列数据分析、判定评判标准好评差评)。6. 支持向量机涵盖SVM算法原理、SVM损失函数、数字识别器案例。7. 决策树算法包括决策树分类原理、cart剪枝、特征工程特征提取、决策树算法api、泰坦尼克号乘客生存预测案例。8. EM算法涵盖初识EM算法、EM算法介绍。9. HMM模型包括马尔科夫链、HMM简介、前向后向算法评估观察序列概率、维特比算法解码隐藏状态序列、HMM模型API介绍。10. 集成学习进阶涵盖Bagging、xgboost算法原理、otto案例(Otto Group Product Classification Challenge xgboost实现)、数据变化可视化、lightGBM、stacking算法基本思想、住房月租金预测。11. 聚类算法包括聚类算法api初步使用、聚类算法实现流程、模型评估、算法优化、特征降维、用户对物品类别喜好细分案例、算法选择指导。12. 数学基础涵盖向量与矩阵范数、朗格朗日乘子法、Huber Loss、极大似然函数取对数原因。


📚📚仓库code.zip 👉直接-->:   https://gitlab.com/yinuo_112/AI/-/blob/main/机器学习/嘿马机器学习(算法篇)/note.md    🍅🍅

✨ 本教程项目亮点

🧠 知识体系完整:覆盖从基础原理、核心方法到高阶应用的全流程内容
💻 全技术链覆盖:完整前后端技术栈,涵盖开发必备技能
🚀 从零到实战:适合 0 基础入门到提升,循序渐进掌握核心能力
📚 丰富文档与代码示例:涵盖多种场景,可运行、可复用
🛠 工作与学习双参考:不仅适合系统化学习,更可作为日常开发中的查阅手册
🧩 模块化知识结构:按知识点分章节,便于快速定位和复习
📈 长期可用的技术积累:不止一次学习,而是能伴随工作与项目长期参考


🎯🎯🎯全教程总章节


🚀🚀🚀本篇主要内容

集成学习进阶

学习目标

  • 知道xgboost算法原理
  • 知道otto案例通过xgboost实现流程
  • 知道lightGBM算法原理
  • 知道PUBG案例通过lightGBM实现流程
  • 知道stacking算法原理
  • 知道住房月租金预测通过stacking实现流程

5.4 otto案例介绍 -- Otto Group Product Classification Challenge【xgboost实现】

1 背景介绍

奥托集团是世界上最大的电子商务公司之一,在20多个国家设有子公司。该公司每天都在世界各地销售数百万种产品,所以对其产品根据性能合理的分类非常重要。

不过,在实际工作中,工作人员发现,许多相同的产品得到了不同的分类。本案例要求,你对奥拓集团的产品进行正确的分分类。尽可能的提供分类的准确性。

链接:https://www.kaggle.com/c/otto-group-product-classification-challenge/overview

2nd iteration


2 思路分析

  • 1.数据获取

  • 2.数据基本处理

  • 2.1 截取部分数据

  • 2.2 把标签纸转换为数字
  • 2.3 分割数据(使用StratifiedShuffleSplit)
  • 2.4 数据标准化
  • 2.5 数据pca降维

  • 3.模型训练

  • 3.1 基本模型训练

  • 3.2 模型调优

    • 3.2.1 调优参数:

      • n_estimator,
      • max_depth,
      • min_child_weights,
      • subsamples,
      • consample_bytrees,
      • etas
    • 3.2.2 确定最后最优参数

3 部分代码实现

  • 2.数据基本处理

  • 2.1 截取部分数据

  • 2.2 把标签纸转换为数字

  • 2.3 分割数据(使用StratifiedShuffleSplit)

# 使用StratifiedShuffleSplit对数据集进行分割


   from sklearn.model_selection import StratifiedShuffleSplit

   sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)
   for train_index, test_index in sss.split(X_resampled.values, y_resampled):
       print(len(train_index))
       print(len(test_index))

       x_train = X_resampled.values[train_index]
       x_val = X_resampled.values[test_index]

       y_train = y_resampled[train_index]
       y_val = y_resampled[test_index]
# 分割数据图形可视化


   import seaborn as sns

   sns.countplot(y_val)

   plt.show()
  • 2.4 数据标准化
from sklearn.preprocessing import StandardScaler

   scaler = StandardScaler()
   scaler.fit(x_train)

   x_train_scaled = scaler.transform(x_train)
   x_val_scaled = scaler.transform(x_val)
  • 2.5 数据pca降维
print(x_train_scaled.shape)
   # (13888, 93)

   from sklearn.decomposition import PCA

   pca = PCA(n_components=0.9)
   x_train_pca = pca.fit_transform(x_train_scaled)
   x_val_pca = pca.transform(x_val_scaled)

   print(x_train_pca.shape, x_val_pca.shape)
   (13888, 65) (3473, 65)

从上面输出的数据可以看出,只选择65个元素,就可以表达出特征中90%的信息

# 降维数据可视化


   plt.plot(np.cumsum(pca.explained_variance_ratio_))

   plt.xlabel("元素数量")
   plt.ylabel("可表达信息的百分占比")

   plt.show()

image-20200211092529327

  • 3.模型训练

  • 3.1 基本模型训练

from xgboost import XGBClassifier

   xgb = XGBClassifier()
   xgb.fit(x_train_pca, y_train)

   # 改变预测值的输出模式,让输出结果为百分占比,降低logloss值
   y_pre_proba = xgb.predict_proba(x_val_pca)
# logloss进行模型评估


   from sklearn.metrics import log_loss
   log_loss(y_val, y_pre_proba, eps=1e-15, normalize=True)

   xgb.get_params
  • 3.2 模型调优

  • 3.2.1 调优参数:

    • n_estimator,
scores_ne = []
      n_estimators = [100,200,400,450,500,550,600,700]

      for nes in n_estimators:
          print("n_estimators:", nes)
          xgb = XGBClassifier(max_depth=3, 
                              learning_rate=0.1, 
                              n_estimators=nes, 
                              objective="multi:softprob", 
                              n_jobs=-1, 
                              nthread=4, 
                              min_child_weight=1, 
                              subsample=1, 
                              colsample_bytree=1,
                              seed=42)

          xgb.fit(x_train_pca, y_train)
          y_pre = xgb.predict_proba(x_val_pca)
          score = log_loss(y_val, y_pre)
          scores_ne.append(score)
          print("测试数据的logloss值为:{}".format(score))
# 数据变化可视化


      plt.plot(n_estimators, scores_ne, "o-")

      plt.ylabel("log_loss")
      plt.xlabel("n_estimators")
      print("n_estimators的最优值为:{}".format(n_estimators[np.argmin(scores_ne)]))
  ![image-20200211092901936]()

  * **max_depth,**
scores_md = []
      max_depths = [1,3,5,6,7]

      for md in max_depths:  # 修改
          xgb = XGBClassifier(max_depth=md, # 修改
                              learning_rate=0.1, 
                              n_estimators=n_estimators[np.argmin(scores_ne)],   # 修改 
                              objective="multi:softprob", 
                              n_jobs=-1, 
                              nthread=4, 
                              min_child_weight=1, 
                              subsample=1, 
                              colsample_bytree=1,
                              seed=42)

          xgb.fit(x_train_pca, y_train)
          y_pre = xgb.predict_proba(x_val_pca)
          score = log_loss(y_val, y_pre)
          scores_md.append(score)  # 修改
          print("测试数据的logloss值为:{}".format(log_loss(y_val, y_pre)))
# 数据变化可视化


      plt.plot(max_depths, scores_md, "o-")  # 修改

      plt.ylabel("log_loss")
      plt.xlabel("max_depths")  # 修改
      print("max_depths的最优值为:{}".format(max_depths[np.argmin(scores_md)]))  # 修改
  * **min_child_weights,**

     * 依据上面模式进行调整

  * **subsamples,**

  * **consample_bytrees,**

  * **etas**
  • 3.2.2 确定最后最优参数
xgb = XGBClassifier(learning_rate =0.1, 
                       n_estimators=550, 
                       max_depth=3, 
                       min_child_weight=3, 
                       subsample=0.7, 
                       colsample_bytree=0.7, 
                       nthread=4, 
                       seed=42, 
                       objective='multi:softprob')
   xgb.fit(x_train_scaled, y_train)

   y_pre = xgb.predict_proba(x_val_scaled)

   print("测试数据的logloss值为 : {}".format(log_loss(y_val, y_pre, eps=1e-15, normalize=True)))

集成学习进阶

学习目标

  • 知道xgboost算法原理
  • 知道otto案例通过xgboost实现流程
  • 知道lightGBM算法原理
  • 知道PUBG案例通过lightGBM实现流程
  • 知道stacking算法原理
  • 知道住房月租金预测通过stacking实现流程

5.5 lightGBM

学习目标

  • 了解lightGBM演进过程
  • 知道什么是lightGBM
  • 知道lightGBM原理

1 写在介绍lightGBM之前

1.1 lightGBM演进过程

image-20191202130509524

1.2 AdaBoost算法

AdaBoost是一种提升树的方法,和三个臭皮匠,赛过诸葛亮的道理一样。

AdaBoost两个问题:

  • (1) 如何改变训练数据的权重或概率分布

  • 提高前一轮被弱分类器错误分类的样本的权重,降低前一轮被分对的权重

  • (2) 如何将弱分类器组合成一个强分类器,亦即,每个分类器,前面的权重如何设置

  • 采取”多数表决”的方法.加大分类错误率小的弱分类器的权重,使其作用较大,而减小分类错误率大的弱分类器的权重,使其在表决中起较小的作用。

1.3 GBDT算法以及优缺点

GBDT和AdaBosst很类似,但是又有所不同。

  • GBDT和其它Boosting算法一样,通过将表现一般的几个模型(通常是深度固定的决策树)组合在一起来集成一个表现较好的模型。

  • AdaBoost是通过提升错分数据点的权重来定位模型的不足, Gradient Boosting通过负梯度来识别问题,通过计算负梯度来改进模型,即通过反复地选择一个指向负梯度方向的函数,该算法可被看做在函数空间里对目标函数进行优化。

因此可以说 。

  • GradientBoosting=GradientDescent+BoostingGradientBoosting=GradientDescent+BoostingGradientBoosting=GradientDescent+Boosting

缺点:

GBDT ->预排序方法(pre-sorted)

  • (1) 空间消耗大

  • 这样的算法需要保存数据的特征值,还保存了特征排序的结果(例如排序后的索引,为了后续快速的计算分割点),这里需要消耗训练数据两倍的内存

  • (2) 时间上也有较大的开销。

  • 在遍历每一个分割点的时候,都需要进行分裂增益的计算,消耗的代价大。

  • (3) 对内存(cache)优化不友好。

  • 在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。
  • 同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。

1.4 启发

常用的机器学习算法,例如神经网络等算法,都可以以mini-batch的方式训练,训练数据的大小不会受到内存限制。

而GBDT在每一次迭代的时候,都需要遍历整个训练数据多次。

如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。

尤其面对工业级海量的数据,普通的GBDT算法是不能满足其需求的。

LightGBM提出的主要原因就是为了解决GBDT在海量数据遇到的问题,让GBDT可以更好更快地用于工业实践。

2 什么是lightGBM

lightGBM是2017年1月,微软在GItHub上开源的一个新的梯度提升框架。

github介绍链接

在开源之后,就被别人冠以“速度惊人”、“支持分布式”、“代码清晰易懂”、“占用内存小”等属性。

LightGBM主打的高效并行训练让其性能超越现有其他boosting工具。在Higgs数据集上的试验表明,LightGBM比XGBoost快将近10倍,内存占用率大约为XGBoost的1/6。

higgs数据集介绍:这是一个分类问题,用于区分产生希格斯玻色子的信号过程和不产生希格斯玻色子的信号过程。

数据链接

3 lightGBM原理

lightGBM 主要基于以下方面优化,提升整体特特性:

  1. 基于Histogram(直方图)的决策树算法
  2. Lightgbm 的Histogram(直方图)做差加速
  3. 带深度限制的Leaf-wise的叶子生长策略
  4. 直接支持类别特征
  5. 直接支持高效并行

具体解释见下,分节介绍。


3.1 基于Histogram(直方图)的决策树算法

直方图算法的基本思想是

  • 先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。
  • 在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。

    Eg:

[0, 0.1) --> 0;

[0.1,0.3) --> 1;

...

image-20191129114925562

使用直方图算法有很多优点。首先,最明显就是内存消耗的降低,直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用8位整型存储就足够了,内存消耗可以降低为原来的1/8。

image-20191129115042904

然后在计算上的代价也大幅降低,预排序算法每遍历一个特征值就需要计算一次分裂的增益,而直方图算法只需要计算k次(k可以认为是常数),时间复杂度从O(#data#feature)优化到O(k#features)。

当然,Histogram算法并不是完美的。由于特征被离散化后,找到的并不是很精确的分割点,所以会对结果产生影响。但在不同的数据集上的结果表明,离散化的分割点对最终的精度影响并不是很大,甚至有时候会更好一点。原因是决策树本来就是弱模型,分割点是不是精确并不是太重要;较粗的分割点也有正则化的效果,可以有效地防止过拟合;即使单棵树的训练误差比精确分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下没有太大的影响。

3.2 Lightgbm 的Histogram(直方图)做差加速

一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。

通常构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。

利用这个方法,LightGBM可以在构造一个叶子的直方图后,可以用非常微小的代价得到它兄弟叶子的直方图,在速度上可以提升一倍。

image-20191129115130409

3.3 带深度限制的Leaf-wise的叶子生长策略

Level-wise便利一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。

  • 但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。

image-20191129114209679

Leaf-wise则是一种更为高效的策略,每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。

  • 因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。
  • Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。

image-20191129114318484

3.4 直接支持类别特征

实际上大多数机器学习工具都无法直接支持类别特征,一般需要把类别特征,转化到多维的0/1特征,降低了空间和时间的效率。

而类别特征的使用是在实践中很常用的。基于这个考虑,LightGBM优化了对类别特征的支持,可以直接输入类别特征,不需要额外的0/1展开。并在决策树算法上增加了类别特征的决策规则。

在Expo数据集上的实验,相比0/1展开的方法,训练速度可以加速8倍,并且精度一致。目前来看,LightGBM是第一个直接支持类别特征的GBDT工具。

Expo数据集介绍:数据包含1987年10月至2008年4月美国境内所有产品航班的航班到达和离开的详细信息。这是一个庞大的数据集:总共有近1.2亿条记录。主要用于预测航班是否准时。

数据链接

3.5 直接支持高效并行

LightGBM还具有支持高效并行的优点。LightGBM原生支持并行学习,目前支持特征并行和数据并行的两种。

  • 特征并行的主要思想是在不同机器在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点。
  • 数据并行则是让不同的机器先在本地构造直方图,然后进行全局的合并,最后在合并的直方图上面寻找最优分割点。

LightGBM针对这两种并行方法都做了优化:

  • 特征并行算法中,通过在本地保存全部数据避免对数据切分结果的通信;

image-20191129115433096

  • 数据并行中使用分散规约 (Reduce scatter) 把直方图合并的任务分摊到不同的机器,降低通信和计算,并利用直方图做差,进一步减少了一半的通信量。

image-20191129115550512

  • 基于投票的数据并行(Voting Parallelization)则进一步优化数据并行中的通信代价,使通信代价变成常数级别。在数据量很大的时候,使用投票并行可以得到非常好的加速效果。

image-20191129115637083


4 小结

  • lightGBM 演进过程

image-20191202130509524

  • lightGBM优势

  • 基于Histogram(直方图)的决策树算法

  • Lightgbm 的Histogram(直方图)做差加速
  • 带深度限制的Leaf-wise的叶子生长策略
  • 直接支持类别特征
  • 直接支持高效并行

🚀✨ (未完待续)项目系列下一章

📚下一篇 将进入更精彩的环节! 🔔 记得收藏 & 关注,第一时间获取更新! 🍅 一起见证整个系列逐步成型的全过程。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐