前言

GBDT和Xgboost都是常用的树模型,也是常见的boosting方法的代表。尤其是Xgboost,更是被誉为kaggle神器。

本篇博客将从加法模型角度,对GBDT和XgBoost的数学原理进行推导。二者都是加法模型,非常相似,同时又因为用泰勒展开拟合残差的阶数,进而有所区别。

加法模型

给定数据集T={(x1,y1),(x2,y2),...,(xN,yN)}T=\{(x_1, y_1), (x_2, y_2), ..., (x_N, y_N)\}T={(x1​,y1​),(x2​,y2​),...,(xN​,yN​)},其中,xi∈Rnx_i\in\mathbb{R}^nxi​∈Rn,yiy_iyi​为标签。

我们想要得到一个模型 y^=F(x)\hat y=F(x)y^​=F(x),来拟合数据集TTT。

boosting的思想是,先随便选择一个分类器,然后在这个分类器基础上,再选择一个分类器,使得这两个分类器合起来,能表现得比其中任何一个分类器要好。然后继续添加分类器,直到最后满足终止条件。

加法模型指的是,这个boosting过程中,不同分类器合起来的方式,我们用加法。

具体过程如下,

  • 初始分类器:f0(x)=0f_0(x)=0f0​(x)=0(这里意思是,我们任意选择其中一种标签作为结果),毫无疑问,这种分类器分类效果很差
  • 我们选择下一个分类器h1(x)h_1(x)h1​(x),使得f0(x)+h1(x)f_0(x)+h_1(x)f0​(x)+h1​(x)能够更好地分类,具体来说,h1(x)=arg min⁡h∑i=1NLoss(yi,f0(xi)+h(xi))h_1(x)=\argmin\limits_{h}\sum_{i=1}^NLoss(y_i, f_0(x_i)+h(x_i))h1​(x)=hargmin​i=1∑N​Loss(yi​,f0​(xi​)+h(xi​))
    这时,我们产生了一个新的分类器 f1(x)=f0(x)+h1(x)f_1(x)=f_0(x)+h_1(x)f1​(x)=f0​(x)+h1​(x)
    实际上,我们往往把h1(x)h_1(x)h1​(x)叫做残差。为什么这么叫,因为它衡量了新分类器f1(x)f_1(x)f1​(x)和旧分类器f0(x)f_0(x)f0​(x)之间的差别。
  • 接下来,我们继续选择下一个残差h2(x)h_2(x)h2​(x),类似的,
    h2(x)=arg min⁡h∑i=1NLoss(yi,f1(xi)+h(xi))h_2(x)=\argmin\limits_{h}\sum_{i=1}^NLoss(y_i, f_1(x_i)+h(x_i))h2​(x)=hargmin​i=1∑N​Loss(yi​,f1​(xi​)+h(xi​))
    这样,我们又产生了一个更好的分类器f2(x)=f1(x)+h2(x)f_2(x)=f_1(x)+h_2(x)f2​(x)=f1​(x)+h2​(x)
  • 类似于上面的过程不停做下去,我们选择第kkk个残差hk(x)h_k(x)hk​(x),
    hk(x)=arg min⁡h∑i=1NLoss(yi,fk−1(xi)+h(xi))h_k(x)=\argmin\limits_{h}\sum_{i=1}^NLoss(y_i, f_{k-1}(x_i)+h(x_i))hk​(x)=hargmin​i=1∑N​Loss(yi​,fk−1​(xi​)+h(xi​))
    产生的分类器fk(x)=fk−1(x)+hk(x)f_k(x)=f_{k-1}(x)+h_k(x)fk​(x)=fk−1​(x)+hk​(x)

从上面的加法模型的过程可以看出,实际需要计算的是在每一次迭代的时候,如何选择残差hk(x)h_k(x)hk​(x)。

残差hk(x)h_k(x)hk​(x)是根据下式得到的
hk(x)=arg min⁡h∑i=1NLoss(yi,fk−1(xi)+h(xi))h_k(x)=\argmin\limits_{h}\sum_{i=1}^NLoss(y_i, f_{k-1}(x_i)+h(x_i))hk​(x)=hargmin​i=1∑N​Loss(yi​,fk−1​(xi​)+h(xi​))

