树及其组合算法

  • 决策树
    • 1 什么是决策树。
    • 2 决策树的分类边界和回归线(面)
    • 3 决策树的主要思想
    • 4 构造决策树的算法
    • 5 决策树剪枝
    • 6 决策树算法的代码实现

树及其组合算法部分其余内容,个人笔记博客传送门
树及其组合算法二:

决策树

基本知识介绍

本学期在机器学习的课上学了一些决策树的知识,现在先把课上学到的内容整理一下,之后再补充其他内容。

决策树是机器学习的核心算法之一,可以用于实现预测。

1 什么是决策树。

决策树的名字来源于其分析结果的展示方式,类似于一棵倒置的树,分为回归树和分类树,它是数据反复分组的图形化体现。决策树的每个节点都对应一条推理规则,决策树能够基于叶节点的推理规则实现对新数据的分类预测或回归预测。
可以用树深度(最远的叶节点离根节点的距离)来度量决策树模型复杂度的标准。下图中最远的叶节点到根节点的距离为2,所以该树深度为2。

2 决策树的分类边界和回归线(面)

  • 分类边界
    决策树随着数据的反复分组而生长,如果待分类的样本有p个属性特征,可以将分类树的“生长”过程看作是对p维特征空间的划分过程,原p维特征空间被划分为m个矩形区域,所有矩形区域的边相互平行或垂直。每个节点的推理规则与矩形区域一一对应。

    多个矩形区域边界(直线)的连接可以形成一个不规则的分类边界(曲线),可以有效地解决非线性分类预测问题。分类决策树的深度越大,相邻的矩形区域就越多.
    分类树算法的核心是找到用于划分的特征以及划分的界限,选择的原则是使得划分后的子区域中样本观测点尽量“纯正”。对于样本观测点的“纯正”程度的衡量通常采用信息增益(ID3算法),信息增益率(C4.5算法)或基尼系数gini(CART分类树算法)。

  • 回归边界
    回归树的生长过程也可以看做是对p维特征空间的划分,回归树的构建重点也是选择划分点(包括划分的特征以及划分的阈值)。与分类树稍微不同的地方是, 分类树它的叶节点输出值是类别,而回归树的叶节点输出值为一个平均值。
    回归树的树深度越大相邻回归平面越多,平面的平滑连接可以形成一个不规则的回归曲面(非线性回归)。


如上图举例,假设样本共有x1x_1x1​和x2x_2x2​两个特征属性,样本对于的yyy是数值型数据。现在需要根据样本的输入属性x1,x2x_1,x_2x1​,x2​预测样本的属性yyy。在构建回归决策树时,按照平方和误差最小的原则,依次选择划分点使得划分之后的两个类别异质性低。根据样本集生成的决策树的可视化树形图如上图所示,那么,其实上述回归树的叶节点的输出值为平均值。更具体来看,①不满足x1>30x_1>30x1​>30条件的样本有4个(y1,y2,y3,y4y_1,y_2,y_3,y_4y1​,y2​,y3​,y4​),因此上图中最右边一个叶节点的输出值为Y‾(1)=y1+y2+y3+y44\overline{Y}^{(1)}=\frac{y_1+y_2+y_3+y_4}{4}Y(1)=4y1​+y2​+y3​+y4​​;②满足条件x1>30x_1>30x1​>30且满足x2<45x_2<45x2​<45的样本共有3个,对应的yyy值为y5,y6,y7y_5,y_6,y_7y5​,y6​,y7​,可以计算该叶节点的输出值Y‾(2)=y5+y6+y73\overline{Y}^{(2)}=\frac{y_5+y_6+y_7}{3}Y(2)=3y5​+y6​+y7​​;③满足条件x1>30x_1>30x1​>30但是不满足x2<45x_2<45x2​<45的样本共有3个,对应的yyy值为y8,y9,y10y_8,y_9,y_{10}y8​,y9​,y10​,可以计算该叶节点的输出值为Y‾(3)=y8+y9+y103\overline{Y}^{(3)}=\frac{y_8+y_9+y_{10}}{3}Y(3)=3y8​+y9​+y10​​。

