机器学习和神经网络 - 页 69

 

5.5 Scikit-learn Transformer API(L05:使用 Scikit-Learn 进行机器学习)


5.5 Scikit-learn Transformer API(L05:使用 Scikit-Learn 进行机器学习)

在视频中,演示者深入探讨了使用 scikit-learn 中的实用程序准备训练数据集的过程,并介绍了转换器 API,它与之前视频中讨论的估算器 API 密切相关。 estimator API 主要用于监督学习模型,例如分类器和回归分析模型,而 transformer API 则专为数据转换而设计。

演示者首先解决与随机子抽样相关的问题,这涉及将数据集分为两个子集,通常是训练集和测试集。他们解释说,随机划分数据集会导致类别标签的分布发生变化,从而导致训练集和测试集中的类别错误表示。为了克服这一挑战,演示者建议使用分层拆分,以确保在子集中保持类别分布或比例。他们继续演示如何使用 scikit-learn 的 model_selection 子模块中的 train_test_split 函数实现分层拆分。

接下来,演示者深入探讨了数据规范化的概念,特别关注两种技术:最小-最大缩放和标准化。 Min-max scaling涉及缩放特征,使其所有值都落在0到1的范围内。演示者提供了min-max缩放的公式,即需要将特征列中的每个值减去最小特征值,然后除以它是由最大和最小特征值之间的差异。

相反,标准化涉及将特征转换为均值为零和标准差为一的特征。演示者解释了标准化公式,该公式包括将特征列中的每个值减去特征的均值,然后除以特征的标准差。他们提到标准化在机器学习中更常用,并且对某些优化算法特别有用。

为了说明最小-最大缩放和标准化的实际应用,演示者提供了使用玩具特征列的示例。他们强调,只要特征居中并且具有近似单位方差,在使用样本或总体标准差之间的选择不会显着影响机器学习结果。此外,他们还强调了使用从训练集中计算出的参数(均值和标准差)来缩放验证集和测试集的重要性,因为验证集和测试集代表看不见的数据。

该视频继续探索机器学习中数据转换和处理的各种技术。它承认对于像标准化这样的简单程序,手动执行转换是可行的,而不依赖于单独的库或高级技术。但是,对于特征选择、特征降维和特征提取等更复杂的转换,使用 Transformer API 等工具可以提供更大的便利性和效率。

接下来,演示者专注于处理分类数据。他们介绍了一个包含三个特征列和一个标签列的玩具数据集,强调分类变量可以分为两种类型:序数和名义变量。序数变量具有特定的顺序或层次结构,而名义变量则没有。例如,他们将“尺码”列突出显示为有序变量,其中 M、L 和 XXL 等 T 恤尺码显示出明确的顺序。为了处理序数变量,视频建议使用映射字典将值转换为数字表示。

另一方面,该视频将类标签作为名义分类数据的示例。由于类标签之间没有内在顺序,演示者建议使用标签编码器为每个标签分配唯一的整数值。标签编码器安装在类标签列上以创建映射字典,然后用于将字符串标签转换为整数标签。

对于像“颜色”这样没有暗示顺序的标称特征列,使用标签编码器可能会引入误导性信息。在这种情况下,视频引入了 one-hot 编码作为合适的替代方案。此技术涉及为标称特征列中的每个不同值创建一个新的特征列,并分配 0 和 1 以指示特定值的存在或不存在。提到删除其中一个生成的特征列可以在不丢失基本信息的情况下消除冗余。

该视频简要介绍了缺失数据并提出了一些基本的处理方法。一种策略涉及删除包含缺失值的行或列,如果它们随机出现并且不表示系统问题。这可以使用 pandas 库中的 dropna() 方法来完成。另一种方法是通过使用诸如 SimpleImputer 转换器之类的工具,使用均值或中位数等统计措施填补空白来估算缺失数据。然而,该视频警告说,应该仔细考虑插补,因为它可能会引入意想不到的偏见。

此外,该视频还提到了通过将问题视为监督学习任务来预测缺失值的可能性。在这种情况下,可以将缺失的特征列作为目标变量,将没有缺失数据的行作为训练数据来拟合回归模型。

该视频全面概述了数据转换技术,包括准备训练数据集的重要性、分层拆分的应用以及使用最小-最大缩放和标准化对数据进行归一化。它还包括处理分类数据、区分序数变量和名义变量,并介绍映射字典、标签编码器和单热编码等技术。此外,该视频还简要介绍了缺失数据并概述了删除或估算缺失值等方法,同时还提到了通过监督学习预测缺失值的可能性。

 

5.6 Scikit-learn 管道(L05:使用 Scikit-Learn 进行机器学习)



5.6 Scikit-learn 管道(L05:使用 Scikit-Learn 进行机器学习)

好了,各位,我们终于到了第 5 讲的最后一部分,在我看来,这是最有趣的部分:神圣的学习管道。这些管道是非常有用的对象或类,使我们能够无缝地结合数据处理和预测步骤。为了给您一个概览,我将展示管道工作原理的流程图,但我不会深入研究所有细节。

将管道视为带有转换器 API 的估算器。与估计器类似,管道有一个适合我们可以在训练集上使用的方法。在内部,流水线经过多个拟合和转换步骤,最终到达最后的拟合步骤。根据我们在管道中定义的内容,它可以执行各种任务,例如数据缩放(例如,标准化或最小-最大缩放)、降维、训练学习算法以及返回我们可以在测试集上使用的预测模型.

当我们在测试集上调用预测方法时,类似于估算器 API,管道在内部使用转换步骤来应用与在训练集上执行的相同的缩放。这确保了数据处理的一致性。最后,管道使用拟合模型进行预测,例如在分类器的情况下返回类标签。

