Course2-Week4-决策树

news2024/11/18 13:48:45

Course2-Week4-决策树

文章目录

  • Course2-Week4-决策树
    • 1. 决策树的直观理解
    • 2. 构建单个决策树
      • 2.1 熵和信息增益
      • 2.2 构建决策树——二元输入特征
      • 2.3 构建决策树——多元输入特征
      • 2.4 构建决策树——连续的输入特征
      • 2.5 构建回归树——连续的输出结果(选修)
      • 2.6 代码实现-递归构建单个决策树
    • 3. 决策树集合
      • 3.1 使用决策树集合
      • 3.2 袋装决策树
      • 3.3 随机森林
      • 3.4 XGBoost算法
      • 3.5 何时使用决策树

  • 笔记主要参考B站视频“(强推|双字)2022吴恩达机器学习Deeplearning.ai课程”。
  • 该课程在Course上的页面:Machine Learning 专项课程
  • 课程资料:“UP主提供资料(Github)”、或者“我的下载(百度网盘)”。
  • 本篇笔记对应课程 Course2-Week4(下图中深紫色)。

1. 决策树的直观理解

  “神经网络”和“决策树/决策树集合”都被广泛应用于很多商业应用,并且在各类机器学习比赛中也取得了很好的成绩。但相比于“神经网络”,“决策树/决策树集合”却并没有在学术界引起很多关注。本周就来介绍“决策树/决策树集合”这个非常强大的工具。

【问题1】“识别猫”:二元分类,对于给定的特征,判断是否为猫。

  • 输入特征:“耳朵形状”、“脸型”、“胡须”。
  • 输出:是否为猫。
  • 默认数据集:三个“二元输入特征”,对应一个“二元输出结果”。

  “决策树(decision tree)”采用“二叉树”的结构,从根节点(root node)开始,不断地进行一系列判断,最终到达叶子节点(leaf node),也就是预测结果。上面的“识别猫”问题将贯穿本周,用于帮助我们理解“决策树”中的概念。比如针对“识别猫”的数据集,我们可以构建如下所示的“决策树”,此时有一个新的输入,就可以按照该“决策树”进行推理:

图2-4-1 构建“决策树”并使用“决策树”进行推理
  • 节点(node):树中的任何一个点都称为“节点”,也就是上图中所有的椭圆或矩形。
  • 根节点(root node):最顶部的节点,也就是最顶部的椭圆,
  • 决策节点(decision node):除了根节点外所有的椭圆,
  • 叶子节点(leaf node):最下面一层的所有矩形。
  • 深度(depth):从根节点到到达最下层的叶子节点,所经过的节点数。上图深度为2。

可以看到按照“决策树”的判断过程,这个新的输入最终被预测为猫,符合预期。但显然,对于当前给定的训练集,若没有其他约束条件的话,上述问题的决策树显然不止一种,如下图:

图2-4-2 各种各样的决策树

在上述这些不同的决策树当中,某些性能很好、某些性能很差。所以“决策树学习算法”就是,在所有可能的决策树中,找出当前数据集所对应的性能最好的决策树模型。下面是我们需要考虑的两条准则:

  1. 如何选择在每个节点使用什么特征进行拆分?
  • 希望拆分后,能尽可能的区分不同的结果 y y y,理想状态就是所有子集都各自是不同种类 y y y 的集合。也就是拆分后,希望尽可能的减少信息的“不确定度。比如在图2-4-1中,由于使用“Ear shape”进行拆分可以使“猫”尽量集中于同一个子集中,“不确定度”最小,所以选择其为根节点。后面会介绍如何计算这种“不确定度”。
  1. 什么时候停止拆分?
  • 子集被完全区分,如上图2-4-1。
  • 达到设置的最大深度。
  • 降低的“不确定度”低于某个阈值。
  • 当前节点的子集大小低于某个阈值(某个数)。

注1:树不应太深、太大,否则有过拟合的风险。
注2:第二节会详细介绍构建“决策树”的步骤。

本节 Quiz

  1. Based on the decision tree shown in the lecture, if an animal has floppy ears, a round face shape and has whiskers, does the model predict that it’s a cat or not a cat?
    √ Cat
    × Not a cat

  2. Take a decision tree learning to classify between spam and non-spam email. There are 20 training examples at the root note, comprising 10 spam and 10 non-spam emails. If the algorithm can choose from among four features, resulting in four corresponding splits, which would it choose (i.e., which has highest purity)?
    × Left split: 5of 10 emails are spam. Right split: 5 of 10 emails are spam.
    × Left split: 2 of2 emails are spam. Right split: 8 of 18 emails are spam.
    × Left split: 7 of 8 emails are spam. Right split: 3 of 12 emails are spam.
    √ Left split: 10 of 10 emails are spam. Right split: 0 of 10 emails are spam.

2. 构建单个决策树

2.1 熵和信息增益

熵(杂质)

  前面提到希望每次在节点进行拆分时,都尽可能的降低信息的“不确定度”,也就是尽可能提升信息的“纯度(purity)”。这个“不确定度”使用“熵(entropy)”来进行计算,下面是“熵”的计算公式和曲线。由于“熵”的物理意义就是“信息的不确定度/不纯的程度”,所以机器学习中又喜欢称“熵”为“杂质(impurity)”。这些都只是花里胡哨的名字而已,只需要记住:

  • “熵”就是“杂质”,表示信息的混乱程度,也就是“不纯”的程度。