3 决策树的主要思想

决策树的主要思想是使用多个线性分类器的组合将样本分隔开,决策树的每个节点都是一个推理规则,白话点来讲就是一个问题,每个问题的回答都相当于一个线性分类器(判断某特征值是否超过某阈值。)对这一系列的问题的回答就是对线性分类器的组合,最终形成的分界面也是一些超平面的组合。

这里补充一点关于线性分类器和非线性分类器的内容:
线性分类器使用线性的函数表达式对样本进行分类,划分边界为直线或超平面
非线性分类器中引入了非线性函数来提升分类效果,划分边界为曲面或多个超平面的组合

4 构造决策树的算法

决策树的算法分为三种,ID3算法,C4.5算法,CART算法。其中ID3算法和C4.5算法是分类树算法,可以生成二叉树或多叉树;CART算法(classification and regression tree)可以用来构造分类树和回归树,只能生成二叉树。
(1)ID3算法(只用于分类树)
选择划分点时采用的原则是使得划分后的子类纯度更高,这里对纯度的衡量,采用的是信息论中的信息增益,选择信息增益较大的特征进行划分。

信息增益简单来讲就是划分前节点的复杂度与划分后子节点复杂度之间的差值:
Gain(D,a)=Gain(D)−∑i=1m∣Di∣∣D∣Gain(Di)Gain(D,a)=Gain(D)-\sum_{i=1}^{m}\frac{|D_{i}|}{|D|}Gain(D_{i})Gain(D,a)=Gain(D)−i=1∑m​∣D∣∣Di​∣​Gain(Di​)
其中Gain(D)是划分前节点的复杂度,根据某个划分点a将该节点划分为m个子节点,Gain(Di)Gain(D_{i})Gain(Di​)表示子节点iii的复杂度,∣Di∣|D_{i}|∣Di​∣表示第iii个子节点中所含样本数,DDD表示父节点中所含总样本数。

对于复杂度的衡量采用信息熵来衡量。信息熵取值为正,以二分类为例,如果集合中只含有一类则信息熵为0,若两类的数量相同则信息熵为1(因为公式中对数的底数为2)。定义:
Entropy(Y)=−∑ipilog2(pi)Entropy(Y)=-\sum_{i}p_{i}log_{2}( p_{i})Entropy(Y)=−i∑​pi​log2​(pi​)
pi=nin1+...+nkp_{i}=\frac{n_{i}}{n_{1}+...+n_{k}}pi​=n1​+...+nk​ni​​
如果样本一共可以分为kkk类,那么pip_{i}pi​表示该该节点Y中第iii类所占的比例。

条件熵:在给定信息X下,原集合的熵值
Entropy(Y∣X)=∑x∈Xp(x)Entropy(Y∣X=x)Entropy(Y|X)=\sum_{x \in X} p(x)Entropy(Y|X=x)Entropy(Y∣X)=x∈X∑​p(x)Entropy(Y∣X=x)
注:这里的p(x)是划分后子节点中样本数占原父节点样本数的比例。条件熵可以看作子节点的信息熵的加权和,权重即子节点所占父节点的比例。

其实,信息增益可以看作是信息熵减去条件熵。

举例说明

Gain(D)=−[37log2(37)+47log2(47)]=0.985Gain(D)=-[\frac{3}{7}log_{2}(\frac{3}{7})+\frac{4}{7}log_{2}(\frac{4}{7})]=0.985Gain(D)=−[73​log2​(73​)+74​log2​(74​)]=0.985