为了得到这个优化问题的解,

  • 我们只需要确保对于每一组数据(xi,yi)∈T(x_i, y_i)\in T(xi​,yi​)∈T,都能选择h(xi)h(x_i)h(xi​)使得Loss(yi,fk−1(xi)+h(xi))Loss(y_i, f_{k-1}(x_i)+h(x_i))Loss(yi​,fk−1​(xi​)+h(xi​))最小
  • 我们对形如Loss(y,fk−1(x)+h(x))Loss(y, f_{k-1}(x)+h(x))Loss(y,fk−1​(x)+h(x))的损失函数进行泰勒展开,即一阶展开 Loss(y,fk−1(x)+h(x))≈Loss(y,fk−1(x))+∂Loss(y,fk−1(x))∂fk−1(x)⋅h(x)Loss(y, f_{k-1}(x)+h(x))\approx Loss(y, f_{k-1}(x))+\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}\cdot h(x)Loss(y,fk−1​(x)+h(x))≈Loss(y,fk−1​(x))+∂fk−1​(x)∂Loss(y,fk−1​(x))​⋅h(x) 或者二阶展开 Loss(y,fk−1(x)+h(x))≈Loss(y,fk−1(x))+∂Loss(y,fk−1(x))∂fk−1(x)⋅h(x)+12∂2Loss(y,fk−1(x))∂(fk−1(x))2⋅h(x)2Loss(y, f_{k-1}(x)+h(x))\approx Loss(y, f_{k-1}(x))+\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}\cdot h(x)+\frac{1}{2}\frac{\partial^2 Loss(y, f_{k-1}(x))}{\partial (f_{k-1}(x))^2}\cdot h(x)^2Loss(y,fk−1​(x)+h(x))≈Loss(y,fk−1​(x))+∂fk−1​(x)∂Loss(y,fk−1​(x))​⋅h(x)+21​∂(fk−1​(x))2∂2Loss(y,fk−1​(x))​⋅h(x)2
  • 一阶展开可以导出GBDT,二阶展开则导出XgBoost

GBDT

如果对损失函数Loss(y,fk−1(x)+h(x))Loss(y, f_{k-1}(x)+h(x))Loss(y,fk−1​(x)+h(x))进行一阶展开,我们有
Loss(y,fk−1(x)+h(x))≈Loss(y,fk−1(x))+∂Loss(y,fk−1(x))∂fk−1(x)⋅h(x)Loss(y, f_{k-1}(x)+h(x))\approx Loss(y, f_{k-1}(x))+\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}\cdot h(x)Loss(y,fk−1​(x)+h(x))≈Loss(y,fk−1​(x))+∂fk−1​(x)∂Loss(y,fk−1​(x))​⋅h(x)

注意到,当令h(x)=−∂Loss(y,fk−1(x))∂fk−1(x)h(x)=-\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}h(x)=−∂fk−1​(x)∂Loss(y,fk−1​(x))​时,
Loss(y,fk−1(x))+∂Loss(y,fk−1(x))∂fk−1(x)⋅h(x)=Loss(y,fk−1(x))−(∂Loss(y,fk−1(x))∂fk−1(x))2≤Loss(y,fk−1(x))\begin{array}{lll} &&Loss(y, f_{k-1}(x))+\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}\cdot h(x)\\ &=&Loss(y, f_{k-1}(x))-\left(\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}\right)^2\\ &\le&Loss(y, f_{k-1}(x)) \end{array} ​=≤​Loss(y,fk−1​(x))+∂fk−1​(x)∂Loss(y,fk−1​(x))​⋅h(x)Loss(y,fk−1​(x))−(∂fk−1​(x)∂Loss(y,fk−1​(x))​)2Loss(y,fk−1​(x))​

这就意味着当h(x)=−∂Loss(y,fk−1(x))∂fk−1(x)h(x)=-\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}h(x)=−∂fk−1​(x)∂Loss(y,fk−1​(x))​时,Loss(y,fk−1(x)+h(x))≤Loss(y,fk−1(x))Loss(y, f_{k-1}(x)+h(x))\le Loss(y, f_{k-1}(x))Loss(y,fk−1​(x)+h(x))≤Loss(y,fk−1​(x))

即损失函数变小了!这正是我们想要的!每次迭代我们始终取h(x)=−∂Loss(y,fk−1(x))∂fk−1(x)h(x)=-\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}h(x)=−∂fk−1​(x)∂Loss(y,fk−1​(x))​,我们就能确保损失函数是一直减小的!

