机器学习算法GBDT的面试要点总结-上篇

2023-11-20

1.简介

    gbdt全称梯度提升决策树,在传统机器学习算法里面是对真实分布拟合的最好的几种算法之一,在前几年深度学习还没有大行其道之前,gbdt在各种竞赛是大放异彩。原因大概有几个,一是效果确实挺不错。二是即可以用于分类也可以用于回归。三是可以筛选特征。这三点实在是太吸引人了,导致在面试的时候大家也非常喜欢问这个算法。 gbdt的面试考核点,大致有下面几个:

  • gbdt 的算法的流程?
  • gbdt 如何选择特征 ?
  • gbdt 如何构建特征 ?
  • gbdt 如何用于分类?
  • gbdt 通过什么方式减少误差 ?
  • gbdt的效果相比于传统的LR,SVM效果为什么好一些 ?
  • gbdt 如何加速训练?
  • gbdt的参数有哪些,如何调参 ?
  • gbdt 实战当中遇到的一些问题 ?
  • gbdt的优缺点 ?

2. 正式介绍

    首先gbdt 是通过采用加法模型(即基函数的线性组合),以及不断减小训练过程产生的残差来达到将数据分类或者回归的算法。

  •  gbdt的训练过程

        我们通过一张图片,图片来源来说明gbdt的训练过程: 

    

                      图 1:GBDT 的训练过程

        gbdt通过多轮迭代,每轮迭代产生一个弱分类器,每个分类器在上一轮分类器的残差基础上进行训练。对弱分类器的要求一般是足够简单,并且是低方差和高偏差的。因为训练的过程是通过降低偏差来不断提高最终分类器的精度,(此处是可以证明的)。

        弱分类器一般会选择为CART TREE(也就是分类回归树)。由于上述高偏差和简单的要求 每个分类回归树的深度不会很深。最终的总分类器 是将每轮训练得到的弱分类器加权求和得到的(也就是加法模型)。

        模型最终可以描述为:$$F_{m}(x) = \sum_{m=1}^{M}T\left ( x;\theta _m \right )$$

        模型一共训练M轮,每轮产生一个弱分类器 $T\left ( x;\theta _m \right )$。弱分类器的损失函数$$\hat\theta_{m} = \mathop{\arg\min}_{\theta_{m}} \sum_{i=1}^{N}L\left ( y_{i},F_{m-1}(x_{i})+T(x_{i};\theta_{m} ) \right )$$

        $F_{m-1}(x)$ 为当前的模型,gbdt 通过经验风险极小化来确定下一个弱分类器的参数。具体到损失函数本身的选择也就是L的选择,有平方损失函数,0-1损失函数,对数损失函数等等。如果我们选择平方损失函数,那么这个差值其实就是我们平常所说的残差

    • 但是其实我们真正关注的,1.是希望损失函数能够不断的减小,2.是希望损失函数能够尽可能快的减小。所以如何尽可能快的减小呢?
    • 让损失函数沿着梯度方向的下降。这个就是gbdt 的 gb的核心了。 利用损失函数的负梯度在当前模型的值作为回归问题提升树算法中的残差的近似值去拟合一个回归树。gbdt 每轮迭代的时候,都去拟合损失函数在当前模型下的负梯度。
    • 这样每轮训练的时候都能够让损失函数尽可能快的减小,尽快的收敛达到局部最优解或者全局最优解。
  • gbdt如何选择特征?

        gbdt选择特征的细节其实是想问你CART Tree生成的过程。这里有一个前提,gbdt的弱分类器默认选择的是CART TREE。其实也可以选择其他弱分类器的,选择的前提是低方差和高偏差。框架服从boosting 框架即可。

        下面我们具体来说CART TREE(是一种二叉树) 如何生成。CART TREE 生成的过程其实就是一个选择特征的过程。假设我们目前总共有 M 个特征。第一步我们需要从中选择出一个特征 j,做为二叉树的第一个节点。然后对特征 j 的值选择一个切分点 m. 一个 样本的特征j的值 如果小于m,则分为一类,如果大于m,则分为另外一类。如此便构建了CART 树的一个节点。其他节点的生成过程和这个是一样的。现在的问题是在每轮迭代的时候,如何选择这个特征 j,以及如何选择特征 j 的切分点 m:

    • 原始的gbdt的做法非常的暴力,首先遍历每个特征,然后对每个特征遍历它所有可能的切分点,找到最优特征 m 的最优切分点 j。
    • 如何衡量我们找到的特征 m和切分点 j 是最优的呢? 我们用定义一个函数 FindLossAndSplit 来展示一下求解过程:

 

 1 def findLossAndSplit(x,y):
 2     # 我们用 x 来表示训练数据
 3     # 我们用 y 来表示训练数据的label
 4     # x[i]表示训练数据的第i个特征
 5     # x_i 表示第i个训练样本
 6 
 7     # minLoss 表示最小的损失
 8     minLoss = Integet.max_value
 9     # feature 表示是训练的数据第几纬度的特征