Ent(D,X=阴)=−[13log2(13)+23log2(23)]=0.918Ent(D,X=阴)=-[\frac{1}{3}log_{2}(\frac{1}{3})+\frac{2}{3}log_{2}(\frac{2}{3})]=0.918Ent(D,X=阴)=−[31​log2​(31​)+32​log2​(32​)]=0.918
Ent(D,X=晴)=−[12log2(12)+12log2(12)])=1Ent(D,X=晴)=-[\frac{1}{2}log_{2}(\frac{1}{2})+\frac{1}{2}log_{2}(\frac{1}{2})])=1Ent(D,X=晴)=−[21​log2​(21​)+21​log2​(21​)])=1
Gain(D,天气)=0.985−(37∗0.918+47∗1)Gain(D,天气)=0.985-(\frac{3}{7}*0.918+\frac{4}{7}*1)Gain(D,天气)=0.985−(73​∗0.918+74​∗1)=0.02
则选择天气这个特征进行划分是信息增益为0.02。

这里可以注意到一个重要的规律,如果分裂的子节点个数越多,那么子节点复杂度加权之和∑i∣Di∣∣D∣Gain(Di)\sum_{i}\frac{|D_{i}|}{|D|}Gain(D_{i})∑i​∣D∣∣Di​∣​Gain(Di​)越小这个规律可以这样理解,考虑采用普通的“样本编号”来进行划分,那么每个子节点中只含有一类,这个子节点的信息熵就为0,那么所有的子节点信息熵加权和也为0,这时信息增益最大,而ID3算法选取信息增益最大的样本特征进行划分。

(2)C4.5算法(只用于分类树)
为了解决ID3算法中倾向于选择有多个子节点的特征属性,C4.5算法中引入了信息增益率的概念,选择信息增益率较大的特征进行划分。
Gain_ratio(D,a)=Gain(D,a)Ent(a划分的节点结构)Gain\_ratio(D,a)=\frac{Gain(D,a)}{Ent(a划分的节点结构)}Gain_ratio(D,a)=Ent(a划分的节点结构)Gain(D,a)​
Ent(a划分的节点结构)=−∑i=1m∣Di∣∣D∣log2(∣Di∣∣D∣)Ent(a划分的节点结构)=-\sum_{i=1}^{m}\frac{|D_{i}|}{|D|}log_{2}(\frac{|D_{i}|}{|D|})Ent(a划分的节点结构)=−i=1∑m​∣D∣∣Di​∣​log2​(∣D∣∣Di​∣​)
参考上面的例子,Ent(天气划分的节点结构)=−[37log2(37)+47log2(47)]=0.985Ent(天气划分的节点结构)=-[\frac{3}{7}log_{2}(\frac{3}{7})+\frac{4}{7}log_{2}(\frac{4}{7})]=0.985Ent(天气划分的节点结构)=−[73​log2​(73​)+74​log2​(74​)]=0.985
Gain_ratio(D,天气)=0.020.985Gain\_ratio(D,天气)=\frac{0.02}{0.985}Gain_ratio(D,天气)=0.9850.02​
对于信息增益率来说,如果所选择的特征属性划分的子节点过多,那么Ent(a划分的节点结构)Ent(a划分的节点结构)Ent(a划分的节点结构)会很大,相应的信息增益率就会变小。
但是这里值得注意的是信息增益率可能会对子节点数目较少的属性有偏好,因此C4.5算法首先计算各属性的信息增益,其中超过平均值的属性才进一步计算增益率来选择最优属性

(3)CART算法(分类树)
CART算法可以用于分类树,也可以用于回归树。当CART算法用来构造分类树时,选择划分点的原理类似于ID3和C4.5算法,都是选取特征属性以及对于的阈值使得划分后的子类“纯度”较高,异质性较低。这里对“纯度”的衡量采用基尼系数gini,选择基尼系数较小的特征进行划分。

说到基尼系数gini,通常对这个名词的使用是在经济学中,用来衡量一个国家的贫富差距,基尼系数越大,贫富差距越大,gini系数超过0.4时贫富差距已经很悬殊了,正常的基尼系数应该在0.2-0.4之间,理想状态下基尼系数gini为0,此时没有贫富差距。基尼系数主要反映的是样本的差异性,当基尼系数越小说明样本间的差异就越小,样本的纯度高。
Gini(D)=1−∑ipi2Gini(D)=1-\sum_{i}p_{i}^{2}Gini(D)=1−i∑​pi2​
Gini(D,a)=∑j=1m∣Di∣∣D∣Gini(Di)Gini(D,a)=\sum_{j=1}^{m}\frac{|D_{i}|}{|D|}Gini(D_{i})Gini(D,a)=j=1∑m​∣D∣∣Di​∣​Gini(Di​)
这里mmm取值应该为2,因为CART算法只能构造二叉树,它是通过自顶向下的递归二分策略实现空间区域的划分。