GBDT是一系列CART树的加起来的结果,这也就意味着hk(x)h_k(x)hk​(x)实际上也是一棵CART树。我们现在知道,对于任意的xi∈Tx_i\in Txi​∈T,hk(xi)=−∂Loss(yi,fk−1(x))∂fk−1(x)∣fk−1(x)=fk−1(xi)h_k(x_i)=-\frac{\partial Loss(y_i, f_{k-1}(x))}{\partial f_{k-1}(x)}|_{f_{k-1}(x)=f_{k-1}(x_i)}hk​(xi​)=−∂fk−1​(x)∂Loss(yi​,fk−1​(x))​∣fk−1​(x)=fk−1​(xi​)​,i=1,2,...,Ni=1, 2, ..., Ni=1,2,...,N。根据这样的数据集Tk=(x1,hk(x1)),(x2,hk(x2)),...,(xN,hk(xN))T_k={(x_1, h_k(x_1)), (x_2, h_k(x_2)), ..., (x_N, h_k(x_N))}Tk​=(x1​,hk​(x1​)),(x2​,hk​(x2​)),...,(xN​,hk​(xN​)),我们是可以生成CART树的。

Xgboost

如果对损失函数Loss(y,fk−1(x)+h(x))Loss(y, f_{k-1}(x)+h(x))Loss(y,fk−1​(x)+h(x))进行一阶展开,我们有
Loss(y,fk−1(x)+h(x))≈Loss(y,fk−1(x))+∂Loss(y,fk−1(x))∂fk−1(x)⋅h(x)+12∂2Loss(y,fk−1(x))∂(fk−1(x))2⋅h(x)2Loss(y, f_{k-1}(x)+h(x))\approx Loss(y, f_{k-1}(x))+\frac{\partial Loss(y, f_{k-1}(x))}{\partial f_{k-1}(x)}\cdot h(x)+\frac{1}{2}\frac{\partial^2 Loss(y, f_{k-1}(x))}{\partial (f_{k-1}(x))^2}\cdot h(x)^2Loss(y,fk−1​(x)+h(x))≈Loss(y,fk−1​(x))+∂fk−1​(x)∂Loss(y,fk−1​(x))​⋅h(x)+21​∂(fk−1​(x))2∂2Loss(y,fk−1​(x))​⋅h(x)2

这也就意味着总体损失函数为x
min⁡h(x)∑i=1NLoss(yi,fk−1(xi)+h(xi))=∑i=1N(Loss(yi,fk−1(xi))+∂Loss(yi,fk−1(x))∂fk−1(x)∣fk−1(xi)⋅h(xi)+12∂2Loss(yi,fk−1(x))∂(fk−1(x))2∣fk−1(xi)⋅h(xi)2)=∑i=1N(Loss(yi,fk−1(xi))+g(xi,yi)⋅h(xi)+12u(xi,yi)⋅h(xi)2)\begin{array}{lll} &\min\limits_{h(x)}&\sum_{i=1}^NLoss(y_i, f_{k-1}(x_i)+h(x_i))\\ &=&\sum_{i=1}^N \left(Loss(y_i, f_{k-1}(x_i))+\frac{\partial Loss(y_i, f_{k-1}(x))}{\partial f_{k-1}(x)}|_{f_{k-1}(x_i)}\cdot h(x_i)+\frac{1}{2}\frac{\partial^2 Loss(y_i, f_{k-1}(x))}{\partial (f_{k-1}(x))^2}|_{f_{k-1}(x_i)}\cdot h(x_i)^2\right)\\ &=& \sum_{i=1}^N(Loss(y_i, f_{k-1}(x_i))+g(x_i, y_i)\cdot h(x_i)+\frac{1}{2}u(x_i, y_i)\cdot h(x_i)^2) \end{array} ​h(x)min​==​∑i=1N​Loss(yi​,fk−1​(xi​)+h(xi​))∑i=1N​(Loss(yi​,fk−1​(xi​))+∂fk−1​(x)∂Loss(yi​,fk−1​(x))​∣fk−1​(xi​)​⋅h(xi​)+21​∂(fk−1​(x))2∂2Loss(yi​,fk−1​(x))​∣fk−1​(xi​)​⋅h(xi​)2)∑i=1N​(Loss(yi​,fk−1​(xi​))+g(xi​,yi​)⋅h(xi​)+21​u(xi​,yi​)⋅h(xi​)2)​