注:逻辑回归中的“二元交叉熵损失函数”就来自于“熵”的计算。

Entropy: H ( P ) = − ∑ a l l    i p i l o g 2 ( p i ) ⟹ 二元分类 H ( p 1 ) = − p 1 l o g 2 ( p 1 ) − ( 1 − p 1 ) l o g 2 ( 1 − p 1 ) \begin{aligned} \text{Entropy:} \quad H(P) = -\sum_{all\;i}p_ilog_2(p_i) \overset{二元分类}{\Longrightarrow} H(p_1) = -p_1log_2(p_1) - (1-p_1)log_2(1-p_1) \end{aligned} Entropy:H(P)=allipilog2(pi)二元分类H(p1)=p1log2(p1)(1p1)log2(1p1)

图2-4-3 “熵”的示意图

  注意,除了“熵”之外,还有其他方法来衡量“信息不纯的程度”,比如开源软件包中会提供“Gini指数”。它表示从数据集中随机选择两个样本,其类别标签不一致的概率,下面是其计算公式。但是为了首先掌握决策树的构建过程,而不是让过多的琐碎的概念困扰,本课程我们就只用“熵”来表示信息的“不纯度”
Gini index: G ( P ) = 1 − ∑ a l l    i p i 2 ⟹ 二元分类 G ( p 1 ) = 1 − p 1 2 − ( 1 − p 1 ) 2 = 2 p 1 ( 1 − p 1 ) \text{Gini index:} \quad G(P) = 1 -\sum_{all\;i}p_i^2 \overset{二元分类}{\Longrightarrow} G(p_1) = 1- p_1^2 - (1-p_1)^2 = 2p_1(1-p_1) Gini index:G(P)=1allipi2二元分类G(p1)=1p12(1p1)2=2p1(1p1)

信息增益

  每次拆分都应最大程度的减少信息的不确定度,也就是“熵”,而减少的“熵”的大小则被称为“信息增益”。通信人表示,这些又双叒叕是花里胡哨的名字,只要记住 “信息增益”就是拆分前后减少的不确定度。注意拆分后信息的不确定度,应该为两分支的熵的加权平均,权值就是 拆分后各分支的子集大小 占 拆分前的集合大小 的比例。下面给出计算公式:

Information Gain = H ( p 1 root ) − ( w left H ( p 1 left ) + w right H ( p 1 right ) ) \text{Information Gain} = H(p_1^{\text{root}}) - \left(w^{\text{left}} H(p_1^{\text{left}}) + w^{\text{right}} H(p_1^{\text{right}})\right) Information Gain=H(p1root)(wleftH(p1left)+wrightH(p1right))

  • H ( p 1 root ) H(p_1^{\text{root}}) H(p1root):拆分前的不确定度。
  • w left w^{\text{left}} wleft:拆分后,左分支的集合大小。
  • w right w^{\text{right}} wright:拆分后,右分支的集合大小。
  • H ( p 1 left ) H(p_1^{\text{left}}) H(p1left):拆分后,左分支的不确定度。
  • H ( p 1 right ) H(p_1^{\text{right}}) H(p1right):拆分后,右分支的不确定度。
图2-4-4 选择根节点——三个特征的信息增益计算

显然,在三种“二元输入特征”中,“Ear shape”的“信息增益”最大,所以选为根节点。

2.2 构建决策树——二元输入特征

构建(二元输入特征)决策树的过程:

  1. 在根节点,找出最大的“信息增益”所对应的特征,作为拆分标准。
  2. 创建左右分支,各自找出剩余特征中“信息增益”最大的,作为各自的拆分标准。
  3. 不断向下进行拆分,直到:
  • “熵”为0,也就是完全分类。
  • 达到预设的最大深度。可以使用“验证集”选择最合适的深度
  • 所有剩余特征的“信息增益”都低于某个阈值。
  • 子集的大小低于某个阈值(某个数)。

注1:停止拆分是为了保证树不会变的太大、太笨重,进而降低过拟合的风险。
注2:上述算法可以使用“递归”。
注3:在构建过程中,左右分支可能会选取相同的特征

图2-4-5 构建决策树的过程——“识别猫”问题

2.3 构建决策树——多元输入特征

  若想针对“多元输入特征”构建决策树,可能会有如下针对“二元输入特征”决策树的改进思路:

  1. 创建多分支【不推荐】。整体思路和前面一样,只不过某些节点可能是多分支,但由于每个输入特征的可选种类不一定相同,这种方法会增加计算难度和代码量。
  2. 将“多元特征”转换成“独热码(One-hot)”【推荐】:不仅可以继续使用之前二元特征的决策树思路,甚至也可以转换成神经网络的训练模式。

注:由于每个样本的码字中只有一个“1”,所以称之为“独热码”。

比如下面的“耳朵形状(Ear shape)”有三种可能取值“尖的(Pointy)”、“松软的(Floppy)”、“椭圆形的(Oval)”,将其转换成独热码后,相当于将1个“三元输入特征”转化成3个“二元输入特征”,于是我们只需要对训练集进行一小步预处理,即可复用上述“二元输入特征”的思路:

图2-4-6 将“多元特征”转换成“独热码”

2.4 构建决策树——连续的输入特征

  和上一小节类似,也是将“连续输入特征”转换成“二元输入特征”,然后继续进行构建。但不同的是,“多元特征”只需在最开始进行预处理,而在没被当前所在分支使用前,“连续输入特征”需要在每个节点都进行一次计算。具体来说,就是选择一个阈值,依照该阈值对当前节点的集合进行拆分,可以使“信息增益”最大,不同节点所计算的阈值可能不同。于是,就可以将“连续输入特征”转换成判断大小的“二元输入特征”。比如在“识别猫”问题中,引入“重量”这一连续取值的输入特征,由于选取“9”作为阈值可以使“信息增益”最大,于是便将“重量”这一“连续输入特征”,转换成“是否小于等于9磅?”这个“二元输入特征”:

图2-4-7 利用“信息增益”将“连续特征”转换成“判断”

2.5 构建回归树——连续的输出结果(选修)

  本小节将“决策树(decision trees)”算法推广到“回归树(regression trees)”,也就是将“决策树”的预测结果扩展到连续的取值。和之前的“拆分后尽可能减少信息的不确定度”类似,“回归树”使用“方差(variance)”来衡量信息的不确定度。于是,拆分后的方差为左右两分支的方差的加权平均,权值也是 左右分支的子集大小 占 拆分前集合大小 的比例。相应的“信息增益”为:

Information gain = V ( s root ) − ( w left V ( s left ) + w right V ( s right ) ) \text{Information gain} = V(s^{\text{root}}) - \left(w^{\text{left}} V(s^{\text{left}}) + w^{\text{right}} V(s^{\text{right}})\right) Information gain=V(sroot)(wleftV(sleft)+wrightV(sright))

  • V ( s root ) V(s^{\text{root}}) V(sroot):拆分前的集合数据的方差。
  • w left w^{\text{left}} wleft:拆分后,左分支的集合大小。
  • w right w^{\text{right}} wright:拆分后,右分支的集合大小。
  • V ( s left ) V(s^{\text{left}}) V(sleft):拆分后,左分支的集合数据的方差。
  • V ( s right ) V(s^{\text{right}}) V(sright):拆分后,右分支的集合数据的方差。

注:通信人表示,“信息增益”只是一个泛在的概念,虽然上述定义和2.1节不同,但物理意义相通。

  回到“识别猫”问题,现在将“重量”作为需要预测的结果(如下左图)。于是,在每次进行拆分时,就使用“方差”来计算“信息增益”,并选择“信息增益”最大的特征作为当前节点的拆分标准。最后达到终止拆分条件,“决策树”构建完成时,直接使用最终分类的均值作为以后的预测值

图2-4-8 每次拆分都尽可能的减少方差
图2-4-9 使用均值作为当前分支的预测结果

2.6 代码实现-递归构建单个决策树

  最后一个小节来使用代码构建单个决策树。注意本练习完全手敲实现前面几节的原理,不调用任何封装好的机器学习库函数,问题要求和代码结构如下:

问题要求:根据下表2-4-1所给出的数据集,构建一个决策树,判断蘑菇是否可以食用。

代码结构

  • 函数1:计算01序列的熵
  • 函数2:按照给定特征分割,返回左右子节点的列表
  • 函数3:计算信息增益
  • 函数4:找到信息增益最大的特征
  • 函数5:递归的构建决策树
  • 主函数:定义训练集,然后直接调用“函数5”,观察其打印输出的决策树结构。

注1:主函数中还有上述5个子函数的测试代码,在下面代码中被注释,但是代码运行结果中有其正确的测试输出。
注2:本实验来自本周的练习“C2_W4_Decision_Tree_with_Markdown”。
注3:不可将本实验作为实际的可食用蘑菇鉴别标准!!!

表2-4-1 数据集
Cap Color
伞盖颜色
Stalk Shape
茎秆形状
Solitary
独株?
Edible
可食用?
BrownTaperingYes1
BrownEnlargingYes1
BrownEnlargingNo0
BrownEnlargingNo0
BrownTaperingYes1
RedTaperingYes0
RedEnlargingNo0
BrownEnlargingYes1
RedTaperingNo1
BrownEnlargingNo0

下面是Python代码和打印输出的结果:

import numpy as np
#################################################################################
# 函数1:计算01序列的熵
def compute_entropy(y):
    """
    Computes the entropy for 
    
    Args:
       y (ndarray): Numpy array indicating whether each example at a node is
           edible (`1`) or poisonous (`0`)
       
    Returns:
        entropy (float): Entropy at that node
        
    """
    # 排除特殊情况
    if(len(y)==0):
        return 0.0
    
    # 正常计算
    p1 = y.sum()/y.size
    # print(p1)
    if(p1==0 or p1==1):
        return 0.0
    else:
        entropy = -p1*np.log2(p1)-(1-p1)*np.log2(1-p1)
        return entropy