(4)CART算法(回归树)
当CART算法用于回归树时,不是用“纯度”来衡量划分,而是用混乱度来选择划分的特征,通常用最小绝对偏差LAD最小二乘偏差LSD平方误差和(李航的书《统计学习方法》)作为衡量指标,最常用的是平方误差和,选取平方误差和最小的特征属性进行划分。
minj,s[minc1∑xi∈R1(yi−c1)2+minc2∑xi∈R2(yi−c2)2]min_{j,s}\quad [min_{c_1} \sum _{x_i\in R_1}(y_i-c_1)^2+min_{c_2} \sum _{x_i\in R_2}(y_i-c_2)^2]minj,s​[minc1​​xi​∈R1​∑​(yi​−c1​)2+minc2​​xi​∈R2​∑​(yi​−c2​)2]
c^1=ave(yi∣xi∈R1)\hat{c}_1=ave(y_{i}|x_i\in R_1)c^1​=ave(yi​∣xi​∈R1​)
c^2=ave(yi∣xi∈R2)\hat{c}_2=ave(y_{i}|x_i\in R_2)c^2​=ave(yi​∣xi​∈R2​)

举例说明
现有样本集中有4个样本,每个样本有2个输入属性和一个输出的属性,现在要构造决策树以实现以后给定x1,x2x_1,x_2x1​,x2​能预测样本对于的yyy属性值。
现在供选择的特征属性有x1x_1x1​和x2x_2x2​;对于特征属性x1x_1x1​还需要选择划分阈值,这里将阈值取为(1.5,2.5,3.5)这里取小数的原因是避免有x1x_1x1​属性取值恰好等于阈值的情况,阈值不一定是1.5,2.5,3.5也可以是其他小数,只要满足第一个阈值在区间(1,2)内,第二个阈值在(2,3)区间内…;对于特征属性x2x_2x2​也需要选择划分阈值,这里将阈值取为(15,20,25)。

首先,计算在不同特征属性j和不同阈值s条件下,划分后子类中的均值。然后计算各个子类的平方误差之和,选择平方误差之和最小时对应的划分点。在这里,最小平方误差和为298.67,对应的划分点为,选择特征属性x2x_2x2​阈值为25进行划分,满足条件x2>25x_2>25x2​>25的划为一个子节点,不满足条件的划为另一个子节点。

5 决策树剪枝

决策树的树深度达到最大,分类边界或回归面最不规则,模型复杂度最高,可能带来的问题是模型过拟合。避免决策树过拟合的有效方式为剪枝pruning,分为:预修剪后修剪

预修剪(参数控制):①最大树深度②最小样本量③最小异质性下降值(大概就是前面所说的“纯度”和“混乱度”)
后修剪:按照从叶节点向根节点的方向,逐层剪掉某些节点分枝的过程。

先介绍一种简单的决策树学习的剪枝算法(参数α\alphaα已知)。
参考李航的书《统计学习方法》

原理:决策树的剪枝往往通过极小化决策树整体的损失函数(loss function)或代价函数(cost function)来实现。换句话来说,剪枝,就是当α\alphaα确定时,选择损失函数最小的模型。