其中,g(xi,yi)=∂Loss(yi,fk−1(x))∂fk−1(x)∣fk−1(xi)g(x_i, y_i)=\frac{\partial Loss(y_i, f_{k-1}(x))}{\partial f_{k-1}(x)}|_{f_{k-1}(x_i)}g(xi​,yi​)=∂fk−1​(x)∂Loss(yi​,fk−1​(x))​∣fk−1​(xi​)​,u(xi,yi)=∂2Loss(yi,fk−1(x))∂(fk−1(x))2∣fk−1(xi)u(x_i, y_i)=\frac{\partial^2 Loss(y_i, f_{k-1}(x))}{\partial (f_{k-1}(x))^2}|_{f_{k-1}(x_i)}u(xi​,yi​)=∂(fk−1​(x))2∂2Loss(yi​,fk−1​(x))​∣fk−1​(xi​)​。

我们说xgboost也是一系列树的加法,因此,这里的h(x)h(x)h(x)实际上也是一棵树,这棵树使得总体损失∑i=1NLoss(yi,fk−1(xi)+h(xi))\sum_{i=1}^NLoss(y_i, f_{k-1}(x_i)+h(x_i))∑i=1N​Loss(yi​,fk−1​(xi​)+h(xi​))最小。

更近一步的,我们还要考虑树h(x)h(x)h(x)的复杂度,我们不希望树叶节点过多,因此,我们将树的复杂度计入损失函数里面,损失函数变成为
∑i=1N(Loss(yi,fk−1(xi))+g(xi,yi)⋅h(xi)+12u(xi,yi)⋅h(xi)2)+γ∣leafs∣+12λ∑l∈leafswl2\begin{array}{lll} && \sum_{i=1}^N(Loss(y_i, f_{k-1}(x_i))+g(x_i, y_i)\cdot h(x_i)+\frac{1}{2}u(x_i, y_i)\cdot h(x_i)^2)\\ &+&\gamma|leafs|+\frac{1}{2}\lambda\sum_{l\in leafs}w_l^2 \end{array} ​+​∑i=1N​(Loss(yi​,fk−1​(xi​))+g(xi​,yi​)⋅h(xi​)+21​u(xi​,yi​)⋅h(xi​)2)γ∣leafs∣+21​λ∑l∈leafs​wl2​​

其中,leafsleafsleafs为树h(x)h(x)h(x)的叶节点集合,wlw_lwl​为叶节点lll处的权重或者值。

注意到,我们是对树h(x)h(x)h(x)做优化,而Loss(yi,fk−1(xi))Loss(y_i, f_{k-1}(x_i))Loss(yi​,fk−1​(xi​))与树h(x)h(x)h(x)无关,因此,可以从上面的目标函数中去掉,这样,我们的目标函数可以写为
∑i=1N(g(xi,yi)⋅h(xi)+12u(xi,yi)⋅h(xi)2)+γ∣leafs∣+12λ∑l∈leafswl2\begin{array}{lll} && \sum_{i=1}^N(g(x_i, y_i)\cdot h(x_i)+\frac{1}{2}u(x_i, y_i)\cdot h(x_i)^2)\\ &+&\gamma|leafs|+\frac{1}{2}\lambda\sum_{l\in leafs}w_l^2 \end{array} ​+​∑i=1N​(g(xi​,yi​)⋅h(xi​)+21​u(xi​,yi​)⋅h(xi​)2)γ∣leafs∣+21​λ∑l∈leafs​wl2​​

