原文towardsdatascience.com/multilayer-perceptron-explained-a-visual-guide-with-mini-2d-dataset-0ae8100c5d1c?sourcecollection_archive---------1-----------------------#2024-10-25分类算法解剖一个小型神经网络的数学带视觉展示https://medium.com/samybaladram?sourcepost_page---byline--0ae8100c5d1c--------------------------------https://towardsdatascience.com/?sourcepost_page---byline--0ae8100c5d1c-------------------------------- Samy Baladram·发布于 Towards Data Science ·13 分钟阅读·2024 年 10 月 25 日–https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/14e597fceb0af5b4a1ac957a8f8434fc.png⛳️ 更多 [分类算法](https://medium.com/samybaladram/list/classification-algorithms-b3586f0a772c)解释· 虚拟分类器 · K 近邻分类器 · 伯努利朴素贝叶斯 · 高斯朴素贝叶斯 · 决策树分类器 · 逻辑回归 · 支持向量分类器 ▶ 多层感知器是否觉得神经网络无处不在它们出现在新闻中、手机里甚至出现在你的社交媒体动态中。但说实话——我们大多数人根本不清楚它们是如何运作的。那些复杂的数学和像“反向传播”这样的术语呢这是一个思考如果我们将事情简化呢让我们探索一个多层感知机MLP——最基本类型的神经网络——来使用一个小型网络分类一个简单的二维数据集只使用少量的数据点。通过清晰的视觉效果和逐步的解释你将看到数学变得生动观察数字和方程式如何在网络中流动以及学习是如何真正发生的https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/68c633860f446dbc91b04b1a420fcef7.png所有视觉效果作者使用 Canva Pro 创建。优化为手机端显示在桌面端可能显示过大。定义多层感知机MLP是一种神经网络类型它使用连接的节点层来学习模式。它之所以得名是因为它有多个层——通常包括一个输入层、一个或多个中间隐藏层和一个输出层。每个节点都与下一层的所有节点相连。当网络学习时它会根据训练示例调整这些连接的强度。例如如果某些连接导致正确的预测它们会变得更强。如果它们导致错误预测它们会变得更弱。通过这种例子学习的方式帮助网络识别模式并对它从未见过的新情况做出预测。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/14e597fceb0af5b4a1ac957a8f8434fc.png多层感知机MLPs被认为是神经网络和深度学习领域的基础因为它们可以处理一些简单方法无法解决的复杂问题。 使用的数据集为了理解多层感知机MLPs的工作原理我们从一个简单的例子开始一个只有几个样本的迷你二维数据集。我们将使用相同的数据集来保持简洁这个数据集来自我们之前的文章。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7d0cc55573cd44b994e5a8fcff182285.png列温度0-3、湿度0-3、打高尔夫是/否。训练数据集有 2 个维度和 8 个样本。在直接进入训练之前让我们先试着理解构成神经网络的关键部分及其如何协同工作。步骤 0网络结构首先我们来看看网络的各个部分节点神经元我们从神经网络的基本结构开始。这个结构由许多个单独的单位组成称为节点或神经元。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/77265c27db24a49170b0d38542b64000.png这个神经网络有 8 个节点。这些节点被组织成一个个层次结构来协同工作输入层输入层是我们开始的地方。它接收我们的原始数据节点的数量与特征的数量相匹配。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f6b53d8cb9333fa129a63e062bced4a6.png输入层有 2 个节点每个特征对应一个节点。隐藏层接下来是隐藏层。我们可以有一个或多个这样的层且可以选择每层的节点数量。通常我们在层数越深时每层的节点数量会越来越少。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/889ce747a48b89418498002342df446c.png这个神经网络有 2 个隐藏层分别包含 3 个节点和 2 个节点。输出层最后一层给出了我们的最终答案。输出层中节点的数量取决于我们的任务对于二分类或回归问题我们可能只有一个输出节点而对于多类问题我们则为每个类别设置一个节点。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/501dd95ec39e9361695c1dfe3776c883.png这个神经网络的输出层只有 1 个节点因为是二分类。权重节点之间通过权重相互连接——权重是控制每个信息片段重要性的数字。每个节点之间的连接都有自己的权重。这意味着我们需要大量的权重一层中的每个节点都连接到下一层的每个节点。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/943ab96a3ec27296e97af58df6ac6f3b.png这个神经网络总共有 14 个权重。偏置除了权重每个节点还拥有一个偏置——一个额外的数字帮助它做出更好的决策。权重控制节点之间的连接而偏置则帮助每个节点调整其输出。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ad9281828475d8a5feccaf9fb504b653.png这个神经网络有 6 个偏置值。神经网络总结来说我们将使用并训练这个神经网络https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/91aa2d74c3115b07db4df4ad2928bd43.png我们的网络由 4 层组成1 个输入层2 个节点、2 个隐藏层3 个节点和 2 个节点以及 1 个输出层1 个节点。这形成了一个 2–3–2–1 的架构。让我们看看这个新图示它展示了我们的网络从上到下的结构。我已经更新了它以便更容易理解数学过程信息从顶部的节点开始沿着各层向下流动直到到达底部的最终答案。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/86f3b59ab8e38a31139b12deeff4036b.png现在我们理解了网络的构建方式接下来让我们看看信息是如何在其中流动的。这叫做前向传播forward pass。第一步前向传播让我们逐步了解网络是如何将输入转换为输出的权重初始化在我们的网络开始学习之前我们需要为每个权重设置一个初始值。我们选择在-1 到 1 之间的小随机数。使用随机数开始有助于我们的网络在没有任何早期偏好或模式的情况下学习。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/acad0344344b5bb71231385d3d1816b5.png所有权重都是从[-0.5, 0.5]范围内随机选择的。加权和每个节点以两步处理传入的数据。首先它将每个输入乘以其权重并将所有这些数字相加。然后它再加上一个数字——偏置——以完成计算。偏置本质上是一个恒定输入为 1 的权重。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f8d6f7809ee3fa23613d041108562246.png激活函数每个节点将其加权和通过激活函数进行处理以生成输出。激活函数通过引入非线性行为帮助我们的网络学习复杂的模式。在我们的隐藏层中我们使用 ReLU 函数整流线性单元。ReLU 很简单如果一个数是正数它保持不变如果是负数它变为零。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6a74e04f64fc33016b7d0d03042d1b62.png层级计算这个两步过程加权求和和激活在每一层中依次进行。每一层的计算帮助我们一步一步地将输入数据转化为最终的预测值。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/62d3a696fdde86aeed6858154a42ef3c.png输出生成最后一层给出了网络的最终答案。对于我们的是/否分类任务我们在这一层使用一种特殊的激活函数叫做sigmoid。Sigmoid 函数将任何数值转化为 0 到 1 之间的值。这使得它非常适合用于是/否的决策因为我们可以将输出视为一种概率越接近 1 意味着越可能是“是”越接近 0 意味着越可能是“否”。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0661018ebd5f06045168823edd7e748a.png这个前向传播过程将我们的输入转化为一个 0 到 1 之间的预测值。但是这些预测有多准确呢接下来我们将衡量我们的预测与正确答案之间的接近程度。步骤 2损失计算损失函数为了检查我们的网络表现如何我们衡量它的预测与正确答案之间的差异。对于二分类问题我们使用一种叫做二元交叉熵的方法它能告诉我们预测值与真实值之间的偏差。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ff06e056294f4c2bbd55e6a76b6db2ff.png神经网络中的数学符号为了提高我们网络的性能我们需要使用一些数学符号。在继续之前让我们先定义一下每个符号的含义权重和偏置权重表示为矩阵偏置表示为向量或一维矩阵。括号表示法[1]表示层的编号。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/a70ec04d0c5d1a4e659e1fc32628bc96.png输入、输出、加权和以及激活后的值节点中的值可以表示为向量从而形成一致的数学框架。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f18f52954b17091054a53c2ec7e40f8c.png总结这些数学符号帮助我们精确地描述网络的运作过程https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/637013282fdcc206f32a296b0ce5d284.png让我们看一个图示展示我们网络中所有数学运算的过程。每一层都有连接层的权重W和偏置b激活前的值z激活后的值a最终预测值ŷ和损失值L在末尾https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/fc645b406cf6eb07ad93cd55ff59f9ab.png让我们看看每一层到底发生了什么第一个隐藏层·取输入x与权重W[1] 相乘加入偏置b[1] 得到z[1]·对z[1] 应用 ReLU 函数得到输出a[1]第二个隐藏层·取a[1]与权重W[2] 相乘加入偏置b[2] 得到z[2]·对z[2] 应用 ReLU 函数得到输出a[2]输出层·取a[2]与权重W[3] 相乘加入偏置b[3] 得到z[3]·对z[3] 应用 sigmoid 来获得我们的最终预测ŷhttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3c4c3f3539c1ab04fa6f9a66c47f140b.png现在我们看到网络中的所有数学公式如何改进这些数字以获得更好的预测这时反向传播就派上用场了——它向我们展示了如何调整我们的权重和偏差以减少错误。第 3 步反向传播在我们了解如何改进网络之前让我们快速回顾一下我们需要的一些数学工具导数为了优化我们的神经网络我们使用梯度——这是一个与导数密切相关的概念。让我们回顾一下基本的导数规则https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0ea522923ac7ce3ac21bd2a8e5c18c63.png偏导数让我们澄清常规导数和偏导数之间的区别*常规导数·用于函数只有一个变量的情况·显示当唯一变量变化时函数的变化量·写作 df/dx偏导数·用于函数有多个变量的情况·显示当一个变量变化时函数的变化量同时保持其他变量不变视为常数。·写作 ∂f/∂xhttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2f60c208ee4d23e387354ed4a346fc2d.png一些偏导数的例子梯度计算与反向传播回到我们的神经网络我们需要确定如何调整每个权重和偏差以最小化误差。我们可以通过一种叫做反向传播的方法来实现它向我们展示了改变每个值如何影响网络的误差。由于反向传播是通过网络反向进行的我们可以将图示翻转过来看看它是如何工作的。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/9f371a97af93a091b3afdbb51105776b.png网络的矩阵规则由于我们的网络使用矩阵权重和偏差的组合我们需要特殊的规则来计算变化如何影响我们的结果。这里有两个关键的矩阵规则。对于向量v, u大小为 1 ×n和矩阵W, X大小为n×n求和规则∂(WX)/∂WI单位矩阵大小为n×n∂(uv)/∂vI单位矩阵大小为n×n矩阵-向量乘积规则∂(vW)/∂Wvᵀ∂(vW)/∂vWᵀ使用这些规则我们得到https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/21a2c76b825f478f0251171b7b979348.png激活函数的导数ReLU 的导数对于向量a和z大小为 1 ×n其中a ReLU(z)∂a/∂z diag(z 0)创建一个对角矩阵表示如果输入为正则为 1如果输入为零或负则为 0。Sigmoid 的导数对于a σ(z)其中 σ 是 sigmoid 函数∂a/∂za⊙ (1- a)这直接乘以元素⊙表示逐位置相乘。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/406536d3c65893436cf88c0b469d845e.png二进制交叉熵损失函数的导数对于一个单独的例子损失函数为L -[ylog(ŷ) (1-y) log(1-ŷ)]∂L/∂ŷ -(y-ŷ) / [ŷ(1-ŷ)]https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/145aab17537a82e33342299758155d04.png到目前为止我们可以将所有的偏导数总结如下https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2ecaacf0d1a77fe1296855018554dd45.png下图展示了我们迄今为止得到的所有偏导数https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/fbe67994cd024b69583a9413901bca26.png链式法则在我们的网络中变化通过多个步骤进行传播一个权重影响它所在层的输出这又影响下一层依此类推直到最终误差。链式法则告诉我们将这些逐步变化相乘以找出每个权重和偏置如何影响最终的误差。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1f8a5d158f28ec911745e2a4e658dc00.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1f941aa47b9eaad7e064eb594ea454ce.png误差计算我们并不是直接计算权重和偏置的导数而是首先计算层误差∂L/∂zˡ相对于预激活输出的梯度。这使得后续计算我们应该如何调整早期层的权重和偏置变得更容易。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6632ead66c14bdace2390adf44c9fd3a.png权重梯度和偏置梯度使用这些层误差和链式法则我们可以将权重和偏置的梯度表示为https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2d83604e28f9ecfdd5471d925723a364.png梯度向我们展示了网络中每个值如何影响网络的误差。我们随后对这些值进行小幅调整以帮助网络做出更好的预测。步骤 4权重更新更新权重一旦我们知道每个权重和偏置如何影响误差即梯度我们就通过将这些值调整到与梯度相反的方向来改进我们的网络。这一步步地减少了网络的误差。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/56bd580089de99dc7ce5af8f7a7915d5.png学习率与优化我们并不是一次性做出大的变化而是进行小而谨慎的调整。我们使用一个叫做学习率η的数值来控制每次调整的幅度如果η太大变化过大可能会导致情况变得更糟如果η太小变化很小改进需要很长时间这种通过小幅、可控的调整来优化的方式被称为随机梯度下降SGD。我们可以将其写作https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/525bd2513df13222570baac0537d0393.pngη学习率的值通常选择较小通常在 0.1 到 0.0001 之间以确保学习的稳定性。我们刚才看到了网络如何通过一个示例进行学习。网络对数据集中每个示例重复这些步骤在每轮实践中逐步改进。步骤总结以下是我们为训练网络在单个示例上所涉及的所有步骤https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/cf84eac8a9e5bace7343937bcfc86018.png扩展到完整的数据集迭代我们的网络会对数据集中的每个示例重复这四个步骤——前向传播、损失计算、反向传播和权重更新。遍历所有示例一次称为一次迭代。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2d454eb9ee57344d96212fd863f3b201.png网络通常需要多次看到所有例子才能熟练掌握任务甚至多达 1000 次。每一次训练帮助它更好地学习模式。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bd6f40a7e518f1a85a5e58d93fec6dae.png批次我们的网络不是一次从一个例子中学习而是一次从一小组例子称为批次中学习。这有几个好处运行更快学习更好的模式稳定地改善在处理批次时网络会先查看组内的所有例子然后再做出改变。这比每看一个例子就改变一次值能得到更好的结果。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/d12014b56111808330a0933a6d0f9811.png测试步骤准备完全训练好的神经网络训练完成后我们的网络准备对它从未见过的新例子进行预测。它使用与训练相同的步骤但只需向前传播通过网络进行预测。进行预测处理新数据时1. 输入层接收新值2. 在每一层·通过权重进行乘法运算并加上偏差·应用激活函数3. 输出层生成预测例如二分类的概率值在 0 到 1 之间https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/aa9a06f87d503e7635666859984dd39e.pngID 9 的预测结果是 1是。神经网络的确定性特征当我们的网络两次看到相同的输入时它会两次给出相同的答案前提是我们没有改变它的权重和偏差。网络处理新例子的能力来自于它的训练而不是在预测时的任何随机性。最后的备注随着网络一次又一次地练习这些例子它会在任务上变得更好。随着时间的推移它犯的错误越来越少预测也变得更加准确。这就是神经网络如何学习的过程查看例子找到错误做出小的改进并不断重复多层感知机分类器代码总结现在让我们看看我们的神经网络是如何运作的。以下是一些 Python 代码构建了我们一直在讨论的网络使用的是我们刚刚学习的相同结构和规则。importpandasaspdimportnumpyasnpfromsklearn.neural_networkimportMLPClassifierfromsklearn.metricsimportaccuracy_score# Create our simple 2D datasetdfpd.DataFrame({:[0,1,1,2,3,3,2,3,0,0,1,2,3],:[0,0,1,0,1,2,3,3,1,2,3,2,1],y:[1,-1,-1,-1,1,1,1,-1,-1,-1,1,1,1]},indexrange(1,14))# Split into training and test setstrain_df,test_dfdf.iloc[:8].copy(),df.iloc[8:].copy()X_train,y_traintrain_df[[,]],train_df[y]X_test,y_testtest_df[[,]],test_df[y]# Create and configure our neural networkmlpMLPClassifier(hidden_layer_sizes(3,2),# Creates a 2-3-2-1 architecture as discussedactivationrelu,# ReLU activation for hidden layerssolversgd,# Stochastic Gradient Descent optimizerlearning_rate_init0.1,# Step size for weight updatesmax_iter1000,# Maximum number of epochsmomentum0,# Disable momentum for pure SGD as discussedrandom_state42# For reproducible results)# Train the modelmlp.fit(X_train,y_train)# Make predictions and evaluatey_predmlp.predict(X_test)accuracyaccuracy_score(y_test,y_pred)print(fAccuracy:{accuracy:.2f})想了解更多查看 scikit-learn 的MLPClassifier官方文档了解更多详情及如何使用本文使用的是 Python 3.7 和 scikit-learn 1.5但核心理念也适用于其他版本。图片归属本文中的所有图表和技术插图都是作者使用 Canva Pro 的商业许可证条款下授权设计元素制作的。 :https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/835013c69e08fec04ad9ca465c2adf6c.pngSamy Baladram分类算法查看列表8 个故事https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f95c1a80b88fe6220b18cd3b2a83a30d.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6ea70d9d2d9456e0c221388dbb253be8.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7221f0777228e7bcf08c1adb44a8eb76.png :https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/835013c69e08fec04ad9ca465c2adf6c.pngSamy Baladram回归算法查看列表5 个故事https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/aa7eeaa18e4bb093f5ce4ab9b93a8a27.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/44e6d84e61c895757ff31e27943ee597.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7f3e5f3e2aca2feec035ca92e1bc440a.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/835013c69e08fec04ad9ca465c2adf6c.pngSamy Baladram集成学习查看列表4 个故事https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1bd2995b5cb6dcc956ceadadc5ee3036.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/22a5d43568e70222eb89fd36789a9333.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8ea1a2f29053080a5feffc709f5b8669.png