基本公式和符号:这里关注的都是叶节点。设树TTT的叶节点个数为∣T∣|T|∣T∣,ttt是树$T$的叶节点,该叶节点的样本点个数为NtN_tNt​,其中第kkk类样本点的个数为NtkN_{tk}Ntk​,k=1,2,3,4...Kk=1,2,3,4...Kk=1,2,3,4...K;Ht(T)H_t(T)Ht​(T)为叶节点t上的经验熵,α≥0\alpha \geq 0α≥0为参数,则决策树学习的损失函数可以定义为
Cα(T)=∑t=1∣T∣NtHt(T)+α∣T∣C_{\alpha}(T)=\sum_{t=1}^{|T|}N_tH_t(T)+\alpha |T|Cα​(T)=t=1∑∣T∣​Nt​Ht​(T)+α∣T∣
其中经验熵(这个就是信息熵的公式)为
Ht(T)=−∑kNtkNtlogNtkNtH_t(T)=-\sum_k \frac{N_{tk}}{N_t} log \frac{N_{tk}}{N_t}Ht​(T)=−k∑​Nt​Ntk​​logNt​Ntk​​
令右边第一项为C(T)C(T)C(T)则有
Cα(T)=C(T)+α∣T∣C_{\alpha}(T)=C(T)+\alpha |T|Cα​(T)=C(T)+α∣T∣
其中C(T)C(T)C(T)表示树T中模型对训练数据的预测误差 ,即模型与训练数据的拟合程度, |T|表示模型复杂度,参数α\alphaα控制两者之间的影响。α\alphaα较大,则模型复杂度对损失函数的贡献度高,倾向于选择更简单的模型;α\alphaα较大,则模型复杂度对损失函数的贡献度低,相对来说训练误差对损失函数的贡献度更高,倾向于选择更复杂的树。
剪枝算法:
输入:生成算法产生的整个决策树TTT,参数α\alphaα。
输出:修剪后的子树TαT_{\alpha}Tα​
①计算每个节点的经验熵
②递归地从树的叶节点向上回缩
设一组叶节点未回缩到父节点时整体树为TBT_BTB​;叶节点回缩到父节点,即剪掉这些叶节点时整体树为TAT_ATA​。
若Cα(TA)≤Cα(TB)C_{\alpha}(T_A) \leq C_{\alpha}(T_B)Cα​(TA​)≤Cα​(TB​)则进行剪枝。
该不等式等价于C(TA)−C(TB)∣TB∣−∣TA∣≤α\frac{C(T_A)-C(T_B)}{|T_B|-|T_A|}\leq \alpha∣TB​∣−∣TA​∣C(TA​)−C(TB​)​≤α
③返回步骤②,直至不能继续为止,得到最小子树TαT_{\alpha}Tα​。

另外单独介绍CART剪枝(α\alphaα未知)
参考李航的书《统计学习方法》

Breiman等人证明:可以使用递归的方法对树进行剪枝,具体分为两个阶段。

  • 第一阶段:剪枝,形成一个子树序列。
    具体地,从整体树T0T_0T0​开始剪枝。对T0T_0T0​的任意中间节点ttt,以ttt为单节点树的损失函数是
    Cα(t)=C(t)+αC_{\alpha}(t)=C(t)+\alphaCα​(t)=C(t)+α
    以ttt为根节点的子树TtT_tTt​的损失函数为
    Cα(Tt)=C(Tt)+α∣Tt∣C_{\alpha}(T_t)=C(T_t)+\alpha|T_t|Cα​(Tt​)=C(Tt​)+α∣Tt​∣
    当α\alphaα为0或者极小的时候,有不等式
    Cα(Tt)<Cα(t)C_{\alpha}(T_t)< C_{\alpha}(t)Cα​(Tt​)<Cα​(t)
    当α\alphaα继续增大时,有
    Cα(Tt)=Cα(t)C_{\alpha}(T_t)=C_{\alpha}(t)Cα​(Tt​)=Cα​(t)
    此时满足TtT_tTt​与ttt有相同的损失函数值,而ttt的节点少,因此ttt比TtT_tTt​更可取,对TtT_tTt​进行剪枝。
    对T0T_0T0​中每个中间节点计算:
    α=C(t)−C(Tt)∣Tt∣−1等价于Cα(Tt)=Cα(t)\alpha=\frac{C(t)-C(T_t)}{|T_t|-1}\quad 等价于C_{\alpha}(T_t)=C_{\alpha}(t)α=∣Tt​∣−1C(t)−C(Tt​)​等价于Cα​(Tt​)=Cα​(t)
    得到一系列αt\alpha_tαt​,找到最小的αt\alpha_tαt​,在T0T_0T0​中剪掉TtT_tTt​,得到子树T1T_1T1​,同时将最小的α\alphaα设为α1\alpha_1α1​。此时T1T_1T1​为参数区间[α1\alpha_1α1​,α2\alpha_2α2​)内的最优子树。

  • 第二个阶段:在剪枝得到的子树序列T0,T1,T2,...TnT_0,T_1,T_2,...T_nT0​,T1​,T2​,...Tn​中通过交叉验证选取最优子树TαT_{\alpha}Tα​