这里h(xi)h(x_i)h(xi​)意味着xix_ixi​最终总会沿着树的路径落到某一叶节点q(xi)q(x_i)q(xi​)中,取得值wq(xi)w_{q(x_i)}wq(xi​)​。这样,可以重写目标函数为
∑i=1N(g(xi,yi)⋅h(xi)+12u(xi,yi)⋅h(xi)2)+γ∣leafs∣+12λ∑l∈leafswl2=∑i=1N(g(xi,yi)⋅wq(xi)+12u(xi,yi)⋅wq(xi)2)+γ∣leafs∣+12λ∑l∈leafswl2=∑l∈leafs(wl∑q(xi)=lg(xi)+12wl2∑q(xi)=lu(xi))+12λ∑l∈leafswl2+γ∣leafs∣=∑l∈leafs(Glwl+12Ulwl2)+12λ∑l∈leafswl2+γ∣leafs∣=∑l∈leafs(12(λ+Ul)wl2+Glwl)+γ∣leafs∣\begin{array}{lll} && \sum_{i=1}^N(g(x_i, y_i)\cdot h(x_i)+\frac{1}{2}u(x_i, y_i)\cdot h(x_i)^2)+\gamma|leafs|+\frac{1}{2}\lambda\sum_{l\in leafs}w_l^2\\ &=&\sum_{i=1}^N(g(x_i, y_i)\cdot w_{q(x_i)}+\frac{1}{2}u(x_i, y_i)\cdot w_{q(x_i)}^2)+\gamma|leafs|+\frac{1}{2}\lambda\sum_{l\in leafs}w_l^2\\ &=&\sum_{l\in leafs}\left(w_l\sum_{q(x_i)=l}g(x_i)+\frac{1}{2}w_l^2\sum_{q(x_i)=l}u(x_i) \right)+\frac{1}{2}\lambda\sum_{l\in leafs}w_l^2+\gamma|leafs|\\ &=&\sum_{l\in leafs}\left(G_lw_l+\frac{1}{2}U_lw_l^2 \right)+\frac{1}{2}\lambda\sum_{l\in leafs}w_l^2+\gamma|leafs|\\ &=&\sum_{l\in leafs}\left(\frac{1}{2}(\lambda+U_l)w_l^2+G_lw_l\right)+\gamma|leafs| \end{array} ​====​∑i=1N​(g(xi​,yi​)⋅h(xi​)+21​u(xi​,yi​)⋅h(xi​)2)+γ∣leafs∣+21​λ∑l∈leafs​wl2​∑i=1N​(g(xi​,yi​)⋅wq(xi​)​+21​u(xi​,yi​)⋅wq(xi​)2​)+γ∣leafs∣+21​λ∑l∈leafs​wl2​∑l∈leafs​(wl​∑q(xi​)=l​g(xi​)+21​wl2​∑q(xi​)=l​u(xi​))+21​λ∑l∈leafs​wl2​+γ∣leafs∣∑l∈leafs​(Gl​wl​+21​Ul​wl2​)+21​λ∑l∈leafs​wl2​+γ∣leafs∣∑l∈leafs​(21​(λ+Ul​)wl2​+Gl​wl​)+γ∣leafs∣​

求上式关于wlw_lwl​的最小值,有
wl=−Glλ+Ulw_l=-\frac{G_l}{\lambda+U_l}wl​=−λ+Ul​Gl​​

代回上式中,目标函数可以重写为
−∑l∈leafsGl22(λ+Ul)+γ∣leafs∣-\sum_{l\in leafs}\frac{G_l^2}{2(\lambda+U_l)}+\gamma|leafs|−l∈leafs∑​2(λ+Ul​)Gl2​​+γ∣leafs∣

类似于GBDT中,CART树根据基尼系数来生成树,这里,xgboost就是根据上式来判断是否切割叶节点,是否剪枝等问题生成树。

总结

GBDT和Xgboost都是树的加法模型,两者都是通过对残差的拟合来生成树;但不同的是,GBDT通过泰勒一阶展开来拟合残差,而xgboost是通过泰勒二阶展开来拟合残差,并根据自己的准则来生成树。