让我用一个简单的管道代码示例来说明这一点。在这里,我使用 sacred learn 的 sklearn.pipeline 子模块中的 make_pipeline 函数创建了一个管道。这是创建管道的便捷方式。在此示例中,我正在构建一个由标准缩放器和 K 最近邻分类器组成的基本管道。正如我们在上一个视频中讨论的那样,标准缩放器通过使数据具有零均值和单位方差来标准化数据。我们将标准缩放器和 K 最近邻分类器初始化为管道的组件。

创建管道后,我们可以使用 fit 方法在训练数据上训练管道。然后,我们可以使用 predict 方法对测试集进行预测。当我们调用 fit 时,管道首先应用标准缩放器从训练数据中学习均值和标准差。然后它使用此信息来缩放数据,并将其传递到下一步,即 K 最近邻分类器。分类器接收标准化训练集并执行其学习算法。

在预测期间,会发生相同的过程,只是不需要拟合步骤。管道重新使用在训练期间学习的统计数据来缩放测试数据,并应用学习的分类器进行预测。

总而言之,管道允许我们将多个对象(例如转换器和估算器)链接在一起,以创建一个有凝聚力的工作流。它提供了一种方便高效的方式来处理机器学习任务中的数据处理和预测步骤。

现在,让我们通过应用模型选择的简单保持方法来了解实际的管道。模型选择涉及调整超参数以选择最佳模型。在 holdout 方法中,我们将数据分成训练集和测试集。在训练集中,我们进一步将其分成一个用于学习的子集和另一个用于验证的子集,我们在其中评估具有各种超参数设置的不同模型。

在 scikit-learn 中,我们可以使用一种称为网格搜索的方法来执行 holdout 方法和超参数调整。网格搜索涉及创建一个参数网格,该网格定义了我们想要评估的超参数组合。例如,在 k-最近邻的情况下,我们可以考虑不同的邻居数 (k) 和距离度量 (p)。网格搜索迭代所有可能的组合,在训练集上拟合模型并在验证集上评估它们。

尽管网格搜索通常与 K 折交叉验证一起使用,但在本例中,我们将重点关注 holdout 方法。要使用管道应用 holdout 方法和网格搜索,我们可以利用 scikit-learn 中的 GridSearchCV 类。这个类允许我们定义参数网格和管道,它处理拟合模型和评估模型的过程。

下面是一个示例代码片段,用于演示如何将 GridSearchCV 与管道一起使用:

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline

# Load the iris dataset
iris = load_iris()
X = iris.data
y = iris.target

# Split the data into training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2 , random_state= 42 )

# Create a pipeline
pipeline = make_pipeline(StandardScaler(), KNeighborsClassifier())

# Define the parameter grid for grid search
param_grid = { 'kneighborsclassifier__n_neighbors' : [ 3 , 5 , 7 ],
               'kneighborsclassifier__weights' : [ 'uniform' , 'distance' ]}

# Create a GridSearchCV object
grid_search = GridSearchCV(pipeline, param_grid, cv= 5 )

# Fit the models and perform grid search
grid_search.fit(X_train, y_train)

# Print the best parameters and best score
print( "Best Parameters: " , grid_search.best_params_)
print( "Best Score: " , grid_search.best_score_)

# Evaluate the best model on the test set
best_model = grid_search.best_estimator_
accuracy = best_model.score(X_test, y_test)
print( "Test Accuracy: " , accuracy)
在此示例中,我们首先加载 Iris 数据集并使用 train_test_split 函数将其拆分为训练集和测试集。然后,我们使用 make_pipeline 创建一个管道,包括一个用于数据缩放的 StandardScaler 和一个作为估计器的 KNeighborsClassifier。

接下来,我们定义参数网格 param_grid,它指定我们要评估的不同超参数组合。在这种情况下,我们改变 K 最近邻分类器的邻居数 (n_neighbors) 和权重函数 (weights)。请注意,网格中的参数名称以管道组件名称为前缀,后跟双下划线 (__)。

我们创建一个 GridSearchCV 对象,传递管道、参数网格和所需数量的交叉验证折叠 (cv)。 GridSearchCV 类通过在训练数据上拟合管道并在验证集上评估模型来自动执行网格搜索。

网格搜索完成后,我们可以使用 GridSearchCV 对象的 best_params_ 和 best_score_ 属性访问最佳参数和最佳分数。我们打印这些值以查看哪种超参数组合产生了最佳性能。

最后,我们通过从 GridSearchCV 对象的 best_estimator_ 属性访问它并使用 score 方法计算准确性来评估测试集上的最佳模型。

此示例演示了我们如何利用管道和网格搜索来有效地探索不同的超参数设置并使用 holdout 方法选择最佳模型。通过在管道中结合数据处理步骤和模型训练,我们可以简化机器学习工作流程并轻松试验不同的组件和超参数。

 

6.1 决策树简介(L06:决策树)



6.1 决策树简介(L06:决策树)

最后,我们将讨论一个新主题——决策树。决策树算法可以被认为是分类器和回归模型的自上而下的迭代构造方法。为了使视频易于管理且不会太长,我将讲座分为七个部分。

在第一部分中,我们将简要概述决策树及其概念表示,并介绍核心术语。接下来,我们将在决策树的上下文中讨论递归算法,并简要解释什么是递归算法。这种理解将帮助我们分析决策树的运行时复杂性(Big O)。

继续,我们将探索不同类型的决策树。目前,第二个学习器实现了 Leo Breiman 开发的 CART(分类和回归树)决策树算法。然而,还有其他算法,如 ID3 和 C4.5,各有优缺点。我们将接触这些不同的方法,并可能会分配一个家庭作业练习,可能会实施 ID3 决策树。

在讲座中,我们还将探讨用于决策树的各种分裂标准。目前,第二个学习者使用 CART,它通常基于 Gini 杂质。但是,它允许混合和匹配不同的拆分标准。这些分裂准则是指用于确定分裂决策树的良好特征的函数或度量。我们将介绍 Gini 杂质和熵标准,并讨论为什么在评估树生长和分裂质量时它们比错误分类错误更受青睐。