#################################################################################
# 函数2:按照给定特征分割,返回左右子节点的列表
def split_dataset(X, node_indices, feature):
    """
    Splits the data at the given node into left and right branches
    
    Args:
        X (ndarray):             Data matrix of shape(n_samples, n_features)
        node_indices (ndarray):  List containing the active indices. I.e, the samples being considered at this step.
        feature (int):           Index of feature to split on
    
    Returns:
        left_indices (ndarray): Indices with feature value == 1
        right_indices (ndarray): Indices with feature value == 0
    """
    # 定义列表
    left_indices = []
    right_indices = []
    # 按照给定特征分割
    for i in node_indices:
        if(X[i][feature]):
            left_indices.append(i)
        else:
            right_indices.append(i)
    # 返回左右列表
    return left_indices, right_indices

#################################################################################
# 函数3:计算信息增益
def compute_information_gain(X, y, node_indices, feature):
    
    """
    Compute the information of splitting the node on a given feature
    
    Args:
        X (ndarray):            Data matrix of shape(n_samples, n_features)
        y (array like):         list or ndarray with n_samples containing the target variable
        node_indices (ndarray): List containing the active indices. I.e, the samples being considered in this step.
        feature (int):          Index of feature to split on
   
    Returns:
        cost (float):        Cost computed
    
    """
    # 排除意外情况
    if(len(node_indices)==0):
        return 0.0
    # Split dataset
    left_indices, right_indices = split_dataset(X, node_indices, feature)
    # root entropy
    H_root = compute_entropy(y[node_indices])
    # Weights 
    w_left = len(left_indices) / len(node_indices)
    w_right = len(right_indices) / len(node_indices)
    # Weighted entropy
    H_left = compute_entropy(y[left_indices])
    H_right = compute_entropy(y[right_indices])
    #Information gain                                                   
    information_gain = H_root - (w_left*H_left + w_right*H_right)    
    return information_gain

#################################################################################
# 函数4:找到信息增益最大的特征
def get_best_split(X, y, node_indices):   
    """
    Returns the optimal feature and threshold value to split the node data 
    
    Args:
        X (ndarray):            Data matrix of shape(n_samples, n_features)
        y (array like):         list or ndarray with n_samples containing the target variable
        node_indices (ndarray): List containing the active indices. I.e, the samples being considered in this step.

    Returns:
        best_feature (int):     The index of the best feature to split
    """    
    
    best_feature = -1           # 最佳的拆分特征
    info_gain = np.array([])    # 所有剩余特征的信息增益
    num_features = X.shape[1]   # 特征总数
    # 遍历计算所有特征对应的信息增益
    for i in range(num_features):
        info_gain = np.append(info_gain, compute_information_gain(X, y, node_indices, i))
    # 找到最大的信息增益并返回
    if(info_gain.max() != 0):
        best_feature = info_gain.argmax()
    return best_feature

#################################################################################
# 函数5:递归的构建决策树
def build_tree_recursive(X, y, node_indices, branch_name, max_depth, current_depth):
    """
    Build a tree using the recursive algorithm that split the dataset into 2 subgroups at each node.
    This function just prints the tree.
    
    Args:
        X (ndarray):            Data matrix of shape(n_samples, n_features)
        y (array like):         list or ndarray with n_samples containing the target variable
        node_indices (ndarray): List containing the active indices. I.e, the samples being considered in this step.
        branch_name (string):   Name of the branch. ['Root', 'Left', 'Right']
        max_depth (int):        Max depth of the resulting tree. 
        current_depth (int):    Current depth. Parameter used during recursive call.
    """ 

    # Maximum depth reached - stop splitting
    if current_depth == max_depth:
        formatting = " "*current_depth + "-"*current_depth
        print(formatting, "%s leaf node with indices" % branch_name, node_indices)
        return
   
    # Otherwise, get best split and split the data
    # Get the best feature and threshold at this node
    best_feature = get_best_split(X, y, node_indices)
    tree = []
    tree.append((current_depth, branch_name, best_feature, node_indices))
    
    formatting = "-"*current_depth
    print("%s Depth %d, %s: Split on feature: %d" % (formatting, current_depth, branch_name, best_feature))
    
    # Split the dataset at the best feature
    left_indices, right_indices = split_dataset(X, node_indices, best_feature)
    
    # continue splitting the left and the right child. Increment current depth
    build_tree_recursive(X, y, left_indices, "Left", max_depth, current_depth+1)
    build_tree_recursive(X, y, right_indices, "Right", max_depth, current_depth+1)

####################################主函数######################################
# 定义训练集
X_train = np.array([[1,1,1],[1,0,1],[1,0,0],[1,0,0],[1,1,1],[0,1,1],[0,0,0],[1,0,1],[0,1,0],[1,0,0]])
y_train = np.array([1,1,0,0,1,0,0,1,1,0])
# print ('The shape of X_train is:', X_train.shape)
# print ('The shape of y_train is: ', y_train.shape)
# print ('Number of training examples (m):', len(X_train))
# 有效样本的索引
root_indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 全部包括则表示全有效
# 递归构建决策树
build_tree_recursive(X_train, y_train, root_indices, "Root", max_depth=2, current_depth=0)