具体地,利用独立的验证数据集,测试子树序列T0,T1,...TnT_0,T_1,...T_nT0​,T1​,...Tn​中各棵子树的平方误差或基尼指数。平方误差或基尼指数最小的决策树被认为是最优的决策树。在子树序列中,每棵子树T0,T1,...TnT_0,T_1,...T_nT0​,T1​,...Tn​都对应一个参数α1,α2,...αn\alpha_1,\alpha_2,...\alpha_nα1​,α2​,...αn​。所以,当最优子树TkT_kTk​确定时,对应的αk\alpha_kαk​也确定了,即得到最优决策树TαT_{\alpha}Tα​。

6 决策树算法的代码实现

代码好多好多,看相关参考资料6

相关参考资料

1.这个大佬写得好详细啊,条理清晰,白话易懂,但是信息增益部分的公式好像有点问题,链接附上:决策树系列。

2.代码实现决策树多分类,使用python自带的iris数据集,借助ID3算法,参考博客链接附上:机器学习五(sklearn决策树——多分类)
3.代码实现回归树的预测实现,使用python自带波士顿房价数据集,参考博文链接附上:回归树预测和机器学习之路: python 回归树 DecisionTreeRegressor 预测波士顿房价

4.回归树的基本原理概述https://blog.csdn.net/weixin_40604987/article/details/79296427

5.极客时间,试读4节,参考决策树CART部分https://time.geekbang.org/column/article/78659

6.代码代码https://blog.csdn.net/z962013489/article/details/80024574