一旦我们了解了这些细节,我们将深入研究可以使决策树在计算运行时间和分类准确性方面更高效的改进。我们还将解决过度拟合的挑战并探索缓解它的技术。

最后,我们将提供一个代码示例,演示如何在流行的机器学习库 scikit-learn 中使用决策树。这个实际示例将有助于巩固您对决策树及其实施的理解。

现在,让我们深入了解决策树的基本概念。虽然严格来说不是机器学习问题,但决策树与涉及决策制定的日常生活场景相关。例如,我们可以考虑在给定时刻做什么的决定。如果我们有工作要做,我们可能会选择留在里面完成工作。相反,如果我们没有任何未完成的工作,我们可以考虑到外面去,这取决于天气前景。

比方说,如果天气晴朗且不太冷,我们可能会选择去海滩。但是,如果是阴天,我们可能会选择去跑步。在下雨或下雪的情况下,我们可以询问我们的朋友他们是否有空。如果我们的朋友很忙,我们可能会决定呆在家里,从事读书等活动。另一方面,如果我们的朋友有空,我们可以探索诸如去电影院、在线玩视频游戏或进行在线聊天等选项。

这个基本大纲代表一棵决策树,其中每个节点对应一个问题或决策,分支导致不同的选项。根节点代表树中的第一个问题或决策,而叶节点是最终输出。内部节点是引导树的流动的中间决策。

此外,决策树中的节点可以分为二类或多类节点。二元节点只提供两个选项,而多类别节点支持两个以上的选项。但是,如前所述,可以将多类别拆分转换为二元拆分。

决策树也可以解释为规则集,类似于编程中的 if-else 语句。事实上,决策树可以转换为规则集,尽管反向转换并不总是可行的。决策树的这一特性使其具有高度的可解释性和可解释性,这在可解释性和可解释性很重要的领域至关重要,例如在法律和医学领域。

要构建决策树,我们需要一个包含输入示例和相应输出示例的数据集。每个示例都包含一组特征(也称为属性或预测变量)和一个目标变量(我们要预测的输出)。决策树算法分析特征及其关系,以确定拆分数据和进行预测的最佳方式。

构建决策树的过程涉及选择最佳特征来拆分每个节点的数据。目标是找到提供最大信息增益或分类准确度最佳分割的特征。这个过程通常是递归执行的,从根节点开始,一直向下到叶节点。

在每一步,该算法都会评估不同的分裂标准,例如基尼杂质或熵。基尼不纯度衡量将随机选择的元素从集合中错误分类的概率,而熵衡量从集合中识别随机选择的元素的类别标签所需的平均信息量。这些标准有助于确定拆分后所得子集的纯度。

一旦选择了一个特征进行分割,数据就会根据可能的特征值被分成子集。对每个子集递归地重复此过程,直到满足停止条件。停止标准可以是达到最大树深度,达到叶节点中的最小样本数,或者在叶节点中达到一定程度的纯度。

为了使用经过训练的决策树预测新实例的目标变量,我们从根节点开始,根据实例的特征值沿着适当的分支向下遍历树。最终,我们到达一个叶节点,它提供预测的输出。

决策树有几个优点。它们易于理解和解释,使它们成为可视化和解释决策过程的流行选择。它们可以处理数值和分类特征,并且可以用于分类和回归任务。决策树对缺失值和异常值也很稳健,因为它们可以在拆分过程中有效地处理它们。

然而,决策树也有一些局限性。它们很容易过度拟合训练数据,导致对未见示例的泛化能力差。这可以通过使用修剪技术或使用随机森林或梯度提升等集成方法来缓解。决策树对训练数据的微小变化也很敏感,可以为相似的数据集生成不同的拆分。此外,决策树可能难以捕获特征之间的复杂关系。

总之,决策树是功能强大且可解释的模型,可用于分类和回归任务。它们通过将数据表示为具有节点和分支的树结构来提供清晰的决策框架。分裂标准和停止标准的选择,以及处理过度拟合的技术,在构建准确和稳健的决策树中起着重要作用。

 

6.2 递归算法和Big-O(L06:决策树)



6.2 递归算法和Big-O(L06:决策树)

在本视频中,我们的讨论围绕递归算法展开,递归算法与分而治之的概念密切相关。分而治之涉及将问题分解为更小的子问题,分别解决它们,然后组合解决方案。决策树训练和预测,以及各种分而治之的算法,都与这个概念有关。递归是一种用于实现分而治之算法的常用技术,尽管它不是唯一的方法。

为了掌握递归的概念,让我们看一个用 Python 实现的递归算法的例子。为了便于讨论,我特意隐藏了该函数的实际名称,以鼓励您在深入研究其细节之前分析其用途。我鼓励您花点时间考虑一下这个函数可能做什么。您可以暂停视频,甚至可以在 Jupyter notebook 中对其进行试验以了解其行为。

假设您已经花时间分析它,让我们一起探索这个功能。这个特定的函数在 Python 列表上运行。例如,考虑一个像 [1, 2, 3] 这样的列表。此函数的目的是确定数组或列表的长度。让我们来看看它是如何工作的。该函数接受一个输入,在这里表示为“X”,并检查两个条件。首先,它检查列表是否为空。如果是,则函数返回 0,因为空列表的长度为零,它充当停止条件。否则,如果列表不为空,则函数返回 1 并使用较小的输入调用自身。

如果这看起来很抽象,让我们一步一步地分解它。假设我们从一个完整的列表开始,例如 [1, 2, 3]。最初,该函数检查列表是否为空,而事实并非如此。因此,它继续执行“else”语句,返回 1 并使用较小的输入递归调用自身。在这种情况下,输入变为 [2, 3] 因为我们从原始列表中删除了第一个元素。我们重复这个过程:函数再次返回 1,用新的输入 [3] 调用自己,最终用一个空列表调用自己。