10     feature = 0
11     # split 表示切分点的个数
12     split = 0
13 
14     # M 表示 样本x的特征个数
15     for j in range(0,M):
16         # 该维特征下,特征值的每个切分点,这里具体的切分方式可以自己定义
17         for c in range(0,x[j]):
18             L = 0
19             # 第一类
20             R1 = {x|x[j] <= c}
21             # 第二类
22             R2 = {x|x[j] > c}
23             # 属于第一类样本的y值的平均值
24             y1 = ave{y|x 属于 R1}
25             # 属于第二类样本的y值的平均值
26             y2 = ave{y| x 属于 R2}
27             # 遍历所有的样本,找到 loss funtion 的值
28             for x_1 in all x
29                 if x_1 属于 R1: 
30                     L += (y_1 - y1)^2 
31                 else:
32                     L += (y_1 - y2)^2
33             if L < minLoss:
34                minLoss = L
35                feature  = i
36                split = c
37     return minLoss,feature ,split

 

    • 如果对这段代码不是很了解的,可以先去看看李航第五章中对CART TREE 算法的叙述。在这里,我们先遍历训练样本的所有的特征,对于特征 j,我们遍历特征 j 所有特征值的切分点 c。找到可以让下面这个式子最小的特征 j 以及切分点c.
    •     
  • gbdt 如何构建特征 ?

        其实说gbdt 能够构建特征并非很准确,gbdt 本身是不能产生特征的,但是我们可以利用gbdt去产生特征的组合。在CTR预估中,工业界一般会采用逻辑回归去进行处理,在我的上一篇博文当中已经说过,逻辑回归本身是适合处理线性可分的数据,如果我们想让逻辑回归处理非线性的数据,其中一种方式便是组合不同特征,增强逻辑回归对非线性分布的拟合能力。

        长久以来,我们都是通过人工的先验知识或者实验来获得有效的组合特征,但是很多时候,使用人工经验知识来组合特征过于耗费人力,造成了机器学习当中一个很奇特的现象:有多少人工就有多少智能。关键是这样通过人工去组合特征并不一定能够提升模型的效果。所以我们的从业者或者学界一直都有一个趋势便是通过算法自动,高效的寻找到有效的特征组合。Facebook 在2014年 发表的一篇论文便是这种尝试下的产物,利用gbdt去产生有效的特征组合,以便用于逻辑回归的训练,提升模型最终的效果。

             图 2:用GBDT 构造特征

        如图 2所示,我们 使用 GBDT 生成了两棵树,两颗树一共有五个叶子节点。我们将样本 X 输入到两颗树当中去,样本X 落在了第一棵树的第二个叶子节点,第二颗树的第一个叶子节点,于是我们便可以依次构建一个五纬的特征向量,每一个纬度代表了一个叶子节点,样本落在这个叶子节点上面的话那么值为1,没有落在该叶子节点的话,那么值为 0.

        于是对于该样本,我们可以得到一个向量[0,1,0,1,0] 作为该样本的组合特征,和原来的特征一起输入到逻辑回归当中进行训练。实验证明这样会得到比较显著的效果提升。

 

 

  • GBDT 如何用于分类 ?

        首先明确一点,gbdt 无论用于分类还是回归一直都是使用的CART 回归树不会因为我们所选择的任务是分类任务就选用分类树,这里面的核心是因为gbdt 每轮的训练是在上一轮的训练的残差基础之上进行训练的。这里的残差就是当前模型的负梯度值 。这个要求每轮迭代的时候,弱分类器的输出的结果相减是有意义的。残差相减是有意义的。

        如果选用的弱分类器是分类树,类别相减是没有意义的。上一轮输出的是样本 x 属于 A类,本一轮训练输出的是样本 x 属于 B类。 A 和 B 很多时候甚至都没有比较的意义,A 类- B类是没有意义的。

        我们具体到分类这个任务上面来,我们假设样本 X 总共有 K类。来了一个样本 x,我们需要使用gbdt来判断 x 属于样本的哪一类。

    • 图三 gbdt 多分类算法流程

        第一步 我们在训练的时候,是针对样本 X 每个可能的类都训练一个分类回归树。举例说明,目前样本有三类,也就是 K = 3。样本 x 属于 第二类。那么针对该样本 x 的分类结果,其实我们可以用一个 三维向量 [0,1,0] 来表示。0表示样本不属于该类,1表示样本属于该类。由于样本已经属于第二类了,所以第二类对应的向量维度为1,其他位置为0。

        针对样本有 三类的情况,我们实质上是在每轮的训练的时候是同时训练三颗树。第一颗树针对样本x的第一类,输入为$(x,0)$。第二颗树输入针对 样本x 的第二类,输入为$(x,1)$。第三颗树针对样本x 的第三类,输入为$(x,0)$

        在这里每颗树的训练过程其实就是就是我们之前已经提到过的CATR TREE 的生成过程。在此处我们参照之前的生成树的程序 即可以就解出三颗树,以及三颗树对x 类别的预测值$f_{1}(x),f_{2}(x),f_{3}(x)$。那么在此类训练中,我们仿照多分类的逻辑回归 ,使用softmax 来产生概率,则属于类别 1 的概率$$p_{1}=exp(f_{1}{(x)})/\sum_{k= 1}^{3}exp(f_{k}{(x)})$$

        并且我们我们可以针对类别1 求出 残差$y_{11}(x) = 0-p_{1}(x)$;类别2 求出残差$y_{22}(x)= 1-p_2(x)$;类别3 求出残差$y_{33}(x)= 0-p_{3}(x)$.

        然后开始第二轮训练 针对第一类 输入为(x,$y_{11}(x)$), 针对第二类输入为(x,$y_{22}(x))$, 针对 第三类输入为 (x,$y_{33}(x)$).继续训练出三颗树。一直迭代M轮。每轮构建 3颗树。

        所以当K =3。我们其实应该有三个式子 $$F_{1M}{(x)}=\sum_{m=1}^{M}{\hat{C_{1m}}I(x\epsilon R_{1m})}$$ $$F_{2M}{(x)}=\sum_{m=1}^{M}{\hat{C_{2m}}I(x\epsilon R_{2m})}$$ $$F_{3M}{(x)}=\sum_{m=1}^{M}{\hat{C_{3m}}I(x\epsilon R_{3m})}$$

        当训练完毕以后,新来一个样本 x1 ,我们需要预测该样本的类别的时候,便可以有这三个式子产生三个值,$f_{1}(x),f_{2}(x),f_{3}(x)$。样本属于 某个类别c的概率为 $$p_{c}=exp(f_{c}{(x)})/\sum_{k= 1}^{3}exp(f_{k}{(x)})$$

  • GBDT 多分类举例说明

        上面的理论阐述可能仍旧过于难懂,我们下面将拿Iris 数据集中的六个数据作为例子,来展示gbdt 多分类的过程。

    • 样本编号 花萼长度(cm) 花萼宽度(cm) 花瓣长度(cm) 花瓣宽度 花的种类
      1 5.1 3.5 1.4 0.2 山鸢尾
      2 4.9 3.0 1.4 0.2 山鸢尾
      3 7.0 3.2 4.7 1.4 杂色鸢尾
      4 6.4 3.2 4.5 1.5 杂色鸢尾
      5 6.3 3.3 6.0 2.5 维吉尼亚鸢尾
      6 5.8 2.7 5.1 1.9 维吉尼亚鸢尾
      图四 Iris 数据集

        这是一个有6个样本的三分类问题。我们需要根据这个花的花萼长度,花萼宽度,花瓣长度,花瓣宽度来判断这个花属于山鸢尾,杂色鸢尾,还是维吉尼亚鸢尾。具体应用到gbdt多分类算法上面。我们用一个三维向量来标志样本的label。[1,0,0] 表示样本属于山鸢尾,[0,1,0] 表示样本属于杂色鸢尾,[0,0,1] 表示属于维吉尼亚鸢尾。

        gbdt 的多分类是针对每个类都独立训练一个 CART Tree。所以这里,我们将针对山鸢尾类别训练一个 CART Tree 1。杂色鸢尾训练一个 CART Tree 2 。维吉尼亚鸢尾训练一个CART Tree 3,这三个树相互独立。

        我们以样本 1 为例。针对 CART Tree1 的训练样本是$[5.1, 3.5 , 1.4, 0.2]$,label 是 1,最终输入到模型当中的为$[5.1, 3.5 , 1.4, 0.2, 1]$。针对 CART Tree2 的训练样本也是$[5.1, 3.5 , 1.4, 0.2]$,但是label 为 0,最终输入模型的为$[5.1, 3.5 , 1.4, 0.2, 0]$. 针对 CART Tree 3的训练样本也是$[5.1, 3.5 , 1.4, 0.2] $,label 也为0,最终输入模型当中的为$[5.1, 3.5 , 1.4, 0.2, 0]$. 

        下面我们来看 CART Tree1 是如何生成的,其他树 CART Tree2 , CART Tree 3的生成方式是一样的。CART Tree的生成过程是从这四个特征中找一个特征做为CART Tree1 的节点。比如花萼长度做为节点。6个样本当中花萼长度 大于5.1 cm的就是 A类,小于等于 5.1 cm 的是B类。生成的过程其实非常简单,问题 1.是哪个特征最合适? 2.是这个特征的什么特征值作为切分点? 即使我们已经确定了花萼长度做为节点。花萼长度本身也有很多值。在这里我们的方式是遍历所有的可能性,找到一个最好的特征和它对应的最优特征值可以让当前式子的值最小。

         我们以第一个特征的第一个特征值为例。R1 为所有样本中花萼长度小于 5.1 cm 的样本集合,R2 为所有样本当中花萼长度大于等于 5.1cm 的样本集合。所以 $R1 = \left \{  2\right \}$,$R2 = \left \{ 1,3,4,5,6 \right \}$.

       