《推荐系统笔记(八)》GBDT和XgBoost的原理(内含详细数学推导)相关推荐

  1. 《推荐系统笔记(九))》DNN的BP算法(内含详细数学推导)

    前言 推荐系统中,我们通常用深度神经网络(DNN)来学习高阶(非线性)特征.这篇博客中,我们将详细介绍DNN的BP算法. 如果觉得此文过长或者写得不容易懂的,可以看看B站上的一个视频讲解(链接),内容 ...

  2. GBDT和Xgboost:原理、推导、比较

    写在前面 网上有很多关于GBDT和Xgboost的文章,但是我在读的时候感觉对于提升树.GBDT和Xgboost之间的关系,以及他们和残差.梯度的关系,所以自己整理了一下,涉及的知识点比较多.Xgbo ...

  3. 【机器学习】XgBoost 原理详解 数学推导

    XgBoost   (Xtreme Gradient Boosting 极限 梯度 增强) 1.基本描述:             假设Xg-模型有 t 颗决策树数,t棵树有序串联构成整个模型,各决策 ...

  4. iToF深度估计原理-带简单数学推导(持续更新)

    文章目录 什么是iToF? 为什么有相位差,就可以测距? 测距原理 正弦调制:4-sampling-bucket 算法(带推导) 脉冲调制 距离--->深度 iToF的标定问题 双频调制是什么? ...

  5. OpenGL之矩阵变换的原理分析与数学推导

    什么是矩阵变换? 这张图比较直观地展示了OpenGL矩阵变换的过程,下面详解一下其中的含义: 首先OpenGL有个世界坐标系,我们渲染的物体就是在世界坐标系中,模型需要放到世界坐标系中,那么当还没放的 ...

  6. 《推荐系统学习(二)》PCA降维方法的数学推导

    前言 PCA降维方法将一组数据看成是一个随机变量生成的,通过将这个随机变量投影到待找的基向量上,这个投影后得到的一维随机向量方差最大.这个待找的基向量方向上,能够将投影后的数据最大程度区分开来. 推导 ...

  7. 生成对抗网络——原理解释和数学推导

    首先我们有两个关键组件:生成器(G)和判别器(D),一开始我们的G-V1生成了一些手写体的图片,然后丢给D-V1,同时我们也需要把真实图片也送给D-V1,然后D-V1根据自己的"经验&quo ...

  8. 『矩阵论笔记』张量CP分解的详细数学推导以及Python实现

    张量CP分解的详细数学推导以及Python实现! 文章目录 一. 张量的基本概念 1.1 张量定义以及张量空间 1.2 阶和纤维(fiber)及切片 1.3 内积和范数及秩一张量/可合张量 1.4 超 ...

  9. ZooKeeper学习笔记(八):ZooKeeper集群写数据原理

    写数据原理 写流程直接请求发送给Leader节点 这里假设集群中有三个zookeeper服务端 ACK (Acknowledge character)即是确认字符,在数据通信中,接收站发给发送站的一种 ...

最新文章

  1. 机器学习奠基人Michael Jordan:下代技术是融合经济学,解读2项重要进展(含PPT)...
  2. Lucene 对文档打分的规则整理记录
  3. 铺地毯pascal程序
  4. Android的JNI开发涉及的char和string之间的互相转换
  5. 用 Span 对 C# 进程中三大内存区域进行统一访问 ,太厉害了!
  6. 使用Fabric8在Kubernetes中使用Camel和CDI
  7. 河南农业大学计算机试题,河南农业大学计算机vb考试必出
  8. 获取arraylist的长度_啃碎JDK源码(三):ArrayList
  9. arguments.callee 指向正在执行的函数的指针
  10. 这个为生信学习打造的开源 Python 文字教程真香!!!
  11. 3D Max 2016安装教程
  12. HUAWEI OSPF配置
  13. 随机森林的原理分析及Python代码实现
  14. QT IOS风格音乐播放器(一) 项目介绍
  15. 喜欢计算机专业的理由英语作文,计算机专业英文自我评价范文
  16. Python+PyCharm的一些基本设置:安装使用、注册码、显示行号、字体大小和快捷键等常用设置...
  17. python编程读取写入excel_Python实现读取并写入Excel文件过程解析
  18. PHP图书信息表books,创建一个图书表
  19. Mat结构及其它数据类型详解
  20. 阿里云服务器最便宜多少钱?附优惠购买教程每月仅需8元!

热门文章

  1. python判断set里是否包含值_【python】判断值是否在list和set的对比以及set的实现原理...
  2. javascript座标_javascript JS元素位置和位置坐标
  3. HNU实验五 小希与火车 基于神经网络的垃圾分类
  4. linux取消登陆管理器,自动登录linux(不使用登录管理器)
  5. K - Repeating Decimals(循环小数)
  6. 解线性方程组的迭代法(雅可比、高斯-塞德尔迭代法)
  7. 目标检测——Detectron2的学习笔记
  8. 有监督学习问题的分类:回归问题和分类问题
  9. 在eclipse中使用第三方库总结
  10. 如何在markdown(csdn)中打出某个字符上面的三角帽子符号