到达空列表后,该函数再次检查“if”条件,该条件现在为真。结果,它返回 0。当我们计算整个表达式时,我们得到值 3。因此,此函数使用递归计算数组的长度,其中函数在其自己的定义中调用自身。值得注意的是,虽然递归是计算机科学理论中概念上优雅的解决方案,但它可能并不总是最实用的实现方法。在 Python 中,递归对自调用的次数有限制,过大的列表会导致 Stack Overflow 错误。

继续,让我们探讨另一个使用递归的例子。在这里,我们使用快速排序算法解决一个分而治之的问题——对列表或数组进行排序。与前面的功能类似,快速排序使用递归作为实现手段。该算法采用停止条件,如果数组包含的元素少于两个,则函数按原样返回数组。否则,算法将执行代码的主要部分。

快速排序是如何工作的?首先,我们选择一个主元,通常是数组的第一个元素。然后,我们创建两个新列表:一个用于存放小于基准的元素,另一个用于存放大于基准的元素。我们遍历数组,不包括枢轴,并根据与枢轴的比较将每个元素分配到较小或较大的列表。接下来,我们使用枢轴作为中心元素,对较小和较大的列表递归调用快速排序。最终,

当列表少于两个元素时,递归调用将达到停止条件。此时,该函数仅返回排序后的列表。

让我们通过一个例子来理解这个过程。假设我们有一个未排序的列表 [7, 2, 5, 1, 9, 3]。快速排序算法将按如下方式进行:

  1. 选择枢轴作为第一个元素,即 7。
  2. 创建了两个空列表,越来越小。
  3. 遍历列表,不包括主元:
    • 2 小于 7,因此它进入较小的列表。
    • 5 小于 7,因此它进入较小的列表。
    • 1 小于 7,因此它进入较小的列表。
    • 9 大于 7,因此它进入了更大的列表。
    • 3 小于 7,因此它进入较小的列表。
  4. 在较小和较大的列表上递归调用快速排序。
    • 对于较小的列表:[2, 5, 1, 3]
      • 选择 2 作为基准并创建空列表。
      • 遍历列表:
        • 5 大于 2,因此它进入更大的列表。
        • 1 小于 2,因此它进入较小的列表。
        • 3 大于 2,因此它进入更大的列表。
      • 在较小和较大的列表上递归调用快速排序。
        • 对于较小的列表:[1]
          • 该列表的元素少于两个,因此按原样返回。
        • 对于更大的列表:[5, 3]
          • 选择 5 作为基准并创建空列表。
          • 遍历列表:
            • 3 小于 5,因此它进入较小的列表。
          • 在较小和较大的列表上递归调用快速排序。
            • 对于较小的列表:[3]
              • 该列表的元素少于两个,因此按原样返回。
            • 对于更大的列表:[5]
              • 该列表的元素少于两个,因此按原样返回。
      • 最终排序的较小列表是 [1]。
      • 最终排序的较大列表是 [3, 5]。
    • 对于更大的列表:[9]
      • 该列表的元素少于两个,因此按原样返回。
  5. 最终排序的较小列表是 [1]。
  6. 最终排序的较大列表是 [3, 5, 9]。
  7. 连接已排序的较小列表、主元 (7) 和已排序的较大列表。
    • 排序后的列表变为 [1, 3, 5, 7, 9]。

通过递归地将列表划分为更小的子列表并对它们进行排序,快速排序算法可以有效地对整个列表进行排序。

总之,递归算法在分治法中起着至关重要的作用。他们将问题分解成更小的子问题并单独解决,最终组合解决方案来解决原始问题。递归函数在自己的定义中调用自己,反复处理较小的输入,直到达到停止条件。但是,重要的是要考虑终止条件以避免无限递归并确保算法收敛到解决方案。

 

6.3 决策树的类型(L06:决策树)



6.3 决策树的类型(L06:决策树)

在之前的视频中,我们重点介绍了决策树和递归算法。现在,让我们深入研究不同类型的决策树。我们将探索改变某些设计选择如何导致决策树算法的不同实现。

首先,让我们用伪代码回顾一下我们在上一个视频中讨论过的通用决策树算法。我们处理了一个二元分类问题,其中类标签只有 1 和 0。我们的树遵循二元结构,涉及二元分裂。这意味着每个节点恰好被划分为两个子节点。此外,我们只考虑二元特征,其中特征值可以是 0 或 1。

然而,正如我们之前在 scikit-learn 中使用决策树可视化所演示的那样,我们还可以利用连续特征并将它们转换为二元分割。例如,我们可以选择一个特征,我们称它为 xj,然后使用阈值将其分成两部分,表示为“t”。这个分裂标准可以定义为 xj 小于 t 或 xj 大于或等于 t,可以表示为 true 或 false。这使我们即使具有连续特征也可以执行二进制拆分,因为我们可以在拆分过程中调整决策阈值。你将有机会在作业中进行这样的拆分。

现在,让我们关注决策树算法的实现。在决策树的每个节点,我们考虑一个单一的特征,表示为 xj,其中“j”的范围从 1 到 m,最多代表 m 个特征。当我们将父节点拆分为两个子节点时,比如说子节点 0 和子节点 1,我们需要确定选择哪个特征进行拆分。对于连续特征,我们还需要考虑决策阈值,我们在其中比较 xj 是否大于或等于特定值“t”。选择合适的特征和阈值是至关重要的,我们需要一个良好的衡量标准来评估分割的质量。

总结通用树生长算法,我们选择在父节点分裂时产生最大信息增益的特征。信息增益是分裂优劣的度量。信息增益越高,分割和选择的特征越好,包括它对连续特征的分割阈值。在下一个视频中,我们将讨论两种常用的衡量分裂优劣的指标:熵和基尼不纯度。

该算法遵循特定的停止条件。如果子节点是纯的,它会停止,这意味着节点内的所有数据点都具有相同的类标签。或者,如果信息增益小于或等于零,则停止,表明没有改善。一旦我们到达一个纯节点或无法取得进展,我们就会停止进一步生长树。