图 5 节点分裂示意图

        y1 为 R1 所有样本的label 的均值 $1/1 = 1$。y2 为 R2 所有样本的label 的均值 $(1+0+0+0+0) /5 = 0.2$。

        下面便开始针对所有的样本计算这个式子的值。样本1 属于 R2 计算的值为$( 1 - 0.2)^2$, 样本2 属于R1 计算的值为$( 1 -1 )^2$, 样本 3,4,5,6同理都是 属于 R2的 所以值是$(0-0.2)^2$. 把这六个值加起来,便是 山鸢尾类型在特征1 的第一个特征值的损失值。这里算出来(1-0.2)^2+ (1-1)^2 + (0-0.2)^2+(0-0.2)^2+(0-0.2)^2 +(0-0.2)^2= 0.84

        接着我们计算第一个特征的第二个特征值,计算方式同上,R1 为所有样本中 花萼长度小于 4.9 cm 的样本集合,R2 为所有样本当中 花萼长度大于等于 4.9 cm 的样本集合.所以 $R1 = \left \{  \right \}$,$R1 = \left \{ 1,2,3,4,5,6 \right \}$. y1 为 R1 所有样本的label 的均值 = 0。y2 为 R2 所有样本的label 的均值 $(1+1+0+0+0+0) /6 = 0.3333$。