# # 测试函数:计算熵
# print("\n测试函数:计算熵")
# print("Entropy at root node: ", compute_entropy(y_train)) 
# # 测试函数:给定特征拆分
# print("\n测试函数:给定特征拆分")
# feature = 0
# left_indices, right_indices = split_dataset(X_train, root_indices, feature)
# print("Left indices: ", left_indices)
# print("Right indices: ", right_indices)
# # 测试函数:给定特征,计算信息增益
# print("\n测试函数:给定特征,计算信息增益")
# info_gain0 = compute_information_gain(X_train, y_train, root_indices, feature=0)
# print("Information Gain from splitting the root on brown cap: ", info_gain0)
# info_gain1 = compute_information_gain(X_train, y_train, root_indices, feature=1)
# print("Information Gain from splitting the root on tapering stalk shape: ", info_gain1)
# info_gain2 = compute_information_gain(X_train, y_train, root_indices, feature=2)
# print("Information Gain from splitting the root on solitary: ", info_gain2)
# # 测试函数:计算信息增益最大的特征
# print("\n测试函数:计算信息增益最大的特征")
# best_feature = get_best_split(X_train, y_train, root_indices)
# print("Best feature to split on: %d" % best_feature)
 Depth 0, Root: Split on feature: 2
- Depth 1, Left: Split on feature: 0
  -- Left leaf node with indices [0, 1, 4, 7]
  -- Right leaf node with indices [5]
- Depth 1, Right: Split on feature: 1
  -- Left leaf node with indices [8]
  -- Right leaf node with indices [2, 3, 6, 9]

测试函数:计算熵
Entropy at root node:  1.0

测试函数:给定特征拆分
Left indices:  [0, 1, 2, 3, 4, 7, 9]
Right indices:  [5, 6, 8]

测试函数:给定特征,计算信息增益
Information Gain from splitting the root on brown cap:  0.034851554559677034
Information Gain from splitting the root on tapering stalk shape:  0.12451124978365313
Information Gain from splitting the root on solitary:  0.2780719051126377

测试函数:计算信息增益最大的特征
Best feature to split on: 2