在生成决策树后,我们可以用它来进行预测。假设我们有一棵多层次的树,包括父节点和叶节点。为了预测新数据点的类标签,我们根据数据点的特征值遍历树。在每个节点,我们根据特征条件跟随相应的分支,直到到达叶节点。对于叶节点,我们使用多数表决方法来确定类标签。这意味着我们预测在该叶节点中出现最频繁的类标签。

重要的是要注意决策树可以处理二分类和多分类问题。我们在前面的幻灯片中讨论的伪代码侧重于二元分类,但决策树可以处理任意数量的类标签。无论班级数量多少,多数表决方法都适用。

在开发决策树算法时,我们会遇到各种设计选择。一个关键问题是如何拆分节点。我们需要定义拆分的标准,并确定如何比较和评估不同的拆分。用于评估拆分质量的两种常用度量是熵和基尼不纯度。

熵是节点内杂质或无序度的量度。它量化与该节点中数据点的类标签相关的不确定性。使用以下公式计算节点的熵:

熵(节点)= - 总和(p(i)* log2(p(i))),对于所有类别 i

其中 p(i) 表示节点中属于类别 i 的数据点的比例。熵值的范围从 0 到 1,其中 0 表示纯节点(所有数据点属于同一类),1 表示最大杂质(数据点在所有类中均匀分布)。

为了评估拆分的质量,我们计算生成的子节点的熵值的加权平均值。这被称为信息增益。信息增益计算如下:

Information Gain = Entropy(parent) - sum((|Sv| / |S|) * Entropy(Sv)), 对于所有子节点 v

其中 Entropy(parent) 是父节点的熵,|Sv|表示子节点v中的数据点个数,|S|是父节点中数据点的总数。信息增益衡量通过基于特定特征拆分节点所实现的熵减少。

基尼杂质是用于评估分割质量的另一种度量。如果我们根据节点中类标签的分布分配类标签,它会量化错误分类节点中随机选择的数据点的概率。使用以下公式计算节点的基尼杂质:

Gini(node) = 1 - sum(p(i)^2),对于所有类别 i

其中 p(i) 表示节点中属于类别 i 的数据点的比例。与熵类似,基尼杂质值的取值范围为 0 到 1,其中 0 表示纯节点,1 表示最大杂质。

为了评估拆分的质量,我们计算生成的子节点的 Gini 杂质值的加权平均值。这被称为基尼杂质指数。基尼杂质指数计算如下:

Gini Index = sum((|Sv| / |S|) * Gini(Sv)),对于所有子节点 v

其中|Sv|表示子节点v中的数据点个数,|S|是父节点中数据点的总数。基尼指数衡量通过基于特定特征拆分节点而实现的基尼杂质减少。

熵和基尼杂质都是决策树算法中常用的,它们之间的选择取决于具体问题和数据特征。在 scikit-learn 中,您可以选择标准参数以在构建决策树模型时指定“熵”或“基尼”。

在下一个视频中,我们将深入研究这些度量并讨论如何使用它们来确定决策树算法中的最佳拆分。

 

6.4 拆分标准(L06:决策树)



6.4 拆分标准(L06:决策树)

在视频中,演讲者深入研究了决策树的复杂性,并在此框架内介绍了拆分标准的概念。拆分标准本质上是用于确定将父节点拆分为其子节点的最合适特征的标准或度量。通常,数据集包含多个特征,表示为 x1, x2, x3, ..., xm,其中 j 表示范围从 1 到 m 的值。

演讲者强调,在决策树的每个节点,必须就用于拆分过程的特征做出关键决策。为了识别最佳特征,定义了某些标准或度量来比较和评估可用特征。目标是选择一个能产生更好分裂的特征,从而提高决策树的预测准确性。

为了说明决策树的工作原理,演讲者展示了一个包含三个特征的玩具数据集:x1、x2、x3 和表示类标签 y 的列。此数据集中的类标签是二进制的,取值 1 或 0。演讲者指出,仅使用两个特征,就可以为该特定数据集实现 100% 的训练准确率。

演讲者向听众提出挑战,提示他们根据这三个特征找出两条规则,使训练准确率达到 100%。他们建议暂停视频以考虑解决方案。随后,演讲者揭示了解决方案,解释说只有 x1 和 x2 是相关且有用的特征,而 x3 看似随机且对准确性没有贡献。

接下来,演讲者通过在图表上绘制 x1 和 x2 的值来直观地表示数据集。图中的红点表示属于类别标签一的数据点,而蓝色方块表示标记为零的数据点。根据在数据点中观察到的模式,说话者继续创建分裂,从而形成决策树。

初始拆分基于 x1 大于 5.5。此划分将数据分为两个区域,一个标记为蓝色,另一个标记为红色。演讲者指出,虽然这种拆分对一些数据点进行了正确分类,但它也对其他数据点进行了错误分类。随后的拆分基于 x2 大于 10.5。这进一步完善了分类过程,并最终导致决策树达到 100% 的训练准确率。

为了提高清晰度,演讲者提供了决策树的更清晰的视觉表示,阐明了与每个节点相关的信息。每个节点代表经历分裂的父节点,从而产生子节点。对于每个节点,显示分裂值(由特征值和阈值表示)、熵(信息量的度量)、训练示例(样本)的数量、类标签分布(地点)和多数类。

决策树以层次结构描述,父节点产生子节点。演讲者强调了每个节点的重要性,强调决策树使用这些节点根据输入特征进行预测。

最后,演讲者提到了另一种方法,可以通过仅利用特征二来实现 100% 的训练准确率。他们演示了基于这种替代方法的决策树,展示了如何在值 7.5 和 10 处拆分特征二,以准确地将数据点分成所需的类别。

在我们具有连续特征并正确设置阈值的理想情况下,上述概念将适用。我们不使用变量“V”,而是使用变量 xj,表示小于或等于阈值的连续特征。第二个子节点将表示大于阈值的值。在这种情况下,如果我们拥有连续的特征,可以使用与之前类似的公式,但现在我们需要在函数中加入一个阈值。我们可以比较这些值以检查它们是否大于或等于阈值。