图 6 第一个特征的第二个特侦值的节点分裂情况        

        我们需要针对所有的样本,样本1 属于 R2, 计算的值为$( 1 - 0.333 )^2$, 样本2 属于R2 ,计算的值为$( 1 -0.333 )^2$, 样本 3,4,5,6同理都是 属于 R2的, 所以值是$(0-0.333)^2$. 把这六个值加起来山鸢尾类型在特征1 的第二个特征值的损失值。这里算出来 (1-0.333)^2+ (1-0.333)^2 + (0-0.333)^2+(0-0.333)^2+(0-0.333)^2 +(0-0.333)^2 = 2.244189. 这里的损失值大于 特征一的第一个特征值的损失值,所以我们不取这个特征的特征值。

图 7 所有情况说明  

        这样我们可以遍历所有特征的所有特征值,找到让这个式子最小的特征以及其对应的特征值,一共有24种情况,4个特征*每个特征有6个特征值。在这里我们算出来让这个式子最小的特征花萼长度,特征值为5.1 cm。这个时候损失函数最小为 0.8。

        于是我们的预测函数此时也可以得到: $$f(x) = \sum_{x\epsilon R_{1}} y_{1}*I(x\epsilon R_{1})+\sum_{x\epsilon R_{2}} y_{2}*I(x\epsilon R_{2})$$

        此处 R1 = {2},R2 = {1,3,4,5,6},y1 = 1,y2 = 0.2。训练完以后的最终式子为 $$f_{1}(x) = \sum_{x\epsilon R_{1}} 1*I(x\epsilon R_{1})+\sum_{x\epsilon R_{2}} 0.2*I(x\epsilon R_{2})$$

        借由这个式子,我们得到对样本属于类别1 的预测值 $f_{1}(x) = 1 + 0.2 * 5  = 2$。同理我们可以得到对样本属于类别2,3的预测值$f_{2}(x)$,$f_{3}(x)$.样本属于类别1的概率 即为 $$p_{1}=exp(f_{1}{(x)})/\sum_{k= 1}^{3}exp(f_{k}{(x)})$$

        下面我们用代码来实现整个找特征的过程,大家可以自己再对照代码看看

 1 # 定义训练数据
 2 train_data = [[5.1,3.5,1.4,0.2],[4.9,3.0,1.4,0.2],[7.0,3.2,4.7,1.4],[6.4,3.2,4.5,1.5],[6.3,3.3,6.0,2.5],[5.8,2.7,5.1,1.9]]
 3 
 4 # 定义label
 5 label_data = [[1,0,0],[1,0,0],[0,1,0],[0,1,0],[0,0,1],[0,0,1]]
 6 # index 表示的第几类
 7 def findBestLossAndSplit(train_data,label_data,index):
 8         sample_numbers = len(label_data)
 9         feature_numbers = len(train_data[0])