本节 Quiz

  1. At a given node of a decision tree, , 6 of 10 examples are cats and 4 of 10 are not cats. Which expression calculates the entropy H ( p 1 ) H(p_1) H(p1) of this group of 10 animals?
    × − ( 0.6 ) l o g 2 ( 0.6 ) − ( 1 − 0.4 ) l o g 2 ( 1 − 0.4 ) -(0.6)log_2(0.6)-(1-0.4)log_2(1-0.4) (0.6)log2(0.6)(10.4)log2(10.4)
    × ( 0.6 ) l o g 2 ( 0.6 ) + ( 0.4 ) l o g 2 ( 0.4 ) (0.6)log_2(0.6)+(0.4)log_2(0.4) (0.6)log2(0.6)+(0.4)log2(0.4)
    × ( 0.6 ) l o g 2 ( 0.6 ) + ( 1 − 0.4 ) l o g 2 ( 1 − 0.4 ) (0.6)log_2(0.6)+(1-0.4)log_2(1-0.4) (0.6)log2(0.6)+(10.4)log2(10.4)
    − ( 0.6 ) l o g 2 ( 0.6 ) − ( 0.4 ) l o g 2 ( 0.4 ) -(0.6)log_2(0.6)-(0.4)log_2(0.4) (0.6)log2(0.6)(0.4)log2(0.4)

  2. Before a split, the entropy of a group of 5 cats and 5 non-cats is H ( 5 10 ) H(\frac{5}{10}) H(105). After splitting on a particular feature, group of 7 animals (4 of which are cats) has an entropy of H ( 4 7 ) H (\frac{4}{7}) H(74). The other group of 3 animals (1 is a cat) and has an entropy of H ( 1 3 ) H(\frac{1}{3}) H(31). What is the expression for information gain?
    × H ( 0.5 ) − ( 7 ∗ H ( 4 7 ) + 3 ∗ H ( 1 3 ) ) H(0.5)-(7*H(\frac{4}{7})+3*H(\frac{1}{3})) H(0.5)(7H(74)+3H(31))
    H ( 0.5 ) − ( 7 10 H ( 4 7 ) + 3 10 H ( 1 3 ) ) H(0.5)-(\frac{7}{10}H(\frac{4}{7})+\frac{3}{10}H(\frac{1}{3})) H(0.5)(107H(74)+103H(31))
    × H ( 0.5 ) − ( H ( 4 7 ) + H ( 1 3 ) ) H(0.5)-(H(\frac{4}{7})+ H(\frac{1}{3})) H(0.5)(H(74)+H(31))
    × H ( 0.5 ) − ( 4 7 H ( 4 7 ) + 1 3 H ( 1 3 ) H(0.5)-(\frac{4}{7}H(\frac{4}{7})+\frac{1}{3}H(\frac{1}{3}) H(0.5)(74H(74)+31H(31)

  3. To represent 3 possible values for the ear shape, you can define 3 features for ear shape: pointy ears, floppy ears, oval ears. For an animal whose ears are not pointy, not floppy, but are oval, how can you represent this information as a feature vector?
    × [1,1,0]
    × [1,0,0]
    × [0,1,0]
    √ [0,0,1]

  4. For a continuous valued feature (such as weight of the animal), there are 10 animals in the dataset. According to the lecture, what is the recommended way to find the best split for that feature?
    × Use a one-hot encoding to turn the feature into a discrete feature vector of 0’s and 1’s, then apply the algorithm we had discussed for discrete features.
    √ Choose the 9 mid-points between the 10 examples as possible splits, and find the split that gives the highest information gain.
    × Try every value spaced at regular intervals (e.g. 8, 8.5, 9, 9.5, 10, etc.) and find the split that gives the highest information gain.
    × Use gradient descent to find the value of the split threshold that gives the highest information gain.

  5. Which of these are commonly used criteria to decide to stop splitting? (Choose two.)
    √ When the number of examples in a node is below a threshold.
    × When a node is 50% one class and 50% another class (highest possible value of entropy).
    √ When the tree has reached a maximum depth.
    × When the information gain from additional splits is too large.

3. 决策树集合

  上一节已经详细的讨论了如何构建单个“决策树”。事实上,如果训练很多“决策树”组成“决策树集合(dicision tree ensemble)”,那么会得到更准确、更稳定的预测结果。下面就来介绍几种构建“决策树集合”的方法。

3.1 使用决策树集合

  使用单个决策树完成任务时,有一个很大的缺点:单个决策树对于训练集的微小变化非常敏感。比如下图中,只是替换了训练集中的单个样本,就导致训练出完全不一样的决策树:

图2-4-10 单个决策树对于训练集敏感

对于一个新的输入,不同的决策树很可能会有不同的预测结果。于是为了使算法更强壮,我们就需要创建不同的训练集,构建出不同的决策树组成“决策树集合(dicision tree ensemble)”。对于新的输入,使用这个“决策树集合”对所有输出结果进行投票,选择最有可能的结果,于是就可以降低算法对于单个决策树的依赖程度,也就可以降低了对于数据的敏感程度:

图2-4-11 使用“决策树集合”进行投票

下面三小节就来介绍三种常见的构建“决策树集合”的方法,主要区别在于单个决策树的训练集选择策略不同

3.2 袋装决策树

  最简单的构建不同训练集的方法,就是“有放回抽样(sampling with replacement)”。假设原始训练集大小为 m m m,每次训练前都随机地有放回抽取 m m m 次样本,作为本次的训练集:

图2-4-12 构建单次训练集——有放回抽样

于是我们便可以创建出,有微小不同的多个训练集。注意到,单次的抽取结果中,可以有重复的样本。上面这种方法就称为“袋装决策树(bagged decision tree)”:

袋装决策树”创建方法:

  • 假设原始训练集大小为 m m m,并且“决策树集合”的大小为 B B B (bag),于是
for b = 1 to B:
    1. 从原始训练集有放回抽取m次,形成本次训练集。
    2. 然后使用该训练集训练单个决策树。

注: B B B 一般取64~128,选取更大的 B B B 可能会提升算法性能,但当 B B B 超过100后就不会有太大的性能增益。

3.3 随机森林

  “袋装决策树”有个缺点,就是很多决策树在根节点或者根节点附近的区域都非常相似。于是为了避免这个问题,在上述“袋装决策树”的基础上,训练单个决策树时,对于每个节点都会从 n n n 个特征中随机选取 k k k 个特征组成子集,然后在这个子集中选取最大的“信息增益”( k < n k<n k<n)。一般来说,都会取 k = n k=\sqrt{n} k=n 。于是,每次的训练集都是随机选取的,单个决策树的每个节点特征都是从随机选取的子集中选取的,这便称为“随机森林(random forest)”。
  正是这些由“随机选取”产生的微小变动组合在一起,使得“随机森林”比单个决策树更加健壮,于是训练集的任何微小变化都不会对随机森林的输出有太大的影响。

随机森林”创建方法:

  • 假设原始训练集大小为 m m m、特征总数为 n n n、“决策树集合”的大小为 B B B (bag),于是
for b = 1 to B:
    1. 从原始训练集有放回抽取m次,形成本次训练集。
    2. 然后使用该训练集训练单个决策树。
          选择单个节点拆分标准时,随机选取k个特征进行计算。

注1: B B B 一般取64~128,选取更大的 B B B 可能会提升算法性能,但当 B B B 超过100后就不会有太大的性能增益。
注2:一般取 k = n k=\sqrt{n} k=n
【轻松一刻】Where does a machine learning engineer go camping?  Answer: In a random forest.

3.4 XGBoost算法

  下面介绍比“随机森林(Random forest)”更强的算法——梯度提升树(Gradient boost tree)。每次抽取新的训练集时,都以更高概率选择上一次决策树训练出错的样本。这就是“增强(boosting)”的含义,类似于“刻意练习”。具体的增加多少概率的数学过程是非常复杂的,本课程不过多讨论,会用就行。“XGBoost(eXtreme Gradient Boosting, 极限梯度提升算法)”就是“梯度提升树”的一种,下面是其特点:

  • XGBoost已经集成好开源库,调用简单。
  • 非常快速和高效。
  • 内置了选择单次训练集的方法,所以无需手动为每次训练生成训练集。
  • 对于“拆分标准”、“停止拆分标准”有很好的默认选项。
  • 内置了正则化防止过拟合。
  • 机器学习竞赛中表现出色,如Kaggle。“XGBoost”和“深度学习”算法是在竞赛表现优异的两大算法。

  多年以来,研究人员提出了很多构建决策树、选取决策树样本的方法。迄今为止,构建决策树集合最常用的方法就是“XGBoost算法”。它运行速度快、开源、易于使用,在很多机器学习比赛、商业应用中广泛使用。XGBoost的内部实现原理非常复杂,所以大家都是直接调用封装好的XGBoost库:

# 分类问题
from xgboost import XGBClassfier
model = XGBClassfier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

# 回归问题
from xgboost import XGBRegressor
model = XGBRegressor()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

3.5 何时使用决策树

本周最后一小节来总结一下“决策树/决策树集合”、“神经网络”各自的适用场景:

决策树/决策树集合:

  • 适用于“结构化数据”,如“房价预测”问题。不建议处理“非结构化数据”,如“图像”、“视频”、“音频”、“文本”等。并且可以处理分类问题、回归问题。
  • 训练速度非常快
  • 对于人类来说更容易理解,比如小型的决策树可以直接打印出来查看决策过程。
  • 缺点是一次只能训练一个决策树,且不支持传统的迁移学习

神经网络:

  • 适合处理所有类型的数据,无论是“结构化数据”还是“非结构化数据”,或者是两者的混合数据。也可以处理分类问题、回归问题。
  • 训练速度较慢
  • 使用迁移学习可以快速完成“预训练”。
  • 可连接性好。几个神经网络可以很容易的串联或并联在一起,组成一个更大的模型进行训练。

注1:老师建议训练“决策树”时直接调用XGBoost库,尽管可能会需要更多的运算资源,但是非常快捷、准确。
注2:“结构化数据”指的是那些可以使用电子表格表示的数据。

本节 Quiz

  1. For the random forest, how do you build each individual tree so that they are not all identical to each other?
    × Train the algorithm multiple times on the same training set. This will naturally result in different trees.
    × Sample the training data without replacement.
    × If you are training B B B trees, train each one on 1 / B 1/B 1/B of the training set, so each tree is trained on a distinct set of examples.
    √ Sample the training data with replacement.

  2. You are choosing between a decision tree and a neural network for a classification task where the input x x x is a 100x100 resolution image. Which would you choose?
    √ A neural network, because the input is unstructured data and neural networks typically work better with unstructured data.
    × A neural network, because the input is structured data and neural networks typically work better with structured data.
    × A decision tree, because the input is unstructured and decision trees typically work better with unstructured data.
    × A decision tree, because the input is structured data and decision trees typically work better with structured data.

  3. What does sampling with replacement refer to?
    × It refers to using a new sample of data that we use to permanently overwrite (that is, to replace) the original data.
    √ Drawing a sequence of examples where, when picking the next example, first replacing all previously drawn examples into the set we are picking from.
    × Drawing a sequence of examples where, when picking the next example, first remove all previously drawn examples from the set we are picking from.
    × It refers to a process of making an identical copy of the training set.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1298640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于K-means与CNN的遥感影像分类方法

基于K-means与CNN的遥感影像分类 一、引言 1.研究背景 航天遥感技术是一种通过卫星对地观测获取遥感图像信息数据的技术&#xff0c;这些图像数据在各领域都发挥着不可或缺的作用。遥感图像分类主要是根据地面物体电磁波辐射在遥感图像上的特征&#xff0c;判断识别地面物体的属…

BUUCTF pwn rip WriteUp

文件分析 下载附件&#xff0c;分析文件 可以看到是64位ELF文件&#xff0c;elf可以理解为Linux中的可执行文件&#xff0c;就像Windows中的exe文件 用ida打开文件 查看main函数的伪代码&#xff0c;可以看到有一个15位的字符数组&#xff0c;该数组通过gets函数传值 还有一…

Jupyter notebook修改背景主题

打开Anaconda Prompt&#xff0c;输入以下内容 1. pip install --upgrade jupyterthemes 下载对应背景主题包 出现Successfully installed jupyterthemes-0.20.0 lesscpy-0.15.1时&#xff0c;说明已经下载安装完成 2. jt -l 查看背景主题列表 3. jt -t 主题名称&#xff08;…

AI:92-基于深度学习的红外图像人体检测

🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的核心代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在不断更新…

SQL命令---修改字段的数据类型

介绍 使用sql语句修改字段的数据类型。 命令 alter table 表明 modify 字段名 数据类型;例子 有一张a表&#xff0c;表里有一个id字段&#xff0c;长度为11。使用命令将长度修改为12 下面使用命令进行修改&#xff1a; alter table a modify id int(12) NOT NULL;下面使修…

【Dubbo3云原生微服务开发实战】「Dubbo前奏导学」 RPC服务的底层原理和实现

RPC服务 RPC服务介绍RPC通信模式RPC架构组成RPC技术要点RPC通信技术选项分析RPC实战开发6大基础组件基础组件之Guava基础组件之Hutools基础组件之ReflectionASM基础组件之FastJSON/FastJSON2基础组件之FST相比FastJSON的优势 基础组件之Commons-Codec RPC框架层面选项分析RPC组…

STM32-TIM定时器中断

目录 一、TIM&#xff08;Timer&#xff09;定时器简介 二、定时器类型 2.1基本定时器结构 2.2通用定时器结构 2.3高级定时器结构 三、定时中断基本结构 四、时序图分析 4.1 预分频器时序 4.2 计数器时序 4.3 计数器无预装时序&#xff08;无影子寄存器&#xff09; …

LVGL_V8.3入门二---实时时钟(模仿华为watch-UI)

系列文章目录 文章目录 系列文章目录前言一、实现效果二、代码解析 前言 在这个博客中&#xff0c;我们将深入探讨LVGL&#xff08;Light and Versatile Graphics Library&#xff09;版本8.3的实时时钟应用&#xff0c;以模仿华为 Watch UI 为例。LVGL是一款专为嵌入式系统和…

Jenkins简单介绍

学习目标 知道jenkins应用场景能够安装部署jenkins服务器能够实现gitgithubjenkins手动构建能够实现gitgitlabjenkins自动发布系统 认识jenkins Jenkins是一个可扩展的持续集成引擎&#xff0c;是一个开源软件项目&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软…

Kafka集成springboot

安装kafka&#xff0c;直接到官网下载bin文件&#xff0c;本文使用windows进行使用kafka。 下载之后&#xff0c;第一步&#xff0c;启动zookeeper&#xff1a; zookeeper-server-start.bat ..\..\config\zookeeper.properties 第二步&#xff0c;启动kafka&#xff1a; kafka…

oops-framework框架 之 多语言设置文本、精灵和骨骼动画

引擎&#xff1a; CocosCreator 3.8.0 环境&#xff1a; Mac Gitee: oops-plugin-excel-to-json 注&#xff1a; 作者dgflash的oops-framework框架QQ群&#xff1a; 628575875 简介 作者dgflash在oops-framework的框架中提供了多语言&#xff0c;主要用于对文本、图片、骨骼动…

Verilog基础:寄存器输出的两种风格

相关文章 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 Verilog中的寄存器操作一般指的是那些对时钟沿敏感而且使用非阻塞赋值的操作。例如状态机中的状态转移&#xff0c;实际上就是一种寄存器操作&#xff0c;因为这相…

【docker 】centOS 安装docker

官网 docker官网 github源码 卸载旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 安装软件包 yum install -y yum-utils \device-mapper-persistent-data…

自下而上-存储全栈(TiDB/RockDB/SPDK/fuse/ceph/NVMe/ext4)存储技术专家成长路线

数字化时代的到来带来了大规模数据的产生&#xff0c;各行各业都面临着数据爆炸的挑战。 随着云计算、物联网、人工智能等新兴技术的发展&#xff0c;对存储技术的需求也越来越多样化。不同应用场景对存储的容量、性能、可靠性和成本等方面都有不同的要求。具备存储技术知识和技…

基于 Gin 的 HTTP 中间人代理 Demo

前面实现的代理对于 HTTPS 流量是进行盲转的&#xff0c;也就是说直接在 TCP 连接上传输 TLS 流量&#xff0c;但是我们无法查看或者修改它的内容。当然了&#xff0c;通常来说这也是不必要的。不过对于某些场景下还是有必要的&#xff0c;例如使用 Fiddler 进行抓包或者监控其…

Flink 本地单机/Standalone集群/YARN模式集群搭建

准备工作 本文简述Flink在Linux中安装步骤&#xff0c;和示例程序的运行。需要安装JDK1.8及以上版本。 下载地址&#xff1a;下载Flink的二进制包 点进去后&#xff0c;选择如下链接&#xff1a; 解压flink-1.10.1-bin-scala_2.12.tgz&#xff0c;我这里解压到soft目录 [ro…

redis之缓存穿透,击透,雪崩~

以下为一个我们正常的缓存流程&#xff1a; 缓存雪崩&#xff1a; 在双十一的时候&#xff0c;淘宝的首页访问量是非常大的&#xff0c;所以它的很多数据是放在redis缓存里面&#xff0c;对应redis中的key&#xff0c;假设设置了缓存失效的时间为3小时&#xff0c;超过这三个小…

视觉学习笔记12——百度飞浆框架的PaddleOCR 安装、标注、训练以及测试

系列文章目录 虚拟环境部署 参考博客1 参考博客2 参考博客3 参考博客4 文章目录 系列文章目录一、简单介绍1.OCR介绍2.PaddleOCR介绍 二、安装1.anaconda基础环境1&#xff09;anaconda的基本操作2&#xff09;搭建飞浆的基础环境 2.安装paddlepaddle-gpu版本1&#xff09;安装…

区块链实验室(29) - 关闭或删除FISCO日志

1. FISCO日志 缺省情况下&#xff0c;FISCO启动日志模块&#xff0c;日志记录的位置在节点目录中。以FISCO自带案例为例&#xff0c;4节点的FISCO网络&#xff0c;24个区块产生的日志大小&#xff0c;见下图所示。 2.关闭日志模块 当节点数量增大&#xff0c;区块高度增大时&…

利用Wix打包安装包

利用Wix打包安装包 背景具体步骤1、安装 WiX Toolset 工具集2、安装 WiX Toolset 系列 Visual Studio 插件3、创建Wix工程4、添加工程文件5、修改Product元素6、修改Package元素7、修改MajorUpgrade元素8、修改Media属性9、设置安装引导界面10、添加WPF项目文件11、添加桌面快捷…