因此,如果我们有一个连续的特征和类似于 CART(分类和回归树)的二叉树,我们只需要对两个子节点而不是多个子节点求和。一个子节点对应大于阈值的值,而另一个子节点代表小于或等于阈值的值。这种简化是合乎逻辑的,因为我们专注于基于阈值的两种可能结果。然而,重要的是要承认这种解释可能看起来很密集,并且仍然缺少一个重要的方面是熵的概念,这将在随后的幻灯片中进行探讨。

在这种情况下,熵属于香农熵,由克劳德香农在信息论领域引入。它不同于生物物理学或热力学中使用的熵。香农熵用作量化决策树中子节点的不纯性或无序性的度量。它量化由具有两个结果的离散随机变量传递的信息量,类似于伯努利分布。在伯努利分布中,表示为 p 的概率参数表示事件发生的可能性。

香农将信息定义为对值 1/p 进行编码所需的位数。简而言之,它衡量与事件相关的确定性或不确定性水平。所需的位数可以计算为 1/p 的以 2 为底的对数。随着概率 p 的增加,所需的位数减少,表明更高程度的确定性。相反,随着概率接近于零,所需的位数会增加,这意味着更高级别的不确定性。

为了举例说明这个概念,让我们考虑几个例子。如果我们的概率为 0.5,则所需的位数将为 1。如果概率为 0,则所需的位数将为无穷大,表示绝对确定性。相反,如果概率为 1,则所需的位数将为 0,表示完全不确定。因此,项 -log2(p) 的值范围从负无穷大到 0。

香农熵被计算为所有可能事件的平均信息。它表示与每个事件相关的信息的加权平均值,权重是事件各自的概率。在决策树的情况下,熵的概念可以用来衡量子节点的不纯度。如果一个节点表现出类标签的均衡分布,它将拥有更高的熵,意味着更大的杂质。相反,如果一个节点显示一个类占主导地位的偏态分布,它将拥有较低的熵,表明较低的杂质。这个概念直观地对齐,因为具有更高杂质的节点提供更少的用于分类目的的信息。

熵提供了一种衡量决策树子节点内不纯或无序的方法。它可以根据类标签的分布来评估节点的纯度。具有较高熵的节点表示更多样化的分布,而具有较低熵的节点表示更均匀的分布。通过考虑子节点的熵,可以在构建决策树时做出更明智的决策。

 

6.5 基尼和熵与错误分类错误(L06:决策树)


6.5 基尼和熵与错误分类错误(L06:决策树)

在上一个视频中,我们讨论了可用于生成决策树的各种拆分标准。现在,让我们深入研究为什么两个分裂标准,即基尼不纯度和熵,优于第三个标准,错误分类错误。

回顾一下,我们有三种杂质度量:熵、缩放熵(缩放 0.5 以与基尼杂质进行比较)和误分类错误。这些杂质措施的形状不同。熵表现为凹函数,而误分类误差在 0.5 处有一个尖峰,具有线性斜率。

问题出现了:为什么我们使用熵和基尼杂质而不是错误分类错误来生长决策树?这个问题不仅适用于熵,也适用于基尼杂质。在本视频中,我们将重点关注熵,但这个概念同样适用于基尼杂质。

让我们考虑信息增益方程。我们有一个父节点的杂质函数,它表示父节点处的数据集 D。当我们根据特征值拆分这个数据集时,我们会生成不同的子节点。这个概念适用于分类特征和连续特征。对于连续特征,我们可以通过基于阈值创建 bin 来进行分割。

杂质度量用于父节点和子节点,我们在考虑父节点和当前子节点的原始数据集的大小的同时将它们相加。通常,如果我们为父节点选择一种不纯度度量,我们也会为子节点保持一致。

在实践中,我们倾向于避免使用错误分类错误,因为它有一个缺点,我们将在本视频中讨论。让我们简要回顾一下熵和误分类误差是如何计算的。熵的计算方法是将每个类别的标签比例与比例的对数相加。另一方面,错误分类错误基于 0/1 损失,它衡量错误分类标签的比例。

现在,关注熵与误分类误差,一个关键区别是它们的形状。熵是凹的,而错误分类错误不是。这种差异影响了为什么熵比生长决策树的错误分类错误更受青睐。

为了说明这一点,让我们考虑一个简单的玩具数据集。在父节点,我们有 40 个一类示例和 80 个零类示例。如果我们根据特征值拆分数据集,我们最终会得到具有不同类分布的子节点。我们需要评估与父节点相比,这种拆分是否提高了节点的纯度。

如果我们计算父节点和子节点的熵,我们发现子节点二的熵低于父节点,表明纯度提高了。但是,子节点一比父节点差。平均而言,我们需要确定拆分是否有益。

为了衡量拆分的质量,我们使用信息增益,它考虑了父节点和子节点的熵值。如果信息增益为正,则表明分裂良好。在我们的示例中,信息增益为正,表明基于熵的有利拆分。

现在,让我们使用错误分类错误检查相同的场景。父节点、子节点一和子节点二的错误是根据错误分类标签的比例计算的。如果我们将这些误差值代入信息增益公式,我们会发现信息增益为零。零信息增益意味着分裂是无益的。因此,这些节点将不存在,我们需要考虑其他功能。

总之,对于增长的决策树,熵优于错误分类错误的主要原因是熵更有效地捕获了数据中的不确定性和无序性。熵的凹形允许更好地区分不同类别的分布,并提供更细微的杂质测量。另一方面,误分类误差是一种更简单的度量,它只考虑误分类标签的比例,并没有捕捉到类别的不确定性和分布。

熵的凹形允许它惩罚小类和大类不平衡。它对类别比例的变化很敏感,对分布更均匀的类别赋予更高的权重。在处理类别分布不平衡的数据集时,此属性使熵特别有用。