【机器学习】树及其组合算法(一)(Bagging,Boosting,GBDT,XGboost,Adaboost,随机森林)相关推荐

  1. 机器学习实战之分类算法(K-近邻/朴素贝叶斯/决策树/随机森林)

    机器学习分类算法 1. 机器学习算法简介 1.1 按照学习方式分类 1.2 区别 1.3 关于监督学习中的分类与回归区别 1.4 机器学习开发流程 2. 数据集介绍与划分 2.1 sklearn数据集 ...

  2. 【机器学习】树及其组合算法(二)(Bagging,Boosting,GBDT,XGboost,Adaboost,随机森林)

    树及其组合算法二:Bagging 1集成学习 1.1集成学习概述 1.2集成学习的原理 2 Bagging 2.1 Bagging的建模 2.2 Bagging的预测 2.3 Bagging测试误差的 ...

  3. 机器学习——基于Bagging的集成学习:随机森林(Random Forest)及python实现

    基于Bagging的集成学习:随机森林的原理及其实现 引入 Bagging装袋 随机森林 随机森林分类 随机森林回归 python实现 随机森林分类 随机森林回归 引入 "三个臭皮匠赛过诸葛 ...

  4. R语言使用caret包构建随机森林模型(random forest)构建回归模型、通过method参数指定算法名称、通过ntree参数指定随机森林中树的个数

    R语言使用caret包构建随机森林模型(random forest)构建回归模型.通过method参数指定算法名称.通过ntree参数指定随机森林中树的个数 目录

  5. 【算法精讲】集成分类与随机森林

    ONE 集成分类 01 什么是集成分类 集成分类是集成学习的一种,先讲下集成学习是什么. 所谓集成学习,引用一句谚语"三个臭皮匠顶个诸葛亮"最恰当不过. 集成学习就是将多个弱学习器 ...

  6. 机器学习算法基础(6): 信息论,决策树和随机森林

    分类算法:决策树.随机森林 1.认识决策树 决策树的划分 2.信息的度量和作用 信息的单位:比特 信息熵 信息和消除不确定性相关 2.决策树的划分以及案例 决策树的划分--信息增益 概念:当得知一个特 ...

  7. python天气数据分析论文_《Python数据分析与机器学习实战-唐宇迪》读书笔记第9章--随机森林项目实战——气温预测(2/2)...

    第9章--随机森林项目实战--气温预测(2/2) 第8章已经讲解过随机森林的基本原理,本章将从实战的角度出发,借助Python工具包完成气温预测任务,其中涉及多个模块,主要包含随机森林建模.特征选择. ...

  8. python数据项目分析实战技法_《Python数据分析与机器学习实战-唐宇迪》读书笔记第9章--随机森林项目实战——气温预测(1/2)...

    第9章--随机森林项目实战--气温预测(1/2) 第8章已经讲解过随机森林的基本原理,本章将从实战的角度出发,借助Python工具包完成气温预测任务,其中涉及多个模块,主要包含随机森林建模.特征选择. ...

  9. 机器学习第20篇 - 基于Boruta选择的特征变量构建随机森林

    前面机器学习第18篇 - Boruta特征变量筛选(2)已经完成了特征变量筛选,下面看下基于筛选的特征变量构建的模型准确性怎样? 定义一个函数生成一些列用来测试的mtry (一系列不大于总变量数的数值 ...

  10. 基于机器学习xgboost 线性回归 随机森林 的电影票房预测 完整数据+代码

    运行参考:https://www.bilibili.com/video/BV1U24y1g7at/?spm_id_from=333.999.0.0 完整代码+数据:

最新文章

  1. 数据结构(5)之单链表的操作(补充)
  2. 大名鼎鼎的红黑树,你get了么?2-3树 绝对平衡 右旋转 左旋转 颜色反转
  3. Sentinel 发布里程碑版本,添加集群流控功能
  4. 微信公众号Java开发-笔记02【开发接入准备、开发接入】
  5. 我运维生涯的第一个Blog
  6. JAVA编写的一个简单的Socket实现的HTTP响应服务器
  7. 事务失败返回_分布式事务方案 TCC
  8. internet缓存Temp中的tmp文件
  9. keepalived+nginx双机热备+负载均衡
  10. deeplearning.ai——构建循环神经网络
  11. 基于springboot+vue的房屋租赁系统(前后端分离)
  12. 记第一次自己组装台式机
  13. 实战:利用CSS动画制作一个梦幻西游动态页面
  14. 只有7步,就能将任何魔方6面还原
  15. python语言迷宫游戏_一个Python迷宫小游戏
  16. Android应用开发详解【郭宏志】(奋斗之小鸟)_PDF 电子书
  17. HD2500显卡驱动linux,Intel HD Graphics 2500/4000驱动免费版
  18. vue动态设置路由重定向
  19. Haproxy+Keepalived+MySQL高可用均衡负载部署
  20. dell服务器维修过程

热门文章

  1. 蛐蛐播放器 android,蛐蛐五线谱播放器
  2. instead of触发器
  3. 2019腾讯算法广告大赛冠军方案复现遇到的问题 python
  4. 多个excel工作簿合并_你还在使用复制粘贴合并表格?一个公式搞定Excel多工作簿合并...
  5. 2030年中国GDP将超越美国成为世界第一?
  6. 这台计算机无法连接usb,爱思助手无法连接或者连接超时解决办法
  7. 实木地板被机器人弄成坑_“实木地板”真的好?这些不搞明白,小心被商家坑了...
  8. 人事管理系统:若依框架集成activiti工作流自动审批
  9. DeepFace人脸检测(python实现)
  10. Kylin多维分析引擎(四):Kylin Cude构建流程详解