10         current_label = []
11 
12         # define the minLoss
13         minLoss = 10000000
14 
15         # feature represents the dimensions of the feature
16         feature = 0
17 
18         # split represents the detail split value
19         split = 0
20 
21         # get current label
22         for label_index in range(0,len(label_data)):
23             current_label.append(label_data[label_index][index])
24 
25         # trans all features
26         for feature_index in range(0,feature_numbers):
27             ## current feature value
28             current_value = []
29 
30             for sample_index in range(0,sample_numbers):
31                 current_value.append(train_data[sample_index][feature_index])
32             L = 0
33             ## different split value
34             print current_value
35             for index in range(0,len(current_value)):
36                 R1 = []
37                 R2 = []
38                 y1 = 0
39                 y2 = 0
40 
41                 for index_1 in range(0,len(current_value)):
42                     if current_value[index_1] < current_value[index]:
43                         R1.append(index_1)
44                     else:
45                         R2.append(index_1)
46 
47                 ## calculate the samples for first class
48                 sum_y = 0
49                 for index_R1 in R1:
50                     sum_y += current_label[index_R1]
51                 if len(R1) != 0:
52                     y1 = float(sum_y) / float(len(R1))
53                 else:
54                     y1 = 0
55 
56                 ## calculate the samples for second class
57                 sum_y = 0
58                 for index_R2 in R2:
59                     sum_y += current_label[index_R2]
60                 if len(R2) != 0:
61                     y2 = float(sum_y) / float(len(R2))
62                 else:
63                     y2 = 0
64 
65                 ## trans all samples to find minium loss and best split
66                 for index_2 in range(0,len(current_value)):
67                     if index_2 in R1:
68                         L += float((current_label[index_2]-y1))*float((current_label[index_2]-y1))
69                     else:
70                         L += float((current_label[index_2]-y2))*float((current_label[index_2]-y2))
71 
72                 if L < minLoss:
73                     feature = feature_index
74                     split = current_value[index]
75                     minLoss = L
76                     print "minLoss"
77                     print minLoss
78                     print "split"
79                     print split
80                     print "feature"
81                     print feature
82         return minLoss,split,feature
83 
84 findBestLossAndSplit(train_data,label_data,0)

 

  • 3 总结

        目前,我们总结了 gbdt 的算法的流程,gbdt如何选择特征,如何产生特征的组合,以及gbdt 如何用于分类,这个目前可以认为是gbdt 最经常问到的四个部分。至于剩余的问题,因为篇幅的问题,我们准备再开一个篇幅来进行总结。也欢迎大家关注我的微信公众号。ModifyAI

 