相比之下,错误分类误差呈线性形状,在 0.5 处有一个尖峰。它对所有的误分类一视同仁,不区分不同程度的误分类。这使得错误分类错误对类别不平衡更加敏感,并且在数据集不平衡的情况下效果更差。

此外,熵和错误分类错误之间的形状差异会影响决策树学习过程。决策树旨在找到最大化信息增益或减少杂质的分裂。由于熵提供了更细粒度的杂质度量,因此它允许决策树进行更明智和准确的拆分。

通过使用熵作为杂质度量,决策树能够捕获特征和类之间的复杂关系。他们可以处理连续和分类特征,并且可以发现数据中的复杂模式。

总之,对于增长的决策树,熵优于错误分类错误,因为它更有效地捕获数据中的不确定性和无序性。它的凹形可以更好地区分不同的类分布,并且对不平衡数据集更稳健。通过使用熵,决策树可以进行更明智的拆分并捕获要素和类之间的复杂关系。

 

6.6 改进和处理过度拟合(L06:决策树)



6.6 改进和处理过度拟合(L06:决策树)

在上一个视频中,我们讨论了可用于生成决策树的不同拆分标准。现在,我们将深入研究为什么两个分裂标准,即基尼杂质和熵,优于第三个标准,错误分类错误。

为了唤醒我们的记忆,让我们回顾一下三个分裂标准:熵、缩放熵(用于与基尼不纯度进行比较)和错误分类错误。这些杂质度量的形状可以形象化如下:熵是一个凹函数,用一条高黑线表示;缩放熵也是凹的,通过将熵乘以 0.5 获得;误分类误差在 0.5 处呈现尖峰和线性斜率。

现在,问题来了:为什么我们在生长决策树时更喜欢使用熵和基尼杂质而不是错误分类错误?这个问题适用于熵和基尼杂质,但为了简单起见,我们将在本次讨论中重点关注熵。

让我们回顾一下信息增益方程。我们从一个父节点开始,表示为 D,并根据特征值拆分该数据集,创建不同的子节点。杂质函数用于父节点和子节点,我们在考虑数据集大小的同时总结杂质值。如果我们为父节点选择熵,我们也为子节点使用熵。同样的原则也适用于基尼杂质。

实际上,我们不希望使用错误分类错误,因为它有一个缺点,我们将在本视频中探讨这一点。为了进一步理解这一点,让我们简要回顾一下熵、基尼不纯度和误分类误差的公式。

熵是通过插入类标签的比例并将它们相加来计算的。它使用对数并由我们对类别求和并将每个类别的比例乘以该比例的对数的公式表示。

另一方面,基尼不纯度计算类别标签比例的平方并从中减去它。它避免使用对数,表示为 1 减去类别标签比例的平方和。

误分类错误基于0-1损失,它衡量误分类标签的比例。例如,如果我们有一个标签为 001111 的节点,则多数投票将预测 0,因为它是多数类。然而,考虑到分布,我们只能在六次中正确四次,从而导致准确率为 4/6 或 66.6%。误差为 2/6 或 33.3%。

为了比较熵和误分类误差,我们观察到熵是凹的,而误分类误差在 0.5 处呈现尖峰和线性斜率。这种差异对于理解为什么熵比生长决策树的错误分类错误更受欢迎是至关重要的。

为了说明这一点,让我们考虑一个简单的玩具数据集,其父节点包含 40 个来自第一类的示例和 80 个来自第二类的示例。假设要分割的最佳特征是 x1,我们根据特征值是 1 还是 0 来划分数据集。我们得到两个子节点:子节点一和子节点二。通过分析类别分布,我们发现子节点二比父节点更纯,而子节点一更差。

关键问题是是否值得拆分此功能。为了确定这一点,我们使用熵计算信息增益。我们计算父节点、子节点一和子节点二的熵值。比较这些值,我们观察到子节点二更好,而子节点一比父节点差。通过应用信息增益公式,我们发现此拆分的信息增益为正,表明拆分提高了数据集的整体纯度。

现在,让我们将错误分类错误视为杂质度量而不是熵。我们计算父节点、子节点一和子节点二的误分类误差。比较这些值,我们发现子节点 2 的误分类误差低于父节点,而子节点 1 的误分类误差较高。

然而,当我们使用误分类误差计算信息增益时,我们遇到了一个问题。信息增益公式涉及从父节点的误分类误差中减去子节点的加权误分类误差。由于误分类误差是线性函数,如果子节点的误分类误差高于父节点,则信息增益可以为负。

在我们的示例中,即使子节点 2 的误分类误差低于父节点,子节点 1 的误分类误差较高,导致负信息增益。这意味着使用错误分类错误作为不纯度度量会阻止分裂,即使它提高了其中一个子节点的纯度。

另一方面,当我们使用熵或基尼不纯度作为不纯度度量时,信息增益总是非负的。熵和基尼杂质都是凹函数,即子节点的杂质值总是小于或等于父节点的杂质值。这确保了只要分裂提高了至少一个子节点的纯度,信息增益就会是正的。

通过使用熵或基尼杂质作为杂质度量,决策树可以根据信息增益进行分裂,这提供了一种有原则的方法来生长树并提高其预测能力。另一方面,错误分类错误可能导致次优分割和不太准确的决策树。

总而言之,决策树算法中对熵和基尼杂质的偏好优于错误分类错误的根源在于它们的数学特性。熵的凹性和基尼不纯度确保信息增益对于提高子节点纯度的拆分为正,而错误分类误差的线性特性可能导致负信息增益和次优拆分。

 

6.7 在 Scikit-Learn 中实现决策树的代码示例(L06:决策树)



6.7 在 Scikit-Learn 中实现决策树的代码示例(L06:决策树)

作为第六讲的总结,我们现在将检查一个使用 scikit-learn 的代码示例,特别关注决策树算法。 Scikit-learn 因其速度、效率和稳健性而被推荐用于现实世界的机器学习项目。虽然我们将在本次演示中使用 scikit-learn,但值得一提的是,您将从头开始为家庭作业实施决策树,以增强您对算法的理解。

首先,让我们导入必要的包,包括水印包,这将帮助我们跟踪所使用软件的版本。如果由于软件版本过时而在运行代码时出现任何问题,这将很有帮助。接下来,我们加载鸢尾花数据集,这是一种常用于分类任务的流行数据集。通过使用像 iris 这样的知名数据集,我们可以更专注于理解代码及其功能,而不是解释数据。

我们将数据集分成训练集和测试集,其中 30% 的数据分配给测试。请务必注意,我们不会在此笔记本中执行任何调整。尽管可以使用网格搜索等技术调整决策树超参数,但我们将保持简单并暂时跳过调整。因此,我们不需要单独的验证集,因为我们将仅在训练集上训练决策树并评估其在测试集上的性能。

继续绘制决策区域,我们初始化决策树分类器并设置超参数。在这种情况下,我们选择信息增益的熵标准,并将最大深度设置为二以用于教育目的。此外,我们将决策树拟合到训练数据并绘制决策区域。通过可视化决策区域,我们可以观察决策树如何根据所选特征分离数据。

我们探索可以为决策树分类器设置的不同选项和超参数。其中包括决定如何在每个节点进行拆分的拆分器,以及与拆分节点和叶节点所需的最小样本相关的参数。还有用于选择杂质度量和控制拆分随机性的选项。这些超参数可以根据具体问题和数据集进行调整和调整。

接下来,我们继续使用 graphviz 库可视化决策树。我们将决策树导出为一个点文件,它将树结构表示为一个图。我们可以自定义图中节点、边和标签的外观。通过将graphviz库与pydotplus库结合使用,我们可以直接绘制决策树,而无需单独保存点文件。这样,我们就可以在笔记本本身中可视化决策树。

为了显示决策树图,我们使用 ipython 显示模块加载生成的 PNG 文件。我们从 ipython 显示中导入图像类,并使用它来加载 PNG 文件。这使我们能够直接在 Jupyter Notebook 中查看决策树图。决策树图根据所选特征分别将拆分和决策边界显示为垂直线和水平线。

总之,此代码示例演示了如何使用 scikit-learn 实现和可视化决策树分类器。决策树算法为分类任务提供了一个可解释的模型,并且可以使用各种超参数进行调整以提高性能。可视化决策树有助于理解算法如何根据输入特征做出决策。

 

7.1 集成方法简介(L07:集成方法)


7.1 集成方法简介(L07:集成方法)

在本周的讲座中,我们将深入研究集成方法,这是机器学习中的一个重要领域。这些方法广泛用于应用机器学习研究,以在实际应用中实现高性能。以其在实践中的有效性而闻名的可靠方法通常会产生最好的结果。

讲座还将重新审视决策树,解决在 Piazza 上提出的一些关于它们的相关性的问题。尽管是一种相对古老且熟悉的算法,但决策树在今天仍然具有高度相关性。它们不仅具有可解释性,而且经常用于集成方法中,表现出卓越的性能。本次讲座也旨在探讨这一方面。

在深入研究集成方法之前,重要的是回顾一下我们在这学期的进展。我们目前正在结束第三部分,它侧重于基于树的方法。然而,值得注意的是,其中一些方法超出了决策树的范围,并包含其他技术,包括应用于深度神经网络的可靠方法。由于决策树与大多数集成方法密切相关,因此它们被归类为第三部分。

完成本节后,我们将深入探讨模型评估,然后再讨论无监督学习,如果时间允许,还会讨论贝叶斯学习。虽然最初的计划是提前进行期中考试和覆盖其他方法,但课程进展时间比预期的要长。尽管如此,花额外的时间设置 Python 环境并熟悉每个人,尤其是那些没有很强 Python 背景的人,是有益的。它确保所有参与者都在同一页面上并为即将到来的家庭作业做好准备,这将涉及实施 CART(分类和回归树)决策树,而不依赖于 scikit-learn 等预建库。

讲座分为七个部分。第一部分提供了集成方法的介绍和概述。随后,我们将探索各种内部方法,从多数表决(最简单的集成方法)开始。然后我们将深入研究装袋,这是一种涉及从训练集中进行引导抽样的技术。将解释此方法的用处。提升,涉及将弱学习器(例如短决策树)提升为强模型,也将被涵盖。特别是,我们将讨论梯度提升,这是当今最流行的算法之一,以其在 Kaggle 竞赛中的成功而闻名。随机森林,另一种广泛认可的集成方法,将被引入。这些模型以其易用性而著称,因为它们通常无需大量超参数调整即可产生出色的性能。推荐给在各个科学领域寻求预测模型的个人,特别是如果他们缺乏机器学习方面的专业知识。

支持向量机 (SVM) 也将被提及,特别是它们在过去因其性能而流行,尤其是使用 RBF(径向基函数)核。然而,随机森林通常无需大量调整即可提供同样好的或更好的结果,这使得它们更适合实际应用。最后,将讨论应用中另一种流行的技术堆栈。

为了说明集成方法的重要性,将提供一个图,展示涉及随机森林的示例。该模型不限于分类任务,可以轻松计算特征重要性。例如,在上述示例中,硫原子被确定为预测分子活性的最重要特征。这种见解在实践中可能很有价值。

此外,包括随机森林和梯度提升在内的集成方法是使用最广泛的非深度学习机器学习模型之一。尽管深度学习越来越突出,但由于其出色的性能和易于实施,集成仍然具有很高的相关性。文章提到极端梯度提升(XGBoost)作为机器学习算法中的“新女王”的崛起。这强调了基于树的模型,特别是梯度提升,在各种应用中的重要性。

总之,本周的讲座将提供对集成方法的全面理解。它将涵盖不同类型的集成技术及其应用。