转载于:https://www.cnblogs.com/ModifyRong/p/7744987.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习算法GBDT的面试要点总结-上篇 的相关文章

随机推荐

  • Unity中实现倒计时的几种方式

    1 Time time using UnityEngine public class TimeTest MonoBehaviour public float secound 10 void Update Timing private flo
  • 新闻文本分类—基于深度学习的文本分类2

    学习目标 学习Word2Vec的使用和基础原理 学习使用TextCNN TextRNN进行文本表示 学习使用HAN网络结构完成文本分类 文本表示方法 Part3 词向量 本节通过word2vec学习词向量 word2vec模型背后的基本思想
  • 细谈JavaWeb中的Request和Response

    文章目录 1 Request和Response的概述 2 Request对象 2 1 Request继承体系 2 2 Request获取请求数据 2 2 1 获取请求行数据 2 2 2 获取请求头数据 2 2 3 获取请求体数据 2 2 4
  • 2020最新版KVM虚拟机安装详解

    VMware Workstation Pro15 5下 1 操作环境 CentOS Linux release 7 7 1908 Core 2 需要用到的工具 XSHELL Centos任意版本镜像 3 必须安装的软件 Xmanager p
  • ec6110刷linux系统,华为DIIEC6110M_VER_C主板救砖纯净系统烧录固件包下载

    大家好今天小编跟大家分享关于华为DIIEC6110M VER C主板 强制升级 但是无反应强刷不起作用或短接后只亮一个绿灯 由于盒子厂商系统升级后 屏蔽了强刷模式导致无法使用 短接方式进行强刷 此时短接强刷这条路行不通的时候 需要使用线刷进
  • 2023年4月23日--4月30日(pbr为主,有时间就看看Ue视频教程,50小时,合计2039小时,剩余7961小时)

    按照规划 本周结合工作内容 以Pbr为主 可以从Ue的材质编辑器获取材质参数 写到glsl或者filament引擎 目前 ue视频教程进行到了智 慧 城 市 3 13 mysql 7 1 tf1 4 11 蓝图反射 1 9 moba 1 5
  • mysql 索引类型详解

    索引的类型和存储引擎有关 每种存储引擎所支持的索引类型不一定完全相同 MySQL 索引可以从存储方式 逻辑角度和实际使用的角度来进行分类 存储方式区分 根据存储方式的不同 MySQL 中常用的索引在物理上分为 B 树索引和 HASH 索引两
  • Downie 4 4.6.12 MAC上最好的一款视频下载工具

    Downie for Mac 简介 Downie是Mac下一个简单的下载管理器 可以让您快速将不同的视频网站上的视频下载并保存到电脑磁盘里然后使用您的默认媒体播放器观看它们 Downie 4 Downie 4 for Mac Downie
  • 编写代码常用快捷键

    编写代码常用快捷键 shift 或 逐个选中字符 ctrl 或 逐词移动光标 ctrl shift 或 逐词选中字符 常用 Home键 将光标移动到行开头 End键 将光标移动到到行结尾 常用 配合shift 或 Shift Home 从光
  • 华为云,站在数字化背后

    一场新的中国数字化战斗 正在被缓缓拉开帷幕 作者 裴一多 出品 产业家 如果说最近的讨论热点是什么 那无疑是互联网云 在数字化进入纵深的当下 一种市面上的观点是互联网的云业务由于盈利等问题 正在成为 被抛弃 的一方 互联网公司开始重新回归T
  • Spyder入门使用教程

    Spyder入门使用教程 Spyder汉化 Spyder汉化博客 创建项目 首先介绍Spyder布局 主要分上面的功能栏和下方的三个区块 点击创建新的项目 选择项目存放的目录 输入项目名 完成项目创建 创建新的文件 按Ctrl S 保存文件
  • Docker 资源汇总

    Docker 资源汇总 转载来源 http codecloud net docker resource 6090 html Menu Main Resources Books Websites Documents Archives Comm
  • Anaconda配置

    Anaconda配置 创建环境 conda create n 环境名 python 3 8 移除环境 conda remove n 环境名 all 查看所有环境 conda env list 激活环境 conda activate 环境名
  • 华为OD机试 - 组装最大可靠性设备(Java )

    题目描述 一个设备由N种类型元器件组成 每种类型元器件只需要一个 类型type编号从0 N 1 每个元器件均有可靠性属性reliability 可靠性越高的器件其价格price越贵 而设备的可靠性由组成设备的所有器件中可靠性最低的器件决定
  • wxwidgets编写多线程程序--wxThread

    细节描述 线程基本上来说是应用程序中一条单独执行的路径 线程有时被称为轻量级进程 但线程与进程的根本不同之处在于不同进程存储空间是相互独立的 而同一进程里的所有线程共享同一地址空间 尽管这使得它更容易共享几个线程间的普通数据 但这也使得它有
  • 企业微信群:机器人实现定时提醒功能

    如果每天都需要 或者经常需要提醒企业微信群里面的人做某一件事情的话 靠人力去实现比较费力 而且偶尔忘记 正好 企业微信群有一个机器人 正可以实现这一功能 1 首先 在企业微信群 添加一个机器人 2 根据企业微信机器人的配置说明 编写程序 这
  • NOSuchKeys: com.aliyun.oss.OSSException: The specified key does not exist.

    出现这个原因就是在指定位置没有找到你想要获取的文件 1 检查你的文件名是否正确 2 你存文件是否带了文件夹 如果带了文件夹 检查文件夹是否正确 本文仅作为笔记
  • List集合的加减操作

    文章目录 一 对List本身有改变 二 对List本身无改变 参考资料 一 对List本身有改变 概述 List1 addAll List2 List1与List2两个集合相加 返回boolean值 原有List1值有变化 List2不变
  • 1-9 人机交互的角度

    操作系统的人机交互部分 OS改善人机界面 为用户使用计算机提供良好的环境 人机交互设备包括传统的终端设备和新型的模式识别设备 OS的人机交互部分用于控制有关设备运行和理解执行设备传来的命令 人机交互功能是决定计算机系统友善性的重要因素 是当
  • 机器学习算法GBDT的面试要点总结-上篇

    1 简介 gbdt全称梯度提升决策树 在传统机器学习算法里面是对真实分布拟合的最好的几种算法之一 在前几年深度学习还没有大行其道之前 gbdt在各种竞赛是大放异彩 原因大概有几个 一是效果确实挺不错 二是即可以用于分类也可以用于回归 三是可